Skip to content
fitme·story
Case studies
v7.10 · 3 min read · 2026-06-10

T13 Per-Gate `last_failed_at` Index — distinguishing "stopped running" from "running + catching" (v7.10)

F17 materialized "when did this gate last run?" per gate in O(1). But "ran" and "caught a violation" are different signals, and F17 only had the first — a gate could fire every cycle and never catch anything (healthy, or toothless) and F17 couldn't tell. T13 extends the index to schema v2 with a per-gate last_failed_at, sourced from the integrity-snapshot history (coverage rows carry no pass/fail signal). 6 cycle-time gates populated from 14 snapshots. The interaction with v7.10's GATE_COVERAGE_ZERO mis-wire detector became the improvement: a 0-candidate gate WITH failure history is demonstrably running, so requiring last_failed_at is None before flagging cleared 4 false advisories.

GATE_COVERAGE_ZERO (last_fired only)
4
false advisories — 0-candidate cycle-time gates flagged as silent, though they were demonstrably running and catching.
GATE_COVERAGE_ZERO (last_fired + last_failed)
0
false advisories — a 0-candidate gate WITH failure history is proven running, so it is no longer flagged.
What do T1 / T2 / T3 mean?
T1Instrumented — from a ledger/commit
T2Declared — stated, not measured
T3Narrative — estimate from memory

T13 Per-Gate last_failed_at Index

Status: shipped 2026-06-10. Extends F17 (the last_fired_at materialized index) with failure history, completing the meta-layer's ability to reason about each gate's health.

The gap F17 left

F17 (v7.9.1) materialized last_fired_at per gate from the append-only gate-coverage.jsonl stream — answering "when did this gate last run?" in O(1). The v7.10 GATE_COVERAGE_ZERO meta-check uses it to flag gates that went silent.

But "ran" and "caught something" are different signals, and F17 only had the first. A gate could be firing every cycle and never catching a violation — healthy, or possibly toothless — and F17 couldn't tell.

The scoping surprise: coverage rows have no failure signal

The obvious move — derive last_failed_at from gate-coverage.jsonl — doesn't work. Coverage rows track {candidates, checked, skipped} (did the gate run), not pass/fail. A gate "failing" means it emitted a finding, and findings aren't in the coverage stream.

The clean source turned out to be the integrity-snapshot history (.claude/integrity/snapshots/<ts>.json): each snapshot carries a timestamp + a findings[] array of {code, severity}. Scanning them gives, per gate code, the most recent snapshot where it appeared.

What shipped

refresh-gate-last-fired.py (schema v1 → v2) now overlays, per gate:

  • last_failed_at — most recent snapshot timestamp where the gate code appeared in findings[]
  • total_failure_snapshots — count of distinct snapshots it appeared in (deduped within a snapshot)
  • last_failure_severity — the severity in the most-recent failing snapshot

Gates that appear only in failure history (a cycle-time code with no coverage row) get a minimal index entry, so the index stays complete. The snapshots dir is derived relative to the ledger path so a tmp-dir ledger in tests resolves to an empty dir (hermetic) while production resolves the real one.

Live: 6 cycle-time codes populated from 14 snapshots [T1] (BROKEN_PR_CITATION last failed 2026-06-04, TIER_TAG_LIKELY_INCORRECT 2026-06-07 across 7 snapshots, etc.). Refresh stays well under the <1s budget.

The interaction that became a refinement

Adding failure-only codes to the index made the v7.10 GATE_COVERAGE_ZERO mis-wire detector false-fire on 4 cycle-time codes (BRANCH_ISOLATION_HISTORICAL, CACHE_HITS_AUTO_INSTRUMENTATION_INACTIVE, PHASE_LIE, TIER_TAG_LIKELY_INCORRECT): they have candidates==checked==skipped==0 (no Mechanism A coverage) but DO appear in snapshots. That's not a mis-wire — they're cycle-time advisory codes that legitimately don't emit coverage.

Documented limitation

Write-time gates block commits rather than logging, so their blocks never reach a snapshot — last_failed_at is meaningful for cycle-time + advisory codes only. Recorded in the index's failure_history_note; a write-time block ledger is a T13.1 follow-up.

Verification (2026-06-10)

  • test_refresh_gate_last_fired.py + test_gate_coverage_zero.py: 27 pass [T1] (incl. 5 new merge-failure-history tests + 1 mis-wire-vs-failure-history test)
  • Full coverage/integrity suite: 22 pass [T1]
  • make integrity-check0 findings [T1] (the 4 false GATE_COVERAGE_ZERO advisories cleared)

Cross-references

Honest disclosures
  • last_failed_at is meaningful for cycle-time + advisory codes only — write-time gates block commits rather than logging findings, so their blocks never reach an integrity snapshot and never populate failure history (recorded as the index's failure_history_note; a write-time block ledger is a deferred T13.1 follow-up).
  • Failure history is derived from just 14 integrity snapshots populating 6 cycle-time gates — a thin, single-environment corpus, so "last failed" reflects the local snapshot history rather than a comprehensive cross-environment record.
Kill criterion · not fired
  • last_failed_at conflated with last_fired_at (a gate that ran but never failed shows a stale last_failed) — would mislead the meta-check.
  • Snapshot scan slows the index refresh beyond the &lt;1s budget.