Skip to content

Commit 5aafc82

Browse files
refactor(metadata-protocol): move package install and update out of protocol.ts into protocol-package-install.ts (#25467 cut 7) (#25642)
<!-- claude-projects-attribution: {"github_login":"os-sales"} --> _Requested by **Sales** · [project thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4Uu2dTVig4NQQadyC11Fs5BFZ)_ Part of #25467 Clause-②: no Metadata-protocol: none Ruling-ref: 6270097840 Cut 7 of the `protocol.ts` split (#24586 ruling A, recorded in `6270097840`). Cuts 1–6 landed as #25494, #25518, #25538, #25589, #25601 and #25623. The claim is `6384152373`. The seat agreed the scope before it and made two calls (the `.d.ts` and the letters), both answered in the claim and below. Four `ObjectStackProtocolImplementation` members, package install and update, move unedited into a new module, `packages/metadata-protocol/src/protocol-package-install.ts`, together with the three manifest-persist declarations that only they read. They are the tail of the class. `protocol.ts` loses 302 net lines. The cut is move-only, and the card stays open for later cuts. Branch: `claude/project-thread-uasfag`, the harness-pinned branch for this session, restarted from `origin/main` at `9d9a06ea38` after cut 6 merged. The branch names no issue, so the claim comment is the identity record. **Serial with the file's in-flight PRs.** Measured just before this PR was opened, on main `ca80f05ec5`: - None of the 14 open PRs touches `protocol.ts`, `protocol-package-install.ts` or the bracketed-refusal pin (each PR's diff read against its merge base). - `git merge-tree` of this head with each of them, and with main, is clean. - Main has not touched `packages/metadata-protocol` since `9d9a06ea38`. ## What moves | Member | Base line | Visibility | Tokens | |---|---|---|---| | `installPackage` | `:29853` | public, annotated return | 444 | | `updatePackage` | `:30106` | public, annotated return | 217 | | `packagePersistService` | `:30137` | private | 45 | | `packageInstallUndo` | `:30165` | private | 181 | `installPackage` and `updatePackage` are public, but their return types are annotated. That keeps them off the series' skip list, which holds public members with inferred return types. The class keeps both signatures byte-identical, so the published `.d.ts` still lists them as before. ## The shape (#23050 shape B, as cuts 1–6 apply it) - **The class keeps every member** with its name, docblock, signature and position, less `async`. Each body is now one host literal plus `fn.call(host, …)`, marked `[#25467 cut 7]`. - **Typing.** `PackageInstallHost` types every member as the class member itself (`ObjectStackProtocolImplementation['m']`). Each moved function types its `this` as the `Pick` of the host over exactly the members its body reads, measured by AST. Each stub annotates its literal as `ThisParameterType<typeof fn>`. There is no cast, and no member changes visibility. - **Members read**, measured by AST: - the fields `engine` and `getServicesRegistry`, as getters; - the methods `packagePersistService` and `packageInstallUndo`, as late-bound closures. - No field is assigned, and the host carries no elevation member. ## Module-level declarations, by reader Each declaration below was checked by an AST reader walk over the whole of base `protocol.ts`. **Move with the bodies, byte-identical and unexported.** Each is read only by moved code and carries exactly its own docblock: `persistPackageManifest`, `snapshotPackageRow`, `restorePackageRow`. **Stay in `protocol.ts` and gain `export` in place.** That is the only edit to each: | Declaration | Read by code that stays | |---|---| | `packagePersistFailureError` | `deletePackage` | | `PackagePersistService` (interface) | the `packagePersistService` stub's signature | `src/index.ts` exports from `./protocol.js` by name, so neither is published (measured below). **Import moved.** In `protocol.ts`, the `PackageInstallManifestSchema` import loses its last reader. Its 2-line `[#24086]` comment moves with it onto the new module's import of the same name. The one new statement in `protocol.ts` is the import of the new module. ## The published `.d.ts` The series bar is ruling `6348891160`, sorted-union identity. Measured first on merged main, as the seat asked, at base `9d9a06ea38` and at head. Both ends were built with `pnpm --filter @objectstack/metadata-protocol build` against the same dependency tree (`turbo run build --filter='@objectstack/metadata-protocol^...'` at base first). - **Normalised sha256**: `ff7d6892b9f1161da356208d51301816c48dc021051544b9c28a3aa14329d57e` at base and at head, on both `dist/index.d.ts` and `dist/index.d.cts`. **Sorted-union identity holds.** The normaliser, run from `packages/metadata-protocol`: ```sh node -e 'const s=require("fs").readFileSync(process.argv[1],"utf8");process.stdout.write(s.replace(/"[^"\n]*"(?:\s*\|\s*"[^"\n]*")+/g,r=>r.split(/\s*\|\s*/).sort().join(" | ")))' dist/index.d.ts | sha256sum ``` - **Raw sha256**: base `25da084d43455d125bfd41b85b1e70477ef7caf77f2cb7da23143b325e51a14e`, head `2d66df37f8e4614df880b46d57781c248549913f7d2279bbd30aa0aa6f1ab290`. Both files match at each end, and both are 770,690 bytes on each side. Raw identity does not hold. - **The full raw diff** (`diff base/index.d.ts head/index.d.ts`; `index.d.cts` is the same): ```diff 2407c2407 < environment: "production" | "development" | "sandbox"; --- > environment: "sandbox" | "production" | "development"; ``` It is one union reordered inside `getDiscovery`'s inferred return type. `getDiscovery` is on the skip list and did not move. The declaration printer orders an inferred union by the order it first meets those types, and that order depends on where code sits in `protocol.ts`. Cut 3 met the same effect. - **Positive control** on a copy of the head `dist/index.d.ts`: changing line 1361 from `private engine;` to `engine;` gives raw `fee7168c23001a389dfae3060f76008adba0aed9a02aa2632a6f9edbde94f1d8` and normalised `be0161971853121da3a941ad8936c6de5bdea6ad91bf0cc6072ded0c27054a58`. Both differ from the real hashes, so the normalised hash moves on a real change. - **Export tables.** The ESM and CJS bundles, loaded at runtime, each export the same 78 names at base and head. The sorted list hashes to `e47ac7c753bcb8bee1e79c1a5f79f7394cf030bd526de81ea8bcbfcb71fa024a` on all four. Neither `packagePersistFailureError` nor `PackagePersistService` appears. No changeset: `skip-changeset`, per ruling `6348891160`. ## Proof of move-only - **Bodies and declarations, by AST token.** For each moved function, the parameters (less the added `this`), the return type and the body have the same token sequence as the base method. Each moved declaration has the same tokens, and its own docblock is byte-identical. 1,243 tokens compared, 0 differ. Negative control: one changed token makes the check report a difference. - **Class side.** The class has 299 members at base and at head. The 295 that did not move are byte-identical to base. Each of the 4 stubs keeps its docblock and signature byte-identical, less `async`. - **Top level of `protocol.ts`.** 232 of the 238 base statements other than the class are byte-identical, leading comments included. The other 6 are: - the 3 moved declarations; - the 2 that gain `export`; - the moved import. - **Size.** +427 / −339 over 3 files, 766 changed lines. `protocol.ts` goes from 30,312 to 30,010 lines, and `protocol-package-install.ts` has 388. ## Readers of the moved lines - **Bracketed-refusal pin** (`protocol.bracketed-refusal-opener-absence.test.ts`, `PRODUCERS`). 3 `new Error(` sites move. The new module is listed with its measured count as its floor, `'protocol-package-install.ts': 3`, as cuts 3, 5 and 6 listed theirs. That is the only edit outside the move. No moved site opens with a bracketed tag. - **Durability checker** (`check-durability-degradation-log-level --list`). Identical at both ends apart from line numbers (159 lines). None of the four members holds a seam. - **ADR anchors and decision letters.** `check:adr-anchors`: 85 → 85 anchored files. Decision-letter citations on the anchored surface go **1,868 → 1,866**, measured exactly at both ends. - The two that leave are `ADR-0087 D1` (the protocol handshake, `assertProtocolCompat`) and `ADR-0087 D2` (the authoring door runs no forward conversion), both in `installPackage`'s body. - `protocol.ts`'s anchor entry governs ADR-0087, but its ADR-0087 paragraph anchors addendum 2026-08-01b, which is `saveMetaItem`'s storable view body (`projectStorableViewBody`, `VIEW_CONSOLE_ROUND_TRIP_KEYS`). It does not cover the install handshake. - `protocol.ts` keeps 26 ADR-0087 citations. So the new module gets no entry: this is the cut 13 rule, disclosed here, as the seat ruled in the scope call. - **Identical output at both ends:** - `check-adr-symbol-anchors`; - `check-platform-checklist` (`protocol.ts#installPackage` and `#updatePackage` resolve on the shells, which stay and are not edited); - `check-system-context-census` and `check-tenant-audit-census`; - `check-query-options-erasure-ratchet`; - spec `check-liveness`. - **Engine-double contract.** `check-engine-double-contract` differs only in `productionFiles` +1 (the new file). - **Governed surface.** `check-governed-merges --branch` on the final 3-path list: NOT governed. 766 changed lines, under the 3,000-line human-merge bar. - **Path readers.** These files name the moved methods: `scripts/symbol-anchors.mjs`, spec `liveness/manifest.json`, the platform checklist, `core` `capability-providers.ts`, `host-engine.ts`, the runtime `packages.ts` domain, and the package tests. Each names a method in prose or by anchor name, or calls it through the instance. None reads the moved lines by path, and all pass. ## Verification - `tsc --noEmit` (package) exits 0. `eslint` on `protocol.ts` and `protocol-package-install.ts` exits 0. - **`packages/metadata-protocol` suite**, base and head, compared per test name and status: - Base `9d9a06ea38`: 21,493 tests (21,474 passed, 0 failed, 19 skipped), 266 files. - Head: 21,494 (21,475 passed, 0 failed, 19 skipped), 266 files. - None lost and none changed status. One was added, the new `PRODUCERS` row (passed). - **Tests outside the package** that read `protocol.ts` by path or exercise these methods, run at head, all pass: - `core` `row-serving-door-exposure.pin` and `second-object-read-exposure.pin` (7, at both ends); - `runtime` package domain and integration tests: `packages-*`, `error-passthrough`, `package-dependencies-patch`, `package-promote-runtime-owner-refusal`, `package-uninstall-shared-object` (190); - `objectql` `core-boundary.ratchet`, `protocol-publish-canonical-fold`, `default-record-page-save-door` and `package-disable-enforcement` (61); - `cloud-connection` marketplace install tests (29); - `client` `discovery-double-retired-key` and `packages-write-envelope` (7), `rest` `discovery-double-retired-key` (2); - `spec` liveness evidence and allow-org-override-absence (44). - **Hand gates at base and head**, all exit 0, with identical output except the letter count above: `check-adr-anchors`, `check-adr-symbol-anchors`, `check-platform-checklist`, `check-system-context-census`, `check-tenant-audit-census`, `check-query-options-erasure-ratchet`, `check-durability-degradation-log-level --list`, and spec `check-liveness`. - **Derived gates.** `dispatch-gates --commands --changed` derives 59 gates on the final tree (3 changed paths). All 59 exit 0 at head, and `--ran` reconciles 59 of 59 with 0 NOT-MEASURED. ## Carry-forward These stay in `protocol.ts` in this series: - **Public members whose return type is inferred.** Annotating one would be a signature edit and needs a ruling. The list: `getDiscovery`, `getMetaTypes`, `getMetaItems`, `getMetaItemsForExecution`, `getMetaItem`, `getMetaItemForExecution`, `getUiView`, `findData`, `getData`, `validateData`, `createData`, `cloneData`, `updateData`, `deleteData`, `saveMetaItem`. - **Bodies kept by a reader:** - `probeRecord`, the per-file erasure-baseline site; - `getMetaItemCached`, whose body the #9157 pin reads by path; - `packagelessAddress`, `refuseUnmintableMetaType` and `metaTypeNamespaceExists`, plus every container the durability read-seam census follows (the durability read-seam census); - `viewContainerNameCollisionRefusal` and `overlaidShippedContainerViewNames`, for the `lookupArtifactItem(` call-site pin. - **Private-static readers.** `getDiscovery`'s inferred-return `.d.ts` depends on byte offsets in `protocol.ts` (shown above), so each cut measures it under the sorted-union bar. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01J8pUyVs5eas1AjMdReJM7C Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9dac9eb commit 5aafc82

3 files changed

Lines changed: 427 additions & 339 deletions

File tree

0 commit comments

Comments
 (0)