- Changed `AgentOutputManager` to use requested names verbatim, adding `-2`/`-3` suffixes only on repeats (e.g. `Anna`, `Anna-2`).
- Renamed main agent id from `0-Main` to `Main`; nested ids now use dot notation without numeric prefix (e.g. `Parent.Child`).
- Updated task widget to render dotted hierarchy as `Parent>Child` breadcrumb without leading index.
- Resume scan now tracks seen names instead of a counter to avoid clobbering prior outputs.
- Removed the `concurrency` argument from `parallel()` and `pipeline()` in both JS and Python runtimes.
- Added `__concurrency__` bridge to resolve the pool ceiling live from `task.maxConcurrency` (default 32; 0 = unbounded).
- Eval fan-outs now run as wide as a `task` tool batch instead of being capped at 16.
- Encouraged staging helpers, datasets, and clients once, then fanning out subagents that call them directly.
- Clarified that re-importing, re-fetching, or serializing across the task boundary is unnecessary.
- Updated the role contract to allow direct trivial edits while reserving substantial work for subagents.
- Reinforced that parallel work must be fanned out broadly and that one-off task dispatches are disallowed.
- Clarified that subagents make edits only, while the orchestrator runs verification for changed files.
- Tracked the latest in-flight preview diff recompute in ToolExecutionComponent and exposed it through a new whenPreviewSettled method.
- Updated component paths that trigger preview recomputation to retain the returned promise instead of fire-and-forget calls.
- Updated the streaming preview height test to await settled diff recomputation before assertions, eliminating requestRender race-based flakes.
- Added `Settings.reloadForCwd` to mutate the live instance in place, so `/move` and cross-project resume pick up the destination project's `.claude/settings.yml` and path-scoped `enabledModels`/`disabledProviders`.
- Wired `reloadForCwd` into `applyCwdChange` (interactive mode) and the `--resume` startup path so settings always follow the active working directory.
- Added tests covering path-scoped re-resolution, no-op on same directory, and disk-backed project layer load/drop.
- Enabled resume picker to preload sessions and toggle folder/all scope with Tab.
- Enabled resume flow to fall back to all-project sessions and switch cwd on resume.
- Added centralized applyCwdChange to refresh caches, commands, and UI after cwd updates.
- Updated session restoration to adopt restored session cwd and sessionDir when present.
- Added ROW_COUNT_PROBE_CAP to limit rows scanned when counting tables, preventing JS thread freezes on large databases.
- Used sqlite_stat1 estimates for tables exceeding the cap; exact counts only for provably small tables.
- Introduced TableRowCount type with exact/estimate/atLeast variants reflected in rendered output.
- Fixed `session_id` never being created or populated; every history row had `NULL` for session.
- Added schema migration (`ALTER TABLE history ADD COLUMN session_id`) for pre-existing databases.
- Wired interactive mode to call `setSessionResolver(...)` so prompts are stamped with the active session at submission time.
- Re-enabled session ranking in `--resume` and in-session pickers via `matchingSessionIds()`, merging fuzzy and prompt-history signals.
- Computed screenshot destination extensions from the MIME type of bytes being written.
- Updated auto-generated paths in screenshot and temp directories to use the matching extension.
Separated the fork prompt result into accepted, declined, and unavailable states.
Interactive declines now return cleanly through runRootCommand, while non-TTY
invocations continue to fail with a diagnostic instead of silently exiting 0.
Updated regression coverage for both branches.
Fixes#1668
createSessionManager threw `Session "X" is in another project (Y).` when
the user answered "n" to the fork prompt, and runRootCommand never caught
it. The throw bubbled up as an Uncaught Exception with a stack trace.
Return undefined from the decline branch instead, and treat
`typeof parsed.resume === "string" && !sessionManager` in runRootCommand
as a user cancellation: print a dimmed "Resume cancelled" message and
return cleanly (exit 0), mirroring how the picker UI handles
"No session selected".
Fixes#1668
Filtered the logout selector to credentials that /logout can actually remove and reported ambient env/config auth when direct logout cannot clear it. Added selector coverage for env-only OpenCode providers.\n\nFixes #1658
- Extracted TUI rendering from `eval.ts` into a dependency-light `eval-render.ts` to break the circular initialization chain.
- `renderers.ts` now imports `evalToolRenderer` from `eval-render` directly, avoiding re-entry into the root barrel while `eval.ts` is still initializing.
- `eval.ts` re-exports `evalToolRenderer` and `EVAL_DEFAULT_PREVIEW_LINES` for backward compatibility.
- Increased first-event timeout test budget from 50ms to 5000ms to prevent CI scheduler jitter from tripping the watchdog on success cases.
- Moved EvalBackendsAllowance and related functions to a dedicated eval-backends.ts module.
- Replaced ad-hoc brokenShellSessions tracking with a quarantineShellSession helper that also awaits the abort cleanup promise.
- Applied quarantine on timeout and cancellation paths, not just errors.
When the autocomplete popup is visible, ESC unconditionally falls through
to the editor base class so it can dismiss the popup. Only an ESC with no
popup visible reaches onEscape and routes to the global interrupt handler.
Removed the shouldBypassAutocompleteOnEscape callback that paved over the
popup-dismissal path whenever the agent was busy (streaming, bash, /btw,
auto-compaction, etc.) — that is precisely the moment the user is most
likely to hit ESC while the popup is open, and dismissing-then-aborting in
one keystroke is a footgun, not a feature. Two-press semantics now match
the standard TUI/IDE pattern: first ESC closes the popup, second ESC
aborts.
Tests cover both branches in custom-editor-keybindings.test.ts and the
input-controller escape suite no longer asserts the dead callback.
Fixes#1655
- Added `DiagnosticsLedger` to track diagnostics already surfaced per file, suppressing repeats within a session.
- Wired dedup into both edit and write tools via a `transformDiagnostics` hook on the writethrough pipeline.
- Added `lsp.diagnosticsDeduplicate` setting (default: true) to control the behavior.
- Only bridge heartbeats (`agent()`/`llm()`) now re-arm the watchdog; compute, stdout, `log()`/`phase()`, and ordinary tool calls count against the budget.
- Emitted an immediate heartbeat at bridge call start to avoid early abort near budget edge.
- Removed `idle` flag and "of inactivity" suffix from timeout annotation strings.
- Updated docs, prompts, and comments to reflect the new wall-clock semantics.
The per-cell `timeout` is an inactivity budget that only re-arms on status
events, but host-side bridge calls can run long stretches with no
intermediate status (a subagent's time-to-first-token on a reasoning
model, a long quiet nested tool, or an entire oneshot llm() request).
The watchdog mistook that for a stall and aborted working subagents
mid-flight.
Pump a lightweight heartbeat while a bridge call awaits, re-arming the
watchdog through the existing emitStatus -> onStatus channel. The
heartbeat is a pure keepalive: forwarded to bump the timer but never
stored or rendered, so a genuinely stalled cell is still interrupted
once the call settles.
- eval/heartbeat.ts: withBridgeHeartbeat() + EVAL_HEARTBEAT_OP
- agent-bridge/llm-bridge: wrap runSubprocess / completeSimple
- js+py executors: forward heartbeat to onStatus, drop from displayOutputs
- tools/eval.ts: bump on heartbeat, skip persist/render
- Tool execution now renders every 16ms and advances spinner glyphs only every 80ms using a tracked last-advance timestamp.
- Output block shimmer ticks were reduced to 16ms so border-frame updates align with the 60fps cadence for smoother animation.
- Added `TokenTaskBudget` type and `taskBudget` option to `StreamOptions`.
- Forwarded `taskBudget` as `output_config.task_budget` with the `task-budgets-2026-03-13` beta header.
- Fixed `disableThinkingIfToolChoiceForced` to preserve `task_budget` when clearing `effort`.
- Accepted `output_config.task_budget` from Anthropic gateway requests.
- Extended ResolveContext / WriteContext with localProtocolOptions so the
internal-URL router can thread the calling session's local-root mapping
through to handlers.
- LocalProtocolHandler.resolveOptions now prefers context.localProtocolOptions
before consulting the process-global override or the first main-kind session
in AgentRegistry, fixing multi-session ACP hosts (cmux) where reads of
local://PLAN.md were routing to a sibling session's artifacts dir even
though plan-mode writes succeeded against the calling session.
- read, find, ast_grep, ast_edit, and search now thread
this.session.localProtocolOptions into the router so local://, memory://,
agent://, and other handlers see the right caller.
- Added regression tests covering the override-vs-context priority and the
ENOENT-against-caller-root path.
Fixes#1608
Guarded find renderer path summaries so raw pre-validation string paths render instead of throwing. Added coverage for pending, fallback, empty, and detailed result render paths.\n\nFixes #1622
The catch around the subagent yield-reminder prompt previously logged
every exception at ERROR. User cancel (^C) and compaction-driven aborts
both surface as ToolAbortError through awaitAbortable, so benign control
flow generated 9 spurious 'Subagent prompt failed' errors in 2 days on
the reporter's instance.
Gate the ERROR branch on '!abortSignal.aborted && !(err instanceof
ToolAbortError)' and route the abort path to logger.debug. The outer
catch + finally still mark the run aborted, so observable behaviour is
unchanged.
Fixes#1623
Avoided the forced teardown repaint during interactive shutdown so disposed UI state cannot clear the viewport before Bash resumes.
Moved TUI stop cursor placement to the first row after short rendered content without adding a blank line.
Fixes#1620
Switch the pre-prompt token estimate to computeNonMessageTokens so the guard sees the same system-prompt, tool-schema, and skills accounting as /context. Without tool tokens, sessions with large MCP tool sets stayed below the compaction threshold while the outbound request was over the model limit.
Refs #1618
Include pending prompt messages in the pre-send context estimate so auto maintenance runs before providers reject over-limit requests. Suppress auto-continue when maintenance runs inline for an active prompt.
Fixes#1618
Enable eager native scrollback rebuild mode while assistant text is actively streaming so reflowed Markdown rows do not leave stale duplicated tails in WSL/Windows Terminal scrollback.\n\nFixes #1615