Repository navigation
refactor(metadata-protocol): move the object-owner verdicts out of protocol.ts into protocol-object-owner.ts (#25467 cut 17) - #26264
Conversation
…otocol.ts (#25467 cut 17) Move the bodies of classifyObjectContribution and releaseAdoptedObjectOwner unedited into protocol-object-owner.ts, behind an ObjectOwnerHost that hands over the engine as a getter. The class keeps both methods, their docblocks and declared signatures; each body becomes a host literal plus a .call. Claude-Session: https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 17 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 9 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 11 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 86585f55019dbdce870c260fc695b0eced837b82 && git checkout 86585f55019dbdce870c260fc695b0eced837b82
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 48fba2b178f896fde34a72f073fcbbb220af5d30 5e5bf4438e39cf2e8ea0c18ee5bf4eeb2a5e7202 && git checkout -B drift-repro 48fba2b178f896fde34a72f073fcbbb220af5d30 && git merge --no-ff 5e5bf4438e39cf2e8ea0c18ee5bf4eeb2a5e7202
node scripts/docs-audit/affected-docs.mjs --json 48fba2b178f896fde34a72f073fcbbb220af5d30
|
席位核对 · ACCEPT ·
|
| item | reading |
|---|---|
| Shape | Draft, base main, Part of #25467 (cut 17), skip-changeset (no published behaviour moves), mergeable clean. |
| Files | 2 files, +125/−51. classifyObjectContribution and releaseAdoptedObjectOwner move into protocol-object-owner.ts (#23050 shape B). Their class members stay as delegating stubs, so the 4 + 1 this. call sites are unchanged. Both bodies read engine only, handed over as a live getter. Not governed. |
| Fix | A pure move. Seat probe: all 51 removed protocol.ts lines reappear verbatim in the new module, 0 missing. No module-level declaration moves or gains export. Dev: AST compare 406 tokens, 0 differ (the negative control gives 1). Class side: 300 members, 298 byte-identical and 2 stubs with identical docblock and signature. .d.ts is raw-identical at both ends (08914e65…) after every merge, and the positive control moves it. Export tables are equal at 78 names. |
| Order questions | Neither body reads a private static or constructs an error, so no PRODUCERS row is owed. releaseAdoptedObjectOwner's catch moves file; the durability --list is identical once line numbers are stripped. ensureObjectStorage stays, per the order. The three main merges touch no file under the package's src/. |
| Evidence | 36 check runs succeeded and 16 were expected skips on this head, 0 failed. The suite ran 21,558 tests at both ends, with 0 lost, 0 added and 0 changed. Derived gates: 53 of 53 exit 0 on the merged tree, and --ran reconciles. |
| Carried | Cut 18 goes to the same thread once this lands: flowSaveReplaysRetired (about 55 lines, reads getOverlayRepo; FLOW_FALLBACK_VERDICT_NOT_REPLAYED gains export, and ALL_CONVERSIONS leaves the import if it loses its last reader). |
| Landing | 「按照 pm-dispatch 规则复核过的都授权」 (Leehom, 2026-10-25T11:35Z): ready and auto-merge through the relay, now that every check on this head is green or an expected skip. |
Generated by Claude Code
Requested by Leehom · project thread
Part of #25467
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Cut 17 of the
protocol.tssplit (#24586 ruling A, recorded in6270097840). Cuts 1–16 landed as #25494, #25518, #25538, #25589, #25601, #25623, #25642, #25719, #25731, #25740, #25797, #25939, #25972, #26014, #26104 and #26168. The claim is6421301816; the scope is the cut 17 proposal of the cut 16 report (6418840219), as the server seat approved it in its dispatch order. Both members passed the AST screen and moved unedited, so no member was left behind.ensureObjectStoragestays where it is, per the order.Two
ObjectStackProtocolImplementationmembers move unedited into a new module,packages/metadata-protocol/src/protocol-object-owner.ts(#23050 shape B). They are the object-owner verdicts:classifyObjectContribution: which contributor kind (own,overlayormismatch) a stored object row registers as, judged against the registry's packaged owner of that name, or its runtime owner when there is none.releaseAdoptedObjectOwner: hands an adopted object's name from the'sys_metadata'sentinel owner to its rebound row.protocol.tsloses 37 net lines (29,327 to 29,290). The cut is move-only, and the card stays open for later cuts.Branch
claude/project-thread-ybjm3his the harness-pinned branch for this thread, restarted frommaindf8aac41f2after cut 16 merged. It names no issue, so the claim comment is the identity record. It holds the move commit4d5121beeand three merges ofmain:f2e7083695(1c5dda251), then81bba6c3f5(2c409efd84) and3d50a43bcb(5e5bf4438e), the last two becausedispatch-gatesprinted STALE TREE for gate sources thatmainhad changed. No merge touches a file ofpackages/metadata-protocol/src/: the package'ssrc/tree is575f85d7at the move commit and at every merge. The merges do changepackages/metadata-protocol/package.json(sideEffects: falseand the repository URL) and itstsconfig.json(now extendstsconfig.base.json), so the workspace was rebuilt in full after them and the package re-measured (below).Serial with the file's in-flight PRs. Measured just before this PR was opened: of the 36 open PRs, two touch
packages/metadata-protocol/src/.protocol.ts(+5 / −2): the import block at:163and a hunk at:23178. Neither is in a moved member or its stub, andgit merge-treeof this branch with feat(spec,metadata-protocol,service-storage,runtime,cli)!: a seed record can carry a file the package ships, seedFile(path) #26244's head is clean.protocol.*.test.tsfiles, none of which names a moved member.No open PR edits the new module.
The order's screen (private statics,
new Error()Both members passed:
ObjectStackProtocolImplementationidentifier and none onthis.constructorin either body.new Error(or any other error constructor, so noPRODUCERSrow is owed.releaseAdoptedObjectOwnerhas onecatch, which logs throughconsole.errorand answersfalse; it moves with its body (see the durability--listbelow).What moves
classifyObjectContribution:17512releaseAdoptedObjectOwner:2612551 body lines (the proposal said about 55).
The shape (#23050 shape B, as cuts 1–16 apply it)
[#25467 cut 17].ObjectOwnerHosttypes its one member as the class member itself (ObjectStackProtocolImplementation['engine']). Each moved function types itsthisasPick<ObjectOwnerHost, 'engine'>, and each stub annotates its literal asThisParameterTypeoftypeof fn. No member changes visibility.this, withascasts, parentheses and!stripped; barethischecked too): both bodies readengineonly (through(this.engine as any)?.registry). It is handed over as a live getter, so the body reads the protocol's engine, and so its registry, at call time.classifyObjectContributionfromapplyObjectRegistryMutation,saveMetaItem,promoteDraftForPublishandloadMetaFromDb(4this.call sites), andreleaseAdoptedObjectOwnerfromreassignOrphanedMetadata(1).Module-level declarations
export. Neither body reads a module-level declaration ofprotocol.ts, and neither reads an import. The new module imports only the class type (import typefrom./protocol.js), so it adds no runtime edge to theprotocol.tscycle.protocol.ts. No import loses its last reader. The one new statement is the import of the new module.The durability
--listreleaseAdoptedObjectOwner'scatchmoved file, so the list was read at both ends.check-durability-degradation-log-levelexits 0 at both ends with identical output, and its--listis identical once[@:][0-9]+is stripped (159 lines; no entry changes file, and no entry names either moved member at either end). Thecatchguardsregistry.unregisterObject, a registry call, and the list names no entry for it at either end.The published
.d.tsThe series bar is ruling
6348891160, sorted-union identity, measured first. Basedf8aac41f2and head4d5121beewere built withpnpm --filter @objectstack/metadata-protocol buildagainst one dependency tree. The closure was built at head by a fullpnpm build(119/119). For the base build, the package'ssrc/was swapped tree-only to base and restored fromHEADunder a trap;git diff HEADwas empty,git statusclean, and both touched blobs equal toHEAD's after. Measured on the pre-merge tree, and again after each merge ofmain(heads1c5dda251,2c409efd84and5e5bf4438e, the last two after a fullpnpm build, 119/119). The readings below hold for every one.08914e65f936a2b031c3f3f215481a97f53d132eefd869e4f42d928947ebe173at base and at head, on bothdist/index.d.tsanddist/index.d.cts, 775,874 bytes each. Raw identity holds, so sorted-union identity holds too. Both members stayprivate NAME;lines.46ccd7e5c4db673652513d1801ec9c9f06bf34a0a7fb6ba97fb2531ef0cc544bat both ends (80 string-literal union runs sorted; the cut 12 normaliser).index.jshashesbfb1ef96fc8499bc…at base and8732ec7d7e0d5cd5…at head. The.call(hostsites ofclassifyObjectContributionandreleaseAdoptedObjectOwneroccur 0 times in the base bundles and once each in the head bundles (ESM and CJS alike).privatewas dropped fromclassifyObjectContribution(on disk, restored fromHEADunder a trap) and the package rebuilt. Both.d.tsfiles move toc685a8419f36b078…(normalised524c41057de3c18c…) and printclassifyObjectContribution(name: string, rowPackageId: string | null | undefined): { kind: 'own' | 'overlay'; …, so the bar can see a change on these members.9f18a0177ac736ed…on all four. Neither moved function norObjectOwnerHostappears.No changeset:
skip-changeset, per ruling6348891160.Proof of move-only
Bodies, by AST token (the TypeScript compiler's AST leaf tokens, JSDoc skipped, over parameters less the added
this, return type and body), baseprotocol.tsatdf8aac41f2against the head module:Negative control, one token changed in an in-memory copy of the head module (
binding !== ownerPackageIdtobinding === ownerPackageId, one occurrence):protocol.ts. All 245 base statements are byte-identical, leading comments included. Head adds one statement, the new module's import.protocol-object-owner.tshas 111 lines.Readers of the moved lines
Every test and script that reads
protocol.tsby path was grepped for the two member names. So was every test file inpackages/andui/, anddocs/qa/.protocol.object-registry-write-through-spelling.test.tsnamesreleaseAdoptedObjectOwneronly in a comment (line 67); neither moved body holds a spelling it counts, and it passes at both ends (in the package suite).packages/objectqltests nameclassifyObjectContributionin their headers and drive it through the save and hydration doors:protocol-runtime-owner-overlay-refusal.test.ts,protocol-sentinel-owner-draft-save-address.test.tsandprotocol-sentinel-owner-package-save-refusal.test.ts. Run at head after the full build: 3 files, 27 tests passed.docs/qa/.check-adr-anchorsexits 0 with identical output at both ends. Neither body cites an ADR; their[#23416]and[#23514]comments are issue citations, which move with them.check-engine-double-contract): exits 0 at both ends. TheupdateData/deleteDataseams keep their entries at new line numbers (13974 → 13976, 13999 → 14001; the two-line import comes before them).productionFilesis 3,733 at base and 3,735 at head: +1 is the new file, +1 is the gitignoredpackages/spec/src/migrations/registry.tsthe spec build writes in the head tree.check-adr-symbol-anchors,check-system-context-census,check-tenant-audit-census,check-query-options-erasure-ratchet,check-filter-alias-parity,check-durability-degradation-log-level.check-nul-bytesdiffers only in the scanned file count, +1. The base-end readings were taken in a clean detached worktree atdf8aac41f2.check-governed-merges --branch claude/project-thread-ybjm3h: 0 of 2 paths hit the register, NOT governed; 176 changed lines, under the 3,000-line human-merge bar.Verification
tsc --noEmitinpackages/metadata-protocolexits 0 before and after the merges.pnpm exec eslint --no-inline-config packages/metadata-protocol(the whole touched package; it has nolintscript, these are the rootlintscript's flags) exits 0, no output.packages/metadata-protocolsuite, base and head, compared per test name and status (vitest--maxWorkers=2, JSON reporter, each run under the shared verify lock,VERDICT command-exit 0both legs), on the pre-merge tree (no merge changed a file of the package'ssrc/):df8aac41f2: 21,558 tests (21,539 passed, 0 failed, 19 skipped), 269 files.4d5121bee: 21,558 tests (21,539 passed, 0 failed, 19 skipped), 269 files.src/swapped tree-only fromdf8aac41f2(the new module removed) and restored fromHEADunder a trap.check-platform-checklist --changed-from origin/main(merged tree): OK, 1 anchored file in the change set, 29 anchors judged, 0 lost.dispatch-gates --commands --repo objectstack-ai/objectstackderives 53 gates on 2 changed paths from the merged tree5e5bf4438e, with no stale-tree warning; all 53 exit 0 after the fullpnpm build(119/119).dispatch-gates --ran: 53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. (The same 53 also all exited 0 on the first merged tree1c5dda251, before the STALE TREE re-merges.)Carry-forward
Unchanged from cut 16. These stay in
protocol.ts:probeRecord,getMetaItemCached,findReferencesToMeta,packagelessAddress,refuseUnmintableMetaType,metaTypeNamespaceExists,viewContainerNameCollisionRefusalwithoverlaidShippedContainerViewNames,reportPageRequiresAbsentAtLoad, the 7applyRegistryWriteThroughcallers, andreadCodeLayerForCarryForward.refusePackagedBaseRemoval,packagedBaseRefusal,runPublishSideEffects,promoteDraftForPublish,publishPackageDraftsanddiscardPackageDrafts.warnClosureReadUnavailable.ensureObjectStorage, the object-owner family's other member, stays per the order (its pin would need widening).🤖 Generated with Claude Code
https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6