6.0 KiB
spec, created, status
| spec | created | status |
|---|---|---|
| docs/specs/ui/requirements/context-window-reset-freshness.md | 2026-07-31 | implemented |
Implementation Plan: Context Window Reset Freshness
Overview
Invalidate context-window data at the successful reset boundary, then teach the frontend to treat an explicit empty metadata value as cache invalidation. The initiating client also clears its local cache after a successful reset response so it does not wait for asynchronous session notifications. A focused browser regression proves that old usage disappears and a later fresh agent report can repopulate the ring.
Confirmed root cause
ResetAgentContext replaces the provider conversation but resetAgentContext only clears acp_session_id; it leaves task_sessions.metadata.context_window intact. The frontend also stores the last reading independently in contextWindow.bySessionId, and extractContextWindow only handles populated readings. Consequently, neither the reset response nor the subsequent session-state events invalidate the old ring; it remains visible until another agent usage frame overwrites it.
Backend
Successful reset metadata invalidation
- Update
apps/backend/internal/orchestrator/event_handlers_workflow.goinresetAgentContextto clearcontext_windowafteragentManager.ResetAgentContextsucceeds, alongsideacp_session_idcleanup. - Keep the clear after the irreversible runtime reset so failed resets preserve the previous reading.
- Log a metadata persistence failure without reporting the already-completed provider reset as failed; always clear the preloaded in-memory snapshot so the initiating client does not receive stale usage back through the final state event.
- Extend
apps/backend/internal/orchestrator/event_handlers_workflow_triggers_test.goto prove successful resets clear both metadata keys and failed resets retain context-window metadata.
The public user-request path and workflow reset path share this helper, so the invariant applies to both without adding a new API or event type. After a successful metadata clear, the existing transition back to WAITING_FOR_INPUT reloads session metadata and publishes it through session.state_changed.
Frontend
Explicit context-window invalidation
- Update
apps/web/lib/ws/handlers/agent-session.tsso context-window extraction recognizes both livemetadatapatches and fullsession_metadatasnapshots. When either explicitly containscontext_window: null, callclearContextWindow; when it contains a valid reading, keep the existingsetContextWindowbehavior; when the key is absent, do nothing. - Extend
apps/web/lib/ws/handlers/agent-session.test.tswith populated, cleared, and unrelated-metadata cases.
Initiating-client reset response
- Update
apps/web/components/task/chat/reset-context-button.tsxto clear the session context-window cache only aftersession.reset_contextresolves successfully. - Add
apps/web/components/task/chat/reset-context-button.test.tsxto prove success clears the correct session and request failure retains the prior cache.
No layout, breakpoint, touch, or scroll behavior changes. Desktop and mobile already render the same TokenUsageDisplay from the shared session-runtime state; apps/web/e2e/tests/chat/mobile-context-window-source.spec.ts remains the nearest mobile exemplar and covers the mobile trigger/tooltip path. The repair therefore uses shared-state tests rather than a new mobile composition.
Tests
- What: successful resets clear persisted context-window metadata while failed resets retain it.
- File:
apps/backend/internal/orchestrator/event_handlers_workflow_triggers_test.go - How: extend the existing real-repository reset helper tests, including successful provider reset plus metadata-clear failure, and run only
TestProcessOnEnterResetAgentContext.
- File:
- What: explicit cleared metadata invalidates the frontend cache, while metadata without the key leaves it untouched.
- File:
apps/web/lib/ws/handlers/agent-session.test.ts - How: dispatch
session.state_changedpayloads against the focused store fake.
- File:
- What: the initiating client clears usage after a successful reset response but not after rejection.
- File:
apps/web/components/task/chat/reset-context-button.test.tsx - How: render the control with mocked WebSocket and Zustand boundaries and exercise the confirmation action.
- File:
E2E Tests
- Scenario: GIVEN an idle session displays old context usage, WHEN the user resets context, THEN the old ring disappears; WHEN the fresh mock agent later reports usage, THEN the ring reappears with the fresh reading.
- File:
apps/web/e2e/tests/session/session-recovery.spec.ts - What to verify: the existing reset dialog/divider/idle flow, absence of the old context trigger after reset, and a fresh context trigger after a mock-agent command that emits
usage_update.
- File:
Implementation Waves And Parallel Candidates
Execution is sequential in the primary conversation.
- Task 01: Invalidate context-window state on successful reset — done
- Task 02: Cover reset freshness end to end — done
Validation commands
cd apps/backend && go test -run TestProcessOnEnterResetAgentContext ./internal/orchestratorcd apps && pnpm --filter @kandev/web test -- --run lib/ws/handlers/agent-session.test.ts components/task/chat/reset-context-button.test.tsxcd apps/web && pnpm e2e:run --host tests/session/session-recovery.spec.ts -- --grep "reset context hides stale usage"
Risks and boundaries
- Session-state payloads use both
metadatafor narrow context updates andsession_metadatafor full state transitions; invalidation must support both without clearing on unrelated partial metadata. - Reset failure occurs before metadata invalidation and must preserve the old reading.
- The existing reset control remains intentionally hidden while busy; changing prompt-admission or cancellation semantics is outside this fix.