The codemod and the migration of the 23 line-addressed invocations
The item that removes the live exposure. Everything before it builds capability; this one spends it.
The measured surface in site/content, re-counted at milestone review:
The item that removes the live exposure. Everything before it builds capability; this one spends it.
The measured surface in site/content, re-counted at milestone review:
a97869dd4bc689efb30c581a138fd83bb12c680110d40fe65Three published references — runes/file-ref.md:51, runes/drawer.md:155 and runes/file-ref.md:75 — carried a file-ref labelled SiteConfig pointing at packages/types/src/theme.ts lines 74–125. SiteConfig is not in that file (it is at packages/types/src/config.ts:42-148), and theme.ts is 104 lines long, so 21 of the 52 requested lines did not exist. The drawer opened onto the back half of ThemeManifest, the whole of LayoutDefinition, and the start of ComponentDefinition.
On the documentation page for the rune whose addressing model is the subject of the spec.
This item is the bug's fix (2). Fix (1) has already landed (refrakt-md/refrakt#639) — the ranges were corrected on their own branch rather than waiting on this milestone, because the file-ref doc page was teaching the broken pattern by example. That correction restored accuracy and left the addressing exposure exactly where it was.
So by the time the codemod runs these are ordinary migrations, pointing at the right files with the right ranges, and the live ones convert like the rest of the live set. The bug closes here, on the anchoring rather than on the ranges.
Two corrections to the bug's original account, both recorded on it:
file-ref.md:51 renders. The other two sit inside ```markdoc fences, so they were wrong examples rather than wrong drawers. For the codemod this matters: a fenced invocation is not a resolvable target, so it cannot be verified byte-identically and must be rewritten by hand to match whatever the live ones become.file-ref.md:40, labelled SiteThemeConfig and therefore missed by a SiteConfig grep. It anchors to theme.ts, not config.ts.Converting 23 invocations by hand is tedious and exactly the kind of change where a slip reintroduces the bug being fixed. The codemod reads each current slice, infers an anchor from its first meaningful line, rewrites the invocation, and verifies the new resolution produces a byte-identical slice — refusing to rewrite when it does not.
The diff stays reviewable; the verification is what makes it trustworthy.
reindent (WORK-589), or every nested target fails verification for a difference the codemod itself introduced.highlight= needs those coordinates preserved or rewritten as highlight-match= (D13), and byte-identical verification covers the slice only, not the highlight. {% snippet path="…/lang-map.ts" lines="10-40" linenumbers=true highlight="18-22" /%} is live on the snippet doc page and has to become something.D8 defers /…/ lexing from WORK-597 — perhaps 15 more lines, causing the single silent-wrong case and most of the 62 refusals in the measurement. Pick it up only if the migration surfaces refusals that need it. Do not do it speculatively.
--fix codemod converts lines= invocations to anchors, verifying byte-identical output and refusing to rewrite when it differsreindent is appliedhighlight= or linenumbers= is either preserved with its coordinates or rewritten to highlight-match=, with its own verification separate from the slice checksite/content are migrated by the codemod, or individually justified as intentionally line-addressedlines= form — the codemod does not attempt them, and a fenced invocation is never reported as an unverifiable refusalsymbol="SiteConfig" on the three in config.ts, symbol="SiteThemeConfig" on the one in theme.ts — and BUG-020 is closedreviewed markers on anything it migratesRun the codemod, read every hunk, and treat a refusal as information rather than an obstacle — a refusal means the anchor engine could not reproduce the slice, which is exactly the case where a human should look at what that snippet was pointing at.
Expect some of the 23 to be legitimately line-addressed: several are demonstrations on the snippet doc page itself, deliberately showing the lines= form. Those should keep it and say so, which is why the criterion reads "migrated, or individually justified".
section and paired are what make the non-TypeScript half of site/content addressable at allreindent ordering the verification depends onDo not auto-stamp review markers (SPEC-134 D8). A marker asserting that a human reviewed 23 regions nobody looked at is a false claim in precisely the shape SPEC-134 exists to prevent. The criterion above is stated negatively on purpose.
This item is also the input to D15: record which languages and formats came up, because that is what decides the shape of the config surface if one ever ships.
site/content/runes/drawer.md, site/content/runes/file-ref.md — the three affected drawersCompleted: 2026-09-24
Branch: claude/v0-37-0-review-vqpl41 PR: refrakt-md/refrakt#648 (batched with WORK-594)
packages/cli/src/commands/migrate-snippets.ts (new) — refrakt migrate snippets [--fix]. Anchor inference, byte-identical verification, refusal reporting, and the per-language tally.packages/cli/test/migrate-snippets.test.ts — 17 tests, most of them about refusing rather than rewriting.site/content; BUG-020's four references anchored.snippet.md itself, the page that documents lines=. One invocation was rewritable, and it was BUG-020's. This item's own Approach predicted it — do not read the count as a shortfall.theme.ts / SiteThemeConfig one sat inside the lines= documentation example, so anchoring it would have left that section without an example. I first left it and was going to check the criterion off regardless. The right fix was to repoint the example at CHANGELOG.md — a file with no symbols, which is when a line range is actually the right tool — freeing the real reference to be anchored. Both criteria met properly rather than one waived.file-ref page, both fixed here: prose claiming symbol= had not landed, and the lines= example pointing at a source declaration — teaching the exact pattern this bug is about.reindent, pinned by a test on a nested target. Get it backwards and every nested target fails verification for a difference the codemod introduced./…/. It stays deferred, per the item's instruction not to do it speculatively.4858 tests pass. refrakt validate --site main: 0 errors, 0 warnings.