diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 6bc870af..ee17846f 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -7690,5 +7690,20 @@ gate is the wrong shape, validation of the walk is the right one. > **Verify the fix against THIS pair.** Both branches are unlanded and anchored, so the collision is reproducible on demand: `git merge-tree --write-tree w3-log-write-failure w3-store-privilege-preflight` and read the merged snapshot. A fix that does not red on that pair has not been shown to work. **Cluster:** Developer tooling / CI. **Priority:** P2. **Verdict:** build. **Severity:** conditional -- no product effect today, but it would ship a console contract whose version does not identify it, which is exactly what the seam exists to prevent. +## 1221. A doc lint crashes when printing a hit that contains a glyph, so it is unreadable exactly when it fires + +> 🔢 **Filed 2026-08-11 -- found by Session B while fixing an unrelated false positive in the same file.** Value **5/10** -- Difficulty **2/10** -- _quick win_. `scripts/docs/asvs_tally_lint.py` raises `UnicodeEncodeError: 'charmap' codec can't encode character` on a stock Windows **cp1252** console when it prints a hit whose text contains a glyph. It fires **only on the failure path** -- printing the hits -- so it is **INVISIBLE WHILE THE LINT IS GREEN**, and it converts a legible FAIL into a traceback at exactly the moment somebody needs to read which document tripped it. **A gate that is correct until it has something to say, and then unreadable.** + +> **WHY THIS IS NOT MORE EVIDENCE UNDER #1030, WHICH WAS THE OBVIOUS CALL AND IS WRONG.** #1030 is *"keep the corpus cp1252-clean, because per-file gating lets the class recur"*. **That cannot fix this, because the corpus this lint reads is REQUIRED to contain cp1252-unsafe characters.** Measured: it walks `base.rglob("*.md")` over `docs/` (`:245`) and explicitly reads `docs/BACKLOG.md` (`:63-64`) -- the file whose **sanctioned banner alphabet** is CLAUDE.md §11's one machine-parsed holdout, every glyph of which is cp1252-unsafe. Its own comment at `:153` records it already redding on backlog content. So a clean corpus is not achievable *here* even in principle, and only making the tool robust addresses it. **#1030 is about the content; this is about the instrument.** Both are needed and neither substitutes. + +> **The decision this needs, and it is a real one rather than a patch.** Either a repo script **forces UTF-8 on its own stdout** (the engine CLI already does exactly this -- `messagefoundry/__main__.py` hardens `sys.stdout`/`sys.stderr`, and the harness and a bench script carry the same remedy), **or** the crash is treated as the corpus's problem and the script stays naive. Those have different blast radii: the first makes every repo script robust and is a one-line idiom already proven in-tree; the second is unachievable for any tool that reads the ledger. `PYTHONIOENCODING=utf-8` works around it either way and is **not** a fix, because CI and a developer shell will not both set it. + +> **MEASURED, AND IT IS NOT AN EDGE CASE WAITING FOR AN UNLUCKY DOCUMENT.** `main`'s `docs/BACKLOG.md` -- the file this lint names at `:63-64` -- carries **799 cp1252-unsafe codepoints across 29 distinct characters**, including **`U+2192` x140**, `U+1F522` x171, `U+2705` x138, `U+26A0` x91 and `U+26D4` x79. So the crash is reachable from any hit whose line carries one, and there are **140 chances from the arrow alone**. That is a large fraction of the possible failures in the primary corpus, not a corner. *(Count codepoints, not UTF-16 units: a first pass reported `U+D83D` x193, which is a SURROGATE HALF and not a character present in the file -- grepping for it finds nothing.)* + +> **FOURTH SURFACE IN ONE DAY**, which is the argument for doing it structurally rather than one file at a time: a `U+21D2` in a `ci.yml` comment, **three pre-existing `U+2192` already on `main` in that same file**, a `U+21D2` in the coordinator playbook, and now this. The first three are #1030's subject; this one is not. + +> **Scope note:** the fix belongs with whichever of the two answers is chosen, and the failure path is the place to prove it -- **make the lint FIRE on a document containing a glyph and read the output**, because a green run exercises none of this. That is the whole point of the item. + +**Cluster:** Developer tooling / CI. **Priority:** P3. **Verdict:** build. **Severity:** minor -- no product effect; it degrades a working gate into an unreadable one at the moment it matters.