docs(hyphens): the `-<br>` break is a written-down limit, with the repair's price named (#457)
#374's last open item was a decision rather than a patch: amend `SplitWord.split`'s contract so a break
inside one cell is in scope, or accept a floor of about 4 per 100 pages and write it down beside the other
limits. The decision was to document it, so this is a comment and two tests — no runtime path moves, and
nothing about the delivered HTML changes.
The shape: `Compos-<br>ite` inside one `<th>` puts the hyphen and the break in a single cell.
`splitWordContradictions` reads `WORD` over `textOf`, where the tag has become a space; the join's rewrite
runs `WORD` over each text run between tags, and `Compos-` ends its run. No letter follows the hyphen either
way, so the word is a candidate for neither pass — the same blindness the file already documents for a
wrapped source, arriving as markup instead of whitespace. Census on the shipped arm: 24 breaks carried into
column heads, `joinBrokenWords` closes 17, 3 of the 7 survivors land on limits already named, the last 4 are
this shape on one page.
Why the repair costs more than the defect: a wider pattern needs a distinction between an element that ends
a CELL and one that ends a LINE, and `textOf` renders both as one space, so `<td>Total-</td><td>farm</td>`
cannot be told from `Compos-<br>ite`. It also decides what `split` REPORTS, and `split` is contractually a
string the document contains — nothing on the page reads `Compos-ite`. Passes downstream read that contract.
`agents/page.md` now tells the page agent a word broken at the foot of a column is one word (#450), which
lowers the rate of the input for free.
Pinned rather than left as prose, in three tests that fail for different reasons: widening the pattern alone
reddens the wrapped-source case, and widening it AND taking whitespace out of `splitWordAudit`'s lookup key
— the whole repair — reddens the `-<br>` limit and the cell boundary as well, all three in one run. Separate
tests on purpose: `assert` stops at the first failure, so while the cell-boundary pin shared a test it
reported nothing and the widening's cost would have arrived one edit cycle after its gain.
Two review rounds, both APPROVED. Round 1 carried two non-blocking notes, both correct and both fixed: the
masked cell-boundary pin above, and "both read `WORD` over `textOf`", which was wrong about the join's width.
Round 2 re-ran the mutation itself, got the three failures and the exact reported values the comment claims,
and returned nothing new. Verified: `tsc --noEmit` clean, `npm test` 1700 / 1700.
Closes #374
Co-Authored-By: bbertucc <bbertucc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>