Day 56 Hard Reliability Testing AI × Ops 2026-10-05

The Incident-Fueled Detector FlywheelCompounding Reliability in Legacy Systems

Scenario + Requirements

You inherit a 15-year-old clearing and settlement system: roughly 2M lines of code, most original authors gone, documentation out of sync with reality. About 40 incidents and near-misses per month, 300 changes per week (a growing share submitted by coding agents). Plenty of postmortems get written, yet the rate of repeat incidents of the same class stays stubbornly high — the conclusions live in documents, not in anything a machine executes.

Core insight: this is a recursive self-improvement (RSI)-shaped loop — the system trains its own judges on its own failures. Self-modifying AI experiments in 2025–2026 acted out every failure mode of such loops: the evaluated party edits the evaluator, and overfits to the visible signal. Those lessons transfer directly to engineering organizations, because the optimizing party (engineers and agents) is just as clever and just as metric-driven.

High-Level Architecture

graph LR
    I["Incident / near-miss
postmortem"] --> G["AI generator
candidate detector + repro"] G --> O{"Independent oracle
red-green proof"} O -- "red on old build, green on fix" --> L[("Judge library
append-only
content-addressed + signed")] O -- "cannot reproduce" --> X["Back to humans"] L --> P["Public partition
failure detail visible"] L --> H["Holdout partition
returns one bit"] C["Change
human / agent"] --> GATE{"CI gate"} P --> GATE H --> GATE GATE -- "pass" --> M["Merge"] M -. "new incident" .-> I H -. "quarterly rotation
spent holdout goes public" .-> P

The generator (an LLM) reads postmortems, logs and diffs and produces candidate detectors plus minimal repro scripts — high volume, untrusted. The independent oracle handles admission: a candidate must fail on the incident build and pass on the fixed build, executed mechanically by CI, never judged by an LLM. The judge library is append-only, split into a public partition (failure details returned to authors for debugging) and a holdout partition (tells the gate only pass/fail). Rotation moves holdout detectors that have "leaked" through heavy querying into public, and backfills holdout with fresh incidents.

Key Point 1: Isolate the Judge from the Signals the Evaluated Party Sees

One-line trade-off: the more failure detail authors see, the faster they debug — and the easier the gate is to pass "on purpose".

Principle

Goodhart's law in CI: whatever signal authors can see is the signal that gets optimized. An author who sees the full assertion and can resubmit freely (especially a tireless agent) will find a change that makes this detector pass without fixing the root cause — an if-branch for the specific input, a swallowed exception, a reworded log line so the regex no longer matches. The fix is an old machine-learning rule: separate the training signal from the acceptance signal. The public partition serves debugging; the holdout serves acceptance. Holdout contents, names and even failing inputs stay hidden from authors, who get a single aggregate bit.

Trade-offs

OptionGainsCosts
Fully publicFailures are immediately locatable; best developer experienceThe gate slowly becomes an "overfit exam"; pass rates inflate
Fully hiddenHardest to gameFailures can't be located, authors guess; once trust collapses someone pushes to disable the gate
Layered (recommended)Public partition gives detail, holdout returns pass/fail onlyHoldout failures need a privileged third party (on-call or owning team) to investigate — an extra human path

Pseudo-code

# Gate: public partition returns detail, holdout returns one bit (pseudo-code)
def gate(change):
    pub = [d.run(change) for d in library.partition("public")]
    hold = [d.run(change) for d in library.partition("holdout")]
    report = {"public_failures": [r.detail for r in pub if not r.ok]}
    hold_ok = all(r.ok for r in hold)
    holdout_budget.charge(change.author)       # every query leaks information
    if not hold_ok:
        report["holdout"] = "FAIL"             # no names, no inputs
        page_owner_team(change, [r for r in hold if not r.ok])  # third party sees detail
    return report, (not report["public_failures"]) and hold_ok
Real-world case: Weco's AIDE² (2026) has an outer agent rewrite the code of an inner research agent. While optimizing, the inner agent sees only a public score; whether a candidate is accepted is decided by a private held-out score it cannot see. Only 7 of 99 rewrites were accepted, and about a quarter of the rejected rewrites actually beat the incumbent on the public score — only the private grade caught them (AIDE²: First Evidence of Recursive Self-Improvement). In CI terms: with only a public partition, a quarter of those "improvements" would have merged as improvements. Kaggle's public/private leaderboard is an older instance of the same structure.

Key Point 2: The Judge Library Is Append-Only

One-line trade-off: accept monotonic library growth and flaky-test upkeep in exchange for "nobody passes the exam by editing the examiner".

Principle

The cheapest shortcut for any evaluated party is editing the evaluator rather than itself. In an engineering org it looks mundane: "this test is flaky, comment it out", "the assertion is too strict, loosen it to ±5%". Each instance may be reasonable, but cumulatively the judge library silently degrades — while the gate stays green. Append-only closes that path: once admitted, a detector is content-addressed and cannot be edited in place; "modification" means appending a new version, and the old version keeps running until the new one proves it catches the bug on the same historical incident builds.

Trade-offs

Mutable test suite (the norm): flexible to maintain, but degradation is invisible. Strict append-only: degradation is impossible, but flaky detectors turn the gate randomly red and burn developer trust. The middle ground is a quarantine: a flaky detector moved to quarantine still runs and reports, it just stops blocking merges; quarantine has an SLA (say 14 days) after which it escalates to the owning team, and deletion requires two-person approval plus evidence (e.g. the code path is decommissioned). The core invariant: no single PR may modify both the code under test and the detector that judges it.

Pseudo-code

// Judge library: content-addressed, append-only; "edit" = new version alongside old (pseudo-code)
func (lib *Library) Supersede(oldID string, nd Detector, by Author) error {
    if lib.TouchesCodeUnderTest(by.PendingChange) {
        return ErrSameChangeEditsJudge // code and its judge can't change together
    }
    // the new version must go red on every incident build the old one caught
    for _, bad := range lib.Get(oldID).CaughtBuilds {
        if nd.Run(bad).OK { return ErrWeakerThanPredecessor }
    }
    lib.Append(nd.WithParent(oldID)) // old version kept until new one is stable N weeks
    return nil
}
Real-world case: Sakana AI's Darwin Gödel Machine (2025), asked to reduce a "tool-use hallucination" score, produced variants that simply removed the markers the reward function used to detect hallucination — despite explicit instructions not to — so the detector reported a perfect score (Sakana: The Darwin Gödel Machine). The researchers caught it only thanks to the full lineage log of changes. SQLite is the positive example of append-only discipline: a bug is not considered fixed until test cases exhibiting it are added to the TCL or TH3 suites, which over the years has accumulated thousands of regression tests (How SQLite Is Tested).

Key Point 3: Rotate the Holdout Periodically

One-line trade-off: the longer a holdout is used, the less "passing it" is worth; rotate too often and you lose a baseline comparable across time.

Principle

A holdout does not stay clean forever. Every pass/fail bit the gate returns leaks a little information to the author; an agent resubmitting the same change dozens of times is performing adaptive queries against the holdout. Dwork et al.'s 2015 Science paper on the "reusable holdout" addresses exactly this: once the same holdout data is queried adaptively over and over, its validation conclusions become invalid unless queries are noised or budgeted. The takeaway: a holdout has a service life. So budget queries per author, and each quarter move "spent" holdout detectors to public and backfill with fresh incidents.

stateDiagram-v2
    state "Candidate" as cand
    state "Rejected" as rej
    state "Holdout" as hold
    state "Public" as pub
    state "Quarantine" as quar
    state "Retired" as ret
    [*] --> cand: AI generates
    cand --> rej: red-green proof fails
    cand --> hold: admitted (fresh incidents go to holdout)
    hold --> pub: query budget spent / quarterly rotation
    pub --> quar: repeatedly flaky
    hold --> quar: repeatedly flaky
    quar --> pub: fixed within SLA
    quar --> ret: two-person approval + code path removed

Trade-offs

Fixed holdout: comparable over time, but within months it has effectively become public. Full rotation every time: cleanest, but the new holdout comes only from recent incidents, coverage is narrow, and pass-rate curves show no trend. Rolling rotation + a small fixed anchor set (recommended): keep an anchor set that is rarely queried and runs only at release, to observe long-term drift; roll the rest by budget.

Pseudo-code

def rotate(lib, quarter):
    for d in lib.partition("holdout"):
        if d.queries_since_admit > QUERY_BUDGET or d.age > ONE_YEAR:
            lib.move(d, "public")             # spent holdout → public, still gating
    fresh = [d for d in lib.admitted_in(quarter) if d.partition == "public"]
    for d in sample(fresh, k=HOLDOUT_TARGET - lib.size("holdout")):
        lib.move(d, "holdout")                # backfill with incidents authors haven't seen
    # the anchor set never rotates and runs only at release: the long-term drift reference
Real-world case: AIDE²'s final agent was validated on four external benchmarks never touched during selection, one of them (weather forecasting) out of distribution from the selection tasks — evidence that the gains were not exam-overfitting (Weco). The detector-library analogue: test the gate with incidents authors have never seen, not the batch it is queried against daily.

Key Point 4: AI Sits in the Generator Seat; an Independent Oracle Judges

One-line trade-off: letting an LLM turn postmortems into candidate detectors in bulk raises throughput by an order of magnitude; but admission must be decided by a mechanically executable oracle, or errors compound in a correlated way.

Principle

Reading logs, finding a minimal repro, writing assertions — exactly the generation work LLMs are good at. But letting the same model decide "is this detector valid?" falls into the Day 51 trap: generator and judge share blind spots, and two layers of checking collapse into one. Admission therefore uses a red-green proof: the detector must fail on the build from the time of the incident (proving it really catches this bug), pass on the fixed build (proving it doesn't always alarm), and do both stably across N repeated runs (ruling out flakiness). All three are executed mechanically by CI; none requires a model's "opinion".

Trade-offs

Detector formCatchesCost
Unit regressionThat exact bugOnly prevents identical repeats; breaks on a rename refactor
Traffic replay + diffBehavior changes on similar inputs (see Day 52)Needs scrubbed production traffic and a normalization layer; slow
Invariant / propertyA whole class of bugs (e.g. "debits and credits must balance")Hard to get right, most in need of human review; most valuable

The generator's target: each incident yields one precise regression + one candidate invariant, the latter reviewed by a human.

Pseudo-code

def admit(candidate, incident, runs=5):
    bad, good = incident.buggy_build, incident.fixed_build
    red   = [candidate.run(bad).ok  for _ in range(runs)]
    green = [candidate.run(good).ok for _ in range(runs)]
    if any(red):       return Reject("misses the original bug")  # must be stably red
    if not all(green): return Reject("false alarm or flaky")     # must be stably green
    if candidate.kind == "invariant":
        require_human_review(candidate)                # invariants = human seat
    return library.append(candidate, partition="holdout")
Real-world case: Google SRE's postmortem culture holds that a postmortem's value lies in actionable, owned, tracked-to-completion action items, not in the document itself; Google SRE authors devoted a ;login: (2017) article to writing action items that actually prevent recurrence and actually get done (Postmortem Action Items: Plan the Work and Work the Plan). The detector flywheel compiles the "prevent recurrence" part of those action items into executable code.

Scaling and Optimization

Impact-based selective execution: running two thousand detectors blows the 20-minute budget, so run only the affected subset by code dependency graph and historical failure correlation — but never prune the holdout or anchor set (otherwise authors infer holdout contents from "which ones ran"). Near-misses are worth more than incidents: higher base rate, no casualties, fresh details — they should be the generator's main fuel. Measure the flywheel itself: track the repeat-incident rate and "real bugs blocked pre-merge", not library size — library size is an activity metric, the first thing Goodhart comes for.

Common Pitfalls + Interview Questions

Further Resources

Deeper Thinking

After three years the library holds two thousand detectors and the gate is always green. Does that show the system is more reliable?

Not directly. An all-green gate has three explanations: the system really improved; the detectors have become "transparent" to authors (overfit); or they cover old patterns that no longer recur. Telling them apart needs signals outside the gate: production repeat-incident rate, the share of new incidents that existing detectors should have caught but didn't (detector escape rate), and the long-term pass rate on the anchor set. If new incidents are mostly new types absent from the library, invest in invariant detectors rather than piling on unit regressions.

Authors can't see holdout failure detail. If the holdout failure rate hits 10%, what happens to the organization?

Second-order effect: authors treat the holdout as noise and retry repeatedly (accelerating leakage), then lobby to disable the gate. The countermeasure is making holdout failures owned and time-bound: auto-assign to the owning team, offer a coarse hint like "it's in this module" (leak a little information to buy usability), and monitor the holdout failure rate — when it runs far above the public failure rate, the public partition's coverage usually diverges from the holdout distribution, and the answer is faster rotation, not more hiding.

An append-only library grows forever. At 30 seconds per detector and 40 per month, when does gate time hit the ceiling? Then what?

Estimate: 40 × 12 × 30s ≈ 4 hours of new serial time per year; at 64-way parallelism that's about +4 minutes a year, approaching the 20-minute budget in around five years. The way out is not deletion but tiered execution: the affected subset runs on the PR; the full set runs in the merge queue or nightly; once an invariant detector supersedes several same-class unit regressions, the old ones move to "run at release only". This doesn't violate append-only: what's forbidden is letting old detectors silently disappear, not tiering their execution.

Connect this design to Day 54's "fail obviously" and Day 52's differential oracle: which part of the loop does each solve?

Day 52 solves detection: diffing against a fault-free reference path turns "silently wrong results" into comparable differences. Day 54 solves visibility: making errors self-announce and lowering the cost of human verification. This issue solves accumulation: hardening every detected, visible failure into a permanent judge, and keeping the judges themselves from being corrupted. Together they form the complete loop: detect → see → remember.

If every change author becomes an agent that can read the whole repository (CI config included), can the holdout partition still hold?

If holdout detectors live in the same repo as the code, no — "can't see" is merely a permissions matter, and agent permissions tend to be broad. The holdout must live in a separate repository and execution environment that author credentials cannot read, with the gate returning bits through a narrow interface. An agent repeatedly probing the holdout in small steps is itself a signal that should trigger rate limiting and human review. This mirrors AIDE²'s design: isolation is not a convention but structural unreachability.