feat(engine): give notes a context window - #5
Merged
Conversation
A note's excerpt was the raw regex match and nothing else, which says
nothing useful when the match is one character:
-:152:125: info em-dash Em dash — an AI punctuation tell.
excerpt: —
You had to open the file and count to column 125 to learn anything. The
em-dash rule made this obvious, but it hit every short match: vibrant,
nestled, anything whose pattern is a single word.
Notes now carry a context field — the match bracketed inside ~40
characters either side, trimmed back to word boundaries with an ellipsis
on any cut end. Human output shows it in place of the bare match.
excerpt is unchanged and still the bare match, so the engine spec that
pins column against excerpt.split.first keeps guarding the
Regexp.last_match clobbering bug it was written for.
Two details worth naming. The window is sliced from the text as written,
not the blanked copy, so --markdown still shows real code and URLs in
context even though they were blanked before matching; blank_markdown is
length-preserving, so offsets line up either way. And a match already 40
characters long returns alone rather than padded — em-dash-overuse spans
can run a whole paragraph, and 80 more characters makes those worse, not
clearer.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
benjaminjackson
force-pushed
the
note-context
branch
from
July 28, 2026 02:42
4265f02 to
971df2e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A note's
excerptwas the raw regex match and nothing else, which says nothing useful when the match is one character:You had to open the file and count to column 125 to learn anything. The
em-dashrule made this obvious, but it hit every short match —vibrant,nestled, anything whose pattern is a single word.What changed
Notes carry a new
contextfield: the match bracketed inside ~40 characters either side, trimmed back to word boundaries with…on any cut end. Human output shows it in place of the bare match.excerptis unchanged and still the bare match — still whatcolumnpoints at — so the engine spec that pinscolumnagainstexcerpt.split.firstkeeps guarding theRegexp.last_matchclobbering bug it was written for.Two details worth naming
The window comes from the text as written, not the blanked copy.
blank_markdownreplaces each non-newline character with one space, so offsets are identical either way — but a window over blanked text shows code and URLs as a run of spaces. Slicing from the original means--markdownstill shows you real code in context even though it was blanked before matching:A match already 40 characters long returns alone, unpadded.
em-dash-overusespans can run a whole paragraph; bolting 80 more characters onto one makes the worst case worse, not clearer.Testing
187 examples, 0 failures. New specs cover a match mid-sentence, at offset 0, at end of text, one wrapping across a source line, the long-match short-circuit, and the pre-blanking-source decision — that last one is easy to undo silently in a refactor, since
line/columnstay correct and only the excerpt turns into spaces.Scanning the project's own README end-to-end, the longest window is 97 characters and none open mid-word.
Docs updated in the same commit per the repo's rule:
README.md(sample regenerated by running it),docs/SPEC.md, the--helpbanner key list, andCHANGELOG.md.🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 5 noreply@anthropic.com