Move session tasks, background tasks, subagents, and team activity into a floating right-side activity panel with capped section scrolling.
Add subagent run detail tabs backed by the existing session run data so member activity can be inspected from the main chat.
Tested: cd desktop && bun run test -- src/components/activity/SessionActivityPanel.test.tsx
Tested: bun run check:desktop
Fix cross-issue regressions found during post-0.4.4 merge review:\n\n- preserve permission mode across clear and empty-session replacement flows\n- keep provider effort passthrough and context-window estimates aligned with runtime metadata\n- invalidate recent project caches and trace message signatures when sessions change\n- recognize Windows ARM64 unpacked package-smoke output\n\nTested: bun test scripts/quality-gate/package-smoke/index.test.ts scripts/quality-gate/runner.test.ts\nTested: bun run check:desktop\nTested: bun run check:server\nConfidence: high\nScope-risk: moderate
Refs: #896, #953
Make provider network proxy mode explicit so desktop sidecar system proxy env does not affect provider connectivity tests or OpenAI-compatible proxy requests unless System proxy is selected.
Tested: bun test src/server/__tests__/network-settings.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/proxy-network-settings.test.ts
Tested: cd desktop && bun run test -- src/stores/settingsStore.test.ts src/__tests__/generalSettings.test.tsx --run
Tested: bun run check:server
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Confidence: high
Scope-risk: moderate
Make bypassPermissions skip permission-approval ask decisions while preserving explicit denies and tools that require user interaction. Keep desktop permission mode state authoritative by waiting for server/CLI confirmation and persisting CLI-originated mode broadcasts.
Tested:
- bun test src/utils/permissions/permissions.test.ts
- bun test src/server/__tests__/conversations.test.ts -t "permission switch|permission restart|permission-mode broadcasts|permission changes made before|bypass permissions back to default|runtime-only model switch"
- bun test src/server/__tests__/ws-memory-events.test.ts
- cd desktop && bun run test -- src/stores/chatStore.test.ts --run
- bun run check:server
Scope-risk: moderate
Use transcript activity timestamps for session list ordering instead of JSONL mtime, and skip duplicate runtime metadata appends.
Tested: bun test src/server/__tests__/sessions.test.ts --test-name-pattern "metadata-only writes|duplicate runtime metadata"
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: bun run check:server
Confidence: high
Scope-risk: moderate
Add a provider-level disableExperimentalBetas setting that writes CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1 into managed provider runtime env, keeps stale parent env isolated, and exposes the toggle in desktop provider settings.
Tested: bun test src/server/__tests__/provider-runtime-env.test.ts --test-name-pattern "experimental betas|stale proxy"
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "experimental betas|POST /api/providers should create a provider|PUT /api/providers/:id should update a provider"
Tested: bun test src/server/__tests__/conversation-service.test.ts --test-name-pattern "experimental beta kill switch"
Tested: cd desktop && bun run test -- --run src/__tests__/generalSettings.test.tsx -t "experimental beta headers|Tool Search"
Tested: cd desktop && bun run test -- --run src/lib/__tests__/providerSettingsJson.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run build
Not-tested: bun run verify
Confidence: high
Scope-risk: moderate
Preserve user-invoked skill command metadata during session restore,
WebSocket replay, and session search while continuing to hide malformed
command breadcrumbs.
Tested:
- bun test src/server/__tests__/sessions.test.ts
- bun test src/server/__tests__/ws-memory-events.test.ts
- bun test src/server/__tests__/searchService.sessions.test.ts
- cd desktop && bun run test -- --run src/stores/chatStore.test.ts
- bun run check:server
- cd desktop && bun run build
- git diff --check
Not-tested:
- bun run check:desktop did not complete because an existing MessageList timestamp assertion fails independently of this change.
Confidence: high
Scope-risk: narrow
Stream inspection transcript aggregation and avoid trace/message polling paths that repeatedly hydrate large session files.
Tested: bun run check:server
Tested: bun run check:desktop
Confidence: high
Scope-risk: moderate
Emit a visible Goal continuing local-command marker before managed /goal continuations, then preserve it through server events, session history, and desktop history restore.
Render the marker as a compact divider so a new assistant continuation after end_turn is visually separated from the previous assistant output.
Related: #901
Tested: bun test src/query/stopHooks.test.ts src/server/__tests__/ws-memory-events.test.ts src/server/__tests__/sessions.test.ts && cd desktop && bun run test MessageList.test.tsx chatStore.test.ts
Tested: bun run check:server
Tested: bun run check:desktop
Not-tested: live release build and Windows v0.4.3 repro path; keep issue open until release validation.
Scope-risk: moderate
Confidence: high
Reduce repeated /api/sessions?limit=400 scans by caching per-file JSONL list summaries keyed by mtime and size. This targets #894 diagnostics where sidebar refreshes reported client_api_request_failed timeouts on session list and inspection paths.
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: bun run check:server
Tested: temporary source server /api/sessions?limit=400 first call 0.80s; after waiting past the 5s list cache TTL, second call 0.03s with identical 399 session IDs.
Not-tested: Windows release build retest for #894 diagnostics timeout.
Confidence: high
Scope-risk: narrow
Adds an idempotent DELETE /api/traces/:sessionId path that removes only the local trace JSONL file and invalidates trace read cache. The Trace list now exposes a trash action behind a confirmation dialog that states chat history is not deleted.
Tested: bun test src/server/__tests__/trace-capture.test.ts
Tested: cd desktop && bun run test -- src/pages/TraceList.test.tsx --run
Tested: bun run check:server
Tested: bun run check:desktop
Tested: Browser smoke with temporary CLAUDE_CONFIG_DIR verified the Trace list delete button and confirmation dialog on ?traceWindow=1.
Constraint: GitHub issue #868 remains open until a release ships and post-release retest passes.
Confidence: high
Scope-risk: moderate
Provider connectivity tests now pass the actual upstream URL and loopback no-proxy rules into proxy fetch option resolution, including IPv6 loopback. This closes the local test/connectivity gap in the #896 proxy compatibility work without closing GitHub issues before release.
Tested: bun test src/utils/proxy.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/network-settings.test.ts src/services/api/client.test.ts
Tested: bun run check:server
Not-tested: Windows dev-sidecar real-machine retest and release build confirmation for #896.
Confidence: medium
Scope-risk: narrow
Preserve loopback NO_PROXY entries when Electron or manual network settings inject proxy environment variables, and make the Anthropic client skip Bun proxy fetch options for local desktop provider proxy base URLs.
Tested: bun test src/utils/proxy.test.ts src/services/api/client.test.ts src/server/__tests__/network-settings.test.ts src/server/__tests__/conversation-service.test.ts
Tested: cd desktop && bun run test -- electron/services/sidecarManager.test.ts --run
Tested: bun run check:server
Tested: bun run check:native
Not-tested: Windows dev-sidecar real-machine retest for #896; current Mac can only prove loopback proxy bypass behavior and native packaging.
Confidence: medium
Scope-risk: moderate
Fix#845 by starting a lightweight standalone provider proxy for CLI-only OpenAI-compatible desktop providers, avoiding a fixed localhost:3456 proxy when the desktop server is not running.
Fix#847 by passing explicit --permission-mode bypassPermissions for scheduled task subprocesses alongside the dangerous-skip flag.
Tested: bun test src/utils/managedEnv.test.ts src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/cron-scheduler-launcher.test.ts
Tested: bun run check:server
Confidence: high
Scope-risk: moderate
Fixes local Batch A from #809+ triage: configurable scheduled task timeout (#809/#846), OpenAI proxy trace request headers (#836), title generation auth strategy (#854), and unresolved parallel tool card settlement (#889).
Tested: bun test src/server/__tests__/cron-scheduler-launcher.test.ts
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun test src/server/__tests__/proxy-network-settings.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts
Tested: bun run check:server
Tested: bun run check:desktop
Not-tested: bun run verify and coverage were not run because this is a local batch checkpoint, not a PR-ready/push-ready handoff.
Confidence: high
Scope-risk: moderate
Add per-model 1M capability flags for custom providers and persist them through provider settings.
When a model is marked as 1M-capable, runtime env uses the local [1m] marker and the desktop form auto-fills a 1000000-token context window when needed.
Tested: bun test src/server/__tests__/providers.test.ts -t "custom providers can mark main and role models as 1M-capable"
Tested: cd desktop && bun run test -- generalSettings.test.tsx -t "normalizes blank model mappings|saves 1M model declarations"
Tested: bun run check:desktop
Tested: bun run check:server
Not-tested: bun run verify / coverage gates were not run for this scoped local handoff.
Confidence: high
Scope-risk: moderate
The configured request timeout (API_TIMEOUT_MS) only feeds the SDK client
timeout, which on a streaming request is cleared the moment response headers
arrive. Slow local/3P models return 200 headers fast but spend minutes
prefilling before the first SSE token, so that window was governed by the idle
watchdog (CLAUDE_STREAM_IDLE_TIMEOUT_MS, 240s) -- a separate env users cannot
configure. The configured timeout therefore never applied to slow prefill, so
raising it had no effect (#826, follow-up to #449).
Split the stream watchdog into phases: use a first-token budget (tied to the
user's request timeout via CLAUDE_STREAM_FIRST_TOKEN_TIMEOUT_MS) until the first
chunk arrives, then switch to the shorter mid-stream idle budget. The overall
max-duration cap (#766) still backstops trickling bodies; CLI defaults fall back
to prior behavior.
Add a provider-level Tool Search capability that defaults on for native Anthropic Messages providers and writes ENABLE_TOOL_SEARCH through the managed provider env path. Keep OpenAI proxy formats opted out because the proxy transforms do not support Anthropic tool_reference history yet.
Preserve upgrade safety by normalizing missing or stringly typed stored values instead of dropping saved providers.
Tested: bun test src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx --run
Tested: cd desktop && bun run lint
Tested: bun run check:server
Confidence: high
Scope-risk: moderate
Persist runtime provider metadata for desktop sessions so context estimates stay tied to the provider that launched the session. Infer a unique saved provider window for older sessions without runtime metadata, and keep Xiaomi MiMo custom providers on thinking-only capability mapping instead of max-effort passthrough.
Tested: bun test src/server/__tests__/conversations.test.ts -t "unique saved provider context window|pass the active provider id|provider model context windows"
Tested: bun test src/server/__tests__/providers.test.ts -t "Xiaomi MiMo custom providers|custom providers declare|model context windows"
Tested: bun test src/server/__tests__/sessions.test.ts src/server/__tests__/searchService.sessions.test.ts src/server/__tests__/ws-memory-events.test.ts
Tested: cd desktop && bun run test -- src/stores/chatStore.test.ts src/stores/providerStore.test.ts src/components/controls/ModelSelector.test.tsx
Not-tested: full bun run verify was not run for this local issue handoff.
Confidence: high
Scope-risk: moderate
Persist transcript usage through session history so reopened desktop tabs can restore header token counts, and resume elapsed timers when reconnected sessions report active status.
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: cd desktop && bun run lint
Tested: bun run check:server
Tested: git diff --check
Not-tested: bun run verify and coverage; scoped local handoff, not PR-ready validation.
Confidence: high
Scope-risk: narrow
Tested: bun test src/server/__tests__/ws-memory-events.test.ts
Tested: bun test src/server/__tests__/sessions.test.ts -t "command breadcrumb"
Tested: bun test src/server/__tests__/searchService.sessions.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts
Tested: bun run check:desktop
Tested: bun run check:server
Scope-risk: narrow
Confidence: high
Add a Codex-style global search dialog (Cmd+K / sidebar button) that
full-text searches across all session transcripts, replacing the old
title-only sidebar filter.
Backend: rewrite searchService.searchSessions as a two-phase engine —
ripgrep finds candidate files + matched lines, then those lines are
parsed to keep only user/assistant text, re-confirmed against the
cleaned text to drop JSON/UUID/base64 false positives, and windowed into
highlighted snippets. Results carry real session titles (new
sessionService.getSessionTitleAndMeta reusing the list title
precedence), project path, mtime, role and match counts; falls back to a
JS scan when ripgrep is unavailable.
Frontend: new GlobalSearchModal (debounced, stale-response-safe, keyboard
nav, role badges, highlighting, recent-chats empty state); Cmd+K now
opens it; the sidebar input is replaced by a search trigger button.
Tests: 15 backend cases (searchService.sessions) + 12 frontend cases
(GlobalSearchModal); existing Sidebar/pages tests updated for the new
trigger.
Prefer the live git diff for currently changed workspace files so DIFF previews do not get stuck on stale transcript snapshots. Refresh an existing workspace preview tab when it is opened again instead of only reactivating cached content.
Tested: bun test src/server/__tests__/workspace-service.test.ts
Tested: cd desktop && bun run test src/stores/workspacePanelStore.test.ts --run
Tested: bun run check:server
Tested: bun run check:desktop
Confidence: high
Scope-risk: narrow
Third-party gateways can trickle content deltas (e.g. a large tool_use
input_json_delta) just under the idle-watchdog window and never send
message_stop. Each delta resets the idle timer, so the in-kernel watchdog
never fires and the request hangs forever — the desktop shows "running"
with slowly growing tokens and a permanently-pending trace span (#766).
Add an overall-duration watchdog (CLAUDE_STREAM_MAX_DURATION_MS) that is
armed once and never reset by incoming chunks; the desktop injects 600000ms
via buildChildEnv. Orthogonal to the idle watchdog: idle catches a fully
silent stream, this catches an endless trickle that never completes. CLI
default stays 0 (disabled) for backward compatibility.
Verified end-to-end by replaying the issue's real captured SSE against the
actual kernel: trickle hangs without the cap, aborts cleanly with it.
Keep provider ordering compatible with older desktop store state, keep workspace traversal blocked even when external changed-file roots are registered, and align the quality-contract test with the current AGENTS wording.
Tested: bun test scripts/pr/quality-contract.test.ts
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx src/__tests__/skillsSettings.test.tsx src/__tests__/pluginsSettings.test.tsx src/__tests__/diagnosticsSettings.test.tsx --run
Tested: bun run check:policy
Tested: bun run check:desktop
Tested: bun test src/server/__tests__/workspace-service.test.ts -t 'does not allow relative traversal'
Tested: bun test src/server/__tests__/sessions.test.ts -t 'workspace/file and tree should reject traversal|workspace/diff should reject traversal' --timeout=20000
Confidence: high
Scope-risk: narrow
Fix four root causes in the desktop preview pipeline, surfaced when the
model writes the files the user pointed it at:
- Output chips guessed paths from prose and could point at a missing file.
They are now reconciled against the turn's real changed files: a bare
`index.html` resolves to the `todo-app/index.html` actually written, and
mentions the turn never changed are dropped.
- A standalone single-page index.html got no browser preview (mistaken for a
Vite template). It is now only routed to the source view when a
package.json/vite.config ships in the same change-set.
- Files written outside the session workdir (another folder, or another drive
on Windows) failed to preview with 'Path is outside workspace'. The turn's
changed-file directories are registered as filesystem access roots; html
serves via /local-file and other files via a workdir-relaxed read.
- The visual-selection prompt leaked as a raw bubble on Windows because the
server-appended '[Image source: ...]' line broke replay dedupe. Replay text
is now metadata-normalized before comparison (affects any image message).
Adds unit tests for each: htmlPreviewPolicy, assistantOutputTargets
reconciliation, replay dedupe + stripGeneratedImageMetadataLines, filesystem
access roots, and workspace outside-workdir reads.
Render provider settings through dnd-kit sortable rows, include official providers in the same order model, and persist providerOrder across server and desktop state.
Tested:
- bun test src/server/__tests__/providers.test.ts src/server/__tests__/persistence-upgrade.test.ts
- cd desktop && bun run test -- --run src/stores/providerStore.test.ts src/__tests__/generalSettings.test.tsx -t "providerStore reorderProviders|Settings > Providers tab"
- cd desktop && bun run lint
- cd desktop && bun run build
- bun run check:persistence-upgrade
Not-tested:
- bun run check:server (broad suite hit environment failures during this run: MCP stdio zshrc timeout, adapter dependency gap at the time, and e2e cascade)
Confidence: high
Scope-risk: moderate
When an upstream request was aborted mid-stream (SDK client timeout,
stream idle watchdog, non-streaming fallback timeout, or user
cancellation), the trace fetch hook waited on a clone of the response
body that could hang forever, so the call never left "pending" in the
trace panel — exactly the silent stall that misled the #766 report.
- captureResponseTraceSnapshot reads the body with abort awareness:
reader.cancel() on abort keeps the partial body, with a 2s grace
backstop for runtimes where cancel cannot wake a hung read.
- The fetch hook now records an error-state call on abort with the
abort reason (e.g. the watchdog's stream idle timeout), duration,
partial response body, and an api_call_aborted event; non-abort
capture failures also record an error instead of inferring ok, and
pre-response fetch rejections carry an aborted flag.
- The trace detail panel shows an "Aborted" badge plus guidance for
aborted calls, and labels the new api_call_aborted phase in all
locales.
Tested: bun test src/server/__tests__/trace-capture.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run test -- --run && bun run lint
Desktop injected a far stricter timeout stack than the terminal CLI, so
healthy-but-slow third-party providers (sensenova/bailian/zhipu) died at
exactly API_TIMEOUT_MS while the UI showed "running" forever:
- API_TIMEOUT_MS is the SDK client's time-to-first-byte budget for
streaming requests; these gateways send zero bytes (no headers, no
SSE ping) until prefill finishes, which takes minutes at large
contexts. Raise the default from 120s to the SDK's own 600s and widen
the configurable range to 30-1800s.
- Widen the desktop-forced stream watchdog idle window to 240s so
silent thinking/prefill phases stop tripping the 90s default.
- Disable the non-streaming fallback for desktop CLI sessions: a
non-streaming request only responds after the FULL generation, so it
can never finish inside the same budget and loops timeout aborts
forever while the UI spins (also avoids double tool execution,
upstream inc-4258). All three knobs respect caller env overrides.
Repro: mock upstream whose SSE stays silent for 150s before a complete
event sequence — terminal env completes; desktop env aborts at exactly
120s (client timeout) or 90s watchdog + non-streaming fallback loop;
the fixed env completes both variants.
Tested: bun test src/server/__tests__/network-settings.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/proxy-network-settings.test.ts
Tested: cd desktop && bun run test -- src/stores/settingsStore.test.ts src/__tests__/generalSettings.test.tsx
Tested: cd desktop && bun run lint
Confidence: high
Scope-risk: medium
Reveal-in-Explorer/Finder rejected ~-prefixed paths because no layer
expanded the tilde to the home directory. Expand it in the three path
normalization entry points: server validateOpenPath, frontend
resolveAbsolute, and Electron normalizeOpenPath. Tilde expansion is
platform-aware (~\ only on win32, where backslash is a separator).
Show ExitPlanMode approvals as a rendered plan preview in desktop chat,
forward plan feedback and requested prompt permissions through the desktop
WebSocket permission response, and keep permission-mode restoration owned by
the CLI runtime.
Tested: bun run verify
Confidence: high
Scope-risk: moderate
Ensure Electron sidecar launch and Windows taskkill calls hide console windows, and pass the same hidden-window spawn option through desktop CLI and scheduled-task subprocess launches.
Tested: cd desktop && bun test ./electron/services/sidecarManager.test.ts
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/cron-scheduler-launcher.test.ts
Tested: bun run check:native
Tested: bun run check:server
Not-tested: Windows GUI quit smoke
Confidence: medium
Scope-risk: narrow
UI rebuild (desktop):
- TraceSession: replace 3-column layout with two panes — turn-grouped
timeline tree (draggable splitter, search/filter, keyboard nav) and a
section-flow detail panel (Response / Messages / System Prompt /
Tools / Parameters / Raw), collapse state persists across spans
- Render LLM requests/responses semantically: messages as role-colored
conversation with tool_use/tool_result pairing instead of raw JSON
dumps; Raw fallback via CodeViewer for legacy truncated records
- TraceList: row-style list with model chips, mono metrics, hover
actions; content-visibility rows (no virtualization, WebKit-safe)
- i18n synced across zh/en/jp/kr/zh-TW (+25/-55 keys)
Data & capture (server):
- Capture full bodies: preview cap 2048 -> 240k chars, stream cap
256KB -> 1MB; list API trims previews to keep polling light; new
GET /api/sessions/:id/trace/calls/:callId returns the full record
- Extract per-call token usage at read time (SSE + JSON + proxy
wrapped); mtime-keyed read cache for the polling path
- Fix sensitive-key regex redacting *_tokens count fields, which made
token stats always report 0
Frontend data layer:
- SSE stream reassembly (Anthropic + OpenAI chat) adapted from
claude-tap (MIT, attribution in THIRD_PARTY_LICENSES.md), request/
response body parsers, shared formatters, on-demand call detail
cache; traceViewModel gains tokenUsage/isLifecycleNoise, drops
fullRaw
Tested:
- bun run check:server (1201 pass)
- bun run check:desktop (lint + 1358 tests + build)
- Chromium walkthrough against real local traces: list, session tree,
LLM semantic detail (new format), legacy fallback, tool detail
Tested:
- cd desktop && bun run test -- --run src/pages/TraceList.test.tsx
- bun test src/server/__tests__/trace-capture.test.ts
- bun run check:desktop
- bun run check:server
Scope-risk: broad
Fixes#652.
Add desktop/server output style settings APIs and a General Settings picker
that mirrors the Claude CLI outputStyle sources.
Persist active-project choices to .claude/settings.local.json and global
choices to user settings, and route /config to the local settings UI.
Tested:
- bun test src/server/__tests__/settings.test.ts
- cd desktop && bun run test -- src/components/chat/composerUtils.test.ts src/stores/settingsStoreOutputStyle.test.ts src/pages/SettingsOutputStyle.test.tsx
- cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx
- bun run check:desktop
- bun run check:server
- bun run verify
Confidence: high
Scope-risk: moderate
Ensure custom OpenAI-compatible provider tests explicitly request non-stream responses for both direct connectivity checks and the proxy pipeline. This avoids default SSE responses being parsed as empty JSON by provider validation.
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "requests non-stream OpenAI Chat responses during provider tests"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun test src/server/__tests__/proxy-transform.test.ts
Tested: bun run check:server
Confidence: high
Scope-risk: narrow
Prevent desktop prewarm launches from inheriting interrupted-turn resume state, while leaving explicit user-message startup unchanged. Also stop server-side background schedulers during shutdown so app quit cannot leave scheduled task runners alive.
Tested:
- bun test src/server/__tests__/conversation-service.test.ts
- bun test src/server/__tests__/conversations.test.ts -t "prewarm"
- bun test src/server/__tests__/conversations.test.ts -t "permission"
- bun test src/server/__tests__/diagnostics-service.test.ts -t "keeps fatal startup errors visible on stderr while recording diagnostics"
- bun test desktop/electron/services/windows.test.ts desktop/electron/services/tray.test.ts desktop/electron/services/sidecarManager.test.ts src/server/__tests__/server-shutdown.test.ts
- bun run check:server
Add a WhatsApp adapter backed by Baileys linked-device auth, plus desktop QR binding UI, server config endpoints, sidecar startup wiring, tests, and documentation.
Constraint: Uses WhatsApp Web linked-device auth, not Meta WhatsApp Business Cloud API.
Tested:
- cd adapters && bun run check:adapters
- bun test src/server/__tests__/adapters.test.ts
- cd desktop && bun run check:desktop
- bun run check:native
- bun run check:persistence-upgrade
- bun run check:docs
Not-tested:
- Live WhatsApp QR pairing, because no WhatsApp account/device was exercised here.
- bun run check:server, because the existing src/server/__tests__/conversations.test.ts timeout still fails independently.
Confidence: medium
Scope-risk: moderate
The diagnostics panel filled with red ERROR/WARN entries during normal use
because the capture layer treated "wrote to console" as "something failed",
with no severity gatekeeping. Much of the noise was also test runs leaking
into the user's real ~/.claude/cc-haha/diagnostics.
- diagnosticsService: default unclassified events to info (not error);
drop writes under NODE_ENV=test when no CLAUDE_CONFIG_DIR is set; document
the console-capture contract (expected states use console.debug/info).
- index: don't install console/process capture under bun test.
- api/diagnostics: an ingested event with missing severity defaults to info.
- oauthRefreshLog (new): token refresh failure is gracefully handled and is
never an error — expected expiry (401/403/revoked) logs at debug, anything
else at warn. Wired into both Haha OAuth services.
- conversationService: classify cli_runtime_exit severity by exit code, so
clean/SIGTERM/SIGKILL exits are info and only abnormal codes stay error
(real "chat died" crashes remain perceivable).
- ws/handler: streaming partial tool-input JSON is normal — debug, not warn.
Tests: oauth-refresh-log + cli-exit-severity unit tests; diagnostics-service
covers the info default and the test-isolation guard.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Async title refresh runs after assistant output, so provider prompts can be biased by assistant language and English title examples. The title language now resolves from the first meaningful user message before consulting the response-language fallback, then retries once when a generated title violates that language.
Constraint: Desktop response-language settings still control assistant prose, not automatic title metadata when the first user message has a clear language
Rejected: Follow response-language setting for every generated title | Chinese sessions flip to English when replies are configured in English
Rejected: Persist mismatched generated titles after retry failure | preserves a bad UX over the safer first-message placeholder
Confidence: high
Scope-risk: moderate
Directive: Do not change automatic title language precedence without re-testing image/text first-turn sessions and English-response-language sessions
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts -t "refreshes the first-turn AI title"
Tested: git diff --check
Tested: real MiniMax-M3 /tmp session 58a47fcd-6f9d-4685-bc73-f9317e3f330e with temporary response language english; assistant replied English and final aiTitle was 标题语言验证
Not-tested: bun run check:server blocked before tests by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Desktop title generation previously upgraded the first sidebar title from the raw user prompt before assistant output existed. That made image-plus-text sessions vulnerable to keeping a title based only on the user's initial wording. This moves polished title generation to completed turns, reuses the CLI title prompt and transcript extractor, and routes title calls through the configured haiku model with a retry when disabled thinking is rejected.
Constraint: The first user message still needs an immediate placeholder title so the sidebar is responsive.
Rejected: Generate the AI title before assistant output | image-derived context is only available after the assistant turn completes.
Confidence: high
Scope-risk: moderate
Directive: Keep polished automatic titles tied to completed transcript turns, not pre-response user prompts.
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts -t "refreshes the first-turn AI title"
Tested: git diff --check
Tested: Real MiniMax-M3 /tmp session f89073ed-3467-492a-b63c-e1886c146a3a with image attachment wrote ai-title "Validate session title generation"
Not-tested: bun run check:server is blocked by existing expired quarantine manifest entries
Desktop chat can fall back to persisted transcript estimates when live inspection context is unavailable. That path previously only used built-in model windows, so custom provider settings such as MiniMax-M3 with a 1,000,000-token window still displayed the default 200,000-token estimate. Resolve transcript context windows from the session or active provider runtime env first, then fall back to built-ins.
Constraint: Provider model context windows are stored in provider runtime env, not always in the server process env.
Rejected: Change the built-in MiniMax-M3 window to 1,000,000 | upstream preset correctly keeps MiniMax-M3 at 204,800 by default, while user overrides must remain provider-specific.
Confidence: high
Scope-risk: moderate
Directive: Keep transcript estimates aligned with session/provider runtime env before consulting built-in model defaults.
Tested: git diff --check
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "active provider model context windows|Sonnet 4.6 transcript usage|low-trust media"
Tested: bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Not-tested: bun run check:server blocked before execution by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow