Repository navigation
refactor(objectql): move the driver options and engine posture bodies out of engine.ts into engine-driver-options.ts (#25522 cut 12) - #26371
Conversation
… out of engine.ts into engine-driver-options.ts (cut 12) buildDriverOptions, driverReadScope, engineLayer0Verdict, wallExemptedOperation, driverWriteTarget and resolveEnginePosture move unedited into engine-driver-options.ts through one DriverOptionsHost, with the module helper only they use (accessibleOrganizationsOf). Each method stays on the class with its signature and docblock as a delegate. Path readers migrated: the system-context census row 24 and its NON_READ_ANCHORS entry, the two federated-readers keys, and the engine.ts ADR anchor paragraph, whose buildDriverOptions half follows its body into the new module's own entry. Claude-Session: https://claude.ai/code/session_014SEAruKUVJHjiYsA6bZyLy Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 3 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 8991c05d8aeea7ace2182c563d20d2fd04326f15 && git checkout 8991c05d8aeea7ace2182c563d20d2fd04326f15
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 6390fe52cecd263f09225d0d6d9b74412d111a67 17781355cdd6796c7604b5a33752d542a7b02cdd && git checkout -B drift-repro 6390fe52cecd263f09225d0d6d9b74412d111a67 && git merge --no-ff 17781355cdd6796c7604b5a33752d542a7b02cdd
node scripts/docs-audit/affected-docs.mjs --json 6390fe52cecd263f09225d0d6d9b74412d111a67
|
席位核对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
维护者速读
engine.ts里「驱动选项与引擎租户姿态」整段 6 个方法和它们独用的一个辅助函数原样搬进新文件engine-driver-options.ts,类上方法签名与注释不变,只把方法体换成转交。engine.ts22,651 → 22,517 行。src/engine.ts(23,903 lines, +7,501 in 30 days) along itsObjectQLseams, one move-only slice per PR #25522 按缝拆分engine.ts的第 12 刀;本段在刀前重测的缝表里净减行最多,且不与在途 PR 重叠。.d.ts六个文件逐字节不变。回滚 = revert 本 PR。packages/objectql/src/engine-driver-options.ts(搬入的方法体)、packages/objectql/src/engine.ts(6 个转交桩)、scripts/adr-anchors/两个 JSON(ADR 锚段落按方法拆分)。pnpm --filter @objectstack/objectql exec vitest run --project local --maxWorkers=2,应见 472 个测试文件全部通过。Cut 12 of the
packages/objectql/src/engine.tssplit (#24586 ruling A, recorded in6270097840). The claim is6429419365. The whole "Driver options and engine posture" section moves unedited into a new module,packages/objectql/src/engine-driver-options.ts:buildDriverOptions(theDriverOptionsevery driver call receives),driverReadScope(the Layer 0 verdict projected onto a read's driver scope),engineLayer0Verdict(that verdict over the engine's own facts),wallExemptedOperation(did the wall's exemption lift an operation's scope),driverWriteTarget(an insert's write target) andresolveEnginePosture(the tenancy posture in force). The one module helper only they use,accessibleOrganizationsOf, moves with them. No behaviour changes. #25522 stays open for the later cuts.Branch
claude/project-thread-isr622(the card thread's harness-pinned branch), cut fromorigin/mainat222755ebb, which contains cut 11's merge (fc70ab36ba, #26351). Nothing was edited before that merge landed.origin/main(6390fe52c) was merged in once before this PR opened; none of the commits it brought touchpackages/objectql/**,packages/core/src/security/**,content/docs/permissions/**,scripts/adr-anchors/**orscripts/check-system-context-census.mjs.What changes
Why this area
Re-measured on
222755ebbwith cut 11's scripts, unchanged (both screens: query-options erasure sites and module-helper closure).engine.tsis 22,651 lines, 7,202 of them from the last 30 days (git blame --since=2026-09-26T23:28Z).scripts/pm/git-history.mjs count: 130 commits in 30 days, 36 in 7.class ObjectQLholds 318 members, 255 methods and accessors.engine.tsat222755ebbis byte-identical to cut 11's head, where the table was first pre-measured while #26351 was in the queue.Seam table at 222755e (41 sections)
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 full per-method screen and price list are in the project file
pm-orders/server/25522-cut12-seam-table.md; the move script ispm-orders/server/evidence/25522/move-cut12.mjsand the anchor splitanchor-cut12.py.accessibleOrganizationsOf, whose two users (engineLayer0Verdict,driverWriteTarget) both moveThe script lists
engineLayer0Verdictas blocked by its helperaccessibleOrganizationsOf, whose other user isdriverWriteTarget.driverWriteTargetalone does not pay (a 4-line body behind a 5-line stub, +1), but moving it withengineLayer0Verdictlets the helper go too, so the pair pays about -19 together with it. That is the order's reading ("engineLayer0Verdictonly together withdriverWriteTarget"), and it empties the section.The shape
private), signature, docblock and position. Each body is now one host literal of exactly theDriverOptionsHostmembers it reads, plus a.call, marked[#25522 cut 12], as cuts 8, 10 and 11 did. Fields go as getters over areadXclosure (txStore,_registry,tenancyPostureProvider); methods go as late-bound closures (isClosedUnitHandle,transactionCoversDriverFor,driverWriteTarget,driverReadScope,wallExemptedOperation,engineLayer0Verdict,resolveEnginePosture), so a spy or double set on the engine is still the one a call reaches.DriverOptionsHosttypes each member as the class member (ObjectQL['txStore']and so on); each function'sthisis thePickof what it reads. The module imports the engine only as a type.accessibleOrganizationsOfmoves with its docblock byte for byte and is not exported; both its users moved. One copy, no re-derivation.isTenancyDisabled(@objectstack/spec/data),ExecutionContext(type),computeTenantLayer0Verdict(@objectstack/core, with its two-line import comment),resolveTenantFieldName(./tenancy/system-write-organization.js),resolveTenancyPosture(@objectstack/types),normalizeTenancyPosture,TenantLayer0VerdictSchemaand the typesTenancyPosture/TenantLayer0Verdict(@objectstack/spec/security) andisFederatedObject(./federated-object.js).engine.tsdropsisTenancyDisabled,computeTenantLayer0Verdict(with its comment),resolveTenancyPosture(the whole import line),normalizeTenancyPostureandTenantLayer0VerdictSchema, whose last code readers moved (three of them are still named in docblocks that stay, which no linter counts as a use), and gains the module import with a three-line comment.isFederatedObject,resolveTenantFieldNameand the two types keep readers inengine.tsand stay imported there.Net lines (the seat's rule)
engine.tsgoes from 22,651 to 22,517 lines, net -134 (44 added, 178 removed). The module is 304 lines. With the path readers below, the diff againstorigin/mainis 544 changed lines over 7 files (+361 / -183).Readers of the moved lines (migrated in this PR)
scripts/adr-anchors/packages__objectql__src__engine.ts.jsondescribes the transaction seam in one paragraph whose first half isbuildDriverOptions's mechanism. The paragraph is divided, one home per half:packages__objectql__src__engine-driver-options.ts.json,adrs: ["ADR-0067", "ADR-0119"](ADR-0119's same-origin amendment, recorded on the 2026-08-06 ruling with ADR-0067's): the opening sentence ("The transaction seam is same-origin by construction (ambient 事务句柄跨数据源泄漏:凡在事务中执行的被审计写入,合规审计行全部静默丢失(#5226 的真实根因) #5351/[spec] engine.transaction 契约收紧:opts.requirefail-closed、跨驱动拒绝、owned-vs-joined 信号(#4619 的契约半边,维护者已批 P2) #5696, 2026-08-06 ruling).") plus thebuildDriverOptionssentence verbatim, plus the last clause of the paragraph's closing sentence, "Never restore the unconditional handle lift."engine.tsentry keeps its three ids, the same opening sentence, theenforceTransactionOriginsentences verbatim, and the closing sentence's first clause, "Never add a companion transaction on the second driver (no two-phase commit in IDataDriver)."engine-execute-transactions.ts's entry (cut 7) still carries the whole paragraph; this PR does not edit it.check-adr-anchorsat base222755ebb(clean detached worktree): 90 anchored files, 1,877 decision-letter citations, 59,281 resolving citations. At head1b8e2b8b1: 91, 1,877, 59,285; at the merged head17781355c: 91, 1,877, 59,316 (main's own citations). The letter-citing body comments that moved (ADR-0131 D8,D9,D13, theADR-0131 D8import comment and the helper'sADR-0105 D2) leftengine.tsbut now count in the newly anchored module, so the count is equal.buildDriverOptionsreadsexecCtx?.isSystem(row 24, "Tenant-audit warning silenced"). The row's anchor incontent/docs/permissions/system-context.mdxand itsNON_READ_ANCHORSentry inscripts/check-system-context-census.mjs(collapsesOntoRead, file key only) now nameengine-driver-options.ts#buildDriverOptions. Control: with the move and neither re-key, the census fails with[ledger-stale-collapse]and[anchor-is-not-a-read-site]onengine.ts#buildDriverOptions; with both re-keys (and the module tracked), it passes: 153 read sites across 83 files (82 at base), 145 of 145 symbols cited.federated-injected-column-readers.test.tskeys rowsFILE#FUNCTION :: SEAM; the twobuildDriverOptionsrows (isFederatedObject(),resolveTenantFieldName()) are re-keyed toengine-driver-options.ts#buildDriverOptions, dispositions unchanged.objectql/src/engine.ts#NAMEpointer underpackages/spec/**,docs/adr/**,docs/qa/**orcontent/**names a moved member other than row 24. Prose that namesbuildDriverOptionsorresolveEnginePosture(ADRs 0034, 0119 and 0131, driver and plugin comments, tests, CHANGELOGs) still resolves, because the methods stay on the class. No core census keys a moved body (row-serving-door-exposurekeys.canReadObject(callers andsecond-object-read-exposurekeysreferenceTargetOf(callers; the moved bodies make neither call). No moved body holds aquery-options/no-any-erasuresite (engine.tsstays at 8 inquery-options-erasure-baseline.json) or a tenant-audit untyped receiver.Tests
Published .d.ts identical (ruling 6348891160), with a positive control
Base:
@objectstack/objectqlbuilt in a clean detached worktree at222755ebb(its ownpnpm installand^...closure build;engine.tsblobd68a6760checked, no module file). Head: built at1b8e2b8b1.buildDriverOptions.call(hostoccurs 0 times in the basedist/index.mjsand once in the head's. All six declaration files are byte-identical, and equal to the hashes cuts 7 to 11 recorded:core.d.mtsef178bf0725eccc2f358f082ce13dc5122a6d5a53c19ef630017256f67de03b4core.d.ts1d20303a455a909e4b55fd0802fb0b0bcb59ec51784daf27d5ef4c0659410953index.d.mtsccf900240aa137abe72f82b8abfc872d42c5645467400134c580285f2a3b3090index.d.ts0454d5e70b156d8effbf27b8915587c7cbee241dcd7d698013c0a4c369a02aa5util-CVzOGxAn.d.mts85ef1cbec2b016d5f7afabaa21689c86c6dffc573076fdfdeb8ea0f1a1b1ad53util-CVzOGxAn.d.ts85ef1cbec2b016d5f7afabaa21689c86c6dffc573076fdfdeb8ea0f1a1b1ad53Positive control:
scripts/ablation-replace.mjsdroppedprivatefrom thedriverWriteTargetstub (anchor hit once, x1 to x0; replacement x0 to x1) and rebuilt: all six hashes and the chunk name changed (util-QbuYzUnN.d.ts6a0616b618e4…,index.d.ts363d8d91d88e…), and the chunk now printsdriverWriteTarget(execCtx: ExecutionContext | undefined): {as a public member. The tool restored the file (bloba17c9e9b93e6equal to HEAD,git diff HEADempty); after a rebuild, all six files compared equal to the head build again.Proof of move-only (TypeScript-AST leaf-token compare)
pm-orders/server/evidence/25522/astcmp.mjs(unchanged from cuts 9 to 11), baseengine.ts(222755ebb) against the head module:async:buildDriverOptions379 tokens / 111 lines,driverReadScope139 / 16,engineLayer0Verdict45 / 15,wallExemptedOperation86 / 8,driverWriteTarget61 / 4,resolveEnginePosture38 / 7.@objectstack/spec/dataimport lessisTenancyDisabled; the@objectstack/coreimport lesscomputeTenantLayer0Verdictand its comment; the@objectstack/typesimport, dropped; the@objectstack/spec/securityimport lessnormalizeTenancyPostureandTenantLayer0VerdictSchema. Head adds the module import.git hash-object, 7 of 7).Suites
At
1b8e2b8b1(the cut; the merge oforigin/mainafter it changes no file underpackages/objectql/**orpackages/core/**):pnpm --filter @objectstack/objectql typecheck(tsc --noEmit+check:test-typecheck): VERDICT command-exit 0.pnpm exec eslint --no-inline-config packages/objectql scripts/check-system-context-census.mjs: exit 0.pnpm --filter @objectstack/objectql exec vitest run --project local --maxWorkers=2: 472 files, 8,789 tests passed (VERDICT command-exit 0). The suites that drive these bodies (engine-driver-read-scope,engine-external-tenant-scope,engine-reference-tenant-scope,engine-timezone-presence-gate,engine-transaction-same-origin,engine-data-events,federated-injected-column-readers) are among them.vitest run --project repoin every package that has one, after the^...closure builds:core6/6 files (83 tests),objectql1/1 (5),rest5/5 (280 passed, 18 skipped),runtime3/3 (947),spec79/79 (1,279),types1/1 (11), all VERDICT command-exit 0..d.tsfiles are byte-identical, so no dependant can see a difference. CI'sTypeScript Type Checkcovers them.Acceptance notes
pr_create(17 open PRs at 00:38Z): two touchpackages/objectql/**. feat!: ownership queues and assignment rules (ADR-0142 phase 2) #26337 (ADR-0142 phase 2, head9ada3a920) editsengine.tsin nine hunks (an import near line 245, three declarations near lines 3916, 4221 and 4751, and theinsert/updatebodies from base line 15629 on) and adds rows tofederated-injected-column-readers.test.tsnear line 355. None is in the moved section (base lines 7141 to 7471), on the import lines or helper this cut edits, or on the two re-keyed rows (line 188).git merge-tree --write-treeof this head with its head merges cleanly (exit 0). Under the card's rule 4 whichever lands second mergesmain. feat(spec,cli)!: retire the ≤16.x retirement kits; the strict unknown-key refusal names the protocol upgrade guide #26138 editsvalidation/rule-validator.test.tsonly. No open PR touchessystem-context.mdx,check-system-context-census.mjsorscripts/adr-anchors/.resolveEnginePosturecallsthis.tenancyPostureProvider?.(). In the class the call's receiver was the engine; in the module it is the host, whose getter returns the same function. The one production registration (plugin-security'ssetTenancyPostureProvider(() => this.tenancyPosture)) and every test registration pass arrow functions, so nothing reads the receiver.this.txStore.getStore()andthis._registry.getObject(...)keep their own receivers (the store and the registry).engine-realtime-publish.ts's header saysaccessibleOrganizationsOfstays inengine.ts; after this cut it lives inengine-driver-options.ts. The file is outside this claim's surface, so it is left for the seat to route.Verification
At
17781355c(final head, the merge oforigin/main6390fe52cinto1b8e2b8b1):dispatch-gates --commandsderived 111 families on the real diff (the same list at1b8e2b8b1and after the merge). Every one was run, each exit code captured before any pipe, then reconciled with--ran: 111 accounted for, 110 run green, 1 NOT MEASURED (exit 3, PREREQUISITE NOT MET; CI runs it):check:dual-build-cjs-loads(needs every package'sdist/). Three first answered a prerequisite and were re-run green after the prerequisite was met:check-engine-split-ratio --days 90andcheck-plugin-teardown-shape --self-test(shallow clone, re-run aftergit fetch --unshallow), andcheck:skill-examples(re-run after building@objectstack/client-reactand@objectstack/client: 264 prose examples type-check). Named readings:check-system-context-censusOK,check:adr-anchorsOK,check:query-options-erasure,check:durability-log-level,check:engine-double-contract,check:lean-entry-closure,check:type-check-debt,check:logger-receiver-detach,check:org-identifier,check:nul-bytes,check-affected-docs, all exit 0.check-adr-anchorsat base and head (above),check-adr-symbol-anchors(2,664 anchors resolve),check-tenant-audit-census(244 write sites certified),check-platform-checklist --changed-from origin/main(13 anchors judged, 0 lost) andcheck-commit-card-trailers --range origin/main..HEAD.Test Corefarm is CI's.skip-changeset: move-only. The published.d.tsfiles 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. The other edits are a docs page, a test key, a repo script and two anchor files.🤖 Generated with Claude Code
https://claude.ai/code/session_014SEAruKUVJHjiYsA6bZyLy
Generated by Claude Code