Repository navigation
refactor(scripts,objectql): codemod-split-engine moves bodies that hand the engine on through a facade host port, and computing hand-stub slots; move eight #30020 bodies - #30987
Conversation
…ity port, computed field keys and exported-name imports; move seven #30020 bodies Claude-Session: https://claude.ai/code/session_016WV4d1YRzpYfqDDnUGmMWK Co-authored-by: Claude <noreply@anthropic.com>
… stub's computing host slot; move serveReferenceNames' slot and drop eight #30020 rows Claude-Session: https://claude.ai/code/session_016WV4d1YRzpYfqDDnUGmMWK Co-authored-by: Claude <noreply@anthropic.com>
…s, exported-name imports and hand slots Claude-Session: https://claude.ai/code/session_016WV4d1YRzpYfqDDnUGmMWK Co-authored-by: Claude <noreply@anthropic.com>
…e fifth pass; changeset Claude-Session: https://claude.ai/code/session_016WV4d1YRzpYfqDDnUGmMWK Co-authored-by: Claude <noreply@anthropic.com>
The fourth pass keeps a hand-grown one-line leaf import on one line (`runStyles`), which only the real tree exercised. Three cases now pin it: a one-line statement past the wrap width reads as `line` and a name a move adds keeps it on one line, the first pass's wrapped statement reads as `wrap`, and a statement in neither form reads as null. The battery's floor goes to its 23 cases. Claude-Session: https://claude.ai/code/session_016WV4d1YRzpYfqDDnUGmMWK Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 21 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 5f7a884d658553c67850a14cdebb9cc018c0e75c && git checkout 5f7a884d658553c67850a14cdebb9cc018c0e75c
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9d313f3ac70e6e7fa84f4869a81dd9890b01f75a 923ebb8225a2fae529189bef10207bb201b8dcaf && git checkout -B drift-repro 9d313f3ac70e6e7fa84f4869a81dd9890b01f75a && git merge --no-ff 923ebb8225a2fae529189bef10207bb201b8dcaf
node scripts/docs-audit/affected-docs.mjs --json 9d313f3ac70e6e7fa84f4869a81dd9890b01f75a
|
|
domain:server#3 · os-elon-musk · session_016WV4cytQjG9X1CrCgytUM5 ACCEPT · #30020 E1 · 2026-11-06T16:04Z · Head-sha: 席位核对
|
Requested by Elon · project thread
domain:server#3 · os-elon-musk · session_016WV4d1YRzpYfqDDnUGmMWK
Refs #30020
Clause-②: no
Metadata-protocol: none
Skills-docs: none — an internal move inside
@objectstack/objectql; nothing a metadata author writes changes维护者速读
scripts/codemod-split-engine.mjs的第四遍(--members)学会三条新规则:方法体里的裸this改读宿主的facade项(R1),this[k]这类计算键在键都是字面字段名时经宿主读写(R3),engine.ts已导出的名字(ScopedContext)从./engine.js导入(R4);新增第五遍--hand-slots,把手写桩里会计算的宿主槽位搬进它的手写模块(H2)。随后用它把ObjectQL上八个把引擎本身传出去的方法体搬进各自的 facet,并删掉登记表里对应的八行例外(46 → 38)。这是 refactor: move shared state out of the protocol.ts and engine.ts facades into state-owning facets, so the hot bodies left on the class can become delegations (ruling 6624345766) #30020 设计 §5 系列的第一个 PR(E1)。bare-this拒绝。Elon 于 2026-11-06 14:58Z 裁定规则 A:门面仍是唯一的状态持有者,宿主加一个facade端口,codemod 在逐字节撤销证明下把this改写为this.facade。.d.ts的成员行不变,五个私有方法的 docblock 跟着方法体走,所以共享声明块少了这五段注释。回滚即 revert 本 PR。scripts/codemod-split-engine.mjs的identityBodyText/identityUndoText、literalFieldKeys、importsEngineValues、runStyles和generateHandSlots/undoHandSlots;packages/objectql/src/engine-defaults-and-autonumbers.ts的模块头和 import 块。node scripts/codemod-split-engine.mjs --self-test预期 169 cases in 11 batteries pass;node scripts/check-facade-delegation-only.mjs预期 38 named exception(s)。What changes
scripts/codemod-split-engine.mjs, fourth pass (--members), three rules (refactor: move shared state out of the protocol.ts and engine.ts facades into state-owning facets, so the hot bodies left on the class can become delegations (ruling 6624345766) #30020 design §3):this(handing the engine on:bindHooksToEngine(this, …),new ScopedContext(ctx, this)) now readsthis.facade, and the pass adds afacade: engineentry to the host interface and its install line. The undo turnsthis.facadeback intothisand drops the entry.typeof thisin a type position stays as written (this-type), since it is a type query, not the value. The first and scoped passes are unchanged and still refusebare-this.this[k]where every valuekcan take is a literal field name (readMigrationFlagRowMemoized's cache slots) reads and writes those fields through host getters and setters, the same way a named field does.engine.tsexports.createContextandbuildHookApiconstructScopedContext, whichengine.tsexports. The receiving module imports it from./engine.js(the cycle is the one the module header already names for values), and the header's import paragraph switches from the types-only sentence to the values one; the undo switches it back. Refused in a routed module.engine-security-resolvers.tscarries an import line fix(objectql,cli): os migrate stored-expressions fills a stored computed field on rows stored before it was declared, and the boot names it #30227 grew past the wrap width.runStylesreads each statement's form (wrapped or one line) and the move and the undo both keep it, so the proof stays byte for byte.scripts/codemod-split-engine.mjs, fifth pass (--hand-slots STUB, H2). A hand-written stub whose host literal carries a slot that computes (an arrow with a body, not a forwarder) has that slot moved into the stub's hand module asexport const SLOT: HOST['SLOT'] = ARROW;, one indentation level out, so its contextual types are unchanged; the slot becomes the shorthandSLOT,. It has its own undo proof, against the tree--membersleft. Used once here:serveReferenceNames'formulaReadsReferenceslot moves intoengine-reference-name-visible.ts.The eight moves (E1 of the design's §5 series), written by the codemod on the latest
main:bindHooksintoengine-hooks-and-functions.ts;resolveReadableIdsSecurityintoengine-security-resolvers.ts;buildHookApiintoengine-defaults-and-autonumbers.ts;readMigrationFlagRowMemoizedintoengine-migration-state.ts(R3);recomputeSummariesintoengine-summaries-and-expansion.ts;ownershipQueueServiceintoengine-insert.ts;createContextintoengine-compatibility-section.ts;serveReferenceNames' slot intoengine-reference-name-visible.ts(fifth pass).The stubs, facet members, host interfaces, host factories and imports are the passes' own output.
engine.tsgoes from 11,153 to 10,977 lines.scripts/facade-delegation-registry.json: the eight#30020rows for these members are removed;check:facade-delegation-onlyis green with 38 named exceptions (46 onmain)..changeset/30020-objectql-identity-port-bodies.md:@objectstack/objectqlpatch, following refactor(objectql): spell the eight ObjectQL facade methods' inferred return types and move five bodies into their facets (.d.ts byte-equal) #30571 / fix(scripts,objectql): codemod-split-engine --members reads hand-written facet headers and inverts its import edits; move registerApp, registerDriver and registerHook #30716 (source maps ship).Tests
The codemod's self-test (
node scripts/codemod-split-engine.mjs --self-test): 169 cases in 11 batteries pass. Two batteries are new, each floor pinned at its case count:this(an object-literal method keeps its own) and adds the host's identity port under its docblock;engine.tsand switches the header;thisin a type position, stay;engine.tsdoes not export, a body that already readsthis.facade, a class that declaresfacade;this.facadethe rewrite did not write, a site put back to a barethis, a factory that does not hand the engine, a port without its docblock, a header left saying "types only";lineand stays on one line when a move adds a name; the first pass's wrapped form reads aswrap; a statement in neither form reads as null.engine.tsdrops an import only the slot read;engine.tsthat kept the slot's import, a head that moved nothing;thisor a local, a stub whose slots all forward, a slot holding a multi-line template, a method that is not a hand stub.Reverse verification (one-time, run on the committed change, restored to the HEAD blob)
Each ablation went red, then
git checkout HEAD -- scripts/codemod-split-engine.mjsandgit status --porcelaincame back empty:bare-thisagain);runStyleswith nolineform (theengine-security-resolvers.tsmove refuses at its import block, and the new one-line case goes red);Verification
The final head merges
origin/main1b3e22f0.engine.tsis unchanged between thatmainand the previous merge (ae82d057, after #30780 and #30800);packages/objectqlmoved (#30836's bare-name module,registry.ts). The moves were regenerated on1b3e22f0and compared with the head, not text-merged.1b3e22f0tree,--members bindHooks,resolveReadableIdsSecurity,buildHookApi,readMigrationFlagRowMemoized,recomputeSummaries,ownershipQueueService,createContext --write, then--members --verify --base origin/main(exit 0: "7 moved method(s) …; engine.ts 11153 -> 10985 lines; undoing the moves does rebuild the base engine.ts and its modules byte-for-byte once the 6 import binding(s) only moved bodies read are pruned from the base"). That tree was recorded as a scratch commit;--hand-slots serveReferenceNames --write, then--hand-slots --verify --base <that commit>(exit 0: "1 moved (serveReferenceNames#formulaReadsReference); engine.ts 10985 -> 10977 lines; undoing the moves does rebuild the base engine.ts and its hand modules byte-for-byte once the 1 import binding(s) only moved slots read are pruned from the base (formulaPlanEntry)"). The result equals the head's ninepackages/objectql/srcfiles byte for byte. The registry's delta againstmainis exactly the eight#30020rows removed, none added..d.tsfor@objectstack/objectql: built at base1b3e22f0and at head. With the shared chunk's hash normalised (util-XXXXXXXX),dist/index.d.tsanddist/core.d.tsare byte-equal (sha256584d6d85…,c48657f3…on both sides). The shared chunk goes from 10,030 to 9,947 lines: the 83 lines are the five private methods' docblocks, in five hunks, all deletions; no other line differs. Control:SecurityResolversFacet.resolveReadableIdsSecurityoccurs 0 times in the basedist/index.jsand once in the head's.pnpm install --frozen-lockfile && pnpm buildon the merged head:pnpm --filter @objectstack/objectql typecheckexit 0 (includingcheck:test-typecheck);pnpm --filter @objectstack/objectql test559 files, 11,200 tests passed;pnpm --filter @objectstack/spec check:generatedall 14 artifacts up to date (withNODE_OPTIONS=--max-old-space-size=8192: itscheck:test-typecheckruns out of heap at the default 2 GB here; this PR does not touchpackages/spec).node scripts/pm/dispatch-gates.mjs --commands: 74 families derived at head923ebb82; all 74 exit 0, includingpnpm check:dual-build-cjs-loads(every package'sdist/was built this time).--ran: 74 derived, 74 run, 0 NOT-MEASURED, 0 UNRUN. The codemod's and the facade gate's self-tests,pnpm --filter @objectstack/spec check:liveness,pnpm check:adr-anchorsand eslint over the changed files are outside the derived set and were run separately, exit 0.Acceptance notes
facadeport, and the codemod rewritesthistothis.facadeunder the byte-exact undo. A facet declares and reaches the state it needs through its host. No field moves.find,findOne) waits for this PR to land.update, which startsengine-update.ts). Shipping it here would leave a rule with no caller..d.tsis not byte-equal: the five private methods' docblocks moved with their bodies (the first pass's docblock rule), so the shared declaration chunk loses those docblocks. No member line changes. The design's "byte-equal" expectation was too strong.scripts/codemod-split-engine.mjs. This PR touches nopackages/spec/liveness/*.jsonand nosystem-context.mdxregister.Human Minimum
packages/specholds no runtime logic. (Not touched.)pnpm lintis CI's run.main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code