Repository navigation
refactor(objectql): move count and rejectCredentialAggregation out of engine.ts into engine-count-aggregate.ts (#25522 cut 18) - #26932
Conversation
… engine.ts into engine-count-aggregate.ts (#25522 cut 18) Move-only. The bodies of ObjectQL#count and #rejectCredentialAggregation move unedited into engine-count-aggregate.ts behind CountAggregateHost (getters for _registry and relatedSchemaOf, late-bound closures for the eight methods count calls). The class keeps both methods with name, modifiers, signature, docblock and position. The seven top-level helpers count shares with find, findOne, update, delete and aggregate gain `export` in place and are imported back, never copied. aggregate stays: packages/spec/liveness/query.json names engine.ts#aggregate as a producer. The module is imported right after ./secret-fields.js, so the bundles' region order gains one line and every external import stays in order. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5n1LHPdPmHoXe1BGDa
📓 Docs Drift CheckThis PR changes 1 package(s): 8 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 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 9a6e4810ca6b847099b1e2b6782bbe16dd29eb81 && git checkout 9a6e4810ca6b847099b1e2b6782bbe16dd29eb81
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e1ab32ed0b68a58096dd9d1c5e2e510e6bbb3a79 b0142c4a27f4b95b789f22f24e7b198a8a449980 && git checkout -B drift-repro e1ab32ed0b68a58096dd9d1c5e2e510e6bbb3a79 && git merge --no-ff b0142c4a27f4b95b789f22f24e7b198a8a449980
node scripts/docs-audit/affected-docs.mjs --json e1ab32ed0b68a58096dd9d1c5e2e510e6bbb3a79
|
席位核对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里「count / aggregate」区的两个方法体(count计数门,和aggregate()的凭据字段聚合守卫rejectCredentialAggregation)原样搬进新文件engine-count-aggregate.ts;类上的方法签名、注释、位置不变,方法体换成转交。count与留下的find/findOne/update/delete/aggregate共用的 7 个顶层 helper 原地加export、由新文件导入(不复制)。engine.ts21,835 → 21,762 行。src/engine.ts(23,903 lines, +7,501 in 30 days) along itsObjectQLseams, one move-only slice per PR #25522 按缝拆分engine.ts的第 18 刀。重测的 seam 表里价最高的是删除级联区(−248),但派单把它和相邻两区排除(fix(objectql)!: a restrict reference refuses the delete of the record it protects even when the referencing row also cascades from it (#26718) #26864 刚落地、objectql: a predicate delete (multi: true with a filter) skips the referential walk, so a flow's bulk delete_record bypasses restrict, master_detail cascade and set_null #26871 正在那里开发);其次是本区,定价 −71,高于 −30,且没有任何 open PR 触及。aggregate本身留在原文件,因为packages/spec/liveness/query.json以engine.ts#aggregate登记它为生产者。.d.ts六个文件与基线逐字节相同(含阳性对照);运行期导出名单相同;构建产物只多出新文件一个区段,外部包导入顺序一条不差(新文件紧接./secret-fields.js导入);一次性晚绑定探针在新旧两版构建产物上逐行一致。回滚 = revert 本 PR。packages/objectql/src/engine-count-aggregate.ts(两个函数与CountAggregateHost)、packages/objectql/src/engine.ts里两个转交桩、新导入行与 7 处原地export。pnpm --filter @objectstack/objectql exec vitest run --project local --maxWorkers=2 src/engine-aggregate-filter.test.ts src/engine-middleware-operation-vocabulary.test.ts,应见两个文件全部通过(聚合与计数门各自走到的测试)。Cut 18 of the
packages/objectql/src/engine.tssplit (#24586 ruling A, recorded in6270097840), under the claim6453372157. Two bodies of the "count / aggregate" section move unedited into a new module,packages/objectql/src/engine-count-aggregate.ts, behindCountAggregateHost:count(the counting door: alias fold, option refusal, filter-array lowering, search expansion, the operation context, token resolution, the middleware chain, the readable-ids boundary and thefind()fallback) andrejectCredentialAggregation(aggregate()'s fail-closed guard against grouping or aggregating asecret/password/internal: truefield). No behaviour changes. Every published declaration file is byte-identical to the base. #25522 stays open for the later cuts.Branch
claude/project-thread-axdp1m(the card thread's harness-pinned branch), cut fromorigin/mainat1708115e2f, which contains cut 17's merge (cea0871ff2, #26881) and #26864.What changes
Why this area
Re-measured on
1708115e2fwith cut 11's measure script and cut 14's price step (price3.mjs), both unchanged.engine.tsis 21,835 lines, 6,991 of them from the last 30 days (git blame --since=2026-09-27T21:00Z, clone deepened to 2026-09-21 first);class ObjectQLholds 326 members, 261 methods and accessors. Query-options erasure sites: 8 at base (lines 8408, 9648, 9894, 9958, 10290, 13570, 13869, 18499), none in this area.claude/project-thread-vdrn59, is developing the predicate-delete walk across it)count58 body lines,rejectCredentialAggregation38;aggregatestays, namedengine.ts#aggregateinpackages/spec/liveness/query.json)resolveFormulaRelatedresolveFormulaRelatedis a later cut, as the order says36 of the 96 moved body lines are from the last 30 days. The two other excluded sections ("Dangling-reference and cascade inspection", "Referential integrity and master-detail resolution") price below -30 anyway.
registerMetadataCollectionswas not considered (the order excludes it).Seam table on
1708115e2f(40 sections ofclass ObjectQL; U = untyped receivers)getStatus…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…assignmentreadUpdatePriorRow…insertManyupdate…updateplanCascadeAtomicity…organizationOwnedRowCountsdelete…deletecount…aggregateexecute…enforceTransactionOriginregisterObject…createThe per-member screen and the full price output are in the project files,
pm-orders/server/25522-cut18-seam-table.md.The shape
CountAggregateHostmembers it reads, plus a.call, marked[#25522 cut 18], as cuts 8 and 10 to 17 did. Fields go as getters over areadXclosure (_registry,relatedSchemaOf); methods go as late-bound closures (resolveObjectName,expandSearchOnOptions,getDriver,resolveWhereTokens,executeWithMiddleware,buildDriverOptions,composeReadableIdsAtBoundary,find), so a spy or double set on the engine is still the one a call reaches. No body assigns a field, so there is no setter (the interface docblock says only "getters" this time, not the cut-17 wording the seat flagged).countis public with a declared return type (Promise<number>);rejectCredentialAggregationis private, so its.d.tsline isprivate rejectCredentialAggregation;either way. No moved body has athis.FIELD.delete/insert/update(site, a private-static read, a self-call toinsert/update/delete, anengine.ts#NAMEpointer or an ADR anchor paragraph of its own.countcallscomposeReadableIdsAtBoundaryandexecuteWithMiddleware, which ADR-0139 names by path; they stay in the class and are reached through the host.countreads seven top-level helpers, all also read by bodies that stay:foldEngineOptionAliases,rejectUnknownEngineOptions,lowerWhereFilterArray,declaredDatetimeLowering(find,findOne,update,delete,aggregate, andjudgeWhereAdmissionfor the last two),ENGINE_WHERE_SLOTS(update,delete,aggregate),ENGINE_COUNT_OPTION_KEYS(ENGINE_OPTION_KEY_SETS) andmergeReadContext(expandSearchOnOptions,find,findOne,aggregate). Each gainsexportin place, byte for byte otherwise (leading docblocks included), and the module imports them as values from./engine.js; nothing is copied.foldEngineOptionAliasesis also named bypackages/spec/liveness/query.jsonasengine.ts#foldEngineOptionAliases, which still holds: it stays inengine.ts. Measured alone before the move (dts-export-variant-cut18.sh, baseengine.tsplus theexport, no move): each of the seven, and all seven together, leave all published declaration files byte-identical.index.tsandcore.tsname their exports singly, so nothing new is published.engine.tsand the module import each other. The module runs nothing at evaluation (declarations only).rejectCredentialAggregationwasengine.ts's only reader ofStandardErrorCode, so that import line (@objectstack/spec/api, with its[#22646]comment) moves to the module verbatim. Two positions were built and compared (cut18-place-builds.sh,bundlecmp.py): importing the module where theStandardErrorCodeline was (line 31) splits an extraengine.tsregion and prints thesecret-fields.tsregion ahead ofengine-secret-internal-fields.tsand the regions between, so the module evaluation order changes; importing it right after./secret-fields.js(the one other module it imports), as this PR does, leaves the order intact. Measured on the final head's bundles: with the// src/engine.tsmarkers set aside (10 at base and head), the// src/...region order equals the base's with one line added,// src/engine-count-aggregate.ts(index.mjs99 to 100 regions,core.mjs88 to 89,index.js100 to 101,core.js89 to 90). The external modules load in the same first-occurrence order, with the same statement counts: 113 and 96importstatements in the ESM bundles, 148 and 130require(calls in the CJS bundles. The late-binding probe answers the same on base and head (Tests).EngineAggregateOptions,EngineCountOptions,QueryAST(types,@objectstack/spec/data),StandardErrorCode(@objectstack/spec/api),collectInternalReadFieldsandcollectCredentialFields(./secret-fields.js), the seven helpers (values) andEngineReadOptions,ObjectQL,OperationContext(types) from./engine.js.engine.tsloses theStandardErrorCodeline; its./secret-fields.jsimport stays (collectInternalReadFieldsis still read there, andcollectCredentialFieldsby the staying docblock's{@link}).aggregatestays, and how the helpers and the import position were handled.Net lines (the seat's rule)
engine.tsgoes from 21,835 to 21,762 lines, net -73 (33 added, 106 removed). The module is 202 lines. The diff againstorigin/mainis 341 changed lines over 2 files (+235 / -106).Readers of the moved lines
engine.tspath. Searched:engine.ts#count,engine.ts#rejectCredentialAggregationandengine.ts … countspellings, plus everyscripts/**file that readsengine.ts(durability baselines, engine-double contract, logger-receiver detach, single-authz resolver, startup-registry verdict, widget-option census, type-check coverage, erasure baseline, tenant-audit and isSystem censuses): none names them. The prose mentions found (CHANGELOG.mdentries, ametadata-protocol/src/protocol.tsdocblock,service-analytics/src/api-exposure-door.ts) namerejectCredentialAggregationby behaviour, not by path.packages/spec/liveness/query.jsonnamesengine.ts#aggregate,engine.ts#foldEngineOptionAliasesandengine.ts#ENGINE_QUERY_SLOTS: all three stay inengine.ts, so nothing underpackages/specchanges.engine-middleware-operation-vocabulary.test.tsreads theOperationContext['operation']union out ofengine.ts, where it stays; the test passes. The bodies call nocanReadObject((core'srow-serving-door-exposure.pin.test.tsis unchanged), noreferenceTargetOf(, noisFederatedObject/resolveTenantFieldName, and read noisSystem(system-context.mdxis unchanged; its census is green). They hold noquery-options/no-any-erasuresite and no tenant-audit untyped receiver.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: identical once line numbers are masked (164 lines: 48 durability seams and 88 read seams);count's driver read sits outside any catch, so it is no seam.engine.tsentry is the transaction-seam paragraph), so the module needs no anchor entry of its own.check-adr-anchorsat base1708115e2f(clean detached worktree): 1,897 decision-letter citations on the anchored surface, 60,009 resolving citations across 8,416 files. At head: 1,896, 60,009 across 8,417. The one letter that leaves the anchored surface is[ADR-0139 D2]incount's body (the executor-boundary comment), which moved verbatim into the unanchored module; cut 15 disclosed the same kind of drop ([ADR-0139 D6], 1,881 to 1,880). No anchor paragraph was written for it: none of theengine.tsentry's text describescount, anddocs/adr/**is outside this claim.Why
#25522 splits
engine.tsone seam at a time so that a change to one area reads, reviews and conflicts as that area alone. After cut 17, the highest-paying section no open PR touches is "count / aggregate". Nothing about what the engine does changes.Tests
No test is added and none is edited: the move is proved by identity, not by new behaviour, and no test reads a moved line by path.
Public
.d.ts: byte-identical (ruling6348891160item 1), with the6441032442report block and a positive controlBuilt
@objectstack/objectqlat the base (1708115e2f:engine.tsblob1878bcbf6512, noengine-count-aggregate.ts) and at head (engine.tsblobc16b33857e02), each from a cleansrc/(dts-cut18.sh: the base leg restores all ofsrc/from the base and deletes the module; both legs check the blob). The builds are the moved code, not a stale cache:count.call(hostoccurs 0 times in the basedist/index.mjsand once in the head's.Every declaration file is raw byte-identical base to head, so
6348891160item 1 holds without any normalisation, and no chunk is renamed (util-BaJGwxSmat both). The6441032442block, for the record (normaliserpm-orders/server/evidence/25522/dtsnorm.mjs, sha25625226e0677bdad24726e9eff76a7e247bf7319440d2430d28cbaab0db6add94b, run asnode dtsnorm.mjs --diff BASE_FILE HEAD_FILE; output incut18-dtsnorm.txt):core.d.ts9f22dc90973142623116d4f119dcfbbe37289c83a4b28734425014727212376d40e2fde86719d3ccd1cf492314c426c977ab836a5ab54580800cd1f41352247a4450aaf478092516…(1 decl) EQUALcore.d.mtse9a0b5acd001130a4a231c60aa44fbd3b59bcecd0c7d7b032e57e9d4d45d2e51171eab8743fd8dfabc014a162c40c3e034be29f262b26a2bcc24cb3e06be04594450aaf478092516…EQUALindex.d.ts6a16c278b5ac5e3ccafa7eff4f71e5f848bd77431442b455f87bb7fbfe4556212bb6a21a929b41c8dbb85c72c600f87ed3a3af12ca731d1cace61f5d4aa3d57e9136189ce4d0aba3…(103 decls) EQUALindex.d.mts284396b272347adb8ee7226e5798f152bf76aa4878c821e3628541de7060b0c8c7d7bab765f3b0fb35241fa03bd0b716a93139c98e5638d209379dad96528f989136189ce4d0aba3…EQUALutil-BaJGwxSm.d.tscb1fddd4136122b5a0cb983b05eca8e06233614eda7e33156ccc3437c199c90cc43cb8b103cc68a1077b69fcbf78fb71ee5de0ace6651f351cb8e90c7a89cc6fb264bade9e7d8157…(173 decls) EQUALutil-BaJGwxSm.d.mtscb1fddd4136122b5a0cb983b05eca8e06233614eda7e33156ccc3437c199c90cc43cb8b103cc68a1077b69fcbf78fb71ee5de0ace6651f351cb8e90c7a89cc6fb264bade9e7d8157…EQUALstatements only in base: 0; only in head: 0, declared-surface digest EQUAL. (b) Every normalised sha256 EQUAL. (c) Specifier sets EQUAL; the run-time export lists are too (index182 names andcore54, ESM and CJS, the same sorted list at base and head). (d) Raw diff: 0 lines in every file. (e) After the head build, the fullturbo run build(116 of 116 tasks, the dependents' DTS builds included) andpnpm --filter @objectstack/core typecheckran on the headdist/: exit 0 each.packages/objectql/package.jsonexportsnames./dist/index.*and./dist/core.*only; (P3)git grep -n -E 'objectql/dist|driver-sql/dist' -- scripts package.json: 0 hits.dts-export-variant-cut18.sh, baseengine.tswith onlyexportadded):none, each of the seven alone, and all seven together print the sameutil-BaJGwxSm.d.ts,index.d.ts6a16c278b5ac…andcore.d.ts9f22dc909731….Positive control. On this head, one
seddroppedprivatefromprivate rejectCredentialAggregation((a moved member's stub; anchor count 1 to 0, replacement count 0 to 1;engine.tsblobc16b33857e02tob97293c87022) and rebuilt (posctl18.sh, build exit 0). The chunk is renamedutil-CKT4sa10and now publishesrejectCredentialAggregation(object: string, query: EngineAggregateOptions): void;(line 11266, where the head printsprivate rejectCredentialAggregation;); its normalised sha256 is32d9098f1fd316a6b8ffb7e5a40a0da99017775007bf862aed09cf9ed0c83ae5≠c43cb8b1…, its declared-surface digest4c6ca61214efff63…≠b264bade9e7d8157…(thedeclare class ObjectQLstatement named as the one changed), and the rawcore.d.ts(6548856dfe13…) andindex.d.ts(7bff7db9b23e…) change with the chunk name.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 toc16b33857e02(git diff HEADempty), and the full build that followed produced an@objectstack/objectqldist/whose six declaration files and two ESM bundles compare equal to the head build.AST compare (move-only)
astcmp.mjs(TypeScript compiler API, comments and whitespace ignored, tokens compared) on baseengine.tsagainst headengine.tsplus the module:1708115e2f(parameters, return type,async, body tokens, and every body line equal after one level of indent):count296 tokens / 58 lines,rejectCredentialAggregation296 / 38.class ObjectQL: 326 of 326 members kept, in the same order; 324 byte-identical, and the 2 stubs keep docblock, modifiers and signature identical.exportcmp.mjs): the@objectstack/spec/apiStandardErrorCodeimport, moved verbatim to the module; the seven helpers, exported in place with statement and leading docblock otherwise identical; and the class. The head adds one statement: the module import.Late-binding probe (base and head
dist)zz-probe-cut18.mjs(a one-off, not committed; in the project files) loads the builtObjectQLand drives both moved bodies with doubles set on the instance after construction.count: with every host member replaced (_registry,relatedSchemaOf, and the eight methods), recording each call and its arguments in order; thefilteralias folding intowhere; a malformed filter array refused (INVALID_FILTER/ 400) and a well-formed one lowered; asearchexpanded through the host; no query; an unknown option refused; a token resolved byresolveWhereTokensand the caller'swherecaptured before the middleware scopes it, on a driver withoutcount(thefind()fallback, 3 rows);whereandfiltergiven together (refused); and a real engine with a registered driver and a registered object (the driver'scountreached twice, the second through a filter array).rejectCredentialAggregation: group by asecret;minover apasswordwith aninternal: trueobjectgroupBy(both named, envelopeINVALID_FIELD/ 400 /field/fields/object); safe fields; an object with no protected field;_registryreplaced twice after construction;aggregate()reaching the stub; andaggregate()reaching a guard double set on the instance. The 35 output lines are identical on base1708115e2fand head (the 17 construction log lines, which carry timestamps, set aside); stderr is identical (empty) too.Suites
Under
scripts/pm/os-verify-lock.shon headb0142c4a2:turbo run build(the rootbuildfilters): 116 of 116 tasks, exit 0.typecheckof@objectstack/objectqland@objectstack/core: exit 0 each.@objectstack/objectqlvitest--project local: 475 files, 8,849 tests passed, exit 0 (engine-aggregate-filter.test.tsandengine-middleware-operation-vocabulary.test.ts, which drive these bodies, among them).packages/*/vitest.repo-tests.jsonproject: core 6 files / 83 tests, objectql 1 / 5, rest 5 / 280 passed and 18 skipped, runtime 3 / 948, spec 80 / 1,295, types 1 / 11. Exit 0 each.Verification
Head
b0142c4a27f4b95b789f22f24e7b198a8a449980. The gate list isnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon this diff at that head (48 commands, merge base1708115e2), each run with its exit code captured before any pipe, then reconciled with--ran.--ran: 48 run, 0 NOT-MEASURED, 0 UNRUN.check:dual-build-cjs-loadsandcheck:dts-closureran after the full build;check-plugin-teardown-shape --self-testafter fetching621a4876and deepening the clone. The exit codes are inpm-orders/server/evidence/25522/cut18-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-system-context-census.mjs,node scripts/check-durability-degradation-log-level.mjs --list(base and head identical, masked), and eslint aspnpm lintruns it (--no-inline-config) onpackages/objectql.Acceptance notes
6453372157named this branch. The branch isorigin/mainat1708115e2fplus one commit.packages/objectql/**, listed at start (each head fetched,git diff --name-only origin/main...pr/N) and again just before opening this: at start, objectql: a predicate delete (multi: true with a filter) skips the referential walk, so a flow's bulk delete_record bypasses restrict, master_detail cascade and set_null #26871's branchclaude/project-thread-vdrn59(now draft fix(objectql)!: a predicate delete honours deleteBehavior for every matched row: restrict refuses, master_detail cascades, set_null clears (#26871) #26930) editsengine.tsin the delete section (hunks at lines 18240 and 19857, the docblock ofcascadeDeleteRelationsanddelete()'s predicate arm), and feat(spec): a hook declares its refusal catalogue, and its body refuses by code, answered in the caller's language #26831 editsengine-execution-plumbing.ts; the rest touch test files orCHANGELOG.mdonly. Before opening: fix(objectql)!: a predicate delete honours deleteBehavior for every matched row: restrict refuses, master_detail cascades, set_null clears (#26871) #26930 (head27b890d0d, unchanged), fix(metadata-protocol,runtime,app-shell)!: refuse a save or draft publish naming a package that is not installed #26920 (15protocol-*.test.tsfiles), feat(spec): a hook declares its refusal catalogue, and its body refuses by code, answered in the caller's language #26831 and the release PR chore: version packages #26517 (CHANGELOG.md,package.json). None touches this area, the seven helpers or the import lines, andgit merge-treeof this head with fix(objectql)!: a predicate delete honours deleteBehavior for every matched row: restrict refuses, master_detail cascades, set_null clears (#26871) #26930's head and withorigin/main8074feb64exits 0 each.origin/mainmoved after the cut (test files underpackages/objectql/srconly, none of this diff's paths); the derived gate list is unchanged. Whichever lands second mergesmain.aggregatestays.packages/spec/liveness/query.jsoncitesengine.ts#aggregatethree times as a producer; moving it would mean re-keying those rows, apackages/specedit this claim forbids. Its guard is what moves, and the class'saggregatereaches it through the stub, as before._registryandrelatedSchemaOfas getters, so a body reads whatever the instance holds when it reads it: the probe replaces both after construction and sees the moved bodies use the replacements. No body assigns a field, so there is no setter.{@link collectCredentialFields}/{@link collectInternalReadFields}in the stayingrejectCredentialAggregationdocblock keep resolving throughengine.ts's./secret-fields.jsimport, which stays. The movedcountbody keeps its five-space indentation minus one level (three spaces), as moved, not re-formatted.Human Minimum
packages/specholds no runtime logic. (Not touched.)CountAggregateHost,engine-count-aggregate.ts).pnpm lintpasses on the touched package.main, one pull request.skip-changeset; both declaration lines are filled in above.packages/specnot touched.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.skip-changeset: move-only inside@objectstack/objectql, with every published declaration file byte-identical and no behaviour change, so there is nothing for a release note to say.🤖 Generated with Claude Code
https://claude.ai/code/session_01FEkQ5n1LHPdPmHoXe1BGDa