reindent (D16)
Strip the slice's common leading whitespace. Every nested target carries one or two levels of indentation it did not ask for and renders with a ragged left edge that wastes horizontal space a code block does not have.
Removing the common prefix preserves relative structure exactly, so the result stays valid in indentation-significant languages: a dedented Python method is a function, a dedented YAML subtree is that subtree rooted.
The default follows the addressing mode, for the same reason D9's does. An author writing lines="10-40" has seen the file and chosen those columns; changing how they render would be a silent visual change to all 23 existing invocations. An author writing symbol="…" never saw a column number — the resolver picked the region, so it owns presenting it legibly.
The coordinate frame stays (D13)
linenumbers and numeric highlight are currently defined in terms of lines=. Remove lines= and neither has a frame. The resolver already produces a [start, end] in file coordinates, so keep it: linenumbers continues to start at start, highlight continues to mean file lines. No new concept, no breakage, and the displayed numbers stay meaningful as a pointer back into the real file.
What changes is that a numeric highlight under an anchor is no longer something an author can write from knowledge. Hence highlight-match=: one or more regexes, each highlighting the lines they match within the resolved slice.
Numeric highlight stays legal and stays useful with lines=. Under an anchor it carries the old exposure, and the docs should say so plainly rather than forbidding it.
Acceptance Criteria
reindent strips the slice's common leading whitespace, defaulting on for symbol / match and off for lines, covered by a test on a nested targetreindent=false and reindent=true force either way- A dedented indentation-significant slice remains structurally valid, covered by a Python method and a YAML subtree
linenumbers and numeric highlight stay in file coordinates under an anchorhighlight-match accepts one or more regexes and highlights matching lines within the resolved slice- The docs state that numeric
highlight under an anchor carries the coordinate exposure anchoring otherwise removes reindent is applied after the resolved [start, end] is fixed, so it never shifts the coordinates linenumbers and highlight read
Approach
Keep reindent as a distinct post-resolution step with its own entry point, rather than folding it into extraction. WORK-590 must compare slices before it runs and WORK-591 must hash after it runs — both need to call the pipeline at a chosen point, which an inlined transform does not allow.
Blocked by
- WORK-587 — there is no resolved slice to present without it
Notes
The ordering constraint is worth stating twice because it is easy to get backwards and produces a confusing failure in each direction:
- WORK-590's codemod verifies a rewritten invocation produces a byte-identical slice. That comparison runs before
reindent, or every nested target fails verification for a difference the codemod introduced. - WORK-591's hash applies
reindent first, so that moving a function into a class — which shifts every line two columns without changing a character of content — does not fire the marker.
References
- SPEC-131 — D13 (
highlight / linenumbers keep file coordinates; highlight-match is the anchor-native form), D16 (reindent, its default, and the codemod interaction) - SPEC-134 — normalization step 1, which is this item's
reindent packages/runes/src/tags/snippet.ts — the schema carrying linenumbers and highlight, and their lines=-framed descriptions
Resolution
Completed: 2026-09-24
Branch: claude/v0-37-0-review-vqpl41 PR: refrakt-md/refrakt#647 (batched with WORK-587 and WORK-588)
What was done
packages/runes/src/lib/present.ts (new) — reindent, shouldReindent, highlightMatchLines, parseHighlightMatch, formatHighlight.- Wired into
snippet-pipeline.ts after the resolved range is fixed, and into the file-ref drawer builder. reindent and highlight-match attributes on both runes.
Notes
- These are separate entry points on purpose, as this item's Approach requires. WORK-590's codemod compares slices before
reindent or every nested target fails verification for a difference the codemod itself introduced; WORK-591's hash applies it first so that moving a function into a class does not fire the marker. An inlined transform would allow neither. reindent does not guess a tab width. A slice mixing tabs and spaces has no common prefix and is returned unchanged — manufacturing one would change bytes the author did not ask to change. Pinned by a test.- The coordinate frame survives anchoring. An anchored slice now emits
lines="start-end" from the resolved range, so linenumbers keeps starting at the real file line. highlight-match offsets are converted from slice coordinates into that same file frame before reaching the fence. - Defaults follow the addressing mode, so none of the existing line-addressed invocations change how they render — covered by a test asserting a
lines= slice keeps its leading indentation.
Verification
4820 tests pass, 0 failures.