Skip to content

fix(i18n): read the provenance companion at serving time in all nine bundle sets - #12724

Merged
os-zhuang merged 7 commits into
mainfrom
claude/issue-12642-provenance-serving-seam
Aug 27, 2026
Merged

os-zhuang merged 7 commits into
mainfrom
claude/issue-12642-provenance-serving-seam

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #12642.

Provenance is now recorded in 9 of 9 bundle sets and served in 9 of 9. It was recorded in 9 and served in 1.

The measurement, re-taken today (not inherited from the card)

Re-run on origin/main at 15bf9e85:

grep -rn "withSourceFallback" --include=*.ts packages/ | grep -v node_modules

Every call site was in @objectstack/platform-objects — src/apps/translations/setup.translation.ts and src/metadata-translations/index.ts. Counted from the tree rather than from the card: 27 committed provenance companions across 9 bundle sets, 3 of them read at serving time. The card's "recorded 9 of 9, served 1 of 9" held, and PR #12491 (merged the same day, same directory family) had not moved it.

plugin-webhooks was not a latent case: it carries 20 records across its three locales, so the instrument was armed there.

The failure, reproduced before anything was changed

The tree is 0-stale by construction — a record is only ever written for a leaf that IS a byte copy of the CURRENT source — so nothing is observable until a source moves. Revising the source string behind objects.sys_share_link.fields.token.label in plugin-sharing (recorded in es-ES alone, which is why no gate can testify):

observation before this PR after this PR
findStaleFills on the es-ES companion 1 stale, named exactly 1 stale, named exactly
what es-ES SERVES "Token" — the superseded draft "Share token" — the current source
zh-CN (no record for that path — legacy-trusted) "令牌" "令牌", untouched

Positive control, proving the probe can observe a substitution at all: the same mutation on @objectstack/platform-objects, where the seam was already wired, moved objects.sys_account._actions.link_social.params.provider.options.apple from "Apple" (raw es-ES module) to "Apple ID" (served bundle). The probe sees substitutions where substitutions happen.

Both mutation legs confirmed on disk by grep counts before and after; both restore legs verified byte-identical to the HEAD blob via git hash-object plus an empty git diff HEAD.

⭐ The route triage preferred does not exist — measured, not assumed

This is the most reusable result in the PR, so it is stated plainly: a future reader will otherwise propose the same route again.

Triage's preferred route was move the seam into the i18n loader, so a set opts in by committing a companion rather than by wiring a call. That seam does not exist. Measured:

  • The loader contract is II18nService.loadTranslations(locale, translations), declared in packages/spec/src/contracts/i18n-service.ts. It receives one locale at a time and has no channel for either the source bundle or the recorded table. Applying provenance there means widening a published contract.
  • There is no shared registration helper either: each of the nine sets registers its own bundle in its own kernel:ready hook.
  • AppPlugin.loadTranslations in @objectstack/runtime does see a whole TranslationBundle, but the nine platform sets never go through it — it serves defineStack({ translations }) app bundles — and it has no companion channel either.

The only place a bundle AND its provenance companion are both in scope is the bundle set's own serving barrel. So the thing that can be centralised is the CODE — already public at @objectstack/platform-objects/apps — and the GUARD, not the call site.

Two relocation routes were measured and rejected. Relocate to @objectstack/core: reaches 8 of 9 free, but platform-objects holds core only as a devDependency, so it trades one new edge for another, and drags the CLI along. Relocate to @objectstack/spec: the only package all nine already depend on, but it widens a published contract for a utility with nine internal consumers and no external pull — clause ②, and the spec seat's call, not this lane's.

The ninth set, and why the dependency edge is the right move

@objectstack/plugin-webhooks was the one set that could not reach the seam: it depends on @objectstack/core, @objectstack/service-messaging and @objectstack/spec — not on @objectstack/platform-objects. That fork was stopped on and reported before being taken, and the measurement that resolved it:

plugin-webhooks    deps: @objectstack/core, @objectstack/service-messaging, @objectstack/spec
service-messaging  deps: @objectstack/core, @objectstack/platform-objects, @objectstack/spec, @objectstack/types

⇒ platform-objects is already in plugin-webhooks' install closure through service-messaging. Declaring it adds no package to the graph — it declares a resolution that already resolves. Relying on that resolution without declaring it is the phantom-dependency shape under this repo's strict package manager, so declaring it is the correct move rather than a shortcut. The barrel is then wired identically to the other seven: one mechanism, no variant.

Why a new gate verdict, and why structural

check:i18n-stale-fill gains a second verdict, UNSERVED PROVENANCE, kept distinct from the stale-fill verdict the way check:i18n keeps its two. It extends the guard that already walks every bundle set and already knows the companions by name, rather than adding a tenth script.

Wiring nine sets without it would fix today's instance while leaving "recorded implies served" an assumption — rebuilding the exact inference hazard the card was filed about, one layer further on. The card's hazard is what a reader concludes from "recorded 9 of 9"; this verdict is what makes that conclusion true and keeps it true for a tenth set that lands tomorrow.

The behavioural alternatives are vacuous today and were measured as such: served-versus-source bytes are equal whether or not the seam is wired (0-stale by construction), and object identity does not separate them either, because withSourceFallback deliberately returns its input by reference when nothing is stale. A gate observable only green is indistinguishable from a gate matching nothing. So the verdict asks the structural question — is this companion's own exported identifier passed as an ARGUMENT to a withSourceFallback(...) call in this package? — and publishes the recognised spelling in its failure text, the trade check:cross-package-test-inputs documents.

Naming the identifier is not enough and neither is calling the seam: the near-miss the rule must separate is a set that wires two locales and forgets the third. Both halves are required per companion, which is per locale.

⚠️ The UNSERVED_PROVENANCE ledger is EMPTY, and that is where a guard usually dies

plugin-webhooks held the only entry while its dependency question was open; wiring it deleted that entry in the same change, because the ledger is shrink-only and fails both ways — a stale entry reds the gate. An empty registry is exactly the state where a guard degenerates into a no-op and nobody notices, so the discrimination is proven rather than assumed, at two levels:

Mechanically, in --self-test — the verdict now compares through the same two-sided ratchet the stale-fill verdict uses, so these cases are its decision procedure rather than a model of it:

  • empty ledger + every set serving ⇒ no finding (passes, correctly)
  • ⭐ empty ledger + a set recording-but-not-serving ⇒ still reported (the emptied ledger did not disarm it)
  • a ledger entry whose set now serves ⇒ reported for deletion

End to end, on the real tree — un-wiring plugin-webhooks, the very set whose entry was just deleted, with the ledger empty:

  • ARM 1 (empty ledger, all served): exit 0 — 27 provenance companion(s), 27 served at serving time, 0 bundle set(s) unserved (0 declared)
  • ARM 2 (empty ledger, one set records-without-serving): exit 1 — UNSERVED PROVENANCE — 1 bundle set(s) record provenance and never read it, naming all three companions and the identifier each exports

Ablation — both new guards were observed RED

Beyond the empty-ledger arms above, the earlier ablation on plugin-sharing (barrel reverted to the origin/main shape, confirmed on disk as 3 → 0 withSourceFallback( occurrences):

  • check:i18n-stale-fill → exit 1, UNSERVED PROVENANCE naming all three companions.
  • packages/plugins/plugin-sharing/src/translations/serving-seam.test.ts → exit 1, AssertionError: expected 'Token' to be 'Share token' — the measured failure itself.

No rebuild was needed between legs and this is load-bearing rather than an omission: the barrel is TypeScript source read relatively by both the test and the gate, and withSourceFallback comes from platform-objects/dist, which the ablation does not touch. Every restore verified byte-identical to the HEAD blob, under a trap on EXIT INT TERM with absolute paths.

Scope

  • No new exported surface. withSourceFallback was already public at @objectstack/platform-objects/apps — the CLI has imported that barrel since the recording rollout.
  • No key set moves. Substitution rather than deletion is the point of ruling i18n: a source-string edit still leaves zh-CN / ja-JP / es-ES silently stale — and pinning en to the source makes the asymmetry sharper, not smaller (needs a maintainer decision) #8765 Option B, and every key-set claim over these bundles is untouched.
  • packages/spec not touched — read-only for this seat. content/docs/releases/** untouched.
  • One manifest line: @objectstack/platform-objects declared in plugin-webhooks, for the reason measured above.
  • Four consequential config changes the gates demanded, none discretionary: paths rules resolving the seam to source in plugin-approvals and plugin-audit (check:type-source-resolution), and matching anchored vitest aliases in plugin-audit and plugin-webhooks (check:test-source-alias). Both registries are shrink-only; neither was widened.

Verification

Gate union derived from the ACTUAL changed paths with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack — not from a hand-written diff — and re-derived after the manifest change, which pulled in three families the first derivation could not see (check:override-consistency, check-osv-exemptions, check-changeset-fixed). Every exit code captured before any pipe. All runs below are on ae7a467d, the final commit of this branch, with a clean tree.

Green: check:nul-bytes · check:i18n · check:i18n-stale-fill (both verdicts, plus its own self-test: 27 assertions, 12 of them new) · check:override-consistency · check-osv-exemptions · check-changeset-fixed · check:agent-test-spelling · check:bash32-floor · check:cli-command-ids · check:entry-guard · check:parse-guard · check:pnpm-filter-targets · check:page-declaration-shape · check:published-files · check:slot-lookup · check:test-source-alias · check:type-source-resolution · check:cross-package-test-inputs (both invocations) · check:type-check-coverage · check:type-check-debt (--re-measure: 31 ledger entries, 1687 raw errors, none above its recorded number — unchanged by this diff; the one surplus it reports is a pre-existing @objectstack/runtime entry) · check:engine-double-contract · check:where-matcher · check:query-options-erasure · check:objectql-double-limit · check-comment-mask-adoption · check-plugin-teardown-shape · check-ci-filter-parity · check:changeset-gate-self-tests · check:objectui-changeset · check:pm-half-states · check-changeset-no-major · check-empty-changeset · check-adr-0087-registration · release-rehearsal-clone --self-test · bare-root-worklist --self-test · check:pm-dispatch-gates.

Tests for the eight wired packages: 239 test files, 4049 tests, all passing. typecheck green for the seven that declare the script.

Not measured, and recorded as not measured rather than green:

  • @objectstack/service-storage declares no typecheck script, so the filtered run matched zero scripts and exited 0 having measured nothing. A zero-match --filter run is the same trap as a gate that refuses.
  • scripts/pm/check-half-states.mjs refuses with PREREQUISITE NOT MET (exit 3) — this container holds no valid GitHub credential, and the script states itself that it swept no issue. It judges the PM board, not this diff.

Generated by Claude Code

claude added 5 commits August 27, 2026 12:47
…ever served

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZbWd2jNV1FErXTPSS4Dry
…hen it moves

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZbWd2jNV1FErXTPSS4Dry
…s that newly import it

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZbWd2jNV1FErXTPSS4Dry
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Aug 27, 2026
@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

9 anchor(s) derived from 8 changed package(s); no hand-written page names any of them. ⚠️ 5 changed file(s) yielded no anchor (packages/plugins/plugin-approvals/tsconfig.json, packages/plugins/plugin-audit/tsconfig.json, packages/plugins/plugin-audit/vitest.config.ts, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 5 changed file(s) yielded no anchor (packages/plugins/plugin-approvals/tsconfig.json, packages/plugins/plugin-audit/tsconfig.json, packages/plugins/plugin-audit/vitest.config.ts, …) — pages documenting those are invisible to this run
  • 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.

Coarse fallback — 29 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 d29e42f8b1b44b92ea58c1d05e619f27c027c3a9 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 3418ef9aa65f14cf37317b97417663be6f0d24a0 — the merge of head ae7a467d1497d193df69619457f9fc688c38260d into base d29e42f8b1b44b92ea58c1d05e619f27c027c3a9, 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 3418ef9aa65f14cf37317b97417663be6f0d24a0 && git checkout 3418ef9aa65f14cf37317b97417663be6f0d24a0
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin d29e42f8b1b44b92ea58c1d05e619f27c027c3a9 ae7a467d1497d193df69619457f9fc688c38260d && git checkout -B drift-repro d29e42f8b1b44b92ea58c1d05e619f27c027c3a9 && git merge --no-ff ae7a467d1497d193df69619457f9fc688c38260d

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

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

claude added 2 commits August 27, 2026 14:13
…e ledger

Declares @objectstack/platform-objects in plugin-webhooks — already in its
install closure via service-messaging, so this declares a resolution that
already resolved rather than adding a package to the graph.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZbWd2jNV1FErXTPSS4Dry
…ests; changeset covers nine sets

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZbWd2jNV1FErXTPSS4Dry
@github-actions github-actions Bot added the dependencies Pull requests that update a dependency file label Aug 27, 2026
@os-zhuang os-zhuang changed the title fix(i18n): read the provenance companion at serving time in seven more bundle sets fix(i18n): read the provenance companion at serving time in all nine bundle sets Aug 27, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 27, 2026 14:53
@os-zhuang
os-zhuang enabled auto-merge August 27, 2026 14:54

Copy link
Copy Markdown
Contributor Author

PM review — ACCEPT, ready + enqueued

Reviewer of record: domain:engine PM seat (#6367). Verified against the tree at head ae7a467d, not against the report.

The addendum's load-bearing claim, checked independently

I asked for two things before this could land: that the plugin-webhooks ledger entry be deleted in the same change, and that the guard still discriminate with an empty ledger. Both hold, and the second one holds for a structural reason worth writing down rather than on the strength of the arms alone:

const declared = Object.keys(UNSERVED_PROVENANCE).sort();
const { added: undeclared, removed: repaired } = ratchet(
  [...unservedByOut.keys()].sort(),   // ← derived from the TREE
  declared,                            // ← the ledger
);

undeclared is computed from unservedByOut, which is built by walking the companions on disk. The ledger only ever subtracts. So an empty ledger is the guard's maximum-sensitivity state, not its off state — the failure mode where a registry empties out and silently takes the check with it is structurally unavailable here. The --self-test cases and the two end-to-end arms then confirm that reading behaviourally, which is the right order: the arms are evidence, the shape is the reason.

Arithmetic closed independently

The report's 27 companions, 27 served is not taken on faith:

8 wired bundle sets × 3 locales = 24    (each index.ts: 3 × withSourceFallback)
platform-objects, already wired  =  3
                                   ---
                                    27

9 of 9 sets, 27 of 27 companions. The count the gate prints is the count the tree supports.

Fences

packages/spec 0 · content/docs/releases/** 0 · docs/adr/** 0 · .claude/** 0. Governed Surface Queue Guard green. Validate Package Dependencies green over the one manifest line — which is the check that would have objected had the service-messaging → platform-objects transitive edge not actually been there.

On the two flagged deviations

Part of → Fixes — accepted. The card asked for the serving seam; served 9 of 9 with the ledger empty and a guard that keeps it that way is the whole of it, not half. Worth noting the gate that polices this was not inherited: Part-of PR must not also close its card re-ran at 14:50:00Z against the edited body and passed. A body edit does not normally re-trigger checks, so this could easily have been a stale green — it isn't.

Title change — accepted, for the same reason: "seven more" had stopped being true.

The five plugin-approvals collection errors are correctly recorded as NOT MEASURED rather than as a failure. A Failed to resolve entry for package is the build closure talking, not the diff; re-running after building the devDependency closure to 33/33 files is the right disposal, and saying so beats a silent re-run.

check:test-source-alias going red the moment the barrel imported the seam, and being repaired with an anchored subpath alias rather than by widening the shrink-only KNOWN_UNALIASED_TEST_IMPORTS registry, is the correct direction on a ratchet. Repairing the cause rather than recording the symptom is what keeps that registry meaningful.

Re-deriving the gate union after the manifest change — and finding three families the first derivation could not have named — is the habit that makes the union a measurement instead of a guess.

Enqueued. Every check green, not the required subset.


Generated by Claude Code

@os-zhuang
os-zhuang added this pull request to the merge queue Aug 27, 2026
Merged via the queue into main with commit 30928a6 Aug 27, 2026
38 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-12642-provenance-serving-seam branch August 27, 2026 15:32
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…mit that decided it (objectstack-ai#20850)

Part of objectstack-ai#20596
Clause-②: no

## What changed

This is the sixteenth stage of the `domain:services` lane of the
dead-citation sweep. It covers `packages/plugins/plugin-webhooks/src/**`
and nothing else. By the seat's claim (`5909908590`), it is the next of
the three single-site packages left in the lane, taken one package per
stage. Later stages cover the other packages, so this PR says `Part of`
and the card stays open.

Every comment or docblock site in scope that cited a tracker number
answering 404 has been rewritten in ruling C+D's form C (comment
5749154545 on objectstack-ai#19123), by the method of stages 1 to 15 (the latest is PR
objectstack-ai#20836, landed as `bbe03f406`). That is **1 site on 1 line in 1 file,
covering 1 number**:

- `src/translations/index.ts:26`, the census's one site in this package
at the base. No test comment, test string, source string or
gate-invisible spelling in this package carries a dead number (see the
supplementary reading below), so the census site is the whole
population.

The rewritten line now cites the commit in this repository that decided
what it describes: **1 commit sha**. No ADR or ruling record records
that decision (see the per-number table), so ruling C's commit rung
applies. No number was dropped.

Only a comment changed. The file keeps its line count (1 line out, 1
in), so no line citation into it moves. No code token moves (see the
guard below). **No citation number is added**: the only tracker number
on the added line is the live `objectstack-ai#12069`, which already stood on it.

The rewritten line is byte-identical to the line the six sibling
translation sets already carry (`plugin-approvals:26`,
`plugin-audit:28`, `plugin-security:26`, `plugin-sharing:26`,
`service-messaging:29`, `service-storage:29`), landed by stages 1, 2, 4,
6, 7 and 9.

**No changeset.** The rewritten docblock does not reach `dist`, and
`dist` is byte-identical with and without the rewrite (see Changeset
below), so this PR takes `skip-changeset`.

## Census: `plugin-webhooks`, before and after

**Instrument (A1).** The gate's own `node
scripts/check-issue-citations.mjs --census --json`, read-only and
unchanged. The count below is its `allocated-but-absent` findings under
`packages/plugins/plugin-webhooks/`. Each run counts as a reading only
because its board frontier equals the newest issue or pull-request
number, read by a separate request just before and just after the run.

| reading | tree | board | whole-repo `allocated-but-absent` |
plugin-webhooks sites | lines | files | numbers |
|---|---|---|---|---|---|---|---|
| before | base `bbe03f406`, run 2026-09-30T11:09:05Z to 11:12:38Z |
enumerated, 187 pages, frontier objectstack-ai#20841 (newest objectstack-ai#20841 before and after)
| 748 | **1** | 1 | 1 | 1 |
| after | head `01312906e`, run 11:26:38Z to 11:30:05Z | enumerated, 187
pages, frontier objectstack-ai#20843 (newest objectstack-ai#20842 before; objectstack-ai#20843 after, a pull
request opened 11:29:02Z inside the run, so the frontier equals the
newest at the run's end) | 747 | **0** | 0 | 0 | 0 |

The whole-repo drop is 1, exactly this diff's census site. The
`resolves` tally is 33,194 in both runs, and `resolves-as-pull-request`
(1,985) and `cross-repo-unjudged` (1,018) did not move either. Neither
run was truncated or discarded: both enumerations read 187 pages at the
newest frontier. The seat's census counted 1 here at `6bff748b`, and the
base agrees: `6bff748b` is an ancestor of the base, and the one commit
between them that touches this package's `src` (`7184436a4`, a
re-translation of generated object leaves) does not touch
`translations/index.ts:26`.

**Supplementary instrument, the whole scope.** The census does not read
test files or strings. So a second reading runs the gate's own exported
`extractCitations` (whole-file and comment-prose projections) and
`namesThisRepository` over every `.ts` file under `plugin-webhooks/src`
(34 files). It takes its verdicts from the before census's own board
reading rather than from a second enumeration: a number is dead when
that census reported it `allocated-but-absent`, and alive when the
gate's own census-scope extraction judged it and the census did not
report it. 4 numbers are covered by neither, because they stand only in
test files. Each was read on its own through the read-only tools:
`objectstack-ai#10619` answers as an issue; `objectstack-ai#8556`, `objectstack-ai#13565` and `objectstack-ai#15687` answer as
pull requests. The probe's controls: `objectstack-ai#11671` and the known issue
`objectstack-ai#10619` answer 404 on the pull-request endpoint.

| reading | citations | dead | src comment | test comment | src string |
test string |
|---|---|---|---|---|---|---|
| before, `bbe03f406` | 369 | **1** | 1 | 0 | 0 | 0 |
| after, `01312906e` | 368 | **0** | 0 | 0 | 0 | 0 |

Its src-comment column equals the census's 1, which is the control on
the second instrument. The 368 live citations are the same in both
readings (363 by the census's judgement, 5 by the single reads), none is
cross-repo, none is unjudged, and the drop of 1 citation is exactly the
rewritten site. A third, raw reading (every `#` followed by 2 to 6
digits, whatever surrounds it) finds 378 occurrences before and 377
after, the same drop of 1. The 9 tokens beyond the gate's grammar are
the same before and after, and none is dead (see Acceptance notes).

## Per-number table

Sites and files count every dead occurrence in scope at the base
(comments and strings, tests included).

| number | sites / files | rewritten / left | anchor: what it decided |
|---|---|---|---|
| `objectstack-ai#11671` | 1/1 | 1/0 | `09b4f4e4e` (PR objectstack-ai#12557): the extract command's
`--source-hashes` option writes a per-locale provenance companion,
`LOCALE.source-hashes.generated.ts`, beside the generated translation
bundles, recording for each leaf the source revision it is still a byte
copy of, per maintainer ruling objectstack-ai#12069 Option A. That is exactly what
`:25-26` say. Its message names `objectstack-ai#12069` but not `objectstack-ai#11671`; its own diff
names `objectstack-ai#11671` on 16 added lines, the first of them its changeset's
headline. `git blame` puts `:26` in `30928a615` (PR objectstack-ai#12724, which wires
the serving-time read of that companion into all nine bundle sets), a
descendant of the anchor. Reused: stages 1, 2, 4, 6, 7 and 9 gave the
identical line in six sibling packages this anchor |

The sha matches exactly one commit (`git rev-parse --disambiguate`,
count 1) and is an ancestor of the base (`merge-base --is-ancestor`,
exit 0; reverse leg, base against the anchor, exit 1; control legs exit
0: stage 1's landing `422db788a`, and the repository's root commit,
15,200 commits deep against the anchor's 3,802; the history is complete,
`--is-shallow-repository` false, 15,201 commits). `objectstack-ai#11671` answers 404
on the issues endpoint and on the pull-request endpoint, read one by
one.

No ADR, `scripts/adr-anchors/` file or ruling record names `objectstack-ai#11671`,
`objectstack-ai#12069` or the source-hash companion (`git grep` over `docs/adr` and
`scripts/adr-anchors`: one unrelated `source-hash cache` hit in
ADR-0080), so ruling C's first rung is empty.

## Wordings to check

- **Tag swap in place.** 「(maintainer ruling objectstack-ai#12069 Option A, objectstack-ai#11671)」
became 「(maintainer ruling objectstack-ai#12069 Option A, commit 09b4f4e)」. It is
the form, and the byte-identical line, the six sibling translation sets
carry.

## Sites left

- **In `src`: none.** No test title, assertion message, operator log
string, runtime refusal, quoted maintainer ruling or generated file in
this package carries a dead number.
- **Outside `src`, listed and left, not edited in this stage:**
- `scripts/i18n-extract.config.ts:17` names the dead `objectstack-ai#11671` (beside
the live `objectstack-ai#12069`); the anchor for whoever next edits it is `09b4f4e4e`.
The file is outside `files[]` and outside the census surface.
- `tsconfig.scripts.json:1` names the dead `objectstack-ai#11351` (404 on the issue
and pull-request endpoints).
- `tsconfig.test.json:3` and `:56` name the dead `objectstack-ai#13176` (404 on both
endpoints; stage 4 measured it dead).
- The other numbers in those files and in `vitest.config.ts` are live:
`objectstack-ai#12069`, `objectstack-ai#12559`, `objectstack-ai#10868`, `objectstack-ai#10756`, `objectstack-ai#5475`, `objectstack-ai#14062`, `objectstack-ai#5286`,
`objectstack-ai#5449`, `objectstack-ai#12542`, `objectstack-ai#10772`, `objectstack-ai#10374`, `objectstack-ai#12642`.
  - The release-owned `CHANGELOG.md` names `objectstack-ai#11671` on 2 lines.
- `package.json`, `tsconfig.json` and `tsup.config.ts` name none.
`files[]` lists `README.md`, but the package has none.

## Mechanical guard: no code token moves

The guard compares, base `bbe03f406` against head, over the one touched
`.ts` file:

- **Reading 1**, the TypeScript parser's leaf nodes (a `forEachChild`
walk, so comments are trivia and JSDoc nodes are never visited). String
and template literals are therefore read in full.
- **Reading 2**, the full token stream in parser context (a
`getChildren` walk, so punctuation and keywords are included; JSDoc
nodes skipped).

Results:

- Real run at the head `01312906e`: 50 base leaf tokens, **0 files with
a token change** on either reading (exit 0).
- Comment control (「Recording alone changes nothing a user sees」 to 「...
alters ...」): 0 files changed, as expected (exit 0).
- Positive control, a code token renamed (`undefined,
zhCNGeneratedSourceHashes)` to `...SourceHashesX)`): DIFFER on the
identifier in both readings (exit 1).
- Positive control, a string-literal key changed (`'es-ES'` to
`'es-EZ'`): DIFFER on the string literal in both readings (exit 1).

Every mutation went through `scripts/ablation-replace.mjs` (wrap mode)
under a shell trap that restores by absolute path, and each landed
(anchor 1 to 0, blob changed). Each restore was proven byte-identical to
the HEAD blob (`929fa19989e2`), with `git diff HEAD` empty and a clean
tree afterwards.

## Changeset: none (`skip-changeset`)

`files[]` is `dist`, `README.md` and `CHANGELOG.md`, and the package is
not private. Measured on the built package (A3), after `pnpm --filter
'@objectstack/plugin-webhooks...' build` at `01312906e`, where the
package's own `tsup` ran and cleaned its output folder:

- The rewritten line, its whole docblock (`:22-55`, which sits on the
unexported `const enSource`) and the old number appear in no `dist` file
(0 in all 20, source maps included). Nor do its neighbours `:23`, `:25`,
`:27` and `:30`, or a never-written negative phrase.
- Positive controls, text that does ship: `WebhooksTranslations` from
this same file is in `index.js`, `index.cjs` and both translations
chunks (8), and `zhCNGeneratedSourceHashes` is in both translations
chunks (4). A docblock line of this package, `auto-enqueuer.ts:33`
(「Enqueue callback into the shared `service-messaging` HTTP outbox
(ADR-0018 M3).」), is in `index.d.ts` and `index.d.cts`.
- **Byte identity.** The package was rebuilt with the base line put back
(through `scripts/ablation-replace.mjs`, with the file proven equal to
the base blob `686646fac51d` during the leg), and again after the proven
restore. The sha256 of all 20 `dist` files is identical in all three
builds: JS entries, declaration files, chunks and source maps.

So nothing this PR rewrites is published, and a changeset would announce
a change no consumer can observe. No `.changeset/*` file is added or
touched.

## Gates (head `01312906e`)

- **Citation judging, as CI runs it:** `node
scripts/check-issue-citations.mjs` exits 0 (「every citation this change
adds resolves」). `pnpm check:issue-citations` exits 0 (self-test, 114
cases, 8 batteries).
- **Doc authoring:** `pnpm check:doc-authoring` exits 0 (the
sibling-package prose-id baseline holds, no growth).
- **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` at `01312906e` (change set derived
from git: 1 path against the merge base `bbe03f406`) derived 50
commands, all among the dispatch list's 65.
- All 65 of the dispatch list ran, each with its exit code captured
before any pipe, and all 65 exit 0; none exited 3.
- `--ran`, fed each command with its exit code, reports 50 derived, 50
run, 0 NOT MEASURED (a derived zero), 0 unrun, and exits 0.
- A full `turbo run build` over `./packages/*` and `./packages/*/*` ran
first under the shared verify lock (71 of 71 tasks), so no gate hit an
unbuilt workspace.
- **Roster families the derivation lists outside its commands** (their
rosters sit in a directory this diff touches): `pnpm
check:authz-resolver`, `pnpm check:error-code-casing` and `pnpm
check:filter-alias-parity`, plus `node
scripts/check-changeset-fixed.mjs`, which the dispatch named. Each exits
0.
- **Tests and typecheck, under the verify lock, at `01312906e`:**
- `pnpm --filter @objectstack/plugin-webhooks test`: 13 files pass and
160 tests pass, which is every tracked test file under `src/`.
- `pnpm --filter @objectstack/plugin-webhooks typecheck` exits 0, and
`tsc --noEmit --listFiles` puts the touched file in the program (the
config includes `src` and excludes no test file).
- `pnpm --filter @objectstack/plugin-webhooks check:test-typecheck`
exits 0 (0 files held in the package's debt ledger).
- **Lint, as a proven narrowing:** eslint with inline config disabled,
over the touched `.ts` file, gives 1 file, 0 errors and 0 warnings (its
`--format json` output). The file is in eslint's own population (not
reported ignored; `dist/index.js`, the control, reads ignored).
`eslint.config.mjs` never enables type-aware linting (no
`parserOptions.project`, as its own lines 327-328 state), so a comment
edit here cannot move the verdict on any untouched file. The repo-wide
`pnpm lint` is CI's run.
- **Control bytes:** `pnpm check:nul-bytes` exits 0, and a raw scan of
the changed file for control bytes finds none.

## Acceptance notes

- **The gate-invisible spellings, grepped as the claim asked** (objectstack-ai#20636,
including the `clause #N` position). At the base and at the head,
`#N-word` is on 0 lines. `#A/#B` is on 8 lines (8 second numbers), and
every second number is live: `objectstack-ai#8022` (3 lines), `objectstack-ai#7986` (2) and `objectstack-ai#8043`
(2) by the census's own judgement, and `objectstack-ai#8565` read on its own as a pull
request. `option #N`, `clause #N` and URL-spelled links are on 0 lines.
So the claim's 0 / 8 / 0 / 0 / 0 hold, and nothing dead hides behind
them. The one other raw token beyond the grammar is `PD objectstack-ai#12` at
`auto-enqueuer.ts:919`, a Prime Directive ordinal the extractor excuses
on purpose.
- **Outside-`src` residue.** Three dead numbers in files outside `src`
and outside `files[]` (`objectstack-ai#11671`, `objectstack-ai#11351`, `objectstack-ai#13176`, listed above) are
left, as stages 13 to 15 left theirs. They ship nothing and move no
gate.
- **The census instrument did not truncate in this stage.** Both
enumerations read 187 pages at the newest frontier.
- **Anchor for the next stages:** `objectstack-ai#11671` → `09b4f4e4e`.
`service-realtime/src/translations/index.ts:27` still carries the dead
number in the identical sentence.
- **Base.** The branch is on `main` at `bbe03f406`. `main` has since
moved five commits (to `688ddef3c`). None touches
`packages/plugins/plugin-webhooks`, `scripts/check-issue-citations.mjs`,
`scripts/pm/dispatch-gates.mjs` or `.changeset/config.json`. No merge
was taken; the merge queue rebuilds on the merged generation.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H)_

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…mmit that decided it (objectstack-ai#20881)

Part of objectstack-ai#20596
Clause-②: no

## What changed

This is the eighteenth stage of the `domain:services` lane of the
dead-citation sweep, and the lane's last package. It covers
`packages/services/service-realtime/src/**` and nothing else. By the
seat's claim (`5913177103`), it is the last of the single-site packages,
taken one package per stage. The card's own close is the seat's act, so
this PR says `Part of` and the card stays open.

Every comment or docblock site in scope that cited a tracker number
answering 404 has been rewritten in ruling C+D's form C (comment
5749154545 on objectstack-ai#19123), by the method of stages 1 to 17 (the latest is PR
objectstack-ai#20866, landed as `6c96b37be`, the base here). That is **1 site on 1
line in 1 file, covering 1 number**:

- `src/translations/index.ts:27`, the census's one site in this package
at the base (a docblock). No test comment, test string, source string or
gate-invisible spelling in this package carries a dead number (see the
supplementary reading below), so the census site is the whole
population.

The rewritten line now cites the commit in this repository that decided
what it describes: **1 commit sha**. No ADR or ruling record records
that decision (see the per-number table), so ruling C's commit rung
applies. No number was dropped.

Only a comment changed. The file keeps its line count (1 line out, 1
in), so no line citation into it moves. No code token moves (see the
guard below). **No citation number is added**: the only tracker number
on the added line is the live `objectstack-ai#12069`, which already stood on it.

The rewritten line is byte-identical to the line the seven sibling
translation sets already carry (`plugin-approvals:26`,
`plugin-audit:28`, `plugin-security:26`, `plugin-sharing:26`,
`plugin-webhooks:26`, `service-messaging:29`, `service-storage:29`),
landed by stages 1, 2, 4, 6, 7, 9 and 16.

**No changeset.** The rewritten docblock does not reach `dist`, and
`dist` is byte-identical with and without the rewrite (see Changeset
below), so this PR takes `skip-changeset`.

## Census: `service-realtime`, before and after

**Instrument (A1).** The gate's own `node
scripts/check-issue-citations.mjs --census --json`, read-only and
unchanged. The count below is its `allocated-but-absent` findings under
`packages/services/service-realtime/`. Each run counts as a reading only
because its board frontier equals the newest issue or pull-request
number, read by a separate request just before and just after the run.

| reading | tree | board | whole-repo `allocated-but-absent` |
service-realtime sites | lines | files | numbers |
|---|---|---|---|---|---|---|---|
| before | base `6c96b37be`, run 2026-09-30T14:25:19Z to 14:29:09Z |
enumerated, 188 pages, frontier objectstack-ai#20876 (newest objectstack-ai#20876 before and after)
| 744 | **1** | 1 | 1 | 1 |
| after | head `3e5cba47c`, run 14:40:18Z to 14:44:03Z | enumerated, 188
pages, frontier objectstack-ai#20878 (newest objectstack-ai#20878 before and after) | 743 | **0** |
0 | 0 | 0 |

The whole-repo drop is 1, and the finding sets of the two runs differ by
exactly one row, `translations/index.ts:27 objectstack-ai#11671`, removed; none was
added. The `resolves` tally is 33,322 in both runs, and
`resolves-as-pull-request` (1,985) and `cross-repo-unjudged` (1,022) did
not move either. Neither run was truncated or discarded: both
enumerations read 188 pages at the newest frontier. The seat's census
counted 1 here at `6bff748b`, and the base agrees: `6bff748b` is an
ancestor of the base, and no commit between them touches this package.

At the after head, no package under `packages/services/`,
`packages/plugins/` or `packages/triggers/` holds a census finding.

**Supplementary instrument, the whole scope.** The census does not read
test files or strings. So a second reading runs the gate's own exported
`extractCitations` (whole-file and comment-prose projections) and
`namesThisRepository` over every `.ts` file under `service-realtime/src`
(18 files). It takes its verdicts from the before census's own board
reading rather than from a second enumeration: a number is dead when
that census reported it `allocated-but-absent`, and alive when the
gate's own census-scope extraction (`collectCitations`) judged it and
the census did not report it. One number is covered by neither, because
it stands only in test files: `objectstack-ai#20044`, read on its own through the
read-only tools, answers as an issue. The probe's control: `objectstack-ai#11671`
answers 404 on the issues endpoint and on the pull-request endpoint.

| reading | citations | dead | src comment | test comment | src string |
test string |
|---|---|---|---|---|---|---|
| before, `6c96b37be` | 20 | **1** | 1 | 0 | 0 | 0 |
| after, `3e5cba47c` | 19 | **0** | 0 | 0 | 0 | 0 |

Its src-comment column equals the census's 1, which is the control on
the second instrument. The 19 live citations are the same in both
readings (17 by the census's judgement, 2 by the single read), none is
cross-repo, none is unjudged, and the drop of 1 citation is exactly the
rewritten site. A third, raw reading (every `#` followed by 2 to 6
digits, whatever surrounds it) finds 20 occurrences before and 19 after,
the same drop of 1, and no token beyond the gate's grammar.

## Per-number table

Sites and files count every dead occurrence in scope at the base
(comments and strings, tests included).

| number | sites / files | rewritten / left | anchor: what it decided |
|---|---|---|---|
| `objectstack-ai#11671` | 1/1 | 1/0 | `09b4f4e4e` (PR objectstack-ai#12557): the extract command's
`--source-hashes` option writes a per-locale provenance companion,
`LOCALE.source-hashes.generated.ts`, beside the generated translation
bundles, recording for each leaf the source revision it is still a byte
copy of, per maintainer ruling objectstack-ai#12069 Option A. That is exactly what
`:26-27` say. Its message names `objectstack-ai#12069` but not `objectstack-ai#11671`; its own diff
names `objectstack-ai#11671` on 16 added lines. `git blame` puts `:27` in `30928a615`
(PR objectstack-ai#12724, which wires the serving-time read of that companion into all
nine bundle sets), a descendant of the anchor. Reused: stages 1, 2, 4,
6, 7, 9 and 16 gave the identical line in seven sibling packages this
anchor |

The sha matches exactly one commit (`git rev-parse --disambiguate`,
count 1) and is an ancestor of the base (`merge-base --is-ancestor`,
exit 0; reverse leg, base against the anchor, exit 1; control leg exit
0: the repository's root commit `1598cabe4`, 15,219 commits behind the
base, against the anchor's 3,821; the history is complete,
`--is-shallow-repository` false, 15,220 commits at the base). `objectstack-ai#11671`
answers 404 on the issues endpoint and on the pull-request endpoint,
read one by one.

No ADR, `scripts/adr-anchors/` file or ruling record names `objectstack-ai#11671`,
`objectstack-ai#12069` or the source-hash companion (`git grep` over `docs/adr` and
`scripts/adr-anchors`: one unrelated `source-hash cache` hit in
ADR-0080; nothing under `docs/` outside the release pages names either
number), so ruling C's first rung is empty.

## Wordings to check

- **Tag swap in place.** 「(maintainer ruling objectstack-ai#12069 Option A, objectstack-ai#11671)」
became 「(maintainer ruling objectstack-ai#12069 Option A, commit 09b4f4e)」. It is
the form, and the byte-identical line, the seven sibling translation
sets carry. The line grows from 77 to 87 characters, as it did in each
sibling; `eslint.config.mjs` declares no line-length rule, and reflowing
would have moved neighbouring lines.

## Sites left

- **In `src`: none.** No test title, assertion message, operator log
string, runtime refusal, quoted maintainer ruling or generated file in
this package carries a dead number. The three generated
`*.source-hashes.generated.ts` headers carry only the live `objectstack-ai#12069` and
`objectstack-ai#8765`.
- **Outside `src`, listed and left, not edited in this stage:**
- `scripts/i18n-extract.config.ts:17` names the dead `objectstack-ai#11671` (beside
the live `objectstack-ai#12069`); the anchor for whoever next edits it is `09b4f4e4e`.
The file is outside `files[]` and outside the census surface. Its other
numbers are live: `objectstack-ai#12559` and `objectstack-ai#10868`.
- `tsconfig.scripts.json:1` names the dead `objectstack-ai#11351` (404 on the issue
and pull-request endpoints). Its other numbers are live: `objectstack-ai#10756` and
`objectstack-ai#5475`.
- `vitest.config.ts` names the live `objectstack-ai#10374`; `README.md` names the live
`objectstack-ai#2992` on 2 lines.
- The release-owned `CHANGELOG.md` names the dead `objectstack-ai#11671` on 2 lines
(`:779`, `:825`) and the dead `objectstack-ai#13112` on 1 line (`:696`; 404 on the
issue and pull-request endpoints). Its other 15 numbers are live: 11 by
the census's judgement, and by single reads `objectstack-ai#18715`, `objectstack-ai#20044` and
`objectstack-ai#12642` as issues and `objectstack-ai#2528` as a pull request.
  - `package.json` and `tsconfig.json` name none.

## Mechanical guard: no code token moves

The guard compares, base `6c96b37be` against head, over the one touched
`.ts` file:

- **Reading 1**, the TypeScript parser's leaf nodes (a `forEachChild`
walk, so comments are trivia and JSDoc nodes are never visited). String
and template literals are therefore read in full.
- **Reading 2**, the full token stream in parser context (a
`getChildren` walk, so punctuation and keywords are included; JSDoc
nodes skipped).

Results:

- Real run at the head `3e5cba47c`: 50 base leaf tokens, **0 files with
a token change** on either reading (exit 0).
- Comment control (「Recording alone changes nothing a user sees」 to 「...
alters ...」): 0 files changed, as expected (exit 0).
- Positive control, a code identifier renamed (`undefined,
zhCNGeneratedSourceHashes)` to `...SourceHashesX)`): DIFFER on the
identifier in both readings (exit 1).
- Positive control, a string-literal key changed (`'es-ES':
withSourceFallback` to `'es-EZ': ...`): DIFFER on the string literal in
both readings (exit 1).
- Positive control, a keyword changed (`const enSource` to `let
enSource`): DIFFER on the keyword in reading 2 (exit 1). Reading 1
cannot see it, which is why both readings run.

Every mutation went through `scripts/ablation-replace.mjs` (wrap mode)
under a shell trap that restores by absolute path, and each landed
(anchor 1 to 0, blob changed). Each restore was proven byte-identical to
the HEAD blob (`cb6af4310953`), with `git diff HEAD` empty and a clean
tree afterwards.

## Changeset: none (`skip-changeset`)

`files[]` is `dist`, `README.md` and `CHANGELOG.md`, and the package is
not private. Measured on the built package (A3), after a full `turbo run
build` at `3e5cba47c`, where this package's own `tsup` ran (a cache
miss) and cleaned its output folder:

- The rewritten line, its whole docblock (`:23-49`, which sits on the
unexported `const enSource`), the anchor sha, the old number and the
live `objectstack-ai#12069` appear in no `dist` file (0 in all 6, source maps
included). Nor do its neighbours `:24`, `:26`, `:28`, `:29` and `:46`,
the module header `:4`, or a never-written negative phrase. The bundle
hoists that declaration to a bare `var enSource, RealtimeTranslations;`
inside the lazily imported module's init wrapper, and its docblock does
not travel with it.
- Positive controls, text that does ship: from this same file,
`RealtimeTranslations` (12 hits), `withSourceFallback` (7) and
`zhCNGeneratedSourceHashes` (6) are in the JS entries. A docblock line
of this package, `realtime-service-plugin.ts:49` (「Services init()
registers on every path」, on a class field), is in all four entries:
`index.js`, `index.cjs`, `index.d.ts` and `index.d.cts`. So a docblock
can reach `dist` here; this one does not.
- **Byte identity.** The package was rebuilt with the base line put back
(through `scripts/ablation-replace.mjs`, with the file proven equal to
the base blob `19744f2a54a4` during the leg), and again after the proven
restore. Each leg cleaned the output folder and rebuilt ESM, CJS and
declarations. The sha256 of all 6 `dist` files is identical in all three
builds: JS entries, declaration files and source maps.

So nothing this PR rewrites is published, and a changeset would announce
a change no consumer can observe. No `.changeset/*` file is added or
touched.

## Gates (head `3e5cba47c`)

- **Citation judging, as CI runs it:** `node
scripts/check-issue-citations.mjs` exits 0 (「every citation this change
adds resolves」; it judged the one added citation, `objectstack-ai#12069`). `pnpm
check:issue-citations` exits 0 (self-test, 114 cases, 8 batteries).
- **Doc authoring:** `pnpm check:doc-authoring` exits 0 (the
sibling-package prose-id baseline holds, no growth).
- **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` at `3e5cba47c` (change set derived
from git: 1 path against the merge base `6c96b37be`) derived 50
commands, all among the dispatch list's 63.
- All 63 of the dispatch list ran, each with its exit code captured
before any pipe, and all 63 exit 0; none exited 3.
- `--ran`, fed each command with its exit code, reports 50 derived, 50
run, 0 NOT MEASURED (a derived zero), 0 unrun, and exits 0. Of the other
13, it classifies 7 as pending-changeset families and 6 as outside this
derivation.
- A full `turbo run build` over `./packages/*` and `./packages/*/*` ran
first under the shared verify lock (71 of 71 tasks), so no gate hit an
unbuilt workspace.
- **Roster families the derivation lists outside its commands** (their
rosters sit in a directory this diff touches): `pnpm
check:authz-resolver`, `pnpm check:error-code-casing` and `pnpm
check:filter-alias-parity`, plus `node
scripts/check-changeset-fixed.mjs`, which the dispatch named. Each exits
0.
- **Tests and typecheck, under the verify lock, at `3e5cba47c`:**
- `pnpm --filter @objectstack/service-realtime test`: 5 files pass and
33 tests pass, which is every tracked test file under `src/`.
- `pnpm --filter @objectstack/service-realtime typecheck` exits 0, and
`tsc --noEmit --listFiles` puts the touched file in the program (the
config includes `src` and excludes no test file; all 5 test files are
listed). The package has no `check:test-typecheck` script.
- **Lint, as a proven narrowing:** eslint with inline config disabled,
over the touched `.ts` file, gives 1 file, 0 errors and 0 warnings (its
`--format json` output). The file is in eslint's own population (not
reported ignored; `dist/index.js`, the control, reads ignored).
`eslint.config.mjs` never enables type-aware linting (no
`parserOptions.project`, as its own lines 327-328 state), so a comment
edit here cannot move the verdict on any untouched file. The repo-wide
`pnpm lint` is CI's run.
- **Control bytes:** `pnpm check:nul-bytes` exits 0, and a raw scan of
the changed file for control bytes finds none.

## Acceptance notes

- **The gate-invisible spellings, grepped as the claim asked** (objectstack-ai#20636,
including the `clause #N` position). At the base and at the head,
`#N-word`, `#A/#B`, `option #N`, `clause #N` and URL-spelled links are
each on 0 lines of this package's `src` (a known-present spelling,
`objectstack-ai#14646`, reads 3 lines as the control), so the claim's 0 / 0 / 0 / 0 /
0 hold.
- **`objectstack-ai#11671` elsewhere.** Five comment lines in
`packages/platform-objects/src` still name it
(`setup.translation.ts:49`, `source-hash.ts:87`, `:214`, `:568`,
`metadata-translations/index.ts:31`), all in the census; that package
belongs to the engine lane's stage card, objectstack-ai#20595. The anchor measured
here, `09b4f4e4e`, is reusable there.
- **Outside-`src` residue.** Two dead numbers in files outside `src` and
outside `files[]` (`objectstack-ai#11671`, `objectstack-ai#11351`, listed above) are left, as stages
13 to 17 left theirs. They ship nothing and move no gate.
- **The census instrument did not truncate in this stage.** Both
enumerations read 188 pages at the newest frontier.
- **Base.** The branch is on `main` at `6c96b37be`. `main` has since
moved six commits (to `9905e61ca`, read at 14:58Z). None touches
`packages/services/service-realtime`,
`scripts/check-issue-citations.mjs`, `scripts/pm/dispatch-gates.mjs`,
`.changeset/config.json` or the doc-authoring prose-id baseline, so no
merge was taken; the merge queue rebuilds on the merged generation. The
derivation's STALE TREE note names three inputs that moved there
(`scripts/check-stack-collection-maps.mjs`,
`scripts/fixtures/i18n-walk-parity/every-group.stack.json`,
`scripts/role-word-baseline.json`); none of the derived 50 commands
names them, and none mentions this package before or after, so a
comment-only diff here cannot interact with them.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

2 participants