Repository navigation
refactor(objectql): type the six #4918 erasure-pinned ObjectQL methods and move their bodies out of engine.ts with the codemod's fourth pass - #30463
Conversation
… engine.ts Five drop the any-assertion (the literals already satisfy EngineQueryOptions); the dangling-reference audit hand-over names EngineQueryOptions, since the published port spells its options Record<string, unknown>. Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
…e slot in seedAutonumber Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
…nto the split class, with an undo proof The first pass runs only on an unsplit engine.ts. --members A,B moves the named ObjectQL methods as the first pass would (same stay rules, stub, facet member and docblock rule) into their section's written facet module, growing its header, host interface, imports, host factory and the statics route by what the bodies read. --members --verify --base REF undoes the moves from the head and requires the base engine.ts and modules byte for byte. The six PATH_READER_PINS rows retire: their #4918 sites are typed. Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
…s the first pass wrote it Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
…ies out of engine.ts with the codemod's fourth pass node scripts/codemod-split-engine.mjs --members seedAutonumber,referenceExists,resolveMasterDetailParent,resolveMasterDetailParents,inspectDanglingReferences,probeReferencingRows --write The six #30019 no-body exceptions leave the facade registry; engine.ts leaves the #4918 erasure baseline (0 sites); the referenceExists read-invention entry follows its body to engine-references-and-master-detail.ts. Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
…8 cases) Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
…ectQL bodies Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
…rtion Claude-Session: https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv Co-authored-by: Claude <[email protected]>
📓 Docs Drift CheckThis PR changes 1 package(s): 20 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 7 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. 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 146b16c98623c351b89a84205daedf279245b7d5 && git checkout 146b16c98623c351b89a84205daedf279245b7d5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin f273c9fe04d4798f8ed3dcf41822817588fe1ac1 293b12ffec15abd89ec4f36b9fbf7b995e0ec481 && git checkout -B drift-repro f273c9fe04d4798f8ed3dcf41822817588fe1ac1 && git merge --no-ff 293b12ffec15abd89ec4f36b9fbf7b995e0ec481
node scripts/docs-audit/affected-docs.mjs --json f273c9fe04d4798f8ed3dcf41822817588fe1ac1
|
|
domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC 维护者速读(席位终稿)
席位意见:同意落地。纯重构,类型收紧后 席位核对ACCEPT · head
|
|
domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC Landing · 2026-11-05T13:36Z · head |
|
domain:server#3 · os-bill · session_01Utp6CbPxYq1wQmUNWvMZkC Queue kick 13:58Z, re-queued once · 2026-11-05T14:01Z
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 42037558126 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Resolves the engine.ts conflict with the #29986 codemod's fourth pass (#30463), which moved referenceExists' body into engine-references-and-master-detail.ts: referenceRow moves there with it, referenceExists delegates to it in the facet, and engine.ts keeps a one-line stub and the host slot. Claude-Session: https://claude.ai/code/session_01Utp6CZavYYLh5k5r6jhgCF Co-authored-by: Claude <[email protected]>
domain:server#3 · os-bill · session_01Utp6CXX2qjqm2uXbJA8Jcv
Requested by Bill · project thread
Fixes #30055
Clause-②: no
Metadata-protocol: none
维护者速读
engine.ts里被 lint 规则:禁止对引擎/驱动查询选项做as any/: any擦除(#4721 的顺带项,已实测残余量) #4918 擦除钉住的六个ObjectQL方法,先把查询选项补上类型(engine.ts的擦除点 6 → 0,退出 erasure baseline),再用 codemod 新加的第四遍--members把方法体搬进三个已有的 facet 模块。engine.ts11,771 → 11,316 行。PIN 表和 facade 例外表各退六行,referenceExists的 read-invention 台账行跟着改指向。as any,另外两处保留具名断言(见 Acceptance notes)。搬移由撤销证明逐字节还原 base;.d.ts声明不变,只少了随方法体搬走的私有 docblock;objectql 测试 base 550 文件 / 10,979 = head。回滚就是 revert。engine.ts里六个擦除点的补类型提交c358b417、162cb326;②scripts/codemod-split-engine.mjs新的第四遍一节(MEMBERS_CARD);③engine-references-and-master-detail.ts新增的四个成员。node scripts/codemod-split-engine.mjs --members --verify --base baf1a536^,应看到6 moved method(s)和does rebuild the base engine.ts and its modules byte-for-byte,退出 0。What changes
as any/: any擦除(#4721 的顺带项,已实测残余量) #4918 sites are typed (commitsc358b417,162cb326, no behaviour change).referenceExists,resolveMasterDetailParent,resolveMasterDetailParentsandprobeReferencingRowsdrop theas anyoutright: their literals (where/fields/context) already satisfyEngineQueryOptions, sotscnow checks them. Two sites keep a named assertion instead of an erasure:seedAutonumber: the keyset walk's page query types itswhereasunknown(it is this scan's filter AND-ed with the seek predicate), so the spread names that one slot asEngineQueryOptions['where'](anOmitofwherefromKeysetPageQuery, intersected with that slot). The runtime object is the same spread.inspectDanglingReferences: the publishedDanglingReferenceAuditPort.findspells its options as a string-keyed record of unknowns, so the hand-over isopts as EngineQueryOptions. Changing the port would change the public.d.ts, which this card rules out.The rule's sites in
engine.tsgo from 6 to 0, soengine.tsleavesscripts/query-options-erasure-baseline.jsonand the lint rule now covers it like any other file.--members(scripts/codemod-split-engine.mjs). The first pass refuses anengine.tsthat already carries its stubs, andmainhas been split since Codemod split: generate the objectql engine.ts split with a deterministic script, verified byte-identical #29986, so "re-run the codemod" needs a pass that works on the split file.--members A,Bmoves the named methods exactly as the first pass would: same stay rules (any reason refuses), same stub, same facet member, same docblock rule, into the facet module of the method's section that the first pass wrote, in class order. That module's header list, host interface and import lines grow by what the moved bodies read, and so do the class's statics route and that facet's host factory. The pass never starts a facet, reroutes a module or widens a generated export list; each of those refuses with exit 2.--members --verify --base REFundoes the moves from the head alone and requires the baseengine.tsand modules byte for byte, every other generated module unchanged, and each moved member equal to its base method's text. Pass 1's renderers are shared, not copied: five pure helpers were extracted from it (classStaticsOf,specifierImportLines,moduleHeaderLines,facetMethodText,hostInstallLines), and its 105 self-test cases still pass unchanged.baf1a536, generated, not hand-edited):node scripts/codemod-split-engine.mjs --members seedAutonumber,referenceExists,resolveMasterDetailParent,resolveMasterDetailParents,inspectDanglingReferences,probeReferencingRows --write.engine-defaults-and-autonumbers.tstakesseedAutonumber;engine-references-and-master-detail.tstakesreferenceExists,resolveMasterDetailParent,resolveMasterDetailParentsandinspectDanglingReferences;engine-cascade-planning.tstakesprobeReferencingRows.inspectDanglingReferencesis public, so its docblock stays on the class and the module carries the placeholder.ObjectQLStaticsgainsreferenceCheckContext. The references facet's host gainsfind,findOne,materializeParentHeader,resolveEnginePosture. Nine import bindings only the moved bodies read leaveengine.ts.PATH_READER_PINSrows (the table is now empty), the six tooling: a structural gate that refuses any method body in a facade file once protocol.ts and engine.ts land in facade form (ruling 6624258595) #30019 no-body exceptions inscripts/facade-delegation-registry.json, and thereferenceExistsentry inscripts/durability-read-invention.baseline.jsonnow namesengine-references-and-master-detail.ts, where its body lives.Size: 9 files, +1,479 / −609 = 2,088 changed lines (under 3,000).
Tests
node scripts/codemod-split-engine.mjs --self-test: 124 cases in 9 batteries pass. The new batterynamed methods onto the split class (fourth pass)has 18 cases: the first pass keeps two pinned fixture methods; the fourth pass moves both into the right module in class order; the proof holds and two runs write identical trees; the stub is the first pass's withasyncdropped; a private docblock moves and a protected one stays; the header, host interface and factory, statics route and imports each grow by exactly what the bodies read; engine.ts prunes what only the bodies read and keeps a type a stub's signature still names; unknown, already-moved, stay-rule and still-pinned names refuse; and the proof fails on an edited body character, a host member nothing reads, an unread import, a stub that keptasync, an unrelated edit inengine.tsor another module, and a head that moved nothing.pnpm --filter @objectstack/objectql test: base (f7afab86sources) 550 files / 10,979 tests passed; head 550 / 10,979 passed.pnpm --filter @objectstack/objectql typecheck: exit 0 (tsc andcheck:test-typecheck).Acceptance notes
as any/: any擦除(#4721 的顺带项,已实测残余量) #4918 rule asks for when the value crosses a boundary typed looser than the engine. Neither is counted by the rule.homeAmountReadsFor(added by hand in fix(objectql): an uninstalled package no longer reads as read-only until a restart #30280) sits inengine-references-and-master-detail.tsout of class order and missing from the module header's list. The fourth pass reads the header's own list and adds its names to it, leaving that drift as it stands. Not a defect; noted for whoever next regenerates the module..d.ts: the private methods' docblocks leave the bundled.d.tswith their bodies (211 lines in each ofutil-HASH.d.tsandutil-HASH.d.mts). Ruling 6624345766 item 1 says a private docblock moves with its body. This is the same reading refactor(objectql): move 36 hand-series private docblocks out of engine.ts with the codemod's third pass (slice 1 of 2) #30341 / refactor(objectql): move the last 28 hand-series private docblocks out of engine.ts with the codemod's third pass (slice 2 of 2) #30415 gave.Verification
Undo proof on the real tree
node scripts/codemod-split-engine.mjs --members --verify --base baf1a536^exit 0:Against
main(f7afab86) the same command refuses all six (the facet member is not its base method's text), because the typing commits changed those bodies. The move is proved against the commit just before it; the typing is the reviewed diff.Declarations, base vs head
pnpm --filter @objectstack/objectql buildatf7afab86sources and at head. The chunk name hash (util-HASH) was normalised.core.d.ts,core.d.mts,index.d.tsandindex.d.mtsare byte-identical once the hash is normalised. The twoutil-HASHfiles differ by 422 lines, every one a docblock line. With docblocks stripped, all six declaration files are byte-identical.Ablation
Re-erasing one moved site (
as anyback onreferenceExists's options inengine-references-and-master-detail.ts, throughscripts/ablation-replace.mjs):pnpm check:query-options-erasureexits 1 withengine-references-and-master-detail.ts: NEW engine query-options erasure (1 site(s)). Restored to HEAD; the hash matches andgit diff HEADis empty.Gates
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 74 families, 80 commands. Among them are the fourth-pass verify, the codemod self-test, eslint on the touched files, andpnpm --filter @objectstack/spec check:liveness. All 80 recordedexit 0, and--ranreconciles:74 derived famil(ies) accounted for — 74 run, 0 NOT-MEASURED.Two first ran
exit 3(prerequisite, not measured) and were rerun green:check-plugin-teardown-shape --self-testneeded its pinned fixture commit fetched into the shallow clone, andcheck:dual-build-cjs-loadsneededpnpm build(119 of 119 tasks; then 116 entry points across 71 packages load).Named here because the card asks:
check-facade-delegation-onlypasses with5 facade class(es) in 3 file(s) hold delegations only, 62 named exception(s)(six fewer);check:query-options-erasurepasses with30 unswept … 13 file(s), none new;check:livenesspasses.🤖 Generated with Claude Code
https://claude.ai/code/session_01Utp6CXX2qjqm2uXbJA8Jcv