Bring the detached quality-gate worktree into local main while preserving the existing main-only desktop diagnostics commits. This merge lands the PR/release quality gate, live model baselines, provider selector docs, AGENTS automation rules, and repository hygiene for generated artifacts.
Constraint: Local main had commits not present in the detached worktree, so fast-forward merge was not possible.
Rejected: Rebase the detached worktree | rewriting the already-verified local commits would discard the exact release-gate evidence SHA chain.
Confidence: high
Scope-risk: broad
Directive: Keep quality reports and local Superpowers plans out of future commits; use report summaries as evidence, not tracked artifacts.
Tested: bun run quality:gate --mode release --allow-live --provider-model codingplan:main:codingplan-main --provider-model minimax:main:minimax-main
Not-tested: post-merge full rerun on main; merge had no content conflicts.
Superpowers plan/spec files are local execution artifacts, and this repo already ignores docs/superpowers/. Remove the previously tracked plan files from the index so future quality-gate work does not mix local planning output into product commits.
Constraint: Local Superpowers files should remain available on disk but not be versioned.
Rejected: Add another ignore rule | docs/superpowers/ is already ignored, and the problem was tracked files bypassing ignore rules.
Confidence: high
Scope-risk: narrow
Directive: Keep generated quality reports and Superpowers planning artifacts out of repository commits.
Tested: git diff --check --cached
Tested: git ls-files -ci --exclude-standard
Not-tested: runtime gates because this is repository hygiene only.
Release quality gates are used as maintainer evidence, so a live baseline failure must not hide later provider or desktop-smoke lanes. Run every lane and summarize all pass/fail statuses so reviewers can tell whether the whole matrix was exercised.
Constraint: Live model lanes can fail independently and may be slow, but release evidence needs complete coverage.
Rejected: Keep fail-fast behavior | it makes reports ambiguous after the first live failure.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce fail-fast behavior for release gates without adding explicit unexecuted-lane reporting.
Tested: bun test scripts/quality-gate/runner.test.ts scripts/quality-gate/baseline/cases.test.ts scripts/quality-gate/providerTargets.test.ts
Tested: bun run quality:gate --mode release --allow-live --provider-model codingplan:main:codingplan-main --provider-model minimax:main:minimax-main
Not-tested: clean-worktree release rerun before this commit; run immediately after committing.
AGENTS.md is the operational contract future CodingAgents read before editing this repo. Record when to run PR, targeted, live-baseline, release, docs, and native gates so users do not need to manually enumerate the commands each time.
Constraint: Live baseline depends on local provider and quota state.
Rejected: Leave this only in CONTRIBUTING.md | human-facing docs do not reliably steer future agents.
Confidence: high
Scope-risk: narrow
Directive: Do not claim PR or release readiness without running the corresponding gate or reporting the blocker.
Tested: git diff --check
Tested: bun run quality:gate --mode pr --dry-run
Not-tested: full quality:pr because this is an AGENTS-only guidance change.
Contributors need a visible path for local verification instead of relying on design notes or maintainer memory. Add a GitHub-facing CONTRIBUTING entrypoint, bilingual docs pages, README links, and VitePress sidebar navigation for PR gates, live model baselines, provider selection, reports, and release checks.
Constraint: Live baseline providers are local machine state; docs must tell contributors how to list and choose their own providers without maintainer UUIDs.
Rejected: Keep the instructions only in the quality-gate design doc | too hidden for clone-and-contribute workflows
Confidence: high
Scope-risk: narrow
Directive: Keep quality-gate commands documented wherever contributor onboarding links are exposed.
Tested: bun run check:docs
Tested: bun run quality:pr
Not-tested: live baseline after the docs-only wording change
The live baseline previously accepted provider UUIDs, which made the gate hard to run on another contributor's machine. Add a local provider listing command and resolve quality-gate targets from stable provider-name selectors while keeping UUIDs and current runtime support.
Constraint: Provider configuration is local machine state under CLAUDE_CONFIG_DIR and must not expose API keys.
Rejected: Require contributors to inspect providers.json manually | too error-prone and leaks implementation detail into the workflow
Confidence: high
Scope-risk: narrow
Directive: Keep live-provider baseline selection copyable from quality:providers before adding more live test lanes.
Tested: bun test scripts/quality-gate/providerTargets.test.ts
Tested: bun test scripts/quality-gate/*.test.ts scripts/quality-gate/baseline/*.test.ts
Tested: bun run quality:providers
Tested: bun run quality:gate --mode baseline --dry-run --provider-model codingplan:main --provider-model minimax:main
Tested: bun run quality:gate --mode baseline --dry-run --provider-model custom:haiku
Tested: bun run quality:gate --mode pr --dry-run
Tested: bun run check:server
The live baseline covered the server WebSocket path, but it still did not prove the desktop app can open a session, apply a selected provider/model, send a chat turn, and surface model/tool progress through the UI. This adds an agent-browser driven smoke lane that starts the local server and Vite desktop app, restores an isolated session tab with the requested runtime selection, submits a small coding task through the composer, and accepts the run only when the fixture diff and tests pass.
Constraint: Desktop smoke must stay behind --allow-live because it launches browsers and real models.
Constraint: The smoke temporarily enables bypassPermissions for the isolated run and restores the previous mode afterward.
Rejected: Wait for a final marker phrase | model reasoning and echoed prompts can contain the same marker before the work is actually done.
Rejected: Use only DOM text as success proof | the browser can show progress while the project files are still unchanged.
Confidence: high
Scope-risk: moderate
Directive: Future desktop smoke cases should verify project state and artifacts, not only UI copy.
Tested: bun test scripts/quality-gate/*.test.ts scripts/quality-gate/baseline/*.test.ts
Tested: bun run quality:gate --mode baseline --dry-run --provider-model minimax-m2.7
Tested: bun run quality:gate --mode baseline --allow-live --provider-model minimax-m2.7 (9 passed, 0 failed)
Tested: bun run check:server
Not-tested: Kimi desktop smoke completion because the provider returned AccountQuotaExceeded / API Error 429 until its reset window.
The first quality gate proved the execution path, but two tiny fixtures were not enough to reveal regressions in real agent behavior. This expands the maintained baseline with deeper failure recovery, workspace search, artifact creation, and cross-module refactor cases, and records per-case diffs so reviewers can see exactly what each model changed.
Constraint: Baseline runs must remain explicit maintainer-controlled live checks, not default PR checks.
Rejected: Require models to edit tests in every contract-change case | correct fixes can satisfy prewritten acceptance tests without modifying tests.
Rejected: Trust only command exit codes | passing tests alone does not show whether the agent edited forbidden or unrelated files.
Confidence: high
Scope-risk: moderate
Directive: Keep live baseline cases product-shaped and inspect both verification output and diff.patch before accepting future fixture changes.
Tested: bun test scripts/quality-gate/*.test.ts scripts/quality-gate/baseline/*.test.ts
Tested: bun run quality:gate --mode baseline --dry-run --provider-model volc-kimi-k2.6 --provider-model minimax-m2.7
Tested: bun run quality:gate --mode baseline --allow-live --provider-model volc-kimi-k2.6 --provider-model minimax-m2.7 (14 passed, 0 failed)
Not-tested: Desktop UI browser smoke and native Tauri release packaging remain outside this baseline expansion.
The desktop product needs a repeatable local gate that can prove the core Coding Agent loop still works after changes, not only that unit tests pass. This adds a quality-gate runner with PR, baseline, and release modes, structured reports, explicit quarantine metadata, and fixture-based live baseline cases that can run across provider/model targets.
Constraint: Existing check:pr and CI policy behavior must remain usable while the stronger baseline grows around it
Constraint: Default PR gates must not require real model credentials or provider quota
Rejected: Build a standalone QA platform first | too heavy before the baseline task shape is proven
Rejected: Keep unstable server exclusions hardcoded in run-server-tests | hides quarantine policy from reports and future review
Confidence: medium
Scope-risk: moderate
Directive: Expand baseline cases by adding focused fixtures and verifiers; do not make normal PR checks depend on live providers
Tested: bun test scripts/quality-gate/*.test.ts scripts/quality-gate/baseline/*.test.ts
Tested: bun run check:server
Tested: bun run quality:gate --mode baseline --allow-live --provider-model 2944f963-ce75-45b7-bac1-6e4f57df0970:kimi-k2.6:volc-kimi-k2.6 --provider-model 9c78d3df-7fb5-44c7-8436-3a41c3a59231:MiniMax-M2.7-highspeed:minimax-m2.7
Not-tested: desktop UI browser smoke and native release mode in this commit
Desktop failures were previously hard to debug from issue reports because server-side and CLI startup details were only partially visible in the UI. This adds a dedicated cc-haha diagnostics store with sanitized structured events, runtime error summaries, a Settings diagnostics view, and an exportable bundle that users can attach to reports.
Constraint: Diagnostic exports must not include chat content, file contents, full environment variables, API keys, bearer tokens, cookies, or OAuth tokens.
Rejected: Export raw server logs | easier to debug but too likely to leak secrets and private workspace data.
Rejected: Keep diagnostics only in transient UI errors | still leaves maintainers unable to diagnose later GitHub issues.
Confidence: high
Scope-risk: moderate
Directive: Do not add raw transcript, prompt, attachment, or environment dumps to diagnostics without a separate privacy review.
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/diagnostics-service.test.ts
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/conversation-service.test.ts
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/conversations.test.ts
Tested: cd desktop && bun run test src/__tests__/diagnosticsSettings.test.tsx --run
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: agent-browser E2E on local server/dev UI for CLI startup failure, provider test failure, diagnostics tab, copy summary, export bundle, and tar/secret scan
Not-tested: Destructive clear-logs button in browser E2E; local deletion was intentionally not clicked.
Large desktop histories were making session discovery parse every JSONL
before pagination, while automatic title updates could still overwrite
manual names during resumed sessions. This keeps listing bounded to the
requested page, preserves custom titles, and blocks deleted placeholder
sessions from being recreated by prewarm startup.
Constraint: Desktop session storage remains JSONL-compatible with the CLI
Rejected: Virtualize the sidebar in this patch | does not fix backend JSONL parsing cost
Rejected: Disable title generation globally | would regress useful titles for unnamed sessions
Confidence: high
Scope-risk: moderate
Directive: Do not reintroduce all-file JSONL parsing on /api/sessions list paths without a heavy-session benchmark
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/title-service.test.ts src/server/__tests__/sessions.test.ts
Tested: ANTHROPIC_API_KEY=test-key bun test src/server/__tests__/conversations.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: heavy local preview with 240 sessions, 320 messages each, and 40 restored tabs
Not-tested: native packaged desktop runtime under Windows with the same heavy fixture
Related: https://github.com/NanmiCoder/cc-haha/issues/237
Related: https://github.com/NanmiCoder/cc-haha/issues/248
The fix was developed and UI-verified in a detached Codex worktree, then merged locally so main carries the same tested request-shape behavior.
Constraint: User requested local main integration without pushing
Confidence: high
Scope-risk: narrow
Tested: git status before merge was clean
Tested: merged commit verification retained in history
Not-tested: Post-merge full suite
DeepSeek-compatible Anthropic endpoints reject requests that combine an explicit disabled-thinking block with an effort value. The desktop UI can create that shape when users disable thinking and keep medium effort selected, so the request builder now omits effort whenever it will send explicit disabled thinking.
Constraint: DeepSeek-compatible Anthropic endpoints reject disabled thinking with effort
Rejected: Only patch Desktop provider settings | hidden title and side request paths still share the request builder
Confidence: high
Scope-risk: narrow
Directive: Keep explicit disabled-thinking providers from sending effort unless the upstream contract changes
Tested: UI repro on pre-fix DeepSeek provider path reproduced the 400
Tested: desktop/scripts/e2e-deepseek-thinking-ui-agent-browser.sh
Tested: bun test src/utils/__tests__/thinking.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/title-service.test.ts
Tested: git diff --check
Not-tested: Real DeepSeek API key live call
The session inspector reused a one-off light palette, so /status, /cost,
and /context could render bright panels inside the dark desktop shell.
This moves the inspector and MCP switch control onto theme-scoped tokens
while preserving the existing light-theme look.
Constraint: Desktop dark mode must keep the existing surface hierarchy and avoid changing global brand colors.
Rejected: Recolor the shared Material palette | too broad for a component-specific regression.
Confidence: high
Scope-risk: narrow
Directive: Keep slash inspector surfaces on semantic theme tokens; do not reintroduce fixed light hex classes.
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test src/__tests__/pages.test.tsx src/__tests__/mcpSettings.test.tsx
Tested: cd desktop && bun run build
Tested: agent-browser screenshots for /status, /usage, /context, and MCP settings on http://127.0.0.1:5184/
Pull requests need a deterministic way to show changed areas, required checks, missing-test signals, and CLI-core risk before review. This adds a path-based policy gate, local impact reporting, PR triage labels/comments, and reusable check scripts so reviewers can evaluate blast radius without trusting contributor claims.
Constraint: CLI core should remain effectively frozen unless a maintainer explicitly overrides it.
Constraint: Default PR checks must be safe for external forks and avoid live model/provider calls.
Rejected: Run live provider tests on every PR | secrets, cost, network, and vendor instability would make the gate noisy and unsafe.
Rejected: Use Dosu as the merge gate | AI review is useful for risk explanation, but deterministic Actions must own blocking checks.
Confidence: high
Scope-risk: moderate
Directive: Keep real model/provider smoke tests in maintainer-controlled workflows; do not make them required for untrusted PRs.
Tested: bun run check:impact
Tested: bun run check:policy
Tested: ruby YAML parse for PR workflows
Tested: git diff --check
Tested: bun run check:native
Tested: npm run docs:build
Tested: bun run scripts/pr/run-server-tests.ts
Tested: bun run check:adapters
Tested: bun run check:desktop
Not-tested: GitHub-hosted pull_request_target label/comment execution before opening this PR
The release script regenerated Cargo.lock after Tauri 2.11 became available, while the desktop Bun lock still resolves @tauri-apps/api and CLI to 2.10.1. Tauri's build preflight rejects that major/minor mismatch on every platform, so the Rust Tauri release stack is now pinned to the 2.10 combination already used by the previous successful release.
Constraint: v0.1.9 must keep the existing desktop Bun lock and JS Tauri packages at 2.10.1
Constraint: scripts/release.ts runs cargo generate-lockfile during release preparation
Rejected: Upgrade JS @tauri-apps packages during the release fix | larger dependency surface and unnecessary for the failed workflow
Rejected: Pin only the tauri crate | cargo still selected tauri-runtime 2.11.0, causing Rust API type mismatches
Confidence: high
Scope-risk: narrow
Directive: Keep Rust and JS Tauri major/minor versions aligned before moving release tags
Tested: gh run view 25217609687 --log-failed
Tested: cd desktop/src-tauri && cargo generate-lockfile
Tested: cd desktop && bunx tauri build --target aarch64-apple-darwin --config src-tauri/tauri.release-ci.json --no-bundle
Tested: cd desktop/src-tauri && cargo check
Not-tested: Full GitHub Actions matrix after retag
The release collects the post-v0.1.8 desktop workspace manager work, provider compatibility fixes, WebSearch fallback support, and desktop lifecycle hardening into a tagged GitHub Actions release.
Constraint: GitHub Release body is sourced from release-notes/v0.1.9.md in the tagged commit
Constraint: The release script owns version bumps for desktop/package.json, Tauri config, Cargo.toml, and Cargo.lock
Rejected: Push the script-generated generic release commit | it would violate the repository Lore commit protocol
Confidence: high
Scope-risk: narrow
Directive: Do not move v0.1.9 without rerunning the release preflight and verifying the tag commit contains release-notes/v0.1.9.md
Tested: bun run scripts/release.ts 0.1.9 --dry
Tested: bun run scripts/release.ts 0.1.9
Tested: cd desktop/src-tauri && cargo check
Not-tested: GitHub Actions release workflow before tag push
The chat timeline lost per-turn changed file cards when the visible user message ids did not match persisted transcript ids, and sessions without SDK file-history snapshots had no fallback source for turn changes. Match live cards by stable user-message index when needed and derive checkpoint previews from transcript tool calls when snapshots are absent.
Constraint: Right-side workspace changes already derive from transcript tool calls, so chat checkpoint data must remain consistent with that source.
Rejected: Force a history reload after every turn | would hide the id mismatch but add churn and still not cover transcript-only sessions.
Confidence: high
Scope-risk: moderate
Directive: Keep snapshot checkpoints as the preferred source, and use transcript extraction only as the compatibility fallback.
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: bun test src/server/__tests__/workspace-service.test.ts
Tested: cd desktop && bun run test src/components/chat/MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test
Tested: git diff --check
Not-tested: Browser E2E against a live model session.
The desktop workspace panel and chat transcript were mixing project-level file state with per-turn session history, which made rewind, file attachment, and changed-file previews brittle across multi-turn and historical sessions. This keeps turn checkpoints durable in the transcript, makes workspace refreshes happen at the right lifecycle points, and hardens long file previews without blocking the UI.
Constraint: Right-side workspace changes are project working-tree state, while chat turn cards are session checkpoint state.
Rejected: Treat every changed-file panel entry as session-local | new sessions must still reveal existing dirty project files.
Confidence: high
Scope-risk: moderate
Directive: Do not couple global workspace status to session checkpoint cards without preserving both product meanings.
Tested: cd desktop && bun run test src/components/workspace/WorkspacePanel.test.tsx
Tested: cd desktop && bun run lint
Tested: git diff --check
Tested: cd desktop && bun run test
Not-tested: Packaged Tauri runtime smoke test
The WebSearch settings footer placed explanatory copy and the save action in one flex row. On narrower dark-mode layouts, the long localized hint could squeeze the button enough for Chinese text to wrap vertically.
Move the action onto its own right-aligned row and give the button a stable minimum width so the layout remains readable across localized settings screens.
Constraint: Settings screen must support Chinese dark-mode copy without vertical button text.
Rejected: Only widening the button in the same flex row | the hint text can still consume the row and compress the action.
Confidence: high
Scope-risk: narrow
Directive: Keep localized action buttons out of compressible text rows unless the container has explicit width guarantees.
Tested: cd desktop && bun run lint
Tested: agent-browser visual check in light and dark settings pages
The desktop start screen can already collect a project directory before the first chat turn, but workspace management is intentionally session-scoped. Creating a draft session immediately after project selection keeps the file manager, changed-file view, runtime selection, and terminal toolbar on the same path users see after sending the first message.
Constraint: Workspace file management state is keyed by session id.
Rejected: Add a separate non-session workspace mode | it would duplicate panel state and create a second lifecycle to maintain.
Confidence: high
Scope-risk: narrow
Directive: Keep workspace management session-scoped; create or reuse a session before exposing the workspace panel.
Tested: cd desktop && bun run test -- TabBar.test.tsx EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Native Tauri folder dialog manual smoke test.
Native Anthropic web search is only reliable for Claude-family model names,
while many configured providers either do not implement the server tool schema
or reject it through proxy layers. This routes WebSearch through a single
resolver, adds Tavily and Brave fallbacks, and exposes provider key setup in
the desktop settings page.
Constraint: Third-party Anthropic-compatible endpoints may reject web_search_20250305 even when the model name is Claude-like
Constraint: Non-Claude models still need a usable WebSearch path when users configure an external search provider
Rejected: Gate native WebSearch by base URL | third-party Claude proxies can support it and official-looking URLs are not the real capability boundary
Rejected: Always expose Anthropic native WebSearch | unsupported providers loop on schema or tool errors
Confidence: high
Scope-risk: moderate
Directive: Keep WebSearch capability resolution centralized in WebSearchTool/backend.ts before adding more search providers
Tested: bun test src/tools/WebSearchTool/backend.test.ts
Tested: cd desktop && bun run test -- generalSettings.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: agent-browser Settings E2E for Tavily/Brave links and settings persistence
Tested: live Tavily and Brave fallback searches returned results using transient keys
Not-tested: automatic LLM decision to invoke WebSearch end-to-end against a paid model session
Desktop users can now disable thinking for new sessions, and Anthropic-compatible providers that opt in receive explicit disabled-thinking requests across main turns, side queries, and AI title generation.
Constraint: DeepSeek/Kimi/GLM Anthropic-compatible endpoints need a non-thinking path without scattering provider-specific logic through the CLI.
Rejected: Per-model if/else branches | centralized provider preset env keeps the native CLI surface smaller and easier to audit.
Confidence: high
Scope-risk: moderate
Tested: bun test src/utils/__tests__/thinking.test.ts src/server/__tests__/title-service.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/conversations.test.ts
Tested: cd desktop && bun run test -- generalSettings.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: agent-browser DeepSeek desktop E2E with transparent proxy captured main and title requests with thinking.type=disabled
Desktop sessions can carry persisted runtime provider selections long after the provider index changes. The server now validates those session-level and active provider ids before launching the CLI, falls back to a valid default path, and includes non-secret launch diagnostics in startup failure messages so future issue reports expose the server-side context.
Constraint: Desktop users often report only the visible chat error, not sidecar console logs
Rejected: Frontend-only cleanup of stale localStorage selections | does not protect API or reconnect paths and loses server-side evidence
Confidence: high
Scope-risk: narrow
Directive: Do not pass session-scoped provider ids into CLI startup without validating they still exist in providers.json
Tested: bun test src/server/__tests__/conversations.test.ts
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun test src/server/__tests__/conversation-service.test.ts
The macOS icon rendered smaller than neighboring Dock icons because the
source artwork left a 120px margin on the 1024px canvas. Scale the macOS
source to the expected 96px margin and regenerate the Tauri icon set so
bundled app assets stay in sync.
Constraint: macOS source artwork should fit a 1024px canvas with 96px icon spacing
Rejected: Adjust only the Dock screenshot or public preview asset | packaged icon.icns would remain undersized
Confidence: high
Scope-risk: narrow
Directive: Regenerate desktop/src-tauri/icons when changing app-icon-macos.svg
Tested: cd desktop && bun run lint
Tested: icon.icns expanded 1024px image reports 96px margins on all sides
Not-tested: Full macOS app rebuild
Windows users reported that the desktop window lost its size and position after restarting, and hidden windows could behave inconsistently when restored from taskbar/tray interactions. The Tauri shell now records the main window bounds in the app config directory, restores them on startup, and skips stale off-screen states when monitor layouts change.
Constraint: Avoid new dependencies for window state persistence
Constraint: Preserve existing hide-to-tray behavior for the main window
Rejected: Add tauri-plugin-window-state | larger dependency surface for one small main-window state file
Confidence: medium
Scope-risk: moderate
Directive: Keep monitor visibility checks when changing restore behavior so external-display removal does not strand the window off-screen
Tested: cargo test
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Windows taskbar manual reproduction; current machine is macOS
Not-tested: cd desktop && bun run test fails in existing frontend locale assertions unrelated to this Tauri change
The workspace panel now treats an empty changed-files status as a browsing case, so opening the panel shows the project tree instead of an empty changed-files view. The panel header controls were also reduced to keep the right workspace rail visually proportional in compact layouts.
Constraint: Users still need to manually inspect the empty changed-files view when they explicitly choose it.
Rejected: Always render the empty changed-files state | it makes the opened workspace feel broken when no files changed.
Confidence: high
Scope-risk: narrow
Directive: Do not auto-switch the workspace view after a user has explicitly selected a workspace view.
Tested: cd desktop && bun run test -- src/components/workspace/WorkspacePanel.test.tsx src/stores/workspacePanelStore.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Browser E2E visual screenshot pass was not rerun for this small header sizing change.
The chat surface now relies on the current-turn changes card for file rollback, so the older per-message hover rewind affordance was removed to avoid two competing rollback models.
Constraint: Current-turn undo still depends on the existing checkpoint rewind API.
Rejected: Keep both rewind entry points | duplicate rollback affordances make the product harder to explain and test.
Confidence: high
Scope-risk: moderate
Directive: Prefer adding rollback behavior through the current-turn change card instead of restoring per-message hover rewind.
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: cd desktop && bun run test
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Browser E2E scripts were updated but not executed in this commit.
The session workspace and current-turn undo surfaces now have regression coverage for multi-turn rollback semantics, stale current-turn cards, and dark theme workspace token usage.
Constraint: Workspace rollback must behave consistently for git and non-git session review flows.
Rejected: Rely on manual browser-only checks | they do not guard future regressions.
Confidence: high
Scope-risk: narrow
Directive: Keep rollback tests focused on target user message identity, not only visible index position.
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: cd desktop && bun run test -- src/components/chat/MessageList.test.tsx src/components/workspace/WorkspacePanel.test.tsx src/stores/workspacePanelStore.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Full live multi-turn assistant generation E2E across a fresh temporary project.
Workspace inspection now shares the same diff renderer between chat change cards and panel previews, supports scoped preview-tab closing, confirms checkpoint undo, resolves rewind checkpoints from the prompt cwd, and removes light-only workspace chrome so dark theme remains coherent.
Constraint: Workspace review must keep working for existing transcript sessions and non-git session-derived changes.
Rejected: Keep a separate chat diff preview | it drifted from panel rendering and dark theme behavior.
Confidence: high
Scope-risk: moderate
Directive: Keep chat and workspace diff rendering shared so theme and truncation behavior do not diverge again.
Tested: cd desktop && bun run test -- src/components/workspace/WorkspacePanel.test.tsx src/components/chat/MessageList.test.tsx src/stores/workspacePanelStore.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: Browser dark workspace preview at http://127.0.0.1:59468/ with src/App.jsx diff
Not-tested: macOS packaged app build
Workspace file preview is a local desktop surface, so image files should not be blocked by the text preview byte cap. Large text files now return a bounded preview instead of an unusable too-large state, while binary files remain explicitly unsupported.
Constraint: Avoid unbounded text payloads that can freeze the desktop renderer
Rejected: Remove all read limits | large generated files can still overload JSON transport and syntax rendering
Confidence: high
Scope-risk: moderate
Directive: Keep image preview detection before text-size limiting so local images remain renderable
Tested: bun test src/server/__tests__/workspace-service.test.ts
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test -- src/components/workspace/WorkspacePanel.test.tsx
Tested: cd desktop && bun run build
Not-tested: Full packaged macOS smoke after this commit
Workspace inspection was visible only as a side panel, while file restore still lived behind the older per-message rewind affordance. This adds a chat-flow change card for the completed turn, keeps undo routed through checkpoint rewind, and tightens the workspace split layout so narrow and fullscreen windows keep both chat and file preview usable.
Constraint: Current session file changes must work for non-Git directories when transcript tool edits are available
Constraint: Workspace preview must remain right-docked without horizontal overflow across narrow and wide desktop viewports
Rejected: Keep only hover rewind | users could not clearly see what the current turn changed before undoing it
Rejected: Use Git as the only changed-file source | many desktop sessions run in temporary or non-Git directories
Confidence: high
Scope-risk: moderate
Directive: Keep checkpoint rewind as the source of truth for undo semantics; workspace diffs are a preview surface, not the restore authority
Tested: bun test src/server/__tests__/sessions.test.ts src/server/__tests__/workspace-service.test.ts
Tested: cd desktop && bun run test -- src/components/chat/MessageList.test.tsx src/components/workspace/WorkspacePanel.test.tsx src/stores/workspacePanelStore.test.ts src/pages/ActiveSession.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: bun /tmp/cc-haha-layout-e2e/run-layout-e2e.mjs
Not-tested: Native Tauri packaged app window chrome behavior
Expose a workspace inspector for desktop sessions so users can browse the active project, preview files, inspect session-derived changes, and review diffs even when the work directory is not a git repository.
Constraint: The workspace view must work for temporary and non-git project directories.
Rejected: Rely only on git status | non-git sessions would lose the changed-files surface.
Confidence: medium
Scope-risk: moderate
Directive: Keep undo semantics separate from workspace browsing; checkpoint-backed rewind should remain the source of truth for rollback.
Tested: bun test src/server/__tests__/sessions.test.ts src/server/__tests__/workspace-service.test.ts
Tested: cd desktop && bun run test -- src/components/workspace/WorkspacePanel.test.tsx src/stores/workspacePanelStore.test.ts
Tested: cd desktop && bun run lint
Tested: git diff --check
Not-tested: Full desktop packaged app build after this commit
Add a bottom README callout that makes the GitHub star ask visible while embedding the live Star History chart in both Chinese and English docs.
Constraint: Keep bilingual README footer sections aligned.
Confidence: high
Scope-risk: narrow
Tested: Verified Star History SVG endpoint returns 200 image/svg+xml.
Not-tested: Full docs site build; README-only content change.
Most reports now come from desktop users, so the templates need to collect the operating system, desktop version, reproduction path, configuration screenshots, and logs before maintainers can diagnose failures.
Constraint: Desktop releases are the dominant support surface for external users
Rejected: Keep CLI-first fields at the top | it delays collecting the information needed for Windows and macOS desktop failures
Confidence: high
Scope-risk: narrow
Directive: Keep desktop OS and app version fields near the top of future issue template edits
Tested: git diff --check -- .github/ISSUE_TEMPLATE/bug_report.md .github/ISSUE_TEMPLATE/question.md
Not-tested: GitHub issue form rendering in browser
Closing the desktop window should not tear down the local server when users expect the app to keep serving background work. The Tauri layer now owns that lifecycle: close hides the main window, tray actions restore or quit, and true quit paths still stop sidecars.
Constraint: Issue #213 asks for Windows close-to-background behavior, and macOS should follow the same desktop lifecycle.
Rejected: Frontend-only close handling | native window close events and OS menu actions need one Tauri-owned path.
Confidence: high
Scope-risk: moderate
Directive: Do not remove the explicit quit marker unless all updater, tray, and app-exit paths are rechecked.
Tested: cargo fmt --manifest-path desktop/src-tauri/Cargo.toml --check
Tested: cargo check --manifest-path desktop/src-tauri/Cargo.toml
Tested: cargo test --manifest-path desktop/src-tauri/Cargo.toml
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Windows cargo check on this macOS machine; x86_64-pc-windows-msvc cross-check stopped in ring because the host lacks Windows C/MSVC headers.
Related: https://github.com/NanmiCoder/cc-haha/issues/213
The release note is now the GitHub Release source of truth, and the desktop version files have been moved together so the tag-triggered workflow can package the same version consistently.
Constraint: release-desktop.yml reads release-notes/v0.1.8.md from the tagged commit
Rejected: Push tag without a release commit | workflow requires version files and notes in the tag
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep the release notes filename aligned with the tag before pushing future releases
Tested: bun run scripts/release.ts 0.1.8 --dry
Tested: bun run scripts/release.ts 0.1.8
Not-tested: Remote GitHub Actions build before pushing the tag
The session inspector now asks the resumed CLI for a fast structural context estimate instead of forcing the full token-counting API path. This preserves live CLI state for system prompt, tools, MCP tools, skills, and messages while avoiding the 20s timeout that made historical sessions appear stuck or fall back to transcript-only estimates.
Constraint: Inspector requests must return quickly for third-party providers and historical resumed sessions.
Rejected: Increase the server timeout | the slow path can still block on provider token counting and keeps the UI feeling broken.
Confidence: high
Scope-risk: narrow
Directive: Keep interactive inspector context on the estimateOnly control path unless the UI explicitly supports a slow precise refresh.
Tested: bun test src/server/__tests__/conversations.test.ts -t 'structured session inspection|Sonnet 4.6 transcript usage'
Tested: cd desktop && bun run test -- --run src/i18n/index.test.tsx
Tested: cd desktop && bun run build
Tested: direct /api/sessions/:id/inspection?includeContext=1 returned live context in 0.046867s with System prompt, System tools, MCP tools, Messages
Tested: agent-browser automation verified no loading/error and visible System prompt/System tools/MCP tools/Messages
Not-tested: bare root tsc --noEmit, because current tsconfig scans existing desktop/src-tauri/target generated binary assets unrelated to this change
Session inspection was coupling quick status and usage rendering to live context control requests, so a slow get_context_usage path could leave the desktop inspector stuck on a loading state. The desktop panel now loads basic inspection data first, renders a transcript-based context estimate immediately, and only asks for live context details as a background refinement.
The translation hook now returns a stable function per locale so effects that depend on translation do not reset and re-fetch after every render.
Constraint: Third-party provider sessions may not expose reliable live context capabilities through the control request path.
Rejected: Keep waiting on live get_context_usage for the context tab | it recreates the user-visible loading stall.
Rejected: Hardcode provider-specific context windows | provider capabilities are not always known from the desktop session record.
Confidence: high
Scope-risk: moderate
Directive: Do not make the inspector first render depend on live CLI control requests without a transcript or cached fallback.
Tested: bun test src/server/__tests__/conversations.test.ts -t "structured session inspection|Sonnet 4.6 transcript usage"
Tested: cd desktop && bun run test -- --run src/i18n/index.test.tsx
Tested: cd desktop && bun run build
Tested: git diff --check
Tested: agent-browser verified /context renders transcript estimate without Loading context data
Not-tested: Provider-specific true context-window discovery for every third-party vendor
Default desktop sessions with an active third-party provider were only passing the selected model into the CLI startup path. That allowed the child CLI to fall back to stale cc-haha settings env instead of the provider index, so the UI-selected provider could diverge from the key and endpoint used by the subprocess.
Route default sessions through the active provider id and make third-party Sonnet capability overrides explicit with a non-empty sentinel. This keeps provider runtime env sourced from providers.json and avoids treating third-party Sonnet models as first-party thinking-capable models.
Constraint: Third-party provider behavior is the product baseline for desktop users.
Rejected: Rely on synced cc-haha/settings.json env | it can be stale and caused provider/key routing mismatches.
Confidence: high
Scope-risk: narrow
Directive: Third-party desktop sessions must carry providerId into ConversationService; do not depend on global settings env for active providers.
Tested: bun test src/server/__tests__/conversations.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/provider-presets.test.ts src/utils/__tests__/thinking.test.ts
Tested: git diff --check