FIVE independently-MATCHed ov_SC06_029 bodies were rejected by a `parse error before '#'` in a file
the GATE ITSELF generates, at a line no draft contains. The isolation emitted, into the §8b carried
decl layer:
extern #define CALL_80185C6C ((void *(*)(s32, s32))func_80185C6C) extern void func_8012C218();
CAUSE. Every peeler in the TU-split chain asked `line.strip().startswith("/*")`, which is blind to a
comment a construct opens MID-LINE and wraps. The declaration ends at its `;` BEFORE the `/*`, so
the caller resumed on the comment's PROSE with in_block=False — and the prose is hostile: `(s32,s32)`
closes a depth-0 paren, `seen_header` latches, and every later `;` reads as a K&R parameter
declaration, so one "construct" swallowed the whole preamble. `parse_overlay_c` then anchored a
`def` on a pure declaration run and `def_proto` rendered it as that definition's implied prototype.
A SECOND defect rode along: `_file_scope_decls` hoisted such a col-0 line VERBATIM, unterminated
`/*` included, so the carried layer opened a comment that silently ate the next two declarations —
a dropped file-scope decl is a silent byte-changer. Building the guard exposed a THIRD: `_strip`
tested for `/*` before stripping `//`, so `// … src/*/*.c` (7 lines in 5 sources) opened a phantom
block comment and blanked everything to the next `*/`.
FIX: one derived comment-state oracle, `comment_open_at()` (R33) — per line, does it BEGIN inside a
block comment — consulted by parse_overlay_c, def_proto, split_src_region.parse and
jr_isolate_all._file_scope_decls (which also truncates a hoisted decl at an unterminated `/*`).
`_strip` now lexes left to right. `parse_overlay_c` RAISES (R43) when a wrapped comment closes with
code after the `*/`, because that construct could never anchor — 0 occurrences fleet-wide.
MEASURED, not assumed:
* the shape occurs 238 times across 193 tracked .c files; 153 are col-0 hoistable declarations in
150 files — every one a binary whose next isolation would have carried a broken decl layer.
* A/B over all 4,188 tracked sources, old parser vs new: round-trip identity 4188/4188 both ways;
exactly 2 files' item lists change, each losing one PHANTOM def and gaining nothing; malformed
implied prototypes 999 -> 984; 0 refusals.
* negative control BEFORE any edit: ov_SC06_029 extract+build -j+check BYTE-IDENTICAL b7b0d4ae.
* with the fix, gate_stage banked 5 of 6 drafts, counted from the SOURCE; the 6th
(func_80184084) is the separate CARVE-REFUSED class.
The 984 residual malformed prototypes are a DIFFERENT pre-existing trigger (col-0 lines gluing
declarations to DEFINE_func_*() invocations); 4 still carry a `#` and survive only because it lands
in a dropped segment. Named in §437, deliberately not fixed here.
Cookbook §437 + a SETUP.md tooling-ledger row for comment_open_at (parse_overlay_c may now raise).
The banks themselves are NOT in this commit: the agent's worktree predated func_8017F9C0's bank, so
adopting its TU verbatim would have destroyed one. They get re-gated against HEAD with these tools.
jr_isolate has been unusable since Phase 26 — its own docstring says "BLOCKED on
split_src_region". Five distinct defects, each found only after fixing the one above it:
1. split_src_region demanded an address for EVERY top-level item, but an overlay .c is
full of address-less constructs (hoisted typedef blocks, per-function extern runs,
comment banners). coalesce() now merges an address-less run FORWARD into the item
below it — they are a preamble belonging to that function, which is §431's model.
2. coalesce re-derived the name from the MERGED text, so item_name matched the preamble
instead of the function. It now carries (addr, name, text) captured before the merge.
3. item_name scanned COMMENTS as if they were code: a comment containing any
parenthesised token won over the real definition below it.
4. item_name matched a leading "extern void (*D_x[])(void);" and returned the name
"void" — the §192 class, which gate_main.sym_of fixed for itself and this tool never
got. A real function was then treated as a preamble and merged into its neighbour,
leaving its body inside another item while its own stub survived: 26 duplicate
symbols in one overlay. It now anchors on a DEFINITION (ends in an open brace, not a
semicolon) and refuses type keywords as names.
5. That definition anchor required column 0, so an INDENTED top-level body was invisible.
Also: jr_isolate's idempotency check keyed on the CONFIG, which it writes FIRST, so any
failure in between left a half-applied tree the tool believed was finished. It now
requires the source file too and refuses with recovery instructions. And inject accepts
"already present and textually IDENTICAL" — splat emits an empty function as C, not as a
stub — while still failing hard when the destination defines it DIFFERENTLY.
Progress on ov_SC02_005: trim went 78 kept / 231 moved -> 89 / 255; duplicate symbols
26 -> 0; the chain now runs to completion (rc=0).
NOT DONE: the object still fails to assemble on a remaining duplicate-definition class.
Tree restored, ov_SC02_005 BYTE-IDENTICAL.