v1.108.238 - a YAML symbol is located at its own key's line, or refuses
Line numbers for YAML symbols came from a forward text scan with three compounding defects. Measured against .github/workflows/health-radar-comment.yml, a five-key step block resolved to lines 31 / 32 / 33 / 34 / 35 and only the last was right:
- Substring matching.
needle in lineletid:answer forrun-id:. - A cursor starting past the item's own key. A list item is identified by its
name:line, and the walk then began on the following line, so the item's ownnamecould never match itself and bound to a nestedname:further down the block. - A silent fabricated fallback. Not-found returned
after + 1— the next line presented as a located match. Two of those five keys were fabricated that way, and because each wrong answer advanced the cursor, the errors cascaded through every sibling after.
True line numbers now come from YAML node marks (yaml.compose), with an anchored key search as the fallback for documents that will not compose. A key that cannot be located reports no line and a zero byte extent rather than a plausible wrong one.
Heuristic repair was tried first and abandoned on evidence
Anchoring the match and refusing on a miss moved agreement from ~73% to 96.5%. An attempt to close the remainder, by advancing a parent cursor past a nested block, made it worse (89.6%): a text cursor has no notion of where a block ends, so each heuristic traded one class of mislocation for another.
The first node-mark implementation silently did not run
It referenced yaml.compose, but this module imports yaml only as a local _yaml. That raised NameError, a broad except Exception turned it into an empty map, and the fallback kept answering while the measurement still looked healthy. The handlers are now narrow (ImportError / YAMLError) so a programming error surfaces instead of degrading, and a test asserts the map is non-empty.
Validation
Against a PyYAML node-mark oracle, 462 of 462 comparable symbols agree — but that check shares a mechanism with the fix, so the load-bearing number is the independent one. Asserting that the located line actually begins with its key, with no node marks involved: 0 of 4773 symbols land on a wrong line, against roughly a quarter before, with 9 honest refusals.
Known issue, now visible rather than hidden
on: is coerced to a YAML 1.1 boolean, so a workflow's on key is named True and cannot be located. It now refuses instead of reporting a fabricated line. Being fixed separately.
_find_line is retained for the Ansible task/role paths, where the search target is free text with no key to anchor on. Nothing has been measured there, so nothing was changed there.
Upgrade note
No INDEX_VERSION bump; existing indexes keep the old line numbers until re-parsed.
Verification status: full suite 6855 passed / 7 skipped / 1 failed. The single failure is test_v1_108_207::test_warms_sentence_transformers, which fails identically on the unmodified previous release commit: it is environment-coupled and goes red on any machine without the optional sentence-transformers dependency. Not related to this change and not a regression.