Repository navigation
refactor(metadata-protocol): move the code-datasource predicates out of protocol.ts into protocol-code-datasource-predicates.ts (#25467 cut 28) - #26980
Conversation
…of protocol.ts into protocol-code-datasource-predicates.ts (#25467 cut 28) Move-only, shape B. isDeclaredCodeDatasource and isHostCodeDatasource move, unedited, into one module. The engine and getServicesRegistry fields are handed over as getters; isDeclaredCodeDatasource's call to isHostCodeDatasource is handed over as a closure, so it still reaches the class method. Claude-Session: https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check6 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. 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 340bdf015d4e18ce571465a7947bb75867a38a96 && git checkout 340bdf015d4e18ce571465a7947bb75867a38a96
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7bb808459050389864535173e117826507a6a888 4dbdd32a0640a357a98bb903e890ee09552e3be4 && git checkout -B drift-repro 7bb808459050389864535173e117826507a6a888 && git merge --no-ff 4dbdd32a0640a357a98bb903e890ee09552e3be4
node scripts/docs-audit/affected-docs.mjs --json 7bb808459050389864535173e117826507a6a888 |
席位核对 · ACCEPT ·
|
| item | reading |
|---|---|
| Shape | Draft, base main, Part of #25467 (cut 28). 2 files: protocol.ts and one new module for the claimed theme, protocol-code-datasource-predicates.ts (isDeclaredCodeDatasource, isHostCodeDatasource). skip-changeset (move-only). Clause-②: no, Metadata-protocol: none. |
| Move check (seat) | All 15 non-blank lines the PR removes from protocol.ts are found verbatim (indent-stripped) in the new module. The added lines in protocol.ts are the import with its header comment and two stubs, each through CodeDatasourcePredicatesHost: engine and getServicesRegistry are handed over as getters, and isDeclaredCodeDatasource reaches isHostCodeDatasource through the class member, so callers (isArtifactBacked, the declinesStoredRow stub, protocol-lock-state.ts, the :28556 call) and overrides still go through the class. |
| Evidence | CI green on head 4dbdd32a06 (34 success, 17 skipped, 0 failed). Governed check: NOT governed, 112 changed lines. The report gives an AST compare of 240 tokens with 0 differ (each negative control differs by 1), raw and sorted-union .d.ts identity (ruling 6348891160) at both ends and on merged vs main, identical suites, and 46 of 46 derived gates. The read-seam census stays at 88 with an identical --list from base to cut. main itself is now at 89 (an objectql engine.ts site from #26930), and the merged tree's list equals main's. |
| Overlap | The claim named #26920. Its merge-tree with this head is clean, tsc on that merged tree exits 0, and the moved bodies still compare 240/0. |
| Landing | 「按照 pm-dispatch 规则复核过的都授权」 (Leehom, 2026-10-25T11:35Z): ready and auto-merge through the relay, once 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 28 of the
protocol.tssplit (#24586 ruling A, recorded in6270097840). Cuts 1–27 landed as #25494, #25518, #25538, #25589, #25601, #25623, #25642, #25719, #25731, #25740, #25797, #25939, #25972, #26014, #26104, #26168, #26264, #26317, #26350, #26366, #26404, #26449, #26654, #26704, #26807, #26873 and #26933. The claim is6455477257. It takes the cut 28 proposal of the cut 27 report (6454673268), a themed pair. Both members passed the AST screen and the read-seam census, and both moved unedited.Two
ObjectStackProtocolImplementationmembers move unedited into one new module,packages/metadata-protocol/src/protocol-code-datasource-predicates.ts(#23050 shape B). They are the protocol's two answers to "is this datasource name defined in code?":isDeclaredCodeDatasource([finding] The metadata door saves an edit to a code-defined datasource (PUT /api/v1/meta/datasource/:nameanswers 200) and the metadata read then serves it, while the datasource admin door refuses the same edit as read-only #21899): does an installed package declare it, or does the host register it from code?isHostCodeDatasource(finding(runtime,metadata-protocol): the metadata door still saves an edit to the host default datasource, which the admin door refuses as code-defined; its code set is not readable from metadata-protocol (the named gap of #21899) #21944): the host's code-datasource set alone, read from thecode-datasource-namesservice.protocol.tskeeps its 29,384 lines: the 15 body lines that left are replaced by 13 stub lines and the 2-line import. 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. It was restarted frommainaa00362fe5(after cut 27's merge). It names no issue, so the claim comment is the identity record. It holds the move commita967328ee5and, as the claim asked, one merge ofmain,4dbdd32a06(13 commits). That merge touches one test file of this package,protocol.runtime-authoring-gate.test.ts(#26928), and notprotocol.ts. The merged tree was still measured againstmain(see "The merged tree againstmain").Serial with the file's in-flight PRs
The claim named #26920 as the open PR that also edits
protocol.tsand asked for agit merge-treeagainst it before this PR was opened.d1002180ce) editsprotocol.tsat:16157–16210and:20210(+54 / −17), plus 7 more files of this package. It names neither moved member. This cut's hunks are at:420(the import) and:15675–15701.git merge-treeagainst this head4dbdd32a06is clean.git merge-treeto a tree, thentsc --noEmitinpackages/metadata-protocolon that tree exits 0. On it, both moved bodies still compare 240 tokens, 0 differ.mainalone is clean too. The conflict cut 27 reported for fix(metadata-protocol,runtime,app-shell)!: refuse a save or draft publish naming a package that is not installed #26920 is gone, since fix(metadata-protocol,runtime,app-shell)!: refuse a save or draft publish naming a package that is not installed #26920 has mergedmainsince then.All 32 open PRs were checked against this head as well. Six touch this package, and none names either member:
picklistandoptionson a field that declares onlypicklist#26953 (metadata-diagnostics.tsand a test), feat(spec, formula, plugin-email, lint): a mail template formats an amount in the record's own currency with currency:@path #26937 (one test), chore(deps)(deps-dev): bump the development-dependencies group across 1 directory with 22 updates #26556 and chore: version packages #26517 (package.json/CHANGELOG.md): merge-tree clean.protocol.meta-types-degenerate-derivation.test.ts) conflicts, but not with this cut. It conflicts withmainalone the same way, as cut 27 reported.mainhas not moved since the merge (0 behind at the derivation).The order's screen (private statics,
new Error(, the read-seam census)Both members passed:
ObjectStackProtocolImplementationidentifier and none onthis.constructor.new Error(, so noPRODUCERSrow is owed.check-durability-degradation-log-level --listwas taken on the base and again on the cut:88 read seam(s)and an identical list once[@:][0-9]+is stripped. The full readings, including the merged tree's 89, are under "The durability--list".What moves
isDeclaredCodeDatasource:15675engine(field);isHostCodeDatasource(method); module-levelPLURAL_TO_SINGULARisHostCodeDatasource:15697getServicesRegistry(field); module-levelPLURAL_TO_SINGULARprotocol-code-datasource-predicates.tshas 82 lines.The shape (#23050 shape B, as cuts 1–27 apply it)
[#25467 cut 28].CodeDatasourcePredicatesHosttypes the three members the bodies read as the class members themselves (ObjectStackProtocolImplementation['engine'],['getServicesRegistry']and['isHostCodeDatasource']). Each function'sthisis aPickof the members it reads.engineandgetServicesRegistryfields are handed over as getters (the hand-over of cuts 16, 20, 24, 26 and 27). So each read finds them at call time, as before.isDeclaredCodeDatasource's call toisHostCodeDatasourceis handed over as a closure,(...a) => this.isHostCodeDatasource(...a), as the claim asked. So that call still reaches the class method (now its stub), not the moved function directly.isDeclaredCodeDatasource:isArtifactBacked(:15484, base) and cut 10'sdeclinesStoredRowstub closure (:15996). The closure is typed byprotocol-lock-state.ts'sLockStateHost, which indexes the class member.isHostCodeDatasource:isDeclaredCodeDatasource(above) and:28556.Module-level declarations, by reader: no import leaves
protocol.tsMeasured by an AST walk over each body's identifiers, against
protocol.ts's top-level declarations and import bindings (property names excluded): the one module-level name the bodies read isPLURAL_TO_SINGULAR, from@objectstack/spec/shared. It has 54 code references left inprotocol.tsand stays; the new module imports it from there too. So the top level ofprotocol.tschanges by the new module's import alone. No import comment moves.The published
.d.tsThe series bar is ruling
6348891160: sorted-union identity, measured first, with raw identity reported when it holds. Both hold for this cut, including on the merged tree againstmain. The cut adds one import statement and its comment ahead of every class docblock, so the cut 25 comment-offset trap was watched. It did not fire: the raw hash is identical at both ends.Base
aa00362fe5and heada967328ee5were built withpnpm --filter @objectstack/metadata-protocol buildagainst one dependency tree. The closure was built at head by a fullpnpm build(116/116). For the base build, the package'ssrc/was swapped tree-only to base (the new module removed) and restored fromHEADunder a trap. Afterwardsgit diff HEADwas empty,git statuswas clean, and both touched blobs equalledHEAD's.a9338265ddd795ccfd7fda56ee209f3c2e162f9153766351149994f20e92715fat both ends, ondist/index.d.tsanddist/index.d.cts. The normaliser sorted 80 string-literal union runs. Sorted-union identity holds.7307bcccb6026da6c004fa2daaca634d3419d202d6b742c122a7a3c64a552712at both ends, 781,687 bytes. Raw identity holds.index.jshashesc256da7d953a800b…at base and2eae069e2f6b4a9f…at head (index.cjsc51a78c2b343bd49…→181916e28805d9b5…).….call(hostgoes 0 → 1 for each of the two members in both bundles.function …(declaration goes 0 → 1.privatewas dropped fromisHostCodeDatasourceon disk (restored fromHEADunder a trap) and the package rebuilt. Both.d.tsfiles move to6bbad327ad411fb0…(normalised25b39e1f5e8cc68f…, which differs from the bar'sa9338265…) and printisHostCodeDatasource(type: string, name: string): boolean;. So the bar can see a change on these members.9f18a0177ac736ed…on all of them. Neither function, and notCodeDatasourcePredicatesHost, appears.The merged tree against
mainThe merged tree
4dbdd32a06was measured againstmain912076f885, its second parent, in the same way. The closure was rebuilt by a fullpnpm build(116/116), andmain's packagesrc/was swapped in tree-only and restored under a trap. The merged tree differs frommainonly by this cut: 2 files, +97 / −15..d.ts: raw7307bcccb6026da6…(781,687 bytes) and normaliseda9338265ddd795cc…, the same atmainand merged. Both identities hold.index.js:c256da7d953a800b…atmain,2eae069e2f6b4a9f…merged. Export tables: 78 names,9f18a0177ac736ed…on both.main'sprotocol.tsagainst the merged one: 240 tokens, 0 differ.mainand merged both give 21,742 tests (21,716 passed, 0 failed, 26 skipped, 278 files), per test identical.No changeset:
skip-changeset, per ruling6348891160.The durability
--listcheck-durability-degradation-log-levelexits 0 at both ends with identical output:88 read seam(s)at both ends. Its--listis identical once[@:][0-9]+is stripped (164 lines, and no entry changes file).tryor reads the gate's read vocabulary (find/findOne/count).main. The extra seam ispackages/objectql/src/engine.ts(runPredicateDelete()guarded indelete(), from fix(objectql)!: a predicate delete honours deleteBehavior for every matched row: restrict refuses, master_detail cascades, set_null clears (#26871) #26930), whichmainbrought in.main's--listand the merged tree's are identical once[@:][0-9]+is stripped (165 lines). So this cut adds or removes nothing on either tree. The claim's "stay at 88" holds for base → cut, andmainitself moved to 89.Proof of move-only
Bodies, by AST token. The compare reads the TypeScript compiler's AST leaf tokens, with JSDoc skipped, over the parameters (less the added
this), the return type and the body. It compares baseprotocol.tsataa00362fe5against the head module:Negative controls, one per member. Each changed one token in an in-memory copy of the head module, and only the mutated member moved (differ 1; the other stayed 0):
protocol.ts. All 261 base statements are byte-identical, leading comments included. Head adds one statement, the new module's import.Readers of the moved lines
These were grepped for the two member names and for the bodies' distinctive text (
code-datasource-names,getAllPackages,PLURAL_TO_SINGULAR[type],#21899,#21944):the 24 files that name
protocol.tsand callreadFileSync;the test files in
packages/,docs/qa/andscripts/;the
@objectstack/specliveness ledgers.By path: none reads a moved line. No by-path reader names either member or that text.
The other files naming them:
protocol-lock-state.ts(cut 10'sLockStateHost, which indexes the class member, so it is unchanged) andpackages/runtime/src/code-datasource-names.ts(comments).isArtifactBackedis pinned byprotocol.lookup-artifact-item-call-sites.test.ts. It is not in this cut, and itsthis.isDeclaredCodeDatasource(call text is unchanged.Behaviour, no edit owed. These drive the predicates through the protocol and pass at both ends, in the package suite:
protocol.code-defined-datasource-door.test.ts,protocol.declines-stored-row-published.test.tsandprotocol.reads-environment-only.test.ts.The liveness ledgers. No row points at either member. Carried forward:
manifest.json'sdependenciesrow →protocol.ts#resolveWritePackageScope(cut 19), andseed.json→protocol.ts#applySeedBodies(cut 14). These arepackages/spec/**, outside this card.ADR anchors.
check-adr-anchorsexits 0 with identical output at both ends (1,896 decision-letter citations, 60,021 citations). No moved line cites an ADR.Engine-double contract (
check-engine-double-contract): exits 0 at both ends.updateData/deleteDataseams keep their entries at new line numbers (14003 → 14005, 14028 → 14030).productionFilesis 3,816 at base and 3,818 at head. The +2 are the new file and the gitignoredpackages/spec/src/migrations/registry.tsthat the spec build writes in the head tree, as in cuts 20–27.Identical output at both ends:
check-adr-anchors,check-adr-symbol-anchors,check-system-context-census,check-tenant-audit-census,check-query-options-erasure-ratchet,check-filter-alias-parityandcheck-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 ataa00362fe5.Verification
tsc --noEmitinpackages/metadata-protocolexits 0 at head, on the merged tree, and on the merge-tree with fix(metadata-protocol,runtime,app-shell)!: refuse a save or draft publish naming a package that is not installed #26920.pnpm exec eslint --no-inline-config packages/metadata-protocolexits 0 with no output (the whole touched package, with the rootlintscript's flags).packages/metadata-protocolsuite, compared per test name and status. Each leg ran vitest--maxWorkers=2with the JSON reporter under the shared verify lock.aa00362fe5: 21,738 tests (21,712 passed, 0 failed, 26 skipped), 278 files.a967328ee5: 21,738 tests (21,712 passed, 0 failed, 26 skipped), 278 files.src/swapped tree-only fromaa00362fe5(the new module removed) and restored fromHEADunder a trap.4dbdd32a06andmain912076f885both give 21,742 tests, per test identical (0 lost, 0 added, 0 changed).check-platform-checklist --changed-from origin/main(merged tree): OK, 31 anchors judged, 0 lost.check-governed-merges --branch claude/project-thread-ybjm3hfinds 0 of 2 paths in the register (13 surfaces), so the PR is NOT governed. It has 112 changed lines, under the 3,000-line human-merge bar.dispatch-gates --commands --repo objectstack-ai/objectstackderives 46 gates on 2 changed paths from4dbdd32a06, with no stale-tree finding. All 46 exit 0 after the fullpnpm build(116/116).dispatch-gates --ranreports 46 derived, 46 run, 0 NOT-MEASURED and 0 UNRUN, and exits 0.Carry-forward
These stay in
protocol.ts:findEnvironmentRows,packagelessAddress,findServedOverlayRow,foldStoredCollection,applyObjectRegistryMutation,unmanagedImportCollisions,rollBackUnmanagedImport,readRevertableCommitandstoredFlowBindingAgrees.rethrowUnlessMetadataStoreUnprovisionedcannot move at all.findEnvironmentRowjoins them: a census trial moving it drops the count by 7.probeRecord,getMetaItemCached,findReferencesToMeta,refuseUnmintableMetaTypeandmetaTypeNamespaceExists.viewContainerNameCollisionRefusalwithoverlaidShippedContainerViewNames, andreportPageRequiresAbsentAtLoad.applyRegistryWriteThroughcallers,readCodeLayerForCarryForwardandensureObjectStorage.emitMetadataMutation,isArtifactBackedandisNestedArtifactField(thelookupArtifactItemsite pins), andgetOverlayRepo.refusePackagedBaseRemoval,packagedBaseRefusal,runPublishSideEffects,promoteDraftForPublish,publishPackageDraftsanddiscardPackageDrafts.warnClosureReadUnavailableandresolveSduiManifest.🤖 Generated with Claude Code
https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6