Files
BFM-decomp/phase-ends/CURRENT_PHASE.md
T
Drew T ebdef9012b feat(phase-27 T2): make the Makefile fail-closed — the enabling fix for every downstream gate
The roadmap §5 asserted `make report` is fail-closed. It was NOT: .ONESHELL sends each
whole recipe to one `bash -c`, so with no -e only the LAST command's exit survives and
every earlier failure is swallowed. `dedup-check` "gated" purely by being last;
lint_symbol_refs / progress --audit / difficulty / dup_report were non-gates. That is the
26-A audit's own thesis (a loud failure nobody counts is as invisible as a silent one)
biting the audit's infrastructure — and until it's fixed, any R32 assertion added to a
report-invoked tool is swallowed on arrival.

- .SHELLFLAGS := -ec (global fail-closed). ONE documented opt-out: check-env (set +e — its
  contract is accumulate-every-failure-and-report, which -e would truncate at the first
  missing tool).
- check-all:610 grep -c landmine fixed (|| true): grep -c exits 1 on zero matches, which -e
  treats as fatal in a command substitution -> check-all would FAIL exactly when nothing did.
- check-all / extract-all: assert COVERAGE (pass == N), not the absence of a failure marker.
  The old `fail == 0` / `! grep -q` form was a VACUOUS PASS on an empty pipeline (R32).
- new `make tools-health` = audit-corpus + audit-cdecl + report, fail-closed — the deliberate
  pre-matching ritual the roadmap's standing invariant names, and the dependent the two
  derived oracles never had (nothing invoked them). NOT a report/build prereq — audit-cdecl
  cross-compiles every C decl through gcc (~minutes). SETUP §6.3 documents it (R21).

VERIFIED:
- NEGATIVE CONTROL (the proof): a broken lint_symbol_refs makes `make report` exit 0 under
  the old .SHELLFLAGS=-c and exit 2 under -ec. The swallow was real, not theoretical.
- the grep -c landmine + the vacuous-pass both reproduced and fixed in isolation.
- check-env still exits 0 (the opt-out works); recipe sweep found the Makefile already
  -e-aware (set -o pipefail, explicit || true) — line 610 was the only real hazard.
- R22 clean-fleet: make check-all -> 136/136 byte-identical; a forced main re-extract+rebuild
  drove the full splat->cpp->cc1->maspsx->as->ld->objcopy->check pipeline under -e -> 143dbb89.
- audit-corpus 7s / audit-cdecl green / tools-health wired.
2026-07-15 17:56:45 -06:00

20 KiB
Raw Blame History

CURRENT PHASE — Phase 27: The Fable5 Farewell Sprint + the Honest Frontier

Status: ACTIVE · plan approved by Drew (gate 1) 2026-07-15 · Generation Gen2 (19th phase of the arc; Phase 14 public-flip deferred to Gen3+) Opening brief: docs/roadmap-to-100.md §3 (P27) — ADVISORY, and materially corrected by this phase's planning verification (see below). Baseline: v1.25.0 / PhaseEnd_Phase26. ⏳ PERISHABLE: the Fable5 window closes ~2026-07-19. Task 1 runs first and concurrently; everything else is deterministic and non-perishable. Recovery note: a fresh session resumes from the ▶ CURRENT TASK below (P3 — autonomous between gates). Read this file's plan context + the roadmap §3 P27 entry + the Planning verification section below (which supersedes several roadmap specifics). The per-task Log at the bottom is the crash-recovery trail.

The plan in one paragraph

Phase 26 closed on an honest pivot — the mechanical/templating harvest is byte-proven exhausted (3 gate probes, 0%) — and on the 26-A tooling-integrity audit, whose finding was that our own tools were manufacturing several of the "compiler walls" we had recorded across 26 phases (→ R32/R33/R34). Phase 27 exists to rebuild the endgame plan on measured reality instead of a manifest that over-promises, and to spend the one perishable input — the Fable5 discovery tier — before it expires. Planning verification (three read-only agents, 2026-07-15) found the roadmap's shape sound but ~28 of its P27 specifics stale, mis-transcribed from the audit they cite, or actively harmful; this phase executes the corrected slate. Owner decisions (2026-07-15): curated .run/ preservation · full disc audit incl. the type-sweep, accepting the denominator expansion · Fable5 in 2 waves with distillation between.

Planning verification — what changed vs the roadmap (R14 at planning scale)

The three findings that reshaped the plan:

  1. The 0x8017BEBC probe would have manufactured a 4th false wall. Billed "possibly the largest cheap win left" (~106k ins), it would fail 112/112 today for a tooling reason: extract_unit doesn't carry the 8 file-scope gte_* macros the banked exemplar references (src/ov_SC01_000/ov_SC01_000_jr_8017BEBC.c:2838-2948); 0 of the 112 member TUs define them. Fix the carry first, or the probe is worthless. Also: "NEVER PROBED" is unproven (A3h's --hseq --band all ran 07-14, after the 07-13 exemplar bank; the family qualified — likely staged-and-failed among the 9,698); "IMM-scattered" is misleading — cls_counts = {PURE: 106, IMM: 6, STRUCT: 0}, a 95%-PURE class with a 6-member IMM tail. Exemplar lives in ov_SC01_000, not ov077.
  2. make report is NOT fail-closed — roadmap §5 asserts it is. Makefile:9-10 sets .ONESHELL with no -e in .SHELLFLAGS (verified via make -p: .SHELLFLAGS := -c), so the recipe is one bash -c and only the last command's exit survives. dedup-check is fail-closed only because it is last; lint_symbol_refs, progress --audit, difficulty, dup_report are swallowed. Until fixed, every R32 assertion added downstream is swallowed on arrival. check-all/extract-all also assert fail == 0 rather than pass == N → an empty pipeline is a vacuous pass. Neither audit target has any dependent.
  3. Four code-bearing SC07 payloads (~2.45 MB) are invisible to every tool. ov_SC07_{006,007,010,011} sit at PAC entry index 1 (1.4.dec) while all 134 onboarded use index 0, and new_overlay.sh:23 hardcodes 0.4.dec + exits at :28. Code-bearing confirmed by probe (98.0% plausible-opcode; jr $ra 2450–2614 — statistically identical to onboarded overlays). Zero mentions in docs/ or config/. The resident is an index-1 entry too — same convention blind spot.

Dropped from the roadmap's slate, with reasons:

  • 0x8013C414 — ×134 contested by an explicit fuel_manifest → reach_verification.o0_overlay_local: verified_reach: 1; worklist.md:197 prices it 329×1 = 0.04% of remaining. Also already drafted (.run/backlog_drafts/, .run/one3-func_8013C414/). Not perishable-window material.
  • func_801549F8 ("2 diffs from done") — traces to the superseded family-endgame-megaplan.md:187; Phase 26 already checked it, walled it at 17/31, and wrote "Permuter/Fable5 class — do NOT hand-grind it" (logs/Phase26.md:540-546); its close=0 row was inside the A10 re-gate that banked 0/958. ×134 contested (fuel_manifest reach=1; 31 ins).
  • func_8012E364 — the "stale closeness" label is itself stale; the backlog was regenerated and now reads close=23 (backlog.md:1317).
  • jtbl_carve.all_data_labels "fix first · load-bearing for B5" — refuted by the audit it cites: measured twice independently, 0 of 5043 jtbl ends differ; "zero live damage, zero latent damage… a case for NONE is defensible" (tooling-audit.md:1435-1447). R33 verdict = delete the dead end-from-next-label logic. B5 is not gated on it. ("+ main's jtbl fns" isn't this tool either — it globs asm/<ov>/data/* only.)

B4 dissolves into Task 4. Its remedy was already run: A9b re-ran 7 "blocked" cores through bank_exemplar → 1/7, and that one (func_8017A4AC) is already banked ×134. The 4 residual need 4 different fixes — and func_8015C32C's is masked_diff.SCALAR_TYPEDEF_RE, already Task 4's debt. (5th core, unnamed in the roadmap: func_80159C84 (337). Arithmetic exact: 5×134 = 233,696 ≈ "234k"; 3 plumbing-shaped = 122,878 ≈ "123k".)

Ledger corruption to fix in Task 8: worklist.md:24/:69 + backlog.md:46 still carry func_80178004 as close=0 | MATCH — a claim Phase 26 explicitly retracted as a myth (best historic permuter score 5, pinned); duplicate rows with conflicting values (func_801549F8 close=0 at :125 AND close=3 at :631; func_8014D820 at :1793 and :1855); func_801670E4 carried at close=94 when the real best is 23. B3's label is wrong though its numbers are right: only 106 of 228 cores are reach-134 (119 are reach-1); the 884,130 gain figure already discounts them.

Confirmed exactly (no change): the 3 seeds still stub at 304/209/279 ins, pin-free, func_801670E4 close=23 · 0x80176734 371 ins, genuinely un-drafted, #4 by templatable weight · the qty_n_refs lever (local-alloc.c:1869) genuinely untested and distinct from the internals already patched · 1,858 / 1,670 / 228 / 884,130 · resident 21 stubs · main 2,002 / 1,048 / 954 · 138 type-4 / 134 onboarded / 166 type-1.

Metric corrections carried into Task 10: roadmap §2's "plus the main EXE's ~2,002 stubs" double-counts finished work — ~954 are LINKED PsyQ = complete per the contract's own decision (2); honest remaining main game code = 1,034. "~80 jtbl fns (progress.md)" — citation wrong (progress.md contains zero "jtbl"); real = 82, of which only 30 are game code.

Meta-lesson (→ decision-log, R31): the roadmap's task-2 framings are transcriptions of the audit's headlines; the audit's own skeptic verdicts disagree with several. tooling-audit.md says so itself: "The skeptics killed 4 findings and downgraded 16 — read the verdicts, not the raw claims."

Task checklist (effort per R7 · one commit per completed task after this file is updated, Drew pushes — R6/R20)

  • ▶ Task 1 — Fable5 discovery sprint [orchestration xHigh · agents model:fable · distillation Max] — PERISHABLE, background. (Task 3 was pulled ahead of it — 5 minutes to make the sprint's inputs non-destroyable; see the Log.) Wave 1 (parallel-isolated): the 3 recon-done pin-free seeds func_8014D820 (304), func_8016CBC0 (209), func_801670E4 (279, close=23); seeds at .run/giants/*.opus.{c,md}. Distill idioms into cookbook §31/§52 + docs/gcc-2.7.2-map/ IN-SESSION (R30) — the value is the idiom, not the bank (§52: a failed Fable5 pass still fed 670 cheap-Opus instances). Wave 2, informed by wave 1: 0x80176734 (371) + the pin-crash cc1 SIGABRT characterization (gates P31's pin-×1 endgame; harness works at .run/fable_80178004/{runorc.sh,oracle2.gdb}; cause is currently hypothesis-only — no abort site, assert identity, backtrace, or minimal repro exists). func_80178004's qty_n_refs = wave-2 filler only (decision-log prices grinding it low-EV). Gate: idioms distilled, not functions banked. Verify: whole-binary byte-gate per crack; family_sweep propagate; R22 clean-fleet.
  • Task 2 — Makefile fail-closed (the enabling fix) [xHigh] — DONE. .SHELLFLAGS := -ec (global fail-closed) with ONE documented opt-out: check-env (set +e — its contract is accumulate-every-failure). Fixed the check-all:610 grep -c landmine (|| true — grep -c exits 1 on 0 matches, which -e would treat as fatal → check-all would fail when nothing failed). Strengthened check-all/extract-all from fail == 0 → pass == N (coverage assertion, R32 — the old form was a vacuous pass on an empty pipeline). Gave the two audit oracles a dependent: new make tools-health = audit-corpus + audit-cdecl + report, fail-closed (NOT a report/build prereq — audit-cdecl is ~minutes). SETUP §6.3 documents it (R21). VERIFIED: (1) known-answer — a broken lint_symbol_refs makes make report exit non-zero, and a negative control proves it: the identical break exits 0 under old .SHELLFLAGS=-c, 2 under -ec; (2) the grep -c landmine and the vacuous-pass both reproduced + fixed in isolation; (3) check-env still exits 0 (opt-out works); (4) make check-all → 136/136 byte-identical, and a forced main re-extract+rebuild exercised the full splat→cpp→cc1→maspsx→as→ld→objcopy→check pipeline under -e → 143dbb89…; (5) audit-corpus (7s) + audit-cdecl (green) + tools-health dry-run all wired. Recipe scan found the Makefile was already -e-aware (set -o pipefail, explicit || true, guarded @ lines) — line 610 was the only real hazard. (completes with this commit)
  • Task 3 — Curated .run/ preservation [xHigh] — DONE (pulled ahead of Task 1 — it de-risks the sprint's inputs). .gitignore /.run/ → contents-exclude form (/.run/* + ! exceptions, the /tools/bin/*.sha256 precedent). Refined at execution against the bytes: the naive "commit the dirs" would have been 12.3 MB of regenerable gcc RTL scratch; the genuinely irreplaceable set is ~2.2 MB / 31 files — the 6 Phase-25 *.opus.{c,md} seed recons (49K), the func_80178004 gdb-on-cc1 harness + ORACLE_PROOF.md + the v00–v07 draft ladder + the sched/combine .lst evidence (~110K), and the two frontier ledgers (backlog.jsonl 1.9M, fuel_manifest.json 67K). dumps_v00..v07/ + d_pf*.i.* stay ignored — regenerable via runorc.sh + the .gdb scripts (R33: commit what a rerun cannot reproduce). VERIFIED: git add --dry-run .run/ stages exactly the 30 intended files, 0 bulk; negative control — .run/ghidra-mcp.log, dumps_v00, d_pf.i.sched, d_pf.s all still IGNORED; no db.*.gbf staged (R23). (completes with this commit)
  • Task 4 — The cdecl strip primitive + surface cc1 stderr [xHigh] — one primitive replacing two regexes with complementary holes; strip-set per-TU via cdecl.tu_scope (NOT a global engine_types.h parse — 213 TUs never include it; NOT a longer name list — tooling-audit.md:1652); split multi-typedef lines via cdecl.split_statements. Surface cc1 stderr in harvest_verify.build() (currently capture_output=True throws it away → a plumbing failure is recorded byte-identically to a compiler wall). Unblocks the 39 _TD-blocked fns (8 already FAILED), the 42 discarded masked-MATCH drafts, and B4's func_8015C32C. Verify (known-answer): .run/drafts-t3b1-fb/func_8015C030.c must reach MATCH (23 ins) unedited (today it CC1-FAILs; newlines alone fix it).
  • Task 5 — extract_unit macro-carry → the 0x8017BEBC probe [Max] — carry file-scope macro deps; then --stage-only sizing (minutes) → a bounded ~10-member gate sample for the rate → leave the full ~112 gated builds to P28's gate farm. Verify: the staged unit compiles standalone (today it cannot); report the realized bank-rate as a measured number. A 0% here is only meaningful AFTER the macro fix.
  • Task 6 — Scanner migration [xHigh] — must precede Task 7. Delete exemplar_miner.py:73's registered_addrs() proxy (R33: remove entirely, not patch — 60%-wrong answer). Migrate difficulty.py off its hand-maintained 136-entry BINARIES dict to corpus (it runs inside make report for every binary → Task 7's onboarding would otherwise make new binaries silently miss make report). Verify: per-binary known-answer diffs of docs/difficulty.*.md byte-identical pre/post.
  • Task 7 — Disc-completeness audit + onboard + type-sweep [xHigh] — generalize new_overlay.sh to accept a PAC entry index; onboard ov_SC07_{006,007,010,011}; sweep the 166 type-1 / 139 type-7 / 29 type-6 entries with sig_image.detect_code_end; fix the contract's binary count. EXPECT THE HEADLINE % TO DROP (~+2.45 MB denominator) and every ×134 → ×138. Verify: each new overlay byte-identical vs its extracted payload; check-all = the new N/N; the sweep's result documented either way.
  • Task 8 — The byte-gate-honest re-scan + partition + ledger rebuild [Ultracode (triage breadth — PROMPT, R26/R27) → Max (synthesis)] — refresh surveys on the fixed tools; worklist --assert-partition scoped honestly (worklist's universe is ONE overlay ~263 stubs vs the fleet's 53,371 — a genuine fleet partition is a scope change, not a flag); triage the 1,670 untriaged; rebuild the wall ledger from data; fix the ledger corruption above. Verify: partition passes against corpus.stubs(); retracted claims gone.
  • Task 9 — Calibration probes (the swing numbers) [Max] — member-adapt close-rate on register-drift members · realized ×N per fresh core crack (the §52 wave banked 5/5 — is that the rate?) · cost/fn per tier. Verify: every number traces to a gate result, not a scan. Report velocity (instr-%/session) for the flip-timing checkpoint — with the caveat that Phase 26's ≈+0.8%/session came mostly from the family engine + audit fixes, both now spent.
  • Task 10 — Completion dashboard + the second oracle [xHigh] — 10a (Ghidra-FREE, no MCP stop, no R23): main into the weighted denominators via corpus.stubs("main") — ⚠️ LANDMINE: the naive glob makes src_stubs resolve src/SLUS_007.26/*.c → 0 files → main reports 100% and the fleet % silently inflates. 10b (small): a sig-resident target — sig_image already supports the resident flat blob; it is simply never invoked. Closes half the R34 blind spot (corpus.sig_is_independent() is literally return binary.startswith("ov_") → main + resident report clean by construction, a silent skip inside the R32 tool). 10c (LARGE — scope, don't force): main's sig_image oracle is blocked by 3 structural issues; seeding from splat destroys independence exactly for the PHANTOM class. Deliver a scoped design + honest deferral, not a fake oracle.
  • Task 11 — PhaseEnd + Roadmap delta [Max] — Tier-1. P7 checkbox walk → Drew's gate-2 → PhaseEnd (P8 format + R25 recap + the standing Roadmap delta line) + R31 decision-log entries; archive this file → phase-ends/logs/Phase27.md (R19, git mv, left uncommitted for Drew's close commit).

Blockers / open

  • None yet. (Dependencies enforced in the harness task list: T6→T7 · T2→T8 · T2+T7→T10 · T5→T9 · all→T11.)
  • Effort/model transitions must be prompted, never assumed (R26/R27): Task 8's triage → prompt for /effort ultracode and wait for the toggle; Task 1's Fable5 agents are spawned via Agent(model: fable) (per-agent model, no session toggle needed); back to Max for Tasks 5, 9, 11.
  • .run/ durability — CLOSED by Task 3 (2026-07-15). The sprint's inputs are now tracked.

Log

(per-task crash-recovery trail — appended after each task, before its commit)

  • 2026-07-15 · Task 0 — Phase Start (gate 1). Session Start Protocol run (PROJECT_CONTEXT + all 26 PhaseEnds + the roadmap + effort-map + decision-log tail). Plan-mode verification via 3 read-only agents against the repo (R14 at planning scale, per roadmap §0's own mandate). Outcome: ~28 roadmap P27 specifics corrected — 3 targets dropped, B4 dissolved into Task 4, 2 false-wall traps caught before they cost a verdict (the 0x8017BEBC gte-macro carry; the make report fail-open), 4 invisible code-bearing overlays discovered. Drew approved the plan + 3 owner decisions (curated .run/ preservation · full disc audit incl. sweep · Fable5 2-waves-with-distill). Harness task list built (R28). This file written (P3 step 4). (committed commit:0629)

  • 2026-07-15 · Task 3 — Curated .run/ preservation. Pulled ahead of Task 1 (a 5-minute deviation from plan order, P3 autonomy): Task 1's Fable5 agents work inside .run/, and its Phase-25 seed recons were untracked — an agent overwriting .run/giants/func_8014D820.opus.c would have destroyed irreplaceable input. Five minutes out of a four-day window is a trivial price for removing that. Execution refined the plan against the bytes (R33): the plan said "track .run/giants/*.opus.{c,md} + .run/fable_80178004/", but those directories are 8.5M and 3.8M — almost entirely gcc RTL dump scratch (d_pf.i.combine/.sched/.lreg, dumps_v00..v07) that runorc.sh + the .gdb scripts regenerate. The irreplaceable core is ~2.2 MB: 49K of seed recon, ~110K of oracle harness + proof + draft ladder, and the two ledgers. Committed that; left the regenerable bulk ignored. Verified both directions (intended set stages; bulk still IGNORED). Carried to Task 1: the sprint's outputs must be added to the allowlist as they land — the same reasoning that motivated this task.

  • 2026-07-15 · Task 2 — Makefile fail-closed. The roadmap §5 asserted make report is fail-closed; it was not (.ONESHELL + no -e → only the last command's exit survives; dedup-check "gated" purely by being last). Set .SHELLFLAGS := -ec globally + check-env opt-out; fixed the grep -c landmine; upgraded check-all/extract-all to coverage assertions (pass == N); added make tools-health as the audits' dependent. The negative control is the proof that mattered — same broken gate, exit 0 under -c vs exit 2 under -ec — turning "the swallow is real" from a claim into a measurement (R14 discipline applied to my own fix). Full clean-fleet R22 held (136/136 + a forced main rebuild under -e). This unblocks every downstream R32 assertion: until now, any gate added to a report-invoked tool was swallowed on arrival. SETUP §6.3 updated (R21).

  • 2026-07-15 · Task 3 (addendum) — the allowlist was still too narrow; cookbook §45 cites untracked files. While reading the seeds for Task 1 I hit a real defect: cookbook §45 names .run/giants/func_80133CD4.fable.c as its worked example and .run/giants/fable_cd4/ as the flagship's gdb oracle — and BOTH were untracked. The documentation cites artifacts that were not in git. Widened the allowlist by file type rather than directory (.run/giants/*.{c,md,sh} + fable_cd4/*.{c,md,sh,gdb,txt}), adding 49 files / 460K: the flagship crack + its oracle, the byte-verified pf*.c regression ladder (the seeds' own "Method/reproducibility" cites it), the dump.sh/mon*.sh harnesses, and the banked giants' drafts. d_pf*.i.*, *.s, dumps_m*/, and the ILS/permuter .logs stay ignored (regenerable via dump.sh). Negative control re-verified. Lesson (→ R31/decision-log): a doc that cites a path is an untested claim about the repo — the citation and the file were four days out of sync, and only reading the seed for an unrelated reason caught it. Candidate for a lint (cookbook path citations must resolve to tracked files).