Skip to content

refactor(objectql): move the validation-message i18n helpers out of engine.ts into engine-validation-messages.ts (#25522 cut 1) - #25615

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-25522-objectql-engine-cut-1
Oct 24, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-25522-objectql-engine-cut-1

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #25522
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160

Cut 1 of the packages/objectql/src/engine.ts split (#24586 ruling A, recorded in 6270097840). The claim is 6382124735. Three ObjectQL method bodies move unedited into a new module, packages/objectql/src/engine-validation-messages.ts: the validation-message localisation helpers validationMessageContext, negotiatedMessageLocale and objectDisplayLabel (all private). setI18nService, the public setter of the field they read, stays in the class: it is a two-line field write, and moving it would grow the class rather than shrink it.

It is move-only, and the card stays open for the later cuts. Branch claude/issue-25522-objectql-engine-cut-1, cut from origin/main at e649c2d91e; main has not moved since.

Serial with the file's in-flight PRs. At start, none of the 12 open PRs touched packages/objectql/** (each PR's file list read). Re-measured just before this PR was opened, on all 14 open PRs: none touches packages/objectql/**.

Why this area for cut 1

The fresh seam table below has six areas with zero or one line from the last 30 days. This one is the only one that meets every series limit and has no path reader outside packages/objectql:

  • Roll-up summaries (0 lines in 30 days) was the first candidate. Two things rule it out for a first cut. recomputeSummaries has an engine write (this.update() and hands this to aggregateSummaryValue, so it would have to stay. And every summaryOperations mention in engine.ts sits in buildSummaryIndex, which the liveness ledger packages/spec/liveness/field.json cites as evidence by path, so moving it pulls a packages/spec edit into the slice.
  • Lifecycle init and health and Datasource routing carry the inferred-return members init and setDatasourceMapping, which must stay.
  • Datasource registry has three this.FIELD.delete/insert/update( sites (the UNTYPED_RECEIVERS limit).
  • Validation-message i18n (122 lines, 0 from the last 30 days): no public member moves, no inferred return type, no write call of any kind, no static, and its only readers are prose mentions.

The shape (#23050 shape B, as #25222, #25223, #25224 and #25467 apply it)

  • The class keeps each method with its name, signature, docblock and position, because tsup emits members with their JSDoc into the .d.ts. Each body is now one host literal plus fn.call(host, …), marked [#25522 cut 1]. objectDisplayLabel reads no member and is called directly.
  • ValidationMessageHost is new. It types every member as the class member itself (ObjectQL['i18nService'], ObjectQL['negotiatedMessageLocale']). Each moved function types its this as the Pick of the host over exactly the members its body reads, and the stub annotates its literal as the ThisParameterType of the moved function. No cast, and no member becomes public or protected.
  • negotiatedMessageLocale goes in as a late-bound closure ((...a) => this.negotiatedMessageLocale(...a)), so a spy or double set on the instance is still the one validationMessageContext reaches.
  • The one field read, i18nService, goes as a getter. That includes the read inside the translate closure, which runs after validationMessageContext has returned and still sees whatever service is installed at call time, as before.
  • Imports. The module imports ObjectQL as a TYPE only, so there is no module cycle at run time. It imports objectLabelKey and resolveBundleLocale from @objectstack/spec/system, the specifier engine.ts used. Those two names had no other reader in engine.ts, so they leave its import list: that is the only edit outside the class besides the new module import. Nothing re-exports the module.

The published .d.ts does not change

Under the series bar (ruling 6348891160). Base was a turbo run build --filter='@objectstack/objectql...' at e649c2d91e (14/14 tasks). Head was pnpm --filter @objectstack/objectql build at 328b5b194e against the same dependency tree.

@objectstack/objectql emits six declaration files: index, core and a shared chunk util-ByiLm3B6 (where declare class ObjectQL lives), each as .d.ts (CJS) and .d.mts (ESM). The chunk name is the same at base and head. All six are byte-identical, and the raw diff of each is 0 lines:

file raw sha256, base = head normalised sha256, base = head
index.d.ts 9ca22071717e3f761198115fa54a143df4151a52950d826a10677420dcad16ae 9ca22071717e3f761198115fa54a143df4151a52950d826a10677420dcad16ae
index.d.mts 69dd1cfe3875024f434b2d7defce771ebc8c7e48a05be7c946fa6ecdbd912b40 69dd1cfe3875024f434b2d7defce771ebc8c7e48a05be7c946fa6ecdbd912b40
core.d.ts d27b72bde2eec9a47c7dd3c104976321533cf397452ca9f84491a455ec28e73b d27b72bde2eec9a47c7dd3c104976321533cf397452ca9f84491a455ec28e73b
core.d.mts 5a0cca505296b678b31c742c285e028fe434f5467bb8d27e052e470ce0e09652 5a0cca505296b678b31c742c285e028fe434f5467bb8d27e052e470ce0e09652
util-ByiLm3B6.d.ts and .d.mts 1742a9cb029654d1ca4e8e392e98001eec85963987f516b1b76f672ecd08e5a9 1742a9cb029654d1ca4e8e392e98001eec85963987f516b1b76f672ecd08e5a9

The normaliser, verbatim from the ruling, run on each file:

node -e 'const s=require("fs").readFileSync(process.argv[1],"utf8");process.stdout.write(s.replace(/"[^"\n]*"(?:\s*\|\s*"[^"\n]*")+/g,r=>r.split(/\s*\|\s*/).sort().join(" | ")))' dist/util-ByiLm3B6.d.ts | sha256sum
  • Normalised = raw on every file, and this is expected. This package's declarations print string literals in single quotes: the chunk holds 23 single-quoted literal unions and 0 double-quoted ones. So the ruling's normaliser, which matches only double quotes, changes nothing here. This cut does not depend on it, because the raw bytes are identical. A later cut of this file would, though; see "For the next dispatch" below.
  • Positive control on a copy of the head util-ByiLm3B6.d.ts: line 7261 private objectDisplayLabel; made public (objectDisplayLabel;, one line differs) gives raw = normalised 270f913f734273e380af6ab964e8b15206aa7c511892dea58cc8f6fd9adf5ef7, which differs from 1742a9cb….
  • Export lists, loaded at runtime from the built bundles (import() of dist/*.mjs, require of dist/*.js), are identical at base and head: . exports 182 names under ESM and 182 under CJS, and ./core exports 54 and 54. The sorted lists hash 881616cc179189098182bd6b8a95701d9922f9677b786bc12e2d31c1adb0adaa (.) and 393e806906e876c2e020aa96617d54050a35ae63cd483b67d8e968b7b5390f49 (./core) at both ends.

No changeset: skip-changeset, per ruling 6348891160 item 4.

Proof of move-only

  • Bodies, by AST token (recursive getChildren leaves): each moved function's parameters (less the added this), return type and body have the same token sequence as the base method, and each body line is the base line with two leading spaces removed. 371 tokens compared, 0 differ. Negative control: one changed token in negotiatedMessageLocale makes the check report a difference.
  • Class side: the class has 317 members at base and head. The 314 members that did not move are byte-identical to base. Each of the 3 stubs keeps its docblock and signature byte-identical.
  • Top level of engine.ts: 232 of the 233 statements outside the class are byte-identical. The other is the @objectstack/spec/system import, less objectLabelKey and resolveBundleLocale. The one new statement is the import of the new module.
  • Size: +135 / -39 over 2 files, under the 3,000-line manual-merge line. engine.ts goes from 23,903 to 23,881 lines. Each stub keeps its docblock and carries its host literal, so the file shrinks by less than the bodies' length. engine-validation-messages.ts has 118 lines.
  • The tests reach the moved body: a one-off mutation of the moved negotiatedMessageLocale (its resolveBundleLocale(...) return replaced by return requested;, written with scripts/ablation-replace.mjs) turns engine-validation-locale-negotiation.test.ts red, 3 failed / 3 passed. It was restored to the HEAD blob 5d9194fa75bb with git diff HEAD empty, and no test file was kept.

Readers of the moved lines

  • ADR anchors. scripts/adr-anchors/packages__objectql__src__engine.ts.json carries one paragraph, on the transaction seam (ADR-0057, ADR-0067, ADR-0119), and none of it describes a moved body. The moved bodies cite no ADR (the ADR-0053 Phase 2 reference is in validationMessageContext's docblock, which stays on the stub). So the new module owes no anchor entry, and none is added. check:adr-anchors: 84 → 84 anchored files; decision-letter citations on the anchored surface 1,883 → 1,883; 52,465 citations across 6,583 files at both ends.
  • Path readers of these symbols (git grep repo-wide): none pins engine.ts#validationMessageContext, #negotiatedMessageLocale or #objectDisplayLabel. The mentions are prose: plugin-approvals/src/reader-locale-labels.ts and service-automation/src/engine.ts (by method name, which still resolves), and spec/src/system/translation.zod.ts (engine.ts's setI18nService, which did not move). check-adr-symbol-anchors: 2,384 anchors resolve at head.
  • core-boundary.ratchet.test.ts: the new module joins the /core closure and imports only @objectstack/spec/system. It passes.

Seam table (fresh, origin/main e649c2d91e, 2026-10-24)

engine.ts is 23,903 lines. 8,253 of them (34.5%) come from the last 30 days (git blame --since=2026-09-24T08:00Z, with history deepened to 2026-09-15). 124 commits touched it in 30 days, and 33 in 7. The file has the module preamble (lines 1–5014, 2,225 lines from the last 30 days), class ObjectQL (5015–23228, 317 members, 255 methods: 147 private, 108 public), and a trailer (23229–23903, 107). Sections are contiguous member ranges, docblocks included. The columns: "inferred public" lists public methods with an inferred return type (these stay), "U" counts this.FIELD.delete/insert/update( sites, and "private statics" lists static members that are not public (these stay).

range section first … last member lines 30-day lines methods inferred public U private statics
5016-5240 Instance state and constructor txStore … Constructor 225 50 1 (1 public) - 0 -
5241-5263 Status and registry accessor getStatus … registry 23 0 2 (2 public) getStatus 0 -
5264-5607 Hook and function registry registerHook … triggerHooks 344 6 16 (16 public) registerHook, triggerHooks 1 -
5608-6084 Hook dispatch internals hasHooksFor … assertBulkPerRowHookBudget 477 53 7 (0 public) - 0 -
6085-6245 Action registry and activation registerAction … setActionActive 161 19 10 (10 public) - 1 -
6246-6527 Registered resolvers and write-gate probes _heldFileResolver … registerInsertRecomputeListener 282 256 6 (6 public) - 0 -
6528-7280 Readable-ids security and permission/formula resolution readableIdsSecurityReported … resolveDefaultPermissions 753 753 15 (2 public) - 0 -
7281-7388 Authz invalidation and middleware registration writeEpoch … hasObjectMiddleware 108 19 4 (4 public) - 0 -
7389-7624 Execution plumbing (middleware, session, provenance, users) executeWithMiddleware … buildUser 236 38 7 (0 public) - 0 -
7625-7955 Driver options and engine posture buildDriverOptions … resolveEnginePosture 331 209 6 (0 public) - 0 -
7956-8165 Organization probe and system-insert organization probeInstallOrganizations … transactionCoversDriverFor 210 45 4 (0 public) - 0 -
8166-8531 Field defaults resolveNowDefault … defaultFieldEntries 366 36 6 (0 public) - 0 -
8532-9142 Autonumber applyAutonumbers … seedAutonumber 611 79 6 (0 public) - 1 -
9143-9807 Package, app, plugin and driver registration registrationConversionWarned … registerDriver 665 170 6 (3 public) registerApp, registerDriver 0 -
9808-10016 Datasource registry supplyFileColumnsMovedResolver … listUnavailableDatasources 209 1 8 (7 public) - 3 -
10017-10263 Write guard and realtime publish assertWriteAllowed … publishBulkDataEvent 247 18 4 (1 public) - 0 -
10264-10385 Validation-message i18n setI18nService … objectDisplayLabel 122 0 4 (1 public) - 0 -
10386-11478 Referential integrity and master-detail resolution assertReferencesResolve … masterDeclaredFields 1093 625 12 (0 public) - 0 -
11479-11594 Dangling-reference and cascade inspection inspectDanglingReferences … inspectCascadeDelete 116 47 2 (2 public) - 0 -
11595-11689 Crypto and tenancy providers setCryptoProvider … setTenancyPostureProvider 95 21 4 (4 public) - 1 -
11690-12255 Secret and internal-field handling encryptSecretFields … resolveInternalField 566 32 9 (3 public) - 0 -
12256-12324 Schema lookup and filter judging getSchema … judgeFilter 69 47 3 (2 public) - 0 -
12325-12667 Datasource routing LIFECYCLE_DATASOURCE … setDatasourceMapping 343 1 8 (3 public) setDatasourceMapping 0 -
12668-12890 Lifecycle init and health init … resolvePrimaryDatasource 223 0 3 (3 public) init 0 -
12891-12964 Media and value-shape presence objectHasMediaField … valueShapeStrictFor 74 13 4 (0 public) - 0 mediaFieldPresence, coveredValueFieldPresence
12965-13647 Migration flags and attestations isFileReferencesMigrationVerified … wasDatastoreCreatedFromEmpty 683 81 17 (8 public) - 0 -
13648-13670 destroy destroy … destroy 23 0 1 (1 public) destroy 0 -
13671-13690 Expand/cascade limits (statics) MAX_EXPAND_DEPTH … MAX_BULK_PER_ROW_HOOK_ROWS 20 0 0 (0 public) - 0 MAX_EXPAND_DEPTH, MAX_CASCADE_DEPTH
13691-14140 Roll-up summaries autonumberCounters … recomputeSummaries 450 0 7 (1 public) - 0 -
14141-14394 Related-record expansion expandRelatedRecords … expandRelatedRecords 254 10 1 (0 public) - 0 -
14395-14838 File-reference hydration resolveFileReferences … readParentDerivedFiles 444 310 5 (0 public) - 0 -
14839-15260 Query lowering resolveWhereTokens … requireFindOnePredicate 422 212 8 (0 public) - 0 -
15261-15817 find / findOne find … staticReadonlyCreateStrip 557 151 4 (2 public) - 0 -
15818-16475 validate validate … validate 658 493 1 (1 public) - 0 -
16476-17820 insert / insertMany readUpdatePriorRow … insertMany 1345 480 3 (2 public) - 1 -
17821-19752 update update … update 1932 391 1 (1 public) - 0 -
19753-21293 Delete cascade and reference walking planCascadeAtomicity … organizationOwnedRowCounts 1541 746 22 (1 public) - 0 storedReferenceIncludes, remainderAfterMemberRemoval, referenceCheckContext, outlivesOrganization, keepsOrganizationReference, organizationCountContext
21294-21863 delete delete … delete 570 48 1 (1 public) - 0 -
21864-22476 count / aggregate count … aggregate 613 362 3 (2 public) - 0 -
22477-22864 execute and transactions execute … enforceTransactionOrigin 388 63 8 (2 public) - 0 -
22865-23228 Compatibility API registerObject … create 364 36 16 (16 public) - 0 -

Cut 1 is the Validation-message i18n row, less setI18nService.

For the next dispatch (cut 2)

  • Proposed area: Datasource routing, less setDatasourceMapping (inferred return, stays) and the two public statics. That is isSystemLedgerObject, getDriver, resolveDatasourceBinding, resolveEffectiveDatasource, resolveMappedDatasource, resolveDatasourceFromMapping and matchPattern. Its 343 lines have 1 line from the last 30 days, no this.FIELD.delete/insert/update( site and no private static. The anchor entry's paragraph names "the same tuple ADR-0057 §3.6 routing reads", so the new module would get its own anchor entry carrying it. Measure getDriver's spies and doubles before choosing it.
  • The alternative, Roll-up summaries (0 lines from the last 30 days), needs the packages/spec/liveness/field.json evidence pointer moved in the same slice, and recomputeSummaries stays.
  • A limit for every later cut. This package's .d.ts prints literals in single quotes, so the ruling's verbatim normaliser cannot absorb a union-member-order swap here. A cut that moves a body checked before the rest of engine.ts and reorders a union would show a raw diff that the normaliser leaves in place. Under the ruling's item 1 that is a stop: the normaliser must not be widened. The decision is raised in the os-dev report on the card.

Verification

  • pnpm --filter @objectstack/objectql typecheck (tsc --noEmit and check:test-typecheck): exit 0. eslint --no-inline-config packages/objectql: exit 0.
  • packages/objectql suite at head 328b5b194e (vitest run --project local): 466 files, 8,700 tests, 8,700 passed, 0 failed, 0 skipped. The suites that pin these helpers (engine-validation-locale.test.ts, engine-validation-locale-negotiation.test.ts, engine-delete-restricted-locale.test.ts) are among them.
  • Downstream type-checks are untouched by construction: every member moved is private, so no dependant can reach one, and all six published declaration files are byte-identical. CI's TypeScript Type Check covers the dependants.
  • dispatch-gates --commands derived 56 families on the real diff. Each was run at head, and its exit code was recorded and reconciled with --ran (56/56 accounted for). 53 exit 0. Three are NOT MEASURED locally, and CI runs them:
    • check-engine-split-ratio --days 90 exit 2, CANNOT COMPUTE: the shallow clone's history starts 2026-09-15, inside the window.
    • check-plugin-teardown-shape --self-test exit 3: the pinned fixture commit is unreachable from this shallow clone.
    • check:dual-build-cjs-loads exit 3, PREREQUISITE NOT MET: it needs every package's dist/. The export lists above are its question for this package.
  • Hand gates at head, all exit 0: check-adr-anchors, check-adr-symbol-anchors, check-nul-bytes, check-platform-checklist --changed-from origin/main.

Generated by Claude Code

…ngine.ts (#25522 cut 1)

Move-only. The bodies of ObjectQL#validationMessageContext,
#negotiatedMessageLocale and #objectDisplayLabel move unedited into
engine-validation-messages.ts; each method keeps its name, signature,
docblock and position and hands its body the members it reads through
ValidationMessageHost. setI18nService stays in the class.

Claude-Session: https://claude.ai/code/session_01JVTd3PprStGa26aez5omLB
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/objectql, touching 6 documentable anchor(s).

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/kernel/services-checklist.mdx (via i18nService (symbol, a field of interface ValidationMessageHost))
What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 19 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json e649c2d91e270e3da26820bcfe54a28445305a75 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from beb5c8f8e8e5434e0e67f8f9198620243aa839fd — the merge of head 328b5b194ecc2c00273f13f4ab84a6d9957548b4 into base e649c2d91e270e3da26820bcfe54a28445305a75, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin beb5c8f8e8e5434e0e67f8f9198620243aa839fd && git checkout beb5c8f8e8e5434e0e67f8f9198620243aa839fd
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e649c2d91e270e3da26820bcfe54a28445305a75 328b5b194ecc2c00273f13f4ab84a6d9957548b4 && git checkout -B drift-repro e649c2d91e270e3da26820bcfe54a28445305a75 && git merge --no-ff 328b5b194ecc2c00273f13f4ab84a6d9957548b4

node scripts/docs-audit/affected-docs.mjs --json e649c2d91e270e3da26820bcfe54a28445305a75

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs e649c2d91e270e3da26820bcfe54a28445305a75 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT · domain:server seat 2 · sunhaolin · session_01JVTd3PprStGa26aez5omLB · 2026-10-24T09:41Z · head 328b5b194e · claim 6382124735

Checklist conclusions (read on GitHub, not from the report):

  • Shape: draft, base main, author objectstack-fleet[bot], assignee sunhaolin. The first line is Part of #25522, and no closing keyword appears anywhere in the body. Clause-②: no and Metadata-protocol: none are line-initial.
  • Scope: 2 files, both in packages/objectql/src/ (engine.ts +17/-39, engine-validation-messages.ts new +118). No governed path (check-governed-merges --pr 25615: NOT governed; 174 changed lines ≤ 3000). skip-changeset under ruling 6348891160.
  • Move-only, re-measured by the seat: I extracted the three private bodies at base e649c2d91 (engine.ts:10291, :10335, :10366) and in the new module (:59, :75, :99). Whitespace-insensitive comparison: all three identical (111 / 627 / 416 significant chars). The stubs keep docblock and signature. negotiatedMessageLocale and i18nService reach the host late-bound; objectDisplayLabel reads no member and is called directly.
  • .d.ts bar: the report gives all six published declaration files raw base = head, a positive control (objectDisplayLabel made public changes the hash), and identical export lists (. 182/182, ./core 54/54). Not re-built by the seat.
  • Tests: the objectql suite at head is 8,700/8,700, and the three locale pins cover the moved helpers. The one-off mutation of the moved locale fallback reddened engine-validation-locale-negotiation.test.ts 3/6 and was restored (blob equals HEAD). No base run was taken (deviation 4); the move proof is the AST and token comparison. These are local readings; CI decides.
  • CI on head 328b5b194e at this reading: 19 success, 12 skipped, 12 in progress, none red. The seat lands only when every check is green or an expected skip.
  • Writes: mcp_calls 0. Both strokes went through the relay as the fleet.

Deviations accepted: 1–6 as reported. On deviation 3: every moved member is private and the declarations are byte-identical, so no dependant's input changed. CI's Type Check lanes cover the rest.

The open question (single-quoted unions in later cuts): no new ruling is needed. Ruling 6348891160's own text sets the series bar as "identity after sorting string-literal union members, plus the same export list". A single-quoted literal is a string literal, so a later cut whose raw diff is only a member-order swap inside a single-quoted literal union meets the ruled bar. The quoted one-liner is the double-quote spelling of that bar. The cut that needs the single-quote spelling states it in its own proof block, with the same positive control. This is the seat's reading of the ruling's text, recorded here so the maintainer can overrule it with one word; it adds no script and no gate.

Carried to the next slice of #25522 (not filed): the dev proposes Datasource routing as cut 2 (measure getDriver's spies and doubles first; the new module owes its own anchor entry for the ADR-0057 routing sentence). Roll-up summaries is cold but owes a packages/spec/liveness/field.json edit (buildSummaryIndex is the evidence path), so it is spec-lane-coupled; avoid it until then.

Landing: pr_ready + automerge_enable through the relay once every check on this head is green. After it merges, #25522 goes back to pm:queue for cut 2.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants