Commit Graph

4 Commits

Author SHA1 Message Date
Drew T 3005fc1239 fix(sync_tu_decls): a no-op sync is not progress, and a repeated symbol is not a blocker
replace_decl returned True whenever the PATTERN matched, even when the
substitution produced identical text. So a draft that already carries the TU's
exact spelling looped until --rounds ran out, spending ONE CLEAN REBUILD PER
ROUND, and then printed 'gave up after 6 rounds (6 synced)' — which reads as
six useful syncs.

Measured on func_8005FA94: 6 rounds, every one
'D_80072960 -> extern void (*D_80072960)(void *);', zero change to the draft,
five wasted rebuilds and a misleading report. R61(a): a no-op must not be
reported as work.

Two guards: no text change ends the loop naming the already-correct spelling
and saying the residual is elsewhere; and a symbol the gate names twice in one
run ends it too, since re-syncing it cannot help.

The comparison is LINE-NORMALISED because the pattern ends in \s*$ and the
substitution eats the matched line's newline — a byte compare called that a
change. Caught by a known-true check (identical/different/absent), not by
reading the code.
2026-09-03 20:38:59 -06:00
Drew T 454d3878bc fix(sync_tu_decls): a definition is a declaration; a gate refusal is not a verdict
Two defects, both found by driving the last two self_decl_tu drafts to a bank.

1. tu_decl looked only for an `extern … sym …;` line, so when the clashing
   symbol is a function the TU DEFINES it stopped with

       stopping: func_8005E480 clashes with the TU itself but src/800c3.c has
       no `extern` line to copy.

   though the authoritative spelling was in the definition's own header at
   src/800c3.c:916. This was the terminal blocker of BOTH remaining drafts
   (func_8005E3AC on func_8005E480, func_8005E79C on func_8005E804). The
   definition is now preferred over an extern when both exist — it is the one
   cc1 checks every other declaration against. Banked func_8005E3AC in one
   round. Checked against known-true cases before being trusted: definition
   path on func_8005E480/func_8005E804, extern path still verbatim on
   func_8005D734, absent symbol still None.

2. gate_main refuses outright on a dirty src/ or a red baseline and never
   reaches a per-draft opinion. The round loop matched neither DROP_RE nor
   COMPILE_RE in that output and fell through to "no declaration conflict
   named; stopping after 0 sync(s)" — reporting a HARNESS refusal as a property
   of the DRAFT (R40). Measured on func_8005E79C, whose gate was refused
   because the bank one command earlier had left src/ uncommitted. The refusal
   is now surfaced and exits 3.
2026-09-03 18:56:21 -06:00
Drew T 9bdd2e27f7 fix(sync_tu_decls): read the post-build conflict too, and refuse a NEAR up front
Two gaps found by running it over all 16 candidates.

It only parsed the slate-load 'DROP … clashes with …' path, so five drafts
whose conflict surfaced AFTER the build as 'COMPILE conflict on `SYM'' looked
unrecoverable when they were the same class one symbol deeper. Both forms are
read now.

And a CC1-FAIL classification says the declaration blocked COMPILATION, never
that the body underneath is right: five candidates compiled once synced and
then failed the byte gate because they were NEARs (closeness 12-89) all along.
It now scores the body first and refuses a NEAR, so a gate is not spent
learning what match_one already knows (R37).

That check had the §238 bug it exists to prevent — I called match_one without
--asm-subdir, so it defaulted to asm/resident/nonmatchings/resident, judged a
DIFFERENT function, returned no verdict, and let the NEAR through. The subdir
now comes from the stub oracle. Caught only by controlling the guard against
a case whose answer I already knew.

Controls: closeness-12 draft REFUSED as a NEAR; func_80013154 still refused as
self_decl_tu with the correct redirect.
2026-09-03 17:31:35 -06:00
Drew T 14f0f91438 feat(tools): sync_tu_decls — bank a draft by copying the TU's own declarations
The dominant reason a byte-correct draft does not bank is not codegen: the
draft and its destination TU spell a shared symbol differently and gcc-2.7.2
rejects the redeclaration. gate_main's pre-check already NAMES the symbol and
which side it kept, and the TU holds the authoritative spelling — so the fix
needs no judgement. Copy the TU's extern line verbatim into the draft,
re-gate, repeat.

Done by hand this session it banked func_8005EB28 in one round and
func_8005EC00 in two, both stuck across multiple slates, both byte-identical
after. The conflicts are typically a CASCADE: banking one function gives the
TU a real definition that then contradicts the stale extern every later draft
in that TU still carries.

Refuses the self_decl_tu class loudly (the TU declares the function being
banked, so the call SITES must change too — that is cast_self_callers
--sync-decls), and refuses any binary but main, whose gate is the one that
names the symbol (R43).

Controls: on an already-banked function it reports no conflict rather than
claiming a bank; on func_80013154 it refuses with the right reason. The byte
gate remains the sole arbiter — every round ends in a real gate run.
2026-09-03 17:20:36 -06:00