Repository navigation
refactor(objectql): move execute and the transaction-routing bodies out of engine.ts into engine-execute-transactions.ts (#25522 cut 7) - #26160
Conversation
…ut of engine.ts Cut 7 of the engine.ts split. The bodies of `execute`, `warnTransactionUnsupported` and `enforceTransactionOrigin` move unedited into `engine-execute-transactions.ts`; each method stays on `ObjectQL` and hands its body the members it reads through `ExecuteTransactionsHost` (fields as getters, methods as late-bound closures). The engine.ts ADR anchor paragraph describes `enforceTransactionOrigin`, so the new module carries that paragraph in its own `scripts/adr-anchors/` entry. Claude-Session: https://claude.ai/code/session_017XKjAUHgJooyUifvSi4RjW Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 1 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 287ac44fa9d8040a2cacac3d1ae655e2a5a3cfbd && git checkout 287ac44fa9d8040a2cacac3d1ae655e2a5a3cfbd
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin a335f1defbea57ffe552d2e9efc5ad8d56a2e76a afe19760a0b4d102c3938beb3a7aa3609bedf7b2 && git checkout -B drift-repro a335f1defbea57ffe552d2e9efc5ad8d56a2e76a && git merge --no-ff afe19760a0b4d102c3938beb3a7aa3609bedf7b2
node scripts/docs-audit/affected-docs.mjs --json a335f1defbea57ffe552d2e9efc5ad8d56a2e76a
|
席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」.
Generated by Claude Code |
Requested by Leehom · project thread
Part of #25522
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160
Cut 7 of the
packages/objectql/src/engine.tssplit (#24586 ruling A, recorded in6270097840). The claim is6417034209. Three bodies of the "execute and transactions" section move unedited into a new module,packages/objectql/src/engine-execute-transactions.ts:execute,warnTransactionUnsupportedandenforceTransactionOrigin. No behaviour changes. #25522 stays open for the later cuts.Branch
claude/project-thread-tsjhtm(the card thread's harness-pinned branch), cut fromorigin/mainata6e8f95d6(after cut 6,3380671aef), withmainmerged once atd1ea2363fbecause #26026 (which editsengine.ts) landed during the cut and this PR lands second. #26026's hunks sit in Autonumber,insertandupdate; none is in this PR's range.Why this area (the fresh seam table)
Measured on
origin/maind1ea2363f(the merged base; a first reading ona6e8f95d6picked the same area).engine.tsis 23,241 lines, 7,344 of them (31.6%) from the last 30 days (git blame -s --since=2026-09-26T13:22Z).scripts/pm/git-history.mjs count(window covered, exit 0): 125 commits in 30 days, 32 in 7.class ObjectQLholds 318 members, 255 methods plus the constructor. Sections are cut 1's contiguous member ranges, re-located by first member name, docblocks included. "inferred public" stays; "U" countsthis.FIELD.delete/insert/update(sites (AST, casts stripped); "private statics" stay.txStore…constructorgetStatus…registryregisterHook…triggerHookshasHooksFor…assertBulkPerRowHookBudgetregisterAction…setActionActive_heldFileResolver…registerInsertRecomputeListenerreadableIdsSecurityReported…resolveDefaultPermissionswriteEpoch…hasObjectMiddlewareexecuteWithMiddleware…buildUserbuildDriverOptions…resolveEnginePostureprobeInstallOrganizations…transactionCoversDriverForresolveNowDefault…defaultFieldEntriesapplyAutonumbers…seedAutonumberregistrationConversionWarned…registerDriversupplyFileColumnsMovedResolver…listUnavailableDatasourcesassertWriteAllowed…publishBulkDataEventsetI18nService…objectDisplayLabelassertReferencesResolve…masterDeclaredFieldsinspectDanglingReferences…inspectCascadeDeletesetCryptoProvider…setTenancyPostureProviderencryptSecretFields…resolveInternalFieldgetSchema…judgeFilterLIFECYCLE_DATASOURCE…setDatasourceMappinginit…resolvePrimaryDatasourceobjectHasMediaField…valueShapeStrictForisFileReferencesMigrationVerified…wasDatastoreCreatedFromEmptydestroy…destroyMAX_EXPAND_DEPTH…MAX_BULK_PER_ROW_HOOK_ROWSautonumberCounters…recomputeSummariesexpandRelatedRecords…expandRelatedRecordsresolveFileReferences…readParentDerivedFilesresolveWhereTokens…requireFindOnePredicatefind…staticReadonlyCreateStripvalidate…validatereadUpdatePriorRow…insertManyupdate…updateplanCascadeAtomicity…organizationOwnedRowCountsdelete…deletecount…aggregateexecute…enforceTransactionOriginregisterObject…createThe per-method move screen for every section, and the pricing below, are in the project file
pm-orders/server/25522-cut7-seam-table.md. A body stays if any of these holds: an inferred-return public method, a U site, a private-static read, anengine.ts#NAMEpointer underpackages/spec/**ordocs/adr/**, athis.update(/this.insert(/this.delete(self-call, or a static. Bodies earlier cuts moved are counted as stubs, not as movable.Pricing (net
engine.tslines): a stub costs a comment, the host literal's open and close and the.call, plus two lines per field read (aread*closure and a getter) and one per method read (a late-bound closure); the import adds three.syncSchemas63,syncObjectSchema17,createContext8,registerObject9syncSchemasholds 35 of the section's 41 recent lines; every body is public APIrecordObservedDeviationandretractCreationAttestationself-callthis.update(createWithAutonumberResyncin this section while the cut ranbuildSummaryIndexand field writes; U = 3; private staticMAX_EXPAND_DEPTHpackages/specpointerWhat stays in the section:
transaction(ADR-0119 cites it asengine.ts#transaction, and ADR-0067's join lives in it), andrunOpenedUnit(4 body lines),isClosedUnitHandle(3),newTransactionScope(5) anddatasourceNameOf(4), whose stubs would cost as much as their bodies.The shape (#23050 shape B, as cuts 1 to 6 apply it)
fn.call(host, …), marked[#25522 cut 7].executestays public with its declared return type (aPromiseofany), so it is not an inferred-return public member.ExecuteTransactionsHostis new:drivers,defaultDriver,txStore,transactionUnsupportedReported,logger,getDriver,datasourceNameOf,isSystemLedgerObject, each typed as the class member (ObjectQL['txStore']). Each moved function types itsthisas thePickof exactly the members its body reads, and each stub annotates its literal asThisParameterTypeof that function. There is no cast, and no member changes visibility.registerDriverreplaces the driver map's contents and the default), so each read happens when the body makes it. The three methods go as late-bound closures over the instance, so a double or spy set on the engine still intercepts.warnTransactionUnsupportedkeeps its default parameter (declaredUnsupported = false) on both the method and the function; the stub passes the value it received.ObjectQLas a TYPE only and nothing re-exports it.engine.tsdropsCrossDatasourceTransactionWriteErrorfrom itstransaction-errors.jsimport, because its last code reader moved; three docblocks that stay still name it in a{@link}(onplanCascadeAtomicity,transactionandenforceTransactionOrigin); their text is unchanged, so the published.d.ts, which prints the publictransactiondocblock, is byte-identical (measured below).redactPropagatedDriverFaultandTransactionUnsupportedErrorstill have readers inengine.tsand stay. The module-scopeScopedContexthelper's callengine.warnTransactionUnsupported?.(…)still reaches the method on the class.Net lines (the seat's rule)
engine.tsgoes from 23,241 to 23,165 lines, net -76 (31 added, 107 removed). The module is 199 lines: the header and host interface (about 66), three one-line docblocks, and the 106 moved body lines with their signatures. The diff is 346 changed lines over 3 files (+239 / -107), far under the 3,000-line human-merge threshold.The published
.d.tsdoes not change (ruling6348891160)Base:
@objectstack/objectqlbuilt withengine.tsrestored fromd1ea2363fand the new module removed (tree only; restored withgit checkout HEAD --, blob hashes compared,git statusclean). Head: built atafe19760a, then rebuilt after the base leg and compared again. The headdist/index.mjscarriesexecute.call(hostonce and the base build has it zero times, so each leg built the source it names. All six declaration files are byte-identical:core.d.ts1d20303a455a909e4b55fd0802fb0b0bcb59ec51784daf27d5ef4c0659410953index.d.ts0454d5e70b156d8effbf27b8915587c7cbee241dcd7d698013c0a4c369a02aa5util-CVzOGxAn.d.ts85ef1cbec2b016d5f7afabaa21689c86c6dffc573076fdfdeb8ea0f1a1b1ad53core.d.mtsef178bf0725eccc2f358f082ce13dc5122a6d5a53c19ef630017256f67de03b4index.d.mtsccf900240aa137abe72f82b8abfc872d42c5645467400134c580285f2a3b3090util-CVzOGxAn.d.mts85ef1cbec2b016d5f7afabaa21689c86c6dffc573076fdfdeb8ea0f1a1b1ad53Positive control: removing
privatefromenforceTransactionOriginin the head source and rebuilding (atb481820cd; the edit's landing checked by occurrence count, 1 private / 0 public before, 0 / 1 after) changed all six hashes, and the chunk name with them (util-CcX3xT6f.d.tsf3f2303e…7731d,index.d.ts9bd53e88…67ce). Restored withgit checkout HEAD --and blob hash compared. Export lists are the same for ESM and CJS at both ends:.182 names (sorted sha256881616cc…0adaa) and./core54 (393e8069…90f49). No moved name is exported. The same six-file comparison againsta6e8f95d6(before the merge) was also byte-identical.Proof of move-only
A TypeScript-AST leaf-token compare (recursive
getChildren, JSDoc skipped) of baseengine.ts(d1ea2363f) against the head module:this, default value included), return type, type parameters and body tokens are SAME,asyncmatches, and every body line equals the base line less two leading spaces, comments included:execute263 tokens / 55 lines,warnTransactionUnsupported89 / 26,enforceTransactionOrigin142 / 25.===to!==in the movedexecute(params === undefined) reports DIFFER; editing only one comment in the movedenforceTransactionOriginfails the line rule. Both exit 1, and the module was restored fromHEADand blob hash compared after each.transaction-errors.jsimport. Head adds the new module import with its comment.Readers of the moved lines
scripts/adr-anchors/packages__objectql__src__engine.ts.jsoncarries one paragraph, the transaction seam, and it describesenforceTransactionOrigin(plusbuildDriverOptionsandTransactionScope, which stay). Per the card, the new module gets its own entry carrying that paragraph verbatim:scripts/adr-anchors/packages__objectql__src__engine-execute-transactions.ts.json, ADR-0057, ADR-0067 and ADR-0119, each named in the module (the movedenforceTransactionOriginbody cites ADR-0057 §3.6, and the module header names all three). This is a data row the existingcheck-adr-anchorsreads (one JSON file per anchored path, no index to register), not a new gate; the engine entry stays as it is, because all three ids and the stubs it describes remain inengine.ts.check-adr-anchorsat based1ea2363f: 88 anchored files, 1,879 decision-letter citations; at head: 89 anchored files, 1,879 decision-letter citations (also 88 / 1,879 ata6e8f95d6). The moved bodies cite no decision letter, and the module header uses none.engine.ts#NAMEpointer anywhere names the three.docs/adr/0096namesengine.tsbesideengine.execute()(file-level); the method is still on the class, so it still resolves.scripts/reader ofengine.tswas screened, and the 32 test files that readengine.tsfrom disk. The twopackages/coredoor pins and thepackages/typescaller pin (which walk every.tsfile) were run and are green.packages/spec/liveness: 46 evidence strings citeengine.ts, and none quotes text from the moved bodies (screened for their identifiers and refusal strings).check-tenant-audit-censusis green (243 write call sites; the moved bodies hold nothis.FIELD.delete/insert/update(site).check:logger-receiver-detachis green (two moved bodies readloggerthrough a getter, so the receiver is kept), and so arecheck-system-context-censusandcheck:durability-log-level.Acceptance notes
engine.tsbeside a moved method still resolves by method name, because every method stays on the class (for exampletransaction-errors.tsnamingenforceTransactionOrigin). Left as it is.pr_create: 36 PRs are open; the only one onpackages/objectql/**is test(objectql): load the package entry with hook-run-as.test.ts, not inside its case #26132 (hook-run-as.test.tsonly). fix(objectql,types,rest)!: a database NOT NULL refusal on a declared field is the record validator's ValidationError at every door #26026 landed during the cut and is merged in.origin/mainmoved five commits after the merge, none onpackages/objectql/**orscripts/adr-anchors/**, anddispatch-gatesprinted no stale-tree warning, so it was not merged again.syncSchemashot); nothing else pays without a ruling (Migration flags needs setters).Verification
At
afe19760a(the merged head):pnpm --filter @objectstack/objectql typecheck(tsc --noEmit+check:test-typecheck, 39 files / 233 errors / 64 pinned signatures held): VERDICT command-exit 0.pnpm exec eslint --no-inline-config packages/objectql: exit 0.pnpm --filter @objectstack/objectql exec vitest run --project local --maxWorkers=2: 471 files, 8,774 tests passed. Before the merge, atb481820cd: 470 files, 8,748 passed. The run includesengine-transaction-contract.test.ts,engine-transaction-declared-unsupported.test.ts,engine-transaction-observability.test.ts,engine-transaction-same-origin.test.tsandengine-scoped-transaction-late-write.test.ts.packages/corerow-serving-door-exposure.pin.test.ts+second-object-read-exposure.pin.test.ts: 2 files, 7 tests passed;packages/typesdriver-error-classification.callers.test.ts: 11 passed..d.tsfiles are byte-identical, so no dependant can see a difference. CI'sTypeScript Type Checkcovers them.afe19760a:dispatch-gates --commandsderived 66 families on the real diff. Every one was run, each exit code captured before any pipe, then reconciled with--ran: 66 accounted for, 65 run, 1 NOT MEASURED. NOT MEASURED (CI runs it):check:dual-build-cjs-loads, exit 3, PREREQUISITE NOT MET (it needs every package'sdist/; the export lists above answer it for objectql). Named readings:check-system-context-censusOK (151 read sites, 144 of 144 symbols cited),check:logger-receiver-detachOK (3,733 files, 0 detaches),check:durability-log-levelexit 0,check-engine-split-ratio --days 9097.6%.afe19760a:check-adr-anchorsat base and head (above),check-adr-symbol-anchors(2,658 anchors resolve),check-tenant-audit-census(243 write call sites),check-nul-bytes,check-platform-checklist --changed-from origin/main(13 anchors judged, 0 lost) andcheck-commit-card-trailers --range origin/main..HEAD.test:repowas not run locally; CI'sTest Coreruns it.skip-changeset: move-only. The published.d.tsfiles and export lists are byte-identical,liveness/and every other published path are untouched, and the module's runtime is the same code under a different file name.Generated by Claude Code