audit-regret

Adversarial workload search for eviction-policy regret. Crafts, shrinks, and classifies workloads on which the adaptive window climber fails to close the gap to its achievable optimum, and routes each

SKILL.md

GitHub

Adversarial policy audit: regret

The third leg of the climber's audit set. /audit-adaptivity finds implementation defects in WindowClimber; /climber-gate re-runs the known traps so a change cannot regress them; this skill finds the traps that are not known yet. It searches over synthetic workloads for cells where the adaptive eviction policy (W-TinyLFU with the window climber) fails to close the gap to what it could have earned, then works each one until it names a failure class, the state variable that should have responded and did not, and the layer responsible. Its outputs are candidate rows for /climber-gate and directions for hill-climber.md §3 and §5. Run it when a new model arrives, after a climber change lands, or when a real trace shows a gap nobody can explain.

The unit of work is a cell: (workload, maximum). The unit of a finding is a family: a parameterized workload with a named mechanism and a measured neighborhood, not one trace.

Scope: the density tier, maxima above DensityClimber.DENSITY_THRESHOLD (4096). At or below it the reactive tier runs (ReactiveClimber.climb, a hit-rate law with Step and nothing else), the debug trajectory is not emitted, and most of the responders in the class table do not exist; such a cell yields end-to-end regret only and belongs to a tier-straddle pair (class 10) or to nothing here. The decision count n = requests / (4 × max) is the density tier's sample period.

Argument

$ARGUMENTS

  • empty or round: the full round below.
  • a class token from the table (structural, wrong-equilibrium, slow-convergence, masked-signal, insufficient-exploration, oscillation, memory-failure, irreversible-damage, aliasing, premature-commitment, tier-discontinuity): the same round with the proposal lanes given that class as their quota and the screen's validity gates unchanged. Use it when the record already points at a class (hill-climber.md §3) rather than asking what is broken.
  • a spec path: skip proposal and screening, and run steps 4 through 7 on that one cell.
  • a trace path (--size N, and --fmt for anything but lirs: arc, corda, ...): steps 5 and 7 on that cell, with --start plants when the question is the descent. Shrink, bisect, and neighborhood need a spec, so step 4 becomes writing the spec that reproduces the trace's mechanism (its anchors and trajectory signature match the trace's) and shrinking that; without one the finding stays a single-cell observation and says so.

Regret, defined for this skill

Every number is relative to anchors from one static sweep (climber-gate/run.py's curve: linked.Lru plus sketch.WindowTinyLfu at windows 1, 2, 5, 10, 20, 30, 40, 50, 70, 80%):

  • start: the static window the product starts at (1%; --start for a planted window). A plant holds probation at its shipped share rather than re-splitting main, so on a planted cell the static sweep is not a like-for-like frozen reference; climber-gate/frozen_matched.py re-measures the frozen point with the plant's geometry (its CELLS list is hard-coded; add the cell) when the frozen point itself is the question.
  • ceiling: the best static window in the reachable range. The window cannot exceed 80% (the climber donates only the protected allocation), so a peak reported at 80% is flagged peak-at-edge and the true optimum may be unreachable by any window setting.
  • LRU: the floor. Below LRU is a bad sign, but "above LRU" is not the bar; the recorded families were built to attack the density signal, and most sit far above LRU while pinned.
  • Belady (--belady, opt.Clairvoyant): the reference with knowledge of future accesses. structural = Belady - ceiling is its gap over the tested static-window family, not proof that every point is recoverable by an online policy or that no adaptive window can recover any of it. Establish a policy mechanism before routing that gap to admission, the sketch, or SLRU. Extra application metadata is another information advantage; neither comparison explains away losses to LRU, static windows or other references using the same key stream.
  • The ceiling is the best static window, not an upper bound: an adaptive window can beat every fixed split where the workload's phases want different ones, so a negative gap (beats-static-ceiling) can be a real result marking a cell where adaptivity is earning. It can also be the grid: the sweep has ten points and a peak between two of them (say 15%) reads as beating both. Before crediting adaptivity, re-sweep densely around the peak with regret.py --windows 0.12,0.15,0.17 (the extra windows are merged into the cached <trace>.anchors.<size>.json, so the ceiling and the position regret update in place).
  • the reactive arm (harness variant reactive): the complexity anchor. Where it ties or beats the shipped machine, the density tier and its goal-metric layer are not earning their keep on that cell. It runs the reactive tier at every size, so it has no trajectory and is compared on its row alone.
  • the ghost (minisim-leader, a simulator climber strategy): an online policy that sees the counterfactual. It simulates the start window and every 5% from 5 to 80% (17 arms, probation fixed as the live climber keeps it) as full-size copies up to 20,000 entries, or 20,000-entry miniatures fed a hash sample of the requests above that, discounts each one's misses over 64·maximum requests, and moves the window to the one with the fewest. It serves twice. As an anchor it calibrates the static ceiling: its gap to the climber ranks cells almost exactly as gap does, so it does not find new cells, but it flags the exceptions (a static ceiling that fixed probation cannot reach, a phased cell where adapting beats every fixed window, a miss both share). As the teacher, its copies' misses at each sample say which window that sample rewarded, which the whole-trace static curve cannot, and the report reads the climber's costly samples against them. Its configuration was measured rather than chosen (hill-climber.md §5): fewer arms missed narrow optima, smaller miniatures mis-ranked near neighbors, and more arms added nothing. It is a reference, not a bound: on DS1 at 2M and 4M it lands below the climber at every size tried, so beating the ghost is not by itself an adaptivity win. It starts at 1% whatever --start plants. One extra simulator run per cell, a few seconds at the gate's sizes, cached in the anchor sidecar with its configuration; n/a on weighted traces (the simulator drops the key-only host) and on a tree older than the strategy.
  • Anchor fidelity: the reference sketch's aging matches the product's at powers of two and runs up to 2× slower elsewhere (rules/simulator.md), so prefer power-of-two maxima; the 4097 side of a tier straddle carries a small offset in start and headroom that the 4096 side does not.

Per arm, regret.py reports gap = ceiling - cache (the pp number gate rows are barred on), headroom = ceiling - start (the prize the climber exists to win), closed = (cache - start) / headroom (the fraction of the prize captured; negative means moving hurt), and missx, the relative extra misses a user pays ((miss_cache - miss_ceiling) / miss_ceiling), and ghost_gap = ghost - cache (what the online reference earned that the climber did not). Rank cells by gap, and read ghost_gap for the exceptions it flags; a small gap on a low-hit-rate cell can still be a large missx, and closed is what separates "did nothing" from "did the wrong thing".

Two cell types, read differently. A prize cell has headroom (the start is not the optimum): the question is whether and how fast the climber captures it. A hold cell has none (the 1% start is already optimal, as on the frequency-favorable real corpus): the only thing the climber can do is leave, so any gap is the cost of moving, and the question is what made it move. A hold cell becomes a descent test by planting the window (--start 0.3 with the harness), which is the only instrument that asks whether the climber can come back down; the frequency-favorable corpus reads clean by default because it never has to.

With a harness tree the trajectory (one climb line per density sample) decomposes the gap: pos_regret = mean_s (ceiling - static(window_s)) is the cost of where the window was, split at the settle point into transient and steady; residual = gap - pos_regret is what the timing of the moves cost (churn, phase interaction) or won. The static curve is the whole trace's, so on a phase-structured workload the split is a blend and the per-sample hr against the six-block window profile is the finer instrument. n is the number of decisions the trace held; under 40 the cell prices convergence, not the machine, and the row says SHORT. The teacher reads the same trajectory against the ghost's copies, sample by sample on the same clock (both start when the cache is half full): cf_loss is the climber's mean loss to each sample's best copy, cf_best what those best copies earned (above the static ceiling where the phases want different windows), and the costly samples, those losing at least 1pp, are grouped into episodes. Each episode names the window the copies preferred, how often the climber's law pointed toward it (law_agree over all costly samples), and the mode that held the climber, and the costly loss is split by mode over the whole run (steering, walks, parks, holds). The loss is taken against the climber's own hit rate, not a copy's value at its window: the copies sit every 5%, and interpolating between them across a cliff invents a cost (crestpast parked at 8.6% read 6pp costly that way, level with the 10% copy in fact).

Two seeds, kept apart: the spec's seed is the trace instance (regenerate with --seed, or regret.py --seed-override, when a verdict is contested, as the gate does with 11/13), and --seeds are the cache's admission draws (-Dcaffeine.climber.seed, harness only), which is what "eight seeded runs" and "read seed by seed" refer to.

The failure classes

Name the class whose repair would close the cell (the primary), and any consequence as secondary. Signatures are regret.py fields; "responder" is the machine state that should have moved and did not, in the debug line's vocabulary (max win hr s mode adj wh mh ph stable auditWait rung left arung acs pcs undo anchorW anchorR ema dev hold fresh shortfall ret auditbar wbase wbar) and the object that owns it (hill-climber.md §4's write-owner map). "Recorded" names an instance already in the record so a new witness is compared to it, not re-derived.

# Class What it is Signature Responder Owner Recorded
0 structural structural no window setting closes the gap; the loss is admission, sketch ranking, or the SLRU split structural large, gap small; or headroom < 1 and peak-at-edge none in the climber policy structure norank_rep_r6 (the sketch cannot rank six-reference keys); the fixed ~19.8% probation (slru_adaptivity study, §5)
1 wrong equilibrium wrong-equilibrium converges and holds a position whose static value is below the ceiling pos_l3 ≥ max(1, gap/2) (wrong at the end), law wants the opposite of needed or nothing (rest_err sign vs w* - win_l3), steer dominant DensityClimber.steer's zero (ln(d_w/d_m); the average-vs-marginal rest point, §2.1) controller cp_w097@16384 resting near 48% against a 10% optimum; ds1_1M 13–22% vs 2%; flood_j100; P3/fiu_webmail resting below a non-convex peak; crestpast's drift (a caught band makes the window denser than a bulk-filled main, so the law rests above the crest and walks a park away from it)
2 slow convergence slow-convergence the right position is reachable and reached, but late; or the profitable phase ends first pos_transient dominant, progress toward w*, late arrival; /walk-paced when the move happens through probes Step.size/DENSITY_GAIN (steering-paced), the sample period, or the ladders and AuditClock waits (walk-paced); actuator-limited when adj far exceeds the realized Δwin (BoundedLocalCache.QUEUE_TRANSFER_THRESHOLD) controller gain, or exploration cadence; policy structure when actuator-limited the 13–16 sample descent from 80% (§5); rep_r6 escape times spread over 91 samples; mixture round-3 escapes at ~100 samples; the ~2-sample-period lag limit on phases
3 masked signal masked-signal the observed statistic reads healthy while the harmed population's misses are invisible to it as class 1 with probes = 0 and steer dominant (sighted); wh above the bar from traffic worth nothing at the margin; a rider that keeps a starved region "sighted" Sample.windowHits/probationHits attribution, Reading.steeringError, the starvation bar (MIN_SIGNAL_SHIFT) controller (estimator) or the goal-metric layer that must judge what density cannot whisper (the trickle keeps the window sighted); deadphase rider (six window hits authorize the maximum step); flood_j100 (dense per slot, zero at the margin); veilmoat (whisper's mask on shallowmoat's terrain: no starvation probe arms, so both 2026-08-15/16 repairs are unreachable and every seed takes the audit path, ~88 samples; a dose note); absolve's walks (the verdict confirms on the lure's hits at 2,200–3,400, unattributable and worthless above the lure's knee); entry_duty (the Sol round, 2026-08-21: a worthless trickle rider square-modulated at period 13.5 keeps the window sighted over a 40–50% prize, zero probes, hybrid ties noaudit at 17.2–17.9pp under the ceiling on 8/8 cache seeds, trace-seed-adjudicated at 149/211/313; a dose note on the posjam_d0 gate row, spec audit-regret/specs/entryduty.json); mainsat (round 7, 2026-08-21: the main-side mirror with an interior peak, main dense and sighted and worthless at the margin, so density pins the floor (noaudit 21.4 against 35.8) and no probe can arm; the equilibrium audit owns it as it owns whisper, a ~48-sample approach at any horizon; spec audit-regret/specs/mainsat.json, a sentinel row)
4 insufficient exploration insufficient-exploration the machine holds a position and never tests far or often enough to find the better one park+hold dominant, audits rare, max_wait 128–512, max_rung 64; /reach when every walk ends crash/fail short of the ceiling window (repeat_arms, top_frac/floor_frac) AuditClock.stillSamples/waitSamples, Ladder.rung, refractoryLeft, Anchor.held/freshLeft, Walk.samples and its crash bar recovery layer metronome (positional clock jam); H4-C1 ratchet; the r3 blind-corner lockout; the moat (a valley deeper than the audit's crash bar); rep_r6's top corner re-probing every refractory cycle; shallowmoat (a valley 2pp deep and 57% wide: the first-round walk adjudicated three or four strides out and never reached the prize; repaired 2026-08-16, now a gate row); absolve (a lure pulsed at 16 samples inside a wide valley: one walk per period, one rung per period, kept confirms reset the rung, escape at s144–159; round 2, gate row at 128 samples); latebloom (round 7, 2026-08-21, gate rows: a flat prelude spends the audit schedule through two honest budget failures, auditWait 32 → 128, then a prize caught only from 50% arrives; the stand-down that detects it reschedules nothing, or the undo's retreat covers it, so the held floor waits out the 128 (54.90 ± 0.04 against 66.4, noaudit 53.39); the phase-1 ladder is the family's shape and its worst cells send the next audit down the alternation from density's ~19% rest into the wait)
5 oscillation / chasing oscillation the loop follows the workload's phase instead of stabilizing; a fixed window at the mean position wins settle never, flips ≥ n/4, residual > pos_regret, move high; six blocks alternate Step decay (reactive) / the proportional density step under alternation; STABLE_BAND_FRACTION; the stillness clock decaying instead of arming controller (no damping or prediction) widepin; phases_d050 (grid-locked, bimodal); posjam_d0; corda_large's churn (10.5pp against any fixed window, §1); hazefloor (rowed round 4 at 320 samples: the top-corner retention cycle with a ~105-sample period, the corner audit's crash at the cliff, the C2 discard, density's slide, the floor's failing ×1 walks and the rung-16 re-crossing; 41.1 against LRU 49.2); parkveil (round 6, gate rows: a zipf↔band square-wave mix at period 13 whose fixed 50% window beats every adaptive arm — the density rest point alternates with the mix, so the ratio's phase immunity fails, and the machine chases between shield-length parks; 53.1 against LRU 66.0)
6 memory failure memory-failure evidence that a decision was wrong has been discarded, so it is repeated /stale-claim: bad_veto (a veto drags to an anchor whose static value is worse, anchorR - ema large); /repeat-probe: repeat_arms (an arm re-launched from a band and direction that already crashed or failed) Anchor.window/rate and Rates (the claim), Ladder.crashStreak, sample.previousHitRate after resized, the frozen Walk.base* recovery layer; policy structure when the memory is the sketch's aging the stale away-anchor claim (a rate claim earned before a regime shift; fixed by the stand-down, regimeramp/staleclaim rows); H4-C1/adv4-F2 (a streak cleared by the other layer's ending); the undo ledger's creep at a starved corner (fixed by the integral ledger, §5); shallowmoat (a mid-depth confirm the density arm reversed in the same sample reset the ladder, so the escalation never started; repaired 2026-08-16: a reversed confirm now deepens the ladder, and one at the deepest commitment that the goal metric confirms parks); absolve_p8 (a confirm density agrees with on its own sample and dismantles within the lure's 8-sample period is rewarded, so the rung reads 1 or 2 on 223 of 255 samples and never reaches 32: the deferreward shape absorbing and deterministic; round 2, gate row at 256 samples); ghostclaim (the stale away-anchor claim's other case: a regime shift lands with the window still and off the anchor, the stand-down keeps the previous regime's claim, and it was then the audit's confirm reference (a walk that finds +30pp at the top fails at budget) and the guard rail's reference (a bad_veto to a position worse in the new regime, held there); round 3, gate row at 128 samples; repaired 2026-08-17: the walk is measured against the smoothed rate it leaves, Walk.baseSmoothedRate, and the claim is the rail's alone; the discard shape died on the moat rows); parkveil (round 6: the discard's cost side — a validated audit-grade park at the top corner survives exactly one fresh-park shield, then the first post-shield phase flip fires isWorkloadShift and the stand-down discards the claim at the anchor, so the position is re-derived through the full ladder every cycle; arm-independent, the census C3 observation's first cost-bearing cell, and the rail cannot hold it because the phase swing prices its margin at 62–101pp; the signal-classification wall); mainsat's plants (round 7: the C2 arrival-discard shape on the rail's return; a veto returns the window to a correct anchor above a cliff, the landing sample's +11pp recovery reads as a workload shift because a veto's return arms no isParkTest cover, the stand-down discards the claim on the anchor and density slides off again every ~19 samples; arrive breaks it, +5.3/+4.6 on the plants, bit-identical unplanted)
7 irreversible damage irreversible-damage by the time the mistake is detected the valuable residents are gone; restoring the position does not restore the rate undo_deficit ≥ 2 (post-undo hr below static(win)), or a recovered window whose hr lags for samples undoRemaining (full undo), the transfer cap, demotion into probation (the walk's own demotions) recovery mechanism (undo policy) or policy structure (region transfer displaces) corda_large's displaced residents; s3_25k (171pp of 246pp of descent undone by one failed probe); the deadphase rider growing the window into main
8 aliasing aliasing two regimes produce the same observables at the decision but need different actions; the machine must fail one a pair: one terrain, one bit flipped, search.py pair shows identical fields at the decision sample and divergent optima the statistic at that decision (starvation bar, crash bar, stillness, first-difference reversal) controller (a new estimator) or a priced trade (design) a correct floor is as still as a trap (the blindprobe/norefr negatives, §5); a monotone drawdown into the moat is a damaging walk at the crash point; a big move because the rest point is wrong is a big move because the workload changed (margrest, §5); window-irrelevant modulation (whisper_mod, posjam)
9 premature commitment premature-commitment the machine parks, confirms, or anchors on a transient (warmup, ramp, trend) and the shield holds it there; or its verdict commits at the wrong position of an honest walk (where the streak completes rather than where the walk was best) early_confirm (an AUDITCONFIRM before sample 24 at a position below the ceiling), long park after the audit verdict (AUDIT_CONFIRM_STREAK, beatBase), AUDIT_WAIT_FIRST, Anchor.freshLeft recovery layer the cold-start misconfirm at ~33% (flatctl, workspace-only; regimeramp is its rowed sentinel); climbtrend/saw_p40 (a trend clears any raw streak); shieldtrap; absolve through 64 samples (the calibration audit's level-test confirm on a phase step in main's hits against a stale reference, then the park and the down-first alternation: shallowmoat's basin B forced on every seed); crestpast (round 4, gate row: the calibration audit crosses a crest on its first stride and confirms on its fifth, AUDIT_CONFIRM_STREAK completing at stride 4 and AUDIT_COMMITMENT holding the verdict to 5, so it parks three strides past the crest, and the return walk's fifth stride is on the cliff side where the level test crashes; classes 1 and 6 co-requisites of a repair, since a confirmed crest is lost within one audit cycle); the far-crest face (s_fatbase, regimeramp's misconfirm at ten times its dose: the calibration walk declines from its first stride into a valley and every sample still clears a reference frozen while the cache filled)
10 tier / scale discontinuity tier-discontinuity the same shape at maxima straddling 4096 (law and cadence switch) or where a size-relative floor crosses a reuse distance the regret jumps across a size while the anchors are continuous DensityClimber.appliesTo, the 2%·max floor against d controller (tier gate) the D2 straddle rows (strad_p8 at 4096/4097); the mixture trap's scale-relative floor

Not classes, and excluded before any classification: warmup (a short trace; regenerate longer, compare six blocks not thirds), a basin lottery (a bimodal cell read from an unseeded mean; adjudicate seed by seed), the alignment offset (a phase grid commensurate with the sample grid; shift the trace start), and a bar inside the spread (a bar is a margin over a re-derivable anchor, never a bare level).

Out of reach of this instrument, not absent from the machine. product.Caffeine builds with a maximum size or weight and nothing else: no expireAfter*, no Expiry, strong references. So no cell here can produce an expired or collected entry, and any regret that only arises when the cache reuses a dead entry's node is unsearchable in a round, not a negative result. That quarter is real: the expired-reload miscredit (2026-08-24) is a class 3 shape reached through a TTL, and it collapsed the converged window from 402 entries to 5 at a maximum of 512. It was found and priced in an in-JVM harness whose recipe is in design-decisions.md under the reload credit. Do not read a round's silence as evidence about anything gated on expiry or reference collection. Reaching it here would mean giving the simulator's policy a TTL, which trades the corpus's trace fidelity for the coverage; that is a call to put to Ben, not to make inside a round.

Which layer is responsible

The decision procedure regret.py encodes as hints, to be applied by hand on the trajectory:

  1. Read the teacher's episodes first: they say when the loss happened and what held the window. An episode whose law pointed away from the preferred window is the rest point or the estimator (1, 3); one whose law pointed toward it while park, hold or a walk held the climber is the recovery layer (4, 6, 9); a run of audit walks away from a good window is exploration cost. A gap the ghost shares (ghost_gap < 1 with gap ≥ 1) is phases the static ceiling blends over, the miniatures' own miss, or structure (step 4). The teacher says what each sample rewarded, not how to see it; a fix works from signals the shipped cache has, never from miniatures.
  2. Is the window still in the wrong place at the end (pos_l3 large)? If not, the loss was transient: class 2 (or 5 if it never settles).
  3. If it is, what does the steering law want there? rest_err is ln(d_w/d_m) over the last third: positive wants a larger window. Compare with the direction the ceiling lies in.
    • Law agrees with the ceiling and the last third is quiet (park/hold/veto): something above the law is holding the window. Recovery layer: 4, 6, or 9 by the fields.
    • Law agrees and the last third steers but the window does not move: the floor clamp, the top corner, or the actuator. /reach (4) or actuator-limited (2).
    • Law disagrees or is silent: the law's own rest point is wrong. Controller: 1, or 3 when the signal is being fed by traffic worth nothing at the margin.
  4. Confirm with arms, never with the shipped machine alone: reactive (is the density tier the cause?), noaudit (is the goal-metric layer helping or hurting here?), nocal (the calibration audit), and --start plants (path dependence: a rest point that depends on where the run began is a memory or commitment failure, not a law failure). A gap that every arm shares is not in what the arms differ on (the density law, the audit layer); look at the machinery they share (the sample period, the transfer cap, the region structure) or at the anchors (structural). climber-gate/marginal.py answers class 1 without a controller: where the average error rests versus where the hit rate peaks. exposure.py/blindlock.py answer class 4's clock questions.
  5. A large structural value or peak-at-edge is a diagnostic lead, not sufficient attribution. Confirm a policy-structure or reachability limitation before routing the finding to admission/sketch/SLRU work, recording it, and stopping controller work unless asked.

The hint strings regret.py prints (the hints column; across seeds each carries a vote count, name xN), and the class each points at. search.py's primary skips the flags when it names the class a shrink must preserve.

  • Flags: SHORT (n < 40), clean (|gap| < 1), beats-static-ceiling (gap ≤ −1), peak-at-edge, left-optimum (a hold cell with a gap).
  • held-against-the-law: wrong at the end, the law wants the right move, the last third is quiet; the recovery layer, refined by memory-failure/stale-claim, premature-commitment, and insufficient-exploration when their fields fire (4, 6, 9).
  • insufficient-exploration/reach: wrong at the end at the floor or top corner, or ≥3 walks ended without a confirm while a move was needed (4).
  • steer-blocked: wrong at the end, the law steers, nothing moves; the actuator or a clamp (2 or 4).
  • wrong-equilibrium, wrong-equilibrium/masked-signal: the law rests wrong; the suffix when no probe was ever armed and steering dominates (1, 3). wrong-equilibrium/mild is a residual position error under the wrong-at-end bar.
  • slow-convergence, slow-convergence/walk-paced (2); oscillation (5); irreversible-damage (7), irreversible-damage?/phase-confounded when the deficit is under the run's own scatter; memory-failure/repeat-probe (6).

Every hint is a pointer; the classification is the trajectory read against the table.

"Classify the signal, not the workload" governs every proposed remedy: a fix may test whether the machine's own measurement can be trusted (a starved region, an unresponsive hit rate, a sample too small to mean anything). A workload label or an inferred class is not evidence for a window choice. An estimator using generic observations remains testable, but must earn its information, action and cost claims under the rules of evidence below; do not substitute a hand-tuned workload lookup.

Instruments

All under this directory unless noted; the runners come from climber-gate/ (run.py, harness.py, marginal.py, startwin.py, exposure.py, blindlock.py, real.py, floors.py, gate.py).

  • workload.py spec.json --out t.lirs [--max N] [--seed S]: the compositional generator. A spec names members (zipf, loop, uniform, scan, pairs d|dreq k, trickle gap, rotation n step period) and segments that give each a share, optionally modulated over the segment (sine/square/ramp). Sizes and distances are × max except dreq and gap, which are requests; durations (samples, period) are density samples of 4 × max requests; re-references land at their exact global index (gen.py's delay ring), and each member owns a disjoint key space. --describe prints the decision count before anything runs. specs/ holds search seeds (mixture, phases, whisper, deadphase, norank, drift), not gate rows; the gate's canonical generators stay in climber-gate/.
  • regret.py <trace|spec> --size N [--fmt f] [--seeds 1,..,8] [--variants hybrid,reactive,noaudit] [--start f] [--belady] [--windows 0.15,0.25] [--max-override N] [--csv out] [--json out]: one cell's anchors (cached beside the trace; --windows sweeps extra static windows and merges them into the sidecar, the dense re-sweep for a peak between two swept points or a cliff the linear interpolation misreads), per-arm regret, per-seed trajectory signatures, the aggregate hint vote, the ghost's hit rate and the teacher's episodes, and a CSV row. --traj FILE --static '1:hr,2:hr,...' --lru x analyzes an existing dump alone (no ghost). --variants (other than hybrid), --start, --seeds, and the trajectory itself are harness knobs; on a stock tree they are silently ignored, so every arm is the shipped machine from 1% and --seeds runs are unseeded draws, while the anchors still take --start at its word and a stock-tree plant reports closed against a start the cache never had. --variants density forces the density tier below 4096, a counterfactual for diagnosing a straddle, not the shipped machine at that size.
  • search.py: eval <specs|dir> --csv [--rank gap|ghost_gap] screens a batch and ranks it by gap or by ghost_gap (resumable; a (label, arm, size, seeds) row is never measured twice, so one spec at two maxima is two rows, --size runs a geometry at another maximum, which is what a 4096/4097 tier straddle wants, and the same cell at a second seed is measured again rather than read from the first seed's row; the label is the spec's basename, so keep basenames unique within a round); mutate base --set path=v1,v2 [--set ...] --out DIR writes a neighborhood or a dose ladder as spec files (scale is a max axis here, since every size in a spec is relative to it); shrink base --csv --out min.json is greedy delta-debugging that keeps a reduction only while the gap stays in [keep·g0, g0/keep] and the primary class is unchanged and the trace keeps ≥ 40 decisions (the class is the base row's first firm hint, an uncertain …?/… hint yielding to a firm one; a member drop that would leave a segment without a positive share is skipped; and the hint is coarser than the mechanism, so read the witness's trajectory before trusting it, as round 3's ghostclaim shrink kept "wrong-equilibrium" while dropping the member the mechanism needed) (a witness made by shortening measures how long the climber takes, and a reduction that amplifies the gap has changed the failure); the class it preserves is the base row's primary hint at the seeds given, so shrink at --seeds 1,2,3 when the base is bimodal, and on a stock tree there is no class and only the gap band holds; bisect base --knob path --lo --hi --bar locates a dose transition and reports cliff or gradient, assuming the gap is monotone in the knob (read the printed ladder; if it is not, mutate a ladder instead); pair a b runs an aliasing pair and prints the decision sample's fields side by side at the first divergence, from the first seed's hybrid dumps.
  • Setup for trajectories and arms: git worktree add --detach <workspace>/tree HEAD, python3 .claude/skills/climber-gate/harness.py apply <workspace>/tree (then verify; the two counts must match — 59/59 as of 2026-09-17, growing as harness hooks are added), and CAF_TREE=<workspace>/tree on every call. Never commit the worktree's edits. A stock tree yields end-to-end regret only (no trajectory), which is enough for a screen and useless for a classification. Maxima in the millions need CAF_EXTRA=-PjvmArgs=-Xmx26g for the eleven-policy anchor sweep; the gate's sizes do not.
  • Cost: at 8192 a 60-sample cell is 2M requests; anchors, the ghost and one product run take ~15 s with a warm daemon, so a 30-spec screen is minutes and a full round with shrink, seeds, and neighborhoods is an hour or two of sequential runs. Runs are sequential by construction; do not parallelize simulator processes in one tree, never killall java, keep CSVs append-and-resume as the tools already do, and prefix long commands with caffeinate -i, which is best-effort from an agent shell (rules/simulator.md), so tell Ben when a round will run past an hour and needs an awake session on his side.

Targeted retention controls

Use these existing-generator inputs when investigating an audit verdict, a delayed retention decision, or the later consequences of a park. The canonical jumpslide is already a gate row; these companions are targeted controls, not new mandatory bars or fresh holdouts. The S1 candidate was closed without adoption; these inputs remain useful for new investigations, not as a pending candidate-validation queue. Its findings are recorded in the design record.

Input Question it helps answer
specs/jumpslide.json and specs/jumpslide_period26.json Can the proposed original decision distinguish two futures with the same first 425,984 requests at C=8192/seed7? The rotation period is the only difference
specs/jumpslide_260.json, workload seeds 11/13 Does a gain at an early fixed horizon survive the full continuation? This extends demand rather than looping/restarting the short trace
specs/lifecycle_fit_scan.json Under fixed write TTL=C, are misses already forced by expiry while all live entries fit? This is hot-set plus unique-scan demand; a real-cache TTL driver and independent lower bound are still required
specs/pure_scan.json Does the accounting correctly recognize an all-miss/no-reuse control where allocation cannot save demand misses?

These work with the normal workload.py/regret.py path. For example, from the repository root:

python3 .claude/skills/audit-regret/workload.py \
  .claude/skills/audit-regret/specs/jumpslide_260.json --seed 13 --describe
python3 .claude/skills/audit-regret/regret.py \
  .claude/skills/audit-regret/specs/jumpslide_260.json --seed-override 13 --variants hybrid \
  --traces-dir .local/experiments/retention-check/traces \
  --dump-dir .local/experiments/retention-check/dumps

For misleading phase support, use the existing generator with --phaselen 18 and 22, each with --phases 48 --max 8192 --dfrac 0.5. For example:

mkdir -p .local/experiments/retention-check
python3 .claude/skills/climber-gate/gen.py phases --max 8192 --dfrac 0.5 \
  --phaselen 18 --phases 48 --out .local/experiments/retention-check/phases18.lirs

Here phaselen is in C requests; workload.py rotation periods/durations are in 4C nominal samples. gen.py's phases/widepin ignore the seed argument, so seed aliases add no independent workload evidence. Use a verified harness for admission seeds, plants or trajectories, as above. The default regret run evaluates ordinary non-expiring cache behavior; it does not implement TTL/invalidation or paired decision interventions. The old PRF outcomes in hill-climber.md do not become expected seeded-stream results or gate thresholds. For cumulative decision attribution, build and validate current-source instrumentation in the new local workspace, following the paired-replay protocol.

The round

Workspace: .local/experiments/audit-regret-<yyyy-mm-dd>/ with LEDGER.md (one row per candidate, status updated in place), tree/ (the harness worktree), specs/, traces/, dumps/, data/. Report: .local/audits/<model>/audit-regret.md (docs/audit-output.md). Both survive rebases; nothing checked in may reference them. The commands, in the round's order, run from the workspace (regret.py/search.py default --traces-dir/--dump-dir to ./traces and ./dumps):

A=$PWD/.claude/skills/audit-regret; G=$PWD/.claude/skills/climber-gate
W=.local/experiments/audit-regret-<date>; mkdir -p $W/specs $W/data $W/traces && cd $W
git worktree add --detach tree HEAD
python3 $G/harness.py apply $PWD/tree && python3 $G/harness.py verify $PWD/tree      # counts match
export CAF_TREE=$PWD/tree
python3 $G/<generator> ... --out traces/<row>.lirs                                   # 0: a gate row
python3 $A/regret.py traces/<row>.lirs --size 8192 --seeds 1
python3 $A/search.py eval specs --csv data/screen.csv --seeds 1                      # 2: screen
python3 $A/search.py shrink specs/<c>.json --csv data/shrink.csv --out specs/<c>_min.json  # 4
python3 $A/search.py bisect specs/<c>_min.json --knob <path> --lo <a> --hi <b> --bar 2 \
    --csv data/bisect.csv
python3 $A/regret.py specs/<c>_min.json --seeds 1,2,3,4,5,6,7,8 \
    --variants hybrid,reactive,noaudit --csv data/classify.csv --json data/<c>_min.json   # 5
python3 $A/search.py mutate specs/<c>_min.json --set <knob>=<lo>,<hi> --set max=8192,16384 \
    --out specs/nbhd && python3 $A/search.py eval specs/nbhd --csv data/nbhd.csv --seeds 1  # 6

0. Baseline. Record the tree (git rev-parse HEAD), build the harness worktree, and reproduce one recorded gate row to prove the instruments read the same numbers: regenerate it from the gate's generation block and pick a low-spread row (straywall2_8192_d050; demoflood_8192 is bimodal since the 2026-08-18 re-base and no longer qualifies), not a lottery cell, since the recorded means are unseeded and a --seeds 1 draw must land inside the row's spread. Read hill-climber.md §3 (the recorded families), §5 (the graveyard), §5's last entries before proposing anything, and keep the §3 family list and the gate table at hand for step 3.

1. Propose. Spawn the two proposal lanes in parallel, each returning specs plus a one-paragraph prediction per spec: the class it targets, the state variable it expects to see fail, the terrain argument (why the static curve has a better window than the machine will find), and the regret it expects. The prediction is the finding's hypothesis; a spec whose regret appears for a different reason than predicted is a new finding, not a confirmation. Write each spec and its prediction together before screening that spec.

  • The blind lane gets WindowClimber.java, hill-climber.md §2 and §4 (the machine), the member/segment grammar, and the class table above. Nothing about §3, §5, or the gate table. Fresh eyes on the mechanism find shapes the recorded families anchor a sighted reader away from.
  • The sighted lane additionally gets §3 and the directions carried from earlier rounds below. Point it to §5 and the gate table by heading rather than copying both into its brief. It must consult the relevant entries, name the nearest recorded family and state what differs, and must not rebuild anything §5 killed.

Give each lane a target count (six to eight specs), a class quota when the argument names one, and the mechanism-directed prompt: for each class, "construct the workload that maximizes this class's regret against this machine, and say which line of densityClimb decides wrongly on it". A lane writes specs; it runs nothing.

Dispatch both lanes on Opus (model: opus), each with an explicit time box of about twenty minutes; dispatch step 7's evaluators on the session model (Fable), since refuting a finding with runs and reading its trajectories is where round 1's errors slipped through on Opus (an evaluator confirmed "the plant at 70% holds" without opening the trajectory, where it was one audit park inside a 64-sample horizon, and let a post-tick misreading of the audit clock stand), and where round 2's Fable evaluators corrected both writeups materially. The lanes differ by what they are shown, not by model: a Fable proposal lane spent four consecutive 96,000-token thinking turns on the open-ended design prompt and was aborted at the output-token cap after two hours with nothing written, while the Opus lane on the same prompt delivered eight specs in fourteen minutes (round 2, 2026-08-16; the earlier Fable attempt at this task shape tripped a safety classifier on the construction framing, 2026-07-30). Ben's direction, 2026-08-17 (either is fine; pick what finds issues), replacing the 2026-08-16 one-lane-per-model rule. If a Fable lane is ever wanted for proposal diversity, run it as a third, non-blocking lane with a different shape: three or four specs, each written to disk the moment it is designed so the harness has tool rounds to deliver a time-box message, and screen whatever it wrote when the round's screen runs; never wait on it. Keep every prompt concrete about the domain it is in (simulator request traces, a cache policy's hit rate, a window-sizing loop) rather than generic red-team language.

2. Screen. search.py eval <specs> --csv screen.csv --seeds 1 on the harness tree at the spec's own maximum (8192 unless the attack is about scale), so every row carries a hint. Apply the validity gates before reading a gap: n ≥ 40, no peak-at-edge unless the attack is structural, and a headroom ≥ 1 prize or a deliberate hold cell. Keep every cell with gap ≥ 2 (or missx ≥ 20% on a low-rate cell) as a candidate.

3. Deduplicate. For each candidate, name the nearest recorded family (§3, the gate table, the frontier sentinels) and the difference; a candidate that is a recorded family at another dose is noted on that family's row and dropped from this round unless its dose is new. pair a candidate against its nearest neighbor when the mechanism is claimed to be the same.

4. Shrink and parameterize. search.py shrink to the minimal witness (class-preserving), then bisect the one continuous knob that carries the effect for its transition and shape, then express the witness as a family with one to three knobs (dose, distance or period relative to max, phase length in samples). Record the transition; a threshold and a gradient are different mechanisms.

5. Classify. regret.py at eight seeds with --variants hybrid,reactive,noaudit, the trajectory read per seed (a bimodal cell has a class per basin; the reactive arm has no trajectory), the layer named by the procedure above, and the responder named in the debug line's vocabulary. If the adjudicated class is not the hint the shrink preserved, the witness may hold a different mechanism than its parent: shrink again from the parent at more seeds. Add --start plants when the question is path dependence, marginal.py when it is the rest point, exposure.py/blindlock.py when it is the clock. Where the arms tie the shipped machine, say so, and name what they share.

6. Neighborhood. mutate the family's knobs one step each way and to a second maximum (16384 or 32768; 4096/4097 when the tier is implicated), eval, and record the surface. The neighborhood is what a fix will be judged on.

7. Challenge. Spawn one evaluator per finding (the session model, Fable) with the finding's writeup, its CSV rows, the anchor sidecars, and the dumps, no source, told to refute it: is it warmup, a basin, an alignment artifact, a peak beyond 80% or between two swept windows, a recorded family re-dosed, or an anchor error? Every objection is answered by a run or the finding is downgraded.

8. Fix, only when asked. Present the classified findings and stop; Ben decides which class to work, one at a time. A candidate change is the smallest one that closes the class: it must close the whole neighborhood (step 6), not the witness, or it has fit the benchmark; it must hold gate.py on the full battery, real.py, floors.py, and the reactive anchor column where the change touches shared state; and it needs a fresh holdout per hill-climber.md §6 (check the unspent inventory first). Two things at once is two rounds.

9. Promote and record. A confirmed family becomes a /climber-gate row (its spec under this skill's specs/, generated by workload.py in the gate's generation block, a gate.py CELLS row with its seeded record) or a frontier sentinel when it is accepted residue; its mechanism goes to hill-climber.md §3 (a family) or §5 (a dated entry) with the class named; open directions go to §3 and §5. Write the report; leave the ledger current.

Directions carried from earlier rounds

What a round did not get to is written here rather than in its report, since a fresh round does not read prior reports. Strike a line when it is done or dead.

  • Real-trace instances of shallowmoat's or absolve's shape (a large flat population, a far recency band, a scan or a pulsed short-reuse population): a climber-gate/marginal.py static anatomy over the corpus, or a real.py pass, would say whether a wide shallow valley with a prize behind it exists outside the generator (round 1, 2026-08-15; still open after round 2). Round 3's screen-level answer from the 77-cell start-knob screen (w1/w2/w5/w10/w20 plus the ceiling): no density-tier cell is flat to 20% with its ceiling far above at 50–70%; every recency-favorable cell rises monotonically from 1% and the nearest valley is arc_DS1@256k (a 0.1pp dip, a 0.5pp prize). Only a full anatomy (the 30–70% windows) can close it.

  • The anchor-fidelity discrepancy on flat-zipf-plus-scan synthetics: the product's parked position earned ~4pp more than sketch.WindowTinyLfu at the same window on a reference curve flat within 0.5pp (b_scarburn, round 1), and the product held at its 2% floor earned +1.6pp over the reference's static 2% on the veil trace while three such cells beat every reference window by 1.2–3.8pp (round 2), so small gaps on that terrain must not be read to the half-point until a same-window comparison settles whether it is admission jitter, sketch parameters, or the reference's own aging.

  • The masked-signal class beyond whisper: neither round's lanes constructed a main-side mirror … Closed in round 7 (2026-08-21): mainsat is the main-side mirror with an interior peak (the two-sided residency condition: the core stays out of the window at 80% and inside main at the peak, with a 52% scan holding the window's residency down), noaudit pins the floor 14pp under the dense-swept ceiling, and the equilibrium audit owns it as it owns whisper; rowed as a sentinel. No new class; the round-2 note on cheap keepalives stands for the window side.

  • s_scarburst and s_flashpark are dose notes on recorded classes with open controls (a second trace seed, a neighborhood) (round 1). Still open after rounds 2–5. Round 6's parkveil supplied the class's independent second construction, period ladder and neighborhood, and family-ized it (the reactive-anchor phase-chase class); scarburst's own grid caveat stands on its row. The pair instrument was exercised in round 2 (s_alias_band/s_alias_scan): the pair's premise failed at the deciding field, window hits 30 against 45 around the bar of 32 at the arming sample, so no class-8 pair has yet survived a screen.

  • Two dose ladders in round 2 flipped by the parent terrain's own lottery rather than by the knob (the veil share below 3e-4; the lure share at ~1.6%): a regenerated trace jitters a basin selector that sits within ±2 hits of the starvation bar, so read the ladder's dumps at the decision sample before calling a transition. workload.py cannot overlay a rider on a fixed base trace (every member draws from one RNG stream); a per-member seed would remove that confound.

  • regret.py's position regret interpolates the static curve linearly between swept windows … a --windows option for a dense re-sweep is the follow-up (round 2). Done in round 3 (--windows; on demoflood the 15%/25% points move the position regret 6.44 → 5.91 and the residual −0.51 → +0.02).

  • absolve was repaired 2026-08-17 (hill-climber.md §5): both gate rows moved (24.77 → 41.46, 27.95 → 46.29) by a repeat-confirm memory on the starvation ladder and a park's first audit following its walk; the period-16 witness at 256 samples reads 46.89 on 8 seeds and the family cells at 128 samples 43–44. Still open on the family: absolve_p20 (a 2-of-8 lottery either way) and the period-16 form's audit crash on the lure's off-step at other doses (three of the neighborhood's period-32 cells at 64 samples).

  • The proposal lane on the session model (Fable) stalled in round 2 (four consecutive 96,000-token thinking turns with two tool rounds between them, then the output-token cap aborted it after ~2 hours; nothing written): the model, not the machine (continuous timestamps, no permission or classifier events); the blind lane fell back to Opus, which delivered in 14 minutes. The dispatch rule above now puts both lanes on Opus with a ~20-minute box. Rounds 3 and 4 ran the third-lane shape (three or four specs, each written to disk the moment it is designed, aimed at named lines) on Fable: three specs and predictions in nine and eight minutes, done before the screen; none survived either screen (round 3: f_ghostlure recorded, f_cornerloop peak-at-edge, f_crestshelf clean; round 4: f_dipref, f_crestcliff, f_probetax clean or beating the reference), so the shape works and its yield is a fair sample of two.

  • hazefloor (round 3): … a sentinel row needs an x4 run at fixed seeds, per-seed bars, a 60/65% re-sweep Done in round 4: rowed at 320 samples (41.09 ± 1.80 at seeds 1–8; the re-sweep moved the ceiling to 52.27 @65%; reactive 36.5, noaudit 37.5; per-seed bars). Still open from that note: an arm with the crash-undo discard disabled, to say how much of the cycle is the discard and how much the corner audit's forced direction; a fix-side question.

  • Two round-3 observations for the record rather than the round: after a regime shift on which everything works (the claim discarded, the audit walk confirms), the machine still spends ~27 samples in the valley (16 of audit wait after the crash-scale swing plus a nine-stride ×1 walk; ghostclaim's 16-sample-phase-1 neighborhood cells at n = 80: 10.6pp, all transient), the recovery latency's floor; and a walk armed in one phase of a large square-wave modulation crash-aborts against its own frozen base the moment the other phase returns, at the position that is right for that phase (s_farecho: the level test across a 20pp phase boundary; the recorded exit-bar threshold at an extreme dose).

  • Class-8 pairs: round 3's s_pairup/s_pairdown held identical machine state through the decision by construction (a member at share 0.0 in the shared segment, only its reuse distance differing), so the pair instrument's premise can be met; the pair diverged at the shift sample itself (hr 0.30 vs 0.55) and the regret came from the stale claim rather than the shared direction bit, so no class-8 finding has yet survived a screen.

  • Round 4's leftovers. b_causepair_b (a hot zipf phasing into main at s6 on a hold cell): the calibration audit's level-step confirm at 33% (absolve's calibration mechanism), the follow rule sending the park's audit up into a crash and back; the reactive law 48.7 against the machine's 42.9 ± 1.9 and noaudit's 47.0, so a reactive-anchor sentinel candidate of scarburst's kind (the hold-cell face); the spec is in the round-4 workspace, not rowed. s_fatbase (the far-crest face of crestpast: regimeramp's cold-reference misconfirm parking the window in a valley 21pp below the ceiling for 32 samples; 29.6 against 44.3 at 45%, LRU 37.2, deterministic) is the trend thread's largest measured dose and would make a sharper sentinel than regimeramp (whose priced cost is ~1.3) if that thread is worked; not rowed. The class-8 pair b_causepair_a/b met the pair premise by construction and failed it at the decision (+22pp against +6pp on the arm's first stride), the third pair in three rounds to do so. The arrival transient (a stride's sample under-reads the position just reached, so a walk's best sample is one to two strides past the static crest on most crestpast cells) bounds any walk's-best verdict and should be measured before one is built. The masked-signal main-side mirror is still untried after four rounds (the sighted lane's s_fatbase attempt at a probation poisoned before the arm did not produce it: no starvation probe armed). Three round-4 specs beat the reference on zipf-plus-scan terrain again (f_dipref −2.3, f_probetax −5.6, s_thrashundo −0.7): the anchor-fidelity note stands.

  • Round 5's leftovers (the consolidation round, 2026-08-20; per-tenant instrument tenants.py). The dilute-valley family (h95±1 on the mixture terrain, class 3 reaching the audit walk's exit tests; witness deterministic at 8 seeds, hybrid 45.65 / noaudit 49.99 on the band tenant) awaits Ben's promotion call as a per-tenant sentinel bar. Unmapped: a d-ladder at fixed h95, the h-scan at 16384/d0.5 beyond h93/h95, K>2 tenants, and per-seed per-tenant readout on a bimodal instance (the second trace instance reads +2.29 with aggregate sd 0.25; tenants.py prints seed means). The admission-duel structural construction failed at 2–3% minority share (a uniform and a mild-zipf minority both admitted fine against a heavy zipf majority) — the class-0 consolidation story is unconstructed, and the masked-signal main-side mirror is still untried after five rounds. A weighted (byte) variant of any tenant family needs a weighted trace writer first; named residue, not scheduled. Dedicated-counterfactual arms above 0.5 of the minority's fraction carry warmup (n < 40); keep the load-bearing comparisons at fractions where n clears the bar.

  • Round 7's leftovers. latebloom's fix-side questions are the latency face (a stand-down that re-arms the clock; a hold that expires with the shield), and its boundary is the catch window beyond density's ~19% rest (dreq·miss/max ≳ 0.19) for the alignments where the stand-down releases the park, with the held alignments losing at any distance above the floor's residency. mainsat's plants are the rail-return arrival discard (its second face); arrive is the measured arm and needs the plants on its benefit side before the C2 verdict is restated. The class-8 pair instrument has failed its premise at the deciding field five times in six rounds; a pair needs the divergent member invisible to hr, wh, mh and ema at the decision, which a ramped or boundary-introduced member never is, so the next pair must differ only in a reuse distance both beyond the current residency and inside the walk's reach, with the divergence opening during the walk. Class 7 still has no synthetic witness (s_recoil's post-undo deficit sat inside its scatter at one seed; run it seeded and longer). s_floorstraddle is a sharper calibration-park sentinel than regimeramp (13.8 against ~1.3) if that thread is worked; not rowed. b_slowfade's monotone-ramp attack on the rail needs an interior peak (size the lean core to leave room) before its bad_veto question can be asked. The dump file name carries no size, so eval --size N on a spec overwrites the spec's own-size dump (the 8192 s_floorstraddle dump was lost to its 32768 run); regenerate the geometry with mutate --set max= instead, which also keeps the sample count.

  • Round 6's leftovers (2026-08-21). The masked-signal main-side mirror is now 0 for 8 across six fable rounds (the parallel Sol synthetic round's two deliberate MAIN mirrors also failed, 0 for 10 across the lanes), and this round's two failures both died at the terrain rather than the mask: s_mainmask's band was worth nothing at any window (its cell is a hold cell with LRU structurally above the whole curve) and b_mainwhisper's peak fled to the 80% edge while the mask itself worked (probes = 0 for the whole trace with main sighted — the first construction to get that far; the spec is in the round-6 workspace for an interior-peak retry). The three constraints — main dense, marginally worthless, and an interior-peak curve — fight each other through the admission filter, and the next attempt should budget the far prize's reuse distance against the miss-rate-scaled residency the round-6 report works out. Two sighted terrains put plain LRU 20+pp above the entire static W-TinyLfu curve (long-distance k=2 bands admission refuses; rep_r6's norank geometry at k=2) — check a screen row's LRU against its ceiling before reading its gap as climber regret. parkveil's 240-sample period ladder was not run (the 60-sample ladder plus the base's p13 record cover the axis for a sentinel, not for a fix); its promotion edits were staged uncommitted for Ben. s_valefloor is preserved as a fast-running class-1 witness (a compressed micro-valley at the floor, 17.99/17.76/23.61 at 1/3/5%, hybrid ≡ noaudit) if marginal steering (§5) is ever worked; the FIU mechanism itself (settling in the near basin) still has no synthetic reproduction — the machine overshoots instead.

  • Round 9's leftovers (2026-08-31, opus-5). moatweather was not run against the real corpus: whether any real cell carries a level step of this size and a traverse long enough for it to land on a walk is the anti-correlation §3 already records, so the honest expectation is a constructed-only row, and the check (a real.py pass plus a scatter-versus-terrain scan) belongs before any repair. Its coincidence axis was measured at one period pair (24 at two phases) and its traverse axis on one terrain; whether the same dreq slope appears on shallowmoat or lowbar with weather added is the generalization. b_moatnoise's divergent attribution (there the calibration audit earns +1.7 and the later audits cost) was not chased to a responder. The class-8 pair failed a seventh time in a new place: s_twinloop_a/b met the premise at the trace (identical member sequences, byte-identical non-twin streams, both verified) and failed at the terrain, because a loop member is not resident when the window's capacity equals its cycle length, so both curves were monotone declines and both cells hold cells; a pair built on a residency threshold must measure the threshold on the generated trace rather than compute it. Class 7 is witness-less for the third round running (s_emberloss's capacity-refill construction did reach the top of the curve, but undo_deficit +1.06 sat inside an hr scatter of 3.54). Three blind cells were dropped peak-at-edge without a dense re-sweep, so one may still have an interior peak. Two process facts: a Fable proposal lane and a Fable evaluator both failed without writing anything, so an evaluator needs a completion check and a re-dispatch on another model rather than an open-ended wait; and the harness did not build at HEAD (the jspecify migration made System.getProperty(k, default) @Nullable at five injection sites), while harness.py strip cannot strip a tree applied by an older harness, so reset a worktree with git checkout -- . before re-applying an edited one.

  • Round 8's leftovers (2026-08-30, fable). The class-8 pair failed its premise a sixth time, with the failure one layer down: the shared 2.2pp/stride drawdown never tripped the absolute 5pp abort, so both walks ran long enough for A's flipped band to be caught — a distance-flip pair that diverges during the walk diverges by being caught, which is visibility, so round 7's "divergence opening during the walk" requirement is self-defeating in that form. The next pair must first prove its shared abort fires on the common terrain (the drawdown dose is what failed), with the flipped band reachable only past the abort stride. The interior-peak bad_veto construction is 0-for-2 (b_slowfade round 7, s_creepveto round 8: the rail never fired; the trend feeds the confirm and the walk exit bars first). Class 7 is still witness-less (s_scorch repeated s_recoil's inside-scatter fate at gap 1.95). The s_probcap structural note is closed: s_probcapgeo places a two-reference band between the window's reach and LRU's (dreq 8,050–9,850; Belady 53.3, LRU 52.3, every reachable window 20.4), and the whole loss is TinyLFU refusing once-seen candidates while the band's push distance exceeds the window's 80.2% cap: a larger probation at the same window recovers nothing (328 to 1,638 entries: 19.9 to 20.1), a filtered full-size LRU reads 20.35, and the reference recovers only at an 89–92% window. Structural; it does not overturn §5's corpus verdict on the main-space knobs. pricedshift (+0.63 at n=129, +1.80 with the capture tail zeroed at repeat×2 on pinnacle) has an unmeasured cost side on the families that need the discard to fire (ghostclaim, regimeramp, the moat rows). The arrival-transient verdict bound was witnessed twice in one round (settleflip's cold-start inversion; pinnacle's one-stride overshoot); if either family is promoted, the bound belongs in hill-climber.md as a recorded residual rather than a round-4 note.

  • Round 10's leftovers (2026-09-17, fable-5.1). needle is constructed-only: a marginal.py static anatomy at a 1% grid over the non-convex real cells (P3, fiu_webmail) is the realism check, and the ten-point grid cannot see the shape, so a screen ranked by coarse gap will miss a narrow interior peak (the round's finding ranked 10th of 17) and a ~96-sample screen reads a retention loss as solved (the wide face's discard lands at ~s116). pricedshift now has a +5.9 benefit witness (one decision: identical to the shipped machine in every dumped field through s115 on every seed checked; +2.8 to +5.9 across the surface) and still no measured cost side on the families that need the discard to fire (ghostclaim, regimeramp, the moat rows); price that before anything else. The narrow face's rule is four consecutive above-bar samples ending on or after the walk's fifth, and every cell shares the calibration's 32.0% park, so its verdict is one reading (the 62.7% sample); a share of 0.10 is a 3-in-12 coin that a two-seed ladder read as a cell, so give a rung near a threshold the seeds a classification cell gets, and read admission seeds as one decision path unless a dump diff says otherwise. Promoted 2026-10-10 as two sentinel rows, re-measured identical at HEAD; round 8's pinnacle survives only in its record, as a one-stride overshoot on arrival, which the narrow face is not. The narrow face has no repair candidate: what separates a three-sample needle from a three-sample spike is persistence at rest, which a moving walk never measures, and every pull-back variant in §5 died on that distinction. b_creepclaim (the blind lane's independent ramp_retest) is a 5-vs-3 basin lottery with a 15pp spread selected by a 0.24pp difference between adjacent samples of one walk: the best-sample rule parks on the catch region's near edge or one stride in, and an insert-rate ramp erodes the edge under the shield with the claim resynced down; reachable there only through the veto, unchallenged, and wanting a cell that reaches it without one. Class 8: s_twinwait_a/b met the pair premise for the first time (40 of 40 trajectory lines byte-identical through the decision: the divergent member absent from the first segment, pairs drawing nothing at construction), and produced no regret because the prefix left the machine parked by the cold-start misconfirm rather than in floor backoff; the next pair keeps the construction and needs a prefix with no warmup trend. Class 7 has its first witness above scatter, and only as a same-position measurement inside a surviving park (the script's undo_deficit stayed phase-confounded on the shipped arm); b_undodebt and s_emberfade sat inside their scatter. The FIU near-basin settle failed again (s_nearsettle rests in the near basin for 30 samples and then crosses: the valley must be deeper than AUDIT_BAR_FRACTION of the base rate, as lowbar's is). After an AUDITCONFIRM+home the follow rule's staleness guard fires whenever the best sample beat the confirm-time smoothed rate by 5pp, which the pull-back makes likely by construction; unpriced. The arrival-discard link showed on three independent cells in one round. Process: give the sighted lane §3, the class table and the directions, and §5 and the gate table by heading only; it had nothing on disk at 28 minutes and delivered within three of a nudge.

  • The real-trace episode readings of round 11's teacher (seed 1, one product draw, no ablation arm confirmed any; each matches a recorded class): (1) the cloud-physics rest point, with the cp_w097/w098/w100@16384 family as its cleanest real class-1 witness, for the carried real-trace anatomy above; (2) the audit retry on floor-optimal traces (P8, P1@65536), its crash persistence and its base frozen on a dip; (3) blind-corner starvation probes from steering on scan samples (DS1@1M), where whether that is the gate's intended price on a scan-heavy trace is still open; (4) the proportional step's phase asymmetry (cp_w058@16384, the law right and the pace wrong). Any climber change that follows owes /climber-gate.

Rules of evidence

  • A new predictor needs controls for the information it adds. Freeze its query population, horizon, weighting and cold-start learning before outcomes. Compare age, authentic aged frequency, their combination, and an equally deep estimator with no new feature; use common queries, complete negative outcomes and explicit censoring. Check what survives the actual maintenance stream, and count learner state and observation work as well as sampled keys. Better reuse prediction or ranking does not establish a mode trigger or a profitable window move; evaluate that action separately. See methodology and the gate's prefix-scoring precautions for application traces.
  • A claim about a particular decision needs a feasible paired continuation, not just a static ceiling gap. Follow §6's decision-replay protocol for attribution and retention studies. regret.py's trajectory hints and the canonical seeded-stream harness do not themselves establish equivalent decision state or request/contest pairing. Implement the needed hooks against the current source in the local experiment, verify prefix/randomness/observer controls, and retain useful workload specs and conclusions in the existing skills/design record. Reports, raw runs, build snapshots and experiment-specific runners belong in .local; preserving them is not integration into this workflow.
  • A gap under 2.5pp needs eight seeded, paired runs; a bimodal cell is read seed by seed and never from a mean; seeded arms pair by seed (regret.py), unseeded comparisons rotate arms inside each run (gate.py), and neither compares across sweeps. Ladder rungs used to establish a classification threshold need the same eight admission seeds as classification cells. Read them seed by seed; a one-seed screen does not establish the boundary.
  • A trace holds requests / (4 × max) decisions; classify nothing under 40 and re-check any finding at repeat ×2 before calling it steady state. Repetition restarts the segment-local modulation clock, so it can introduce a phase jump. For a single sine- or square-modulated segment, also lengthen samples with repeat=1 and verify that the original request prefix is unchanged. Keep restarted and continuous controls separate; recovery after a restart does not establish recovery under uninterrupted demand.
  • Sign-uniform losses across a family are a mechanism, not noise, whatever their size, and a result that contradicts the round's hypothesis is written up as the result rather than reframed into one the data supports.
  • Uniform across seeds is not uniform across a family. Seeds vary admission draws, not a spec's schedule, so where a regime changes at a fixed sample every seed meets it at the same audit phase, and a loss on all eight seeds can be one timing draw. Move the change (its segment's samples) before classifying it as a mechanism: on the gate's slowswap step the shipped climber reads 33.3–41.8 as the swap moves ±24 samples.
  • Do not rebuild §5's graveyard, and do not reopen anything in it without a new mechanism; when a proposal resembles one, say which and what differs.
  • Holdout discipline is §6's: freeze before tuning by LRU-only characterization (run.py --anchors --variants ''), spend once, and match the holdout to the change.
  • One session's fix is presented before it is committed; docs (hill-climber.md, the gate table, rules/design-decisions.md) move in the same commit as the code.

Reporting

.local/audits/<model>/audit-regret.md, with the metadata header (Audit, Date, Commit) and, in this order: the screen table (label, size, n, LRU, start, ceiling@w, cache, gap, headroom, closed, missx, hint vote); one section per finding (the family and its knobs, the minimal witness spec, the transition, the class and secondary classes, the responder and owner, the arm table at eight seeds, the neighborhood surface, the nearest recorded family and the difference, the evaluator's objections and how each was answered, and the promotion status); the candidates dropped and why (dedup, validity gate, unreproduced); and what was not tried. Findings that turn out structural go in their own section addressed to the admission/sketch/SLRU owner. Everything that changed the record goes into hill-climber.md in the same session, and the ledger row is closed with the report's path.