Repository navigation
refactor(objectql): move the lifecycle health bodies out of engine.ts into engine-lifecycle-health.ts (#25522 cut 3) - #25686
Conversation
…rce bodies to engine-lifecycle-health.ts Cut 3 of the engine.ts split: the two lifecycle health bodies move unedited into a new module through LifecycleHealthHost (drivers and _registry as getters, isSystemLedgerObject and resolveDatasourceBinding as late-bound closures). The class keeps both methods with their signatures and docblocks. init stays (inferred return type). Claude-Session: https://claude.ai/code/session_0161WE4VX4T7VT66M6pYcVjD 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 — 19 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 b2b133a326c33e499f0cce6082a24a9d307d4240 && git checkout b2b133a326c33e499f0cce6082a24a9d307d4240
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin b2909fd46e541f8a310023641320fef58f115091 7b61487ac1b5cc2d961aede3a3e8575d740e5c55 && git checkout -B drift-repro b2909fd46e541f8a310023641320fef58f115091 && git merge --no-ff 7b61487ac1b5cc2d961aede3a3e8575d740e5c55
node scripts/docs-audit/affected-docs.mjs --json b2909fd46e541f8a310023641320fef58f115091
|
席位核对ACCEPT ·
Landing: Generated by Claude Code |
Part of #25522
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160
Cut 3 of the
packages/objectql/src/engine.tssplit (#24586 ruling A, recorded in6270097840). The claim is6386147359. Two publicObjectQLmethod bodies move unedited into a new module,packages/objectql/src/engine-lifecycle-health.ts:checkDriversHealthandresolvePrimaryDatasource.initstays: its return type is inferred. #25522 stays open for the later cuts.Branch
claude/issue-25522-objectql-engine-cut-3, cut fromorigin/mainat24d350b45. Since thenmainhas moved five commits (tob2909fd46). None touchespackages/objectql/src/**; #25657 changespackages/objectql/package.json's zod range only. The branch has not been merged forward; CI builds the merge ref.Serial with the file's in-flight PRs (A1). At start, none of the 14 open PRs touched
packages/objectql/src/engine.ts(every file list read through the REST API, the 183-file Version Packages PR #25640 page by page). Just before this PR was opened I measured again: 10 PRs are open, and none touches it (the two new ones, #25682 and #25684, read file by file; the other 8 unchanged).What moves, re-measured on
origin/main24d350b45The cut-2 dev proposed this area in PR #25636's body. I measured it again before moving anything, and every premise holds:
checkDriversHealth(opts?: { timeoutMs?: number }), which returns aPromiseofDriverHealth[], andresolvePrimaryDatasource(): PrimaryDatasourceVerdict. The stubs keep both signatures, so the.d.tskeeps its bytes (measured below).git blame --since=2026-09-24T16:00Zover both methods, docblocks included (156 lines), finds 0 recent lines. Control on the same blame: the whole file has 8,293 recent lines. History was deepened to 2026-09-15 first (126 commits touch the file in 30 days, 35 in 7).this.FIELD.delete/insert/update(site, and no static read.PLATFORM_PROVIDED_OBJECT_NAMESis a module import from@objectstack/spec/system, not a class static. It has no other reader inengine.ts, so it leavesengine.ts's import and the new module imports it.engine.ts#…path reader for either symbol anywhere in the repo (packages/spec/liveness/**,scripts/**,docs/**,content/**).engine-driver-health.test.ts,engine-primary-datasource.test.ts,engine-driver-eviction.test.ts,datasource-unavailable.test.ts) or as whole-engine fakes (packages/runtime/src/http-dispatcher.ready.test.ts), which never reachObjectQL.The shape (#23050 shape B, as cuts 1 and 2 apply it)
fn.call(host, …), marked[#25522 cut 3].LifecycleHealthHostis new. It types each member as the class member itself (ObjectQL['drivers'],ObjectQL['_registry'],ObjectQL['isSystemLedgerObject'],ObjectQL['resolveDatasourceBinding']). Each moved function types itsthisas thePickof the host over exactly the members its body reads, and each stub annotates its literal as theThisParameterTypeof the moved function. There is no cast, and no member becomes public or protected.drivers(both bodies) and_registry(resolvePrimaryDatasource). Each read happens when the body makes it, so a driver registered or evicted later is seen as before.isSystemLedgerObjectandresolveDatasourceBinding. A double set on the instance is still the one the body calls.checkDriversHealthstaysasyncon both the stub and the moved function, so a throw inside the body is still a rejected promise.ObjectQLas a type only, so there is no module cycle at run time. It importsDriverHealthandPrimaryDatasourceVerdictas types from./driver-connect-errors.jsandPLATFORM_PROVIDED_OBJECT_NAMESfrom@objectstack/spec/system, the specifiersengine.tsuses.engine.tsgains one import and dropsPLATFORM_PROVIDED_OBJECT_NAMESfrom its@objectstack/spec/systemimport, its only other reader being a backticked docblock mention. Nothing re-exports the module.Net lines (this seat's rule: an area moves only when
engine.tsshrinks)24d350b45engine.ts(wc -l)engine-lifecycle-health.tsDiff: +163 / −72 over 2 files, under the 3,000-line manual-merge line.
The published
.d.tsdoes not change (ruling6348891160)Base: the
@objectstack/objectqldependency closure built at this branch (pnpm --filter '@objectstack/objectql^...' build, which the diff does not touch), thenpnpm --filter @objectstack/objectql buildwithengine.tsrestored from24d350b45(tree only) and the basedist/saved; the head build runs aftergit checkout HEAD -- packages/objectql/src/engine.tswithgit statusclean. The headdist/index.mjscarriesreadRegistrytwice and the base copy 0 times, so each build is the one it claims to be.All six declaration files are byte-identical. The raw diff of each is 0 lines. The util chunk name,
util-ByiLm3B6, is the same at both ends.index.d.ts9ca22071717e3f761198115fa54a143df4151a52950d826a10677420dcad16ae9ca22071717e…c15106196eb2…index.d.mts69dd1cfe3875024f434b2d7defce771ebc8c7e48a05be7c946fa6ecdbd912b4069dd1cfe3875…a2d6d7b241e8…core.d.tsd27b72bde2eec9a47c7dd3c104976321533cf397452ca9f84491a455ec28e73bd27b72bde2ee…d27b72bde2ee…core.d.mts5a0cca505296b678b31c742c285e028fe434f5467bb8d27e052e470ce0e096525a0cca505296…5a0cca505296…util-ByiLm3B6.d.tsand.d.mts1742a9cb029654d1ca4e8e392e98001eec85963987f516b1b76f672ecd08e5a91742a9cb0296…bffd1b630dab…node -e 'const s=require("fs").readFileSync(process.argv[1],"utf8");process.stdout.write(s.replace(/"[^"\n]*"(?:\s*\|\s*"[^"\n]*")+/g,r=>r.split(/\s*\|\s*/).sort().join(" | ")))' FILE | sha256sum. This package prints single-quoted literals, so on these files it changes nothing and normalised = raw. The third column is the same single class spelled with a single quote; it also matches. This cut does not depend on it, because the raw bytes are identical.util-ByiLm3B6.d.ts: line 8318private isSystemLedgerObject;made public (isSystemLedgerObject;, raw diff 2 lines) gives raw = ruled-normalisedc944677ee7e7c23a9ecabb6466a616a9f993d3e41fbee3b854527e039c7d19cd, which differs from1742a9cb…. The single-quote normalisation givese86dbb567ef0…, which differs frombffd1b630dab….import()and CJSrequire), are identical at base and head..has 182 exports under ESM and 182 under CJS;./corehas 54 and 54. The sorted lists hash881616cc179189098182bd6b8a95701d9922f9677b786bc12e2d31c1adb0adaaand393e806906e876c2e020aa96617d54050a35ae63cd483b67d8e968b7b5390f49at both ends (the same as cut 2's).No changeset:
skip-changeset, per ruling6348891160item 4.Proof of move-only
getChildrenleaves of the TypeScript parse). For each moved function, the parameters (without the addedthis), the return type, theasyncmodifier and the body have the same token sequence as the base method:checkDriversHealth251 tokens,resolvePrimaryDatasource218 tokens, all SAME. Every body line is the base line less two leading spaces (36 and 39 lines, braces included). Negative control: one changed token in the movedresolvePrimaryDatasource('system-object-unbound'misspelled in memory) makes the same check report DIFFER.engine.ts. 234 of the 235 base statements outside the class are byte-identical at head. The other is the@objectstack/spec/systemimport lessPLATFORM_PROVIDED_OBJECT_NAMES. The one new statement is the import of the new module.engine-driver-health.test.ts(7 cases oncheckDriversHealth, timeout and skip paths included),engine-primary-datasource.test.ts(everyresolvePrimaryDatasourceverdict),engine-driver-eviction.test.tsanddatasource-unavailable.test.ts. All pass at head (below).Readers of the moved lines
scripts/adr-anchors/packages__objectql__src__engine.ts.json's one paragraph is about the transaction seam (buildDriverOptions,enforceTransactionOrigin), neither of which moves. The ADR-0057 §3.6 mention inresolvePrimaryDatasource's docblock stays on the stub; the one-line// ADR-0057 §3.6comment inside the body moves with it. No anchor entry describes a moved body, so none is added.check:adr-anchorsexit 0 at both ends: 85 anchored files; 1,847 decision-letter citations on the anchored surface at base and at head; 52,546 citations at both ends (6,610 files at base, 6,611 at head: the new module).pnpm --filter @objectstack/spec check:livenessexits 0 at head. No ledger points at either moved symbol.check-adr-symbol-anchors: 2,384 anchors resolve at head.check-platform-checklist --changed-from origin/main: 1 anchored file in the change set, 14 anchors judged, 0 lost.Direct dependants (A3)
The moved members are reached from
@objectstack/runtime(http-dispatcher.ts's/readyhandler calls both) and named in@objectstack/service-datasource's comments. I built their dependency closures (pnpm --filter '@objectstack/runtime^...' --filter '@objectstack/service-datasource^...' build, underos-verify-lock, VERDICT command-exit 0) and ranpnpm --filter @objectstack/runtime --filter @objectstack/service-datasource typecheck(VERDICT command-exit 0):service-datasourcetsc --noEmitdone;runtimetsc --noEmitandcheck:test-typecheckOK; 0error TSlines. Both read the published declarations, which are byte-identical above.For the next dispatch (cut 4)
publishDataEvent(58-line body) andpublishBulkDataEvent(55-line body).this.FIELD.delete/insert/update(site; no static read; noengine.ts#…path reader; novi.spyOnor instance assignment on either, measured repo-wide.publishDataEvent's range, 2 inpublishBulkDataEvent's).realtimeService,logger,_registry).engine.tsdrops by roughly 95 lines.assertWriteAllowed.packages/spec/liveness/datasource.jsoncitespackages/objectql/src/engine.ts#assertWriteAllowedas evidence, the same reasonresolveDatasourceBindingstayed in cut 2.setRealtimeServiceandlistUnavailableDatasourcesare 1–2-line bodies, shorter than a host literal.expandRelatedRecordsreads the private staticMAX_EXPAND_DEPTH).Verification
All at head
7b61487ac.pnpm --filter @objectstack/objectql typecheck(tsc --noEmitandcheck:test-typecheck), underos-verify-lock: VERDICT command-exit 0; 39 files / 233 errors / 64 pinned signatures held.packages/objectqlsuite (vitest run --project local --maxWorkers=2, underos-verify-lock, VERDICT command-exit 0): 466 files, 1,899 suites, 8,700 tests, 8,700 passed, 0 failed, 0 skipped.eslint --no-inline-config packages/objectql: exit 0.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 56 families on the real diff at7b61487ac(stderr names the repo and the commit). All 56 were run, each exit code recorded before any pipe. 53 exit 0 on the first pass, andcheck-engine-split-ratio --days 90exit 0 after the history deepening it names as its remedy (git fetch --shallow-since=2026-07-19; it had refused with exit 2, CANNOT COMPUTE; ratio 98.1%).--ranreconciles: 56 accounted for, 54 run, 2 NOT MEASURED. CI runs both:check-plugin-teardown-shape --self-testexit 3: its pinned fixture commit is not in this shallow clone.check:dual-build-cjs-loadsexit 3, PREREQUISITE NOT MET: 54 export entries of other packages have nodist/(9 listed, "… 45 more"). The export lists above answer its question for this package.check-adr-anchors(base and head),check-adr-symbol-anchors,check-platform-checklist --changed-from origin/main,pnpm --filter @objectstack/spec check:liveness.test:repowas not run locally; CI'sTest Coreruns it.Generated by Claude Code