Commit Graph

19 Commits

Author SHA1 Message Date
Drew T bfea4affd8 feat(draw): route the model tier off the prior RESIDUAL CLASS, not nins
Measured on S71's own wave: wall-clock tracks iteration count, and iteration count
tracks the residual class, not size. A 26-instruction function took 18 min / 31 tool
calls (regalloc, finished NEAR); a 122-instruction one took 80 s / 10. The 20-33 min
runs were all compiler-internal residuals — scheduling ties, birthing boost, register
colouring, LUID order — where every hypothesis costs a compile-and-measure cycle.

arm_for keys on nins alone, so a 47-instruction regalloc wall could not be drawn at
the higher tier and nothing escalates mid-run. arm_from_history() now reads the
function's own journal notes at draw time and returns fable when they name one of
those classes; it never downgrades the size ladder's choice.
R39 control over 3,147 functions with history x 3 bands = 9,441 decisions:
4,020 upgrades (43%), 0 downgrades.

The control's FIRST form passed over an empty set — it keyed on journal rows carrying
a binary, and there are none: the agent verdict schema never had that field, so every
historical note is name-keyed and the same name is a different function in another
overlay (§238). claude_wave_draft.js's VERDICT now requires `binary`, so new rows are
exact. Cookbook §413.
2026-09-02 01:29:59 -06:00
Drew T 1dd15eda32 feat(triage): the triage ladder — built, wired, and acceptance-green
tools/triage_ladder.py — the zero-token pre-agent pass, split PRE (target-side:
BANKED/WALL-332/PARKED, no build) from POST (residual_rules_b, needs a draft).
--escalate refuses a walled or banked target; --acceptance is the R39/R32 harness.
Refuses on a non-quiescent tree: a merging gate makes the stub oracle wrong in
both directions (measured, ov_SC01_004:func_8017EB30).

Acceptance, on the whole corpus: false-skip 0/1367 open stubs, recall 426/426
matched, wall tier fires on exactly the 10 enumerated walls (0 extra, 0 missing).
The first wall control asked for evidence that CANNOT exist — it scanned banked
functions' .s, which splat never writes — and printed '0 scanned / 0 tripped',
indistinguishable from a pass. The R32 empty-denominator assertion caught it on
its first run; replaced with a two-sided sweep over all open stubs.

tools/cast_self_callers.py — the §378 lever + --sync-decls for the narrow-param
case C89 forbids no-proto from reaching (§378a).

Wiring: wave_args drops walled/parked targets at draw time via pre_classify (one
implementation, R33); escalate_fable.js refuses any target without triage:'DRAFT'.

Tool fixes found by measurement:
* fix_arity_callers was blind to main entirely (globbed src/main/main*.c; main is
  src/*.c) — reported success over an empty file set through three gates. Now
  refuses when --binary selects no files.
* parallel_gate records each worker's 'failed by class' line (was truncated out of
  the 200-char tail); gater_lane retries in-tree ONLY on the diagnostic-free
  blind-worktree signature — S69 ran 22 serial retries against real cc1 errors.

docs: cookbook §376/§377/§378 (index 1033), SETUP.md, wave-playbook §4b.
2026-08-31 23:53:50 -06:00
Drew T e57deb0a8b feat(wave): escalate_fable.js — a Fable tier that is warm-started, not restarted
An escalation that re-derives what the cheaper tier already closed pays twice for
the same instructions. This passes the prior draft, its measured closeness and its
full residual report into the prompt, tells the agent to reproduce that closeness
first (and to STOP and report if it cannot -- R40), and forbids re-trying the
levers the prior agent already ruled out.

Points the agent at the escalation path the project actually has for a
compiler-internal residual (R17): the pinned gcc-2.7.2 source in-repo,
docs/gcc-2.7.2-map, and pass-disabling as a DIAGNOSTIC only.

Requires a 'new_idiom' field in the verdict: a Fable run that closes a function
but names no reusable lever has bought one function; one that names the lever
buys the class.
2026-08-31 16:18:00 -06:00
Drew T d804449be5 fix(distill): carry banked=False through to the distiller and the verifier
The distill prompt asserted 'the whole-binary byte-gate ACCEPTED the final draft, so the final body is
ground truth' for EVERY target. With --with-unbanked now feeding it drafts the gate REFUSED, that
sentence would have laundered an unproven body into a byte-proven cookbook entry (R14/G3). A target
with banked=False now gets an explicit PROVENANCE WARNING telling the distiller to extract the lever
anyway (cookbook 52: a model that FAILS still distils the idiom that cracks its siblings) but to mark
every claim UNPROVEN and never assert byte-equality; the verifier is told the same so its
entry_markdown carries the label. Exercised this session: the one surviving ADDENDUM came from an
unbanked draft and is filed UNPROVEN.

Also regenerates the scoreboard after the day's banks.
2026-08-29 19:03:28 -06:00
Drew T c865841dbe feat(tools): claude_integration_recover.js — one agent per byte-correct-but-CC1-FAIL draft, fixes the DRAFT-side decl conflict only (never a shared header, §65a blast-radius law); t5d had 5 of 6 misses in this class (P31 S63 T5) 2026-08-26 21:10:39 -06:00
Drew T 41b259e528 fix(wave): cards keyed by (binary,fn) — t5a received 48/48 ANOTHER binary's card (R48); t5_cards.py builds the target's OWN fuel (tu_ref 88% / decl_prior 98%) via wave_card_fuel.py extracted from build_wave_atlas (R33); t5_bank.sh recovers un-banked drafts via fix_tu_ret_decls (2/2 on t5a); distill workflow generalized (P31 S63 T5) 2026-08-26 20:19:41 -06:00
Drew T f8cc4c77d3 feat(tools): T5 wave draw/bank halves — t5_targets.py (routed, ledgered, band-stratified draw) + t5_bank.sh (judge → R22 sweep → commit); claude_wave_draft.js generalized; packs/judge refuse duplicate fn names (R43/R48); sweep #8 213/213 (P31 S63 T5.1) 2026-08-26 19:35:54 -06:00
Drew T 74ec441d60 feat(tools): the Claude-subagent wave harness promoted from the T4 probe — claude_wave_packs.py (identical api_agent packs), workflows/claude_wave_draft.js + claude_wave_distill.js (the 60-agent draft and the R16 distill scripts), wave_judge.py (per-arm whole-binary gate with git-diff bank detection, tree reset, --union); SETUP row (P31 S62) 2026-08-26 19:01:41 -06:00
Drew T 2b38c68333 feat(phase-29): SESSION-21 T1-T3 — the frontier measured, the family-exemplar wave, 3 tool fixes
- T1 FRONTIER MEASURED (zero-token, R35: family map regenerated on fresh sigs first — it was
  stale by ~657 banked members): 36,020 stubs / 2,345,599 weighted ins remain, and only
  9.0% are h_exact-FREE. PROPAGATION IS TAPPED (238 distinct classes / 3,245 instances);
  22,498 distinct classes / 1,680,097 distinct ins is what is actually left. The mass is FLAT
  across all 139 binaries (~300-550 sub-500 stubs each) -> "pick the best overlay" is not a
  strategy. .run/s21_frontier.py + .run/s21_frontier.json
- T2 THE AXIS IS THE FAMILY, NOT THE LOCATION: 1,342 substantial h_seq families /
  1,298,135 templatable ins = 55% of ALL remaining weighted instructions. Routed by blocker:
  jr/§81 181 fams (33.6%) · DRAFT-with-cached-Ghidra-C 91 (28.6%) · DRAFT-modal 1,023 (27.5%)
  · zero-crack 45 (6.5%) · permanent walls 2 (3.9%). Live+cached+non-wall in ov_SC01_077 = 54
  families / 589,502 ins, value steeply concentrated (top 24 = 96%).
  .run/s21_targets.py + .run/s21_targets.json + .run/s21_draft_pool.json
- T3 WAVE 1 LAUNCHED: tools/workflows/family_core_wave.js (NEW) — 24 xHigh drafters, one per
  family exemplar, stake 575,488 templatable ins (24% of remaining). Supersedes worker_wave.js
  for family work: carries each target's family STAKE, encodes the four §58/§87 integration
  rules at source (splat D_<UPPERHEX> not Ghidra DAT_; never invent a symbol; canonical callee
  sigs; leave decl plumbing to the ladder), and requires symcheck.py on any claimed MATCH.
- T3b LADDER HYGIENE, both SESSION-20 carry items fixed — one defect, two masks: a byte-NEUTRAL
  transform was left in the tree when it banked nothing. family_sweep's --normalize-self-decls
  backstop only fired on MISMATCH (left 123 files of dead diff on a 0/123 run); gate_stage's
  ARITY undo narrowed to src/shared/ and left ~40 TUs. Both now restore the full snapshot when
  NOTHING banked (no banks to preserve => the splice hazard cannot apply). §61 on the success path.
- T3c BACKLOG addr DEFECT fixed (R32/R33): new addr_of() derives the address from `name`,
  assert_addr_coverage() fails loud on an unkeyable row, append_record fills both directions.
  Found a latent bug doing it: load_best() keyed on `addr or name`, splitting one function into
  two "best" records. Keyable rows 128/1,701 (7.5%) -> 1,701/1,701 (100%).
2026-07-26 23:37:35 -06:00
Drew T ba0cfb751e fix(workflow): wave_binary drafters MUST copy the winner back to draftDir/<fn>.c (a wave's 24 winners were written under scratch names and recovered only from agent transcripts) 2026-07-23 22:38:10 -06:00
Drew T f142a6858f feat(phase-29): ov_SC06_018 crack-wave — func_801365B8 x138 (fresh-exemplar sweep CONFIRMED), thesis is family-specific
- binary-aware crack wave (new tools/workflows/wave_binary.js): 8-target calibration
  over ov_SC06_018 substantial stubs, 7/8 match_one MATCH
- func_801365B8 (155, reach 133): cracked FRESH in ov_SC06_018, swept 132/132 siblings
  via family_sweep --hseq --source ov_SC06_018 --allow-pins -- SESSION-10 refused this
  family 0/133 from an ov077 exemplar. THESIS CONFIRMED (fresh exemplar unlocks it).
- func_80133AB0 (137, reach 137): cracked fresh + banked x1 (+ a byte-neutral s17a-1
  cast reconcile of banked caller func_801343C4), but the family sweep FAILED 0/136 even
  from the fresh exemplar (reverted clean) -- THESIS REFUTED for this family.
- FINDING (R14/R31 -> decision-log): the fresh-exemplar sweep is FAMILY-SPECIFIC, not a
  blanket mechanical x137. A fresh crack is necessary but not sufficient; the byte-gate
  arbitrates each family (~50% on this 2-family sample -> discount the ~1.5pp estimate).
- tooling (R33): family_sweep --source override now searches matched_members (a fresh
  member leaves 'members' after a sig-regen); cdecl._depth0_spans consumes backslash
  line-continuations so a raw-draft #define macro no longer trips audit-cdecl.
- R22 clean-fleet 140/140 byte-identical; tools-health green (dedup 1849/0, C1 234615);
  0 NON_MATCHING. fleet 78.4->78.5% instr / 67.1->67.5% distinct / 88.14->88.18% fn-count.
2026-07-22 18:12:09 -06:00
Drew T c916115291 feat(phase-29 T3): the §53 has_mid_jr INTERLOCK + worker_wave -O0 build-step fix
- family_sweep §53 INTERLOCK (the Task-3 deliverable): a has_mid_jr family CANNOT bank through the
  carve-less --hseq path — its exemplar's own bank needed a jump-table carve. The sweep now SKIPS them
  LOUDLY, names the right tool (jtbl_family_bank), and states that a 0% from this path is a TOOL
  ARTIFACT, not a wall. Uses the manifest's has_mid_jr (family_hseq already derived it — R33, one
  oracle, shared with dedup_extend; no re-derivation). --allow-jr is the escape hatch.
  WHY: a silent 0% from the wrong tool is exactly what manufactured the Phase-26 "structural families
  ≈0% / don't template" doctrine and steered two phases of strategy (§53, Phase-28 T1). The interlock
  makes the omission impossible to misread.
  VERIFIED (live-fire + negative control, R32/R35): manifest carries 11 has_mid_jr families / 163
  member-slots of 1418 sweepable; --band substantial -> skips 9 families / 155 slots (159 -> 150
  families); --allow-jr -> 159 (does NOT skip). It correctly flags 0x8017bebc (n=115) = B2, the very
  family whose missing carve produced the ≈0% doctrine (0/8 -> 102/115 once carved).

- worker_wave.js: pass --o0 to the match_one self-check for -O0 targets (new `o0` target flag) + an
  -O0 prompt block (§18/§18-P29: the %lo-fold residual and the array-of-struct crack). Without it an
  agent iterates a -O0 target against an -O2 compile and can NEVER match — the same wrong-build-step
  trap that produced the Phase-28 "~3%" swing number (Task 1). Exercised live by func_8013C414.

- byte-neutral: tooling only, no src/config touched.
2026-07-17 02:12:17 -06:00
Drew T 897939eb46 feat(phase-25): T5b batch-1 (partial) — +1877 fns (fleet 71.47->72.02%)
- T5b measure-wave over the <=149-ins cheap tier (83 targets, generated §12-robust
  t5_scaleup.js, Opus xHigh). Drew stopped at ~50 on HTTP-529 overload; processed the
  54 landed drafts (0 truncated) as T5b.
- 46/54 match_one-MATCH (85%); gate banked 16 clean (main 1, _a 10, _after 5) +
  family_sweep +1861 siblings/1 fail across 133 overlays (14 exemplars, ~0 tokens).
- R22 clean-fleet 136/136 byte-identical; dedup-check 1813/0; 0 NON_MATCHING (G4).
- frontier map now 64 exemplars measured (.run/t5_frontier.jsonl). Def-side loose-typing
  wall confirmed dominant at scale (~30/46 match_one-MATCH gate-rejected -> backlog);
  fleet-wide caller-decl reconcile = the #1 T7 lever. 8 near-miss -> permuter fuel (T5c).
- more T5b batches (29 cheap + 34 giants + 5 _o0) + T5c/T5d -> T6 remain (phase OPEN)
2026-07-08 22:56:01 -06:00
Drew T f154822f7b feat(phase-22): cheap-tier A/B experiment harness + findings
ab_match.js (per-arm-model fan-out fork of worker_wave) + ab_score.py (disk-truth
match_one scorer, --measured for real $). Haiku drafters vs Opus on 20 reach1 fns:
proxy 10 vs 15 matches, Haiku ~4.8x more matches/$, parity on <=52-ins band. Whole-binary
gate banked 4 (proxy over-counts; TU-plumbing wall). backlog/fleet refreshed.
2026-06-29 12:52:39 -06:00
Drew T 62fa026f7e feat(phase-21): worker_wave — GIANT-guarded §27 hint (arg-arity decls, sibling templates, coalescing residual) 2026-06-25 16:46:35 -06:00
Drew T e30697a081 docs(phase-21): _a vein is a x134 lever (10/11) — worker_wave region-fix + cont.4 findings
- worker_wave.js: derive match_one self-check --asm-subdir per-target from t.asm
  (was hardcoded main subdir -> every _a agent self-check crashed on missing .s ->
  blind drafting). Enabled the 16/24 close rate on the _a measurement wave.
- CURRENT_PHASE cont.4: the _a vein is x134 (10/11 propagate byte-identical), not the
  cont.3/§24 x1 wall. The gate's propagated:0 was 2 bugs: dedup_propagate all-or-nothing
  batch-revert poisoned by 1 stale -O0 overlay-local straggler (func_8013C360), and
  gate_stage sh() swallows dedup_propagate's non-zero exit. Realized +0.39% (commit:0267).
2026-06-24 20:37:57 -06:00
Drew T f137658171 fix(phase-21): drafters write ONLY their draft .c — distill owns cookbook (prevent unverified near-miss idiom pollution) 2026-06-22 09:36:47 -06:00
Drew T 5fc5d64445 feat(phase-21): R2/R3 — the learning flywheel (class-grouped waves + distill)
- residual class travels with the draft: drafter stamps // @class / // @stuck; gate_stage logs
  the worker's gcc-quirk class to the backlog (not the coarse manifest class).
- wave_targets.py --class <C> / --list-classes: class-grouped re-attempt waves over the backlog's
  classified near-misses (REGALLOC/SCHEDULE/REMAT/STRUCT/IV/LOOPGUARD/LOOSE/PLUMBING).
- orchestrator prep: auto-picks a class-focused wave when a class accrues >= threshold near-misses,
  else a fresh pool harvest; clears the draft dir per wave.
- tools/workflows/distill.js: post-wave agent extracts NEW byte-verified gcc idioms -> cookbook §21
  (R16, conservative); drafters now read the LIVE cookbook so distilled idioms feed forward.
- runbook: the full prep->worker->gate->distill cycle (the Phase-18 close-rate loop, automated).
2026-06-21 13:56:59 -06:00
Drew T 2d7926e9f6 feat(phase-21): T4/T5 tooling — worker Workflow + wave selector + permuter grinder
- tools/workflows/worker_wave.js: parallel toolkit-aware drafter agents (xHigh) per target,
  each writes its best matching C to the drafts dir (gate run by the orchestrator after).
  args parsed robustly (harness may serialize to a JSON string — §20 gotcha).
- tools/wave_targets.py: select a wave batch from the fuel manifest (pool/region/N, skips
  backlog walls). tools/grinder.py: token-free permuter grinder — permute backlog near-misses
  -> gate_stage -> bank; STOP/heartbeat, idles for new worker near-misses, supervisor-friendly.
2026-06-21 12:41:14 -06:00