Bias the orchestrator toward delegating medium tasks (>2 steps or >1 file), reserving direct action for trivial work. Require restating relevant project rules (e.g. codegraph-first) inside sub-agent prompts, since read-only agents (Explore/Plan) run without project memory.
Tested: bun test conversations.test.ts (orchestration cases pass)
Confidence: high
Scope-risk: narrow
Tested:
- cd desktop && bun run test -- src/__tests__/pluginsSettings.test.tsx src/stores/pluginStore.test.ts --run --reporter=verbose --pool=forks --maxWorkers=1 --minWorkers=1
- bun run check:desktop
- git diff --check
Scope-risk: moderate
Confidence: high
Git writes upstream branch config when a worktree starts from origin/main. Use the already-resolved base SHA as the worktree start point so parallel agent worktrees do not race on shared .git/config.
Tested: bun test src/utils/__tests__/worktree.test.ts
Tested: real gpt-5.5 Sub2API run with four worktree-isolated agents
Not-tested: bun run check:server currently fails unrelated WebSocket restart/timeouts
Confidence: high
Scope-risk: narrow
方案3 (desktop, manual-guided): when compactions keep firing only a turn or two
apart — the same thrash the CLI circuit breaker trips on — chatStore now appends
a one-time visible system notice suggesting the user start a fresh session
(the prior summary stays in the current one). Detection lives in module-level
state (compactionThrashBySession) so PerSessionState is untouched; counts user
turns between compactions, suggests after 3 rapid ones, deduped per session and
reset on /clear. New i18n key chat.contextExhausted (en/zh/zh-TW/jp/kr).
Also includes in-progress orchestration/coordinator work on the same files
(orchestrationPrompt.ts, conversationService coordinatorMode --append-system-prompt,
ws handler/events, chatStore, ChatInput, sessionRuntimeStore, types/chat) —
committed together per request.
Tested:
- bunx vitest run desktop/src/stores/chatStore.test.ts (102 pass, incl. new
方案3 rapid-compaction suggestion + spread-out negative case)
- cd desktop && bun run lint (clean)
- get_diagnostics clean across changed server + desktop files
Not-tested: full bun run check:server / check:desktop gates; pre-existing WS
runtime-restart integration tests are flaky in this env (CLI code 143).
Confidence: medium-high
Scope-risk: moderate
Third-party Anthropic-compatible relays reject oversized requests with a 400 context_too_large / 'exceeds the context window' body instead of Anthropic's 'prompt is too long' wording. That fell through to a raw API error with no recovery hint. Normalize it via a new isContextWindowExceededMessage() so getAssistantMessageFromError and classifyAPIError route it onto the existing prompt-too-long handling, surfacing the actionable 'Context limit reached / compact or clear' guidance (TUI) and businessError.prompt_too_long copy (desktop).
Tested: bun test src/services/api/errors.test.ts (4 pass)
Not-tested: full bun run check:server gate
Confidence: high
Scope-risk: narrow
Stop-generation set a 3s force-kill timer that called stopSession(sessionId). If the user switched provider/model in that window, the restart spawned a NEW CLI process under the same sessionId; the stale timer then SIGTERM-killed the new process during its startup grace window -> 'CLI exited during startup with code 143'.
Fix: tag each spawned process with an instanceId (sessionId#N). handleStopGeneration captures the live instanceId up front; the 3s fallback calls stopSessionInstance(sessionId, instanceId), which only kills when the current live process still matches that instance. A restart replaces the instance, so the stale timer becomes a no-op.
conversationService.ts: instanceId field + counter, getActiveInstanceId(), stopSessionInstance().
ws/handler.ts: handleStopGeneration uses the instance-guarded fallback.
conversations.test.ts: instance-guard regression tests.
Tested: bun test conversations.test.ts -t instance/stopSessionInstance (pass). Staged via hunk selection to exclude unrelated in-progress orchestration work that shares these files.
Confidence: high
Scope-risk: narrow
When the auto-compaction circuit breaker has tripped and the context is still over threshold, autoCompactIfNeeded now returns contextExhausted:true. This is the signal the desktop will use to suggest starting a fresh session (carrying the latest summary) instead of degrading silently. Pure predicate isContextExhausted() added + tested (15 pass). Desktop wiring (ws translation + chat suggestion card + new-session handoff) is intentionally not included here — those files currently carry unrelated in-progress changes.
Two context-management fixes (CLI/sidecar side):
1. Re-compaction loop (方案1+2). Auto-compaction previously only circuit-broke
on hard failures; a compaction that succeeded but left context still over
threshold reset the failure counter and re-compacted every turn, burning a
summary API call each time.
- autoCompact.ts: isIneffectiveCompaction() — when truePostCompactTokenCount
is still >= threshold, count it toward the existing circuit breaker instead
of resetting to 0; query.ts now honours that count on the success path.
- shouldThrottleAutoCompact() — suppress proactive autocompaction for a few
turns after a compaction, unless at the hard blocking limit (so we never
risk prompt-too-long by throttling).
2. Post-compact context meter stuck at ~100% (sessionService.ts). The transcript
context estimate counted the entire pre-compact history plus the summarization
call's huge input_tokens, pinning the indicator near full until the next turn.
Now the estimate is scoped to messages after the latest compact_boundary, with
a model fallback for the just-compacted/no-new-turn case. Non-compacted
sessions are unchanged.
Tested:
- bun test src/services/compact/autoCompact.test.ts (12 pass; throttle + ineffective predicates)
- bun test src/server/__tests__/conversations.test.ts -t "context" (6 pass incl. new compact-boundary scoping case)
Not-tested: 4 pre-existing WebSocket runtime-restart integration tests fail in this env (CLI subprocess code 143); unrelated to these changes.
Confidence: high
Scope-risk: moderate
- Update source: desktop/package.json publish.owner NanmiCoder -> 706412584 (electron-updater
now checks this fork's releases via app-update.yml). Also bump homepage and the legacy
Tauri updater endpoint to the fork.
- About page: GITHUB_REPO / issues / releases / changelog and the displayed repo name now
point to 706412584/cc-haha. Sidebar repo link and ActivitySettings profile subtitle too.
- Attribution: original author (NanmiCoder + Bilibili/Douyin/Xiaohongshu social links) is
preserved unchanged. Added a new "Fork maintainer" credit (706412584) with i18n keys
settings.about.forkMaintainer / forkMaintainerHint across en/zh/zh-TW/jp/kr.
Why: this is a self-maintained fork shipping its own builds; pointing the updater at upstream
risked overwriting custom builds with upstream releases and hid the fork's own releases.
Tested:
- bunx vitest run src/pages/ActivitySettings.test.tsx src/__tests__/generalSettings.test.tsx (59 pass)
- cd desktop && bun run lint (clean)
Not-tested: full verify (long-running)
Confidence: high
Scope-risk: moderate
Built-in agents:
- Add debugger, security-reviewer, refactor, migration, docs-writer, performance, commit-pr built-ins and register them in getBuiltInAgents().
Desktop:
- AskUserQuestion prompts no longer vanish silently: when an unanswered question card is cleared by turn end (message_complete / error) — e.g. a malformed question call — a visible system notice (chat.questionDropped) is appended instead. Added across en/zh/zh-TW/jp/kr.
Versioning:
- Bump desktop/package.json to 0.5.5 and add release-notes/v0.5.5.md.
Tested:
- bunx vitest run desktop/src/stores/chatStore.test.ts (99 pass, incl. dropped-question notice for message_complete + error, and no notice for non-AskUserQuestion)
- bun test src/tools/AgentTool/builtInAgents.test.ts (pass)
- cd desktop && bun run lint (clean)
- build:windows-x64 + package-smoke (PASS, Claude-Code-Haha-0.5.5-win-x64.exe)
Not-tested: full bun run verify / check:server (long-running)
Confidence: high
Scope-risk: moderate
These were accidentally committed in the previous catch-all commit. They're local tool artifacts (.codegraph index, .codegraph/daemon.pid runtime PID, personal IDE settings) that don't belong in the repo. Adding them to .gitignore and removing from tracking via git rm --cached so working copies stay intact.
ChatInput / SkillPickerMenu:
- + menu now has 4 entries: file, slash command, Skills, Plugins.
- Skills/Plugins open an inline picker above the composer (mirrors the file-search popover: ↑↓ navigate, Enter pick, Esc dismiss). Picking inserts a "@skill:<name>" / "@plugin:<name>" token at the cursor — visible to the user, also legible to the agent as "use this skill/plugin".
Queue "send now":
- sendQueuedMessageNow no longer aborts the running turn or promotes-and-waits — it just sends the message immediately. Removes the prior "Request was aborted" / code 143 retry loop caused by mid-turn stop_generation.
Theme follow-system persistence:
- settingsStore.loadSettings now honours a locally stored "system" theme over whatever concrete value the server last saw, since the server intentionally rejects "system". Fixes follow-system reverting to a concrete theme on every restart.
- uiStore.test.ts: updated the toggleTheme cycle test to include the system step (was a stale failure independent of these changes).
FileReadTool:
- Treat pages: "" as undefined ("read whole file") so the agent's empty-string slips don't trap the tool in a validation-error retry loop.
i18n:
- Added chat.openSkills / openPlugins / skillPicker.{title,empty} / pluginPicker.{title,empty} / sendNow across en / zh / zh-TW / jp / kr.
- Did NOT touch unrelated settings.skills.recommended.* / settings.plugins.* additions present in the working tree from another in-progress task.
Tested:
- bunx vitest run src/stores/chatStore.test.ts -t "message queue" (10 pass)
- bunx vitest run src/stores/settingsStore.test.ts src/stores/uiStore.test.ts (32 pass)
- bun run lint (desktop tsc --noEmit, clean)
- Windows package-smoke after build:windows-x64 (PASS)
Not-tested: full bun run check:desktop / check:server (long-running)
Confidence: high
Scope-risk: narrow
Built-in additions (always shipped):
- test-author: writes/runs tests for changed code, detects framework, reports changed-line coverage.
- code-reviewer: read-only static review, finds bugs/smells/security issues, ends with REVIEW: APPROVE | CHANGES_NEEDED.
Project-level addition under .claude/agents/:
- game-developer: covers Unity/Unreal/Godot and web JS engines. The system prompt forces engine-version detection (ProjectVersion.txt, *.uproject, project.godot, package.json), prefers querying real symbols already in the project (codegraph) over recalling APIs, and falls back to verifying uncertain APIs against the engine's official docs — to defend against API hallucinations across versions.
.gitignore: switched ".claude/" to ".claude/*" with explicit "!.claude/agents/**" so project agents can ship in the repo while user-private files like .claude/settings.json stay ignored.
Tests:
- builtInAgents.test.ts: asserts test-author + code-reviewer are registered, game-developer is NOT a built-in.
- gameDeveloperAgent.test.ts: parses .claude/agents/game-developer.md through the runtime parser and asserts the strengthened guidance (codegraph, official docs, ProjectVersion.txt) is present.
Tested: bun test src/tools/AgentTool/builtInAgents.test.ts src/tools/AgentTool/gameDeveloperAgent.test.ts (5 pass)
Not-tested: full bun run check:server (long-running)
Confidence: high
Scope-risk: narrow
v0.5.3's one-shot skip only blocked a single auto-drain, but a Stop emits
multiple idle events (message_complete + status idle); the second one still
drained one queued message and flipped the button back to running. Replace
the one-shot skip with a sticky queueDrainPaused flag: Stop pauses all
auto-drains until the user sends their next message (which clears it and
fires immediately, ahead of the queue). The queue then resumes FIFO on the
next idle. Bumps desktop app to 0.5.4 with release notes.
Tested: tsc --noEmit; Vitest chatStore 94 passed (incl. multi-idle stop /
priority message / queue resume); browser end-to-end (Stop keeps button at
Run with queue intact, priority send immediate, queue resumes); Windows x64
NSIS package + package-smoke PASS.
Scope-risk: narrow
Confidence: high
Stop no longer flushes the queue: a user-initiated Stop now skips exactly the
auto-drain triggered by its resulting idle (one-shot guard). The queue stays
intact, the next message the user sends fires immediately (priority, not
queued — even with items waiting), and the queue resumes FIFO on the next idle
after that turn. Queue enqueue/drain/edit mechanics are otherwise unchanged.
Also removes the Buy-Me-a-Coffee / donation section from README (zh/en).
Bumps desktop app to 0.5.3 with release notes.
Tested: desktop tsc --noEmit; Vitest chatStore 94 + pages/ActiveSession 43
passed (incl. stop-no-flush / priority-message / queue-resume case); Windows
x64 NSIS package + package-smoke PASS.
Scope-risk: narrow
Confidence: high
Desktop chat message queue (v0.5.2):
- Queue follow-up messages (Enter) while the agent is busy; FIFO auto-drain
on true idle. Collapsible, height-capped to-do panel above the composer so
it never inflates the composer. Per-item move-to-top/edit/delete/clear.
Never drains mid-stream, during tool execution, or while a permission
prompt is pending; Stop cancels the current turn but keeps the queue.
Per-session isolation. In-memory only (no persistence schema change).
Also included in this commit:
- Settings provider form: model-id comboboxes + fetch-models + per-slot
context-window auto-fill.
- Bundled skills: defineGoal, pdf, screenshot.
- Bump desktop app to 0.5.2 with release notes.
Tested: desktop tsc --noEmit; Vitest chatStore/pages/ActiveSession 136 passed
(incl. 7 queue tests); browser end-to-end queue smoke; Windows x64 NSIS
package + package-smoke PASS.
Not-tested: full check:desktop suite has pre-existing unrelated failures
(electron packaging, theme cycling, ThinkingBlock label); check:server.
Scope-risk: moderate
Confidence: medium
In-progress generations were interrupted when a set_runtime_config
arrived mid-stream: the handler immediately stopped and restarted the
CLI subprocess. Track per-session busy state from outbound status
events and queue the restart, applying it (with the latest override,
collapsing multiple toggles) once the session returns to idle.
Bumps desktop app to 0.5.1 with matching release notes.
Tested: desktop tsc --noEmit; Windows x64 NSIS package + package-smoke.
Not-tested: check:server, desktop Vitest.
Scope-risk: narrow
Confidence: medium
Commit 449ff0b0 changed completed thinking blocks to render the
'thinking.labelDone' title ("Thought"/"已思考") instead of the static
"Thinking" label, and updated ThinkingBlock.test.tsx but not
chatBlocks.test.tsx. The three inactive/default-state cases there still
queried the toggle button by /Thinking/ and failed. Match the new
done-state label (/Thought/); the active-state case is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Main added two TranslationKeys after this branch's base — 'thinking.labelDone'
(the "Thought" label shown after thinking completes) and
'slashCmd.agent.description' — which the jp/kr/zh-TW locale files did not yet
cover, so the Record<TranslationKey, string> contract failed tsc after merging
main. Add both keys to each new locale:
- jp: '思考完了' / '選択した Agent でプロンプトを実行'
- kr: '사고 완료' / '선택한 Agent로 프롬프트 실행'
- zh-TW: '已思考' / '使用指定 Agent 執行提示'
en/zh are unchanged. `tsc --noEmit` is now clean and the i18n + timestamp
suites pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Guard OpenAI-compatible proxy streaming bodies with the configured AI request timeout so a provider that emits partial SSE and then idles cannot leave proxy consumers waiting forever.
This is a proxy-level fix found while investigating #548; it does not claim to close the broader desktop interruption issue.
Tested: bun test src/server/__tests__/proxy-network-settings.test.ts
Tested: bun run check:server
Confidence: medium
Scope-risk: narrow
The desktop notification poller fired on mount, racing the bootstrap that
resolves the dynamic server URL and confirms /health. Its first requests hit
the uninitialized default base URL and failed with "Failed to fetch", logging
spurious client_api_request_failed warnings to the diagnostics panel.
Add a whenDesktopServerReady() signal resolved once initializeDesktopServerUrl
sets the base URL and the healthcheck passes, and gate the poller on it so it
only starts once the server is reachable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The thinking block title always rendered the static "思考中"/"Thinking"
label; isActive only toggled the animated dots. Once thinking finished
the dots disappeared but the in-progress text stayed. Switch the label
to "已思考"/"Thought" when the block is no longer active.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The models API derives its model list from ANTHROPIC_MODEL and the
ANTHROPIC_DEFAULT_{HAIKU,SONNET,OPUS}_MODEL env vars. A developer who exports
these for a custom provider (e.g. MiniMax) leaked them into the no-provider
fixture: the four collapsed to one model, the default model became the
custom one, and switched-model names fell back to the raw id — failing five
"available models" / "default model" assertions on that machine while passing
on clean CI.
Clear those four vars in the e2e setup and restore them in teardown, matching
the existing CLAUDE_CONFIG_DIR / CLAUDE_CLI_PATH isolation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Indent session rows under their project group and switch project folder icons between open and closed states when collapsed.
Tested: cd desktop && bun run test --run src/components/layout/Sidebar.test.tsx -t "groups sessions by project|collapses a project group"
Tested: cd desktop && bun run test --run src/components/layout/Sidebar.test.tsx
Tested: bun run check:desktop
Tested: Browser plugin smoke on http://127.0.0.1:3456/ confirmed first project open -> closed state, icon state, and pl-6 session indentation.
Confidence: high
Scope-risk: narrow
Normalize image blocks loaded from transcript history back into renderable data URLs and keep generated image metadata out of the visible user bubble. Image source metadata is applied in order so multi-image messages retain the correct paths and names.
Tested: bun run test -- --run src/stores/chatStore.test.ts
Tested: bun run check:desktop
Confidence: high
Scope-risk: narrow
(cherry picked from commit 82381e8d647fa19e20853a96b9681fb548c17f0a)
Close the native preview WebContentsView when the Electron renderer starts a top-level navigation so refreshed session pages cannot leave the in-app browser surface behind.
Fixes#680
Tested:
- bun run verify
Confidence: high
Scope-risk: narrow
When the signing secrets are absent, `CSC_LINK`/`APPLE_*`/`WIN_CSC_*` render
as empty strings. electron-builder treats a present (even empty) CSC_LINK as
"a certificate is configured", tries to load it, resolves the empty path to
the working dir and dies with "<workdir> not a file" — which broke the v0.4.0
release build.
Drop those env vars from the release build step so unsigned builds behave
exactly like the (already-green) dev build, which only sets
CSC_IDENTITY_AUTO_DISCOVERY=false. Add them back once an Apple Developer ID /
Windows cert is available.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Release is gated on the tag only. `bun run verify` runs on PRs and locally,
not at release time, so a failing quality gate no longer blocks publishing.
- release-desktop.yml: remove the quality-preflight job and its `needs`.
- release-workflow.test.ts: assert the release workflow does NOT run verify.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Intro now explains why we migrated: users reported macOS performance
issues and Windows behaviour diverging from the macOS dev environment;
Electron's bundled Chromium unifies the rendering layer at the cost of a
larger installer.
- Fixes section rebuilt from the real v0.3.2..HEAD commits, keeping the
upstream issue numbers (#665#653#351#672#678#671#681#658#651#620)
so they can be closed against this release.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Real-world testing showed the unsigned app just needs the original 0.3.2
one-liner after the "damaged" prompt (System Settings "Open Anyway" also
works). Drop the Sequoia / "don't trash it" / clear-DMG-first / script
walkthrough noise and match the historical release-note style.
- release-notes/v0.4.0.md: macOS = drag in + `xattr -cr ...`, Windows one
line, Linux kept short.
- docs/desktop/04-installation.md: same trim, remove duplicated FAQ entry.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unsigned builds ship manual downloads only, so the macOS auto-update zip
(~187MB) and the blockmaps just clutter the release page and dev artifacts.
- release-desktop.yml: stop attaching *.zip / *.blockmap to the GitHub
Release; users now see DMG/exe/AppImage/deb + install-macos-unsigned.sh.
- build-desktop-dev.yml: stop collecting *.zip / *.blockmap into the dev
artifact for the same reason.
- electron-builder still produces dmg+zip and the whole updater-metadata
pipeline (latest*.yml merge/validate) is untouched, so auto-update can be
re-enabled later by restoring the two asset globs.
- sync release-workflow.test.ts dev-artifact assertion accordingly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use frameless Electron chrome only on Windows and remove the native Windows application menu so the packaged app matches the previous Tauri-style desktop surface.
Add a Windows-only manual drag fallback for desktop drag regions, while excluding tab reorder targets and preserving macOS/Linux native chrome and menu behavior.
Tested: cd desktop && bun run test --run electron/services/menu.test.ts electron/services/windows.test.ts src/hooks/useElectronWindowDragRegions.test.tsx src/components/layout/TabBar.test.tsx src/components/layout/Sidebar.test.tsx src/lib/desktopHost/electronHost.test.ts electron/ipc/capabilities.test.ts
Tested: cd desktop && SKIP_INSTALL=1 bun run build:windows-x64
Tested: Computer Use Windows packaged app smoke verified no native menu, custom controls, drag regions, tab reorder, close-to-background, and deepseek-v4-pro provider response FINAL_WINDOWS_ELECTRON_REAL_PROVIDER_OK.
Not-tested: full bun run verify.
Constraint: keep custom frameless behavior scoped to win32 so macOS and Linux native chrome paths remain intact.
Confidence: high
Scope-risk: moderate
- Rewrite release-notes/v0.4.0.md to match the historical style (no emoji,
Highlights/Fixes/Notes), keep it user-facing only (drop release-process
notes), and correct Linux (supported since the Tauri builds, not new).
- README.md / README.en.md: replace Tauri references with Electron, list
macOS / Windows / Linux, and point first-launch approval to the guide.
- Rewrite docs/desktop/04-installation.md for Electron: Electron asset
names, Linux section, and the unsigned-macOS flow (clear the DMG quarantine
before double-clicking; drop the WebView2/right-click-open leftovers).
- install-macos-unsigned.sh: keep the same-folder DMG flow, no online download.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove maintainer-facing release workflow notes from the public release markdown and keep the macOS unsigned install guidance concise.
Tested: git diff --check
Tested: bun run check:docs
Confidence: high
Scope-risk: narrow
Bump the Electron desktop package version to 0.4.0, publish a macOS unsigned install helper, and let the release workflow continue when Developer ID signing is not configured.
Tested: bash -n desktop/scripts/install-macos-unsigned.sh
Tested: bun test scripts/pr/release-workflow.test.ts
Tested: bun run scripts/release.ts 0.4.0 --dry
Tested: git diff --check
Tested: bun run check:docs
Tested: bun run check:policy
Confidence: high
Scope-risk: moderate
Summarize the v0.3.2 to v0.4.0 Electron migration window and document the installer paths users should follow.
Tested: bun run scripts/release.ts 0.4.0 --dry
Tested: git diff --check
Tested: bun run check:docs
Confidence: high
Scope-risk: narrow
Keep development desktop artifacts limited to distributable archives and update
metadata so macOS workflow downloads do not duplicate the packaged app bundle.
The package smoke step still validates the unpacked app before upload.
Tested: bun test scripts/pr/release-workflow.test.ts
Tested: bun run check:policy
Confidence: high
Scope-risk: narrow
Match Electron Builder Linux output by accepting linux-*-unpacked directories,
treating AppImage blockmaps as optional, and validating release asset names
against the generated x86_64/amd64 and arm64 artifacts.
Tested: bun test scripts/quality-gate/package-smoke/index.test.ts
Tested: bun test scripts/pr/release-workflow.test.ts scripts/quality-gate/package-smoke/index.test.ts
Tested: bun run check:policy
Tested: bun run check:native
Tested: bun run verify
Confidence: high
Scope-risk: moderate
Ensure Electron Builder has the project URL and maintainer metadata required by Linux deb targets, and lock the fields with release workflow coverage.
Tested: bun test scripts/pr/release-workflow.test.ts
Tested: bun run check:policy
Tested: bun run check:native
Tested: bun run verify
Confidence: high
Scope-risk: narrow
Replace the local pre-push quality gate with a reminder-only hook, keep manual quality commands documented, and update the contract test to prevent reintroducing a blocking push gate.
Tested: bash .git/hooks/pre-push </dev/null
Tested: bun test scripts/git-hooks/install.test.ts scripts/pr/quality-contract.test.ts
Tested: bun run check:policy
Tested: bun run check:docs
Tested: git diff --check
Confidence: high
Scope-risk: narrow
Use OS-assigned ports for server integration tests and publish the actual Bun server port after startup, preventing local port collisions from failing server checks.
Tested: bun test src/server/__tests__/e2e/business-flow.test.ts
Tested: bun test src/server/__tests__/e2e/full-flow.test.ts src/server/__tests__/conversations.test.ts src/server/__tests__/tasks.test.ts src/server/__tests__/haha-openai-oauth-api.test.ts
Tested: bun run check:server
Confidence: high
Scope-risk: narrow
Use container queries for the activity summary grid so the Token usage panel responds to its own width instead of the full desktop viewport. This prevents loose medium-width layouts and over-compressed five-column cards when the settings page is shown with sidebars.
Tested:
- cd desktop && bun run test -- src/pages/ActivitySettings.test.tsx --run --reporter=verbose --pool=forks --maxWorkers=1 --minWorkers=1
- cd desktop && bun run test -- src/theme/globals.test.ts --run --reporter=verbose --pool=forks --maxWorkers=1 --minWorkers=1
- bun run check:desktop
- Electron smoke at 1180px and 900px against the local dev server
Not-tested:
- Coverage report; this is a presentation-only desktop UI change.
Confidence: high
Scope-risk: narrow