Repository navigation
refactor(objectql): move the validate body out of engine.ts into engine-validate.ts (#25522 cut 16) - #26792
Conversation
…ne-validate.ts The write preview's body moves unedited into a new module behind ValidateHost; the method keeps its name, modifiers, signature, docblock and position, and hands the body the members it reads. Six helpers the body shares with insert/update gain export in place and are imported back, never copied. The preview parity pin reads the preview's calls from the new module, and the system-context site register follows the moved isSystem read. Two staying docblocks stop linking the constant the previous cut moved. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5oafXXU7gvgcHxdZb9
The batch roll-up accumulation's three hunks in the write preview land in engine-validate.ts, where the body now lives; getSummaryDescriptors joins ValidateHost as one more late-bound method. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5oafXXU7gvgcHxdZb9
📓 Docs Drift CheckThis PR changes 1 package(s): 21 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 8 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. 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 704dcdf14fc9689388d809c4e7fbb4b0e7356b02 && git checkout 704dcdf14fc9689388d809c4e7fbb4b0e7356b02
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin c8583f80ac47177421c9c1fb71e5e33e431ad9cf 3d228114aa43f1a727ac431f005090b996b74437 && git checkout -B drift-repro c8583f80ac47177421c9c1fb71e5e33e431ad9cf && git merge --no-ff 3d228114aa43f1a727ac431f005090b996b74437
node scripts/docs-audit/affected-docs.mjs --json c8583f80ac47177421c9c1fb71e5e33e431ad9cf
|
The import dry run's three hunks in the write preview land in engine-validate.ts, where the body now lives; assertReferencesResolve joins ValidateHost as one more late-bound method. The docblock hunk applies to engine.ts, where the docblock stays. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5oafXXU7gvgcHxdZb9
席位核对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 + 6441032442
维护者速读
engine.ts里写入预览validate(不落库、按写入路径自己的规则给出每行判定)的方法体原样搬进新文件engine-validate.ts,类上的方法签名与注释不变,只把方法体换成转交;方法体与insert/update共用的 6 个工具函数原地加export、由新文件导入(不复制)。顺带把上一刀遗留的两处{@link READABLE_IDS_MAX_CHAIN_DEPTH}用一个仅类型导入接回(注释文字一字不改)。engine.ts22,189 → 21,733 行。fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680 与 fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778(都改了validate方法体)已先合入,各自的三处改动随方法体一起搬进新文件。src/engine.ts(23,903 lines, +7,501 in 30 days) along itsObjectQLseams, one move-only slice per PR #25522 按缝拆分engine.ts的第 16 刀。validate是缝表上收益最大的一块(约 −439),之前被「公开.d.ts逐字节不变」挡住;新裁决6441032442(B)允许仅声明顺序与分块文件名变化,本刀按该裁决切出。.d.ts六个文件在裁决规定的归一化后完全相同(声明集、导出集、声明内容逐字节相同,只是分块里声明的先后与分块名变了);含正控。新文件与engine.ts互相导入,构建产物里模块顺序只多出新文件一行;一次性探针在新旧两版构建产物上逐行对照(69 行完全一致)。回滚 = revert 本 PR。packages/objectql/src/engine-validate.ts(搬入的方法体与ValidateHost)、packages/objectql/src/engine.ts里validate的转交桩与 6 处原地export、packages/objectql/src/validate-preview-parent.test.ts(对齐检查改为从新文件读预览调用)。pnpm --filter @objectstack/objectql exec vitest run --project local --maxWorkers=2 src/validate-preview-parent.test.ts,应见该文件全部通过(其中 parity 一组从engine-validate.ts找到唯一的预览调用)。Cut 16 of the
packages/objectql/src/engine.tssplit (#24586 ruling A, recorded in6270097840), under the claim6441744054. The body ofObjectQL#validate, the write preview (the write path's own verdict over candidate rows, persisting nothing), moves unedited into a new module,packages/objectql/src/engine-validate.ts, behindValidateHost. This is the first cut under the.d.tsdeclaration-reorder ruling6441032442(letter B): the published declaration chunk is reordered and renamed, and every declaration file is EQUAL under that ruling's normaliser (report block below, with its positive control). No behaviour changes. #25522 stays open for the later cuts.Branch
claude/project-thread-cjdmc4(the card thread's harness-pinned branch), cut fromorigin/mainatfe53769a8e, which contains cut 15's merge (378c940b16, #26645), withorigin/mainmerged in at1685a06dd9(after #26680) and atef7067fdaf(after #26778).What changes
Why this area
Re-measured on
fe53769a8ewith cut 11's measure script and cut 14's price step (price3.mjs), both unchanged.engine.tsis 21,947 lines, 6,830 of them from the last 30 days (git blame --since=2026-09-27T12:20Z, clone deepened to 2026-09-21 first);class ObjectQLholds 318 members, 255 methods and accessors. Query-options erasure sites: 8 at base (lines 8286, 9595, 9841, 9905, 10237, 13517, 13816, 18736), none invalidate's range.Seam table on
fe53769a8e(41 sections ofclass ObjectQL; U = untyped receivers)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-member screen and the full price output are in the project files,
pm-orders/server/25522-cut16-seam-table.md.fe53769a8e, 345 of them from the last 30 days; 492 once #26680's and #26778's lines arrived)METADATA_ARRAY_KEYSand itscheck-stack-collection-maps.mjsrow), as the order saysresolveFormulaRelated(Readable-ids security and permission/formula resolution)validate; a later cutThe shape
validatewith name, modifiers, signature, docblock and position. Its body becomes one host literal of exactly theValidateHostmembers it reads, plus a.call, marked[#25522 cut 16], as cuts 8 and 10 to 15 did. Fields go as getters over areadXclosure (_registry,_writeWallVerdict,logger,_writeGateProbe); methods go as late-bound closures (resolveObjectName,permissionResolution,resolveDefaultPermissions,initializeSummaryFields,applyFieldDefaults,staticReadonlyCreateStrip,mediaValueShapeStrictFor,valueShapeStrictFor,validationMessageContext,buildEvalUser,findOne,readUpdatePriorRow,resolvePreviewParents,resolvePredicateRelated,resolveOptionPermissions, and the two the body gained while this cut was in flight:getSummaryDescriptorsfrom fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680 andassertReferencesResolvefrom fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778), so a spy or double set on the engine is still the one a call reaches. The body assigns no field, so there is no setter (cut 13's setter ruling has nothing to apply to).validateis public with a declared return type (PromiseofValidateDataResponse), so the inferred-return series limit does not hold it; it has nothis.FIELD.delete/insert/update(site, no private-static read and no self-call toinsert/update/delete.undeclaredWriteFieldErrorsandstripComputedWriteFields(insert,update),droppedFieldEvents(insert),insertStaticReadonlySubject(insert,withholdInsertReadonlyFromHooks),updateStaticReadonlySubject(update,staticReadonlyStoredView),shouldSkipStateMachine(insert,update) andservedAsStored(already exported forengine-master-detail-related.ts). The six that were not exported gainexportin place, byte for byte otherwise (leading docblocks included); none moves and none is copied. The module imports the seven as values andObjectQLandWriteWallRowVerdictas types from./engine.js. It is a new module, so before that it imported nothing from./engine.js.index.tsandcore.tsname their exports singly, so nothing new is published. ExportinginsertStaticReadonlySubjectis the export that reorders the published chunk (below); that is what ruling6441032442now allows.engine.tsand the module import each other. The module runs nothing at evaluation (declarations only), andengine.tsimports it right after./engine-update-dispatch.js, which is after every module the body imports (validation/record-validator,validation/rule-validator,engine-update-dispatch, the@objectstack/specsubpaths), so the evaluation order of every other module is unchanged. Measured on the built bundles (index.mjs,core.mjs,index.js,core.js): with the// src/engine.tsregion markers set aside (9 at base and at head), the// src/...region order at head equals the base's with one line added,// src/engine-validate.ts, betweenengine-update-dispatchandintegrity/dangling-reference-audit. The bundles hold both files in one module, so the published build has no cycle. The late-binding probe answers the same on base and head (Tests).RAW_FILE_VALUES_CONTEXT_KEY,EngineQueryOptions(type),ExecutionContext(type),ValidateDataIssueandValidateDataResponse(types),WriteObservabilityOptions(type),validateRecordInScope,normalizeBlankTypedValues,normalizeNumericStringValues,ValidationError,valueShapeStrictEffective,mediaStrictEffective,evaluateValidationRules,hasParentScopedRequiredWhen,stripReadonlyFields,stripRuntimeOwnedFields,createBatchSummaryAccumulator(fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680's, whichengine.tskeeps forinsert) andresolveEngineUpdateDispatchwithEngineUpdateDispatchData(type).engine.tsdrops the four whose last reader moved:ValidateDataIssue,RAW_FILE_VALUES_CONTEXT_KEY,valueShapeStrictEffectiveandmediaStrictEffective(each from its existing import line; no line is removed).{@link READABLE_IDS_MAX_CHAIN_DEPTH}. The docblocks ofcomposeReadableIdsAtBoundaryandcomposeReadableIdsChainstay byte for byte; the link now resolves through a type-only import,import type { READABLE_IDS_MAX_CHAIN_DEPTH } from './engine-readable-ids-permission-formula.js'(a type-only import is erased from the JavaScript; TypeScript counts a{@link}as a use), and the constant gainsexportin place in that module (one home, unchanged value). Measured first the other way, and dropped: re-wording the two docblocks to name the module changed the published chunk, because those PRIVATE members' docblocks are printed in the.d.ts(private composeReadableIdsAtBoundary;under its docblock). That is a change inside thedeclare class ObjectQLstatement, outside ruling6441032442's bar, so it was not kept. With the type-only import the head.d.tsis byte-identical to the ruling's measured variant (below).Net lines (the seat's rule)
engine.tsgoes from 22,189 to 21,733 lines, net -456 (44 added, 500 removed). The module is 607 lines. The diff againstorigin/mainis 1,187 changed lines over 5 files (+671 / -516).Readers of the moved lines
content/docs/permissions/system-context.mdxsite register. The body's oneisSystemread (the caller-write strips' gate) moves with it, so the generated register's anchorpackages/objectql/src/engine.ts#validate(1 read, row 21b) becomespackages/objectql/src/engine-validate.ts#validate, rebuilt bynode scripts/check-system-context-census.mjs --write(aftergit add -Nof the module), never by hand. Row 21b'sSymbolcell namesvalidateby symbol, so it stays.scripts/check-system-context-census.mjs'sNON_READ_ANCHORShas novalidaterow.packages/objectql/src/validate-preview-parent.test.ts(f), the preview/write parity pin. It readengine.tsand attributed eachevaluateValidationRulescall to its enclosing class method, the one invalidatebeing the preview. The preview's call now lives in the module's top-level functionvalidate, so the reader reads both files and attributes a call to its enclosing method OR function, and names the file in its messages. The writes still come fromengine.ts. It still finds exactly one preview call (toHaveLength(1)), so it cannot pass empty.validatebyengine.tspath:objectql/src/engine.ts#NAMEpointers underpackages/spec/**,docs/**,content/**andscripts/**name none of the moved names;federated-injected-column-readers.test.tskeys none; the body calls nocanReadObject((core'srow-serving-door-exposure.pin.test.tsis unchanged) and noreferenceTargetOf((core'ssecond-object-read-exposure.pin.test.tsis unchanged); it holds noquery-options/no-any-erasuresite (8 at base and head), no tenant-audit untyped receiver and no private-static read.engine.tsentry is the transaction-seam paragraph), so the module needs no anchor entry of its own.src/protocol.ts(33,065 lines, +10,169 in 30 days) along itsObjectStackProtocolImplementationseams, one move-only slice per PR #25467).check-durability-degradation-log-level --listat base and head is identical once line numbers are masked: 48 durability seams and 88 read seams (at baseef7067fdaf), the same entries;validateis named in none.check-adr-anchorsat baseef7067fdaf(clean detached worktree): 1,898 decision-letter citations on the anchored surface, 59,978 resolving citations across 8,400 files. At head: 1,898, 59,978 across 8,401 (the +1 file is the new module). The count held at the earlier bases too (fe53769a8eand1685a06dd9: 1,871 = 1,871). The moved body citesADR-0104andADR-0113without a decision letter, so no letter leaves the anchored surface.Why
#25522 splits
engine.tsone seam at a time so that a change to one area reads, reviews and conflicts as that area alone.validateis the area that pays most (the seam table) and the one ruling6441032442freed; #26680 and #26778, which edited its body while this cut was in flight, have landed and are carried here (Acceptance notes). Nothing about what the engine does changes.Tests
No test is added. One test's source reader is migrated with the body (above): the move is proved by identity, not by new behaviour.
Public
.d.ts: the declaration-reorder bar of ruling6441032442item 1, with a positive controlBuilt
@objectstack/objectqlat the base (ef7067fdaf,origin/mainafter #26778:engine.tsblob8116d440cd7e,engine-readable-ids-permission-formula.tsblob099ea596128b, noengine-validate.ts) and at head (engine.tsblobfa37297312da), each from a clean tree (dts-cut16.sh), after a fullturbo run build(116 of 116 tasks). The same bar held at the two earlier bases (fe53769a8eand1685a06dd9, the latter with byte-identical declarations to the former). The builds are the moved code, not a stale cache:validate.call(hostoccurs 0 times in the basedist/index.mjsand once in the head's.Normaliser:
pm-orders/server/evidence/25522/dtsnorm.mjs, sha25625226e0677bdad24726e9eff76a7e247bf7319440d2430d28cbaab0db6add94b(the ruling's), run asnode dtsnorm.mjs --diff BASE_FILE HEAD_FILEon the twodist/directories.6348891160's union-order normaliser has nothing to apply to: the statement-level one closes every diff on its own.core.d.ts01b7e638addebd16…642b5a3662c27aabde2dae4bb5877f515cb89f4c1e8075f21c0598b7e602520640e2fde86719d3ccd1cf492314c426c977ab836a5ab54580800cd1f41352247a4450aaf478092516…(1 decl) EQUALcore.d.mts66eaf00a556923e4…07f5718a09a2662c2f94bc3d79a8e74b67310efa82071a5d81ed1b716adaa69c171eab8743fd8dfabc014a162c40c3e034be29f262b26a2bcc24cb3e06be04594450aaf478092516…EQUALindex.d.tsf16604a77d499f56…6dd970eb9c7dc4364e2fe99d22460672edc270302287f812231d8230904911222bb6a21a929b41c8dbb85c72c600f87ed3a3af12ca731d1cace61f5d4aa3d57e9136189ce4d0aba3…(103 decls) EQUALindex.d.mtse6a8dff9693367bd…37153868b48bef0e9ad655d74b549a30f51510977cb704e0d6624db1d8e83781c7d7bab765f3b0fb35241fa03bd0b716a93139c98e5638d209379dad96528f989136189ce4d0aba3…EQUALutil-BcFTQcXa.d.ts→util-DdsJlVTF.d.tsd8cd099b508be5ea…856d98e0e45ced3ec15bf72a1ac09420a2c4f73b5165ab598c1d7d0000705f02a4372dd015163a46e90b82473d806423a5ca982b8bef21e6e8bfed2b0655b9dd71a464127e0b90b1…(173 decls) EQUALutil-BcFTQcXa.d.mts→util-DdsJlVTF.d.mtsd8cd099b508be5ea…856d98e0e45ced3ec15bf72a1ac09420a2c4f73b5165ab598c1d7d0000705f02a4372dd015163a46e90b82473d806423a5ca982b8bef21e6e8bfed2b0655b9dd71a464127e0b90b1…EQUALstatements only in base: 0; only in head: 0, declared-surface digest EQUAL.index182 names andcore54, ESM and CJS, the same sorted list at base and head).import/exportline and the side-effectimport '@objectstack/spec/…'lines in another order (12 and 8 lines); in the chunk, therule-validatordeclaration block printed earlier (hunks3598a3599,4164and11504,12069d12069), the externalimportstatements in another order and two specifier lists in another order. The chunk is renamedutil-BcFTQcXa→util-DdsJlVTF. Nothing else differs; the normalised files are identical.export function insertStaticReadonlySubjectalone variant measured for6441032442(pm-orders/server/evidence/25522/dts-reorder-ruling-measure.md): the samerule-validatorblock printed earlier, the same line counts. At the earlier base1685a06dd9the head was that variant byte for byte; main has since added declarations of its own, so the raw hashes are new.@objectstack/rest,@objectstack/runtime,@objectstack/client,@objectstack/client-reactand@objectstack/corewith their dependencies, whose DTS builds type-check against it) andpnpm --filter @objectstack/core typecheckran on the headdist/: exit 0 each.packages/objectql/package.jsonexportsnames./dist/index.*and./dist/core.*only,driver-sql's./dist/index.*only, so no chunk is a published path; (P3)git grep -n -E 'objectql/dist|driver-sql/dist' -- scripts package.json: 0 hits.Positive control. One
seddroppedprivatefromprivate async readUpdatePriorRow(on the head (a member the moved body reads through the host; anchor count 1 to 0, replacement count 0 to 1;engine.tsblobfa37297312dato843d3085ea88) and rebuilt (posctl16.sh, build exit 0): the chunk was renamedutil-BKP1J1qR, which now publishesreadUpdatePriorRow(object: string, id: unknown, context: ExecutionContext | undefined, base?: unknown): Promise…(line 10556); its normalised sha256 isd84c4ef94b1e5c90f96d9e23107fe38c3378bdcf7adb9f341f6357f8108435a8≠a4372dd0…, and its declared-surface digeste4dc581b5cbaa0f8…≠71a464127e0b90b1…(thedeclare class ObjectQLstatement named as the one changed).index.d.tsnormalises EQUAL under the control (an entry only re-exports), which is why every declaration file is read. The restore leg put the blob back tofa37297312da(git diff HEADempty), and the head was rebuilt before every later step.AST compare (move-only)
astcmp.mjs(TypeScript compiler API, comments and whitespace ignored, tokens compared) on baseengine.tsagainst headengine.tsplus the module:ef7067fdaf(parameters, return type,async, body tokens, and every body line equal after one level of indent):validate2,238 tokens / 492 lines, fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680's and fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778's hunks included. (Against the earlier bases it was SAME too:fe53769a8e2,093 / 469,1685a06dd92,148 / 476.)class ObjectQL: 324 of 324 members kept, in the same order; 323 byte-identical (both re-pointed docblocks included), and the stub keeps docblock, modifiers and signature identical.exportcmp.mjs): the 3 import lines that lose a name; the 6 helpers that gainedexportand are otherwise byte-identical with their leading docblocks; and the class. The head adds two statements: the module import and the type-only import.engine-readable-ids-permission-formula.ts: one statement changes,const READABLE_IDS_MAX_CHAIN_DEPTH = 8;gainsexport(its docblock and value unchanged).Late-binding probe (base and head
dist)zz-probe-cut16.mjs(a one-off, not committed; in the project files) loads the builtObjectQLand drivesvalidatewith doubles set on the instance after construction for the members whose real answer needs a datasource (mediaValueShapeStrictFor,valueShapeStrictFor,findOne,readUpdatePriorRow), the other eleven host methods wrapped to record the call order,getSummaryDescriptorsandassertReferencesResolvereplaced in their own cases, and_registry/loggerreplaced on the instance; then it prints results, the call order and the log lines. Cases: an insert that passes; a required field missing (two rows); a bad option; an undeclared key (thrownINVALID_FIELD); the computed and static-readonlystrips with theonFieldsDroppedevents; the same underisSystem; a listener that throws (logged and ignored);updateby id (the read door, then the stored row);updatewhose row the read door does not serve;updatewith no id; strict and warn-first value-shape postures;_writeWallVerdictset after construction (one row refused, one judged); a wall answering the wrong count (thrown);_writeGateProbeset after construction denying, and throwing;findOnereplaced after construction;loggerreplaced after construction; an unknown object;getSummaryDescriptorsreplaced after construction, reached by a two-row insert and not asked by a one-row insert;assertReferencesResolvereplaced after construction, reached on each insert row (its throw on the second row surfaces as it does at base) and not run by an update preview. The 69 output lines are identical on baseef7067fdafand head (the engine's construction log lines, which carry timestamps, set aside): the getters read what the instance holds when the body reads it, and the closures reach the replaced methods.Suites
Under
scripts/pm/os-verify-lock.shon head3d228114aa:@objectstack/objectql's dependencies, then of@objectstack/rest,@objectstack/runtime,@objectstack/client,@objectstack/client-reactand@objectstack/corewith their dependencies: exit 0.typecheckof@objectstack/objectqland@objectstack/core: exit 0 each.turbo run build(the rootbuildfilters): 116 of 116 tasks, exit 0.@objectstack/objectqlvitest--project local: 475 files, 8,843 tests passed, exit 0 (the migrated parity pin, with fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778's insert-preview case, and fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680'ssummary-batch-accumulation.test.tsamong them).validatepreview,pnpm --filter @objectstack/rest exec vitest run src/import-batch-parent-summary-rule.test.ts src/import-dry-run-batch-parent-summary.test.ts(fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680's and fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778's): 2 files, 18 of 18 passed, exit 0.pnpm --filter @objectstack/core exec vitest run src/utils/import-runner(fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778's dry-run callers of the preview): 16 files, 186 tests passed, exit 0.packages/*/vitest.repo-tests.jsonproject: core 6 files / 83 tests, objectql 1 / 5, rest 5 / 280 passed and 18 skipped, runtime 3 / 947, spec 80 / 1,295, types 1 / 11. Exit 0 each.Verification
Head
3d228114aa43f1a727ac431f005090b996b74437. The gate list isnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this diff at that head (85 commands, merge baseef7067fdaf), each run with its exit code captured before any pipe, then reconciled with--ran.--ran: 85 run, 0 NOT-MEASURED.**check:dual-build-cjs-loadsran after a fullturbo run build(116 of 116 tasks);check-plugin-teardown-shape --self-testafter fetching621a4876and deepening the clone (--shallow-since=2026-07-22). The exit codes are inpm-orders/server/evidence/25522/cut16-ran-final.txt.node scripts/check-adr-anchors.mjs(counts above),node scripts/check-tenant-audit-census.mjs,node scripts/check-adr-symbol-anchors.mjs,node scripts/check-platform-checklist.mjs --changed-from origin/main,node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD,node scripts/check-durability-degradation-log-level.mjs --list,node scripts/check-system-context-census.mjs, and eslint aspnpm lintruns it (--no-inline-config) onpackages/objectql.Acceptance notes
6441744054named this branch. The branch is cut fromfe53769a8e, which holds cut 15's merge (378c940b16).origin/mainwas merged three times: atf6ffd72347(no conflict), at1685a06dd9once fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680 landed, and atef7067fdafonce fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778 landed. The second and third merges conflicted invalidate's body, as expected. Each resolution keeps the stub inengine.ts, adds the member the body newly reads to its host literal (getSummaryDescriptors, thenassertReferencesResolve), and applies the PR's three body hunks to the same lines ofengine-validate.ts, one indent level in. fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778's docblock hunk applies toengine.ts, where the docblock stays.packages/objectql/**or a re-keyed reader, listed at start and again just before opening this. fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680 (Fixes Declarative "at most one row per parent where X" (conditional unique) — summary-based guards miss rows in the same bulk insert #25579) editedvalidate's body while this cut was in flight; under the seat's ruling (option A on the open question in the report on [maintainer] refactor(objectql): splitsrc/engine.ts(23,903 lines, +7,501 in 30 days) along itsObjectQLseams, one move-only slice per PR #25522) this branch waited for it, mergedmainafter it landed, and carries its three preview hunks inengine-validate.ts(the AST compare above is against1685a06dd9, after fix(objectql)!: a child rule reading a parent summary counts the earlier admitted rows of the same bulk create #26680). fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778 (Fixes import: the dry run previews each row alone, so after #25579 it answers valid for a row the commit refuses by a batch-aware parent-summary rule #26684) edited it next (a sequentialjudgeRowloop and the insert's reference check after the rules); under seat ruling6446486417this PR opened at07d67daf3ewithout landing ahead of it, then mergedmainonce fix(core)!: the import dry run previews create rows in the commit's batches (#26684) #26778 landed and carries its hunks, withassertReferencesResolveas one more late-boundValidateHostmember (the AST compare above is againstef7067fdaf, after both). feat(formula): label(record.<field>) renders a select value in the reader's locale #26755 and feat!: ownership queues and assignment rules (ADR-0142 phase 2) #26337 editedengine.tsoutsidevalidateand have both landed; they merged without conflict. Re-read at this head: the only other open PR touchingpackages/objectql/**is fix(spec): a translation item is named in snake_case, the locale tag goes inlocale#26769 (a test file only), andgit merge-treeof this head withorigin/main0ea90c7a18exits 0. Whichever lands second mergesmain.{@link READABLE_IDS_MAX_CHAIN_DEPTH}to be re-pointed comment-only. Re-wording them is not.d.ts-neutral: the docblocks of private members are printed in the published chunk, so the first build of this cut (with the two docblocks re-worded to name the module) left one residual statement,declare class ObjectQL, after the normaliser, which is outside6441032442's bar. The type-only import keeps both docblocks byte for byte and makes the link resolve; it costs oneexporton the constant in its own module. Recorded here so a later cut does not re-word a private member's docblock expecting no.d.tschange.resolveFormulaRelatedstays (about -27): it belongs to another section, so taking it here would make this two areas. Its blocker (FormulaRelatedreorders the chunk) is gone under the same ruling, so it can lead a later cut. Package, app, plugin and driver registration (about -233) follows once feat!: ownership queues and assignment rules (ADR-0142 phase 2) #26337 lands._registry,_writeWallVerdict,loggerand_writeGateProbeas getters, so the body reads whatever the instance holds when it reads it: the probe replaces_writeWallVerdict,_writeGateProbe,loggerandfindOneon the instance after construction and sees the moved body use the replacements. No body assigns a field, so there is no setter.ValidateHostis the series' shared paragraph, word for word as onReadableIdsPermissionFormulaHost. The orphanedinsertdocblock and comment block that sit abovevalidate's own docblock inengine.tsstay where they are, byte for byte (moving them would be an edit, not a move).Human Minimum
packages/specholds no runtime logic. (Not touched.)ValidateHost,engine-validate.ts).pnpm lintpasses on the touched package.main, one pull request.skip-changeset(ruling6441032442item 4); both declaration lines are filled in above.packages/specnot touched.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/; thesystem-context.mdxregister is regenerated by its script.skip-changeset: move-only inside@objectstack/objectql, with the published declarations EQUAL under ruling6441032442item 1 and no behaviour change, so there is nothing for a release note to say.🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5oafXXU7gvgcHxdZb9