From 4a730084f1dd9ac9ad0181d4025db6a2e161921e Mon Sep 17 00:00:00 2001 From: kami Date: Sun, 26 Jul 2026 23:30:35 +0400 Subject: [PATCH] docs(sprint): record #307, #304, #309, #306 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01HgDL1v3GuQ9RZnYR6fDT95 --- docs/sprints/2026-07-23.md | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/sprints/2026-07-23.md b/docs/sprints/2026-07-23.md index f3f381d3..7065311a 100644 --- a/docs/sprints/2026-07-23.md +++ b/docs/sprints/2026-07-23.md @@ -121,6 +121,48 @@ every flat alias still pointed at npm, so a Kotlin run's auto-gate would have ru `ProjectProfileLoader`; the gate prefers `.` and falls back to flat. #267's "re-scope #40" is now just the live confirmation. +### Goal 3 + Goal 2 progress — 2026-07-26 + +- **#307 ✅** (commits `c742656e`, `68b5392e`). `ContextAssembledEvent` records the injected manifest — + `{sourceType, sourceId, tokenEstimate, layer, role}` per entry, no content (that stays in CAS). Scope + check confirmed nothing existing carried it; `ContextTruncatedEvent` only reports drop counts. Emitted + at **all four** `contextPackBuilder.build` sites, not just the stage's first: the motivating question + ("did the steer-away hint fire on 7 consecutive turns?") is a per-rebuild question, and one event per + stage couldn't answer it. Turned out to be the delivery-tracking substrate #306 needed. +- **#304 ✅** (commit `2b13f610`). Chose option (b) — recovery is a real second chance. + `detectRepeatedToolFailure` windows its fold to events after the most recent `FailureTicketOpenedEvent` + naming the stage. Route budgets are charged off the ticket event by the reducer, so the reset can't + open an infinite route-in/route-out cycle: 2+2 route cycles, each needing 6 fresh failures to re-trip. +- **#309 ✅** (commits `ee69f9be`, `9db4e3dd`). `RecoveryFileLoopBreak.kt` — `fileRepairOutcomes` + correlates each `FileWrittenEvent` with the next `LspDiagnosticsCompletedEvent` per path, feeding both + consumers off one fold: the in-recovery guard (a path rewritten 3x without clearing opens + `FailureTicketOpened(gate=recovery_loop_break, escalated=true)` and fails terminally instead of + looping) and the ledger annotation in `buildRetryFeedbackEntry`, still `EntryRole.USER` with #313's + precedence untouched. **Correction landed on top:** the fold conflated "no diagnostic run since this + write" with "ran clean" — so the ledger said *"done, leave it"* about unverified files, and the breaker + could kill a run on the *absence* of evidence. Now a distinct `unchecked` state; the breaker requires + `!unchecked`. + - Left deliberately: the guard is terminal, not an operator-approval pause. Recovery is the last tier, + so there is nowhere to route; it opens the ticket for the record, then fails. Human-in-the-loop there + is a follow-up if wanted. +- **#306 ✅** (commits `bc5afa51`, `f78c7f15`). Two halves, and only both together fix the report. + *Across stage entries:* the hint is keyed to its `RetryAttemptedEvent` occurrence, delivery derived by + folding prior `ContextAssembledEvent` manifests (`sourceType="unconfirmedFix"`, `sourceId=classKey`) — + no new state, pure fold (invariant #9). *Within one stage entry:* the guard alone was not enough — + `unconfirmedFixEntries` is called once at stage entry and its result folded into `accumulatedEntries`, + which every `pushBack` rebuild re-uses, so the hint rode into every turn regardless. That is the actual + 7-turn symptom; the entry is now dropped once its first pack is built. + - Directions 2/3 from the ticket needed no code: `classKey` already derives from the current retry's + own class, and routing dead-ends carry `gate="stage"` while every other path carries its real gate, + so `"$gate:$signature"` can't collapse them. Locked in with a regression test rather than a rewrite. + +**Goal 3 remaining:** #299 + #300 (provider-death path). #308 partly pre-empted by `ac460156` — a shell +timeout is now recoverable and coaches `nohup &` detach, so there is no background-process registry to +build unless a real gate needs one. + +**Goal 2 remaining:** #261 (impl decomposition), plus status calls on #260 and #305 — both have landed +commits (`516af1ca`; `5df35879`/`8806de16`/`12775d56`/`f5aaa255`) but neither ticket is closed. + --- ## Landed out-of-band — context message-type sweep (#312, #313)