Skip to content

feat(ledger-health): orphan-token audit + scope batch5 down (#75) - #76

Open
squid-protocol wants to merge 2 commits into
mainfrom
feat/ledger-orphan-token-audit-75
Open

feat(ledger-health): orphan-token audit + scope batch5 down (#75)#76
squid-protocol wants to merge 2 commits into
mainfrom
feat/ledger-orphan-token-audit-75

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Closes #75.

The problem

A collective deviation_ledger.json entry lists a signal union of N tokens across M languages; the reports read it as the N×M cross-product of excused cells (bias_report.explain_out_of_band, docs/GATING.md "ledgered"). The shapes an entry documents retire one at a time — a decoy gets planted, an engine rule narrows, a metric re-baselines — and nothing notices when the last out-of-band cell a token still explained goes green. The token then sits in the union excusing a dead cell nobody looks at, which the ledger _doc rule already forbids: "a token must hold for EVERY language listed." #75 showed this is structural — batch5-tier2-morphology-shapes had decayed for the third time.

The automation (tools/ledger_orphan_check.py)

A scan-free, baseline-gated audit modelled on na_check.py:

  • Flags orphan tokens — a validated signal token that has a comparable cell but is in band on all of them. Resolves apiraw_arch_api (the engine's own RISK_INPUT_COLUMNS map) so it reads the column the signal is actually measured under; skips n/a tokens (that's na_check's domain) and ungated/pseudo-signal tokens (api_orphan_credit, structural_boundaries, vocabulary columns) that are never banded.
  • Cannot disagree with the gate — it reuses bias_report.out_of_band_cells/reference_medians, the exact banding bias_report.py --gate uses.
  • Baseline-gated, report-not-hard-gate (answering batch5-tier2-morphology-shapes has decayed again: 4 of its 8 signal tokens now excuse nothing, and one of them is factually wrong #75's open question) — docs/orphan_token_baseline.json holds the reviewed backlog; --ci fails only on new orphans; the human report highlights partial-decay entries (some tokens dead while others still hold) as the scope-down candidates.

Responsive wiring:

  • verify.yml gates PRs on new orphans (seconds, scan-free).
  • bias-history.yml re-baselines in lockstep with the cache against engine main, so engine drift re-baselines itself and a PR's --ci only ever sees orphans the PR introduced.
  • bias_report.py prints an orphan summary on every regen.

Current backlog: 47 orphan tokens across 37 entries, 8 partially decayed — the first run already proves #75's thesis was corpus-wide, not a batch5 quirk.

batch5 scope-down

Dropped safety from the union: #59 retired the css/yaml safety pairing and against engine main 08a08c6 all five languages read the median (green), so it excused nothing — removing it changes no gate outcome (gate stays at 0 unexplained). Kept branch/doc (real, still-true documented shapes not deviating today), now recorded in the orphan baseline as reviewed-dormant so the next reader doesn't re-litigate them.

A live demonstration of why this is needed

#75 was measured against engine 15d7af4 and proposed also dropping high_risk_execution (orphaned + its "no JCL form" claim disproved by #72). But against current engine main 08a08c6, high_risk_execution reads 2 vs median 3 for css/html/jcl/yaml and is load-bearing again; meanwhile api's real deviation moved onto raw_arch_api. The audit caught that #75's own hand-analysis had gone stale in five days — exactly the decay it exists to catch — so I did not hand-apply the stale token list; the tool is the source of truth. The verdict records all of this.

Verification

  • ledger_orphan_check.py --ci → exit 0 against the committed baseline; drop any baselined token and it exits 1 with the offending cells named.
  • bias_report.py --gate equivalent: 0 unexplained cells after the safety drop.
  • YAML/JSON validated; no import cycle (deferred import, like findings_report).

Cross-repo

None — self-contained in this repo. No engine change is required; the audit reads the committed docs/bias_data.json cache that bias-history.yml already maintains against engine main.

🤖 Generated with Claude Code

squid-protocol and others added 2 commits September 5, 2026 22:35
…itgalaxy#2789

Corpus side of gitgalaxy#2770, step 2 of GATING.md's cross-repo flow. The engine
half is gitgalaxy#2789, merged at 08a08c6a with the rosetta:rebless-owed label.

No manifests move: dependency_density is a bias-report metric derived from the
import_count and coding_loc recorder columns, not a SIGNAL_SCHEMA key, so no
expected_signals.json cell changes and no verify_language gate moves --
confirmed by #2789's own rosetta-audit ("46 language(s) checked -- 0
regression(s), 2 pre-existing, 0 broken", the two pre-existing being the
objective-c/typescript args drift already re-blessed here by #66).
bias-history.yml regenerated the report against engine 08a08c6 in 8ba80c2, so
the numbers are already on main. This is the ledger work automation cannot do.

control-flow-ratio-denominator-is-a-vocabulary-tally -- NARROWED. Its reading of
the SPREAD stands and its cells stay explained, but two other claims did not
survive being checked against the engine source:

  1. "No engine change is wanted" was scoped to control_flow_ratio itself and
     silently covered its derived consumer: dependency_density divided by
     max(int(coding_loc * control_flow_ratio), 1), so a GATED metric was reading
     this ungoverned denominator. #2789 removed that dependency.
  2. The "gitgalaxy compares control_flow_ratio between files WITHIN one
     repository, where the vocabulary is held constant" defense has two holes
     the entry never tested. It is a WITHIN-language defect that
     control_flow_ratio is 0 for any branchless file -- measured over all 46
     languages' 184 shells, 133 (72%) record 0, and in 39 of 46 languages
     exactly three of the four do, since only main.* carries the planted
     branches -- giving any consumer that multiplies by it a discontinuity of
     21x on yaml and 6x on python when one `if` is added. And the
     within-repository premise holds only for a monolingual repo:
     security_auditor._build_feature_frame, the very consumer the entry cites,
     one-hot encodes language but applies no per-language normalisation and no
     groupby.

still_reproduces stays true -- the vocabulary tally is still what
control_flow_ratio's own cells measure. Under gitgalaxy#2770 shape (b), branch
over coding_loc, the metric becomes plantable and this entry retires instead.

no-dependency-capture-languages -- figures superseded, resolution unaffected.
Its resolved m4/yacc profile quotes dependency_density "1.0 on a/b and
0.1667-0.2 on main", measured when the denominator collapsed to 1 on a
branchless file, so "1.0 on a/b" was the raw import count rather than a density.
Re-measured at the new definition: 0.02 on a/b/main and 0.0 on c for both
languages -- still the healthy sibling shape, still_reproduces stays false. The
old numbers are kept in place because they are what was measured at the time.

docs/findings_by_language.md regenerates off the ledger, so #2770 joins the
issue list for the languages the narrowed entry covers. That is its whole diff.

Gates: bias_report.py --gate exit 0 (0 unexplained cells, 0 length leaks);
na_check.py exit 0 (0 unreviewed n/a cells). bias_report.md, bias_data.json and
bias_variance_chart.svg regenerate to a ZERO diff against 8ba80c2, confirming
this PR changes no measurement. dependency_density's consistency badge reads
93%, up from 83% -- and the old 83% was itself an artifact of the denominator
being the constant 1 for most cells.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016BHBDqfybkLJqnQt9AoyTt
Collective deviation-ledger entries decay silently: an entry lists a `signal`
union of N tokens across M languages, the reports read it as the N×M cross-product
of excused cells, and the shapes it documents retire one at a time (a decoy gets
planted, an engine rule narrows) while nothing notices when the LAST out-of-band
cell a token still explained goes green. The token then sits in the union excusing
nothing. #75 found this is structural, not sloppy -- batch5-tier2-morphology-shapes
had decayed a third time.

## The automation (the durable fix)

tools/ledger_orphan_check.py -- a scan-free, baseline-gated audit modelled on
na_check.py. Flags every validated signal token that has a comparable cell but is
in band on all of them (an ORPHAN), resolving api→raw_arch_api via the engine's own
column map and skipping n/a and ungated tokens. It reuses bias_report's
out_of_band_cells so it can NEVER disagree with `--gate` about which cells are out
of band. `--ci` fails only on NEW orphans beyond docs/orphan_token_baseline.json;
the report highlights "partial-decay" entries (some tokens dead, others still hold)
as the scope-down candidates.

Wired to be responsive: verify.yml gates PRs on new orphans; bias-history.yml
re-baselines in lockstep with the cache (so engine drift re-baselines itself and a
PR only ever fails on orphans it introduced); bias_report.py prints an orphan
summary on every regen. Current backlog: 47 tokens across 37 entries, 8 partially
decayed -- the automation's first output already proves #75's thesis was corpus-wide,
not a batch5 quirk.

## batch5 scope-down (the motivating entry)

Dropped `safety` from the signal union: #59 retired the css/yaml safety pairing and
against engine main 08a08c6 all five languages now read the median (green), so it
excused nothing -- removing it changes no gate outcome. Kept `branch`/`doc` (real,
still-true documented shapes not deviating today) recorded in the orphan baseline as
reviewed-dormant so they aren't re-litigated.

Notably, #75 (measured against the older engine 15d7af4) proposed dropping
`high_risk_execution` too -- but against current engine main it reads 2 vs median 3
and is load-bearing again, and `api`'s real deviation is on raw_arch_api. The audit
caught that #75's own hand-analysis had already gone stale, which is exactly the
decay it exists to catch. Verdict updated to record all of this; gate stays green
(0 unexplained).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W5quEPoCFpsoz4hNP2uPyq
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

batch5-tier2-morphology-shapes has decayed again: 4 of its 8 signal tokens now excuse nothing, and one of them is factually wrong

1 participant