Skip to content

chore(console): bump the objectui pin to 53ded82bf7a4 — the shipped console lowers array analytics filters - #16788

Merged
baozhoutao merged 5 commits into
mainfrom
claude/issue-16626-objectui-pin-bump
Sep 8, 2026
Merged

baozhoutao merged 5 commits into
mainfrom
claude/issue-16626-objectui-pin-bump

Conversation

@claude

@claude claude Bot commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #16626

Bumps the objectui pin from a472b07167a3 to 53ded82bf7a4 so the console this repo ships carries objectui#7754's array-analytics lowering, unblocking #15442 / #15449.

The pin moved through scripts/bump-objectui.sh — never a hand edit of .objectui-sha or the generated console dist.

Acceptance criterion — the card's, verbatim, with its control legs

The instrument is only trustworthy once the control legs answer. Taken in a non-shallow objectui clone (9702 commits; git rev-parse --is-shallow-repository = false):

leg command exit reads as
CRITERION git merge-base --is-ancestor 53ded82b "$(git show origin/main:.objectui-sha)" — against this branch's pin 0 ✅ the shipped console now carries the fix
CONTROL-A --is-ancestor NEWPIN~40 NEWPIN 0 instrument alive
CONTROL-A' --is-ancestor NEWPIN~200 NEWPIN 0 alive at depth
CONTROL-C --is-ancestor NEWPIN origin/main 0 the pin is on objectui main
the gap this PR closes --is-ancestor 53ded82b a472b0716 (the OLD pin) 1 the shipped pin lacked the fix

⚠️ Stated honestly: because this bumps to exactly 53ded82b, the criterion holds reflexively (a commit is its own ancestor). The load-bearing legs are CONTROL-C and the functional probe below, not the criterion's exit 0 on its own.

Pre-bump readings agreed with triage to the commit: --is-ancestor 53ded82b a472b0716 → 1, --is-ancestor a472b0716 53ded82b → 0, distance 34.

How far to bump — the measured judgement

Bumped to exactly 53ded82b (34 commits), not to tip.

At measurement time tip was 376 commits away, not the 308 the card recorded — tip moved between filing and execution, which is itself a reason not to chase it. The 34-commit range already carries 2 declared-breaking entries and several ADR-0049 retirements; tip would add 342 more commits of unrelated console change onto a card whose stated purpose is one lowering fix — and, per the card's own headline, CI cannot see any of it.

Functional probe — because CI is blind to this seam

Green CI is not evidence here. Producer side runs the real lowering each pin performs (translateFilterArray at the old pin; lowerAnalyticsFilterForWire = translateFilterArray → isFilterAST → parseFilterAST at the new one). Wire side is the real AnalyticsQueryRequestSchema from the built @objectstack/spec.

authored filter form pin a472b0716 (shipped today) pin 53ded82bf (this PR)
record {status:{$ne:'done'}} — control ACCEPT ACCEPT
rule array [{field,operator,value}] REFUSE invalid_type@where ACCEPT
comparison tuple ['status','!=','done'] REFUSE invalid_type@where ACCEPT
and-group ['and', rule, rule] REFUSE invalid_type@where ACCEPT
empty array [] REFUSE invalid_type@where ACCEPT (posts no where at all)

What each pin actually puts on the wire as where:

form old pin posts new pin posts
rule array ["status","!=","done"] (still an array) {"status":{"$ne":"done"}}
and-group ["and",["status","!=","done"],["amount",">",100]] {"$and":[{"status":{"$ne":"done"}},{"amount":{"$gt":100}}]}
empty array [] no where key

The control ACCEPTs at both pins, so the probe is measuring the array arms and not a broken harness.

This coverage remains CI-invisible. Nothing added here renders the showcase object-metric tiles through the pinned console; the probe above is a one-off measurement recorded in this PR, not a standing test. Recorded per triage's acceptance point 4.

Clause-② tested and confirmed no — no producer/consumer mismatch

The bumped console does not accept a shape the spec refuses. The fix runs the other way: it narrows what the console posts, lowering an authored FilterArray to the FilterCondition the contract already declares. AnalyticsQueryRequestSchema.where is unchanged on origin/main (FilterConditionSchema.optional(), packages/spec/src/data/analytics.zod.ts — now line 410, the card's :299 having drifted as the file grew) and its own describe text already prescribes exactly this: an authored FilterArray is lowered by parseFilterAST on the client before the wire; this field admits only the lowered FilterCondition.

Four packages/spec/src files ARE touched — the pin-citation records below, and nothing else. They are comment-only, and measured so rather than asserted: the base (8b37a0973d) and head versions of all four compile to AST-identical output under TypeScript with removeComments: true. String literals survive that pass, so no describe text, error-guidance string, tombstone or alias literal moved. analytics.zod.ts and filter.zod.ts have zero diff against origin/main. Hence Clause-② no: the accept set did not widen, and the producer simply stopped emitting a shape that was always refused.

The second half of a pin bump

Pin citations re-measured, not sha-swapped (#10274)

12 asserting citations across 4 spec sources. Three cited objectui files changed over the range, so their anchors were re-derived:

record anchor was now
api-methods-batch-conformance.test.ts ObjectGrid.tsx selection block 3544-3559 3538-3553
dataset.zod.ts dataset-format.ts formatMeasureDate 184-197 185-198
dataset.zod.ts dataset-format.ts datetime arm 194 195
dataset.zod.ts date-display.ts formatDate 104-137 131-164
dataset.zod.ts date-display.ts ±7-day fallback 90 117

The ObjectGrid.tsx block is byte-identical across the hop — git hash-object on both spans returns 6133933199230670e29d8c7f51c558d86a0af1d2 — so it shifted six lines up and no substance moved. No read point died.

Every remaining anchor sat in a file byte-identical over the range and was still re-READ at the new pin rather than carried on that identity (containers.tsx ×4, plugin-kanban ×4, the plugin-dashboard metric chain ×4, button.tsx ×5, resolve-icon.ts ×4, lazy-icon.tsx, useBulkExecutor.ts). All correct as written.

Only the asserting spelling was updated; the 3 bare dated-history mentions of a472b0716 are left as the historical records they are.

Gates

Derived from the actual changed set with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack and reconciled with --ran.

90 derived families run, 86 exit 0. The other four measured nothing:

gate exit why it is not a red
check:dual-build-cjs-loads 3 PREREQUISITE NOT MET — reads built output; 86 packages have no dist/. Needs a whole-workspace build, which is CI's.
check:type-check-debt 3 --re-measure cannot run: 30 workspace deps unbuilt. The gate itself says a number from here would measure a different world.
check:doc-formula-expressions 3 PREREQUISITE NOT MET — @objectstack/formula unbuilt.
check:react-declaration-parity 1 → 0 needed MANIFEST; green once set (see #16715 note above).

Exit 3 is this repo's explicit nothing was measured code, distinct from a finding's 1. Every exit code was captured before any pipe.

Declared narrowing: the three exit-3 families need a full workspace build and are left to CI.

Package-level: pnpm --filter @objectstack/spec typecheck → 0; pnpm --filter @objectstack/spec test → 465 files / 12952 tests passed. Both through scripts/pm/os-verify-lock.sh (VERDICT command-exit 0).

All 127 changed lines under packages/spec/src are comment lines — verified mechanically, zero non-comment changed lines — so no type or runtime surface moves with them.

验收备注

Triage's acceptance points, answered:

  1. ✅ Bump went through scripts/bump-objectui.sh, not folded into finding(spec): ElementDataSourceSchema.filter (page.zod.ts) still declares the MongoDB-style FilterConditionSchema — the binding-level sibling of #14406 outside ComponentPropsMap, while objectui's composition seam lowers three shapes and its own pins author the tuple array #15442.
  2. ✅ The mandatory second half is done — manifest ratchet re-recorded and the docs/releases-maintenance.md "After the pin moves" procedure followed. Hit the check-react-blocks-declaration-parity.ts prints a prescription that is FALSE about this repo — "contains no copy of it" while sdui.manifest.json is checked in at the root; it made a dev declare a runnable gate NOT MEASURED #16715 false prescription and did not dump from objectui.
  3. ✅ Criterion re-run with all three legs plus the shallow check; readings above.
  4. ✅ Recorded explicitly: the gap remains CI-invisible. The probe is a one-off measurement in this PR, not a standing test.
  5. ⬜ Not this PR's act: unblocking finding(spec): ElementDataSourceSchema.filter (page.zod.ts) still declares the MongoDB-style FilterConditionSchema — the binding-level sibling of #14406 outside ComponentPropsMap, while objectui's composition seam lowers three shapes and its own pins author the tuple array #15442 / finding(spec): four object-* filter doors in ComponentPropsMap declare z.unknown() — no orthography at all — so they still accept the MongoDB-style record ui#6206-B retired, silently; the card that closed the last FilterConditionSchema door assumed they declared the array #15449 and replying on chore(console): bump the objectui pin past 53ded82b — the shipped console refuses every array analytics where, which blocks the ruled #15442/#15449 filter converge #16626. finding(spec): ElementDataSourceSchema.filter (page.zod.ts) still declares the MongoDB-style FilterConditionSchema — the binding-level sibling of #14406 outside ComponentPropsMap, while objectui's composition seam lowers three shapes and its own pins author the tuple array #15442 and finding(spec): four object-* filter doors in ComponentPropsMap declare z.unknown() — no orthography at all — so they still accept the MongoDB-style record ui#6206-B retired, silently; the card that closed the last FilterConditionSchema door assumed they declared the array #15449 are not touched here and stay open.

⚠️ Landing note for the PM: this PR touches generated artifacts, so it needs the four-step bash scripts/pm/os-regen-merge.sh sequence rather than a plain merge.

Out of scope, noted not filed: the range's own changeset records that objectui merged 7 commits carrying no .changeset/*.md; upstream's own gate for that is objectui#3387. Carrier: that upstream card.

Authored by Claude Code in session session_012GKcPZbMoGq7WPzKLfRBTU.


Generated by Claude Code

fix(data-objectstack): lower an array analytics filter through parseFilterAST before the wire (#7752) (#7754)

objectui@53ded82bf7a494f54e344e19099dbf00854b8694
…4 pin bump

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
…the pin-bump artifacts

Re-derived every asserting `.objectui-sha` citation at 53ded82bf7a4 rather than
swapping the sha (#10274): 12 citations across 4 spec sources. Three cited
objectui files changed over the range and their anchors MOVED; the rest were
re-READ at the new pin rather than carried on byte-identity.

Regenerated the two pin-derived records: scripts/sdui-manifest.record.json and
packages/sdui-parser/objectui-lockstep.json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
@github-actions github-actions Bot added the size/m label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/sdui-parser, @objectstack/spec, touching 6 documentable anchor(s). ⚠️ 1 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

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

  • content/docs/data-modeling/analytics.mdx (via DatasetMeasureSchema (symbol, a top-level const))

⛔ 1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v15.mdx (via PageTabsProps (symbol, a top-level const object))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/sdui-parser/objectui-lockstep.json) — pages documenting those are invisible to this run
  • the SDK route bridge reached 61 of 219 client-bound route-ledger rows — the other 158 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 158: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 56 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 102 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.

Coarse fallback — 131 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 a749dcc4b6f5a40cdffe7958ec576dda6bc2d01e → packageMentionDocs.

Which tree this was computed on

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

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

⚠️ 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 a749dcc4b6f5a40cdffe7958ec576dda6bc2d01e → pass the list as
args.docs, on the commit named under Which tree this was computed on.

…position

The disposition claimed the diff was `.objectui-sha` plus the changeset and
nothing else. It is not: the four packages/spec/src pin-citation sources and the
two generated pin records are in it too. A changeset ships verbatim to the
published CHANGELOG, so a published artifact must not misdescribe its own diff.

The operative clause is unchanged and still true — no schema, no authorable
metadata key, no protocol surface — and the disposition stays
`not-required (no-migration-prescription)`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Both required corrections are in, on b715b351c6. Prose only — no code, no pin, no generated JSON.

1. The permanent changeset (.changeset/console-53ded82bf7a4.md, commit b715b351c6, 1 file, 1 line changed). The false sentence "This diff is .objectui-sha plus this changeset and nothing else" is replaced with the real write set: the pin, this changeset, the four packages/spec/src pin-citation sources, and the two generated pin records (scripts/sdui-manifest.record.json, packages/sdui-parser/objectui-lockstep.json). The comment-only claim is now stated as the reviewer measured it — AST-identical under removeComments — rather than asserted. The operative clause is untouched and still true, and the disposition is still not-required (no-migration-prescription).

2. The PR body's Clause-② section. "No spec file is touched by this PR" is gone. It now says four are touched, comment-only, AST-identical base-vs-head under removeComments: true, with analytics.zod.ts and filter.zod.ts at zero diff against origin/main — therefore no.

Verification of the follow-up commit:

  • git diff 4a705a4490..HEAD --name-only → .changeset/console-53ded82bf7a4.md only; nothing outside .changeset/*.md.
  • .objectui-sha, scripts/sdui-manifest.record.json and packages/sdui-parser/objectui-lockstep.json are byte-identical to the reviewed commit (git rev-parse on each blob at both commits).
  • check-adr-0087-registration --base origin/main → exit 0, and its echoed reason now prints the corrected sentence.
  • Also green on the corrected file: check-adr-0087-registration --self-test, check-changeset-no-major, check-empty-changeset, check:objectui-changeset, check:changeset-gate-self-tests, check:console-sha, check:nul-bytes, check-comment-mask-corpus, check-closing-keyword-parity — all exit 0, each captured before any pipe.

⚠️ One note for the record: on the first body edit the platform appended its own bare attribution block beneath the session-URL one, leaving two. Corrected in a single follow-up PATCH by sending the body with no footer and keeping the session id as body prose; the stored body now carries exactly one block. Not re-pasted in a loop.

Still draft, auto-merge unarmed — the flip is yours.


Generated by Claude Code

@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Generated-artifact sync done via bash scripts/pm/os-regen-merge.sh, in a dedicated worktree on the branch — never the shared checkout. Head is now 7be42d4145, 0 behind / 5 ahead.

What the sync produced: nothing changed, and that is a measurement

Both generated records regenerated to byte-identical output. After the merge I rebuilt the spec closure and re-ran the full chain; git status came back empty and every blob hash is unchanged from before the merge:

artifact blob before blob after
scripts/sdui-manifest.record.json 8389fcb5 8389fcb5
packages/sdui-parser/objectui-lockstep.json bc425df3 bc425df3
sdui.manifest.json 78f870e4 78f870e4
.objectui-sha a9b031ce a9b031ce

This is a real regeneration, not a skipped one — both generators printed their writes (wrote sdui.manifest.json (57 components, sha256 49211fee7792…), re-recorded … at pin 53ded82bf7a4, and the lockstep recorded objectui@53ded82bf7a4 — 214 region line(s), 24 diagnostic code(s)). They wrote identical bytes because the merge moved neither input: .objectui-sha is untouched by main's six commits, and none of my artifacts is on the merge=os-regen list, so step 2 had nothing to reconcile and step 3 reported no additional changes to commit. No regeneration commit exists because there was nothing to commit.

The #16797 guard was applied

OBJECTUI_ROOT was pointed at a worktree pinned at 53ded82bf7a4, asserted equal to .objectui-sha before the generator ran. Result: objectui.rev == recordedAgainstPin == 53ded82bf7a4, 24 diagnostic codes — the correct record, unchanged.

The guard still matters today: objectui tip has moved twice since this PR opened (now f76f4362). parse.ts happens to be byte-identical at pin and tip, but the packages/sdui-parser/src tree is not (7b91c2c9 at the pin vs a1ba42c5 at tip), which is where the 25-vs-24 gap lives. Recording from tip would still have shipped the wrong record.

Nothing of main's was swallowed

The strongest available form of step 4.3: git diff origin/main HEAD --name-only returns exactly the 8 files this PR owns and nothing else, so no file of main's is altered in this tree. Corroborated by quoted-exact-name grep with a positive control — BOOLEAN_AGGREGATE_FIELD_TYPES 1/1 and recordsOf 58/58 against origin/main, with a deliberately impossible symbol reading 0/0 to prove the query can miss. All five files main's commits added are present.

Gates re-run on the merged head

Re-derived post-merge (8 paths vs the new merge base b38821d1c) and re-ran the full set: 90 families, 87 exit 0. check:react-declaration-parity is green here (with MANIFEST set), which is the one that moved up from the pre-merge run.

The same three are PREREQUISITE NOT MET (exit 3 — nothing measured, not a finding): check:dual-build-cjs-loads, check:type-check-debt, check:doc-formula-expressions. All three read whole-workspace build output that nothing in this diff feeds; left to CI. Exit codes captured before any pipe.

Still draft, auto-merge unarmed — the flip stays yours.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 8, 2026 07:12
@baozhoutao
baozhoutao enabled auto-merge September 8, 2026 07:12
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit 30b0990 Sep 8, 2026
36 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-16626-objectui-pin-bump branch September 8, 2026 07:35
veigajoao pushed a commit to veigajoao/objectstack that referenced this pull request Sep 29, 2026
… sites to the commits that decided them (stage 5) (objectstack-ai#20576)

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

## What changed

This is stage 5 of the staged sweep: the `ui/` area
(`packages/spec/src/ui/**`, 133 files), plus two sites freed since stage
4: `data/filter-subtree-provenance.ts` (PR objectstack-ai#20460 landed without
touching it) and `meta-spelling/manifest-collection-spelling.ts` (the
census hand-over, comment 5882628946 on objectstack-ai#20234).
`ui/view-grouping-query.ts` is excluded because objectstack-ai#20446's claim holds it;
it carries 4 citations and none of them is dead, so the exclusion
removes nothing. Later stages cover the other areas, so this PR says
`Part of`.

Every comment and docblock site in that population that cites a tracker
number answering 404 has been rewritten in ruling C+D's form C (comment
5749154545 on objectstack-ai#19123). That is **87 comment sites**: 84 re-anchored and
3 respelled.
- **84 re-anchored, over 25 numbers.** Each rewritten line now cites the
commit in `origin/main` history that decided what the line describes,
and says in its own words what that commit decided. One line
(`ui/dashboard.zod.ts:686`) quotes ADR-0087 itself; it keeps ADR-0087 as
its citation and paraphrases the amendment heading instead of quoting
its number.
- **3 respelled**, so each number of a sibling pair carries its own
qualifier: `ui/view.zod.ts:3634` now reads `objectui#6110 +
objectui#6111`, and `ui/component.zod.ts:3479` and `:4140` now read
`objectui#8221's PR objectui#8758`. Each second number answers 404 here,
and the sentence attributes it to objectui (objectui REST: `issues/6111`
200, `pulls/8758` 200, merged 2026-09-09).

Only comments changed, plus the one generated reference page they
project into and a patch changeset. Every source file keeps its line
count (90 lines out, 90 in, over 25 files). Three of the 90 lines held
no dead number; each is the other half of a rewritten sentence:
`ui/action.zod.ts:400`, `ui/action-param-carryover.test.ts:13` and
`ui/expression-bindable-text-keys.test.ts:119`. No code token moves (see
the guard below).

**No tracker number is added.** Every tracker number on an added line
was already on the lines it replaces, and no `PR #N` is added.

## Census: before and after

**Instrument.** This is the instrument of stages 1 to 4, rebuilt for
this stage. It sends REST `GET
/repos/objectstack-ai/objectstack/issues/N` without following redirects,
for every distinct number cited in the population. The population is:
- the citation gate's own exported `CITATION_RE` and
`NON_CITATION_HEADS` at the base, kept when the qualifier is none,
`objectstack`, `objectstack-ai/objectstack`, `framework`, `pre-` or
`post-`;
- matched case-insensitively (`Pre-`, `POST-`, `Framework`);
- N of 100 or more, excluding `summon` heads.

A qualifier covers only the number it is joined to. Each site is
classified by the TypeScript parser as a line comment, a docblock, a
block comment or a string.

**Controls.** The lit controls were `objectstack-ai#16862`, `objectstack-ai#16847` and `objectstack-ai#17698`. The
dead controls were `objectstack-ai#16714`, `objectstack-ai#16715` and `objectstack-ai#16697`. They were probed at
the start, after every 100 numbers and at the end: 18 of 18 lit (200)
and 18 of 18 dead (404) over 6 checkpoints in the base run, and 15 of 15
and 15 of 15 over 5 checkpoints in the head run.

| reading | tree | numbers probed | 200 | 404 | 301 or other | dead
sites | lines | files | of which comments | of which strings |
|---|---|---|---|---|---|---|---|---|---|---|
| before | base `487a7846df`, probed 2026-09-29T02:57:01Z to 02:59:36Z |
400 | 372 | 28 | 0 | **111** | 110 | 26 | 90 | 21 |
| after | head `83e39641d0`, probed 2026-09-29T03:15:00Z to 03:18:06Z |
383 | 372 | 11 | 0 | **24** | 23 | 8 | 3 | 21 |

The head probe found no number newly dead since the base probe: the same
372 numbers answer 200. The head was probed at `83e39641d0`; every
census file is byte-identical at the final head.

**Cross-check under the grammar that landed during this stage.** PR
objectstack-ai#20554 (`199002b3e4`) landed the closed qualifier set while this stage
ran, and it reads `objectui PR objectstack-ai#8758` as objectui's number. Re-run with
that gate's own `extractCitations` and `namesThisRepository`, the same
population reads **108** dead sites before and **21** after, all 21 test
strings. The difference is exactly the three `objectui PR objectstack-ai#8758` prose
sites below, which that PR's own header measured as "census deaths here
that are not deaths at all".

**Per file.** Cited sites are every in-repo citation the population
reads, live or dead.

| file | cited sites (base) | dead before | by class | dead after |
|---|---|---|---|---|
| `data/filter-subtree-provenance.ts` | 9 | 3 | 3 docblock | 0 |
| `meta-spelling/manifest-collection-spelling.ts` | 8 | 2 | 2 line
comment | 0 |
| `ui/action-param-carryover.test.ts` | 5 | 3 | 2 line comment, 1 string
| 1 |
| `ui/action.test.ts` | 39 | 3 | 3 line comment | 0 |
| `ui/action.zod.ts` | 90 | 7 | 5 docblock, 2 line comment | 0 |
| `ui/bulk-action.test.ts` | 9 | 4 | 2 line comment, 2 string | 2 |
| `ui/bulk-action.zod.ts` | 9 | 3 | 2 docblock, 1 line comment | 0 |
| `ui/component-element-navigation-17987.test.ts` | 8 | 5 | 1 docblock,
4 string | 4 |
| `ui/component-type-vocabulary.test.ts` | 8 | 2 | 2 docblock | 0 |
| `ui/component-type-vocabulary.ts` | 2 | 1 | 1 docblock | 0 |
| `ui/component.test.ts` | 190 | 22 | 11 line comment, 11 string | 11 |
| `ui/component.zod.ts` | 265 | 20 | 16 docblock, 4 line comment | 0 |
| `ui/dashboard.zod.ts` | 52 | 1 | 1 docblock | 0 |
| `ui/expression-bindable-text-keys.test.ts` | 3 | 2 | 2 line comment |
0 |
| `ui/expression-bindable-text-keys.zod.ts` | 4 | 2 | 2 docblock | 0 |
| `ui/form-select-option.test.ts` | 3 | 1 | 1 docblock | 0 |
| `ui/index.ts` | 15 | 2 | 2 line comment | 0 |
| `ui/interaction-config-retirement.test.ts` | 19 | 1 | 1 docblock | 0 |
| `ui/react-blocks.test.ts` | 9 | 2 | 1 docblock, 1 string | 1 |
| `ui/react-blocks.ts` | 17 | 4 | 2 docblock, 2 line comment | 0 |
| `ui/view-form-features-root.test.ts` | 4 | 1 | 1 line comment | 0 |
| `ui/view-metadata-schema.test.ts` | 31 | 3 | 2 line comment, 1 string
| 1 |
| `ui/view-submit-redirect-url.test.ts` | 8 | 1 | 1 line comment | 0 |
| `ui/view.test.ts` | 136 | 2 | 1 docblock, 1 string | 2 |
| `ui/view.zod.ts` | 331 | 13 | 10 docblock, 3 line comment | 2 |
| `ui/widget-i18n-retirement.test.ts` | 17 | 1 | 1 line comment | 0 |

`ui/` alone went from 106 dead sites in 24 files to 24. The other 107
`ui/` files carry no dead site.

## Per-number table

Anchors are 9-hex commit abbreviations. "Wrote" means the commit's own
diff added the line being rewritten.

| number | comment sites / files | anchor: what it decided |
|---|---|---|
| `objectstack-ai#5970` | 4 / 2, `action.zod.ts:819`, `action.test.ts:268`, `:304`,
`:354` | `97e7e3caa`: `ActionSchema.visible` / `disabled` speak one
condition shape; `visible` gains its boolean arm. Stage 1's anchor for
the same number |
| `objectstack-ai#6276` | 7 / 1, `component.zod.ts:34`, `:165`, `:568`, `:2455`,
`:2546`, `:2554`, `component.test.ts:2126` | `78f0be872`: declares
`element:record_picker`'s flat `sort` / `limit` on the objectstack-ai#5611 rule
(maintainer ruling 2026-08-08, direction A). It wrote `:34`, `:2455` and
the "enumerate by the renderer's read pattern" lesson |
| `objectstack-ai#8794`, `objectstack-ai#8836` | 3 / 1, `filter-subtree-provenance.ts:130`, `:131`,
`:156` | `1850ebbb0`: corrects the reuse-safety claim from the survey
and pins the invariant. It wrote `:131` itself. Stages 1 and 3 gave both
numbers this anchor |
| `objectstack-ai#9933` | 7 / 2, `view.zod.ts:2517`, `:5060`, `:5086`, `:5118`,
`:5513`, `view-metadata-schema.test.ts:398`, `:410` | `d5552ca13`:
admits `columnState` as an explicitly runtime-only view-overlay key,
rejected by name at every authoring door. It wrote "explicitly out of
objectstack-ai#9933's scope" |
| `objectstack-ai#9972` | 3 / 2 (+1 unread), `component.zod.ts:2213`,
`component.test.ts:382`, `:3565`; also `:3612`'s `objectstack-ai#9881/objectstack-ai#9972`, a
slash-joined spelling the grammar does not read | `60e0f900a`: records
the live read point of `page:tabs` `items[].icon` and its accept-pin. It
wrote the `:382` header |
| `objectstack-ai#10194` | 1 / 1, `manifest-collection-spelling.ts:71` (`pre-objectstack-ai#10194`)
| `2306a765c`: `/meta/theme` and `/meta/analytics_cube` stop storing any
JSON as success and validate at the write door. The line now says "the
store-anything branch from before commit 2306a76". Stage 1's anchor |
| `objectstack-ai#10274` | 6 / 2, `component.zod.ts:2304`, `component.test.ts:308`,
`:405`, `:3591`, `:3603`, `:3612` | `d1ba685ec`: re-measures the four
pin citations and gates the class. Its gate header records that the
re-measure found two anchors wrong since they were written, which is why
a refresh re-reads. Stage 3's anchor |
| `objectstack-ai#10485` | 4 / 4, `index.ts:51`,
`interaction-config-retirement.test.ts:116`,
`widget-i18n-retirement.test.ts:112`,
`manifest-collection-spelling.ts:67` | `35ad101bc`: retires the `themes`
carrier and `ThemeSchema` whole (ruled B, 2026-08-21; ADR-0049 stays
cited). Stage 1's anchor |
| `objectstack-ai#11284` | 5 / 2, `react-blocks.ts:39`, `:94`, `:109`, `:295`,
`react-blocks.test.ts:139` | `5383fa670`: the react tier converges on
the metadata-tier vocabulary, deprecate-first. Its changeset heads
"(objectstack-ai#11284, maintainer ruling 2026-08-23)" |
| `objectstack-ai#11350` | 1 / 1, `index.ts:105` | `ece4dad31`: records the maintainer
ruling of 2026-08-23 that a type in an entry's public declarations must
be nameable from that entry. Same wording as stage 1's
`kernel/index.ts:53` |
| `objectstack-ai#11507` | 2 / 2, `component.zod.ts:1465`, `component.test.ts:2726` |
`88b9d749a`: declares `sys_activity.type` an open, author-extensible
vocabulary (maintainer ruling 2026-08-24, direction 4). Stage 3's anchor
|
| `objectstack-ai#11658` | 2 / 2, `component.zod.ts:1464`, `component.test.ts:2725` |
`1a6a19c31`: opens `RecordActivityProps.types` to author-contributed
kinds, executing that ruling. Stage 3's anchor |
| `objectstack-ai#11703` | 3 / 2, `action.zod.ts:399` to `:400`, `:460`,
`action-param-carryover.test.ts:12` to `:13` | `5cb62d88b`:
`clone_permission_set` carries all five copied facets; its params list
had silently dropped three. The lines now name "the silent-drop shape
commit 5cb62d8 fixed" |
| `objectstack-ai#11753` | 5 / 2, `action.zod.ts:66`, `:390`, `:398`, `:409`,
`action-param-carryover.test.ts:1` | `0e4e51b0a`:
`ActionParamSchema.carryOver`, the spec half of the 2026-08-25
maintainer ruling (recommendation A). It wrote every one of these lines,
and its changeset records the `visible: false` measurement `:398` names
|
| `objectstack-ai#12194` | 1 / 1, `view.zod.ts:4838` | `311433f6b`: declares the
metadata item-name grammar (`QUALIFIED_ITEM_NAME_PATTERN` among it) and
refuses it at the publish door. Stage 2's anchor |
| `objectstack-ai#12868` | 5 / 2, `view.zod.ts:2938`, `:2966`, `:3179`, `:7087`,
`form-select-option.test.ts:4` | `c459da6bc`: narrows the per-option
`default` key out of the form-view options vocabulary. Its changeset
records the ruled census `:2966` cites ("measured ZERO occurrences").
Stages 3 and 4's anchor |
| `objectstack-ai#12950` | 3 / 2, `component-type-vocabulary.ts:4`,
`component-type-vocabulary.test.ts:4`, `:101` | `225e7690f`: created
`component-type-vocabulary.ts`; its message records the readiness read
`:101` pins (`global:search` and `global:notifications` stay declared) |
| `objectstack-ai#13156` | 2 / 2, `view-form-features-root.test.ts:70`,
`view-submit-redirect-url.test.ts:110` | `fd289be45`: strips tracker ids
from function-declaration-built refusal prose. It wrote both lines.
Stage 3's wording ("commit fd289be's strip") |
| `objectstack-ai#13670` | 1 / 1, `expression-bindable-text-keys.zod.ts:72` |
`8c6a7fc0b`: records `text.value` as deliberately omitted; its message
states the ruling that `text`'s evaluation channel is `content` alone |
| `objectstack-ai#13672` | 3 / 2, `expression-bindable-text-keys.zod.ts:89`,
`.test.ts:65`, `:118` | `e854a531a`: narrows the `button` row to the
spelling its key reaches, and records `action:button` and `ui:button` as
deliberately out |
| `objectstack-ai#16626` | 1 / 1, `component.test.ts:2336` | `30b099078`: the objectui
pin bump to `53ded82bf7a4` that ships objectui#7754's array-analytics
lowering, the door the family waited on. The association is PR objectstack-ai#16788's
body (it names objectstack-ai#16626 as the card it lands), and `30b099078` is that
PR's merge commit; neither its message nor its diff names objectstack-ai#16626 (the
stage-3 objectstack-ai#11065 precedent) |
| `objectstack-ai#17987` | 9 / 2, `component.zod.ts:10`, `:4014`, `:4062`, `:4153`,
`:4193`, `:5068`, `:5226`, `:5457`,
`component-element-navigation-17987.test.ts:4` | `e233db9db`: declares
element-level `navigation` on `object-kanban` / `object-calendar` and
gives `object-timeline` its `ComponentPropsMap` row, executing the
objectui#8652 ruling (verbatim `B`) |
| `objectstack-ai#18003` | 1 / 1, `dashboard.zod.ts:686` | **ADR-0087**, the rung
above a commit. The line quoted the ADR's own amendment heading, number
included. It now reads "(ADR-0087, its 2026-09-13 amendment, 「the level
half」)": the ADR stays the citation and the fragment it quotes is
verbatim |
| `objectstack-ai#18177` | 5 / 2, `bulk-action.zod.ts:51`, `:169`, `:262`,
`bulk-action.test.ts:61`, `:307` | `adabccf5f`: `BulkActionParamSchema`
is strict and declares `dependsOn`, executing decision batch objectstack-ai#146 item
4, letter A |
| `objectstack-ai#6111` | 1 / 1, `view.zod.ts:3634` | respelled `objectui#6111` (not
re-anchored): it is objectui's number |
| `objectstack-ai#8758` | 2 / 1, `component.zod.ts:3479`, `:4140` | respelled `PR
objectui#8758` (not re-anchored): objectui's PR objectstack-ai#8758, merged 2026-09-09
|

No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/`
records the decision behind any of the 25 re-anchored numbers except
objectstack-ai#18003. ADR-0126 mentions objectstack-ai#11703 and objectstack-ai#11753 only as references
("permission-set precedent"), not as the record of either decision.

**Anchor checks.** Every sha on an added line is one of 23, and none is
on a removed line. At the base `487a7846df`:
- each matches exactly one object (`git rev-parse --disambiguate`, count
1, 23 of 23);
- each is an ancestor (`git merge-base --is-ancestor`, exit 0, 23 of
23); the control leg `e9584681a4` also exits 0, and the repository is
not shallow;
- for 22 of the 23, a grep of the commit's own message or diff finds the
number it replaces (the message for 16; the diff for `0e4e51b0a`,
`5383fa670`, `c459da6bc`, `225e7690f`, `e854a531a`, and for objectstack-ai#8836 in
`1850ebbb0`). `30b099078` is the exception explained in the table.
- Each commit was read for the rule its line states, not only for the
number. In most cases the commit wrote the very line it now anchors.

Wordings to check, each true of its commit:
- `filter-subtree-provenance.ts:130` and `:156` read 「survey commit
1850ebb records」: the survey was the card's, and the commit's message
records its measurement. It is stage 3's wording for the same relation
(「from the survey it records」).
- `component.zod.ts:1465` and `component.test.ts:2726` read 「maintainer
ruling commit 88b9d74 declared」: that commit landed the ruling
(direction 4) as the `sys_activity.type` declaration.
- `manifest-collection-spelling.ts:71` reads 「the store-anything branch
from before commit 2306a76」: before that commit, `PUT
/meta/theme/:name` stored any JSON as success.

## Mechanical guard: no code token moves

The check compares leaf tokens with comments stripped, base `487a7846df`
against the head. It uses the TypeScript parser's leaf tokens from the
head's lockfile, so template literals are scanned in context, and it
excludes JSDoc nodes. It ran over all 25 touched `.ts` files, and every
control mutates the head text in memory only.

- Real run: 101,836 base tokens, **0 files with a token change** (exit
0).
- Comment-insertion control (`ui/index.ts`): 0 files changed (exit 0).
- Positive control (a declaration inserted into `ui/view.zod.ts`): 1
file reads DIFFER at token 19222 (exit 1).
- Positive control (one digit changed in a `component.test.ts` test
title): 1 file reads DIFFER at token 14972 (exit 1).

Line balance holds in every file, 90 out and 90 in over the 25, and
every line count is equal at base and head. Tracker numbers:
added-not-removed is empty in every file. The net-removed numbers are
the 25 in the table, 85 sites: the census's 84 comment sites, plus the
slash-joined `objectstack-ai#9972` at `component.test.ts:3612`.

## Generated page

`check:generated` proved one artifact stale:
`content/docs/references/ui/expression-bindable-text-keys.mdx`, the
projection of `expression-bindable-text-keys.zod.ts`'s module docblock.
`check:generated --fix` regenerated only that page, and a re-run read
`All 15 generated artifacts are up to date`. Its two changed lines are
the `:72` and `:89` substitutions verbatim. No other docblock here
projects into a reference page, and nothing under `skills/**` moved.

## Changeset

This change ships bytes, so a `patch` changeset for `@objectstack/spec`
is included. It says only that the provenance comments were re-anchored.
`Clause-②: no`: no export, key, value or type moves (the guard above).

Measured on the head's built package: 6 touched sources are
`src/**/*.zod.ts`, which `files[]` ships verbatim. The rewritten
comments also reach `dist`:
- `c459da6bc` appears in 32 bundled `.js` files and 2 `.d.ts`;
- `adabccf5f` in 24 `.js` and 2 `.d.ts`; `d5552ca13` and `0e4e51b0a` in
24 `.js` each; `e233db9db` and `78f0be872` in 2 `.js` and 2 `.d.ts`
each;
- the positive control, the pre-existing sentence 「the object-field face
enforces」, appears in 32 files.

## Gates (head `1b885d3c27`)

- **Citation judging pass, run as CI runs it:** `pnpm
check:issue-citations && node scripts/check-issue-citations.mjs`, both
under the grammar PR objectstack-ai#20554 landed, exit 0. The self-test passes 114
cases in 8 batteries. The live, diff-scoped run judged 13 citations
across 11 files: 3 resolve and 10 are declared cross-repo references. It
reads "every citation this change adds resolves".
- **Doc authoring:** `pnpm check:doc-authoring` exits 0. Its 16,759
customer-facing strings across 1,174 spec sources carry no internal
issue id, and the sibling-package prose-id baseline holds with no
growth.
- **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` at this head derived 112
families, and all 112 exit 0. `--ran` reports 112 run, 0 NOT MEASURED, 0
unrun. A full `turbo run build` of `./packages/*` at this head ran
first, under the shared verify lock: 71 of 71 tasks, VERDICT
command-exit 0. So no gate met an unbuilt prerequisite.
- **Five roster gates the derivation flags for this diff** (their
rosters sit in `.changeset/` or `packages/`, so their silence proves
nothing): `node scripts/check-changeset-fixed.mjs`, `pnpm --filter
@objectstack/spec run check:spec-changes`, `pnpm check:authz-resolver`,
`pnpm check:error-code-casing` and `pnpm check:filter-alias-parity`. All
exit 0.
- `pnpm --filter @objectstack/spec run check:generated` (derived) reads
`All 15 generated artifacts are up to date`, and `check:docs` reads `226
generated files in sync`.
- **Tests and typecheck, under the lock:**
- `pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/ui
src/meta-spelling`: Test Files 98 passed (98), Tests 3452 passed (3452),
VERDICT command-exit 0 (the chain held the lock 142s on a shared box).
- The 16 spec suites outside `src/ui` that read the touched files'
source text or pin their lines: Test Files 16 passed (16), Tests 489
passed (489). They are
`scripts/{export-origins,file-description,root-index,schema-closure,skill-map-guards,strictness-ledger}.test.ts`,
`src/ai/tool-confirmation-prescription-tense.pin.test.ts`,
`src/api/api-entry-graph.pin.test.ts`,
`src/contracts/scoped-context.test.ts`,
`src/data/filter-subtree-provenance.test.ts`,
`src/shared/{alias-integrity,evaluated-slot-population,retired-key-migrate-sentence,union-author-message-pins}.test.ts`,
`src/system/constants/platform-object-names.test.ts` and
`src/type-alias-convention.pin.test.ts`. Three more suites matched the
reader scan and are not run here:
`scripts/build-schemas-check-mode.test.ts` only imports `ViewItemSchema`
(code the guard proves unchanged) and rebuilds schemas in a temp tree;
`scripts/def-key-collisions.test.ts` names `ui/view.zod.ts` only in a
comment; `scripts/published-projection-choke-point.test.ts` matched on
`build-react-blocks-contract.ts`, not a touched file. They are left to
CI.
- `pnpm --filter @objectstack/spec typecheck`: exit 0, including
`check:test-typecheck` (53 files, 251 errors, 138 pinned signatures
held). The same three runs also passed, with the same counts, on the
pre-merge tree.
- **Lint, as a proven narrowing:** `eslint --no-inline-config --format
json` over the 25 touched `.ts` files gives 25 files, 0 errors and 0
warnings. All 25 are in eslint's own population (`isPathIgnored` is
false for each, read through eslint's API). `eslint.config.mjs` never
enables type-aware linting (no `parserOptions.project`, which its own
lines 327 to 328 state), so a comment edit here cannot move the verdict
on any untouched file. The repo-wide `pnpm lint` is CI's run.
- **Merge probe:** a `merge-tree` of the head onto `origin/main`
`f572a7eb3c`, from a bare shared clone with no merge driver registered,
exits 0 (2026-09-29T04:15Z).

## Acceptance notes

- **Base and merge.** The branch forked from `487a7846df`, one commit
past the claim's stamp `6154165484` (PR objectstack-ai#20551, outside the surface).
`origin/main` then moved three commits, and `199002b3e4` (PR objectstack-ai#20554)
changed `scripts/check-issue-citations.mjs`, so the gate derivation read
STALE TREE. `origin/main` `dee9b26f6c` was merged in (`1b885d3c27`): a
clean merge with no driver-routed path and no lockfile change, touching
none of this diff's files. The PR's delta against `dee9b26f6c` is
exactly its 27 files. `origin/main` has since moved one more commit,
`1c761c0d71` (PR objectstack-ai#20565, tests in two other packages), which touches
none of them.
- **One site beyond the hand-over's list.** The hand-over named
`manifest-collection-spelling.ts:71` (`pre-objectstack-ai#10194`). The same comment's
first line, `:67`, cites `objectstack-ai#10485`, which also answers 404, and it is
rewritten too. The claim names this file; the fix is the same defect
class, mechanical in the form stages 1 to 4 fixed, in a file no other
claim holds, under the same gates. Reverting it would be one line.
- **Open PRs, re-read at 2026-09-29T04:22Z:** 8 open PRs, and none
touches any file in this diff. The one that touches `ui/` is objectstack-ai#20570
(objectstack-ai#20446's), on the excluded `view-grouping-query.ts`. The in-flight
`Claim:` comments on the 12 `pm:dispatched` cards were read too: only
objectstack-ai#20446's names a `ui/` file (`view-grouping-query.ts`, excluded above).
- **Hypothesis 2, measured.** In `ui/`, 14 sibling-qualified pairs leave
the second number bare: 13 on one line (`+`, `and`, `,`, `/` or `'s PR`
between them) and `component.zod.ts:3478` to `:3479`, split across a
line break. In 3 of them the second number answers 404 here and the
sentence attributes it to objectui (`objectstack-ai#6111` once, `objectstack-ai#8758` twice); they
are respelled above. In the other 11 the second number answers 200 here,
so it is judged as this repository's and left: `action.zod.ts:1603`,
`component.test.ts:2052`, `:2199`, `:2315`, `component.zod.ts:3276`,
`:3793`, `:4812`, `expression-bindable-text-keys.zod.ts:33`,
`page.test.ts:696`, `react-blocks.ts:256` and `widget.zod.ts:34`. The PR
objectstack-ai#20554 header measured `,` and `and` pairs as naming this repository's
number and `/` pairs as mostly, but not always, the qualifier's. Whether
any `/` pair here names objectui's number is not measured; a 200 here
cannot tell.
- **What stays in this population: 24 dead sites** (21 under the landed
grammar).
- **21 test strings**, left as tokens (vitest `it` / `describe` titles
in 7 test files): `objectstack-ai#6276` ×6, `objectstack-ai#11658` ×3 and `objectstack-ai#11507` ×1 in
`component.test.ts`; `objectstack-ai#9972` in `component.test.ts:411`; `objectstack-ai#17987` ×4 in
`component-element-navigation-17987.test.ts`; `objectstack-ai#18177` ×2 in
`bulk-action.test.ts`; `objectstack-ai#9933` in `view-metadata-schema.test.ts:406`;
`objectstack-ai#11284` in `react-blocks.test.ts:147`; `objectstack-ai#11753` in
`action-param-carryover.test.ts:17`; `objectstack#11195` in
`view.test.ts:3396`. None is a Zod `.describe()` text, an exported
string or a migration-entry field, so no form D site arises here.
- **3 comments that name objectui's live PR objectstack-ai#8758 in prose** (`objectui
PR objectstack-ai#8758`): `view.zod.ts:2354`, `:2579` and `view.test.ts:426`. They are
not pairs, and the landed grammar reads them as objectui's.
- **Left for later stages of objectstack-ai#20234** (the stage-4 landing comment
5882686893's list, unchanged): the migrations area, the `liveness/**`
notes, the `why` strings and the `PROVENANCE_WAIVERS` reason,
`rest-server.zod.ts`, the held `analytics*` and `driver/turso.*` files,
the 2 `AGGREGATION_CASES` note strings, and `data/`'s test strings and
deliberate markers.
- **The same rot outside `packages/spec/src`** is objectstack-ai#20556's, not this
card's. Examples met here: ADR-0087's own amendment heading
(`docs/adr/0087-metadata-protocol-upgrade-contract.md:390`, `:397`)
cites the dead `objectstack-ai#18003`, and ADR-0126 cites `objectstack-ai#11703` and `objectstack-ai#11753`; both
are governed. `packages/spec/scripts/strictness-ledger.test.ts:375`,
`:380` cite `objectstack-ai#9933`, and `check-objectui-pin-citations.ts` cites
`objectstack-ai#10274` and `objectstack-ai#9972`.
- **Unchanged wording.** `react-blocks.test.ts:140` says the 2026-08-23
ruling was "recorded on-card". The card is gone, and the changeset of
`5383fa670` (now cited on `:139`) records the ruling. The line holds no
number, so it is left.
- **The citation gate's reach.** It defers `packages/**/*.test.ts`. The
11 touched non-test files are in its judging population.

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

---------

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants