Repository navigation
refactor(metadata-protocol): generate the protocol.ts section split with a deterministic codemod - #29998
refactor(metadata-protocol): generate the protocol.ts section split with a deterministic codemod#29998objectstack-fleet[bot] wants to merge 6 commits into
Conversation
…ith a deterministic codemod (WIP) scripts/codemod-split-protocol.mjs applies the E1 host split (packages/metadata-protocol/scripts/host-split.mjs) to whole sections of ObjectStackProtocolImplementation and proves the move: undoing it rebuilds the base protocol.ts and protocol-host.ts byte for byte, and host-split's own check passes for every moved member. Generated output, unedited. Claude-Session: https://claude.ai/code/session_01WGufzgddMBbTQd9yVo4Yuz Co-Authored-By: Claude <noreply@anthropic.com>
…e import prune
The codemod now drops the imports only the moved bodies read (the package
compiles with noUnusedLocals), and its byte-identity proof recomputes that
prune from the head's own references. A JSDoc {@link X} counts as a read, as
the compiler counts it. A move that would reach a type-predicate method
through a new host entry stays (the forwarding closure drops the predicate).
An inferred return type no longer keeps a method in protocol.ts.
Regenerated: 70/284 methods move into 10 section modules; protocol.ts goes
from 23135 to 13905 lines.
Claude-Session: https://claude.ai/code/session_01WGufzgddMBbTQd9yVo4Yuz
Co-Authored-By: Claude <noreply@anthropic.com>
…er in protocol.ts A moved body that reads no member would never read its `host` parameter, which the package's noUnusedParameters refuses, so such a method now stays (stay rule no-host-read). Regenerated: 69/284 methods move; protocol.ts goes from 23135 to 13915 lines. Claude-Session: https://claude.ai/code/session_01WGufzgddMBbTQd9yVo4Yuz Co-Authored-By: Claude <noreply@anthropic.com>
… in protocol.ts and widen the by-path censuses The declaration bar on the built .d.ts refused the previous split: moving getDiscovery's body made the compiler re-infer its printed return type through the moved function, which dropped the @deprecated docblock on one key. The pilot's rule is back: a non-private method with an inferred return type stays. Regenerated: 61/284 methods move into 9 section modules; protocol.ts goes from 23135 to 15318 lines. The censuses that read protocol.ts by path now also read the modules the split moved bodies to, where the class is spelled host. instead of this. (ruling 6597555122): the recovery-door emit and projector counts, the write-through and registerItem caller sets, the lookupArtifactItem sites, the read-verb fold population (the signature is read off the class member, the fold off the moved body) and the stored-row write census of the view expansion reconcile. Claude-Session: https://claude.ai/code/session_01WGufzgddMBbTQd9yVo4Yuz Co-Authored-By: Claude <noreply@anthropic.com>
…verned bodies The split moved the bodies the protocol.ts entry's invariants govern: applyObjectRegistryMutation and hydrateOverlayIntoRegistry into protocol-registry-hydration.ts, loadMetaFromDb into protocol-diff-delete-load.ts, saveMetaItem's view storage into protocol-save.ts. Each module gets an entry carrying the host entry's own invariant paragraphs for the ADRs it now cites (ADR-0029 and ADR-0126, ADR-0029, ADR-0005 and ADR-0087), as the sql-driver pilot did; the host entry stays for the stubs and the citations left there. Claude-Session: https://claude.ai/code/session_01WGufzgddMBbTQd9yVo4Yuz Co-Authored-By: Claude <noreply@anthropic.com>
…lity census; parse through ts-parse check-durability-degradation-log-level read three moved catch blocks as inventing an answer, lost one read seam, and kept two stale FAILURE_PROPAGATION_SITES keys, all because the codemod split moved the bodies into section modules: - A moved body that delegates its catch to the class's guard as host.rethrowUnlessMetadataStoreUnprovisioned(error) now reaches that guard through the same HOST CALL rule isReadCall already follows. - A host.x() call resolves to the class member x first, through its stub, even when the module declares x itself (x's own moved body, whose extra host parameter failed the arity check). This restores rollbackToPackageCommit's seam around revertCommit. - migrateStoredMetadata and duplicatePackage are keyed by their new modules. The census reads the base's numbers again: 51 durability seams (9 propagating), 102 read seams (13 discriminated). Three self-test rows pin the two rules (the read-seam floor goes 67 -> 70); removing either rule turns exactly its row red. The codemod now parses through ts-parse.mjs (parseSourceFile, createProgramChecked), as check:parse-guard requires. Claude-Session: https://claude.ai/code/session_01WGufzgddMBbTQd9yVo4Yuz Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 75 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 18 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 10 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 1c98876e6d60e1593a6a1f9f1a593f722b81b80d && git checkout 1c98876e6d60e1593a6a1f9f1a593f722b81b80d
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0b99c2b1645b101459b1dd9fd4fecdf996194a76 32c7bc04abfde7f2bf4962e70ffde52da50f3d1a && git checkout -B drift-repro 0b99c2b1645b101459b1dd9fd4fecdf996194a76 && git merge --no-ff 32c7bc04abfde7f2bf4962e70ffde52da50f3d1a
node scripts/docs-audit/affected-docs.mjs --json 0b99c2b1645b101459b1dd9fd4fecdf996194a76
|
Requested by Yibo Wang · project thread
Part of #29985
维护者速读
scripts/codemod-split-protocol.mjs,按 ruling E(E1 host 模式)把ObjectStackProtocolImplementation的 61/284 个方法体移入 9 个分节模块,类上只留签名、docblock 和一行 stub。生成文件未手改。按裁决 6597555122 第 3 点,8 个按路径读protocol.ts的普查测试和check-durability-degradation-log-level跟随代码读新模块(host.与this.同义),ADR 锚点为 3 个接收受管代码的模块各加一条。protocol.ts。protocol.ts和protocol-host.ts(只剩 80 个仅被移出方法体读的 import,证明从 head 重新推出这次修剪)。测试计数 base 22,339 → head 22,340(多 1 条非空检查),门禁读数 base = head,打包.d.ts按 6441032442 B 第二归一化相等。回滚即 revert。protocol.ts的读者」表;② codemod 的STAY_REASONS(尤其inferred-return-type,.d.ts对比抓到过它);③check-durability-degradation-log-level.mjs的两处 host 调用改动和 3 条自测。pnpm install --frozen-lockfile后运行node scripts/codemod-split-protocol.mjs --verify --base 9049be26,预期61/61 moved bodies restore to the base body exactly、23135 -> 15318 lines,退出码 0;node scripts/codemod-split-protocol.mjs --self-test42 例通过。Clause-②: no
Metadata-protocol: none
What changes
scripts/codemod-split-protocol.mjs(new): plans, writes and proves the split. It reusespackages/metadata-protocol/scripts/host-split.mjs(E1's rewrite set:this.x→host.x, a private static →host.x) for every move, so a moved function has the shape of the 87 existingprotocol-*.tsmodules.SECTION_ANCHORS, after [maintainer] refactor(metadata-protocol): splitsrc/protocol.ts(33,065 lines, +10,169 in 30 days) along itsObjectStackProtocolImplementationseams, one move-only slice per PR #25467's section table); the five sections the hand series already emptied write no module..d.tssays, what a by-path reader sees, or when the move cannot be undone byte for byte. Measured on this file (a method can carry several): already-moved 190, no-yield 18, inferred-return-type 8, closed-set 4, name-taken 3, no-host-read 2, host-entry-predicate 1.inferred-return-type(the pilot's rule, back): without itgetDiscovery's printed return type lost the@deprecateddocblock onapiName.no-host-read: a body that reads no member would leavehostunread (noUnusedParameters).host-entry-predicate: a forwarding closure drops a type predicate (TS2322).protocol.ts(noUnusedLocals); a JSDoc{@link X}counts as a read, as tsc counts it. The proof recomputes the prune from the head's own references.--self-test: 42 cases in 6 pinned batteries, each proof fed an input it must refuse.--writeon base9049be26, unedited.protocol.tsandprotocol-host.tschange; new:protocol-class-head.ts,protocol-discovery-and-bases.ts,protocol-search-and-cache.ts,protocol-write-gates.ts,protocol-registry-hydration.ts,protocol-save.ts,protocol-history-and-publish.ts,protocol-package-commits.ts,protocol-diff-delete-load.ts. Nothing re-exports them.scripts/check-durability-degradation-log-level.mjs:host.guard(error)reaches the class's guard through the HOST CALL ruleisReadCallalready follows.host.x()call resolves to the class memberxfirst, even when the module declaresxitself (that member's own moved body, whose extrahostparameter failed the arity check and droppedrollbackToPackageCommit's seam).FAILURE_PROPAGATION_SITESkeysmigrateStoredMetadataandduplicatePackageby their new modules.scripts/adr-anchors/: three new entries.protocol-registry-hydration.tsgets ADR-0029 and ADR-0126,protocol-diff-delete-load.tsgets ADR-0029, andprotocol-save.tsgets ADR-0005 and ADR-0087. Each carries the host entry's own invariant paragraphs, in the pilot's shape. The host entry stays.Verification
9049be26protocol.tslinesaf32bb253715742dca426de0417e7d3ccf91ba461c4b69637e2289756cdd6916on two runs; regenerating on base reproduces the committed tree with zero difftypechecktestcheck:durability-log-leveltest:repopnpm lintdispatch-gates --commandsat head32c7bc04--ran: 0 NOT-MEASURED, 0 UNRUN.d.ts: ruling 6441032442 item 1, second normalisationThe reading uses the dtsnorm reader over the built
dist/of base and head (index.d.ts,index.d.cts).index.d.tsindex.d.ctsgetDiscovery's printed type)A positive control plants a
private→ public change and is caught (normalised and surface both differ). On the previous generation, which had noinferred-return-typerule, the same reading refused the split.Readers of
protocol.tsby pathprotocol.recovery-doors-mutation-projector.test.ts,protocol.recovery-doors-emit-mutation.test.tsprotocol.tsplus every split module,(this|host).; the receive-path body is read inprotocol-class-head.tsprotocol.object-registry-write-through-spelling.test.ts'objects'scan over every split moduleprotocol.register-item-call-sites.test.tsfileprotocol.lookup-artifact-item-call-sites.test.tsfileprotocol.read-verb-canonical-fold.test.tsprotocol.view-expansion-reconcile-call-sites.test.tsprotocol.tsplus the codemod's modules (see Findings)protocol.hydrate-overlay-canonical-type.test.tsprotocol-registry-hydration.tscheck-durability-degradation-log-levelcheck:adr-anchorsexit 0protocol.query-transport-dialect.test.ts, coresecond-object-read-exposurepin, objectqlcore-boundaryratchet, spec liveness / absence pins,check-filter-alias-parity,check-nul-bytes,check-system-context-censusprotocol.ts, or they read the directory)Every widened census was ablated once: a moved call renamed, an
awaitdropped, a fold argument changed, or an assert code changed. Each one fails at head. A one-character hand edit inprotocol-save.tsmakes--verifyexit 1.Not met: the line bar
protocol.tsends at 15,318 lines, against the 13,000 that ruling 6591753301 item 3 set for the pilot and carried to the next three files. What is left is mostly docblocks and signatures that stay on the class by E1's design: the.d.tsprints them. Another 190 methods are already stubs from the hand series. Reaching 13,000 needs a decision the codemod cannot make, such as moving the docblocks, or a different decomposition. It is raised with the seat and is not hand-cut here.Findings outside this PR
protocol-packageless-overlay-migration.ts(hand series) callsrepository.delete(onsys_metadata. That call is outside the #23198 stored-row census, which reads only therepo.spelling. Widening the census to every module would have turned it red, so the census reads the codemod's modules and the hand-series module stays outside, as before. This was reported to the seat.🤖 Generated with Claude Code
https://claude.ai/code/session_01WGufzgddMBbTQd9yVo4Yuz