- Updated prewalk gating in `AgentSession` to key the todo gate on active tools instead of registry presence, so deactivated todo tools no longer block prewalk handoff.
- Changed subprocess tool filtering so `todo` is stripped for normal subagents but retained when prewalk is armed, and propagated the prewalk state through tool-session setup.
- Added regression tests for restricted active-tool slates and prewalk/non-prewalk subagent tool propagation to verify todo is handled correctly in each case.
wantsSnapcompact is true for both the default strategy and an explicit
/compact snapcompact mode override. The prior fix downgraded both to LLM
compaction, which silently shipped the transcript to a provider for users
who deliberately requested the local-only no-LLM archive path. Only the
default-configured strategy now falls back; explicit snapcompact keeps
failing locally. Added a regression test for the explicit path.
Fixes#5064
A stalled or dropped provider stream that surfaces as stopReason:"error"
carrying the bare "Request was aborted" sentinel fell through both retry
gates: #isRetryableReasonlessAbort required stopReason:"aborted", and
#isRetryableError's classifier returns no retriable kinds for the generic
sentinel. The turn died immediately despite retry.enabled.
- Relaxed #isRetryableReasonlessAbort to accept an empty generic-abort
sentinel turn under stopReason "aborted" or "error", tagging it Abort so
#handleRetryableError retries it without model fallback.
- Kept the deliberate-abort guards intact: user interrupts and silent aborts
carry their own markers (not the generic sentinel), and #abortInProgress /
#isDisposed / #streamingEditAbortTriggered still settle without retry.
- Rewrote the stale fallback test that froze the buggy no-retry behavior to
assert retry-and-recover for the error-stop sentinel.
Fixes#5375
navigateTree() treated every custom_message entry as a re-editable user
turn, setting the leaf to the injection's parent and dumping the expanded
skill body into the editor. A /skill:<name> invocation is persisted as a
skill-prompt custom_message, so selecting it in /tree dropped the skill off
the active branch. Skip the parent-leaf/editor-prefill path for
skill-prompt entries so the leaf lands on the injection node itself.
Fixes#5374
- Added a Codex rate-limit parser for `x-codex-*` headers and registered it with the Codex usage provider.
- Updated auth-storage to require parsed usage headers before ingesting usage data, treated exhaustion as non-throttled, and renamed ranked candidate drain fields.
- Reworked key ranking math to use `headroom / remainingHours` with a 1-minute minimum, then applied measured-usage precedence with hot-window demotion behavior.
- Updated session handling and tests to support provider-aware header ingestion with deterministic, exhaustion-aware account selection.
Manual /compact with the snapcompact strategy hard-threw when the active
model lacked image input, unlike the auto-compaction path which downgrades
to LLM-backed compaction. Clear snapcompactReady instead of throwing so the
flow falls through to #compactWithFallbackModel (active text-only model
tried first for text->text summarization).
Fixes#5064
- Added `tui.scrollbackRebuild` configuration with interactive startup/controller wiring to apply `setScrollbackRebuild`.
- Exposed prewalk session state in `SegmentContext` and rendered a dedicated prewalk segment/icon in the status line.
- Added divergence-aware TUI full-paint logic that enables scrollback erase-and-replay rebuilds for non-multiplexer divergence cases.
- Updated rendering and streaming tests to verify rebuild behavior (`3J`) and eliminate stale marker expectations under drift scenarios.
- Replaced legacy `pi/` role alias prefix with canonical `@` syntax across model resolution, documentation, and tests.
- Added support for bare `*` default alias and multiple alias prefix detection with custom role resolution in `resolveConfiguredRolePattern()`.
- Enhanced thinking suffix parsing to accept unambiguous abbreviations (minimum 2 characters) for effort and level selectors.
- Extended `resolveCliModel()` and `filterAvailableModelsByEnabledPatterns()` to accept settings parameter for role alias resolution from `--model` flag.
- Removed the Google Interactions transport and deleted interaction-specific request options from the shared AI stream typing/API surface.
- Simplified Google provider routing to eliminate interactions auto-selection logic and keep `streamGoogle` on the `:streamGenerateContent` path.
- Updated Vertex request handling to use resolved stream hosts without `/interactions`/`Api-Revision` and removed related interaction constants.
- Deleted obsolete Interactions tests and updated remaining Google stream tests to no longer reference `useInteractionsApi`/`storeInteraction`/`previousInteractionId`.
- Removed the `downshift.boomerang` feature, including CLI flags, configuration schema settings, and internal session state logic.
- Deleted the associated prompt definition file and all unit tests related to the boomerang validation flow.
- Cleaned up frontend forms and server request handling in the harbor-manager package to reflect the feature removal.
- Updated the downshift planning prompt instructions to maintain continuity in task creation.
- Modify downshift logic to ignore `todo` tool calls as triggers, requiring them instead to open a "gate" that permits switching only on subsequent `edit`/`write` actions.
- Ensure the starting model consistently handles implementation until the todo list is established, preventing premature hand-off to the fast/cheap model.
- Update system prompts to emphasize strict validation and multi-test execution requirements for the boomerang model upon returning to the primary context.
- Introduced `--downshift-boomerang` CLI flag and `downshift.boomerang` configuration setting.
- Integrated boomerang validation hand-back logic and context cutting within the agent session.
- Added system prompt templates and runtime checks to facilitate message handling for boomerang transitions.
- Included unit tests to verify context management and validation pass requirements during the boomerang process.
- Included the todo tool in downshift action triggers, gated on the plan nudge being in context — a post-nudge todo init is the planning-complete signal, while a turn-one todo remains bookkeeping.
- Updated flag help, settings schema, SDK docs, slash-command text, and plan-nudge instructions.
- Added a regression test covering the nudge-gated todo trigger.
- Replaced legacy reasoning-slide functionality with new downshift and plan-yolo capabilities.
- Updated CLI arguments, slash commands, and configuration schemas to support the new model-switching and execution behaviors.
- Refactored agent session logic to handle downshift arming, plan-yolo headless execution, and context scrubbing.
- Renamed and added system prompts to align with the updated downshift and plan-yolo workflows.
- Clear inherited todo list state and persist empty edit at fork creation to prevent parent task reminders from affecting the tangential session.
- Re-inject the fork notice after each auto-compaction event to ensure the boundary between the parent and child session survives history summarization.
- Align the provider cache key with the parent's actual pinned key to correctly mirror cached session context.
- Update `AgentSession` to perform a full entry rewrite during tool result pruning to ensure session files match pruned state for reliable resuming and branching.
- Added `warning` field to `CompactionEntry` and `CompactionSummaryMessage` to persist dead-end status in session history.
- Introduced a multi-tier rescue mechanism in `AgentSession` that automatically performs `elide` and `dropImages` passes when maintenance fails to recover sufficient headroom.
- Integrated visual indicators for dead-ends into the `CompactionSummaryMessageComponent`, surfacing warnings directly on the compaction divider and detail block.
- Updated `AgentSession` logic to re-evaluate progress after each rescue tier and emit recovery notices, ensuring transparent reporting of automated history rewrites.
- Update in-flight context snapshots after historical messages are modified by compaction or elision.
- Prevent stale run-start token counts from triggering false-positive dead-end "no progress" warnings during auto-continuation.
- Add regression test to verify that prompt headroom measurements correctly account for post-compaction context sizes.
- Extended `AgentSession` to consult `retry.fallbackChains` on non-retryable (hard) model errors.
- Implemented `#isHardErrorFallbackEligible` to validate eligibility for model switching before surfacing terminal errors.
- Updated `#handleRetryableError` to orchestrate immediate model switching for hard errors, bypassing backoff-retries for the failing model.
- Ensured hard errors propagate to the user if no fallback candidates are available or if no credential can be resolved for the fallback model.
Applied explicit thinking suffixes from matching configured model roles when the temporary model picker switches the session model.
Added regression coverage for the Alt+P temporary picker resolution path.
Fixes#5290
- Permit model fallback even if the retry budget is exhausted when the current provider is locked by credential rotation or usage limits.
- Reset the retry budget when successfully switching to a fallback model to ensure the new model has a full allowance of retries.
- Added a regression test to verify that credential rotation failure triggers model fallback.
Close pending tool turns recorded during normal shutdown and apply interrupted-tail recovery when switching or reloading sessions.
Signed-off-by: Christian Stewart <christian@aperture.us>
- Added `model_perf` table to store persistent, recency-weighted TPS and TTFT statistics per model.
- Introduced `AgentStorage.recordModelPerf` to asynchronously capture and aggregate turn timing metrics.
- Implemented a background backfill mechanism to migrate historical request data from `stats.db` into new performance aggregates.
- Updated `AgentSession` to record performance metrics upon turn completion.
- Bumped `SCHEMA_VERSION` to 6 and cleared existing performance data to account for improved duration-based TPS calculation.
- Implemented model-specific keys and provider wildcards for `retry.fallbackChains` with updated resolution logic.
- Added interactive fallback chain management in the model roles UI, including support for reordering and editing.
- Improved fallback chain specificity rules and added comprehensive validation with startup warnings.
- Fixed mouse interaction alignment and hover state coordinate mapping in the roles view.
- Updated task synchronization to include all todo phases regardless of completion status.
- Removed logic that filtered out completed or abandoned tasks during session synchronization.
Removed accepted empty Auto-Learn capture stops from live and persisted context, including the hidden capture prompt when it directly parents the no-op stop.
Extended the regression to prove the next real prompt does not replay the stale Auto-Learn nudge.
Fixes#5211
- Forwarded the session provider state map to ephemeral side-channel turns so Codex can allocate websocket transport state for the side request session id.
- Extended the /btw side-channel regression to assert providerSessionState reaches the stream options with the websocket preference.
Fixes#5213
- Preserved the session websocket preference for ephemeral /btw side-channel turns so Codex websocket-only models do not fall back to SSE.
- Prioritized active /btw and /omfg panels in Esc handling before loop, maintenance, and main-turn interrupts.
- Added regression coverage for side-channel websocket options and /btw Escape priority.
Fixes#5213
Cleared the terminal empty-stop acceptance flag for every agent-initiated prompt so non-opt-in custom turns cannot inherit Auto-Learn capture behavior.
Added a regression covering a non-opt-in custom turn after a non-empty Auto-Learn capture response.
Fixes#5211
Marked Auto-Learn capture turns as accepting terminal empty assistant stops so the empty-stop guard does not retry the expected no-reply completion.
Added a focused AgentSession regression covering the auto-continue capture turn.
Fixes#5211
Blockers from final review:
- runtime.ts:457 TS2741: #collectAndMaintainBatch now returns wip in its
result type; #drain destructures it and passes it to the retry-requeue
unshift — a WIP batch that fails retry no longer silently loses its
[in progress] heading.
- agent-session.ts import order: annotateForStaleness moved before
formatAdvisorBatchContent (biome enforces case-insensitive alpha order).
Cap edge case (advisor nit + review CONCERN): final round of the
coalescing for-loop now breaks BEFORE the late-item splice so any
deltas that arrived during round MAX_COALESCE_ROUNDS-1's
maintainContext call stay in #pending for the next drain iteration
instead of being merged into an unbudgeted batch. Doc comment updated
to match ('left for the next drain iteration' is now accurate).
Cap test: bounded version that only pushes new turns for the first 3
maintainContext calls so the drain while-loop terminates cleanly after
a second iteration. The previous unbounded version created an infinite
drain loop (each maintainContext call unconditionally pushed another
turn) and timed out.
Blocker: wip field added to PendingDelta and threaded into the reprime
path. #collectAndMaintainBatch now captures the most-recent WIP state
from each delta batch and forwards it to #renderDelta in both the
normal and reprime branches, so a willContinue:true turn never loses
its [in progress] heading through a reprime.
Safety cap: MAX_COALESCE_ROUNDS=3 constant defined and used in the
coalescing for-loop, preventing indefinite dispatch stall under
pathological fast-primary + slow-maintainContext conditions.
Testability: annotateForStaleness extracted as an exported pure function
in advise-tool.ts and used in AgentSession#routeAdvice. Three unit
tests added in advisor.test.ts covering the no-staleness, staleness,
and note-preservation contracts. This addresses the ReviewSession
regression-test concern without requiring a full AgentSession harness.
Reprime turn-tally coverage: new test 'backlog stays accurate when a
delta arrives during the reprime-triggering maintainContext' asserts
runtime.backlog === 0 after all three turns, catching a deleted
turns += reduce(...) line.
Fragile double-await tests converted: sends-batch-when-maintenance-fails
and expands-plan-mode-context now use Promise.withResolvers signals
instead of counted await Promise.resolve() hops.
Docs: onTurnEnd JSDoc added; hasFreshBacklog comment broadened to cover
all drain-busy phases (not just agent.prompt).
Three related changes that address the pattern of the advisor flagging things
the primary already fixed:
Fix 1 — coalesce late-arriving deltas before agent.prompt (runtime.ts)
Refactored #drain into a reusable #collectAndMaintainBatch helper that loops
until the pending queue is stable (no new deltas arrive during a maintenance
check) before calling agent.prompt. Previously, any turn queued during the
maintainContext await was deferred a full extra model-call cycle; now it is
merged into the current batch after re-checking the token budget for the
expanded payload. Every await in the loop has an epoch guard so a
reset/dispose mid-await cannot leak a stale batch. finalTurns always counts
all merged turns so #backlog decrements correctly.
Fix 2 — hasFreshBacklog + delivery-time staleness annotation (runtime.ts, agent-session.ts)
Added AdvisorRuntime.hasFreshBacklog getter (true when #pending.length > 0
while agent.prompt is running — i.e., newer primary turns arrived after the
reviewed window). #routeAdvice checks it at delivery time and appends a
lightweight caveat to the note so the primary agent knows to verify before
acting. Uses #pending.length not #backlog, which is always > 0 mid-call.
Fix 3 — willContinue WIP marker in rendered delta + system prompt (runtime.ts, agent-session.ts, system.md)
onTurnEnd now accepts { willContinue } and passes it through to #renderDelta,
which tags the heading '[in progress — more steps follow]' for intermediate
turns. The agent-session.ts call site passes context.willContinue. The advisor
system prompt instructs the model to withhold critique on WIP updates.
Also fixed pre-existing inline casts in #renderDelta and #dedupContextMessage
that suppressed the type checker instead of using the narrowing already provided
by the role discriminant.
All 75 advisor tests pass; pre-existing type errors in cursor.ts are unrelated.
- Enabled persistence of dangling tool calls during transcript rebuilds by adding `keepDanglingToolCalls` configuration.
- Integrated `seal()` logic for pending tool blocks to properly finalize history during idle session states.
- Enhanced UI helpers and session context to preserve assistant turns during streaming or mid-turn rebuilds.
- Added comprehensive unit and integration tests to verify correct tool call tracking and transcript integrity.