Repository navigation
refactor(metadata-protocol): move the publish batch's seed apply and its pending-declaration collection out of protocol.ts into protocol-publish-batch.ts (#25467 cut 14) - #26014
Conversation
…its pending-declaration collection out of protocol.ts (#25467 cut 14) Move-only. The bodies of applySeedBodies and collectBatchPendingDeclarations move into the new protocol-publish-batch.ts (host shape B: a live engine getter, protocol-bound closures for getMetaItem, getOverlayRepo and warnClosureReadUnavailable). applySeedBodies reads getMetaItem through an any cast inside the loader's metadata adapter, so the host carries it. warnClosureReadUnavailable stays in the class: it writes closureReadWarned. Both members keep their name, docblock and signature in the class as stubs that delegate. declaresClientRefusal and memberOption gain export in place; CLOSURE_CONTEXT_KEY_BY_TYPE leaves protocol.ts' import with its last reader. Nothing re-exports the new module, so the published surface does not move. Claude-Session: https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
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 1551ea67ea6f787fc008b19f7e74678ce385fa0a && git checkout 1551ea67ea6f787fc008b19f7e74678ce385fa0a
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 56a234653bc43aee4df6ad9c80e78bea1957138b 721669cb133b7eb23ff2157f01ab68dad58244cf && git checkout -B drift-repro 56a234653bc43aee4df6ad9c80e78bea1957138b && git merge --no-ff 721669cb133b7eb23ff2157f01ab68dad58244cf
node scripts/docs-audit/affected-docs.mjs --json 56a234653bc43aee4df6ad9c80e78bea1957138b
|
席位核对 · ACCEPT ·
|
| item | reading |
|---|---|
| Shape | draft, base main, Part of #25467 (cut 14), skip-changeset (no published behaviour moves). |
| Files | 2 files, +240/−148: applySeedBodies and collectBatchPendingDeclarations move into protocol-publish-batch.ts; the host carries a getMetaItem closure for the one (this as any) read the screens miss. Not governed. |
| Fix | a pure move: AST compare 658 tokens, 0 differ (negative control 1); .d.ts sha identical at both ends (positive control moves it); export tables equal (78 names); no private-static read, no new Error(, no PRODUCERS row. |
| Evidence | package suite 21,553 tests at both ends, 0 lost, 0 changed; 53/53 derived gates; the seven by-path test files re-grepped. |
| Carried | the clientFacingFailureText docblock wording, left to keep the .d.ts byte-identical. Cut 15 (artifact-lookup family) follows from the same thread once this lands. |
| Landing | 「按照 pm-dispatch 规则复核过的都授权」 (Leehom, 2026-10-25T11:35Z): ready + auto-merge through the relay once every check on this head is green or an expected skip. |
Generated by Claude Code
席位核对 · CI note ·
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40307144724 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
席位核对 · queue note ·
|
Requested by Leehom · project thread
Part of #25467
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Cut 14 of the
protocol.tssplit (#24586 ruling A, recorded in6270097840). Cuts 1–13 landed as #25494, #25518, #25538, #25589, #25601, #25623, #25642, #25719, #25731, #25740, #25797, #25939 and #25972. The claim is6410996628; the scope is the cut 14 proposal of the cut 13 report, as the server seat approved it in its dispatch order, unnarrowed.Two
ObjectStackProtocolImplementationmembers move unedited into a new module,packages/metadata-protocol/src/protocol-publish-batch.ts(#23050 shape B): the publish batch's seed applyapplySeedBodiesand the collection of the batch's own pending declarationscollectBatchPendingDeclarations.protocol.tsloses 132 net lines (29,620 to 29,488). 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 frommain0479cd6a0aafter cut 13 merged. It names no issue, so the claim comment is the identity record. It holds the move commitc2c08b1aeand two merges ofmain(4003f5015with05f7758f0,721669cb1witha4eae0649). Neither merge touchespackages/metadata-protocol/: the package'ssrc/tree is941b828dat0479cd6a0a, ata4eae0649and at the base of this diff.Serial with the file's in-flight PRs. Measured just before this PR was opened: of the 20 open PRs, two touch
packages/metadata-protocol/src/, and neither touchesprotocol.tsor the new module. #25989 editsprotocol.runtime-authoring-gate.test.ts(behaviour, no by-path read) and #25986 editsprotocol-package-install.tsand its test.What moves
applySeedBodies:23330collectBatchPendingDeclarations:23526150 body lines (the order's estimate was about 146).
The shape (#23050 shape B, as cuts 1–13 apply it)
.call, marked[#25467 cut 14].PublishBatchHosttypes every member as the class member itself (an indexed access onObjectStackProtocolImplementation). Each moved function types itsthisas thePickof the host over exactly the members its body reads. Each stub annotates its literal asThisParameterTypeoftypeof fn. No member changes visibility.this, withascasts and parentheses stripped):applySeedBodiesreadsengine(a live getter) andgetMetaItem(a closure). ThegetMetaItemread was not in the proposal. The body spells it(this as any).getMetaItem(...)inside the loader's metadata adapter, so athis.NAMEscreen does not see it. Without it in the host, the adapter would callundefinedat runtime whiletscstayed green (theanycast hides it). The closure callsgetMetaItemon the protocol at call time, so a spy set on the instance is still the one the adapter reaches.collectBatchPendingDeclarationsreadsgetOverlayRepoandwarnClosureReadUnavailable, both as closures.warnClosureReadUnavailablestays in the class, as the order said: it writes the instance fieldclosureReadWarned. Neither moved body reads a private-static member: the AST walk found no access on theObjectStackProtocolImplementationidentifier and none onthis.constructor, in either body.runPublishSideEffectsandpublishPackageDraftscallapplySeedBodies;publishPackageDraftscallscollectBatchPendingDeclarations.Module-level declarations, by reader
exportin place, none moves.declaresClientRefusal(read byapplySeedBodies' catch) andmemberOption(read bycollectBatchPendingDeclarations).canonicalMetaType,clientFacingFailureTextandseedRequestValidationErrorwere already exported. None is re-exported fromindex.ts, so the package's export table does not change (below).CLOSURE_CONTEXT_KEY_BY_TYPEloses its last reader inprotocol.tsand leaves the./runtime-authoring-gate.jsimport; the new module imports it from there, beside the typeRuntimePendingDeclarations. The body's two dynamic imports (./seed-loader.js,@objectstack/spec/data) move unchanged and resolve from the same directory. The one new statement inprotocol.tsis the import of the new module. The new module's runtime import from./protocol.jsis the cycle earlier modules already use (protocol-batch-data.ts,protocol-drafts.ts,protocol-publish-backfill.tsamong them): it reads only function declarations, and only at call time.The published
.d.tsThe series bar is ruling
6348891160, sorted-union identity, measured first. Base and head were built withpnpm --filter @objectstack/metadata-protocol buildagainst one dependency tree: the closure built at head by a fullpnpm build(119/119), then the package'ssrc/swapped tree-only to0479cd6a0afor the base build and restored fromHEADunder a trap (git diff HEADempty,git statusclean and both touched blobs equal toHEAD's after). Measured twice: on the pre-merge tree (base0479cd6a0a, headc2c08b1ae) and after mergingmain(head4003f5015, closure rebuilt by a fullpnpm build, 119/119). The readings below hold for both.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.jshashes46f350a33fcbf439…at base anda63f0a4b6b52b222…at head; each function's.call(hostsite occurs 0 times in the base bundles and once in the head bundles (ESM and CJS alike).HEADunder a trap, hash equal toHEAD's after):privatedropped fromapplySeedBodiesand the package rebuilt. Both.d.tsfiles move toa0203ce8529250b7…and print the member's full signature (applySeedBodies(bodies: unknown[]): Promise<{ success: boolean; inserted: number; … }>), so the bar can see a change on these members.9f18a0177ac736ed…on all four. Neither moved function, the host type,declaresClientRefusal,memberOptionnorCLOSURE_CONTEXT_KEY_BY_TYPEappears.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.tsat0479cd6a0aagainst the head module:Negative control, one token changed in an in-memory copy of the head module (
seeds.length === 0toseeds.length !== 0, one occurrence):protocol.ts. 239 of the 242 base statements are byte-identical, leading comments included. The other three: the./runtime-authoring-gate.jsimport losingCLOSURE_CONTEXT_KEY_BY_TYPE, andmemberOptionanddeclaresClientRefusalgainingexport. Head adds one statement, the new module's import.protocol-publish-batch.tshas 224 lines.Readers of the moved lines
The seven test files the cut 13 report named were re-grepped by path for both member names. None reads
protocol.tsby path (noreadFileSync, noprotocol.tspath literal); none namescollectBatchPendingDeclarations.protocol.batch-verb-driver-text.test.tsprotocol.applySeedBodies(...)build-probes.test.tsvi.spyOn(protocol, 'applySeedBodies')protocol-publish-package-drafts.test.tsSeedLoaderServicegetMetaItemadapter read. Passes at head.publish-package-drafts-response-conformance.test.tspackages-publish-drafts-response-conformance.test.tspackages-seed-apply-disclosure.test.tsapi/protocol.test.tsdocs/qa/platform-checklist/areas/platform-core.json:2880anchorspackages/metadata-protocol/src/protocol.ts#applySeedBodies+. The method keeps its name inprotocol.ts;check-platform-checklist --changed-from origin/mainjudges it (see Verification).protocol.tsby path and names a symbol the bodies use (protocol.hydrate-overlay-canonical-type,protocol.read-verb-canonical-fold,protocol.lookup-artifact-item-call-sites,protocol.register-item-call-sites,protocol.object-registry-write-through-spelling,protocol.view-expansion-reconcile-call-sites) ran in the package suite and passes at both ends;check-durability-degradation-log-levelran as a hand gate (below).PRODUCERS): the moved bodies construct no error (0new Error(, 0new TypeError(;applySeedBodiesthrows theseedRequestValidationError(...)it calls, which is built inprotocol.ts). No row is owed, as the order said.check-adr-anchorsexits 0 at both ends: 86 anchored files, 58,982 citations, files 8,267 → 8,268, and 1,844 → 1,843 decision-letter citations. The one that leaves the anchored file is the[ADR-0131 D6, §12]comment inapplySeedBodies' body (protocol.tsADR-0131 D6114 → 113). Theprotocol.tsanchor does not cover ADR-0131, and no entry paragraph describes the seed apply, so the new module gets no entry (disclosure only, as cuts 8, 12 and 13).check-durability-degradation-log-levelexits 0 at both ends with identical output, and its--listis identical once[@:][0-9]+is stripped (159 lines).check-engine-double-contract): exits 0 at both ends. TheupdateData/deleteDataseams keep their entries at new line numbers (14085 → 14086, 14110 → 14111).productionFilesis 3,710 at base and 3,712 at head: +1 is the new file, +1 is the gitignoredpackages/spec/src/migrations/registry.ts, which the spec build writes in the head tree and the clean base tree had not built.check-adr-symbol-anchors,check-system-context-census,check-tenant-audit-census,check-query-options-erasure-ratchet,check-filter-alias-parity.check-nul-bytesdiffers only in the scanned file count, +1. The base-end readings were taken in a clean detached worktree at0479cd6a0a.check-governed-merges --branch claude/project-thread-ybjm3h: 0 of 2 paths hit the register, NOT governed; 388 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 (the merges changed no file of the package):0479cd6a0a: 21,553 tests (21,534 passed, 0 failed, 19 skipped), 268 files.c2c08b1ae: 21,553 tests (21,534 passed, 0 failed, 19 skipped), 268 files.src/swapped tree-only from0479cd6a0a(the new module removed from the tree) and restored fromHEADunder a trap.build-probes,protocol-publish-package-drafts,publish-package-drafts-response-conformance: 3 files, 43/43 passed, exit 0. runtimepackages-publish-drafts-response-conformance,packages-seed-apply-disclosure: 2 files, 16/16 passed, exit 0.check-platform-checklist --changed-from origin/main(merged tree): OK, 1 anchored file in the change set, 29 anchors judged, 0 lost. That includesplatform-core.json'sprotocol.ts#applySeedBodies+.dispatch-gates --commands --repo objectstack-ai/objectstackderives 53 gates on 2 changed paths from the merged tree721669cb1, 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. (Cut 13 derived 59:.github/workflows/ci.ymlchanged onmainbetween the two cuts.)Acceptance notes
clientFacingFailureText's docblock (which ships in the.d.ts) says "declaresClientRefusalstays private on purpose: nothing outside this file needs the raw predicate". This cut exports it fromprotocol.tsbecause the moved catch reads it. Its purpose still holds at the package boundary:index.tsdoes not re-export it and the export table is unchanged. The sentence was left as it is, because editing it would change the.d.tsthis series holds byte-identical. Rewording it to "outside this package" can ride a later cut that already moves.d.tstext, or a docs-only PR.applySeedBodiesreadsengineonly. The AST walk with casts stripped found the(this as any).getMetaItemread too; the cut 15 screen below uses the same walk.Carry-forward
Unchanged from cut 13: public members whose return type is inferred, the bodies kept by a reader (
probeRecord,getMetaItemCached,findReferencesToMeta,packagelessAddress,refuseUnmintableMetaType,metaTypeNamespaceExists,viewContainerNameCollisionRefusalwithoverlaidShippedContainerViewNames,reportPageRequiresAbsentAtLoad, the 7applyRegistryWriteThroughcallers,readCodeLayerForCarryForward), and the private-static readers (refusePackagedBaseRemoval,packagedBaseRefusal,runPublishSideEffects,promoteDraftForPublish,publishPackageDrafts,discardPackageDrafts) stay inprotocol.ts. Added this cut:warnClosureReadUnavailable, which writes an instance field.🤖 Generated with Claude Code
https://claude.ai/code/session_016SP1spj613tyGCgxoD1An6