audit-adaptivity

Audit the adaptive window hill-climber and region-resize logic for implementation defects (not algorithm quality)

SKILL.md

GitHub

Audit the adaptive W-TinyLFU control loop and the admission-window / main-region resize logic for IMPLEMENTATION defects. This is the one eviction subsystem not in /audit-subsystem-safety's scope, and it was recently rebuilt — the climber now lives in the package-private WindowClimber class (reached through the generated climber field), with a new density-signal + probe-machine large tier (>4096) — so it has elevated bug density.

Scope boundary — implementation correctness, NOT algorithm quality

The adaptation policy itself is at its tuned frontier. Out of scope: convergence rate, hit-rate, oscillation-as-a-design-tradeoff, and the choice of the tuning constants. (Behavioral hit-rate regression against the adversarial trap suite is /climber-gate's job, not this audit's.) Do NOT report "the climber could converge faster / oscillates / constant X should be Y." Report only defects: arithmetic that yields a wrong value, a sign error, a state that violates a structural invariant, a race, a NaN, or an overflow.

Methods in scope

  • climb, determineAdjustment — the feedback step (reactive: hit-rate delta; density: within-sample densities → step → adjustment). determineAdjustment carries mainProtectedMaximum to size the probation capacity for the probe verdict
  • densityClimb, armProbe, walkStep, probeEnding, undoProbe, DensityClimber.steer — the large tier's signal, probe machine, and verdict internals (all on WindowClimber)
  • increaseWindow, decreaseWindow, demoteFromMainProtected — region transfer
  • setMaximumSize — initial window/main split, plus WindowClimber.resized (the SLOW_ADAPT_THRESHOLD step-sign flip and the probe-machine reset)
  • evictFromWindow / evictFromMain — they consume the region maxima the climber sets

Probe machine (>4096, in WindowClimber): starved samples (region hits below max(4, requestCount >> MIN_SIGNAL_SHIFT)) at a blind corner launch a bold-driver walk. Endings: crash-abort (full undo, refractory re-armed WITHOUT doubling), reversal-through-base and budget expiry (failed experiments: full undo + ladder x2), adjudication at >=4x the bar under the committed depth (confirm keeps the position + ladder resets to 1; anything else fails with a full undo). The verdict is asymmetric BY DESIGN: an up-probe confirms iff ln((windowDensity+eps)/(walk.baseProbationDensity+eps)) > 0 — the probation-marginal baseline FROZEN in armProbe — while a down-probe uses the average-density sign test (error*dir > 0). Ladder: PROBE_BACKOFF_INITIAL (16) doubling to _MAX (64). Invariants to audit: 1 <= starvation.rung <= 64; 0 <= refractoryLeft <= starvation.rung, which both oracles assert directly — the walk budget is a separate field (Walk.samples, bounded by PROBE_WALK_BUDGET) on an object that exists only while walking, so the two can no longer alias; probe state fully reset by resized; an undo returns exactly to walk.baseWindow; the below-floor lift cannot exceed the floor; sample.probationHits <= sample.hits - sample.windowHits; walk.baseProbationDensity is written ONLY in armProbe (each re-arm re-snapshots) and is non-negative and finite; the probation capacity denominator is max(1, maximum - windowMaximum - mainProtectedMaximum) — capacities, never occupancy.

NOT bugs (adjudicated design; read hill-climber.md §4 before flagging): the up/down verdict asymmetry (the window has no marginal substructure to price against); the frozen — hence stale-looking — baseline (judging against the LIVE probation rate is an absorbing false-veto: the walk's own demotions enrich it — the demoflood gate row; a cold-start-transient baseline is bounded and self-heals because every re-arm re-snapshots); probation attribution captured BEFORE reorderProbation can promote the entry in onAccess (the promoting access counts as a probation hit, the next as protected); a zero baseline auto-confirming any >=4x-bar earnings (the opportunity cost of a dead boundary is ~zero — nullchurn stays harmless); and the lowmix named trade (a gate sentinel). A walk's bases (down, baseHitRate, baseWindow, baseProbationDensity) are final on the Walk object, which exists only while one is in flight — "dead state while not probing" is the absent object, so there is nothing to go stale.

Cache-side fields: windowMaximum, mainProtectedMaximum, windowWeightedSize, mainProtectedWeightedSize; QUEUE_TRANSFER_THRESHOLD.

WindowClimber owns adjustment, sample (Sample: hits, misses, windowHits, probationHits, previousHitRate), and tier (a ReactiveClimber or DensityClimber). The Climber base class owns step (Step: size), initialized from the maximum and the strategy's chosen direction at construction. DensityClimber owns refractoryLeft, retreatLeft, undoRemaining, and its helper objects: walk (Walk, null while none is in flight: ladder, isAudit, down, baseWindow, baseHitRate, baseSmoothedRate, baseProbationDensity, samples, belowBarStreak, aboveStreak, beatBase), starvation and audit (a Ladder each: rung, crashStreak), auditClock (AuditClock: down, waitSamples, stillSamples, lastWindow), anchor (Anchor: window, rate, held, freshLeft, returning, returnLeft, shortfallStreak), and rates (Rates: smoothed, deviation). Reading is the per-sample derived view, computed once and read-only.

The 38 constants live with the mechanism each tunes, so a knob names its owner: WindowClimber — RESTART_THRESHOLD; DensityClimber — DENSITY_THRESHOLD, DENSITY_GAIN, SAMPLE_MULTIPLIER; Step — STEP_PERCENT, STEP_DECAY_RATE, MIN_INITIAL_STEP; ReactiveClimber — SLOW_ADAPT_THRESHOLD, SLOW_ADAPT_RATIO_CAP, SLOW_ADAPT_DECAY_RATE; Reading — STABLE_BAND_FRACTION, MAX_STEP_FRACTION, WINDOW_FLOOR_FRACTION, DENSITY_EPSILON, MIN_SIGNAL_SHIFT, MIN_STARVATION_BAR; Rates — VETO_MARGIN_MIN, RATE_SMOOTHING, DEVIATION_SEED, VETO_MARGIN_SCALE; AuditClock — AUDIT_WAIT_INITIAL, AUDIT_WAIT_FIRST, AUDIT_WAIT_MAX; Anchor — VETO_STREAK, VETO_RETURN_BUDGET; Walk — PROBE_WALK_BUDGET, PROBE_BAR_CAP, PROBE_EXIT_BAR_MULTIPLE, AUDIT_CRASH_PERSISTENCE, AUDIT_COMMITMENT, AUDIT_CONFIRM_STREAK; Ladder — PROBE_BACKOFF_INITIAL, PROBE_BACKOFF_MAX, PROBE_CRASH_ESCALATION, PROBE_STRIDE_SCALE_MID, PROBE_STRIDE_SCALE_DEEP, PROBE_COMMITMENT_MID, PROBE_COMMITMENT_DEEP.

Structural invariants to attack (violations are real bugs)

  1. Region partition sum: windowMaximum + mainMaximum (probation + protected) must equal maximum after every climb and every resize. Can any single transfer, or a sequence capped by QUEUE_TRANSFER_THRESHOLD, drift the sum?
  2. Non-negative maxima: can windowMaximum or mainProtectedMaximum go negative — a quota larger than the donor region, or repeated decreaseWindow at the floor? EXCEPTION (adjudicated 2026-07, F1; duration priced 2026-08-22, M1): a transiently negative policyWeight — the sanctioned telescoping race, an out-of-order UpdateTask drain — can over-shift the caps beyond the commanded adjustment, even past these bounds. Tolerated by design: the caps are policy targets (eviction is driven by the telescoping weightedSize/maximum), and they walk back only by the weight each later transfer moves, so a swing larger than a cycle's transfer suspends the split for many cycles with the total still bounded. Report cap drift only with a mechanism that never walks back.
  3. Quota accounting: in increaseWindow/decreaseWindow the quota is decremented per transferred node by policyWeight. With weighted entries, can quota underflow, skip/over-run the loop, or transfer the wrong count? Does the QUEUE_TRANSFER_THRESHOLD cap leave the regions half-adjusted such that the next climb mis-reads them? (Same F1 exception as #2 for the negative transient.)
  4. determineAdjustment math:
    • requestCount = hits + misses; the early return guards requestCount < effectiveSampleSize. Is the hitRate division ever reachable with requestCount == 0?
    • small-cache branch (ReactiveClimber.samplePeriod): (long) (sketchSampleSize * ratio), where ratio = clamp(initialStep / magnitude). Can initialStep be 0 (maximum 0 or tiny) making magnitude 0 → division by zero? Can the (long) cast truncate ratio so it defeats the intended sample-period growth?
    • ReactiveClimber.climb uses Math.copySign(Step.restartMagnitude(max), amount). For amount == 0.0 / -0.0, does copySign choose the intended direction? Can step.size become NaN or 0 and permanently stall adaptation (a stuck-window bug, distinct from slow convergence)?
  5. setMaximumSize at boundaries: the step-sign flip at max <= SLOW_ADAPT_THRESHOLD plus a runtime maximum change via Policy.eviction.setMaximum — when maximum crosses SLOW_ADAPT_THRESHOLD in either direction, do the window/main split, the step.size sign, and the sample state stay mutually consistent?
  6. Stale adjustment and sample memory across the gates: climb calls determineAdjustment then increaseWindow/decreaseWindow off the climber's adjustment. The tier is skipped on three paths: an uninitialized sketch (resetSample), a sub-period sample, and a cache below half occupancy (discardSample, which resets a full sample). Can a stale adjustment from a prior cycle be re-applied? The half-full gate is reachable mid-life while the tier's walk, anchor and rates persist, so also check what each path does to the cross-sample previousHitRate that the reactive step, the stand-down trigger (isWorkloadShift) and the walk's bold driver (nextStride) compare against.
  7. Layer ownership of the ladders, streaks, and schedules — the highest-yield row, because it has produced two real bugs and both were invisible from a single code path. hill-climber.md §4 carries a write-owner table (observation / active walk / starvation retry / audit retry+schedule / goal guard / motion out). Enumerate every write to starvation.rung, starvation.crashStreak, audit.rung, audit.crashStreak, auditClock.waitSamples, auditClock.stillSamples, anchor.held, anchor.freshLeft and check each against its owner — including endings that are not crashes. Both landed defects were exactly this shape: the shared crash streak let exogenous pulses pair separate audit crashes into a rung ratchet (H4-C1), and later a non-crash ending (budget expiry, reversal-through-base) still cleared the other layer's streak, which disarmed that layer's escalation and its AUDIT_CRASH_PERSISTENCE tolerance — so an interleaved blind corner reached around the first fix. One cross-write is sanctioned, journaled: an audit confirm rewards the starvation ladder (starvation.reward) and zeroes its refractory. An audit's undo leaves the refractory alone (since 2026-08-16, pinned by undoProbe_auditRetreat_leavesTheStarvationRefractoryAlone). Anything else is a finding. Checkable products the oracles already assert, and which a new invariant should join: anchor.freshLeft > 0 ⇒ anchor.held, anchor.held ⇒ anchor.isPlanted, walk != null ⇒ undoRemaining == 0, and auditClock.waitSamples > PROBE_BACKOFF_MAX ⇒ audit.rung == PROBE_BACKOFF_MAX (the ratchet as an invariant). Note the one legitimate coupling so it is not reported: the audit clock is a function of window position, so any layer that moves the window decays stillSamples — that is the intended semantics, and it is the remaining path by which frequent blind corners defer audits.

Output

For each defect: give concrete maximum/weight/access values, trace the arithmetic step by step, show the resulting invariant violation or wrong region size, and a Verification (a BoundedLocalCacheTest white-box method plus the required -P flags).

Everything here runs under evictionLock (single-writer), so most findings will be arithmetic / state-corruption, not races — but explicitly check whether any climber-written field (adjustment, step.size, the region maxima) is also read off-lock by a concurrent reader before concluding "single-writer, cannot race."