Skip to content

docs(kernel): list services.sms in the runtime-services stability matrix, and gate the matrix and every label it publishes (#9684) - #9753

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-9684-versioning-matrix
Aug 19, 2026
Merged

docs(kernel): list services.sms in the runtime-services stability matrix, and gate the matrix and every label it publishes (#9684)#9753
os-steve merged 1 commit into
mainfrom
claude/issue-9684-versioning-matrix

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes#9684

versioning.mdx's "Current Matrix" carried seven rows for eight pagesservices.sms missing from a fifth enumeration of the same chapter, the third landing of this defect class on one chapter in a day: #9604 added it to two index lists, #9630 corrected the accessor/slot mismatch, and each was found by a human re-reading the chapter rather than by machinery. So the row is the small half; the gate extension is the point.

The row

| services.sms | stable |, inserted between email and settings so the matrix keeps following meta.json's nav order. The label is derived, not chosen: sms-service.mdx declares - **Stability:** stable, which is the same source the other seven rows agree with (verified for all eight — no existing row contradicts its page, so there was nothing to normalise).

The gate — two additive limbs, five existing checks untouched

scripts/check-runtime-services-index.mjs:

  • check 6 — the matrix vs the pages on disk. Membership plus order, exactly as check 3 holds the chapter list: the matrix follows meta.json's pages order today and that convention is the only thing telling the next author where a new row goes.
  • check 7 — every published stability LABEL vs the page that declares it, on both tables that publish one: the matrix and the services.* table in kernel/index.mdx. This is the half with lasting value. Membership checking catches a missing row; this catches a wrong one — a table that lists the page and contradicts it, which a reader plans an upgrade against. The kernel table was carrying an unchecked stability column all along; it agrees today, and now it has to.

The page's own - **Stability:** label bullet is the source of truth (it is what a reader lands on), so a disagreement is always reported against the table, and a page that declares no label at all is a finding — the tables cannot be checked without it.

Deliberately not checked, and recorded as such in the script header: the label vocabulary. Filed separately as #9751 with sizing — deriving stable/experimental from one of the two legends would make this gate the authority on which labels exist and would pick a winner between two hand-written legends nobody has declared canonical.

#9629 is not decided here

STABILITY_ROW_RE is anchored to ^| table rows. The Source-of-Truth list's extra Security: row — the one #9634 deliberately kept out of the gate, because encoding it either way pre-judges an open maintainer question — is prose, so it cannot enter any set this limb builds; and the expected set is still derived from the pages on disk, never from a hand-written list, so no allowlist entry was introduced. Two self-test assertions pin it: readStabilityRows over the fixture's index.mdx (which carries a Security: row) returns zero rows, and no finding on a failing tree mentions Security.

Enumeration census (the measurement that chose this shape)

Six enumerations of this chapter's eight services.* pages exist, found by scanning every file naming five or more of the accessors:

#whereheld?
1runtime-services/meta.jsonpagesyes (checks 1, 3)
2runtime-services/index.mdx chapter listyes (checks 2, 3)
3kernel/index.mdxservices.* tablemembership + href since #9634; its stability column now too
4the *-service.mdx files on diskthe derivation source
5runtime-services/index.mdx Source-of-Truth listdeliberately not held (#9629)
6versioning.mdx "Current Matrix"this PR

No seventh. .claude/workflows/docs-accuracy-audit.js lists all 11 chapter files, but as part of a repo-wide docs enumeration already held by check:docs-audit-scope. kernel/services.mdx and kernel/services-checklist.mdx enumerate the kernel registry / CORE_SERVICE_PROVIDER, a different and larger set. Since exactly one unheld membership enumeration remained, a bespoke limb beats a generalised "every enumeration agrees" check — the generalisation is precisely what would drag in row 5 and decide #9629 by accident.

Verification

Self-test 17 → 27 assertions; every new limb observed red on a real mutation of the real tree and silent on the correct one, with byte-identical restores:

Gates run locally at 8fc81320b, all green: check:runtime-services-index, check:doc-anchors, check:docs-audit-scope, check:docs-redirects, check:role-word, check:published-readme-links, check:nul-bytes, check:required-contexts, check:workflow-status-functions, check:node-version, check:shard-attestation, check:type-check-coverage, check:cross-package-test-inputs, and spec check:liveness / check:empty-state / check:variant-docs / check:strictness-ledger. One derived gate was not run: check:type-check-debt, whose --re-measure refuses to run without the built closure of all workspace packages (0 dist/ dirs in a fresh worktree) and which a docs + script + workflow-comment diff cannot move; CI runs it after the closure build.

No changeset: nothing published changes (docs page, gate script, one workflow comment) — skip-changeset, matching #9634 and #9681.

Also filed while sweeping: #9752IEmailService's JSDoc claims alignment with a CoreServiceName member that does not exist. Out of scope here; not addressed in this PR.

Generated by Claude Code


Generated by Claude Code

…rix, and gate the matrix and its labels (#9684)
`versioning.mdx`'s "Current Matrix" carried seven rows for the chapter's eight
pages: `services.sms` was missing from a FIFTH enumeration of the same chapter,
after #9604 fixed it in two index lists and #9630 fixed the accessor/slot
mismatch. Every enumeration of this chapter that the gate does not hold has
drifted, and each one was found by a human noticing.
So the row is the small half. `check-runtime-services-index.mjs` gains two
additive limbs, leaving the five existing checks untouched:
- check 6 holds the "Current Matrix" to the pages on disk — membership and
order, exactly as check 3 holds the chapter list, because the matrix follows
meta.json's nav order and that convention is the only thing that tells the
next author where a new row goes;
- check 7 holds every published stability LABEL to the page's own
`- **Stability:** <label>` bullet, on BOTH tables that publish one — the
matrix and the `services.*` table in `kernel/index.mdx`. This is the half
with lasting value: membership checking catches a MISSING row, this catches a
WRONG one, which is a live lie a reader plans an upgrade against.
The page is the source of truth for its own label, so a disagreement is always
reported against the table, and a page that declares no label at all is a
finding.
The `services.sms` label is derived, not invented: `sms-service.mdx` declares
`- **Stability:** `stable``, which is what the row now says.
#9629 is untouched: the stability row parser is anchored to `^|` table rows, so
the Source-of-Truth list's prose `Security:` row — the one #9634 deliberately
kept out of the gate — cannot enter any set here. The self-test pins that on
the parser and again on a failing tree.
Self-test 17 -> 27 assertions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja
@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation ci/cd labels Aug 18, 2026
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 18, 2026
@claude

claudeBot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

✅ PM ACCEPT — #9684 / PR #9753

Verified independently: 3 files +210/-17, zero governed-surface hits, no non-green gates (two still running).


⭐ H1 — the census chose the shape, and it chose against generalising

Six enumerations of this chapter's eight services.* pages, found by scanning every file in the tree naming five or more accessors:

#enumerationheld?
1runtime-services/meta.jsonpages✅ checks 1+3
2runtime-services/index.mdx chapter list✅ checks 2+3
3kernel/index.mdxservices.* table⚠️ membership+href since #9634stability column unheld
4the *-service.mdx files on diskthe derivation source
5runtime-services/index.mdx Source-of-Truth list⛔ deliberately unheld (#9629)
6versioning.mdx "Current Matrix"this card

And the conclusion that matters:

Because exactly ONE unheld membership enumeration remained, I shipped a bespoke limb rather than a generalised "every enumeration agrees" check — the generalisation is exactly what would drag row 5 in and decide #9629 by accident.

That is my H1 question and my H3 warning answered by the same measurement. I said the census decides bespoke-vs-generalised and I genuinely did not know which way it would go; it went to bespoke for a reason, not by default. A generalised check would have looked more principled and quietly resolved an open maintainer question.

The seventh was ruled out with reasons rather than by not finding it: .claude/workflows/docs-accuracy-audit.js (governed, and already held by check:docs-audit-scope as part of a repo-wide enumeration), kernel/services.mdx and services-checklist.mdx (the kernel registry / CORE_SERVICE_PROVIDER — a different and larger set), CHANGELOG and docs/audits/* (historical records).

H2 — checkable, and nothing needed normalising

All 8 pages carry a parseable - **Stability:** \label`bullet at line 8. All 7 pre-existing matrix rows **and** all 8 kernel-table stability cells already agreed with their pages — **no source disagreement to report, nothing normalised**, and thesmslabel was **derived** fromsms-service.mdx` rather than chosen. Ruling 3 discharged exactly.

⭐ And the bonus is a real one: kernel/index.mdx's stability column was unheld.#9634 held that table's membership and hrefs; its labels were a second published copy of the same fact with nothing behind them. Catching that while auditing a different table — and closing the class rather than the instance — is the difference between fixing #9684 and fixing what #9684 is an instance of.

⭐ H3 — you proved the avoidance instead of asserting it

STABILITY_ROW_RE is anchored to ^| table rows; the Source-of-Truth list's Security entry is prose (- Security: \path``), so it cannot enter any set the new limbs build — and the expected set is still derived from the pages on disk, never from a hand-written list, so no allowlist entry exists.

Then the part I did not ask for and should have: two self-test assertions pin itreadStabilityRows over a fixture index.mdx that carries a Security row returns zero rows, and no finding on a failing tree matches /[Ss]ecurity/. So the promise "this change does not decide #9629" is now enforced rather than believed, and a future widening that breaks it goes red.

H4 — four mutations, and one of them applies yesterday's lesson

(a) versioning.mdx reverted → exit 1, exactly one finding, naming the #9684 defect verbatim. (b) queue's matrix label flipped → "the table, the page is the source of truth". (c) kernel table's sms row flipped → red. (d) audit-service.mdx stripped of its Stability bullet → red against the page.

And (c) carries a second result you called out:

this also disproves a false-absence of the #9681 kind: the kernel table's 8 rows really are parsed on the real tree, not a silent zero

That is exactly the trap #9681's dev hit hours ago — a narrowed regex making audit report a false absence because a registration spanned two lines. Designing a mutation to prove your parser sees the rows, rather than only that it reacts to them, is the lesson carried forward rather than re-learned.

Plus per-limb ablation (if (false && …)): limb 6 red on exactly its 3 assertions, limb 7 red on exactly its 3 — proving the two new limbs are independent rather than one masking the other. Self-test 17 → 27.

On the gate not run, and on labels

check:type-check-debt's --re-measure refuses without the built closure (0 dist/ in a fresh worktree; it names 55 missing type entry points and points at #6376). Skipping a full monorepo build under the shared lock for a gate a docs + gate-script diff cannot move is the right trade, and naming it beats omitting it.

And skip-changeset was applied with POST rather than a set-replacing PUT, so the labeler bot's three survived — verified by read-back. A label write that silently clobbers a bot's labels is its own small incident; this is the second dev today to get that right deliberately.

#9751 and #9752

#9751 — the stability vocabulary (stable/experimental) is hand-written in two legends (index.mdx's "Stability Legend" table and versioning.mdx's "Stability Labels" bullets) and nothing holds them to each other or to the labels in use, so an invented label like beta stays green even after this PR. Deliberately left out with the right reason: deriving the vocabulary from one legend makes the gate the authority on which labels exist and picks a winner between two legends nobody has declared canonical. Sizing given (~20-line limb + self-test once the maintainer says which legend is canonical), and recorded as deliberately-not-checked in the script header so the next reader finds the decision rather than the gap. Escalating.

#9752packages/spec/src/contracts/email-service.ts:11 claims alignment with a CoreServiceNameemail member that does not exist (email is subsumed under notification). The slot is real and registered; only the JSDoc's provenance claim is false. Same class as #9630, and you flagged the trap in the plausible fix: adding the enum member would invent a core-service identifier nobody registers. Noted that it sat in the 2026-06 audit followups unfiled until now. Queued.

Verdict: ACCEPT. Arming once the two running gates converge.


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review August 18, 2026 23:42
@os-steve
os-steve added this pull request to the merge queueAug 18, 2026
Merged via the queue into main with commit 1a3336aAug 19, 2026
25 checks passed
@os-steve
os-steve deleted the claude/issue-9684-versioning-matrix branch August 19, 2026 00:23
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddocumentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

runtime-services/versioning.mdx's stability matrix omits services.sms — a fourth enumeration of the chapter that #9634's gate does not hold

2 participants

@os-steve@claude