# Upgrade Guide — vNEXT

<!-- assembled-by: assemble-next-md -->
<!-- bump: patch -->

## What Changed

The SessionManager age-gate (the 5-second monitor tick) used to re-request a kill for an over-age, idle-at-prompt session on EVERY tick. When the §P2 KEEP-guard correctly vetoed that kill (the session had a recent user message, was topic-bound, or held an open commitment), the session survived — but the gate re-asked 5 seconds later, forever. On 2026-06-05 this produced 17,503 identical kill-request log lines for kept sessions plus the wasted CPU that read as "heavy load." A new pure, bounded `AgeKillBackoff` ledger makes the age-gate RESPECT the guard's verdict: after a veto it suppresses re-requests for `ageKillBackoffMinutes` (default 10) — ~6 asks/hour instead of 720 — collapsing to ONE informative log line. It changes only how OFTEN the age-gate asks, never WHICH sessions die: the KEEP-guard remains the sole authority, and a genuinely-abandoned session (no keep-reason) still dies on the first ask exactly as before.

## What to Tell Your User

Your long-lived working sessions no longer get hammered by a kill-request loop they always survive — the churn (and the log/CPU noise it caused) is gone, while nothing about which sessions actually get cleaned up has changed.

## Summary of New Capabilities

- Age-gate kill back-off: a vetoed kill is honored for a back-off window instead of being re-asked every tick. Tunable via `ageKillBackoffMinutes` in config (default 10; `0` restores the legacy every-tick behavior). Existing agents get the fix automatically on update — the default lives in code, no config migration required.

## Evidence

Live incident 2026-06-05: 17,503 identical "Requesting kill"/deferral lines for over-age sessions (this conversation's topic plus three other long-lived sessions), every one correctly vetoed by the KEEP-guard — wasted CPU that surfaced to the operator as "resource issues." Root cause: the age-gate at `SessionManager.monitorTick` re-requested a kill every 5s with no memory of the prior veto. Fix: `src/core/AgeKillBackoff.ts` (pure, injectable clock, bounded `maxTracked` memory, mirrors `AttentionTopicGuard`), wired into the age-gate to `recordVeto`/`recordKilled` and gate re-asks via `shouldRequest`. Spec `docs/specs/age-kill-backoff.md` (converged + approved). Tests: 11 green — 7 unit (incl. a 720→6 asks/hour regression pin) + 4 integration against the real SessionManager ledger; tsc clean.
