Files
BFM-decomp/tools/audit_digest.py
T
Drew T 1576570271 fix(phase-30 S1e): the distinct-code "regression" was a STALE DIGEST — alias lever ungated
The S38 checkpoint gated the phase's best lever ("do NOT scale the alias lever") on
distinct-code falling 89.3 -> 89.2. It never fell.

PROOF (each commit's metric recomputed from its OWN committed tree, 0 unresolved):
  commit:1426 TRUE     : instr 12394533  distinct 5022306  (77895 uniq)
  commit:1426 COMMITTED: instr 12402412  distinct 5029324  (78025 uniq)   <- stale
  HEAD TRUE == COMMITTED: instr 12405402  distinct 5025082  (77952 uniq)
  => true delta 843->HEAD: instr +10869, distinct +2776 ins / +57 uniq. ALL ROSE.
The 843 digest was generated from a working tree still holding work REVERTED before the
commit landed (+7,879 ins / +130 uniq overstated) and never regenerated, so the next
HONEST digest read as a fall. => THE ALIAS LEVER IS UNGATED (scale it, §61 small batches).

Both recorded leads were wrong (R14): progress.py:423's SIG regex feeds fn-count ONLY
(neither weighted metric sees a C identifier — both derive matched = sig - corpus.stubs),
and "the harvest reverted functions to INCLUDE_ASM" died on one grep (483 removed, 0 added).
The 3-grep proof: identical sigs + unchanged tools/ + zero +INCLUDE_ASM => HEAD's stub set
is a strict subset => both numerators are FORBIDDEN to fall.

THREE INSTRUMENT DEFECTS, all one class (a bare except around a fail-CLOSED oracle):
- progress.py stub_addrs wrapped corpus.stubs in `except Exception: return set()`. An empty
  stub set means "could not answer", not "no stubs", so matched = sig - stubs credited EVERY
  function. Byte-witnessed: instr 100.00% / distinct 100.00% in a tree with no asm/. Now
  propagates.
- cast_call_sites.tu_for + reconcile_tu.tu_for had the identical swallow, falling back to the
  default <ov>.c instead of the jr/-O0 split TU — silently reinstating the exact bug
  cast_call_sites' own docstring says it exists to fix. A wrong-TU reconcile fails the gate,
  and this phase's base rate is ~24k PLUMBING vs 4,917 DIFF, so it presents as a codegen wall.
  Now propagate CorpusError; ValueError fallback for curated names preserved; derived-TU path
  re-verified (a _jr_ split stub resolves correctly, both tools agree).

NEW GATE (R34 — the byte-gate is a null oracle for DOCUMENTS; check-all stays 140/140 over a
stale digest forever): tools/audit_digest.py + `make audit-digest`, wired into tools-health
after report. Recomputes the three headline metrics from the current tree and fails if the
committed digest disagrees. Compares INTEGERS, not percentages — the +7,879-instruction
staleness printed as "94.4%" on both sides. Negative-control-proven against the stale 843
digest (fails, exit 1) and green on HEAD.

Verified: make report exit 0 (dedup-check 1910 validated / 0 failed, C1 coverage
241216/241216); audit-digest OK; cookbook-index OK (398 sections); metrics unchanged by the
fix (94.40% / 89.18%). No src/ or config/ edits — no bytes touched, nothing banked.

cookbook §140 · decision-log 2026-08-04 · SETUP.md inventory (R21) · R14/R32/R34/R35.
2026-08-04 21:48:57 -06:00

130 lines
6.2 KiB
Python

#!/usr/bin/env python3
"""tools/audit_digest.py — does the COMMITTED fleet digest still describe the CURRENT tree?
WHY THIS EXISTS (Phase 30 S1e)
===============================
`docs/progress.fleet.md` is the project's headline instrument: the burn-down, the roadmap's
re-baselines, and every "is this lever paying?" call are read off its three numbers. It is written
by `tools/progress.py --fleet` from whatever tree happened to be on disk at that moment — and then
COMMITTED, at which point nothing ever checks it again.
That gap produced a real, costly false alarm. The S38 digest committed at `commit:1426` claimed:
instr 12402412 distinct 5029324 (78025 uniq)
The same metric recomputed from `commit:1426`'s own committed tree gives:
instr 12394533 distinct 5022306 (77895 uniq)
— overstated by +7,879 instructions and +130 unique functions, because the digest was generated
from a working tree that still held banked work which was REVERTED before the commit landed, and
was never regenerated afterwards. The next honest digest was therefore LOWER than the stale one, so
the metric appeared to FALL (distinct-code 89.3 -> 89.2) while the tree had in fact only gained
(true delta over that span: instr +10,869, distinct +2,776 ins / +57 unique fns — everything rose).
A session then opened with "distinct-code FELL — UNEXPLAINED; do NOT scale the alias lever until it
is resolved", i.e. the project's best-performing lever was gated on a phantom regression, and the
recorded lead (a name-scanning regex in classify()) pointed at a function that does not feed either
weighted metric at all.
WHY THE EXISTING GATES CANNOT SEE IT (R34)
==========================================
The whole-binary byte-gate is a perfect CORRECTNESS oracle and a NULL oracle for documents: a stale
digest is byte-irrelevant, so `make check-all` stays 140/140 across it forever. `audit-corpus` and
`audit-binaries` assert things about the CODE. Nothing asserted that the number we publish about the
tree is a number OF that tree. This is that second, disagreeing oracle — and its only job is to
disagree when the digest and the tree have drifted apart.
WHAT IT ASSERTS
===============
Recompute the three headline metrics from the CURRENT tree and require the committed digest to
match. A mismatch is not "the numbers moved" — it is "the published number was never true of this
tree", and the fix is always the same: `make report`.
Exit 0 = the digest describes this tree. Exit 1 = it does not (message says which metric drifted).
Usage: tools/audit_digest.py [--fix]
"""
import re
import sys
import os
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(REPO, "tools"))
DIGEST = os.path.join(REPO, "docs/progress.fleet.md")
# The three headline lines, exactly as progress.fleet() writes them. Parsed as integers (the
# printed percentages are rounded to 1dp, so they are far too coarse to catch a 130-function drift —
# the +7,879-instruction staleness above still rendered as "94.4%" both before and after).
_LINES = {
"fn-count": re.compile(r'^FLEET fn-count byte-ident:\s*(\d+)\s*/\s*(\d+)', re.M),
"instr": re.compile(r'^FLEET instr-weighted\s*:\s*(\d+)\s*/\s*(\d+)', re.M),
"distinct": re.compile(r'^FLEET distinct-code\(uniq\):\s*(\d+)\s*/\s*(\d+)\s*=\s*[\d.]+%\s*\((\d+)/(\d+)', re.M),
}
def committed():
"""The three metrics as published in docs/progress.fleet.md."""
if not os.path.exists(DIGEST):
raise SystemExit(f"audit-digest: {os.path.relpath(DIGEST, REPO)} does not exist — run `make report`.")
txt = open(DIGEST).read()
out = {}
for key, rx in _LINES.items():
m = rx.search(txt)
if not m:
# R32: a line we cannot read is a DEFECT, not a skip — a silently-unparsed headline is
# exactly the blindness this file exists to remove.
raise SystemExit(f"audit-digest: cannot parse the '{key}' line out of "
f"{os.path.relpath(DIGEST, REPO)} — the digest format changed and this "
f"oracle went blind. Fix the pattern, do not delete the check.")
g = [int(x) for x in m.groups()]
out[key] = tuple(g)
return out
def live():
"""The same three metrics, recomputed from the CURRENT tree."""
import progress
# fn-count comes from the per-binary classification; the weighted pair from the derived stub
# oracle. Both are recomputed here exactly as `progress.fleet()` does it.
order = [b for b in ("main", "resident") if b in progress.BINARIES] + \
sorted(b for b in progress.BINARIES if b not in ("main", "resident"))
rows = [progress.report(b, write=False) for b in order]
byte = sum(r["byteident"] for r in rows)
match = sum(r["matchable"] for r in rows)
wm = progress.weighted_metrics()
if not wm:
raise SystemExit("audit-digest: no .run/sig.*.jsonl — run `make sig-overlays sig-resident`.")
return {
"fn-count": (byte, match),
"instr": (wm["fleet_m"], wm["fleet_t"]),
"distinct": (wm["dedup_m"], wm["dedup_t"], wm["dedup_fns"], wm["dedup_total_fns"]),
}
def main():
fix = "--fix" in sys.argv
have, want = committed(), live()
bad = [k for k in want if have.get(k) != want[k]]
if not bad:
print(f"audit-digest: OK — docs/progress.fleet.md describes the current tree "
f"(instr {want['instr'][0]}/{want['instr'][1]}, "
f"distinct {want['distinct'][2]}/{want['distinct'][3]} uniq).")
return 0
print("audit-digest: FAIL — the committed digest does not describe the current tree.")
print(" A stale digest is BYTE-INVISIBLE (check-all stays green over it), and a later honest")
print(" regeneration then reads as a REGRESSION that never happened. See this file's header.")
for k in bad:
print(f" {k:9s} committed {have.get(k)} actual {want[k]}")
if fix:
print(" --fix: regenerating…")
import progress
progress.fleet()
return 0
print(" Fix: `make report` (regenerates the digest), then commit it WITH the work it describes.")
return 1
if __name__ == "__main__":
sys.exit(main())