Repository navigation
refactor(objectql): move the realtime publish bodies out of engine.ts into engine-realtime-publish.ts (#25522 cut 4) - #25948
Conversation
Cut 4 of the engine.ts split. The bodies of the private ObjectQL#publishDataEvent and #publishBulkDataEvent move unedited into packages/objectql/src/engine-realtime-publish.ts, reached through RealtimePublishHost (realtimeService, logger and _registry as getters). The module-level event helpers only those two call (generateEventUuid through eventMatchedCount, accessibleOrganizationsOf excepted) move with them byte for byte. Each method keeps its name, signature, docblock and position. The three path readers of the moved code follow it: the engine-data-events source pin, the federated injected-column readers ledger key, and the realtime-protocol docs page. Claude-Session: https://claude.ai/code/session_017kEHq65soeg6DRE9DDutT2 Co-Authored-By: Claude <noreply@anthropic.com>
…Response import Its one caller in engine.ts was projectEventRecordBody, which moved to engine-realtime-publish.ts with its import in the previous commit; the three remaining mentions are prose. Claude-Session: https://claude.ai/code/session_017kEHq65soeg6DRE9DDutT2 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:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
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 9ae6255da4cf814d40d1385345cd3bb8ef472d39 && git checkout 9ae6255da4cf814d40d1385345cd3bb8ef472d39
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 2a728ba2acf52c13d1918c2afca7b79bf391e1f5 b51ec853692eb963ae47ee4620582bfa9e363268 && git checkout -B drift-repro 2a728ba2acf52c13d1918c2afca7b79bf391e1f5 && git merge --no-ff b51ec853692eb963ae47ee4620582bfa9e363268
node scripts/docs-audit/affected-docs.mjs --json 2a728ba2acf52c13d1918c2afca7b79bf391e1f5
|
The realtime publish helpers moved out of engine.ts with their docblocks, and five decision-letter citations left the anchored surface with them. This entry anchors the new module, so check-adr-anchors verifies those letters again, and states the D8 invariant the bulk organization stamp keeps: it reads the wall's recorded verdict and nothing else. Claude-Session: https://claude.ai/code/session_017kEHq65soeg6DRE9DDutT2 Co-Authored-By: Claude <noreply@anthropic.com>
|
ADR anchor entry added (claim amendment
Generated by Claude Code |
席位核对ACCEPT ·
Generated by Claude Code |
Requested by Elon · project thread
Part of #25522
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160
Cut 4 of the
packages/objectql/src/engine.tssplit (#24586 ruling A, recorded in6270097840). The claim is6408069065. The bodies of the two privateObjectQLrealtime publish methods move unedited into a new module,packages/objectql/src/engine-realtime-publish.ts:publishDataEventandpublishBulkDataEvent. The ten module-level event helpers that only those two call move with them, byte for byte. #25522 stays open for the later cuts.Branch
claude/project-thread-6ikbqy(platform-assigned to this card thread), cut fromorigin/mainatf00e8d5c8. Since thenmainhas moved to2a728ba2a; no commit in that range touchespackages/objectql/**or the docs page this PR edits. The branch has not been merged forward, and CI builds the merge ref.Serial with the file's in-flight PRs (A1). Before the first edit, none of the 7 open PRs touched
packages/objectql/src/engine.ts,engine-data-events.test.ts,federated-injected-column-readers.test.tsorrealtime-protocol.mdx(every file list read through the REST API). Seat 1's #25653 editswithRunAsinengine.ts, a different region. Just before this PR opened I measured again: 16 PRs are open, and one new one touchesengine.ts. #25935 (opened 04:48Z, after this claim) adds one import line near base line 279 and an aggregate refusal near base line 21954. Neither overlaps this diff; the nearest hunk here ends at base line 263. For each of those PRs, whichever lands second mergesmain.What moves, re-measured on
origin/mainf00e8d5c8The cut-3 dev proposed this area in PR #25686's body. I measured it again before moving anything:
Promiseofvoid). The stubs keep both signatures and docblocks, so the.d.tskeeps its bytes (measured below).publishDataEvent, 2 inpublishBulkDataEvent;git blame --since=2026-09-26T04:00Zatf00e8d5c8, after deepening history to 2026-07-19). The moved helpers carry 71 recent lines out of 279. Control: the whole file has 7,261 recent lines on the same blame.this.FIELD.delete/insert/update(site and no static read. The bodies read three members only:realtimeService,loggerand_registry.realtimeServiceanywhere in the repo's tests. The callers still call the methods on the engine.engine.ts:generateEventUuid,eventRecordId,eventRecordBody,redactEventMetadataBody,projectEventRecordBody,eventUserId,eventOrganizationId,eventOrganizationValue,bulkEventOrganizationIdandeventMatchedCount. No other code inengine.tscalls any of them, measured by name. They move with the bodies, so the new module needs no runtime import ofengine.ts.accessibleOrganizationsOfsat between them, but the tenant wall reads it, so it stays.The cut-3 proposal priced this cut at about −95 lines and listed no path reader. Both readings are corrected here. The helpers move too, so the cut is larger. And three readers read the moved code by path; each is migrated below.
The shape (#23050 shape B, as cuts 1 to 3 apply it)
fn.call(host, …), marked[#25522 cut 4].RealtimePublishHostis new. It types each member as the class member itself (ObjectQL['realtimeService'],ObjectQL['logger'],ObjectQL['_registry']). 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.setRealtimeServiceis seen as before.publishBulkDataEvent's host has no_registry, because its body never reads it.ObjectQLas a type only, so there is no module cycle at run time. It imports what the moved code reads, with the specifiersengine.tsused.engine.tsdrops these imported names, whose only reader was the moved code:redactStoredMetadataBody,STORED_METADATA_BODY_COLUMNandSTORED_METADATA_TYPE_COLUMN(@objectstack/spec/kernel),RealtimeEventPayload(@objectstack/spec/contracts), the whole@objectstack/spec/apiimport (BulkDataEventSchema,DataEventSchema,BulkDataEvent,DataEvent), andomitInternalFieldsFromWriteResponse(@objectstack/core; its three other mentions are prose). The[#21120]andomitInternalFieldsFromWriteResponseimport comments move with their imports. Nothing re-exports the module.Net lines (the seat's rule: an area moves only when
engine.tsshrinks)f00e8d5c8engine.ts(wc -l)engine-realtime-publish.tsDiff: +538 / −420 over 5 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; the diff touches none of it). Thenpnpm --filter @objectstack/objectql buildwithengine.tsrestored fromf00e8d5c8(tree only), and the basedist/saved. The head build runs aftergit checkout HEAD -- packages/objectql/src/engine.ts, withgit statusclean. The headdist/index.mjscarriesreadRealtimeService4 times and the base copy 0 times, so each build is the one it claims to be. I ran the pair twice (once for the declarations, once for the export lists), with the same result.All six declaration files are byte-identical, and the raw diff of each is 0 lines. The util chunk name,
util-BuVJ7CNx, is the same at both ends.index.d.ts6f76e7978f0fc72c6bbcf129f97c753188123ed605cf01ee38d1774ea8f0e69aindex.d.mts21fdbb330b86ada1f46e2431bae853a8ccb8d64f08469e3e2b41254a50605145core.d.ts2cd3ea741f5c01f5de3274d5728254ead8bacb8dcd57886bede9f39c648bb2f1core.d.mts47c1c62d395f5a63d64842bd99ecf6fbeadbf5a34c057b7a9f4b005377c11c5autil-BuVJ7CNx.d.tsand.d.mts05835759410068e3f1002223baf35eca63064ee4d090b1eb5fd5276b2da3feeeutil-BuVJ7CNx.d.ts. Line 7157private publishDataEvent;made public (publishDataEvent;, raw diff 4 lines) gives raw = normaliseda379ca74f62d51b31185fa0119cfcd24e1a5c920645e135390c257e372f4192d, which differs from05835759….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 cuts 2 and 3. No moved name is exported.No changeset:
skip-changeset, per ruling6348891160item 4.Proof of move-only
The proof uses AST tokens: the recursive
getChildrenleaves of the TypeScript parse. JSDoc leaves are compared with leading indentation stripped per line, because the moved code is one level shallower.this), the return type and the body have the same token sequence as the base method:publishDataEvent371 tokens andpublishBulkDataEvent287 tokens, both SAME. Every body line is the base line less two leading spaces (60 and 57 lines, braces included).getFullText, trimmed): 741 tokens in all.publishBulkDataEvent(matched === 0tomatched === 1, in memory) makes the same check report DIFFER. Changing one in the moved helpereventRecordIdalso reports DIFFER.engine.ts. 222 of the 237 base statements are byte-identical at head. The other 15 are the 10 helpers, the class, and four imports: three narrowed by the names listed above, and the@objectstack/spec/apiimport, gone whole. The new statements are the import of the new module, the three narrowed imports, and the class.engine-data-events.test.ts(42 cases),engine-realtime-credential-mask.test.tsandengine-realtime-stored-metadata-body.test.ts. All pass at head (below).Readers of the moved lines, migrated in this PR
engine-data-events.test.ts's source pin ("BulkDataEventSchema.parse at the publish site stays the validator…") readengine.tsforprivate async publishBulkDataEvent(andfunction bulkEventOrganizationId(. It now readsengine-realtime-publish.tsforexport async function publishBulkDataEvent(, and the body ends at the module's own closing brace. Every assertion is unchanged. Proof that it can still fail:scripts/ablation-replace.mjsadded aneventOrganizationId(call into the moved bulk body (anchor 1 → 0, blob02e17ff9f831→87ab8ae01da1). The pin went red: 1 failed / 41 passed. Restored, the blob is HEAD's again andgit diff HEADis empty.federated-injected-column-readers.test.tskeys each seam use asFILE#FUNCTION :: SEAM. The row foreventOrganizationId :: resolveTenantFieldName()moves fromengine.ts#toengine-realtime-publish.ts#. Its disposition and reason are unchanged. Proof: putting the old key back (blob17bd6adaf9c5→6ea31c760521) makes "has a row for every seam use in the source" fail and name the new key as unlisted. Restored the same way.content/docs/protocol/kernel/realtime-protocol.mdxpointed atpublishDataEventinpackages/objectql/src/engine.tsfor whatchangescarries. It now namesengine-realtime-publish.ts.pnpm --filter @objectstack/spec check:livenessexits 0 at head.scripts/adr-anchors/packages__objectql__src__engine.ts.json's one paragraph is about the transaction seam, which does not move. No anchor entry describes a moved body, so none is added.check:adr-anchorsexits 0 at both ends: 137 decision numbers, and 58,841 citations at both ends (8,253 files at base, 8,254 at head: the new module). The decision-letter count on the anchored surface goes from 1,847 at base to 1,842 at head. The five citations are ADR-0076 D2, ADR-0131 D8, ADR-0095 D1, ADR-0105 D2 and ADR-0131 D7. They sit in the moved helper docblocks, and the new module is not an anchored file. They are still valid letters. A probe entry for the new module, made only to measure and then deleted, put the count back to 1,847 with the gate at exit 0. Whether the module should get its own entry is in Acceptance notes.check-adr-symbol-anchors: 2,474 anchors resolve.check-platform-checklist --changed-from origin/main: 1 anchored file in the change set, 14 anchors judged, 0 lost.Direct dependants (A3, narrowed and declared)
No dependant was type-checked locally. Both moved methods are private, so no dependant can reach them, and the six published declaration files are byte-identical. CI's TypeScript Type Check lanes cover the dependants.
For the next dispatch (cut 5)
From cut 3's list, the areas still waiting are these: Roll-up summaries (spec-coupled, see cut 1); the Datasource registry (U = 3); Related-record expansion (
expandRelatedRecordsreads the private staticMAX_EXPAND_DEPTH). I did not measure a fresh seam table for cut 5. The next dispatch should measure one.Acceptance notes
engine-realtime-publish.ts? Five decision-letter citations left the anchored surface with the moved helpers (above). By card ask 3, no entry is owed, because no anchor paragraph describes a moved body. This claim's file surface also does not includescripts/adr-anchors/**, so I did not add one. If the seat wants those five letters checked again, a one-file entry that names ADR-0131 would do it. The paragraph would coverbulkEventOrganizationId, which reads the recorded wall verdict alone (D8). The probe above shows that entry passes. Carrier: the seat.Verification
All at head
2108463930.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): 467 files, 1,903 suites, 8,718 tests, 8,718 passed, 0 failed, 0 skipped.pnpm lint(eslint . --no-inline-config, repo-wide, as the seat asked): exit 0.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 91 families on the real diff at2108463930(stderr names the repo and the commit). All 91 were run, and each exit code was recorded before any pipe. 89 exited 0 on the first pass.check:skill-examplesexited 3 until I built the@objectstack/client-react...closure, then exited 0 (262 prose examples type-check).check-engine-split-ratio --days 90exited 0, ratio 97.8%, with history deepened to 2026-07-19.--ranreconciles: 91 accounted for, 90 run, 1 NOT MEASURED:check:dual-build-cjs-loadsexited 3, PREREQUISITE NOT MET: the other packages have nodist/. The export lists above answer its question for this package, and CI runs it.check-adr-anchors(base and head),check-adr-symbol-anchors,check-platform-checklist --changed-from origin/main,check-commit-card-trailers --range origin/main..HEAD.test:repowas not run locally; CI'sTest Coreruns it.Generated by Claude Code