The model-reference check told operators to install a plugin or configure
models.providers for a retired provider like openai-codex, which would
recreate a route the architecture deliberately removed, while doctor --fix
already migrates the ref losslessly. Ask the migration owner whether it would
rewrite the ref and, when it would, name the target and the repair command.
Restore direct project sessions regressed by registered-project placement. Git remains required for managed worktrees, while direct sessions validate only that the project directory is available.
Refs #112242
Doctor's human output labels less than 100 MB free as CRITICAL because config,
session, and log writes may fail silently and lose data. The structured lint
finding still used warning, so --severity-min error filtered it out, returned
ok=true, and exited successfully. Share the threshold decision between the
structured severity and requirement: critical is error, low space remains
warning. Update the regression contract accordingly.
The stream:"plan" fallback on both native platforms is deliberate compatibility
debt with a fixed expiry, not a permanent contract. Record the sunset date, point
each platform at its twin and at the tracking issue, and correct the Android note
to v2026.8.x (the newest released tag also lacks progressCard.get).
Refs #125639
* improve(ui): flatten transcript tool activity
* improve(ui): complete tool activity redesign
* improve(ui): normalize activity row typography
* improve(ui): unify activity typography contract
* improve(ui): standardize all activity row text
* improve(ui): increase activity text size
* improve(ui): underline activity filenames
* improve(ui): tighten activity row spacing
* improve(ui): standardize activity chevrons
* improve(ui): reveal child chevrons on interaction
* improve(ui): retain active child chevrons
* improve(ui): space expanded child tools
* improve(ui): remove idle activity fade and gap
* fix(ui): preserve tool activity contracts
* fix(ui): simplify activity basename lookup
* fix(ui): preserve canonical tool row actions
* fix(ui): record tool outcomes and repair transcript row regressions
Neutral collapsed rows are the design, but this branch left failures with
nowhere to land and shipped chrome whose styles it had already deleted.
- Expanded standalone tool messages close with the outcome line, so an inline
rows shape still reports the failure instead of dropping it.
- Progress-card receipts drop the badge and the spinner: this branch removed
both styles, leaving a 0x0 invisible running indicator, and the receipt
label already names the state.
- Single delete patches are non-navigable; their workspace target is gone, so
the file action could only ever fail to load.
- Flush command padding derives from the action-button size instead of a stale
42px constant, and the running text wave covers command rows again.
- Activity lane returns to the tool-shell column width the rule claims.
- Drop CSS nothing references: tool-card tabs, empty, plain-output, activity
scroll masks, secondary command text.
- renderToolDataBlock takes an optional label instead of comparing copy.
- Split the oversized tool-card test file and refresh stale row assertions.
* fix(ui): fold the tool action size into the card header rule
Stylelint no-duplicate-selectors rejects the separate .chat-tool-card__header
block; the custom property belongs in the existing rule.
---------
Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
* fix(setup): refresh Codex registry with staged install
* fix(macos): verify inference before onboarding handoff
* fix(setup): use native Codex home for subscription auth
* fix(codex): honor attempt-scoped setup config
* fix(macos): align onboarding handoff with reopen
* fix(setup): await prepared model convergence
* fix(ui): avoid false auth state for empty catalog
* fix(setup): scope catalog convergence to Codex gateway
* fix(setup): publish the committed runtime catalog
* fix(models): project configured static runtime models
* fix(codex): expose app-server model catalog
* fix(models): preserve Codex auth across reloads
* fix(ci): align Codex onboarding checks
* test(ui): stabilize dock suppression environment
* fix(codex): honor discovery config in app-server model catalog
The manifest documents discovery.enabled (bundled fallback list) and
discovery.timeoutMs (default 2500ms) for model discovery; the new catalog
path used the generic 60s request timeout and ignored the enable gate.
Also drop the test-only listModels injection seam in favor of vi.mock.
* fix(setup): refuse prepared Codex auth over an explicit remote transport
configureCodexCliPreparedAuth silently rewrote an explicitly configured
websocket/unix app-server to local stdio (keeping a dangling url), moving
the credential boundary onto this host. Fail setup with actionable
guidance instead; also surface the root cause when the prepared model
catalog refresh fails after activation.
* refactor(agents): one canonical model-catalog identity key
Three near-identical key helpers existed (models-list-result,
models-list-configured-static, harness/model-catalog). Export
resolveModelCatalogIdentityKey from the route-policy owner, collapse the
duplicate dedupe loops into dedupeByKey, make donor enrichment Map-based,
and inline the one-off harness-augment wrapper.
* fix(macos): restore custodian handoff for fresh activations
Landing every finish on the plain dashboard stranded the custodian
first-run flow (memory import, channels, permissions, hatch). Fresh
activations now hand off to custodian onboarding; live-verified
pre-existing setups reopen the normal dashboard, matching the removed
already-configured shortcut. Tests pin the destination per path.
Also isolate the post-startup Codex login test from developer machines:
ambient OPENAI_API_KEY and a real Codex login made it assert-fail.
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(ui): coalesce device refreshes during active loads
Nodes and device list loaders dropped every refresh request received while a
previous list RPC was in flight. A successful approve, reject, removal, token
mutation, or Gateway resolved event could therefore be overwritten by the old
pre-mutation response and remain stale until the next poll.
Record one closed pending refresh mode per list owner. When the current request
settles, immediately run the coalesced refresh, preserving whether any queued
caller requested visible error handling. Add order-faithful node and device
regressions that fail when the follow-up list request is dropped.
* test(ui): initialize queued device refresh state
Forced embedded-run terminalization now settles the exact closure-bound local placement claim, preserving replacement fencing and allowing archive to drain.
Closes#125555
Resolve retained dependency closures from each physical importer so Docker pruning preserves concurrent nested package versions required at runtime.
Add importer-bound regressions and a post-prune grammY import gate.
Co-authored-by: AmAzing129 <115673583+AmAzing129@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* fix(apps): render legacy plan events when the Gateway lacks the progress-card store
progressCard.get ships in no released Gateway tag, so iOS/macOS on any current
release silently showed no status card after the durable-card migration. Restore
legacy stream:"plan" rendering, synthesized into the unified progress card and
gated on a tri-state capability probe so a dual-emitting Gateway never fights the
durable store. Mirrors the Android fix in #125444.
* fix(apps): invalidate progress-card capability on gateway route replacement
A replacement route may be a different Gateway, so a cached known-absent store
must not authorize the legacy plan fallback against a new Gateway that dual-emits
both sources. Clear and re-probe on .routeChanged.
Fix xAI barge-in truncation that reported 3760 ms after only 3700 ms of decoded audio.
Share exact audio-duration math across OpenAI, xAI, and Google while keeping provider-specific rounding at each caller.
Claude Code forwards Agent-tool subagent records with parent_tool_use_id set; the streaming parser treated them as parent records, so subagent thinking streamed as the assistant's reasoning and subagent tool calls surfaced as unattributed top-level tool events. Gate the thinking/tool dispatchers and assistant-snapshot path on one shared isClaudeSubagentRecord guard.
Also read Claude result errors[] (skipping [ede_diagnostic] telemetry) for every error result instead of reporting only the subtype name.
Fixture: live Claude Code 2.1.234 stream-json capture with a background Explore subagent. Telegram E2E on the claude-cli backend shows the progress draft with only the parent Agent row.
With no servers configured, mcp probe emitted only its header line and exited
0, while mcp list and mcp doctor both name the condition and the command that
fixes it. Short-circuit the human path with the same guidance and skip building
a runtime for zero servers; JSON output keeps its existing empty envelope.
Browser screenshot results always named the message tool even when policy had
removed it from the model's effective tool surface. Report the staged sanitized
outbound copy and its path without naming another independently gated tool, so
the result remains actionable without becoming hallucination bait. Update the
vision, fallback, and raw-image result tests to protect that contract.
Transcript search excludes sessions whose indexes are rebuilding and already
returns indexing=true, but the model-facing tool gave no guidance that its
results were incomplete. Add a bounded warning telling the model to retry
sessions_search shortly, and cover the exact result contract with a regression
test that fails on the previous behavior.
The gateway-routed path already mapped terminal run status to an exit code,
but the local embedded path did not, so a failed turn exited 0 while its own
JSON envelope reported status "error". Route both through the canonical
agent-run terminal outcome, and fail closed on an unrecognized status since
the gateway response carries an open string.
worker_session_placement_moves.target_machine_class was in the canonical state schema and the feature lazy ensureColumn path but not in CLAW_LAZY_ADDITIVE_STATE_COLUMN_DEFINITIONS, so a global state DB that already had the lazily-created table failed the strict startup schema check (column definitions differ) and the gateway crash-looped. Register it as lazy-additive so startup repair adds the column in place, like the sibling worker_session_placements entries.
* fix(cli): render gateway transport failures as expected conditions
An unreachable gateway is an expected, recoverable operator condition, but
only the devices command family surfaced it through the root failure handler,
where it rendered as "The CLI command failed" with debug hints. Extract
GatewayTransportError into its own module so the failure renderer can classify
it without importing the transport stack, and treat it as an expected CLI
error alongside missing credentials.
* fix(gateway): import the transport error kind used by the JSON shape
* test(cli): extract the process-test gateway harness
The new devices coverage pushed gateway-backed-exit.process.test.ts past the
max-lines budget, and that file is not in the ratchet baseline. Move the mock
Gateway servers into a sibling test-helpers module instead of suppressing the
rule.