Recorded todo reminder developer messages in the session log so JSONL transcripts match model-visible context when reminders are enabled.\n\nFixes #2824
- Sanitized artifact filenames by normalizing tool names before composing spill paths.
- Applied `wrapToolWithMetaNotice` to custom tool adapters and RPC-host tools in agent-session setup.
- Wrapped SDK-registered extension/custom tools with the same meta-notice adapter during session creation.
- Queued advisor concern cards now get reclaimed as visible advice during settle when auto-resume suppression is active and the session is idle.
- Preserve logic was narrowed to keep advisor cards hidden only during abort teardown, allowing steers during resumed streaming turns.
- A regression test was added to verify stranded advisor steers are persisted as visible advice without triggering an advisor-only resume turn.
- Added resolveAdvisorDeliveryChannel in advisor tooling to map each note to aside, steer, or preserve using severity, auto-resume suppression, core-streaming, and abort state.
- Updated AgentSession advice enqueuing to route concern/blocker notes through that resolver, preserving them only when the interrupted turn is idle or tearing down and steering them during active resumed turns.
- Added regression tests for resolveAdvisorDeliveryChannel covering nit versus interrupting severities across streaming, aborting, and suppression combinations.
- Rewrote `formatSessionDumpText` in `session-dump-format.ts` to emit the pre-16.x full dump: system-prompt prelude, model/thinking config, tool inventory with parameters, and the transcript as markdown role headings (`## User`, `## Assistant`, `### Tool Call`/`### Tool Result`), reusing `renderDelimitedThinking` for `<thinking>` blocks.
- Dropped the compact default and the `[raw]` flag from `/dump`: removed the `isRaw` parameter from `handleDumpCommand` in `command-controller.ts`, `interactive-mode.ts`, and `types.ts`, and removed the `inlineHint: "[raw]"`/`compact` plumbing in `builtin-registry.ts`.
- Updated the `formatSessionAsText` doc comment in `agent-session.ts` to describe the verbose dump shape.
- Removed the obsolete `formatSessionDumpText raw thinking` suite from `advisor.test.ts` and refreshed `session-dump-format.test.ts` to assert the verbose dump output.
- Recorded the revert in the coding-agent changelog and trimmed `/dump` from the compact transcript tool-intent-prefix entry.
- Generalized `isUserQueuedMessage` to a user-attribution predicate (`role === "user"` or custom `attribution === "user"` and not display-suppressed) so visible agent-authored steers (advisor cards, IRC/extension asides) and hidden goal/plan/budget steers are all excluded from editor restore, not just advisor cards.
- Gave `AgentSession.clearQueue` a `{ forInterrupt }` option: plain Alt+Up dequeue restores user messages and preserves every other queued message for the continuing stream, while Esc+abort keeps only advisor cards (for `abort()`'s `#extractQueuedAdvisorCards` preservation) and drops other internal steers so the post-abort `#drainStrandedQueuedMessages` can't auto-resume the interrupted run.
- Threaded `forInterrupt: options?.abort` from `InputController.restoreQueuedMessagesToEditor` and kept `queuedMessageCount` on actual displayable-queue semantics so `hasPendingMessages()`/RPC and the empty-submit abort gate stay accurate.
- Updated skill-queue tests to cover both policies (hidden and visible agent-authored steers preserved on dequeue, dropped on interrupt) and refreshed the changelog entry.
- Added `isUserQueuedMessage()` to `agent-session.ts`, treating only plain user turns and visible `attribution: "user"` custom messages (e.g. `/skill`) as restorable, so advisor concern/blocker notes, hidden goal/plan/budget steers, and IRC/extension asides no longer leak into the editor on Esc/Alt+Up.
- Reworked `clearQueue()` to return only user-authored messages while re-queuing advisor cards via `replaceQueues()` (so the user-interrupt abort path still re-records them as advice) and dropping other agent-authored steers to prevent a silent auto-resume on leftover internal context.
- Filtered `getQueuedMessages()` chips and rewrote `popLastQueuedMessage()` to skip agent-authored cards and pull the last user-authored entry, while `queuedMessageCount` still counts all displayable queued work.
- Extended `input-controller-skill-queue.test.ts` with a `queueAdvisorSteer` helper and cases asserting advisor/IRC cards count as pending work but stay out of chips, restore, and `popLastQueuedMessage`, and survive `clearQueue()`.
- Updated #isRetryableReasonlessAbort to reject reasonless aborts when the streaming-edit guard flag is set.
- This prevented routing those aborts through retry logic and avoided prompt hangs or unintended guard bypasses during edit-stream recovery.
Install a subagent's ordered model candidates as child-session retry fallback chains so a retryable provider failure advances to the next candidate instead of killing the worker (issue #2750).
Auto-retry empty/reasonless provider aborts without model fallback (issue #2685). Includes review fix b7a3d01439: skip the retry while the session is disposing to avoid a shutdown hang.
A dispose-driven bare abort() yields the same empty/reason-less aborted turn as a transient provider abort, but with #isDisposed set and #abortInProgress unset. #isRetryableReasonlessAbort matched it and routed it through #handleRetryableError, which created #retryPromise and scheduled a continuation the disposed guard then skipped without resolving the promise — hanging the in-flight prompt() in #waitForPostPromptRecovery during shutdown.
Guard the predicate on !#isDisposed so lifecycle aborts settle the turn, and add a regression test. Addresses review feedback on #2689.
Empty provider-side aborted turns now enter the existing auto-retry path without switching retry model fallback, while aborted turns with partial content still settle normally.\n\nFixes #2685
The first-message eager-task / eager-todo preludes are the oldest messages in a
session, so auto-compaction summarizes them away and the agent silently loses the
delegate-via-tasks / phased-todo guidance mid-work. Re-assert those reminders on
the auto-continuation turn that follows a compaction.
- Widen #createEagerTaskPrelude / #createEagerTodoPrelude to accept
`string | undefined`; `undefined` (post-compaction) skips only the
first-message and prompt-suffix gates, keeping the mode / agent-kind /
plan-mode / surviving-todo / active-tool gates intact.
- Reminder-only post-compaction: the todo nudge never attaches a forced `todo`
tool_choice on the resumed turn (forcing a tool after a mid-turn compaction
would override the agent's in-flight action).
- Add #buildPostCompactionEagerNudges() and prepend its output on the single
#scheduleAutoContinuePrompt continuation hook. All three call sites are
willRetry-safe, so overflow/incomplete retry recoveries never carry the nudge.
Op: extend
Matched retry fallback roles against the plain model selector as well as the routed in-flight selector, preserving configured chains for compat-routed OpenRouter and Vercel models.
Added regression coverage for a compat-routed OpenRouter primary using a plain role selector.
Stopped retry fallback selector parsing from treating every @ suffix as upstream routing, preserving exact model ids like google-vertex Claude @default variants.
Resolved fallback candidates from raw selectors during preflight so routed selectors still work without corrupting exact at-suffixed ids.
Resolved retry fallback primaries from the raw selector during cooldown restore so OpenRouter and Vercel upstream pins survive fallback recovery.
Added regression coverage for routed OpenRouter primaries reverting after cooldown expiry.
Kept OpenRouter and Vercel upstream routing suffixes in subagent retry fallback selectors so same-base routed candidates stay distinct.
Resolved retry fallback candidates from the raw selector before model switching so routed fallback models keep their requested upstream route.
- SetAdvisorEnabled now used settings.override for advisor.enabled when enabling or disabling, keeping advisor toggles session-local.
- /advisor on|off handlers now called refreshStatusLine after each toggle, and the status line updates immediately in the UI.
- A regression test was added to assert setAdvisorEnabled invokes override with both values and does not call set.
- Passed USER_INTERRUPT_LABEL through abort paths in collab, ACP, RPC, runtime, and SDK flows.
- Added userInitiated to synthetic continue inputs and session prompt calls.
- Suppressed advisor auto-resume during user aborts and preserved queued concerns.
- Cleared suppression on user prompts and reclaimed parked advisor cards on abort settle.
Checked structured classifier refusals before the interrupted-output retry guard so provider refusals with explanatory content still use the configured fallback path.
Fixes#2683
- Added awaited `onTurnEnd` and `setOnTurnEnd` wiring for turn-end callbacks.
- Added `advisor.syncBacklog` settings (off/1/3/5) and documented 30-second catch-up caps.
- Fixed advisor runtime backlog handling with failure counters, waiters, and retry requeue.
- Updated agent sessions to enqueue advisor updates on turn end and removed direct `turn_end` branch logic.
Prevented auto-retry from regenerating write calls after a provider stream timeout has already exposed assistant content or tool-call arguments.
Fixes#2683
- Added discovery of local, user, and ancestor `WATCHDOG.md` files via `discoverWatchdogFiles`.
- Appended discovered watchdog prompts to advisor system prompts during session setup.
- Added protocol startup defaults that force `advisor.enabled` and `advisor.subagents` false.
- Handled `maintainContext` failures and drained pending updates before token estimation.
- Added advisor context maintenance hook and token estimation before prompting for auto-upkeep.
- Added re-prime replay handling to reset advisor context and recover deferred prompts.
- Implemented session-level context compaction with model promotion and snapcompact-first fallback summarization.
- Surfaced advisor settings in the model tab and updated advisor system guidance text.
- Created AdvisorRuntime and AdviseTool to drive a read-only advisor agent that delivers severity-tagged advice (nit, concern, blocker) with interruption policy and transcript delta rendering.
- Added /advisor slash command with on/off/status/dump subcommands to control advisor lifecycle and inspect advisor metrics (model, messages, tokens, cost).
- Added advisor.enabled and advisor.subagents settings to enable passive advisor review on main agent and spawned task/eval subagents.
- Implemented advisor message rendering with severity-color badges (blocker=error, concern=warning, nit=muted) in chat log and status line indicator (++ badge).
- Extended yield-queue and session-history-format to support advisor batching and optional thinking block inclusion.
Keep provider-anchored pre-prompt checks based on the prior provider prompt usage plus only positive current system/tool token growth, avoiding a second full charge for unchanged non-message context.
Fixes#2628
- #handleAgentEvent now delegates non-`agent_end` events to a new `#processAgentEvent` routine.
- For `agent_end`, it tracked a resolver promise via `#trackPostPromptTask` before awaiting event handling and resolved it in `finally`.
- This kept `#waitForPostPromptRecovery()` from returning before deferred compaction or handoff work was registered.
Track the non-message token estimate used for provider-anchored assistant usage, then add only positive current system/tool growth during pre-prompt threshold checks. Restore released collab changelog entries to the immutable 15.13.1 section.
Fixes#2628
Include the current system prompt and active tool schemas when provider-anchored pre-prompt checks estimate threshold pressure, and cover the case with a regression test.
Fixes#2628
Use provider-anchored context usage for pre-prompt context-full threshold checks when available, then add only pending prompt tokens. This keeps OpenAI Responses encrypted reasoning payloads from overcounting local prompt pressure while the visible context usage remains below threshold.
Fixes#2628
- Added `features.unexpectedStopDetection` and `unexpectedStopModel` settings for opt-in behavior.
- Added assistant-stop handling to classify stop reasons and resume generation with retry prompts.
- Added unexpected-stop classifier logic with candidate checks, model fallback, and YES/NO parsing.
- Added retry tracking that caps auto-continues at three attempts and logs a warning when exceeded.
The pre-prompt context check ran compaction directly, so snapcompact (or
any strategy) fired before auto-promote ever got a chance — defeating
Auto-Promote Context. It now tries promotion to a larger-context model
first (mirroring the post-turn threshold path) and only compacts when no
target is available.
Auto and manual compaction now project a snapcompact result's
post-compaction size (kept history + frames at the image budget + summary
+ non-message overhead); when it still exceeds the model's usable window,
they downgrade to a context-full LLM summary instead of leaving the
session overflowing.
`#checkTodoCompletion` used to append a `<system-reminder>` and then call
`#scheduleAgentContinue`, so a text-only acknowledgement ("paused at your
instruction") triggered another `agent_end` that re-ran the same check and
fired the next reminder — counter ticked 1/3 → 2/3 → 3/3 inside a single user
pause without any user input. The user perceived three back-to-back reminders
appear from nowhere; the agent felt implicit pressure to invent busy-work or
take destructive ops to silence the loop.
Added `#todoReminderAwaitingProgress`: a reminder sets it, any `toolResult`
(real tool-level progress) or a new user prompt clears it, and
`#checkTodoCompletion` stays silent while it is set. Reset alongside
`#todoReminderCount` on user prompts, session reset, handoff, and the no-op
short-circuits in `#checkTodoCompletion` so the field never gets stuck.
Escalation through `todo.reminders.max` still works when the agent makes
tool-level progress between stops — that is the case the cap was designed for.
Regression coverage in `agent-session-todo-reminder-loop.test.ts` drives a
mocked `agent.continue` to mirror the bug-reported model behaviour and pins
the contract: exactly one reminder per user pause when the agent only
acknowledges; re-escalation when the agent actually calls a tool between stops.
Fixes#2590
- agent-loop: raise repetition-detection floor to 180 chars and clear thinking
replay anchors when collapsing a detected loop.
- providers/google: ignore empty text parts, retain terminal thoughtSignatures,
and stop function-call signatures clobbering the prior block.
- autolearn: capture goal-mode at the turn boundary; harden managed-skill writes
against hard-links/symlinks (O_NOFOLLOW + nlink); refuse minting managed skills
whose name an authored skill already claims.
- eager tasks: thread agentKind through the session so a custom top-level agentId
still gets always-mode delegation; split Eager Tasks prompt into hard vs soft.
- title-generator: race the online title model against a local tiny-model fallback.
- eager-todo: keep the soft reminder aligned with the todo init schema.
- mcp/stdio: keep close() detaching the read loop instead of awaiting it.
- stream loop: fix collapsing and tool-call thought-signature handling.
- Added a generation-aware early-exit check in `#waitForPostPromptRecovery` to return when the prompt turn is superseded.
- Passed the current prompt generation into the post-prompt recovery wait after prompting.
- Ensured aborted prompts no longer block while later queued retry/follow-up turns drain.
Two controller bugs from review:
- The post-stop nudge still queued a passive `nextTurn` message during goal
mode (goal mode only disabled `autoContinue`). That message rides the goal
continuation and can divert the goal loop into capture. Return early when
goal mode is active.
- `#suppressNext` was latched before the fire-and-forget `sendCustomMessage`.
It must arm synchronously (the synthetic turn's `agent_end` fires inside
`sendCustomMessage` before it resolves), but a rejected or *deferred* dispatch
(ACP clients downgrade `triggerTurn` to a queue) then produces no `agent_end`,
so the latch swallowed the next real stop. `sendCustomMessage` now returns
whether it actually started a turn; the controller disarms the latch when no
turn ran (rejection or deferral).
`task/executor.ts` widens its pending-message array to `Promise<unknown>[]` to
absorb the new return type (the resolved values are discarded).
Addresses review threads on PR #2542 (threads 5, 9, 12).
- Added session-domain modules and exports for session-entries, context, listing, loader, and migrations.
- Changed persistence to async append writes plus writeTextAtomic, removing sync line APIs.
- Added compaction-aware session context rebuild with dangling tool-call cleanup.
- Added resumable session resolution with status inference, id/stem/suffix matching, and backup recovery.
- Validated queued toolChoice against active tools in agent and coding-agent sessions.
- Rejected queued forced choices with reason "unavailable" when selected tools were inactive.
- Dropped provider toolChoice payloads when requested function tools were not offered.
- Probed Tokio worker-thread support and fell back to current-thread runtime creation.
Adds a fastModeScope setting (both|openai|claude, default both). setFastMode(true)
derives the service tier from it (both->priority, openai->openai-only,
claude->claude-only) instead of hardcoding unscoped priority; the off path and
the already-on no-op are unchanged. /fast status now reports the active scope.
Default both preserves existing behavior.
- Queued steering now drains after session settlement, so aborted auto-continued turns no longer leave queued messages stranded.
- Resumable-state detection now treats tool-result messages as resumable so continue can process queued steering after an interrupted tool execution.
- Regression tests were added for queued steer draining after abort and after an interrupted tool result.
- Replaced queued-message interrupt flow with session abort calls on empty submit and escape.
- Removed interrupting state and notifyInterrupting teardown paths from abort handling.
- Updated AgentSession queue operations to use shared steering and follow-up queue views.
- Propagated isAborting through session state and collab payloads to suppress late updates.