- Replaced time-based sleeps and polling loops with event-driven promise resolvers and fake timers across agent and tool tests.
- Migrated test suites to share in-memory auth storage and fixtures using lifecycle hooks.
- Updated catalog model definitions, metadata, and configurations.
- Added `providerRetryWait` and `retryWait` hooks to stream/usage options so tests bypass real scheduler delays.
- Parameterized GitHub Copilot poll intervals and Copilot model retry base delay for fast test execution.
- Replaced `Bun.sleep`/`setTimeout` polling loops with `AbortSignal` event listeners in agent session tests.
- Consolidated auth-gateway E2E helpers into a shared `test/helpers` module, eliminating duplicated `checkGatewayAvailable` implementations.
- Migrated credential-disabled tests from SQLite-backed stores to an in-memory store, removing temp-dir lifecycle overhead.
Addresses the codex review comments on #1015 plus a sweep of adjacent
ACP conformance gaps surfaced while wiring them up.
Tool call + diff metadata
- acp-event-mapper: thread session cwd through and resolve every
`ToolCallLocation` (initial args, in-flight updates, result details)
to absolute paths against it; ACP requires absolute paths for
client-side file mapping.
- edit/modes/patch: emit the destination path for moves in the diff
result so post-edit "open file" actions land on the new file.
Permissions
- agent-session: pass cwd into `extractPermissionLocations` and resolve
raw `path`/`file`/etc. fields against it before sending
`session/request_permission`.
- agent-session: gate the permission wrapper on
`bridge.capabilities.requestPermission && bridge.requestPermission`,
matching the read/write/bash capability+method pattern.
acp-agent
- `authenticate`: validate `methodId` against the methods advertised by
`initialize` and reject anything else, so malformed clients fail fast.
- `setSessionConfigOption(MODE_CONFIG_ID)`: also emit
`current_mode_update` so clients tracking `modes.currentModeId` see
the same transition `session/set_mode` would produce.
- Pass `runtime.notifyConfigChanged` to builtins; emit
`available_commands_update` from a shared `reloadPlugins` helper
reused by `/reload-plugins`, `/marketplace`, and `/plugins`.
- prompt resource handling: route `resource` content with `image/*`
MIME into the `images` array instead of dropping it as an opaque
blob; non-image blobs still fall back to the URI placeholder.
- pass session cwd to the event mapper.
Builtins
- model: call `runtime.notifyConfigChanged()` after a successful
`setModel` so the ACP config selector reflects the new model
immediately.
- mcp: redact query strings and userinfo from MCP server URLs before
emitting them in `/mcp list` (prevents leaking `?exaApiKey=…` style
secrets); wire `manager.setAuthStorage(...)` before `prepareConfig`
in `/mcp test|resources|prompts` so OAuth servers can refresh tokens.
- ssh: reject non-integer `--port` values via a `^\d+$` guard instead
of silently coercing through `Number.parseInt`; list project hosts
first and dedupe user-scope duplicates to match capability-loader
precedence.
- export: reject clipboard aliases (`--copy`, `clipboard`, `copy`)
before passing them to `exportToHtml` as a filename.
- compact / force / move / browser: surface underlying failures via
`usage(errorMessage(...))` instead of letting them crash the command.
- session save|delete: route through the active SessionManager so the
persist writer is consulted and stale storage references are removed.
- marketplace / plugins / reload-plugins: call `runtime.reloadPlugins()`
on install/uninstall/upgrade and enable/disable so slash command
registries and command lists refresh consistently.
- shared.usage: make async and `await runtime.output(...)` so
`sessionUpdate` text is never dropped or reordered.
- types: document the new `reloadPlugins` and `notifyConfigChanged`
runtime hooks.
bash tool
- Use a shared `fireKill()` from the abort listener so `session/cancel`
terminates the remote command immediately instead of waiting for the
next `currentOutput()` round trip.
- Race `currentOutput()` against the abort signal so a stuck
`terminal/output` RPC cannot delay cancellation.
- Kill the terminal before reading final output on timeout so a slow
output read cannot let a timed-out command keep running past the
enforced timeout.
Tests
- acp-agent.test: extend the existing config-option assertions to
verify both `model` and `thinking_level` changes emit
`config_option_update` notifications scoped to the right session.
- acp-builtins.test: cover `/model` emitting both
`notifyTitleChanged` and `notifyConfigChanged`; lock in the parsed
`mcp add` / `ssh add` call shapes so future arg-parser regressions
fail the test instead of silently writing different configs; add a
`reloadPlugins` stub plus a typed `notifyConfigChanged` slot to the
shared test runtime factory.
- acp-stdout-hygiene.test: drain stderr in parallel and assert no
JSON-RPC frame leaks onto it; terminate the spawned process so the
stderr pump resolves deterministically.
CHANGELOG: itemize the above under `[Unreleased] > Fixed`.
CI
- bun run check: clean (TS + Rust)
- bun run test: 4128 pass / 689 skip / 0 fail (TS); 252 pass / 0 fail
(Rust nextest)
- bun run ci:test:smoke: --version / --help / `stats --help` all OK