Repository navigation
feat(scripts): codemod-split-protocol --members moves the bodies E1 refuses, unedited, and retires nineteen protocol.ts facade rows - #30954
objectstack-fleet[bot] wants to merge 5 commits into
Conversation
… receiver and the statics forwarder, and moves nineteen protocol.ts bodies The members pass now moves, unedited, the members E1's rewrite refuses: an instance body run on the class's host as `this` (`.call(host)`), a private static run on a forwarder of the class's statics, a body that reads nothing of the class (plain), and a private static table moved to its section's leaf. The undo proof covers every form byte for byte, and the self-test gains three batteries for them. Nineteen facade-gate exceptions retire; triggerAutomation stays as an accepted exception with its reason rewritten. Three source-reading pins follow the moved bodies. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj
…eceiver forms A guard or read wrapper whose body moved by the receiver forms is reached through a stub that runs its facet member on the host (`.call(protocolHost(this))`), on the statics forwarder, or with no receiver (an instance method's plain form). The resolver follows those stubs to the facet member, and a facet member's `this.x()` to the class member through the imported host or forwarder interface, so the three read seams that delegate to the moved `rethrowUnlessMetadataStoreUnprovisioned` are judged on its discriminated branch again. The checker's output on the tree is byte-identical to the base. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj
📓 Docs Drift CheckThis PR changes 1 package(s): 28 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 — 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 2ece0c2d60e91f063766e2abfde25cdb55f68166 && git checkout 2ece0c2d60e91f063766e2abfde25cdb55f68166
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin c77dd17f2671f35e8f194ca1e63d8cc75bfb861a 6a6b307eab78ba32366dff8123ce4d2dffd63356 && git checkout -B drift-repro c77dd17f2671f35e8f194ca1e63d8cc75bfb861a && git merge --no-ff 6a6b307eab78ba32366dff8123ce4d2dffd63356
node scripts/docs-audit/affected-docs.mjs --json c77dd17f2671f35e8f194ca1e63d8cc75bfb861a
|
|
domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw 席位核对 · ACCEPT · #30147 (phase 3a) · 2026-11-06T14:15ZHead-sha:
|
…ALLOWED_TYPES initializer in its leaf module Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj
|
domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw 席位核对 · ACCEPT (delta) · #30147 (phase 3a) · 2026-11-06T14:36ZHead-sha:
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 42243079369 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
…s first load at collection Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj
|
domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw 席位核对 · ACCEPT (delta) · #30147 · 2026-11-06T16:48ZHead-sha:
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 42257643045 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by Elon · project thread
Part of #30147
Clause-②: no
Metadata-protocol: none
维护者速读
scripts/codemod-split-protocol.mjs --members新增三种不改写方法体的搬移形式(.call(host)接收者、statics 转发器、无接收者的 plain 形式)外加静态表搬到叶子模块,并用它把 protocol.ts 上 19 个还留着方法体的成员搬进各自的 facet。this.x→host.x)搬不了它们,只能当例外留在类上。index.d.ts的表面不变,只有 14 个 private 成员的 docblock 随方法体搬走;回滚即 revert 本 PR。packages/metadata-protocol/src/protocol.ts顶部新增的ObjectStackProtocolImplementationStatics与类尾的 static block;scripts/codemod-split-protocol.mjs的 receiver forms 一节;scripts/check-durability-degradation-log-level.mjs的 stub 解析。node scripts/codemod-split-protocol.mjs --members --verify --base 616311c126,预期输出forms: e1 2, plain 5, statics 5, receiver 3, table 4与undoing the moves does rebuild … byte-for-byte,退出码 0。What changes
The tool. The members pass (#30518) moved a member only when E1's
rewrite could carry it, so it refused a local named
host, a body thatreads no member, and every private static that reads the class. It now
ports the two mechanisms the sql-driver codemod grew (#30249, #30306), for
those reasons only (
RECEIVER_SOLVES), and moves the body unedited:thisis typed as thePickofProtocolHostit reads, and the stub runs it on the host:
return FACET.x.call(protocolHost(this), …).ObjectStackProtocolImplementationStatics, declared ahead ofthe class and filled by a static block at its end, forwards each static a
moved body reads. A facet module imports it AS the class name, so a body
that names the class reads it unedited; a private static that reads
thisruns on it:FACET.x.call(ObjectStackProtocolImplementationStatics, …).return FACET.x(…).section's leaf,
protocol-write-gates-tables.ts, which imports norelative module (an initializer runs while the class is evaluated).
as the predicate, so the narrowing survives the hop.
The undo proof covers every form: from the head alone each stub, facet
member, forwarder entry, host entry and leaf is undone and the result is
the base tree byte for byte.
The moves. Nineteen members, all in sections that already have a facet:
reconcileViewExpansions,packagelessOverlayWriteRefusal,namedBaseOverlayWriteRefusal,mergesOverlayAtRead,registryAllowsOverlay,isOverlayAllowed,isRuntimeCreateAllowed,codeOnlySourceHint,codeOnlyCreateError,codeOnlyOverrideError,refuseOrganizationScopedWrite,overlayPackageMismatchError,rethrowUnlessMetadataStoreUnprovisioned,objectExtensionItemRefusal,packagedBaseRefusaland the four tablesOVERLAY_ALLOWED_TYPES,STATIC_REGISTRY_TYPES,RUNTIME_CREATE_ALLOWED_TYPES,OVERLAY_CAPABLE_TYPES. Forms: e1 2, plain 5, statics 5, receiver 3,table 4.
protocol.tsgoes from 13,007 to 12,577 lines.The registry. The nineteen rows are deleted (46 to 27 exceptions).
triggerAutomationstays, its reason rewritten as an accepted exception:its body is one
throw, and its section has no facet module, which thispass never starts.
getDiscovery(a hand move) and the engine.ts andsql-driver.ts rows are the later PRs of this card.
Followers of the moved bodies.
check-durability-degradation-log-level.mjsresolved a stub only in theE1 and facade-host shapes, so three read seams whose catch delegates to
the moved
rethrowUnlessMetadataStoreUnprovisionedread as inventing ananswer. Its resolver now follows the receiver, statics and plain stubs to
the facet member, and a facet member's
this.x()through the importedhost or forwarder interface. Its output on this tree is byte-identical to
the base's.
packages/metadata-protocolfollow the movedbodies: the bracketed-opener scan's producer floors, the
registerItem(call site's file, and the view-expansion record's forwarder read.
protocol.ts#refusal) points atprotocol-write-gates.ts.Why
Ruling 6624345766 item 3 wants every facade-gate exception row to name the
card that moves it, and #30147 phase 3 measured that one codemod port would
retire about 19 of its 21 protocol.ts rows (comment 6653253380). The rows
that stay are named in this card's report.
Tests
node scripts/codemod-split-protocol.mjs --self-test: 112 cases in 13batteries pass (85 in 10 before). The three new batteries generate each
form on a fixture, fail ten mutations of the proof, and refuse seven
inputs no form carries.
check-durability-degradation-log-level.mjs --self-test: 86 read-seamcases pass (81 before). Ablation: the five new cases against the base
resolver fail the three positive ones; the two negative controls pass on
both.
@objectstack/metadata-protocolvitest: base4d56914aaa320 filespassed, 4 skipped; 22,487 tests passed, 26 skipped. Head
ae519e3e99: 320files and 22,489 tests pass, 26 skipped (the two new producer rows of the
bracketed-opener pin are the +2; one file first read a
specdist builtbefore the rebase onto
616311c126and passes, 18/18, once rebuilt).packages/restvitest at7d49cfc21(this branch before its rebase onto four unrelatedmaincommits): 398 files, 7,752 tests passed, 354skipped. At base the local worktree loaded 383 of 398 files (15 import a
sibling package's
srcthat the worktree had nonode_modulesfor), allof them passing.
discovery-search-capability-agreement.test.ts4/4 at base andhead.
Acceptance notes
.d.tsbar. The public surface ofdist/index.d.tsanddist/index.d.ctsis equal. The files are not byte-equal: 14 privatemembers' docblocks changed, because a private member's docblock moves with
its body (docblock ownership, as in Codemod split: generate the rest of the metadata-protocol protocol.ts split with a deterministic script, verified byte-identical #29985). Stripped of docblocks the two
sides are identical (sha256
5cf3216a10daa533…base,9cab7eb90040d456…head).
forwarder runs with the class as
this, never a subclass; every staticit forwards is private, so no subclass reaches one.
{@link ObjectStackProtocolImplementation.x}in a facetmodule that imports the forwarder now resolves to the forwarder.
packages/metadata-protocol/src/protocol*.ts(checked against all open pulls at the time of writing).
Verification
Undo proof
node scripts/codemod-split-protocol.mjs --members --verify --base 616311c126atae519e3e99: exit 0.Facade gate and companions
node scripts/check-facade-delegation-only.mjs: exit 0, 27 namedexceptions.
pnpm --filter @objectstack/metadata-protocol typecheckexit 0,buildexit 0.pnpm check:platform-checklistexit 0.pnpm --filter @objectstack/spec check:livenessexit 0. eslint on thechanged files: clean.
dispatch-gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackatae519e3e99: 86 families derived, all 86 run, all exit 0 (codes captured before any pipe).--ran: 86 derived, 86 run, 0 NOT-MEASURED, 0 UNRUN. Four gates first answered PREREQUISITE NOT MET or red on a partial build or a shallow clone (check-plugin-teardown-shape --self-test,check:dual-build-cjs-loads,check:lean-entry-closure) or before the durability resolver fix (check:durability-log-level); each exit 0 on the re-run after a fullpnpm build.Changed lines
2,459 changed lines (+1,720 / −739, 15 files, changeset included), under the 3,000 budget.
Human Minimum
packages/specholds no runtime logic.pnpm lintpasses.main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj