Commit Graph

4 Commits

Author SHA1 Message Date
Drew T cd1e38ee0b fix(tools): jr_isolate_all recognises lifted "} __attribute__((...)) X;" typedefs as engine types (5 drafts refused on Block4 after the lift) and drops a cut equal to the object start (a jr function that leads its object made an empty region -> out of order); mk_write refuses to merge a block that moved on disk since the caller read it (R43) (P31 S62 T3) 2026-08-26 15:48:50 -06:00
Drew T fabde98078 fix(tools): three carve-lane defects behind the last CARVE-REFUSED class — jr_isolate_all's decl carrier no longer carries glued DEFINE_…() invocations (it re-instantiated shared bodies as nameless functions in the new region; prototypes carried instead), jtbl_carve treats a full data-side overlap after isolation as the ordinary tail state, and mk_write.write_overlays_mk merges only the caller's changed blocks into the CURRENT file under the lock (base=; the whole-file rewrite raced between parallel carves — ov_SC03_029/105/MAIN_012 drifts) (P31 S62 T3) 2026-08-26 15:38:23 -06:00
Drew T 197470ff5f fix(gate/tools): baseline-RED skip in the gate, jtbl_pads_fix un-broken three ways, mk_write parse guard, shadow join for 0-bank waves (P31 S61 T10+/S61-10)
gate_stage: a binary on .run/baseline_red.txt (+ fleet_red.txt) refuses its drafts with class
BASELINE-RED before any build — a RED binary rejects every draft gated against it, and 174 of the
resolver's 245 doubly-verified drafts were refused exactly that way (negative-controlled both
directions: RED refused without a build, GREEN still reaches the ladder).
jtbl_pads_fix: (1) OBJ_ERR required the make bracket to start with build/src but make prints
[Makefile:687: build/src/...] — find_drift returned None over failing builds ('no pad-count drift',
six binaries); (2) only the 'consumed N but M' phrasing was handled — the 'more rodata .align
directives than pad specs' direction (a NEW table from a banked switch) now searches declared+1/+2;
(3) write_pads split its line on ':' but ':=' contains a colon, appending a second ': JTBL_PADS'
per write, and wrote via a raw truncating open() — the fifth un-converted mk write site; now
path-split-once + mk_write.
mk_write: refuses a parse-poisoned registry line (R43) — one such line kills EVERY build of EVERY
binary at make parse time, strictly worse than the wipes the line-count floor guards.
rtu_shadow: a 0-bank wave has no commit — gatedness now comes from the ox ledger; baseline-RED
binaries are excluded from the prediction metrics with their count reported (R41).
integration_resolver: stub_removals() nets out carve moves (72 gross -> 63 real in the first pass).
2026-08-26 00:29:05 -06:00
Drew T d801b8f177 fix(config): the registry wiper found — four truncating writes, now atomic and collapse-refusing
ROOT CAUSE of both wipes today. config/overlays.mk was rewritten in four places with

    open(mk, "w").write(txt)

(jr_isolate_all.py:593, jtbl_carve.py:1077/1118/1165) — which TRUNCATES to zero first and only
then writes. Three ways that loses the registry: the process dies between truncate and write
(empty file); another process reads inside that window (sees an empty registry); two writers
interleave (a partial line lands after the last good one — this morning's file ended in a stray
`uto.txt` fragment, exactly that fingerprint). The jtbl carve automation runs AT THE GATE, which
is when all three wipes happened, and ONE_PER_GID=0 made it far likelier by putting many more
carve members in every wave.

BLAST RADIUS, measured twice: with no binaries registered, main's object glob sweeps every
overlay's nonmatchings/*.s into MAIN's OBJS and assembles them standalone, so main cannot build,
the main lane correctly refuses against a RED baseline, and every overlay gate rejects every
draft. Waves dn/do banked 0/224 and 0/236; waves ei..em banked 2 of ~1,100 with 675 backlog rows
reading "match_one MATCH but the whole-binary gate rejected" — the local oracle proving the
drafts were byte-correct while the tree could not build them.

tools/mk_write.py is now the only writer: atomic (tmp + fsync + os.replace, so no reader ever
sees a partial file and a crash leaves the original intact), collapse-refusing (a rewrite below
80% of the current line count raises), and flock-serialized.

TWO HONEST LIMITS, recorded rather than papered over:
  * Callers still READ outside the lock, so two concurrent carves can each read-edit-write and
    the second drops the first's line. That is a LOST UPDATE — a missing line, not a wiped file —
    caught downstream by the fleet check and jtbl_pads_fix. Closing it means holding the lock
    across read-modify-write in every caller.
  * The guard now also refuses when the CURRENT file is under 100 lines. That case cost me
    directly: my own verification control overwrote a registry a carve had truncated seconds
    earlier, because the collapse check was skipped when the old file was empty. A control must
    assert its precondition; mine did not, and now the tool enforces it instead.
2026-08-25 17:48:45 -06:00