Diagnostics
diagnostics
Pure, bounded diagnostics for anchor mismatches.
When an anchor fails to match, the caller needs to know why: a tab where spaces were expected, a trailing space run, a non-breaking space, an em dash instead of a hyphen, or simply the wrong line. This module answers that question with side-effect-free helpers: no filesystem, no subprocess, no network. Inputs are already-read lines plus the anchor string.
Every output is bounded (MAX_SNIPPET_CHARS, MAX_DIAGNOSTIC_CHARS) and
every scan is bounded (MAX_CANDIDATE_LINES) so a pathological input can
neither blow up the message nor the runtime.
Candidate
dataclass
A near-miss window found in the scanned lines.
Attributes:
| Name | Type | Description |
|---|---|---|
line |
int
|
1-based line number where the window starts. |
ratio |
float
|
similarity ratio against the anchor, in |
text |
str
|
the raw window text, terminators excluded. |
Source code in packages/axm-edit/src/axm_edit/core/diagnostics.py
NearMiss
dataclass
A rendered explanation for an anchor that matched nothing.
Attributes:
| Name | Type | Description |
|---|---|---|
candidate |
Candidate | None
|
the closest window found, |
message |
str
|
a single bounded line naming the difference, every invisible or non-ASCII character replaced by its marker. |
Source code in packages/axm-edit/src/axm_edit/core/diagnostics.py
closest_candidate(lines, old)
Return the line window closest to the old anchor, or None.
The scan slides a window of the anchor's line count over the first
MAX_CANDIDATE_LINES lines and keeps the best similarity ratio. A window
below SIMILARITY_THRESHOLD is never reported: no best-effort guess.
Ties are resolved deterministically in favour of the lowest 1-based line
number, thanks to the strictly-greater comparison.
Source code in packages/axm-edit/src/axm_edit/core/diagnostics.py
explain_difference(expected, actual)
Explain, on a single bounded line, how actual differs from expected.
The message names the 1-based column of the first difference, the two
offending characters (non-ASCII punctuation is routed through the Unicode
naming helper) and both sides rendered by :func:render_invisibles. The
result never exceeds MAX_DIAGNOSTIC_CHARS.
Source code in packages/axm-edit/src/axm_edit/core/diagnostics.py
explain_near_miss(lines, old)
Assemble the near-miss report for an old anchor that matched nothing.
Three branches, in order: the anchor swallowed a line break (the message
names the first of the two joined lines and carries the <LF> marker);
a similar window exists (the message names its 1-based line and contrasts
both sides through :func:render_invisibles, so a tab, a trailing space
run, a non-breaking space or a Unicode punctuation swap is named instead
of being dumped raw); or nothing is similar enough, in which case the
candidate is None and the message says so explicitly.
The returned candidate is the one :func:closest_candidate produced,
unchanged, and the message never exceeds MAX_DIAGNOSTIC_CHARS.
Source code in packages/axm-edit/src/axm_edit/core/diagnostics.py
format_match_lines(match_lines, limit=MAX_LISTED_MATCH_LINES)
Render match line numbers, keeping at most limit of them.
The kept numbers are comma-joined in their original order; whatever the
sequence holds beyond limit is summarised by a trailing
(+N more) suffix instead of being dumped. A sequence of limit
numbers or fewer renders as the plain comma-joined list, with no suffix.
Pure by construction: it reads nothing but its arguments, so an anchor repeated hundreds of times still yields a bounded, actionable list.
Source code in packages/axm-edit/src/axm_edit/core/diagnostics.py
render_invisibles(text)
Render text with every invisible or non-ASCII character named.
Tabs become <TAB>, a trailing space run becomes one <SP> marker per
space, U+00A0 becomes <NBSP>, line terminators become <CR>/<LF>
and any other non-ASCII character becomes its Unicode name (or the
<U+XXXX> fallback). Ordinary printable ASCII is passed through
untouched. The result never exceeds MAX_SNIPPET_CHARS.