The inline writethrough budget is 500ms (INLINE_DIAGNOSTICS_WAIT_TIMEOUT_MS);
the test published the deferred diagnostics at 900ms and asserted the inline
call returned in <800ms, leaving only ~300ms of headroom over the budget. CI
jitter pushed elapsed to 844ms (still correct deferral, just slow), failing the
over-tight bound. Publish at 2000ms and assert <1500ms so the deferral margin
is wide while still proving inline does not block on the slow publish.
Completes the injectable-fetch transport wiring (15.10.8) that the feature
left half-done, fixing the deterministic CI test failures:
- compaction.compact() rebuilt summaryOptions field-by-field but dropped
`fetch`, so the injected transport never reached
requestOpenAiRemoteCompaction / generateSummary's remote path. Thread it.
- Read-tool URL pipeline had no fetch seam: renderHtmlToText gained a
fetchOverride param but renderUrl/ToolSession never carried one, so the
jina/parallel reader backends always used global fetch. Add
ToolSession.fetch -> renderUrl -> renderHtmlToText (defaults to global).
- searchWithParallel mirrored extractWithParallel but missed the fetch
option; add it.
- Repair tests whose deleted hookFetch interceptors were never replaced
with a FetchImpl seam (fetch-kagi-toggle, web-search-parallel,
issue-970 discovery).
- Update issue-1746 POSIX case to the #2154 preserved-scrollback contract:
unknown-viewport streaming deferral is now platform-independent.
- Added optional FetchImpl fields to compaction, proxy, AI, coding-agent, and mnemopi options.
- Threaded injected fetch implementations through OAuth, discovery, and search/LLM request flows.
- Removed exported hookFetch utility and its package entrypoint from utils.
- Replaced global-fetch test monkeypatching with per-test FetchImpl mocks across test suites.
- Parsed a trailing `@slug` to set OpenRouter `provider.only` or Vercel Gateway routing per invocation.
- Resolved via `parseModelPattern`, composing with thinking levels and round-tripping through selectors.
- Split only when the base resolves to an aggregator, so ids containing `@` stay intact.
- Dropped blank lines, capped at 8 lines, and width-truncated each line so a proxy 502's HTML body can't flood the transcript.
- Mirrored the pinned error banner's preview behavior; full text still kept in the persisted session.
- Added a `bash.enabled` boolean setting with a default of `true` in the settings schema.
- Updated tool generation to include the `bash` model tool only when `bash.enabled` is enabled.
- Extended createTools tests to assert `bash` is omitted when disabled and omitted from requested disabled tool lists.
MCPManager.connectServers used to fall through to an unbounded
Promise.allSettled over every still-pending server without cached tools,
so a single MCP server stuck waiting on the per-request MCP timeout
(OMP_MCP_TIMEOUT_MS, default 30 000 ms) gated the entire UI ready
signal — exactly the 30.282 s stall the reporter observed against
sbox-superdocs in #2100.
Drop the fallback wait. Pending-without-cache servers are left in flight
and their tools surface via the existing background #onToolsChanged ->
refreshMCPTools path the moment the connect completes; failures continue
to log through the background catch handler (gated on
allowBackgroundLogging) so users still see which server failed.
Adds a regression test that spawns an unresponsive stdio MCP fixture
and asserts connectServers returns inside the 250 ms STARTUP_TIMEOUT_MS
window (padded for CI jitter). The same test times out at 15 s without
the patch.
Fixes#2100
On kitty (Linux/Wayland) and any terminal supporting OSC 5522 enhanced
paste, the /login API-key prompt for OpenCode Zen — and any other modal
Input prompt (Perplexity OTP, GitHub Enterprise URL, manual OAuth
redirect URL, …) — silently dropped pasted content. The user could not
paste their API key; on Enter or Esc the key surfaced in the main
prompt.
Cause: InputController.#setupEnhancedPaste enables kitty's enhanced
clipboard protocol on TUI start and consumes the resulting OSC 5522
packets in an addInputListener that runs *before* focus dispatch in
tui.#handleInput. The controller's pasteText callback then routed
unconditionally to this.ctx.editor.pasteText(text) — the main
CustomEditor — even when selector-controller had cleared editorContainer
and focused a temporary Input. The text accumulated in the detached
editor and only resurfaced when the modal was dismissed.
Fix:
- TUI.getFocused() exposes the currently focused component.
- Input.pasteText(text) mirrors Editor.pasteText so any Input can absorb
a payload from a non-bracketed transport.
- InputController's enhanced-paste callback consults getFocused() and
routes text to the focused component when it exposes pasteText,
falling back to the editor only when no modal target is in focus.
- Image pastes refuse with a status message when a modal Input is
focused, instead of stuffing a binary blob into the hidden editor.
Regression tests in packages/tui/test/input.test.ts and
packages/coding-agent/test/issue-2127-repro.test.ts pin both the new
TUI/Input contract and the InputController routing source.
Fixes#2127
Threshold-driven auto-compaction with strategy=shake auto-continued even when
the shake reclaimed nothing material, and the next agent turn re-triggered the
same shake (which had nothing new to drop on a second pass), spinning forever.
After shake completes, recompute the post-shake context estimate; when it
still exceeds the auto-compact threshold (or shake reclaimed nothing on overflow
recovery), emit a one-shot fallback warning and hand off to the summarization
driven context-full path so progress actually resumes. Idle is exempt — its
60s+ timer self-throttles and cannot dead-loop on its own.
Fixes#2119
Rendered the MCP OAuth fallback as a short terminal hyperlink plus a single unwrapped copy URL line so terminals do not receive hard-broken authorization URLs.\n\nFixes #2121
Skill prompt custom messages now scan user-authored skill args for magic keywords and turn budgets, matching normal prompt steering behavior without scanning skill body text.
Added a regression test for workflowz and hard turn-budget args on skill prompts.
Fixes#2128
- Updated PI native streaming requests to send model identifiers as provider-qualified keys.
- Updated the auth-gateway model registry to store `${provider}/${id}` first and retain legacy bare IDs as fallback keys.
- Added an `openPlanReview` flow that selected the newest `local://<slug>-plan.md`, resolved its title, and reopened approval.
- Registered a new `/plan-review` builtin slash command that invokes that flow and clears the editor text.
- Added tests covering latest-plan selection plus warnings when plan mode is inactive or when no local plan file exists.
- Updated `renderResult` to inspect `isError` on detail-less task results and render an error state with the error glyph.
- Replaced success/completed status symbols in agent, review, and result outputs with the shared `status.done` symbol.
- Added tests for detail-less task rendering to verify failed results show error and successful results show the done glyph.
- Introduced filterInitialToolsForDiscoveryAll() to centralize tool filtering when discovery mode is "all", replacing inline logic in createAgentSession.
- Added forceActive parameter to ensure tools required by forced tool_choice features (e.g., eager todo) remain active in the request, preventing provider 400 errors.
- Updated eager todo enforcement to check active tool set instead of registry, ensuring it respects tool discovery hiding.
- Derived descriptors, default-model map, env keys, login list, and refresh dispatch from one ProviderDefinition per provider.
- Disabled OpenAI Codex stream obfuscation and interrupted whitespace-only tool-call argument deltas.
- Derived auth-broker callback ports and paste-code login set from the registry.
- Added status.done and tool.* symbols to theme mappings and presets.
- Replaced generic success glyphs with contextual +/-, tool icons, and warnings.
- Mapped tool/task/job completions to status.done or status.enabled with icon overrides.
- Triggered runtime provider refresh after extension registration and warned on failure.
- Ran the operand as an ordinary descendant so it is reaped with the host instead of leaking as an orphan.
- Propagated the command's exit status; reported missing operand and exit 125 with no operand.
- Updated the bash tool prompt's daemon guidance away from nohup/setsid/disown detachment.
- Switched shell renderer success icon/state to "done".
- Matched the `bash` tool's max in the Zod schema and runtime clamp.
- Allowed heavy local-compute cells to request budgets above 10 minutes.
- Updated docs and prompt to reflect the new 1-3600s range.
- Derived device_id from both install id and account UUID via v2 hash domain.
- Fell back to v1 install-only hash when no account UUID is present.
- Threaded account UUID through Anthropic metadata user_id resolution.
- Substituted injected on-disk roots for `local://` in read/write/append (Python and JS).
- Pinned `local://` to the session's own root so eval writes land where reads resolve.
- Rejected path traversal and unknown `scheme://` paths instead of creating junk `local:` dirs.
- Added unit and integration tests covering resolution, guards, and plain-path passthrough.
- Added `getRules()` to `TtsrManager` to expose registered TTSR rules in registration order.
- Updated `createAgentSession` to append `ttsrManager.getRules()` to active rules so TTSR rules can be resolved through `rule://`.
- Rewrote the rulebook matching docs to reflect that `rule://` now includes registered TTSR rules and why.
- Rendered added/current lines without `+`/space prefix padding.
- Collapsed long added runs with a bare `…` marker instead of `+…`.
- Normalized adjacent ASCII/Unicode elision markers to one `…`.
- Updated live transcript state derivation to treat a trailing-line extension with unchanged rows as append-only.
- Replaced the prior append-grew heuristic with preserved-row checks so non-rewritten history is not marked volatile.
- Added a regression test covering in-place streaming line growth and scrollback commit safety in transcript containers.