- Switched advisor turns to the next configured model after provider quota or rate-limit failures.
- Emitted fallback applied and succeeded lifecycle events without reporting advisor unavailability after recovery.
- Added an end-to-end advisor quota fallback regression test.
Fixes#5740
Answered unconfigured workspace/configuration sections with the spec-required null value and covered the Roslyn post-initialization pull path.
Fixes#5745
The host guard's stdin restore only dropped listeners a module added; a
module that removed a snapshot listener (e.g. a factory calling
process.stdin.removeAllListeners("data") when a subagent re-runs preloaded
factories against a live parent TUI) permanently stripped ProcessTerminal's
input handler. Reconcile each guarded event back to the pre-load snapshot:
when membership changed, removeAllListeners then re-add the snapshot in
order, restoring both additions dropped and removals reinstated. Snapshot
via rawListeners so once-wrapped handlers round-trip intact.
Fixes#5618
Custom tool/extension/hook/plugin modules under ~/.claude/tools are
evaluated with live side effects during createAgentSession. A module that
attaches a stdin consumer at import time — an MCP StdioServerTransport
built at module top level, or a bare process.stdin.resume() — steals
Bun's single stdin reader, so the TUI receives exactly one data event and
goes permanently deaf after the first keypress. Under tmux the terminal's
automatic DA1 reply is that one event, so the first user keystroke is
already dead: the input-deafness reported in #5378/#5618.
Broadened the loader's withExitGuard (renamed withHostGuard) to also
snapshot and restore process.stdin around third-party module evaluation:
any data/readable/end/close/error listener the module adds is removed, and
the stream's paused and raw-mode state is restored to the pre-load
snapshot. The exit guard already fenced process.exit; stdin is the same
class of host-state hijack.
Fixes#5618
New-session persistence is lazy: after `/new`, the JSONL is not created
until assistant output exists. Exiting before any assistant message left
the per-terminal breadcrumb pointing at a not-yet-materialized file, which
`readTerminalBreadcrumbEntry` rejected (missing target), so `continueRecent`
fell back to `findMostRecentSession` and resurrected the pre-`/new` transcript.
`/new` now records a durable `fresh` breadcrumb boundary. The reader returns a
fresh breadcrumb even when its target is absent (with `exists:false`), and
`continueRecent` honors it by starting fresh instead of falling back. The crumb
is re-stamped non-fresh once the session materializes, so a genuinely
stale/deleted breadcrumb still falls back to the most-recent session. The
breadcrumb write is now synchronous so the fresh->materialized re-stamp cannot
reorder.
Fixes#5730
- Tracked delivered message identities alongside the numeric cursor.
- Re-primed advisor context when a live transcript prefix diverged.
- Covered accepted empty-stop pruning before the next real user turn.
Fixes#5731
Schema-invalid JSON objects can reach mounted approval functions before xdev dispatch validates their arguments. Fall back to the exec tier when an approval function throws, preserving fail-closed prompting and allowing dispatch to surface its normal schema error.
Added regression coverage for ast_edit payloads containing null paths.
Fixes#5727
The write approval gate discarded a mounted tool's function-valued
approval and never decoded the device JSON payload, defaulting the tier
to exec. Read/write xd:// operations then prompted in non-yolo modes
that permit them.
Now decode valid object payloads and resolve the mounted tool's normal
approval decision via resolveToolTier; malformed JSON, non-object
payloads, and unknown devices still fall back to exec and prompt.
Fixes#5727
Report bundles now concatenate every same-day omp.<date>.<pid>.log tail oldest-first, so a report from a later invocation still captures a crashed process's log after the shared-filename scheme was replaced with PID-qualified paths.
Fixes#5716
- Prevented compaction from reopening a settled terminal answer unless queued work or an active goal remains.
- Ran auto-learn capture in an abortable detached agent with constrained tools and isolated provider state.
- Replaced primary-turn capture coverage with private-capture regression tests.
Fixes#5715
Tried existing unique workspace suffix matches before recovering a missing cwd path from the active approved plan. Added regression coverage for the precedence rule.
Made fatal reporting bypass revoked stderr streams and armed a referenced forced-exit watchdog around bounded cleanup.
Separated rotating log and audit namespaces by PID and disabled compression pipelines so concurrent TUI processes cannot race shared rotation state.
Fixes#5716
Recovered the active local plan when a model rewrites its local URL as a missing same-basename cwd-root path. Real working-tree files retain precedence.
Fixes#5704
Decoupled fullscreen alternate-screen rendering from terminal mouse capture.
Disabled pointer tracking for Plan Review so terminals retain native selection.
Fixes#5711
Unknown reserved __omp_worker_* selectors hit the worker-host re-entry
seam, runWorkerEntrypoint returned false, and the ignored result let the
process exit 0 with empty stdout/stderr. A stale or mistyped selector
looked healthy to parent processes and install smoke paths.
Check runWorkerEntrypoint's return at the dispatch seam: an unrecognized
selector now writes "Error: unknown worker selector: <arg>" to stderr and
sets a nonzero exit code without starting a worker. Known selectors and
normal CLI arguments are unchanged.
Fixes#5712
fs.realpath throws EISDIR on Windows drive roots (e.g. R:\), but
canonicalProjectDir in launch/presence.ts and launch/client.ts only
recovered ENOENT, aborting startup. Both now fall back to path.resolve()
on EISDIR, matching the existing ENOENT handling.
Fixes#5708
Building the cmd.exe /c command line and spawning with windowsVerbatimArguments so cmd.exe expansion cannot eat or inject on %VAR%, quote, and metacharacter args (BatBadBut / CVE-2024-24576).
Fixes#5696
Removed the 24-column cap from account cells so wide terminals can show full disambiguating labels.
Kept usage bars independently capped and added regression coverage for same-email organization accounts.
Fixes#5701
The /usage show "in use by this session:" marker took only the bare
email from OAuthAccountIdentity, so two same-email Anthropic credentials
in different orgs were indistinguishable. Route the label through a
shared formatActiveAccountLabel that suffixes the active org, matching
the account list and login-success surfaces.
Fixes#5691
Moved #hidePlanReview from after the model restore to immediately before the synthetic execution dispatch, past the awaited sessionManager.setSessionName. Hiding earlier restored editor focus while the async title write was in flight, so operator keystrokes could submit a normal turn ahead of the approved execution turn and reorder it.
Fixes#5688
MCPManager evicted a server's tools by matching the raw mcp__<name>_
prefix against sanitized tool names. One server's sanitized name can
prefix another's (atlassian vs imported atlassian:atlassian), so every
reconnect of the shorter-named server dropped the sibling's tools and
re-announced them moments later, spamming paired xd:// unmount/mount
notices on each transport flap. Names containing sanitized characters
never prefix-matched at all, leaving stale tools registered after
disconnect. Replacement and removal now match mcpServerName.
Cursor synthesizes an executed native delete as a tool call named delete. When write or edit enabled native deletion, the advisor quarantine allowlist still omitted that synthetic name and rolled back the completed turn.
Add delete to the allowlist from the same mutation-capability boolean that enables native deletion, with regression coverage for the quarantine path.
Fixes#5680
The stale-buffer flicker fix (68f84d7c20, #5319) moved #hidePlanReview out of the picker's synchronous finish() into closePlanReview(), reached only after #approvePlan returns. #approvePlan awaits session.prompt of the synthetic plan-approved turn, which blocks for the whole run, so the fullscreen plan-review overlay stayed mounted while work proceeded underneath.
Hide the overlay inside #approvePlan after the async transcript rebuild (exitPlanMode/compaction, tool and model restore) completes but before the blocking dispatch. #hidePlanReview is idempotent, so the caller's trailing closePlanReview() stays a safe no-op, and #5319's stale-buffer guard is preserved.
Fixes#5688
CursorExecHandlers.executeDelete removes files directly via fs.rmSync,
bypassing the tool map that every other exec handler consults. A background
advisor with the default read-only set (advise/read/grep/glob) could delete
workspace files from a Cursor deleteArgs frame despite holding no mutating
tool.
Add an allowNativeDelete option (default allowed, preserving the primary
agent's behavior) and set it for the advisor only when it was granted a
file-mutating tool (write/edit).
Fixes#5680
The built-in advisor runs in its own Agent that was constructed without
cursorExecHandlers. On the Cursor provider every tool executes server-side
and is dispatched back through the client's exec handlers, so each advisor
tool call — including the MCP advise tool — came back toolNotFound and no
advice was ever routed. Same advisor worked on every other provider.
Build a Cursor exec bridge over each advisor's granted tool set and pass it
(plus a live cwd resolver) when constructing the advisor Agent, mirroring the
primary agent's bridge. The advisor-layer analog of #5650/#5651.
Fixes#5680
- Suppressed user-visible xd:// mount notices when startup.quiet is enabled.
- Preserved hidden model-facing mount delta steering.
- Added regression coverage for both behaviors.
Fixes#5670
- Used the active provider session id for title credential selection.
- Covered explicit provider-session credential stickiness alongside disposal cancellation.
- Delayed reader cancellation so pipeline consumers can flush after producers are terminated.
- Kept the JavaScript watchdog behind bounded native timeout cleanup.
- Added native and executor regressions for timeout-time output draining.
Fixes#5316
- Routed automatic first-input and replan title requests through AgentSession lifecycle cancellation.
- Propagated disposal aborts to online provider and local tiny-model title generation.
- Added a regression test proving an in-flight title request settles when disposal begins.
Fixes#5666
Extension-scheduled setInterval/setTimeout/detached callbacks ran outside
the handler-dispatch try/catch, so a throw surfaced as a process-level
uncaughtException and the global postmortem handler tore down the whole
session instead of isolating the misbehaving extension.
- Added ManagedTimers backing sanctioned ctx.setInterval/setTimeout/clearTimer:
callbacks run with handler-dispatch isolation (throw/rejection logged and
routed through onError), handles are unref'd, and all are cleared on
session_shutdown.
- Wired the helpers into ExtensionRunner.createContext and the runner-less
command-context fallback; onSession now inherits the runner context.
- Documented in-process no-isolation behavior and the managed timers in
docs/extensions.md and docs/skills/authoring-extensions.md.
Fixes#5664
In plan mode the active session model is the plan-role model, but
reassigning that role through the model hub only wrote settings and
never moved the live session onto the new model — planning continued on
the model plan mode was entered with until the next entry.
Subscribe InteractiveMode to onModelRolesChanged and, while plan mode is
active, re-resolve the plan role and switch onto it (deferring to the
next turn boundary when a turn is streaming). Extract the transition
decision into a pure resolvePlanModelTransition() helper with tests.
Fixes#5657