Found while implementing #12881 (the runtime-interface-only comment blind spot). Filed unassigned. Not fixed there — the fix changes verdicts across the whole changeset stock and deserves its own measurement.
What happens
findMigrationPrescription's framed-table arm opens a framed region at a heading matching MIGRATION_FRAMING_RE and closes it at the next heading of any level. So a ## Migration section that organises its rewrite tables under ### sub-headings — the ordinary way to write a two-part rename — loses its framing before the first table row is read.
Measured on e44d54a59 through the gate's own exported function:
A '## Migration' + table -> { branch: 'framed-table', ... }
B '## Migration' + '### Method namespace' + table -> null
C '## Migration' + '| Wrote | Write instead |' table -> { branch: 'framed-table', ... }
A and B differ by one sub-heading line. The header-framed arm does not rescue B either: OLD_COLUMN_RE was derived from the stock (Wrote, you wrote, Removed, Retired, and the Chinese equivalent) and does not include before, which is what B's header row says.
Why it matters
runtime-interface-only and no-migration-prescription both inherit the prescription refusal — that inheritance is what makes the first a narrowing of the second rather than a fifth way around it. A changeset that ships a real consumer-rewrite table therefore should not be able to hold either exemption.
Live instance: PR #12885's changeset carries a ## Migration section with two | before | after | tables under ### sub-headings, and findMigrationPrescription returns null on it (measured 2026-08-28). Its runtime-interface-only disposition is honest on its own terms, and it now passes the gate — but it passes without the prescription arm ever having been consulted, which is not the same as passing it.
This is the fourth spelling of one recurring shape; the gate's header records the first three, each repaired after a real changeset held an exemption on the gap.
Suggested direction (not a decision)
Track heading DEPTH so a framed region closes at the next heading of the same or shallower level, rather than at any heading. Widening OLD_COLUMN_RE to include before is the smaller, more local alternative and would also catch this row, but it does not address nesting.
Either change refuses changesets that pass today, so it wants the same treatment the earlier repairs got: measure the stock before and after, and read the rows that move.
Evidence
scripts/check-adr-0087-registration.mjs, findMigrationPrescription — the framedSection assignment inside the heading branch of the second loopOLD_COLUMN_RE / headerFramesRewrite for the second half- The live changeset:
.changeset/adr0006-d2-client-environments-namespace.md on branch claude/issue-12866-adr0006-d2-sdk-environments
Generated by Claude Code
Found while implementing #12881 (the
runtime-interface-onlycomment blind spot). Filed unassigned. Not fixed there — the fix changes verdicts across the whole changeset stock and deserves its own measurement.What happens
findMigrationPrescription's framed-table arm opens a framed region at a heading matchingMIGRATION_FRAMING_REand closes it at the next heading of any level. So a## Migrationsection that organises its rewrite tables under###sub-headings — the ordinary way to write a two-part rename — loses its framing before the first table row is read.Measured on
e44d54a59through the gate's own exported function:A and B differ by one sub-heading line. The header-framed arm does not rescue B either:
OLD_COLUMN_REwas derived from the stock (Wrote,you wrote,Removed,Retired, and the Chinese equivalent) and does not includebefore, which is what B's header row says.Why it matters
runtime-interface-onlyandno-migration-prescriptionboth inherit the prescription refusal — that inheritance is what makes the first a narrowing of the second rather than a fifth way around it. A changeset that ships a real consumer-rewrite table therefore should not be able to hold either exemption.Live instance: PR #12885's changeset carries a
## Migrationsection with two| before | after |tables under###sub-headings, andfindMigrationPrescriptionreturnsnullon it (measured 2026-08-28). Itsruntime-interface-onlydisposition is honest on its own terms, and it now passes the gate — but it passes without the prescription arm ever having been consulted, which is not the same as passing it.This is the fourth spelling of one recurring shape; the gate's header records the first three, each repaired after a real changeset held an exemption on the gap.
Suggested direction (not a decision)
Track heading DEPTH so a framed region closes at the next heading of the same or shallower level, rather than at any heading. Widening
OLD_COLUMN_REto includebeforeis the smaller, more local alternative and would also catch this row, but it does not address nesting.Either change refuses changesets that pass today, so it wants the same treatment the earlier repairs got: measure the stock before and after, and read the rows that move.
Evidence
scripts/check-adr-0087-registration.mjs,findMigrationPrescription— theframedSectionassignment inside the heading branch of the second loopOLD_COLUMN_RE/headerFramesRewritefor the second half.changeset/adr0006-d2-client-environments-namespace.mdon branchclaude/issue-12866-adr0006-d2-sdk-environmentsGenerated by Claude Code