# Handoff — Sonnet **Sprint goal focus:** Freestyle runs survive & gates bite (Goal 1) + one hard resilience feature (Goal 2). You get the router/orchestrator brain-surgery — cross-module, judgement-heavy, easy to get subtly wrong. Read the full task body in Vikunja (project 4) before starting each — `mcp__vikunja__get_task_details `. Mark each **Doing** on start, and **commit green work referencing the task #** when done. ## Tasks ### #299 — Single provider death → unrecoverable session kill A retryable provider connection drop collapses into a hard `NoEligibleProvider` abort that fails the WHOLE session. On a retryable inference failure, tolerate a briefly-absent provider (bounded wait/backoff for the capability) before declaring terminal. Distinguish "provider temporarily down" from "capability never configured". Files: `CapabilityAwareRoutingStrategy.kt:31`, `DefaultInferenceRouter.kt:54`, `ServerModule.runSession` (the catch that fails the session), SessionOrchestrator retry path. ### #300 — HealthMonitor detects provider loss ~18s too late Same incident as #299. Health status must GATE routing/retry, not just log reactively. Mark a provider unhealthy immediately on the connection drop (event-driven), and have the retry consult health + wait for recovery. **Do #299 first — #300 completes the health-gating half.** ### #297 — Analyst CoT indecision loop burns full budget, emits nothing Analyst maxed 16384 reasoning tokens and emitted an empty artifact because the request maps to a PARENT epic, not a single task, and the DoD prompt says "the single task this run owns" → endless oscillation. Primary fix: pre-resolve which task the run owns before the analyst, OR make the DoD prompt explicit ("define the DoD for the epic as a whole; do NOT pick a child"). Optional backstop (can be a separate task): reasoning-token soft cap. ### #263 + #267 — Auto build-gate never fires on real freestyle scaffold The terminal build gate produced ZERO `StaticAnalysisCompleted` events across a 60-file run. Root cause traced in the ticket: writes-based terminal-stage selection can't pick a non-writing REVIEW terminal stage, and the last writing stage's build gate is shadowed by its own contract gate short-circuiting. Fix direction: attach the auto build-gate to the last WRITING stage, or run it as a workflow-terminal check on the `done` transition independent of per-stage autoBuildGate. Reconcile code (per-stage writes filter) vs comment (terminal-only) — they disagree today. **#267 is the settle-it-live half: one live run confirms the gate fires. Do them together.** **Depends on #191 (Codex) landing** — the gate fires into missing `node_modules` without `setup=npm ci`. Coordinate so your live run goes green. ### #301 — Escalate repeated scope/manifest write-block to user approval (Goal 2) After N same-path scope/manifest rejections (config `escalate_scope_after_n`, default 3), stop rejecting: reach back to the FIRST rejected invocation's pristine write args in the event log, present via the existing approval/pause flow, approve→widen scope + execute, reject→continue. No branching/replay-engine — plain forward event-log read. Wiring pointers in the ticket: `SessionOrchestratorToolExec.kt` ~234-282 (BLOCK branch) and ~284-422 (existing approval flow + `OutsidePathAccessGrantedEvent` widen-and-execute template). **This is the natural carry-over if the lane is over-full — it's a feature, not a run-killer.** ## Sequencing 299 → 300 (same owner). 263/267 needs 191 (Codex) landed first.