Repository navigation
fix(mcp, email, knowledge, queue, sms, storage, trigger, i18n): runtime strings state each decision in words instead of a tracker number (stage 2) - #21311
Conversation
…me strings state each decision in words instead of a tracker number Stage 2 of the services lane: every ledgered tracker-number occurrence in connector-mcp, plugin-email, service-storage, service-knowledge, service-queue, service-sms, trigger-record-change and service-i18n (22 occurrences in 21 string sites) is gone. Where the sentence already said what was decided, only the citation goes; where it leaned on the number, it now says the decision in words. The change-email notice template description changes in all four locales. The doc-authoring ledger is recomputed with --census-ledger: the 14 file blocks of these packages are deleted and no other row moves. Four test assertions that pinned an id now pin the sentence that replaced it. Text only: no status, error code, field, route or control flow moves. Claude-Session: https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 8 package(s): 3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 17 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 2c096c8029f9572d8185b8ec5bf821bd1042f5c4 && git checkout 2c096c8029f9572d8185b8ec5bf821bd1042f5c4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 393ae878d3d52fe843c56b4621c004b934dcf853 7bcf2f613f595e00d9ede5742fffa52263842abf && git checkout -B drift-repro 393ae878d3d52fe843c56b4621c004b934dcf853 && git merge --no-ff 7bcf2f613f595e00d9ede5742fffa52263842abf
node scripts/docs-audit/affected-docs.mjs --json 393ae878d3d52fe843c56b4621c004b934dcf853
|
…rds instead of a tracker number (stage 3) (objectstack-ai#21346) Part of objectstack-ai#20751 Clause-②: no **Stage 3 of the `domain:services` lane under the maintainer's A / A ruling (5902360492): the `service-datasource` and `plugin-approvals` strings.** The card stays open for the later stages, so this PR carries no closing keyword. Text only: no status, error `code`, field, route, export or control flow moves (AST skeleton reads SAME for 12 of 12 changed sources, below). ## What this does The two packages' refusals, warnings, log lines, datasource route-ledger notes, the generated object-draft comment, and the `sys_approval_action` / `sys_approval_delegation` field help and description (with their `es-ES`, `ja-JP` and `zh-CN` variants) sent the reader to a tracker number for the reason behind them. In form D, as stages 1 and 2 applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words. All 34 ledgered occurrences in the two packages (claim `5945630892`), re-derived from the ledger on `origin/main` at `1371dc98` and again on the merged tree at `222ecc27`: `service-datasource` 9 (9 pairs, 3 files), `plugin-approvals` 25 (23 pairs, 7 files). They sit in 32 string sites. None of them is in the three excluded files (`datasource-secret-binder.test.ts`, `sys-approval-token.object.ts`, `approval-token-internal-hash.integration.test.ts`); none of those files is touched. ### Rewritten in words Author- and administrator-visible text first, log lines last. | Where (head line) | Cited | The text now says | Decision read from | |---|---|---|---| | `plugin-approvals` `sys-approval-action.object.ts:165`, `via_override` help, and its three locale leaves | 3424 | "admitted to this action only by the privileged override, which lets a platform or organization admin act on any pending request so that one nobody in its slate can decide never stays stuck" | the card's fix comment (an admin escape hatch rather than refusing empty approvers at creation) and the `isOverrideActor` contract it landed: a platform or tenant admin may always act on a PENDING request | | `service-datasource` `datasource-credential-migration.ts:269-272`, the migration refusal `reason` | 8078, 8081 | "an alias spelling from before inline credentials were refused at publish, which no connection builder reads, or ... turso's `encryptionKey`, which has no secret slot of its own: the one slot carries the `authToken`" | 8078 (the spec half: `password` / `authToken` declared unwritable, the old alias spellings carry the refusal, `encryptionKey` left writable because neither ruled mechanism can carry it) and 8081 item 4 (the binder injects exactly one secret slot; a second slot is undecided) | | `service-datasource` `external-datasource-service.ts:925`, the generated draft's remote-primary-key comment | 10997 | "For a COMPOSITE key a driver's introspection can report only the first column, so treat the list as a lower bound" | 10997 repaired the SQLite arm (every column whose `pk` ordinal is above zero, ordered by key position, PR 11104), so the old "some drivers report only the first column" named a defect that is gone in-tree; the caveat stays because the generator renders whatever key it was given and the driver population is open (the `external-datasource-service.ts` docblock records both) | | `plugin-approvals` `approval-service.ts:1765`, the `queue` approver warning | 3508 | "because the platform has no ownership queue to expand it from (the type is deprecated and no longer offered for authoring). Route this step to a team, department or position instead." | the card's resolution: deep deprecation rather than an implementation, since there is no queue entity or member table; the routing advice is the same one the `approval-approver-type-unsupported` lint hint gives | | `plugin-approvals` `approval-service.ts:2629`, `:2636`, the live-record warnings | 3447 | "resolving approvers against the trigger snapshot instead of the live record they are normally resolved from" | the card's P1 (approvers are resolved against the live record re-read at node entry; the trigger snapshot is the fallback the code keeps when that read finds nothing or fails) | | `plugin-approvals` `approval-service.ts:3669`, the recall refusal's developer log line | 3424 | "holds no admin override for a ... request (the override reaches pending requests only)" | same as the `via_override` row | | `service-datasource` `datasource-route-ledger.ts:139`, list note | 3827 | "the retained connect verdict per datasource, so a datasource that failed to connect reports `error` here instead of looking untested" | the card's half A (`status` reports the retained connect result instead of a constant `unvalidated`) | | `service-datasource` `datasource-route-ledger.ts:149`, migrate-credential note | 8155 | "drops the inline key only once the secret is stored" | the maintainer-approved shape (b): the reference is durably written before the inline key is removed | | `service-datasource` `datasource-route-ledger.ts:161`, remote-tables note | 7744, 4249, 7955 | "both stay mounted, because renaming a live route to match a ledger would be an API break ... one failure contract (a refusal answers 400 `EXTERNAL_DATASOURCE_ERROR`, the code registered for the service that refused) and one request shape (both forward `?schema=` with the same coercion)" | 7744's dispatch and outcome (the ledger describes what is mounted; no rename), 4249's option 1 as landed (the separately registered `EXTERNAL_DATASOURCE_ERROR`), 7955's route A (forward `?schema=` with the twin's coercion) | ### Citation only (the sentence already stated the decision) - `plugin-approvals`: `sys-approval-action.object.ts:194` `attachments` help, and its three locale leaves (3266, "Files supporting this action — e.g. a signed contract or evidence"); `sys-approval-delegation.object.ts:43` description, and its three locale leaves (1322, "route this user's approver slots to a delegate within a time window"); `approval-service.ts:1782` (3807, "the slot routes to no one and the request cannot advance until someone is added or the approver is re-pointed"); `:2044` (10230), `:2113` and `:2139` (10547), `:2474` (10153), each already saying the team, member or manager is dropped because routing to them "would put approval authority over the record outside its tenant", and the truncated-read line already saying routing is left unchanged rather than risk dropping a member; `:4245` (3823, "that pause continues only through this service ... any other node type there is resumable by anyone with the run id (amended ADR-0044)"). - `service-datasource`: `external-datasource-service.ts:921` (11000, "Preserved as a COMMENT because 'ServiceObject' has no authorable key for a federated object's remote primary key: 'fields.FIELD.primaryKey' is not part of the field schema"). Every cited card (19: 8078, 8081, 3827, 4249, 7744, 7955, 8155, 10997, 11000, 10153, 10230, 10547, 3424, 3447, 3508, 3807, 3823, 3266, 1322) was read through REST, body and every comment, before its string was rewritten. 8078 is a pull request; its body carries the decision. ### Translations - `via_override` help: the `es-ES`, `ja-JP` and `zh-CN` leaves were real translations; each now carries the same decision ("un administrador de la plataforma o de la organización", "プラットフォーム管理者または組織管理者", "平台管理员或组织管理员") and no number. - `attachments` help (all three) and the `zh-CN` `sys_approval_delegation` description were real translations; each dropped its citation only. - The `es-ES` and `ja-JP` `sys_approval_delegation` descriptions were byte copies of the English source. They are now copies of the revised English, and `node scripts/check-i18n-bundles.mjs --write --filter=plugin-approvals` rewrote `en` from the object source and recorded the two new digests in the `es-ES` / `ja-JP` `*.source-hashes.generated.ts` companions. No digest and no `en` leaf was hand-edited; the merge kept every hand-written translated value. - Tracker numbers left in the package's locale bundles: 0. ## Ledger (`scripts/doc-authoring-prose-id.baseline.json`) Stage 2 (PR objectstack-ai#21311) held this file. This branch was built while it sat in the queue, then `origin/main` (`222ecc27`, which contains `6091136e`, the stage-2 merge) was merged in, and only then was the ledger recomputed with `node scripts/check-doc-authoring.mjs --census-ledger` (exit 0, no growth refusal) into a scratch file and copied into place. The diff deletes 52 lines and adds none: exactly the 10 file blocks of the two packages. Every other row is unchanged (a scripted comparison of the 62 other keys: 0 moved). | | before (`222ecc27`) | after | |---|---|---| | `service-datasource` | 9 occurrences, 9 pairs, 3 files | 0 | | `plugin-approvals` | 25 occurrences, 23 pairs, 7 files | 0 | | whole ledger | 261 occurrences, 189 pairs, 72 files | 227 occurrences, 157 pairs, 62 files | `pnpm check:doc-authoring` at the head: "sibling-package prose ids hold the baseline — 204 pinned site(s) across 62 file(s), 85660 string(s) read in 1247 parsed source(s), no growth, no burn-down unrecorded". No gate is added or loosened; `scripts/check-doc-authoring.mjs` is untouched. ## Changeset `.changeset/20751-services-strings-stage3-state-the-decision.md`: `patch` for `@objectstack/service-datasource` and `@objectstack/plugin-approvals`. Measured after building at the head: the new author-visible sentences are in each package's built output (`plugin-approvals` `dist/index.js` and `dist/index.mjs`; `service-datasource` `dist/index.js` and `dist/index.cjs`). A TypeScript scan of every string literal and template text in the built output finds 0 tracker ids in `service-datasource`; in `plugin-approvals` its six matches are all CSS hex colours (`#2563eb`, `#64748b`) in the action-link page template, not tracker ids. Control: the same scan reads 82 in `plugin-security`'s built output and 66 in `service-automation`'s. The datasource route ledger does not ship: `DATASOURCE_ROUTE_LEDGER` and its new note text are in 0 files under `packages/services/service-datasource/dist`, so the changeset does not describe it. ## Text-only proof A TypeScript-AST skeleton of each changed non-test `.ts` file, where every string literal and template text is a placeholder, a run of adjacent string operands of a `+` chain is one string (only its embedded expressions are kept), identifiers and numbers keep their text, and comments are never read. `222ecc27` against the head: 12 of 12 SAME. Controls on scratch copies of `approval-service.ts`, each mutation's marker counted once on disk first: a one-identifier rename reads DIFF; a text-only change reads SAME; a re-split of one template into two concatenated pieces reads SAME. (A first draft of the tool wrapped every `+` chain in its own token and read `approval-service.ts` DIFF by two tokens: the `queue` warning went from one template to a three-piece chain. The corrected tool treats a chain of strings as one string, which is what the re-split control pins.) ## Pins Assertions that found a warning or comment by its tracker number now find it by what it says. No `code` or `status` assertion was touched; none of these strings is a coded refusal. - `approval-service.test.ts:3165`: the `queue` warning by `'queue'` and "no ownership queue to expand it from" instead of the id. - `approval-service.test.ts:3218`: the expanded-to-nobody warning by "cannot advance until someone is added or the approver is re-pointed" instead of the id. - `team-approver-org-screen.test.ts:223` and `team-member-org-screen.test.ts:250`: the warning found by "team 'team_b' was dropped from the approver slate" and "member(s) of team 'team_a' were dropped from the approver slate"; both test titles drop "and the card". - `external-object-draft-primary-key.test.ts:218` and `:229`: "a driver's introspection can report only the first column" and "not part of the field schema" instead of the ids; the first test's title said 10997 "is unfixed and in another lane", which stopped being true when PR 11104 landed, and now says "a driver can under-report a composite key". The `lower bound` and `no authorable key` assertions beside them are unchanged. - `external-object-draft-authorised-shape.test.ts:151` pins the comment line "Preserved as a COMMENT because 'ServiceObject' has no authorable key for a", which this PR leaves byte-identical. Every re-pinned case was run with the verbose reporter and is listed as passed. ## Tests All through `scripts/pm/os-verify-lock.sh`, every verdict `VERDICT command-exit 0`: - Build: `turbo run build` over the closure of the two packages and `@objectstack/cli` (59/59), then, after merging `origin/main`, `turbo run build --filter=./packages/* --filter=./packages/*/*` (71/71). - At the merged head `7740c0f0`: `@objectstack/service-datasource` 35 files, 707 tests passed; `@objectstack/plugin-approvals` 53 files, 824 tests passed. - `typecheck` for both, including `check:test-typecheck: OK` for `plugin-approvals`. ## Gates - `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` (no paths) at `7740c0f0` (18 paths vs merge base `222ecc27`): 72 commands, run one at a time from the worktree, each exit code recorded before any pipe. `--ran`: "72 derived famil(ies) accounted for — 72 run, 0 NOT-MEASURED (a DERIVED zero — all 72 recorded an exit code and none of them is 3)". - `check:i18n`: "all bundles in sync, no undeclared authoring keys"; `check:i18n-stale-fill`: "no new stale fills, 0 baselined"; `check:issue-citations`: "no issue citations added against 222ecc2 (12 file(s) read)"; `check:nul-bytes`: OK, 9637 files; `check:type-check-debt`: "none above its recorded number"; `check:dual-build-cjs-loads`: 105 require entry points across 66 packages load; `check:dts-closure`: 71 built packages, 167/167; `check:sourcemap-no-sources-content`: 68 packages, 522 maps. - Outside the derived set, all exit 0: the eleven declared wide-population families (`check:init-service-contract`, `check:live-db-isolation`, `check:meta-type-normalized`, `check:optional-error-sink`, `check:resume-authority-declared`, `check:route-envelope`, `check:runner-env-posture`, `check:settings-bind-window`, `check:startup-registry-verdict`, `check:verify-stand-in`, `check:wildcard-fallthrough`) and the artifact-roster families whose roster sits under one of this PR's directories (`check-changeset-fixed`, `check-published-list-mirrors` and its self-test, `check:authz-resolver`, `check:console-injection`, `check:error-code-casing`, `check:filter-alias-parity`, `check:published-readme-exports`, `check-dts-references --self-test`; `check:engine-double-contract` and `check:i18n-stale-fill` are already in the derived set). The path-scheduled CI jobs and the type-check lanes are CI's. - `pnpm lint` (`eslint . --no-inline-config`, repo-wide, not narrowed) at `7740c0f0`: exit 0, 146 s under the lock. ## Acceptance notes Noted, not filed: - `docs/qa/platform-checklist/areas/approvals.json:1249` quotes the `queue` warning with its old tracker suffix. The part it quotes before the suffix survives verbatim in the new text, so a runner still finds the warning; the file is outside this stage's surface. Carrier: none. - `external-object-draft-primary-key.test.ts` keeps a docblock (lines 63 to 67) saying 10997 is a separate, unfixed defect in the engine lane. It is a comment above the fixture, outside the ledger; this PR changes only the title and assertion of the test that pins the caveat. Carrier: none. - `packages/lint/src/validate-approval-approvers.ts:463` carries the same `queue` citation in its lint message, and its test pins the id. `packages/lint` is outside this lane's ledger share. --- _Generated by [Claude Code](https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Part of #20751
Clause-②: no
Stage 2 of the
domain:serviceslane under the maintainer's A / A ruling (5902360492): theconnector-mcp,plugin-email,service-storage,service-knowledge,service-queue,service-sms,trigger-record-changeandservice-i18nstrings. The card stays open for the later stages, so this PR carries no closing keyword. Text only: no status, errorcode, field, route, export or control flow moves (AST-skeleton proof below, 14 of 14 files SAME).What this does
These eight packages' refusals, warnings, log lines, route-ledger notes and the built-in change-email notice template description (in all four locales) sent the reader to a tracker number for the reason behind them. In form D, as stage 1 applied it, the number goes. Where the sentence already said what was decided, only the citation goes. Where it leaned on the number, it now says the decision in words.
All 22 ledgered occurrences in the eight packages (claim
5944824425), re-derived from the ledger onorigin/mainat383a00c7, not from the card's table:plugin-email6,service-storage4,service-knowledge3,connector-mcp2,service-queue2,service-sms2,service-i18n2,trigger-record-change1. The card's table reads the same 22. They sit in 21 string sites (one storage note carried two ids).Rewritten in words
Author- and administrator-visible text first, log lines last. Every cited card was read through REST (body and every comment) before its string was rewritten.
connector-mcpmcp-provider.ts:142, allowlist-miss refusal (fatal at boot, skipped and logged on a runtime publish)connector-mcpmcp-provider.ts:149, default-deny refusalplugin-emailtemplates/auth-templates.ts:573,:601,:630,:660, theauth.email_change_noticedescription seeded intosys_email_template(en-US, zh-CN, ja-JP, es-ES)plugin-emailinternal-header-readback.ts:128, thrown when the engine cannot dereferenceheaders_jsonservice-queuedb-queue-adapter.ts:93, thrown whensys_job_queueloses its retention declarationtrigger-record-changerecord-change-trigger.ts:240, array-trigger warning to the flow authorservice-knowledgeknowledge-service.ts:321, no-identity retrieval warningservice-knowledgeknowledge-service-plugin.ts:221, predicate-write warningservice-queuequeue-service-plugin.ts:160, rejected-floor errorservice-smssms-daily-quota.ts:327, unreadable-counter warningservice-storageattachment-lifecycle.ts:529, reclamation-gate lineplugin-emailemail-service.ts:925, over-limit attachments lineservice-storagestorage-route-ledger.ts:113, download-URL row note (guard data, not shipped)0bab8bb45(the service-storage protocol stays canonical), and the later retirement of the dispatcher bridge recorded inpackages/runtime/src/route-ledger.tsCitation only (the sentence already stated the decision)
service-knowledgeknowledge-service-plugin.ts:220(4639, "A bulk event carries a count, not records, ... cannot be repaired from the event stream": the honest aggregate event).service-smssms-plugin.ts:170(2814): the counter store'ssubjectis now "daily SMS send quota". It is prose only, interpolated into the store's bind and fallback log lines, never a key.service-i18ni18n-route-ledger.ts:98,:100(3636, "The client now sends the path form the spec declares"; "it now sends both the object and the locale in the path", checked againsti18n.getTranslations/i18n.getFieldLabelsinpackages/client/src/index.ts).service-storagestorage-route-ledger.ts:113(second half) and:119(3689, "moved into the declared envelope"; "retired when every storage route moved to the declared envelope,okbeing a private second word forsuccess").Translations
The change-email notice description is the only string here with locale variants. Each of the zh-CN, ja-JP and es-ES rows carries the same decision as the en-US row ("使被劫持的会话无法在原邮箱不知情的情况下转移账号身份", "乗っ取られたセッションが元のアドレスに知られないままアカウントの識別情報を移せないようにします", "para que una sesión secuestrada no pueda trasladar la identidad de la cuenta sin aviso") and no number. They are template rows, not i18n bundle keys, so no bundle or digest moves.
check:i18nreads "all bundles in sync". The built-in seeder upserts by name and locale on every boot, so a deployment's existing rows take the new description.Ledger (
scripts/doc-authoring-prose-id.baseline.json)Recomputed with
node scripts/check-doc-authoring.mjs --census-ledger(exit 0, no growth refusal) into a scratch file, then copied into place. The diff deletes 44 lines and adds none: exactly the 14 file blocks of the eight packages. A scripted comparison of every other key: 0 moved, 0 added.383a00c7)plugin-emailservice-storageservice-knowledgeconnector-mcpservice-queueservice-smsservice-i18ntrigger-record-changepnpm check:doc-authoringat the head: "236 pinned site(s) across 72 file(s), 86149 string(s) read in 1248 parsed source(s), no growth, no burn-down unrecorded" (the census before the change read 257 sites). No gate is added or loosened;scripts/check-doc-authoring.mjsis untouched.Changeset
.changeset/20751-services-strings-stage2-state-the-decision.md:patchfor@objectstack/connector-mcp,@objectstack/plugin-email,@objectstack/service-knowledge,@objectstack/service-queue,@objectstack/service-sms,@objectstack/service-storageand@objectstack/trigger-record-change.Measured after building at the head:
plugin-email's four descriptions read back from the built module's exportedAUTH_EMAIL_CHANGE_NOTICE_TEMPLATES, all four id-free)..js/.mjs/.cjsfinds 0 tracker ids. Control: the same scan reads 86 inplugin-security's built output and 66 inservice-automation's.@objectstack/service-i18nis deliberately NOT in the changeset. Its only change is the route ledger, which no entry imports:I18N_ROUTE_LEDGERand the new note are in 0 files of itsdist/(positive control:registerRoutesin 4). The same holds forservice-storage's ledger (STORAGE_ROUTE_LEDGERin 0, controlreap guard: keptin 2), so that package's patch is forattachment-lifecycle.tsalone.Text-only proof
A TypeScript-AST skeleton of each changed non-test
.tsfile: every string literal and template text is a placeholder, a run of adjacent string operands of a+chain is one string (embedded expressions kept in order), identifiers and numbers are kept, and comments are never read. The walk visits every child (no early exit).383a00c7against the head: 14 of 14 SAME, node counts identical per file. Control on scratch copies ofmcp-provider.ts: renaming one identifier reads DIFF; changing only a string's text reads SAME; re-splitting one template into two+operands reads SAME.Pins
Four assertions named a tracker id and now name the sentence that replaced it:
service-knowledge__tests__/event-sync-data-events.test.ts:166,:167:toContain('cannot be repaired from the event stream')andtoContain('the lifecycle reap guard de-indexes those rows before they are deleted')instead of the two ids. The third half-pin (application-level predicate writes are not) is unchanged, so both halves of the honest line stay pinned.trigger-record-changearray-form-refusal-end-to-end.test.ts:116andrecord-change-trigger.test.ts:183:toMatch(/multi-event arrays are deferred until/)instead of the id. The label now reads "states the standing decision".No
codeorstatusassertion was touched; none of these strings is a coded refusal. Every other old fragment was searched repo-wide: no other test, doc or fixture quotes them.Tests
All at head
7bcf2f613, throughscripts/pm/os-verify-lock.sh, eachVERDICT command-exit 0:turbo run buildover the eight packages and their dependency closure (37/37), thenturbo run build --filter=./packages/* --filter=./packages/*/*(71/71) for the dist-reading gates.vitest run --maxWorkers=2per package:plugin-email31 files, 510 tests;service-storage41 files, 629 tests;trigger-record-change10 files, 101 tests;service-queue5 files, 77 tests;service-i18n5 files, 74 tests;service-sms5 files, 74 tests;service-knowledge4 files, 44 tests;connector-mcp3 files, 23 tests. All passed. The three re-pinned files were also run with the verbose reporter, which names the three cases holding the four re-pinned assertions as passed.typecheckfor all eight, exit 0, includingcheck:test-typecheck: OKwhere the package wires it.Gates
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(no paths) at7bcf2f613: 72 commands over 19 paths, run one at a time from the worktree, each exit code recorded before any pipe.--ran: "72 derived famil(ies) accounted for — 72 run, 0 NOT-MEASURED (a DERIVED zero — all 72 recorded an exit code and none of them is 3)".check:dual-build-cjs-loadsandcheck:i18nfirst answeredPREREQUISITE NOT MET(exit 3, only the closure was built). After the full package build they and the other dist-reading gates were re-run, all exit 0: 105 require entry points across 66 packages load; "all bundles in sync";check:dts-closure71 built packages, 167/167 declaration files;check:sourcemap-no-sources-content68 packages, 522 maps;check:lean-entry-closureandcheck:published-filesgreen.check-issue-citations: "no issue citations added against 383a00c (14 file(s) read)";check:nul-bytes: OK, 9609 files, no raw ASCII control bytes;check:i18n-stale-fill: "no new stale fills";check:type-check-debt: "none above its recorded number";check:engine-double-contract: OK.check:init-service-contract,check:live-db-isolation,check:meta-type-normalized,check:optional-error-sink,check:resume-authority-declared,check:route-envelope,check:runner-env-posture,check:settings-bind-window,check:startup-registry-verdict,check:verify-stand-in,check:wildcard-fallthrough) and the artifact-roster families whose roster sits under one of this PR's directories (check-changeset-fixed,check-published-list-mirrorsand its self-test,check:authz-resolver,check:console-injection,check:error-code-casing,check:filter-alias-parity,check:published-readme-exports,check-dts-references --self-test). The path-scheduled CI jobs and the type-check lanes are CI's.pnpm lint(eslint . --no-inline-config, repo-wide, not narrowed) at7bcf2f613: exit 0, 128 s under the lock.AGENTS.md; the tree stayed clean throughout.Acceptance notes
origin/mainmoved 8 commits to393ae878after the branch point. None touches any of this PR's 19 paths or any of the eight packages, and the ledger is not among them, so the recomputed ledger stands on the merged tree. The branch was not merged withmain; the queue rebuilds it there.storage-route-ledger.conformance.test.ts:74,i18n-route-ledger.conformance.test.ts:91); they are test files, outside the ledger and this stage.packages/lint/src/validate-flow-trigger-readiness.ts:557carries the same 3457 deferral in the lint hint, and its test pins the id (validate-flow-trigger-readiness.test.ts:738).packages/lintis not in this stage. The trigger warning now uses the lint hint's own phrase ("multi-event arrays are deferred"), so the two read alike once that stage lands.Generated by Claude Code