corpus: freeze the damage, patch one class at a time, and say where one rule stops - #2161
corpus: freeze the damage, patch one class at a time, and say where one rule stops#2161gHashTag wants to merge 1 commit into
Conversation
…ne rule stops (Closes #2160) The mechanism is one character: the opening quote of the type string was replaced by '['. Substituting it back and asking whether the result is a closed string is a decision procedure, and it splits the 125 lines exactly on class boundaries -- 107 in 12 classes restorable, 18 in 3 classes truncated beyond recovery and held for a language decision rather than guessed at. Two validations per candidate, because deleting a line also makes a file parse: the field must return with a non-empty type and nothing previously present may vanish. Two measurement units, because our own first reading of six still-malformed classes (co-located destroyed lines) was checked and found false -- the cause was co-located damage from other restorable classes. Repairing those exposed a third defect that had been hidden behind them: ten files now fail on 'pub const Name(T) = struct', a parser gap on generic const struct declarations, not corpus damage. Re-run differential: 623 unchanged, 8 field-loss, 1 strict-improvement, 2 malformed-input-tradeoff, 0 unknown (was 616/13/1/4/0). All eight remaining field-loss files contain a destroyed line. field-loss is not zero, so #2151 stays undecided. Negative fixtures were tested for discriminating power, not assumed to have it: the reconstructed first signal set fires on 6 of 6, the current one on 0. No spec under specs/ is modified by anything here.
Disclosure: this stacked PR is NOT gate-equivalent to a master-based one
Cause, read from the workflow files rather than inferred:
Base here is Ran the two content gates by hand instead, so the claim is measured rather than assumed:
Not verified by hand: whatever |
Closes #2160
Stacked on
w699-restore-loop-tools(#2159), not onmaster—damage_repair.pyimports the field extractor fromdiffbin.py, which lives on that branch. Base it on master and the import breaks. Review #2159 first.No spec under
specs/is modified by anything here. Repairs are written to a scratch tree;specs/is read-only to both new tools.What the tools do
tri damage-freeze— writes the snapshot, 125 rows with class id, shape, file, line, field, verbatim rhs, ±2 lines of context, and the file digest.docs/corpus/damage_snapshot_2026-08-15.json,corpus_sha256 = 1b5a37b7a89efb782db7efd2ca7af728d4ed48b1c13ac2a35088c7926b16afd9.tri damage-repair— one candidate per class, reversible diff, effect measured. Refuses to run if any file digest has moved since the freeze, because a patch applied to a changed file is applied to a different file than the one surveyed.The mechanism
Intact:
name : "TypeText",. Damaged: the opening quote became[.children : "[4]?QuadNode",→children : [[4]?QuadNode",. One fact, both signals, one-character patch, self-inverse.The split, which is the result
[[]Const [,→"[]Const [,is not closed.[]Const []Const u8and[]Const [N]u8are both plausible; the file has no evidence. Held asneeds-human-language-decision, owner: language owner. Criterion: state what an unclosed element type in slice position means and whether a placeholder is permitted.Double validation
Deleting the line also makes a file parse. So: (1)
t27c parseexits 0; (2) the field is back with a non-empty type and nothing previously present vanished.Two units, because a hypothesis of mine was wrong
Per-class: 6
parse-restored, 6still-malformed, 0ambiguous, 3needs-human-language-decision.I read those six as co-located unrestorable damage. Checked: false — 0 destroyed lines across all seven files. Real cause: co-located damage from other restorable classes, untouched by a single-class run. Hence
--combined:A third defect, visible only after the first two were fixed
10 of 11 remaining files fail at
pub const Name(T) = struct {—Unexpected token in expression: KwStruct. Parser gap on generic const struct declarations, not corpus damage.bitset.t27fails atExpected LParen, got KwTest— separate, unclassified. Both need their own issues; neither is in scope here.Re-run differential
623 unchanged, 8 field-loss, 1 strict-improvement, 2 malformed-input-tradeoff, 0 unknown(was616 / 13 / 1 / 4 / 0).8 of 8 remaining field-loss files contain a destroyed line — exact correlation.
field-loss ≠ 0, so the gate on #2151 is not met. #2151 stays undecided and must not be merged.
Fixtures, tested rather than assumed
15 positive (one per class, carrying shape/origin/candidate/expected effect) + 6 negative pinning the false signals:
target : < 5000ns, match arms, multi-line arrays, function signatures, raw strings, intact convention.Discriminating power: reconstructed first signal set fires on 6 of 6 negatives, current on 0. On the real corpus naive = 1378 lines, current = 125.
loop-tools-trackedextended to both new tools and verified to FAIL (exit 1) while untracked and PASS after commit.Not claimed
cost, full-run hang undiagnosedfpga-formal/fpga-synthesisred is the master baseline (#2153).check-first-party-doc-language.shhas 8 pre-existing errors on master; none is a file from this branch.