Commit Graph

11 Commits

Author SHA1 Message Date
Drew T db63fcc673 tools(phase-35): T6 part 2 — the dead macro branches dropped from 12 live tools; the macro-form guard in tool_census --check (ast scan of every LIVE tool, FROZEN/retired/6 whitelisted detectors excluded; 0 LIVE tools reference the retired form; --guard-root negative control: the pre-T4 tree flags exactly the 12 fixed + 3 retired); progress.py: an empty-bodied included member is EMPTY, not folded into REAL (the R32 bucket assertion caught the double count) — the fleet denominator 363,221 -> 363,680 (+459: SC03_015's 219 single-site macros, SC03_118 +3, the never-extended members of five groups) and REAL 360,744 -> 350,533 with EMPTY up the same; progress.json + README block + fleet table regenerated; SETUP; kit corpus 2026-09-08 20:53:05 -06:00
Drew T 9fc27960e9 feat(integration): teach the rest of the toolkit about §378 (self-caller cast)
The lever existed but nothing downstream applied it. Proof it mattered: a wave
agent this session diagnosed its own blocker as "§378 THE SELF-CALLER CAST, a
TU-level fix (cast_self_callers.py) that requires editing src/, which I'm not
permitted to touch" — the knowledge propagated, the automation did not.

* recover_integration.py: NEW "self-cast" stage (tier=binary), so the driver can
  run the whole chain as --stages arity,self-cast. The docstring states WHY the
  order is not arbitrary: self-cast answers the error that "arity" CREATES.
* residual_rules_b.py: both decl-conflict tiers now prescribe the full chain
  instead of "route to integration / budget for banking", and
  NOCOMPILE-UNDECLARED-FIXED now says outright NOT to gate the autodecl arm (it
  is a second conflicting declaration in the real TU).
* wave-playbook §4b: replaced the stale two-step recipe with the three-step
  chain, the one-driver form, the callee variant, and the MANDATORY
  --undo-journal.
* SETUP.md: full inventory row (R21) — it had zero mentions.

Not wired, deliberately: gate_stage's ladder rewrites DRAFTS via _xform, while
this edits the TU; a src-side edit inside the automatic gate needs
revert-on-failure, which recover_integration already owns.

Still open: a draft_prechecks rule to catch the self-decl conflict statically,
before a build is spent. The new stage's plumbing is verified (CLI + candidate
selection); its functional end-to-end run is NOT — gate12 held the tree.
2026-09-01 11:03:06 -06:00
Drew T 8ae40e10d2 fix(recover): exempt --probe-only from the single-instance lock — it writes nothing
The lock I added earlier today guards a real hazard (the driver mutates the shared tree and is not
parallel-safe), but I scoped it to the whole tool instead of the mutating path. --probe-only execs
blocker_probe, which compiles in its own scratch dir and touches nothing — excluding it buys no
safety and costs a free diagnostic.

Measured cost: a t7b drafting agent (func_801832E0) tried the probe TWICE, was refused both times by
a concurrent sweep holding the lock, and submitted with its blocker unconfirmed — exactly the $0
diagnostic the pack tells agents to run first.

Control: with the lock held, --probe-only now returns rc 0 and its verdict table; the mutating path
still returns rc 1 REFUSED.
2026-08-29 19:33:13 -06:00
Drew T 25b72baa8a fix(recover): single-instance lock — the driver is not parallel-safe and now refuses instead of corrupting
Three properties compose into tree corruption under concurrency:
  (a) assert_write_set measures a GLOBAL git status, so a concurrent run's writes read as THIS
      run's blast-radius violation and abort it;
  (b) an abort does NOT restore the stage edits already on disk;
  (c) gate_stage's commit is a deliberately broad 'git add -u src/' — and it must be, since
      propagation touches many overlays and a narrower filename glob once DROPPED four R22-verified
      banks — so a concurrent --commit sweeps the aborted run's half-applied edits into its commit.

Measured today: xargs -P 4 over 33 binaries put 696 broken lines of ov_MAIN_012 into md_MAIN_026's
+1 bank commit; check-all went 212/213 and the wave bank was blocked behind it (R59).

Narrowing the gate's git add was the WRONG fix (it would restore defect (c)'s predecessor). Instead
the driver enforces its own contract: flock on .run/recover/.driver.lock, refuse loudly (R43).
Control: with the lock held -> rc 1 REFUSED; lock free -> rc 0 and the probe runs normally.
2026-08-29 15:51:25 -06:00
Drew T edec2adb99 fix(recover): --probe-only crashed for --funcs/--auto/--from-file (it exec'd the probe BEFORE staging)
os.execv'd tools/blocker_probe.py with --drafts <run_dir>/drafts while that directory was still
created further down, so every non---draft-dir probe died with FileNotFoundError. Only --draft-dir
worked, because stage_drafts() had already populated the dir. Staging now happens first.

Control: the --draft-dir path returns the same verdict as before the move (ov_SC06_029
func_80185214 -> DIFF 52/52 ins, identical to the pre-edit run). --funcs now works: 10 backlog
candidates classified in one pass (2 real-TU MATCH, 3 conflicting-types, 2 too-few-arguments,
1 parse error).

Worth recording (R40): my own probe loop grepped for result rows and swallowed the traceback, so the
crash read as 'no blockers found' — a silently narrowed scope in the harness, not the tool.
2026-08-29 13:41:51 -06:00
Drew T 6ed0f77b6a fix(recover): gate the RAW draft first — macro-externs is a fallback, not the measurement (+ classify_fail drops orphan notes); cookbook §313
recover_integration's macro-externs stage rewrote a draft's callee extern to the FLEET macro's
signature and then gated only the rewrite. func_ADDR names are per-address, not per-function, so
another overlay's 'extern void func_8017C338(void)' replaced this overlay's correct 4-arg decl and
manufactured the CC1-FAIL it reported as the draft's failure. The untouched draft banks
byte-identical (ov_SC03_012:func_8017BEBC, 246 ins, banked in the previous commit).

reconcile_and_gate(draft_rewrite=) now gates raw (pass 1a) then rewrites only what raw refused
(pass 1b), records the winning variant per fn, and re-gates that variant in pass 2.

harvest_verify.classify_fail kept the 'note:' half of a benign warning pair and labelled a built
draft CC1-FAIL with it; notes now drop with their warnings. Negative-controlled over 5 diagnostic
shapes — only warning+note-only changed (to the honest no-diagnostic label). R39/R57/R32.

Cookbook 920 -> 921 sections, index green.
2026-08-29 12:26:02 -06:00
Drew T 1a8cda6c54 feat(phase-31 T6): PLUMBING campaign — +9 banked (64% probe); recipe + 3 laws (§173)
- tools/plumbing_groups.py: derives the honest still-open pool from the classified
  ledgers (R38) — '1,217 PLUMBING' collapsed to 237 (SELF 109 / CALLEE 48 / OTHER
  48 / DATA 32)
- recover_integration: PER-GROUP ISOLATION (git-checkout binary TUs between groups
  — one TU-stage edit was poisoning every other group's whole-binary gate with a
  phantom shared error; per-group banked_from_source capture) + new stages
  'macro-externs' (§121 draft-tier, via family_sweep.macro_def_sig_map, R33) and
  'tu-scope' (§103 STU binary-tier, the sweep-only lever)
- the probe (ov_SC03_107): raw 0/14 -> root-caused (poisoning + stale seed
  symbols; rtu_match MATCHes them — blind to reloc names, R34) -> symfix-first
  -> 9/14 BANKED (64%)
- sweep finding (Law 3): the no-draft majority (ov_SC02_037 44/44, most of
  ov_MAIN_012) had verdicts from transient sweep remaps never persisted — family-
  lane fuel, not recovery fuel; the stored-draft class is consumed
- cookbook §173 (symfix-first / per-group isolation / verdicts-without-drafts);
  index 518 green; R22 clean fleet 213/213; phase total 17 banked @ 0 agent tokens
2026-08-14 19:42:55 -06:00
Drew T ffca2e4803 feat(phase-29): T16.10 — the driver's SUCCESS path verified (free re-bank test); 2 defects fixed
- THE FREE TEST (cookbook §66): reverted func_801778A8's bank to its INCLUDE_ASM stub (stub state
  rebuilds BYTE-IDENTICAL 7ca772be — a faithful revert proves itself; needs `make extract` first,
  the R22 corollary) and re-banked it THROUGH recover_integration.py --commit --r22.
  pass1 1/1 -> exact restore -> pass2 1/1 -> commit commit:0928 -> R22 140/140 -> report.json.
  Bank confirmed from SOURCE (stub gone), never the report (§55b trap 4). EQUIVALENCE: git diff vs
  the pre-revert commit = ONE blank line (mine) -> the driver reproduced SESSION-16's state exactly.
- DEFECT 1 (SAFETY, found by reading before firing): PROPAGATION is a fleet-tier write
  (dedup_propagate --auto-from -> src/shared/engine_core.h + up to 138 overlay .c) that was both
  UNDECLARED and the DEFAULT, so --max-tier binary still permitted the widest write in the toolchain.
  assert_write_set cannot catch it (it runs before the gate; under --commit git status is clean).
  FIXED up front: propagate now requires --max-tier fleet AND --r22, and is REFUSED after a
  demacroize stage (those banks are x1 by construction; --auto-from would re-macroize and undo them).
  Both refusals negative-control-tested, exit 1. The "standing hazard" is now a refusal.
- DEFECT 2 (METRIC): gate_stage scraped the fleet % via a progress.py label that no longer exists ->
  fp=None -> 50 gate commits recorded "fleet None%". Now reads FLEET instr-weighted (legacy fallback
  + loud stderr warning if neither matches); parses 79.6.
- STALE DIGEST (R14): docs/progress.fleet.md at HEAD disagreed with HEAD's own source by 45 in the
  dedup-shared column — generated during the §65g local_type trial whose edits were then reverted.
  Regenerated (reproduced identically in-gate + standalone); headline %s unaffected.
- cookbook §66/§66a/§66b distilled in-session (R30); SETUP.md gains the missing recover_integration
  row (R21 debt). tools-health OK: corpus 0/0, cdecl green, audit-binaries 140 citizens, lint OK,
  dedup-check 1879/0. Fleet unchanged 79.6% instr / 67.7% distinct / 88.86% fn-count.
2026-07-24 15:33:25 -06:00
Drew T 9137d3b784 feat(phase-29): T16.4 — encode the recovery recipe in recover_integration.py (tiers ENFORCED, §55b trap 4 closed)
Extended, not replaced: it already owned exact snapshot/restore, split-aware grouping and the two-pass
gate-all -> restore -> re-stage-winners protocol. A new driver would be a 7th snapshot impl (R33).

- --draft-dir (repeatable): consume a WAVE dir instead of the backlog (unreliable closeness,
  overlay-specific drafts). Strict ^func_[0-9A-Fa-f]{8}\.c$ filter -- the wave dirs carry scratch
  (_b.c, try2.c, scratch/) and run_gate globs *.c blindly.
- --run-id: all scratch under .run/recover/<id>/, and run-local verified_out/failed_out passed into
  run_gate -- closes §55b trap 4 (the accumulating .run/harvest_verified.txt phantom bank), which the
  cookbook still lists as "still armed".
- --stages with the new demacroize stage; --max-tier; --r22; --probe-only; --report.
- TIERS ENFORCED not documented: stages declare T0/T1/T2, the driver MEASURES the write set
  (git status before/after) and ABORTS if a stage writes outside its blast radius (§61d). A fleet-tier
  stage is refused without --max-tier fleet AND --r22. Both refusals negative-control-tested.
- stub_map now derives from corpus.stubs (R33, coverage-asserting) instead of a private regex that
  could silently return a short map; banked_from_source() is the sole bank oracle for reporting.
- End-to-end on the remaining 22: excluded 26 already-banked by name, demacroize ran on 12, banked 0,
  restored exactly (src/ clean), 14/14 prior banks intact. A clean negative -- it does not manufacture
  banks. Those 22 need normalize_self_decls / draft type-uniquify wired next.
2026-07-24 14:37:59 -06:00
Drew T d7b877f12c fix(phase-25): recover_integration split-aware (§39) — per-stub asm-subdir, gate per split group
--auto silently skipped the 263-stub ov_SC01_077_after cohort: the drift-check hardcoded
the main asm subdir and gate_stage was never passed src/asm/src_file. Now stub_map() reads
each stub asm subdir from its INCLUDE_ASM line, the drift-check uses the per-fn subdir, and
reconcile_and_gate groups targets by split file, gating each via run_gate(src=,asm=,src_file=).
fix_arity_callers/dedup_propagate already split-aware; harvest_verify self-filters per split.
2026-07-08 01:23:08 -06:00
Drew T 91e5c4c294 feat(phase-24): T6 — integration-recovery tool (gate-recovery proven; ×134 propagation deferred)
The integration-recovery tool for leaf-MATCH-but-whole-binary-gate-rejected fns ("declaration/TU
plumbing" — the dominant residual gate_stage's canon/cast/sig_unify pipeline doesn't reach).

- tools/recover_integration.py (NEW): batch recovery — gather leaf-MATCH candidates (--auto from
  the backlog, drift-checked R14; or --funcs/--from-file) → no-proto their conflicting caller decls
  → gate_stage (byte-gate + log). 2-PASS snapshot/restore: pass 1 finds the bankable set, pass 2
  re-banks ONLY winners from the clean snapshot (so non-banks are never corrupted).
- tools/fix_arity_callers.py: extended with --binary — scan+rewrite the overlay's OWN inline caller
  decls (src/<bin>/<bin>*.c), not just engine_core.h. That was THE gap: a conflicting caller extern
  is often inline in the overlay src (e.g. func_8016E778's `extern void f(void)` vs def `f(int)`),
  which fix_arity_callers never saw -> the fn stayed unbanked.
- VALIDATED: banked 13 leaf-MATCH fns (func_8014F74C/801542A4/8015BE94/8015F380/80160F00/801653B8/
  80166244/8016E778/801732C4/8017331C/80173374/80174554/801745AC), CLEAN-verified together
  (ov_SC01_077 d19c9580). The banks themselves are reverted here (they re-bank via the tool and
  will land ×134 once propagation-recovery lands — cleaner than committing ×1).
- R14 lesson (clean-verify caught it, R22): fix_arity_callers --revert is LOSSY for --any-proto
  (()->(void), not back to the original args) -> corrupted non-banks; fixed with the 2-pass snapshot.
- REMAINING T6 (×134 propagation-recovery, 3 diagnosed blockers): (1) dedup_propagate find_site
  misses INDENTED inline defs (Phase-15 class); (2) overlay-local-type lift; (3) auto-reconcile the
  straggler's conflicting caller externs (the flagship func_80132784 / ov_SC02_005 class, done by
  hand — needs automating). See CURRENT_PHASE.
2026-07-03 13:33:13 -06:00