Commit Graph

5 Commits

Author SHA1 Message Date
Drew T 09b7f71a19 fix(serial lane): it was dead at turn 0 — a family-card file fed to a per-function consumer
idiom_serial passed `--cards .run/aprop_cards.json` to api_agent. That file is a FAMILY-card
file — rows are {family, members, seed, cls, reach}, with no per-function key — while
api_agent's --cards wants per-function wave cards and built its map with `c['fn']`. Result:
KeyError at line 647, the agent died before its first turn, and every target logged
"no-draft". The lane read as a model failure; its ledger holds 8 rows total and the tells
lane had, literally, "never yet run".

TWO FIXES, one on each side of the contract:

  * api_agent REFUSES, never crashes (R43). It accepts 'fn' or 'name', skips rows with
    neither, and says how many it skipped. The R32 warning two lines below — "ZERO matched —
    wrong card file?" — existed to catch exactly this and was unreachable behind the crash. A
    guard downstream of the failure is not a guard.
  * idiom_serial passes no --cards at all. Its fuel is the --brief: the target plus every
    idiom distilled so far in the run, which IS the compounding channel the 2,000-way fan-out
    lacks. It never needed a wave card.

Verified: the lane now reaches `api_agent: stealth/ox-alpha -> 1 target(s), max 60 turns` and
drafts, instead of exiting in 0.1 s.
2026-08-25 15:00:31 -06:00
Drew T b0587c573e fix(idiom_serial): main is never a target, and a contended index is not a dirty tree
The serial lane's first-ever run on tells died 0 seconds in, on both counts:

  [1/6] func_8017D1C0 @ ov_SC06_027 · 118 ins  -> drafting
  [2/6] func_8001382C @ main · 103 ins         -> could not commit — refusing on a dirty tree

MAIN IS NOT A SERIAL-LANE TARGET. main gates through gate_main on the main lane's own cadence
(a clean whole-EXE rebuild with bisection), so this lane cannot bank it however good the draft
is — a main target burns a slot to learn that. md_* was already excluded for jtbl; main never
was, because the lane predates main being in the atlas at all.

A CONTENDED INDEX IS NOT A DIRTY TREE. Six campaign lanes plus the re-gate runner commit
continuously, so `git commit` here loses the index.lock race routinely — twice today it was a
STALE lock blocking every lane for 8 and 21 minutes. The lane refused over a tree that was
fine. It now retries the commit six times at 5 s before concluding, and the refusal is
reserved for FOREIGN DIRT it must not adopt — which is the property that rule was protecting.

Verified: pick_targets('extend-tell', 8, 80) now returns 8 overlay targets, no main.

Also in this commit: MAX_BINS 160 -> 50 in the drafter shell. Wave size was the right lever at
50% conversion (dd: 217 banked of 422 gated in 39 min); at 5% it is dead weight — dq banked 8
of 167 gated and took 98 MINUTES, while four drafted waves queued and the free-ox fleet sat at
14 agents / 10 req/min. At this conversion a 150-card wave banks what a 430-card wave banks,
in a third of the gate.
2026-08-25 14:57:13 -06:00
Drew T e40fe9c116 fix(main-lane): the baseline was RED — guard every gate with a no-draft control (S59)
PROVEN: from 14:57:01 to 18:43:23 today HEAD built main to 307aa45d… against the
expected 143dbb89…, with NO draft substituted (measured under gate.main.lock, no
gate_main alive). Auto-commit commit:2693 had adopted a mid-flight gate_main
substitution — its carve-out reverted main's TUs, gate_main re-wrote them, and
`git add -A src/` swept the unverified bodies in (a TOCTOU race, 14 s after a
bisect chunk banked). Every main batch after it was doomed before its first
draft was judged: m00–m03 card cycles drafted ~737, slated 160, banked 0, and
burned ~50 clean rebuilds bisecting innocent slates. commit:2712 restored the
green content by accident (it swept this investigation's diagnostic checkout).

gate_main: on any batch failure, ONE try_batch([]) control runs first — if HEAD
itself is red it prints BASELINE RED, leaves the slate reusable, exits 3 (R40).
clean_build no longer reports a linked-but-mismatched build as "no binary" (the
build target embeds the SHA check), the compile-conflict shortcut fires only on
error-shaped lines naming a symbol some draft in the slate actually uses (the
baseline's own func_800143AC implicit-decl WARNING was matching — every m04
chunk died with "drafts declaring it: []"), reverts narrow to top-level src/*.c
(main_tus) so a main gate can never destroy overlay lanes' in-flight work, and
--assert-baseline is a first-class mode.

main_lane: every cycle opens with gate_main --assert-baseline and REFUSES to
draft or gate against a red baseline (R43) — BaselineRed parks nothing, burns
no tries, writes .run/main_lane.BASELINE_RED, re-checks every 30 min.

Adopters (ox_campaign ×3, maintenance.sh, gate_stage, gate_lane, idiom_serial):
main's TUs (top-level src/*.c) are never staged and never reverted by an
overlay/maintenance lane — one writer (gate_main), one committer (main_lane,
after the whole-EXE SHA re-checks green). Unstage-after-add is race-free where
the old revert-then-add was the losing half of the TOCTOU.

Diagnosis, evidence and the full timeline: docs/tool-designs/main-lane-fix-s59.md
2026-08-24 19:08:47 -06:00
Drew T 9e44612c2a feat(jtbl): the carve→draft→bank pipeline is automated at the gate — byte-proven ×3, one per class (S59)
The carve stays INSIDE the byte-gate (harvest_verify._jtbl_prep_one, the §61b-proven
order); everything new routes work to it:

* jtbl_carve: island_probe (read-only classifier: tail/covered/island-end/island-blocked/
  island-pads/main-manual), --island-split (the one-line §260 insert, end-adjacent only),
  and apply() now recognizes a completed island split as a no-op success instead of the
  historical refusal.
* harvest_verify: _ISLAND_WALLS branch — on the §154-A refusal the gate isolates (body
  still spliced), inserts the split line, re-extracts, re-carves. Snapshot-restore covers it.
* jtbl_lane.py (new): probe → draft (--draft-dir or api_agent) → gate via the exact
  sweep_parallel worker call, HOLDING the campaign draw lock across gate+commit → commit
  named per-binary paths. One jtbl target per gate invocation (§61c).
* build_wave_atlas: probe filter + one-jtbl-card-per-binary cap (inert unless
  --levers jtbl-carve). idiom_serial: refuses the jtbl-carve lever (R43; its pre-carve ran
  the refuted order — S58: 8 attempts, 0 banks).

Proven end to end with the live campaign running (banks committed separately):
  commit:2661  ov_SC03_014/func_8017DCC0  tail: §8b adjacent merge + §8e pad recovery,
             jr_8017AE2C.o .rodata 0x14→0x28 TIGHT, sha d84b01a2 green
  commit:2663  md_SC03_076/func_801F218C  covered: §260 STAGE 2 — sha 9a165e36 identical
             with the table COMPILER-EMITTED; the first md_* jr bank ever
  commit:2664  md_SC03_135/func_801E5358  island-end: the FULL split done BY THE GATE on a
             virgin module (~1.1s, R40-checked), sha b901fda5, md.o 0x27c→0x268 + jr.o 0x14

Census (245/245 members probed, R32): 181 members / 26,445 ins reachable unattended;
main 47 parked (gate_main cadence), island-blocked 10 (stack order), island-pads 6
(needs §8e pads for modules.mk), no-jtbl 1 (atlas mislabel).
Design + failure semantics + campaign hook: docs/tool-designs/jtbl-automation-s59.md;
cookbook §260-A.
2026-08-24 12:31:14 -06:00
Drew T e7ebb1cd45 docs+rules(S58): R42 commit-banked-work-immediately, R43 refuse-unsupported-input
R42: gate_main reverted 61 byte-proven overlay banks it could not distinguish from its own
substitution (sweep_parallel gates commit=False by design). Fixed by committing overlay banks
before the main batch, chunking main at 8 to bound bisect cost, and replacing every blind
'git checkout -- src/ config/' with commit-or-refuse in ox_campaign and idiom_serial.

R43: sweep_parallel had an explicit branch admitting main, which cannot be gated incrementally
— wave ab banked 0/105 main cards while its non-main cards banked 94/115 (82%), and the wave
read as a drafting failure. sweep_parallel now refuses main and names gate_main.py.

Also: validate_targets now prefers the card's own addr field (named symbols like SYS_OBJ_F00
were MALFORMED and discarded whole 220-card waves); ox_campaign deals model lanes by
smallest-ratio scheduling (a 73-card wave had put 73 shards on ox and 0 on deepseek);
docs/accelerators.md gains the four vacuous-check defects.
2026-08-23 12:59:59 -06:00