@@ -193,6 +193,50 @@ timeout). The accepted remainder is equivalent by construction:
193193 it (invalid input throws first), so the copy is defensive; forcing it is
194194 allocation-only.
195195
196+ ## Timed-out mutants (audited set)
197+
198+ ` TIMED_OUT ` is detected — these mutants never enter a baseline — but the
199+ watchdog observed slowness, not wrongness: for exactly these mutants the
200+ ratchet cannot see a weakened covering assertion, because a timeout keeps
201+ "detecting" no matter what the test asserts. Per HARDENING.md, the summary's
202+ ` N timed out (load-dependent) ` is therefore an audited set, not a count: every
203+ member is listed here with the structural cause that makes it spin, and a
204+ mutant timing out that is * not* on this list is something a reviewer stops on.
205+ Members flip ` KILLED ` ↔` TIMED_OUT ` run to run — the covering test reaching a
206+ failure races the watchdog over a dead mutant, benign in both directions — so
207+ per-run counts sit at or below the set size. (The 2026-07-21 convergence check
208+ recorded 7 iterator members; one has since settled to ` KILLED ` .)
209+
210+ As of 2026-07-26 — 8 members, 6 iterator + 2 util, numbers none:
211+
212+ ** iterator**
213+ - ` BaseJsonIterator.reduceScale:1021 ` , two mutants (` scale-- ` → ` scale++ ` ;
214+ loop condition → ` true ` ): the counter crossing the negative ` scaleLimit ` is
215+ the loop's only exit; both remove it and the divide loop spins on a settled
216+ quotient of 0.
217+ - ` BaseJsonIterator.skipObject:1122 ` (scan cursor ` i++ ` → ` i-- ` ): the
218+ ` i == tail ` bound is an equality a backward walk never meets, and the
219+ string-skip re-entry (` i = head - 1 ` after ` skipPastEndQuote() ` ) can pull
220+ the cursor back into the same cycle indefinitely.
221+ - ` BytesJsonIterator.parseMultiByteString:575 ` (escape-decode ` buf[head++] ` →
222+ ` buf[head--] ` ): the cursor backs away from the ` head == tail ` guard and
223+ re-decodes earlier bytes; the spin races the eventual bounds fault, which is
224+ why this member often lands ` KILLED ` instead.
225+ - ` CharsJsonIterator.parse:136 ` (escape skip ` ++i ` → ` --i ` ): cancels the for
226+ loop's own ` ++i ` , pinning the cursor on the same backslash — a pure
227+ oscillation with no exit and no fault.
228+ - ` CharsJsonIterator.skipPastEndQuote:156 ` (` buf[head++] ` → ` buf[head--] ` ):
229+ same reversed-cursor family as ` parseMultiByteString:575 ` .
230+
231+ ** util**
232+ - ` JIUtil.escapeQuotesChecked:170 ` (do-while ` ++from ` → ` --from ` ): after an
233+ odd, already-escaped quote the backward ` from ` makes ` indexOf('"', from) `
234+ re-find the same quote every pass (a negative fromIndex clamps to 0), so
235+ the loop never reaches ` len ` .
236+ - ` FieldMatcher.of:51 ` (` names.length << 2 ` → ` >> 2 ` ): collapses the table
237+ capacity below the entry count, and the linear-probe insert loop exits only
238+ on an empty slot or a duplicate name — a full table offers neither.
239+
196240## Mutator-set trial (2026-07-21)
197241
198242Per HARDENING.md ("the mutator set bounds what the ratchet can see"),
0 commit comments