Skip to content

fix(spec): os migrate meta guidance for twenty-four more migration-entry families states each lesson in words, not tracker numbers (stage 8) - #20607

Merged
os-justin merged 1 commit into
mainfrom
claude/issue-20233-migrate-meta-tracker-free-stage-8
Sep 29, 2026
Merged

os-justin merged 1 commit into
mainfrom
claude/issue-20233-migrate-meta-tracker-free-stage-8

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Part of #20233
Stage 8: the stack-, evaluated-, aggregation-, authoring-, automation-, cache-, tenant-, client-, spec-, cli-, identity-, import-, tool-, advanced-, cloud-, startup-, sys-, declarative-, sort-, address-, packages-, platform-, session- and strategy- families.

Clause-②: no

os migrate meta prints each ADR-0087 semantic entry's surface, replacement, reason and acceptanceCriteria to the author. In these families, each sentence that cited a tracker number now says what the cited ruling, measurement or fix decided (form D). ADR ids stay, and so do the contributor-guide rule references, which are not tracker ids.

  • Text only: the dev's base-vs-head AST comparison over the changed entry files and registry.ts found no change outside prose fields, except surface on the two entries whose surface carried an id.
  • Pin: packages/cli/test/migrate-meta-engine-guidance.test.ts covers the 24 new prefixes; its ablation went red.
  • Generated: registry.ts, spec-changes.json and docs/protocol-upgrade-guide.md, by their generators. patch changeset.

The measurements are in the dev's report on #20233 (5886017515).

Acceptance notes

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1

…try families states each lesson in words, not tracker numbers (stage 8)

The stack-, evaluated-, aggregation-, authoring-, automation-, cache-,
tenant-, client-, spec-, cli-, identity-, import-, tool-, advanced-,
cloud-, startup-, sys-, declarative-, sort-, address-, packages-,
platform-, session- and strategy- ADR-0087 semantic entries: every
tracker, decision-batch and summon number in replacement / reason /
acceptanceCriteria, and in the two surface fields that carried one, is
rewritten to say what the cited ruling, measurement or fix decided.
ADR ids and contributor-guide rule numbers stay. Text only; the
registry, spec-changes.json and the upgrade guide are regenerated.

The migrate-meta guidance pin covers the twenty-four prefixes and its
REWRITTEN floor rises 174 -> 203.

Claude-Session: https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Sep 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

Coarse fallback — 137 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 7001918e4955e2c1cad101b1f227199ebbf46966 → packageMentionDocs.

Which tree this was computed on

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

node scripts/docs-audit/affected-docs.mjs --json 7001918e4955e2c1cad101b1f227199ebbf46966

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 309e2f32714c992eade14ebd810996a58cd191bb
Local-runs: none

① Derived judgments

Inputs. Card #20233 body and all 30 comments (triage 5856629820; rulings carried — C+D on #19123 5749154545 form D, A on surface 5858839916; the stage 1–7 records; the stage-8 claim 5883700046 and os-dev-report 5886017515). PR #20607 body, its 34-file list, and the diff from the merge base f11b5f2 to the head (origin/main has since moved to eb4b17c; of this PR's paths only registry.ts moved there). The 85 distinct tracker ids the removed lines cited, read off the diff: 69 objectstack ids answering 200 and objectui#6812 by REST; the 12 answering 404 from main's commits and CHANGELOGs; cloud#2037, hotcrm#1141 and better-auth#10909 (403) from the objectstack records that quote them (#16526, #8687, #16629).

Accept-set and public-surface changes implied by the diff: none. The diff changes only the surface, replacement, reason and acceptanceCriteria strings of 29 semantic entries, their three regenerated projections, one test and one changeset. No schema, conversion, matcher, entry id, export or runtime string moves. Right: this is the prose-only change rulings C+D and A call for, and the shape stages 1–7 landed.

Prose only — checked on the merge-base..head pair, not taken from the report. (a) Every changed line in the 29 entry files sits inside one of the four prose string literals, read line by line. (b) Mechanically: with comment lines dropped, every string-literal body blanked and 'a' + 'b' runs collapsed, the token skeleton of each of the 30 changed .ts files under packages/spec/src/migrations/ is identical base vs head; the comment lines are identical; each file's id: values are identical; registry.ts carries the same 314 ids before and after. (c) Exactly two surface fields change — authoring-schemas-strict-unknown-keys and evaluated-expression-slots-source-required — both of which carried a tracker id at base, the only surface edits ruling A allows. spec-changes.json (20/20 lines) and docs/protocol-upgrade-guide.md (12/12 lines) change only that same prose; the generator gates ride Lint & Repo Gates, green on the head.

No tracker id left in author-shown fields of these families. On the head, the 32 entries the 24 prefixes select (29 changed plus the untouched client-envelope-convergence-analytics-automation, client-oauth-applications-delete-void, stack-config-default-export-unbuilt-refused) carry no # plus four or five digits and no repo#N form on any non-comment line. Three short #N tokens remain, all on lines this PR does not touch: AGENTS.md #0.1 (address-, replacement), Prime Directive #2 (evaluated-, reason), PD #10 (identity-, reason). None is a tracker id; PD #2 and PD #10 resolve to AGENTS.md's Prime Directives; #0.1 resolves to nothing in AGENTS.md today (the dev flagged it — ③). Comment and docblock lines still cite ids, unchanged, under #20234, as the PR body says.

Rewritten sentences vs their sources — what I checked and how I chose it. I read every rewritten line in the diff and resolved every one of the 85 distinct ids. Claim-level tests (the ruling comment or landing commit itself) went to every sentence whose replacement asserts a ruling date, an option / route / letter or a verbatim quote — #4721, #4936, #5073, #6409, #7630, #11825, #12776, #13802, #13881, #14478, #14788, #15136, #15811, #15939, #16059, #16325, #16421, #16526, #16629, #17667, #19543 (doors ① and ④), and the dated rulings carried on #6704, #8715, #10485, #14519. The paraphrased fixes and findings (#2922, #3464, #3715, #3950, #4001, #4095, #4212, #4286, #4666, #4834, #4988, #5055, #5143, #5499, #5581, #5907, #6037, #6048, #6083/#6279, #6203, #6350, #6486, #7300, #8075, #8421, #8687, #10194, #10724, #11811, #11833, #11925, #12036, #12209, #13388, #14238, #14902, #15430, #15479, #15807, #16186, #16293, #16296, #16320, objectui#6812) were tested against the card's title/body or main's commit. The "own card, id dropped" class (#4484, #5040, #5227, #5540, #5599, #5638, #6011, #6361, #6815, #12007, #13023, #17157) was tested only for the sentence staying true without the number, which holds wherever the entry id itself is named.

Findings by class:

Pin. packages/cli/test/migrate-meta-engine-guidance.test.ts: COVERED_PREFIXES gains exactly the 24 prefixes the PR names; on the head registry each selects only its own family (32 entries; cli- does not reach client-, sys- not system-, packages- not package-), so the pin's own prefix rule holds; REWRITTEN gains the 29 changed ids (174 → 203). The assertion locates every selected entry's printed block verbatim in os migrate meta output and refuses # plus four or five digits in it, so the pin covers what the PR says it covers. The ablation is the dev's claim and was not re-run; Test Core and all six shards are green on the head.

PR body claims. "Text only … except surface on the two entries" — right. "Pin covers the 24 new prefixes" — right. "Generated … by their generators" — the generated diffs carry only the entry text and the generator gates are green. "ADR ids stay, and so do the contributor-guide rule references, which are not tracker ids" — right for PD #2 and PD #10; #0.1 is not a tracker id but points at nothing (③).

② Semver level

.changeset/20233-stage-8-migration-guidance-tracker-free.md: '@objectstack/spec': patch, a standalone Clause-②: no line, no widening / narrowing arm, no model identifier; the body names the two surface rewrites and the one correction. The diff publishes only from packages/spec (entries, registry.ts, spec-changes.json); the CLI change is a test file and docs/ is unpublished, so no second changeset is owed. The fix is to author-shown text of a released package (the card is a bug), which AGENTS.md's Post-Task Checklist step 3 assigns a patch changeset, never skip-changeset. No accept set moves, so Clause-②: no is right and no ADR-0087 disposition marker is owed. The PR body carries the same Clause-②: no. Check Changeset success. Level right.

③ Boundary flags

Dev report 5886017515 — open_questions: none.

deviations, each answered:

  1. Deletion-leg ordering (run from base in its own worktree while the rewrite was already committed) — process only; its two reds were the tool pin's fragment assertions, and every asserted fragment (ai.requiresConfirmation, ACTION_CONFIRMATION_REQUIRED, 428, confirm: true) is in the head text. No effect on the diff.
  2. Census and astdiff scripts rewritten in-container and validated against the stage 5–7 records — instrument provenance; my own skeleton compare in ① reaches the same text-only verdict independently.
  3. The cli- protocol 17 → 18 correction — verified true on the tree (①) and declared in the changeset and PR body as required.
  4. The pre-push hook refused a Part of line in the commit message; the commit was amended before any push — the relation lives in the PR body ("Part of os migrate meta prints tracker numbers to the author: ADR-0087 migration entries' reason / replacement / acceptanceCriteria text carries ~2,060 of them, 178 dead, which AGENTS.md's runtime-string rule forbids #20233"), the head is the branch's only commit, and Part-of PR must not also close its card and The card this PR closes must claim this branch are green.
  5. Attribution — the head commit ends with the model-free trailer pair AGENTS.md prescribes (the session link and the generic co-author line), and the PR body ends with the session-URL footer; no model identifier in the changeset, the entries or the PR. Fine.
  6. No labels or assignees written by the dev; bots set documentation / size/l / tests / tooling; needs:contract-review is on the PR and the card. Fine.
  7. test/migrate-meta.e2e.test.ts NOT MEASURED locally (nightly by name) — declared; it is outside the merge queue's required set and no head check depends on it.
  8. origin/main not merged; the dev's driver-free merge-tree is clean against eb4b17c with registry.ts the only moved path, and the merged registry equals regeneration — the seat regenerates on landing, as the claim's concurrency note already provides. GitHub reads the PR mergeable.
  9. Teardown — no bearing on the diff.

out_of_scope_findings:

  1. 76 prose-field sites remain in 39 entries, turso- (8) the largest — carrier: this card's later stages, as staged. Answered.
  2. 832 comment / docblock lines still cite ids — carrier packages/spec/src: 1,277 comment lines still cite 170 deleted tracker numbers (1,295 sites) — the staged remainder of ruling C+D on #19123, measured by PR #20226 #20234 (form C), untouched here as the claim requires. Answered.
  3. address-location-value-unknown-keys-refused's replacement cites AGENTS.md #0.1, and AGENTS.md carries no such numbering — 承接者:无. Escalated. It is not a tracker id, so it is outside this card's property, and the line is outside this PR's diff; it does not block this stage. It is nonetheless author-shown text pointing at a rule that does not exist by that number, and it should not stay noted only in a report: the seat should give it a carrier — a small card, or an explicit extra in the next stage of os migrate meta prints tracker numbers to the author: ADR-0087 migration entries' reason / replacement / acceptanceCriteria text carries ~2,060 of them, 178 dead, which AGENTS.md's runtime-string rule forbids #20233.

Claim 5883700046 stop-on-breach conditions, checked: no id / from / to / matcher change (①); no #20234 comment line touched (comment lines identical); no #20513 runtime string touched (nothing outside the entries, their projections, the pin and the changeset changed); none of the fenced open-PR entries (turso-, cube-, filter-is-empty-lowers-to-empty-operator, realtime-event-type-unemitted-values-retired) is in the file list.

Check-runs on the head 309e2f3, read last: 46 runs deduped to 35 names by newest started_at (newest 2026-09-29T07:56:38Z) — 30 success, 5 skipped (Auto Label, Build Docs, Check PR Size, Console Pin Gate, Packed-tarball smoke (opt-in)), 0 failed, 0 still running. Green: Build Core, Check Changeset, Lint & Repo Gates, Spec property liveness, Governed Surface Queue Guard, Test Core and its six shards, TypeScript Type Check and the four Type Check jobs, Dogfood Regression Gate and its three shards, Dogfood Verify CLI, Temporal Conformance (live PG + MySQL), the three card / branch guards, Check Documentation Links, Flag docs affected by code changes, filter. Commit status: one context (Vercel, ignored build step), success.

Implemented-by: claude/issue-20233-migrate-meta-tracker-free-stage-8
Reviewed-by: session_01Sfe5YjBLwB9J3y8fvm2xq1

VERDICT: PASS

Adopted and posted by domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1) · 2026-09-29T08:13Z · rendered by the seat's at-tier review subagent on this head; its served tier family was read from the subagent transcript before posting. ③'s escalated item, AGENTS.md #0.1 in the address- entry's replacement (not a tracker id; the seat found no such numbering in AGENTS.md), is carried by #20233 as an explicit extra of its next stage. PR #20610 landed on registry.ts after this head; a driver-free git merge-tree of this head onto origin/main 7510663c87 exits 0, and the merge queue runs CI on the merged state. Landing waits for all checks green.


Generated by Claude Code

@os-justin
os-justin marked this pull request as ready for review September 29, 2026 08:16
@os-justin
os-justin enabled auto-merge September 29, 2026 08:16
@os-justin
os-justin added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit c1d8051 Sep 29, 2026
51 checks passed
@os-justin
os-justin deleted the claude/issue-20233-migrate-meta-tracker-free-stage-8 branch September 29, 2026 08:41
veigajoao pushed a commit to veigajoao/objectstack that referenced this pull request Sep 29, 2026
…data/analytics.zod.ts to the commits that decided them (stage 7) (objectstack-ai#20616)

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

Stage 7 of the staged sweep: `packages/spec/src/stack.zod.ts` and
`packages/spec/src/data/analytics.zod.ts`, both freed by landings (PR
objectstack-ai#20579 and PR objectstack-ai#20458). Its claim is `5885635758`. Every comment or
docblock line in those two files that cited a tracker number answering
404 now cites the commit on `main` that decided its rule, in ruling
C+D's form C, and says in its own words what was decided. Comments only:
12 lines out, 12 in, across 2 files. No code token, string literal or
`describe()` text moves. No dead site stays: none of the 12 is read by
literal.

The census is the gate's own `node scripts/check-issue-citations.mjs
--census --json`, filtered to the two paths. Before: base `0f6dcac5e9`,
board enumerated (185 pages, frontier objectstack-ai#20611). After: head `cc0580d404`,
board enumerated (185 pages, frontier objectstack-ai#20615).

## Measurement

| file (under `packages/spec/src/`) | dead before | after | numbers,
then anchor |
|---|---:|---:|---|
| `stack.zod.ts` | 9 | 0 | objectstack-ai#10485 ×2 (`:415`, `:1023`) to `35ad101bc`;
objectstack-ai#6238 (`:633`) to `c8d6f6e08`; objectstack-ai#14192 (`:1233`) to `4d0d9445a`; objectstack-ai#14686
×2 (`:3037`, `:3194`) to `279431e7a`; objectstack-ai#14662 ×3 (`:4510`, `:5070`,
`:5293`) to `35dffeace` |
| `data/analytics.zod.ts` | 3 | 0 | objectstack-ai#10194 ×3 (`:404`, `:407`, `:485`)
to `2306a765c` |
| **2 files** | **12** | **0** | 6 numbers removed, 6 distinct shas |

Per-file counts at base equal the claim's (9 and 3, from stage 6's
census). A second instrument agrees site for site: every `#N` in the two
files, classified by the TypeScript parser, and each of the 84 distinct
numbers of 100 or more probed by REST `issues/N` without following
redirects (the other 3 are the ordinals `Prime Directive objectstack-ai#12`, `batch
objectstack-ai#23`, `batch objectstack-ai#57`).
- Base: 244 sites, all in comments (0 strings, 0 code). 78 numbers
answer 200 and 6 answer 404: the same 6 numbers and the same 12 sites as
the gate.
- Its string-class positive control found 11 string sites in
`kernel/manifest-unknown-keys.test.ts` and
`packages/cli/src/utils/lower-callables.test.ts`.
- Head: 232 sites, 78 numbers, all 78 answer 200 (the same 78), none
answers 404.
- Lit controls objectstack-ai#16862, objectstack-ai#16847 and objectstack-ai#17698 answered 200 at every
checkpoint (3 at base, 3 at head); dead controls objectstack-ai#16714, objectstack-ai#16715 and
objectstack-ai#16697 answered 404 at every checkpoint.

## Why each anchor decides its line

Each sha resolves uniquely, is an ancestor of `origin/main` (and of the
base), and has one parent. No file under `docs/adr/**`,
`docs/NORTH-STAR.md` or `scripts/adr-anchors/` names any of the six
numbers or records these rules, so each takes the commit rung, as stages
1–6 did.

- **objectstack-ai#10485 to `35ad101bc`** (`:415`, `:1023`): retires the `themes`
carrier key and `ThemeSchema` under ADR-0049. Its message records the
ruling, "Ruled B (退役授权面, 2026-08-21)", and its own `stack.zod.ts` diff
wrote both lines. `:415` keeps ADR-0049 and the ruling in its words; the
D3 entry `stack-themes-carrier-retired` it names on `:423` is unchanged.
This is the anchor stages 1, 5 and 6 used for the same retirement.
- **objectstack-ai#6238 to `c8d6f6e08`** (`:633`): widens the array member of
`functions` so its `handler` also takes the lowered string ref, which is
the fix for `objectstack build` refusing its own array output. Its
message names objectstack-ai#6238, and its own diff wrote the line. objectstack-ai#4343 and objectstack-ai#4976 on
the same line stay (both 200).
- **objectstack-ai#14192 to `4d0d9445a`** (`:1233`): turns `ManifestSchema` and its
nested blocks into `strictObject` and flips the assembled-body strip pin
to a refusal pin; each of its sub-commits names objectstack-ai#14192. The line itself
was written later by `c78c9180de`, whose own message says "objectstack-ai#14192 closed
ManifestSchema with strictObject", so the commit that closed it is the
anchor.
- **objectstack-ai#14686 to `279431e7a`** (`:3037`, `:3194`): "defineStack refuses two
actions that resolve to one scope-qualified runtime key". Its subject
names objectstack-ai#14686, and its diff adds `collectDuplicateActionKeyErrors` and
the changeset for that refusal. Both lines were written later by
`773a99960a` (PR objectstack-ai#15022), whose message describes the same "same-key
rule, which runs before the merge".
- **objectstack-ai#14662 to `35dffeace`** (`:4510`, `:5070`, `:5293`): "composeStacks
refuses two stacks whose actions resolve to one scope-qualified runtime
key". It checks the composed set with the rule `defineStack` applies
within one stack, with no `actionConflict` option (maintainer ruling
2026-09-03). Its message does not name objectstack-ai#14662; its own `stack.zod.ts`
diff wrote all three `(objectstack-ai#14662)` lines.
- **objectstack-ai#10194 to `2306a765c`** (`analytics.zod.ts:404`, `:407`, `:485`):
binds `analytics_cube` (and `theme`) in `UNREGISTERED_KIND_SCHEMAS`, so
`PUT /meta/analytics_cube/:name` parses through `CubeSchema`, and gives
`CubeSchema` the `...MetadataProtectionFields` spread. Its message names
objectstack-ai#10194, and its own diff wrote all three lines. The `[objectstack-ai#10194]` markers
become `[commit 2306a76]`, the spelling stages 1 and 5 already use in
`kernel/metadata-type-schemas.ts`.

## Mechanical proof

- **Token guard** (my `tokcmp.mjs`: TypeScript 6.0.3 leaf tokens, JSDoc
kinds excluded, controls mutate the head text in memory only). Base
`0f6dcac5e9` against the head, 2 files, 17,249 base tokens:
  - Real run: 0 files with a token change (exit 0).
  - Comment-insertion control (`data/analytics.zod.ts`): 0 (exit 0).
- Code-insertion positive control (`stack.zod.ts`, a declaration
appended): DIFFER at token 15388 (exit 1).
- String positive control (the first `StringLiteral` the parser locates
in each file): DIFFER at token 5 (exit 1), once per file.
- `describe()` positive control (the first `.describe()` string argument
the parser locates: `stack.zod.ts:133`, `analytics.zod.ts:244`): DIFFER
at tokens 507 and 442 (exit 1).
- **Line balance**: `stack.zod.ts` +9/−9, `data/analytics.zod.ts` +3/−3;
line counts equal at base and head (5344 and 853).
- **Tracker numbers**: added-not-removed is empty in both files, and no
`PR #N` is on an added line. Net-removed: 12 sites, 6 numbers. The only
numbers on added lines are objectstack-ai#4343 and objectstack-ai#4976, which stay on `:633`.
- **Shas**: 6 distinct on added lines, 0 on removed lines.
  - `rev-parse --disambiguate` answers 1 object for each.
- `merge-base --is-ancestor` exits 0 for each, against `origin/main`
`7510663c87` and against the base; each is single-parent; the repository
is not shallow.
- **Literal readers**: all 26 string, template and regex literals in the
repository that carry one of the six numbers (42 code files) were
matched against the two files' base text: 0 occur there. Each removed
line was also cut into 4-word windows (96) and searched across the tree:
the 9 hits inside string literals are other files' own test titles
sharing a phrase ("the ADR-0010 protection envelope", "an assembled body
is"), and none reads either file. The source-text readers of the two
files read code, not these comments:
`compose-stacks-refusal-envelopes.test.ts` counts `throw new Error(`,
and `check-stack-collection-maps.mjs` and
`check-skill-top-level-keys.mjs` read the declared collections and keys.

## Tests and gates (at head `cc0580d404`)

- `pnpm exec turbo run build --concurrency=2 --filter=./packages/*
--filter=./packages/*/*` under `os-verify-lock`: Tasks 71 successful, 71
total, VERDICT command-exit 0.
- `pnpm --filter @objectstack/spec check:generated` under the lock: all
15 generated artifacts up to date, `check:docs` over
`content/docs/references/**` included; VERDICT command-exit 0. No
reference page projects any of the 12 lines, so none is regenerated.
- `vitest run --maxWorkers=2` under the lock over the two files' own
suites (`src/stack*`, `src/compose-stacks*`, `src/define-stack*`,
`src/assembled-package-body`, `src/data/analytics*`, `src/data/cube*`):
Test Files 35 passed (35), Tests 976 passed (976).
- The 37 spec suites that read source text across `src/`, or carry one
of these numbers, under the lock: Test Files 37 passed (37), Tests 759
passed (759).
-
`scripts/{category-title,dist-freshness,dist-freshness-adoption,file-description,strictness-ledger,strictness-ledger-doc,root-index,skill-map-guards,export-origins,split-entries,root-entry-type-nameability.pin}`,
`scripts/liveness/{evidence,tombstoned-row-status}`;
- `src/type-alias-convention.pin`, `src/eager-entry-import`,
`src/api/{api-entry-graph.pin,auth,export-job-family-retirement}`,
`src/ai/tool-confirmation-prescription-tense.pin`,
`src/data/{currency-mode-family-closure.pin,external-lookup-retirement}`,
`src/identity/position-delegatable-enforcer.pin`,
`src/integration/{connector-connection-timeout-retirement,connector-resilience-keys-retirement}`,
`src/security/rls-tags-retirement`,
`src/shared/{alias-integrity,retired-key-migrate-sentence}`,
`src/system/{compliance-families-retirement,constants/platform-object-names,email-template-floor-locale-parity.pin,message-queue-retirement}`,
`src/ui/{action-requires-confirmation-docblock.pin,i18n,interaction-config-retirement,strictness-batch14}`,
`src/kernel/{manifest-unknown-keys,metadata-type-schemas}`.
- Left to CI:
`scripts/{build-schemas-check-mode,def-key-collisions,openapi-self-consistency}`
(each rebuilds artifacts in a temp tree) and
`scripts/{check-generated-ledger,check-generated-fix-rebuild.pin}` (read
the ledger and `dist`). None reads comment text.
- `pnpm --filter @objectstack/spec typecheck` under the lock: exit 0;
`check:test-typecheck` OK (53 files / 251 errors / 138 pinned signatures
held).
- Lint, a proven narrowing: `eslint --no-inline-config --format json`
over the 2 files gives 2 files, 0 errors, 0 warnings.
  - `isPathIgnored` is false for both, read through eslint's API.
- `eslint.config.mjs:327-328` says type-aware linting is never enabled,
so a comment edit cannot move an untouched file's verdict.
  - The repo-wide `pnpm lint` is CI's.
- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands`: 79 families derived and run, every one exit 0. `--ran`
reads "79 derived, 79 run, 0 NOT-MEASURED, 0 UNRUN". Among them:
- `pnpm check:issue-citations` (self-test, 114 cases in 8 batteries) and
the live diff-scoped `node scripts/check-issue-citations.mjs`: it judged
the 2 citations on added lines, objectstack-ai#4343 and objectstack-ai#4976, and both are live
issues.
- `pnpm check:doc-authoring`: 16,804 customer-facing strings across
1,179 spec sources clean; the sibling baseline holds.
- `pnpm check:stack-collection-maps`: 8 enumerations reconciled against
31 declared collections.
- Changeset: `patch` for `@objectstack/spec`. Both files are
`src/**/*.zod.ts`, which `files[]` ships verbatim, and the rewritten
docblocks reach `dist`: "posture: commit 4d0d944 closed" and "[commit
2306a76] This docblock used to say" are each in 2 `.d.ts`, their old
spellings in 0. Positive control: the unchanged neighbouring sentence
"BY INHERITANCE — an undeclared key on one is REFUSED" is in the same 2
`.d.ts`.
- Merge probe: a no-driver `merge-tree` of the head onto `origin/main`
`7510663c87`, from a bare shared clone, exits 0. The 3 commits `main`
gained since the base touch neither file nor the citation or derivation
scripts, and a re-derivation prints the same 79 commands. No merge was
made.
- No ablation or reverse verification: the change is comment-only, so
there is no behaviour to invert.

## Hypotheses (measured first)

1. **Holds.** 12 dead sites at the tip, 9 in `stack.zod.ts` and 3 in
`data/analytics.zod.ts`, equal per file to stage 6's census.
2. **Holds.** Read at 2026-09-29T07:36Z and again at 08:16Z, after the
last push and before this PR was opened: all open PRs' full file lists
(9 PRs, 166 files at the second read) and the newest `Claim:` on all 11
`pm:dispatched` cards. None names either file, except this card's own
claim.
3. **Holds, with nothing to keep.** All 12 sites are comments. No test
string, exported string or `describe()` text carries one, and no test or
script reads any of them by literal.
4. **Holds.** No generated reference page projects these lines;
`check:docs` is green with no regeneration.

## Deviations

- None to the file surface: the 12 claimed lines and one changeset, no
generated page needed.
- Commit trailers follow AGENTS.md's model-free pair (`Claude-Session`
plus `Co-authored-by: Claude`); the pre-push trailer check passed on
every push.

## Acceptance notes

**What stays for later stages.** The gate's census at this PR's head
(base `0f6dcac5e9` plus this PR) reads **248** dead sites (29 numbers)
in `packages/spec/src`. The only `packages/spec/src` change `main` has
made since the base (objectstack-ai#20610's migrations entry and registry) adds four
live numbers and removes none, so 248 also stands at the tip
`7510663c87` plus this PR:
- `migrations/` **233**: objectstack-ai#20233 edits the same entry files (PR objectstack-ai#20607
holds `migrations/registry.ts`).
- `conversions/registry.ts` **12**: PRs objectstack-ai#20570 and objectstack-ai#20587 hold it.
- `integration/connector.zod.ts` **1**: PR objectstack-ai#20587 (objectstack-ai#20287).
- `data/api-derivation.ts:163` (objectstack-ai#6259) and
`identity/identity.zod.ts:230` (objectstack-ai#8715), **1** each: kept because tests
read them by literal, so removing them is form D.

**Outside the gate's census: test files.** The gate defers `*.test.ts`.
The same six dead numbers still stand at 15 comment sites and 10
test-title strings in `packages/spec/src` test files:
- `data/analytics-strictness-batchd.test.ts:96` (comment, objectstack-ai#10194) and
its title `:93`. This file is in the `analytics*` set stages 3 and 4
excluded while PR objectstack-ai#20458 held it;
`analytics-date-range-two-bound-window.test.ts` and
`cube-member-inner-name-retirement.test.ts` were in that set too and are
not re-measured here.
- The package root: `compose-stacks-action-echo.test.ts:20`, `:34`,
`:200` (objectstack-ai#14686) and titles `:176`, `:224`;
`compose-stacks-action-key-collision.test.ts:3` (objectstack-ai#14662);
`stack-top-level-strict.test.ts:103` (objectstack-ai#10485) and title `:128`;
`type-alias-convention.pin.test.ts:257`, `:1572`, `:1937` (objectstack-ai#10485).
- `shared/`: `metadata-collection.test.ts:250`,
`metadata-url-spelling.test.ts:51`, `:72`, `:168` (objectstack-ai#10485), `:257`
(objectstack-ai#10194), title `:254`. `automation/sync-retirement.test.ts:207`
(objectstack-ai#10485).
- `kernel/`: `manifest-unknown-keys.test.ts`, four titles (objectstack-ai#14192);
`metadata-type-schemas.test.ts:422`, a title (objectstack-ai#10194).
- Stage 6 took the package root, `shared/` and `automation/` through the
gate's census, which never lists a test file, so test-file comment lines
there may carry other dead numbers as well. That wider population is not
measured here.

**Outside `packages/spec/src`.** The same six numbers stand at 44 more
sites
(`packages/{metadata-protocol,objectql,rest,runtime,cli,core,metadata,qa}`,
`examples/`, `scripts/`, `packages/spec/scripts/`), and at 19 sites in
`migrations/` (the objectstack-ai#20233 area).

**Rung.** The objectstack-ai#10485 retirement also has the ADR-0087 D3 entry
`stack-themes-carrier-retired`, which `:423` already names. This PR
takes the commit rung, as stages 1–6 did.

**Wording, each true of its commit.** `:3037` and `:3194` now read
"commit 279431e's same-key refusal": the refusal that commit added, in
lines `773a99960a` wrote. `:1233` reads "commit 4d0d944 closed
`ManifestSchema`", in a line `c78c9180de` wrote.

---
_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

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants