338 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
065a80580b Render scheduled task summaries as markdown
Scheduled task results can contain assistant-authored markdown, but the
runs panel previously displayed that content as plain pre-wrapped text.
Reusing the desktop markdown renderer keeps task summaries aligned with
chat and settings surfaces while adding a compact prose variant for the
narrow log panel.

Constraint: Desktop task logs need dense formatting without introducing a new markdown dependency
Rejected: Keep whitespace-pre-wrap summary text | markdown syntax remains visible in completed task runs
Confidence: high
Scope-risk: narrow
Directive: Keep scheduled run summary rendering on the shared MarkdownRenderer path so links, lists, inline code, and future markdown fixes stay consistent
Tested: cd desktop && bun run test src/components/markdown/MarkdownRenderer.test.tsx src/components/tasks/TaskRunsPanel.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: bun run check:desktop
Tested: agent-browser E2E against isolated CLAUDE_CONFIG_DIR with real backend and Vite UI; verified strong/li/code/link DOM output and no raw markdown bold markers
Not-tested: Tauri native packaged app shell
2026-05-09 22:43:00 +08:00
程序员阿江(Relakkes)
da477c2b4b Merge session title sanitation into main
Bring the detached worktree fix onto local main after verifying the title-generation regression path and local quality checks.

Constraint: The worktree commit was based on an older main commit, while local main already contained later chat scroll fixes.
Confidence: high
Scope-risk: moderate
Directive: Keep title sanitation shared across CLI, server, and desktop read paths.
Tested: bun run check:server
Tested: bun run check:desktop
Tested: bun run verify (7 passed, 1 failed on existing aggregate agent-utils coverage baseline)
Not-tested: live model title-generation smoke
2026-05-09 22:34:54 +08:00
程序员阿江(Relakkes)
179f79b794 fix: sanitize generated session titles
Slash-command and skill prompts can enter the title-generation path as internal XML breadcrumbs. The async title request previously treated that transport metadata as user prose, so a generated ai-title could persist raw command tags and override the normal session title.

This routes title sources and generated title output through a shared sanitizer, preserving user-visible command names and arguments while dropping unrelated internal XML metadata. Desktop fallback title rendering now applies the same cleanup so existing transcripts with bad ai-title entries recover on read.

Constraint: Session titles can be produced by both desktop server logic and the SDK generate_session_title control request.
Rejected: Only clean desktop session display | leaves CLI and remote title generation able to persist bad titles again
Confidence: high
Scope-risk: moderate
Directive: Keep generated-title input and persisted-title readback on the shared sanitizer; do not add a title path that reads command XML directly.
Tested: bun test src/utils/__tests__/sessionTitle.test.ts src/utils/__tests__/sessionTitleText.test.ts
Tested: bun run check:server
Tested: bun run check:desktop
Tested: bun run verify (7 passed, 1 failed on existing aggregate agent-utils coverage baseline)
Not-tested: live model title-generation smoke
2026-05-09 22:34:27 +08:00
程序员阿江(Relakkes)
50d4679f51 Merge chat scroll recovery into main
Bring the detached worktree fix into the local main line while preserving the newer main behavior that passes session context into interactive chat message blocks.

Constraint: Local main already contains six unpublished commits on top of origin/main
Constraint: Merge conflict only affected MessageList message rendering around sessionId propagation
Rejected: Overwrite main's MessageBlock call shape | would regress AskUserQuestion and permission interactions that need sessionId
Confidence: high
Scope-risk: moderate
Directive: Keep MessageBlock sessionId propagation when editing chat rendering; AskUserQuestion depends on it
Tested: cd desktop && bun run test -- MessageList.test.tsx
Not-tested: Full verify after merge; previous verify remains blocked by agent-utils global coverage baseline
2026-05-09 21:52:31 +08:00
程序员阿江(Relakkes)
6382115de9 fix: keep chat tabs from losing scroll context
Chat sessions need predictable navigation when users switch tabs or read history during streaming. This preserves each session's scroll position, defaults fresh sessions to the latest message, and adds a compact jump-to-latest affordance when auto-follow is paused.

The PR gate also exposed that provider-scoped scheduled tasks must force the sdk-cli entrypoint when launched through the sidecar, so the same change records that runtime contract and its regression assertion.

Constraint: Desktop chat should not force-scroll while the user is reading older messages
Constraint: Scheduled task provider env must not inherit stale parent model runtime values
Rejected: Persist scroll positions in localStorage | session scroll is transient UI state and should not survive app restarts
Confidence: high
Scope-risk: moderate
Directive: Do not remove the sdk-cli entrypoint marker from provider-scoped cron tasks without rerunning the sidecar launcher regression
Tested: cd desktop && bun run test -- MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/cron-scheduler-launcher.test.ts src/utils/__tests__/themeWords.test.ts
Tested: bun run check:desktop
Tested: bun run check:server
Tested: bun run check:native
Not-tested: bun run verify still fails on pre-existing agent-utils global coverage baseline below threshold
Not-tested: Chrome extension E2E blocked by Codex Chrome Extension communication timeout after plugin diagnostics passed
2026-05-09 21:51:34 +08:00
程序员阿江(Relakkes)
184323ba02 Merge AskUserQuestion multi-select fix into main
The detached desktop bugfix worktree contains the AskUserQuestion multi-select handling change, while local main already carries separate local commits. Merge instead of cherry-picking so main records the worktree integration point without dropping local-only history.

Constraint: Local main and the detached worktree had diverged
Rejected: Reset main to the worktree HEAD | would discard local main commits
Confidence: high
Scope-risk: narrow
Directive: Keep AskUserQuestion selection mode controlled by the explicit multiSelect marker
Tested: cd desktop && bun run test -- src/components/chat/AskUserQuestion.test.tsx src/components/chat/chatBlocks.test.tsx src/components/chat/MessageList.test.tsx
Tested: bun run check:desktop
Not-tested: Full root bun run verify after merge
2026-05-09 21:49:59 +08:00
程序员阿江(Relakkes)
60f69c2062 fix: respect AskUserQuestion multi-select markers
Desktop question prompts can carry CLI-provided multiSelect flags, so the answer UI now stores selections per question as arrays and only allows multiple checked options when that flag is true. The message renderer also passes the owning session id into permission UI so pending responses go back to the session that produced the prompt instead of whichever tab is active.

Constraint: AskUserQuestion input may arrive as either questions[] or single question shape
Rejected: Make all option questions multi-select | single-select prompts must remain constrained unless the CLI marks them multiSelect
Confidence: high
Scope-risk: narrow
Directive: Do not infer multi-select from option count; honor the explicit multiSelect flag
Tested: cd desktop && bun run test -- src/components/chat/AskUserQuestion.test.tsx src/components/chat/chatBlocks.test.tsx src/components/chat/MessageList.test.tsx
Tested: bun run check:desktop
Tested: Chrome/CDP smoke against /tmp/cc-haha-ask-user-real verified multi-select and single-select behavior
Not-tested: Chrome extension RPC path, which timed out in this environment despite native host checks passing
2026-05-09 21:48:16 +08:00
程序员阿江(Relakkes)
b31be5161c feat: support custom Computer Use Python interpreters
Computer Use setup could fail on machines where PATH discovery misses a valid Python installation, especially Windows or conda-style environments. Store an optional interpreter path, prefer it during environment checks and venv creation, and expose a desktop settings control for selecting or clearing it.

Constraint: Python discovery is environment-specific and cannot always be inferred from PATH.
Rejected: Continue falling back to PATH after an invalid custom path | hides a user-selected broken interpreter and makes diagnosis ambiguous.
Confidence: high
Scope-risk: moderate
Directive: Preserve unknown Computer Use config fields and keep blank interpreter paths normalized to automatic detection.
Tested: bun test src/utils/computerUse/preauthorizedConfig.test.ts src/server/__tests__/computer-use-python.test.ts src/server/__tests__/computer-use-api.test.ts
Tested: cd desktop && bun run test src/pages/ComputerUseSettings.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: Computer Use browser smoke saved /opt/homebrew/bin/python3 and backend persisted then reset pythonPath to null
Not-tested: Full bun run check:server; existing cron-scheduler-launcher test expects CLAUDE_CODE_ENTRYPOINT=sdk-cli but received undefined.
Related: https://github.com/NanmiCoder/cc-haha/issues/331
2026-05-09 21:46:11 +08:00
程序员阿江(Relakkes)
623f4a5848 chore: bump desktop version to v0.2.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 23:43:29 +08:00
Relakkes Yang
a0624eeb21 fix: restore Windows desktop notifications 2026-05-08 23:22:58 +08:00
程序员阿江(Relakkes)
f379a9928a fix: remove pr-checks lane and fix test env isolation
- Remove pr-checks lane from quality gate (not needed locally)
- Fix launcherRouting tests to pass explicit null envAppRoot to avoid CLAUDE_APP_ROOT pollution
- Fix cron-scheduler-launcher test: CLAUDE_CODE_ENTRYPOINT is correctly set to sdk-cli for scheduled tasks, update assertion and restore env var in cleanup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 21:00:06 +08:00
程序员阿江(Relakkes)
3794a9d9ef fix: surface worktree identity in session badge
The footer project chip previously kept showing only the source project and selected branch even after a session launched inside an isolated CLI worktree. That made an active worktree session look identical to a normal checkout, especially while agent tools were already operating under .claude/worktrees. The server now returns explicit worktree metadata from the session launch intent, and the desktop chip preserves the user-facing project and branch while appending the isolated worktree slug.

Constraint: CLI worktree branches are internal implementation details and should not replace the user-selected branch label.

Rejected: Show only the actual worktree git branch | it would expose worktree-desktop-* internals and make the business branch harder to read.

Confidence: high

Scope-risk: narrow

Directive: Keep normal checkout footer rendering unchanged; only add worktree identity when session metadata says isolation is enabled.

Tested: bun test src/server/__tests__/sessions.test.ts --test-name-pattern git-info

Tested: cd desktop && bun run test -- src/components/shared/ProjectContextChip.test.tsx

Tested: cd desktop && bun run lint

Tested: git diff --check
2026-05-08 18:08:30 +08:00
程序员阿江(Relakkes)
678ba18a6f fix: keep session git badge on the active CLI checkout
The chat footer previously read git-info from the persisted session file and refreshed only on tab changes. Repository launches can update the active CLI cwd after the composer has already rendered, so the footer could keep showing an older selected branch even while the running model was operating in the correct checkout.

Constraint: The active CLI process is the source of truth for a live session cwd
Rejected: Derive the footer branch only from persisted session metadata | metadata can lag behind startup and does not prove the current running cwd
Confidence: high
Scope-risk: narrow
Tested: bun test src/server/__tests__/sessions.test.ts --test-name-pattern "git-info should prefer"
Tested: cd desktop && bun run lint
Tested: git diff --check
2026-05-08 18:02:12 +08:00
程序员阿江(Relakkes)
b40ffb0714 feat: align desktop repository sessions with CLI worktrees
Desktop repository launches now defer isolated worktree creation until the
first user turn so the CLI owns worktree setup, cwd initialization, and
session metadata. The chat UI surfaces the pre-startup Git phase so users see
when a session is creating a worktree or switching a branch before model
output begins.

Constraint: Desktop must preserve the selected source checkout until a user actually sends a message
Constraint: CLI setup is the canonical owner for worktree creation and cwd initialization
Rejected: Create the worktree eagerly in the desktop session picker | it diverges from CLI session startup and creates worktrees before a conversation exists
Confidence: high
Scope-risk: moderate
Directive: Keep repository session startup routed through CLI worktree flags; do not reintroduce eager desktop worktree creation without testing transcript cwd and cleanup behavior
Tested: bun test src/server/__tests__/sessions.test.ts src/server/__tests__/conversation-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "worktree startup status"
Tested: cd desktop && bun run test -- src/pages/EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: git diff --check
Tested: CLI init-only native worktree smoke from feature/rail
Tested: agent-browser UI flow with MiniMax-M2.7-highspeed in a /tmp repository
2026-05-08 16:08:58 +08:00
程序员阿江(Relakkes)
649c24b9d2 Merge commit 'a31b304' 2026-05-08 13:45:16 +08:00
程序员阿江(Relakkes)
a31b3045fd Preserve explicit desktop runtime selection
Desktop sessions can prewarm before the user-selected runtime reaches the server, and an empty-session draft could previously persist an inferred default runtime as if the user had explicitly selected it. The fix keeps new-session defaults implicit while preserving explicit draft selections, and waits for queued runtime restarts before the first turn is delivered to the CLI process.

Constraint: Runtime selection is session-scoped and may arrive while prewarm or first-turn startup is already in flight

Rejected: Always persist the current default provider/model into new sessions | this masks whether the user actually selected a runtime and can launch stale providers

Confidence: high

Scope-risk: moderate

Directive: Do not send user turns across pending runtime restarts without re-checking the session runtime override

Tested: bun test src/server/__tests__/conversations.test.ts

Tested: cd desktop && bun run test -- src/pages/EmptySession.test.tsx

Tested: git diff --check
2026-05-08 13:45:02 +08:00
程序员阿江(Relakkes)
592ace93d0 fix: avoid treating normal folders as repository warnings
Non-Git folders are valid launch targets for desktop sessions, so the composer should not render them as an inline repository warning. The branch and worktree controls remain hidden outside Git repositories while server-side repository validation still protects actual branch-launch requests.

Constraint: Non-Git directories must remain usable as ordinary session workdirs.
Rejected: Keep the inline not-Git warning | it reads like an error even though the user can continue normally.
Confidence: high
Scope-risk: narrow
Directive: Keep dirty-worktree and checked-out-branch warnings visible because those still require a launch-mode decision.
Tested: cd desktop && bun run test -- --run src/pages/EmptySession.test.tsx src/components/chat/ChatInput.test.tsx
Tested: bun run check:desktop
Tested: git diff --check -- desktop/src/components/shared/RepositoryLaunchControls.tsx desktop/src/pages/EmptySession.test.tsx desktop/src/i18n/locales/en.ts desktop/src/i18n/locales/zh.ts
Not-tested: Native Tauri packaged window visual check
2026-05-08 12:41:34 +08:00
程序员阿江(Relakkes)
eadbd4be14 Keep newly activated desktop tabs visible
When the tab strip overflows, newly opened sessions were active but could remain outside the visible horizontal viewport. The tab bar already owns element refs for drag and close behavior, so the focused fix scrolls the active tab into view after activation and refreshes overflow controls on the next frame.

Constraint: Preserve existing tab ordering, drag behavior, and close-button affordances.
Rejected: Reorder new sessions to the left | changes established tab order and makes history harder to scan.
Confidence: high
Scope-risk: narrow
Directive: Keep active-tab visibility behavior in TabBar so all activation paths share it.
Tested: cd desktop && bun run test -- TabBar
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: agent-browser overflow smoke with six tabs confirmed active Untitled Session fullyVisible=true
Not-tested: Full bun run verify gate.
2026-05-08 12:41:04 +08:00
程序员阿江(Relakkes)
8134436562 Fix macOS build artifacts to keep notification identity stable
The notification bridge fix was correct, but the local macOS build script still left Tauri's raw app and DMG outputs available with the executable's ad-hoc signing identifier. Opening that raw artifact made macOS treat notification authorization as a different app identity, so the UI could fall back to the unsupported environment state even though the canonical output worked.

Normalize the Tauri-produced app bundle in place before copying it to the canonical output, then replace the Tauri-generated DMG with the rebuilt canonical DMG. This keeps every path printed by the build script on the same bundle identity and prevents testers from accidentally opening the unstable raw artifact.

Constraint: Local test builds use ad-hoc signing, but macOS notification authorization still depends on stable app identity.
Rejected: Only tell testers to open canonical output | the script still printed and preserved misleading usable-looking artifacts.
Confidence: high
Scope-risk: narrow
Directive: Keep Tauri raw app and canonical app signing identifiers aligned before reporting build artifacts as runnable.
Tested: bash -n desktop/scripts/build-macos-arm64.sh
Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh
Tested: codesign -dv --verbose=4 shows com.claude-code-haha.desktop for both target bundle app and canonical app
Tested: hdiutil verify target DMG and canonical DMG
Tested: Computer Use opened target bundle app and verified Settings -> General shows notifications as authorized.
Not-tested: Fresh first-time notification prompt after resetting macOS notification permissions for this bundle id.
2026-05-08 11:11:20 +08:00
程序员阿江(Relakkes)
6b55ace2d7 Prevent model selector clipping in task modals
The model selector dropdown was rendered inside the modal scroll container. When the task form sat near the top of the dialog, the upward-opening menu could be clipped by the container and become impossible to scroll into view. The selector now portals the menu to the document body and positions it against the trigger with viewport-aware fixed coordinates.

Constraint: The same selector is used by chat/session controls and scheduled-task controls, so the fix must preserve existing runtime selection behavior.
Rejected: Increase modal scroll padding | still leaves the dropdown coupled to a clipping parent and breaks in other overflow containers.
Confidence: high
Scope-risk: narrow
Directive: Keep floating selector content outside scroll-clipping parents; update viewport positioning if the modal layout changes.
Tested: cd desktop && bun run test -- src/components/controls/ModelSelector.test.tsx src/components/tasks/NewTaskModal.test.tsx
Tested: bun run check:desktop
Tested: git diff --check
Not-tested: Manual packaged desktop app check.
2026-05-08 10:43:09 +08:00
程序员阿江(Relakkes)
ed2595b1c7 Merge scheduled task provider runtime support 2026-05-08 09:49:27 +08:00
程序员阿江(Relakkes)
7696e21dc2 Support provider runtimes for scheduled tasks
Scheduled tasks used the model selector in model-only mode, so a task could store a third-party model id without the provider runtime needed to execute it. The desktop task editor now stores the selected provider with the model, and the scheduler injects the same provider-scoped runtime env that desktop sessions use before launching the sidecar.

Constraint: Scheduled tasks run outside an active desktop websocket session, so provider runtime must be serialized on the task itself.
Rejected: Reuse session runtime localStorage for tasks | scheduled executions can run long after the UI session is gone.
Confidence: high
Scope-risk: moderate
Directive: Keep task execution provider env isolated from inherited process env; stale parent ANTHROPIC_* values must not override task provider choices.
Tested: cd desktop && bun run test -- src/components/tasks/NewTaskModal.test.tsx src/components/controls/ModelSelector.test.tsx
Tested: bun test src/server/__tests__/scheduled-tasks.test.ts src/server/__tests__/cron-scheduler-launcher.test.ts
Tested: bun run check:desktop
Tested: bun run check:server
Tested: git diff --check
Not-tested: Live third-party provider API call; covered by sidecar launch integration with provider proxy env.
2026-05-08 09:49:16 +08:00
程序员阿江(Relakkes)
7796fec691 fix: request macOS notifications from the main queue
The Rust command now keeps the synchronous bridge wait off the invoke thread, but the Objective-C bridge still initiated UserNotifications authorization from that worker. In a packaged app that path could fail immediately and the settings UI collapsed the error into an unsupported environment.

Start notification settings reads, authorization requests, and delivery submissions on the macOS main queue while keeping the blocking wait on the worker thread. This preserves foreground-safe notification delivery without deadlocking the UI or losing the system permission prompt.

Constraint: UserNotifications APIs are UI-adjacent and should be initiated on the app main queue.
Rejected: Only change the unsupported status copy | it would keep the authorization path broken.
Confidence: high
Scope-risk: narrow
Directive: Keep UserNotifications calls main-queue initiated while the synchronous wait remains off the main thread.
Tested: cd desktop/src-tauri && cargo test
Tested: bun run check:native
Tested: SKIP_INSTALL=1 ./scripts/build-macos-arm64.sh
Tested: codesign --verify --deep --strict --verbose=2 desktop/build-artifacts/macos-arm64/Claude Code Haha.app
Tested: hdiutil verify desktop/build-artifacts/macos-arm64/Claude Code Haha_0.2.1_aarch64.dmg
Tested: Computer Use opened /Users/nanmi/workspace/myself_code/claude-code-haha/desktop/build-artifacts/macos-arm64/Claude Code Haha.app and verified Settings -> General shows notifications as authorized after disable/enable.
Not-tested: Fresh first-time system notification prompt on a machine that has never granted this bundle identifier.
2026-05-08 09:43:25 +08:00
程序员阿江(Relakkes)
de9d044bdb fix: keep macOS notification bridge off the invoke thread
The macOS notification bridge synchronously waits for UserNotifications callbacks. Running that wait on the Tauri command caller can block the callback path and make permission reads time out, which the UI reports as an unsupported environment.

Route the bridge calls through a blocking worker so permission reads, permission prompts, and delivery checks do not stall the app thread that needs to service native notification callbacks.

Constraint: UserNotifications permission and delivery APIs complete asynchronously through macOS callbacks.
Rejected: Change the settings status label only | it would hide the failed native permission read without fixing notification delivery.
Confidence: high
Scope-risk: narrow
Directive: Keep macOS notification bridge calls off the invoke caller thread unless the Objective-C bridge becomes fully async.
Tested: cd desktop/src-tauri && cargo test
Tested: bun run check:native
Tested: cd desktop && bun run test --run src/lib/desktopNotifications.test.ts src/__tests__/generalSettings.test.tsx
Tested: SKIP_INSTALL=1 ./scripts/build-macos-arm64.sh
Tested: codesign --verify --deep --strict --verbose=2 desktop/build-artifacts/macos-arm64/Claude Code Haha.app
Tested: hdiutil verify desktop/build-artifacts/macos-arm64/Claude Code Haha_0.2.1_aarch64.dmg
Not-tested: Manual click-through of the newly built .app notification settings screen.
2026-05-08 09:27:20 +08:00
程序员阿江(Relakkes)
57a77453ed fix: isolate desktop provider runtimes per session
Desktop sessions can run against different saved providers at the same time, so the runtime selection must remain scoped to the session from WebSocket startup through the CLI request path. This adds parallel-session regression coverage, a browser-driven fake-provider E2E, and refreshes idle connected sessions after provider saves so stale provider edits are reapplied without disturbing active turns.

Constraint: Desktop provider credentials must stay session-scoped and must not leak across concurrent CLI child processes
Rejected: Rely on provider test connectivity alone | it does not exercise the desktop WebSocket, session runtime, or CLI request path
Confidence: high
Scope-risk: moderate
Directive: Do not change runtime selection persistence or provider env injection without rerunning the parallel provider browser E2E
Tested: cd desktop && bun run test src/stores/providerStore.test.ts src/stores/chatStore.test.ts
Tested: CLAUDE_CONFIG_DIR=/Users/nanmi/.claude bun test src/server/__tests__/conversations.test.ts --timeout 30000
Tested: desktop/scripts/e2e-parallel-providers-agent-browser.sh
Tested: bun run quality:smoke --provider-model custom:main:custom-main --provider-model minimax:main:minimax-main
Tested: cd desktop && bun run lint
Tested: git diff --check
Not-tested: bun run verify passes fully; coverage lane still fails on the existing agent-utils ratchet below baseline
2026-05-08 08:53:05 +08:00
程序员阿江(Relakkes)
0a4f2ae6b6 fix(desktop): keep Computer Use toggles stable
Settings refreshes can complete after the user changes Computer Use authorization state. The page now ignores stale config reads once a local mutation has happened, so enablement and grant controls no longer visually roll back and require a second operation.

Constraint: Computer Use config is shared between the desktop settings page and runtime MCP exposure.
Rejected: Refetch after every save | still allows older in-flight reads to overwrite newer local intent.
Confidence: high
Scope-risk: narrow
Directive: Do not apply async settings snapshots after a newer local authorization mutation without a freshness check.
Tested: cd desktop && bun run test -- src/pages/ComputerUseSettings.test.tsx
Tested: bun run check:desktop
Tested: bun run check:coverage
Not-tested: bun run verify is blocked by existing path-aware policy labels for broader dirty scope.
2026-05-07 21:33:33 +08:00
程序员阿江(Relakkes)
f01ba4eda6 Merge repository launch context controls into main
The detached worktree contains the session composer repository controls work: preserving launch context across empty chat tabs, exposing branch and worktree selection under the composer, tightening long-label truncation, and validating the launch paths with desktop tests. Main had moved forward independently, so this records the integration as a merge commit instead of rewriting either side.

Constraint: Merge into local main only; do not push or alter remote state.
Rejected: Rebase the detached worktree onto main | it would rewrite the already reviewed local commit chain and was unnecessary after a clean merge.
Confidence: high
Scope-risk: moderate
Directive: Keep repository context controls under the composer as a single-line rail; long repo or branch labels must truncate inside their own controls.
Tested: bun run check:desktop
Not-tested: Native Tauri packaged window visual check
2026-05-07 20:13:31 +08:00
程序员阿江(Relakkes)
5c738db3af fix: keep launch context rail on one line
Long branch names should be clipped inside the branch selector instead of forcing the repository context rail onto a second row. The rail now stays nowrap, the branch selector owns truncation, and the worktree mode selector keeps its readable fixed footprint.

Constraint: Preserve the existing composer and repository context layout shape.
Rejected: Let the rail wrap on long branch names | it creates the broken two-line state shown in the desktop composer.
Confidence: high
Scope-risk: narrow
Directive: Long repository or branch labels must truncate inside their own controls rather than changing the rail height.
Tested: cd desktop && bun run test -- --run src/pages/EmptySession.test.tsx src/components/chat/ChatInput.test.tsx src/components/shared/DirectoryPicker.test.tsx
Tested: bun run check:desktop
Tested: agent-browser selected a long branch on http://localhost:4790 and verified rail height 53px, branch width 260px, no horizontal overflow; screenshot /tmp/cc-haha-launch-rail-long-branch-nowrap.png
Not-tested: Native Tauri packaged window visual check
2026-05-07 19:59:19 +08:00
程序员阿江(Relakkes)
5675539ef0 fix: make worktree launch mode selectable
The worktree control is a mode choice, so it should behave like the branch selector instead of a hidden toggle. This adds a compact dropdown with current and isolated worktree options while preserving the existing launch layout and isolation guard.

Constraint: Keep the composer context rail layout unchanged.
Rejected: Keep the single-click toggle | the interaction hid the available modes and made the state harder to reason about.
Confidence: high
Scope-risk: narrow
Directive: Worktree mode must stay an explicit selection surface, not a hidden toggle.
Tested: cd desktop && bun run test -- --run src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx src/components/shared/DirectoryPicker.test.tsx
Tested: bun run check:desktop
Tested: agent-browser worktree dropdown desktop and mobile screenshots at /tmp/cc-haha-worktree-dropdown-menu.png, /tmp/cc-haha-worktree-dropdown-selected.png, /tmp/cc-haha-worktree-dropdown-mobile-menu.png, /tmp/cc-haha-worktree-dropdown-mobile-selected.png
Not-tested: Native Tauri packaged window visual check
2026-05-07 19:44:51 +08:00
程序员阿江(Relakkes)
ca4900ed0c fix: cluster repository launch chips
The composer context rail should read as one compact group, not three stretched controls. This change removes flex growth from the repository picker, caps branch width by content, softens the active worktree state, and removes hover borders that made secondary state controls look primary.

Constraint: Keep the existing composer and session layout unchanged.
Rejected: Use a prominent active outline for worktree | it made the state look like the primary action.
Confidence: high
Scope-risk: narrow
Directive: Keep this rail content-sized; long names should truncate inside chips instead of spreading across the bar.
Tested: cd desktop && bun run test -- --run src/components/shared/DirectoryPicker.test.tsx src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: bun run check:desktop
Tested: agent-browser desktop screenshot /tmp/cc-haha-repo-controls-compact-worktree-active-final.png and mobile overflow check /tmp/cc-haha-repo-controls-compact-mobile-final.png
Not-tested: Native Tauri packaged window visual check
2026-05-07 18:40:25 +08:00
程序员阿江(Relakkes)
fd5dc097a7 fix: isolate desktop session streaming state
Desktop chat sessions can stream and reconnect concurrently, so shared in-process buffers must not be keyed only by process lifetime. This change scopes streaming delta buffers, task-tool refresh bookkeeping, and CLI task mutations to the session that produced the event. It also ignores stale client socket closes after a newer socket has replaced the active connection for the same session.

Constraint: Desktop users can keep multiple sessions and tabs active at the same time.
Rejected: Serialize all desktop streaming through one active session | would hide the race instead of preserving multi-session behavior.
Confidence: high
Scope-risk: moderate
Directive: Do not reintroduce process-global chat/task pending state without session keys and multi-session regression tests.
Tested: cd desktop && bun run test -- src/stores/chatStore.test.ts src/stores/cliTaskStore.test.ts
Tested: bun test src/server/__tests__/websocket-handler.test.ts
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
Tested: bun run check:server
Tested: bun run check:coverage | changed-lines 100%, fails only existing agent-utils baseline
Tested: bun run verify | 8 passed, 1 failed on existing agent-utils coverage baseline, 2 skipped
Not-tested: Real desktop dual-window manual smoke.
Related: https://github.com/NanmiCoder/cc-haha/issues/302
Related: https://github.com/NanmiCoder/cc-haha/issues/303
2026-05-07 18:33:57 +08:00
程序员阿江(Relakkes)
3606531f7e fix: tighten repository launch context bar
The launch controls live directly under the composer, so they need to read as a compact context rail rather than a second card. The styling now uses a lighter surface, shorter controls, bounded flex sizing, and explicit hover titles for long repository and branch names. Git repo status is passed into the picker so a freshly opened Git project does not briefly look like a plain folder.

Constraint: Keep the existing session/composer layout untouched; only refine the context bar under the input.
Rejected: Redesign the empty session layout | user explicitly scoped this to the lower context bar.
Confidence: high
Scope-risk: narrow
Directive: Do not grow this rail vertically without browser-checking long repo and branch names.
Tested: cd desktop && bun run test -- --run src/components/shared/DirectoryPicker.test.tsx src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: bun run check:desktop
Tested: agent-browser long repo and long branch screenshots at /tmp/cc-haha-repo-controls-polished-git-long-branch-selected.png and /tmp/cc-haha-repo-controls-polished-mobile-long.png
Not-tested: Native Tauri packaged window visual check
2026-05-07 18:33:42 +08:00
程序员阿江(Relakkes)
09209ecefb fix: preserve repository context after session launch
Empty ActiveSession launch controls now use both loaded chat messages and persisted session messageCount, so historical sessions do not briefly fall back into new-session launch mode while message history is still loading. Regression coverage also locks the first-message branch launch flows for direct checkout and isolated worktree sessions.

Constraint: Historical session lists already know messageCount before chat history finishes loading
Rejected: Wait for history fetch before rendering composer controls | it keeps the wrong new-session affordance visible during reopen
Confidence: high
Scope-risk: narrow
Directive: Branch/worktree launch controls are only for messageCount-zero sessions; reopened history must render repository context chips
Tested: bun run test -- --run src/components/chat/ChatInput.test.tsx src/pages/ActiveSession.test.tsx src/__tests__/pages.test.tsx
Tested: bun run check:desktop
Tested: agent-browser /tmp repo direct branch launch on /private/tmp/cc-haha-repo-e2e-IP9mkb produced session 9089ae96-5dd6-4ea6-b88e-376ab081ca24 on workDir /private/tmp/cc-haha-repo-e2e-IP9mkb
Tested: agent-browser /tmp repo isolated worktree launch produced session 9ec657bd-e503-48b3-b52f-36e210fc5d64 on workDir /private/tmp/cc-haha-repo-e2e-IP9mkb/.claude/worktrees/desktop-main-9ec657bd
Not-tested: root bun run verify; desktop surface was covered with check:desktop and live browser smoke
2026-05-07 18:19:18 +08:00
程序员阿江(Relakkes)
0e705473ff fix: show repository controls in empty chat tabs
Empty active session tabs were still using the old directory-only picker, so sessions created from the sidebar lost the branch and worktree controls even when their workDir was a Git repository. Reuse the launch controls below the existing composer and replace only the empty session when the user changes repository launch options.

Constraint: Sidebar-created sessions land in ActiveSession, not the EmptySession landing view
Rejected: Reshape the whole session layout | the intended surface is only the controls below the composer
Confidence: high
Scope-risk: narrow
Directive: Keep repository launch controls shared between EmptySession and empty ActiveSession composer flows
Tested: bun run test -- --run src/__tests__/pages.test.tsx src/components/chat/ChatInput.test.tsx
Tested: bun run check:desktop
Tested: agent-browser sidebar new-session smoke at http://127.0.0.1:4790/ with screenshot /tmp/cc-haha-after-sidebar-new-session-controls.png
Not-tested: root bun run verify remains blocked by pre-existing root coverage gate outside desktop
2026-05-07 18:08:38 +08:00
程序员阿江(Relakkes)
0f220f4af5 fix: restore empty session launcher layout
The repository launch controls should extend the existing empty-session composer, not replace the session layout. This restores the previous mascot, title, composer sizing, textarea, and run button while keeping the project, branch, and worktree controls attached directly beneath the input.

Constraint: User requested the original session layout stay intact except for adding repository controls under the chat input
Rejected: Keep the Codex-style centered launcher rewrite | it changed too much of the existing session surface
Confidence: high
Scope-risk: narrow
Directive: Future changes to repository launch controls should treat EmptySession layout as fixed unless explicitly requested otherwise
Tested: cd desktop && bun run test -- --run src/components/shared/DirectoryPicker.test.tsx src/pages/EmptySession.test.tsx src/__tests__/pages.test.tsx
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
Tested: agent-browser screenshot /tmp/cc-haha-layout-restored-selected.png on localhost:4790
Not-tested: root bun run verify not rerun for this narrow layout correction
2026-05-07 17:56:33 +08:00
程序员阿江(Relakkes)
f3dc2399c2 fix: polish desktop launch repository controls
The empty-session launch surface needed to behave like a real coding-agent entry point: project, branch, and worktree choices are now visible together, and branch choices that cannot safely run in-place force an isolated worktree before session creation.

Constraint: Desktop launch flows must preserve repository safety when a target branch is dirty or checked out elsewhere
Rejected: Keep branch and worktree controls as detached chips | the selection state was easy to miss and visually inconsistent with the launcher
Confidence: high
Scope-risk: moderate
Directive: Do not remove the automatic worktree requirement without rechecking dirty and checked-out branch launches through the desktop UI
Tested: cd desktop && bun run test -- --run src/components/shared/DirectoryPicker.test.tsx src/pages/EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
Tested: browser-driven desktop smoke on ports 4789/4790
Not-tested: bun run verify still has the pre-existing agent-utils coverage ratchet failure outside desktop
2026-05-07 17:47:42 +08:00
程序员阿江(Relakkes)
2dd8ee4a33 fix: keep open session tab titles in sync
Open session tabs can outlive the title value they were created with, while the sidebar and session detail view read from the refreshed session list. Refresh existing tab titles when a session tab is reopened and after session list refreshes so the top tab bar cannot keep a stale generated title.

Constraint: Sidebar filtering and session refresh should not leave already-open tabs with stale labels.
Rejected: Only rely on WebSocket title update events | restored tabs and already-open tabs can miss later session-list corrections.
Confidence: high
Scope-risk: narrow
Directive: Keep session tab titles derived from current session list data when available.
Tested: cd desktop && bun run test -- --run src/stores/tabStore.test.ts src/stores/sessionStore.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run test -- --run
Tested: agent-browser smoke on http://127.0.0.1:1420/ confirmed top tabs match sidebar and session detail titles.
2026-05-07 16:38:27 +08:00
程序员阿江(Relakkes)
4c2881aaf0 Prevent duplicate desktop app instances
Notification clicks and repeated launches can enter the native app through OS-level activation paths, so the desktop runtime now registers Tauri's single-instance guard before sidecars or other plugins start. A second launch restores and focuses the existing main window instead of creating another app process.

Constraint: macOS and Windows launch paths must reuse the running desktop instance.
Rejected: Handle only notification click callbacks | does not cover Dock, shortcut, installer, or Windows relaunch paths.
Confidence: high
Scope-risk: narrow
Directive: Keep the single-instance plugin before sidecar startup so duplicate launches cannot create extra runtime processes.
Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh
Tested: open -n built app twice; desktop_count stayed 1 with pid 69821
Tested: bun run check:native
Tested: cargo test --manifest-path desktop/src-tauri/Cargo.toml
Tested: cd desktop && bun run test -- desktopNotifications.test.ts
Tested: cd desktop && bun run lint
2026-05-07 16:28:08 +08:00
程序员阿江(Relakkes)
7fbce35be6 fix: prevent malformed generated session titles
Session titles need to appear immediately, but the async AI title pass can return fenced or escaped JSON fragments. Keep the first-message title path fast, preserve optimistic client titles during background refresh, and only accept structured title responses that parse cleanly.

Constraint: Desktop sessions should stop showing Untitled/New Session after the first user turn.
Rejected: Accept short raw model output as a fallback | malformed JSON fragments are short enough to leak into the UI.
Confidence: high
Scope-risk: moderate
Directive: Do not loosen generated title parsing without regression coverage for fenced, escaped, and truncated JSON responses.
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/stores/sessionStore.test.ts src/pages/EmptySession.test.tsx
Tested: agent-browser smoke on http://127.0.0.1:1420/ confirmed sidebar and tab titles update without JSON fragments.
2026-05-07 16:28:08 +08:00
程序员阿江(Relakkes)
a340e41046 fix: make local desktop builds reflect current UI state
The desktop test package was able to reuse stale Tauri target output even after the frontend and sidecar were rebuilt, which made UI changes look missing after a build. The local macOS build script now clears that cache by default while retaining an opt-in incremental path.

The project selector also no longer repeats the active branch because branch and worktree are now first-class launch controls beside it.

Constraint: Local macOS test packages must prioritize freshness over incremental build speed
Rejected: Keep branch text in the project chip | duplicated the dedicated branch selector and made the launch row harder to scan
Confidence: high
Scope-risk: narrow
Directive: Keep branch selection behavior in RepositoryLaunchControls; DirectoryPicker should only identify the project
Tested: cd desktop && bun run test -- DirectoryPicker.test.tsx
Tested: cd desktop && bun run lint
Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh
Tested: Opened built app and confirmed sidecar /health returned ok
2026-05-07 15:57:40 +08:00
程序员阿江(Relakkes)
7ae885a114 fix: add safe Doctor rescue path for desktop upgrades
Online upgrades can strand users on stale desktop UI state or malformed local persistence. This adds a deny-by-default Doctor path that resets only regenerable desktop UI state, reports protected local files with redacted metadata, and keeps protected repair as a dry-run no-op until a reviewed backup-first flow exists.

Constraint: Chat transcripts, model/provider config, Skills, MCP, IM bindings, adapter sessions, OAuth tokens, plugins, and team/session records are user-owned protected state.
Rejected: Automatically rewrite malformed protected JSON | unsafe without schema-specific migrations and backups.
Rejected: Continue relying only on startup migrations | users need an explicit recovery action after a white screen.
Confidence: high
Scope-risk: moderate
Directive: Keep Doctor repair deny-by-default; do not mutate protected state without an explicit reviewed backup-first manual repair flow.
Tested: bun test src/server/__tests__/doctor-service.test.ts
Tested: cd desktop && bun run test src/components/ErrorBoundary.test.tsx src/lib/doctorRepair.test.ts src/__tests__/diagnosticsSettings.test.tsx src/components/layout/StartupErrorView.test.tsx
Tested: cd desktop && bun run lint
Tested: bun run check:server
Tested: bun run verify (failed only existing agent-utils coverage baseline; changed-lines coverage 97.62%)
Not-tested: Packaged desktop manual Doctor click path.
2026-05-07 00:04:06 +08:00
程序员阿江(Relakkes)
fa47adc33a fix: prevent upgrade crashes from stale persistence
Desktop users can carry provider indexes, managed settings, localStorage state, and native update state from builds that no longer match current readers. This adds startup migrations and recovery paths before server and React state are consumed, plus a persistence upgrade gate so future storage protocol changes ship with old-format fixtures.

Constraint: Existing installs may contain malformed or legacy JSON/localStorage that must not block startup.
Constraint: Local verify should evaluate the current worktree diff rather than unrelated detached-worktree history.
Rejected: Treat invalid persisted state as fatal | reproduces white-screen and startup failure behavior for existing users.
Rejected: Bypass PR policy locally | hides real gate behavior and does not fix detached-worktree false positives.
Confidence: high
Scope-risk: moderate
Directive: Any local JSON, localStorage, or app config shape change must add a migration fixture and keep `bun run check:persistence-upgrade` green.
Tested: bun run check:persistence-upgrade; bun run check:policy; bun run check:desktop; bun run check:server; bun run check:native; bun run verify (9 passed, 1 coverage baseline failure)
Not-tested: Live provider baseline; existing user configs beyond covered fixtures
2026-05-06 23:20:21 +08:00
程序员阿江(Relakkes)
b156be8d8d feat: make PR quality verification self-enforcing
Contributors and coding agents need one local command that both reports and enforces the quality contract. This change turns the PR gate into the shared verification entrypoint, adds path-selected local lanes, tightens coverage accounting around changed lines, and documents the repair loop in contributor and agent-facing guidance.

Constraint: Ordinary PR verification must stay non-live and runnable without provider credentials
Constraint: Coverage policy updates in this commit require maintainer approval before push/merge
Rejected: Keep quality guidance only in docs | agents need executable scripts and AGENTS.md instructions to follow the loop consistently
Confidence: high
Scope-risk: broad
Directive: Do not bypass `bun run verify` for production changes; fix failed lanes and coverage reports instead of lowering thresholds
Tested: bun run check:policy
Tested: ALLOW_CLI_CORE_CHANGE=1 ALLOW_COVERAGE_BASELINE_CHANGE=1 bun run verify
Not-tested: live provider baseline; no provider credentials were required for this non-live PR gate
2026-05-06 22:33:43 +08:00
程序员阿江(Relakkes)
9719726cd2 feat: make quality gates observable and enforceable
The repository now has a measurable PR quality path instead of a loose set of
manual checks. Coverage, quarantine governance, provider smoke, desktop smoke,
and workflow wiring all produce durable reports that contributors and maintainers
can inspect without reconstructing terminal output.

This also fixes the desktop smoke current-runtime path so browser-driven smoke
runs use the desktop default active provider instead of forcing the official
current model, and records that runtime decision as an artifact.

Constraint: Default PR gates must remain non-live and contributor-safe while live model checks stay explicit.
Constraint: Release packaging is still GitHub Actions based, so release preflight must run before the build matrix.
Rejected: Make live provider or desktop smoke mandatory on every PR | secrets, quotas, and model availability are maintainer-controlled.
Rejected: Let PRs lower coverage baselines in the same change | base-branch ratchet comparison must remain authoritative.
Confidence: high
Scope-risk: moderate
Directive: Do not relax coverage or quarantine policy without a maintainer approval label and a fresh quality report.
Tested: ALLOW_CLI_CORE_CHANGE=1 ALLOW_COVERAGE_BASELINE_CHANGE=1 bun run quality:gate --mode pr
Tested: bun run quality:gate --mode baseline --allow-live --only provider-smoke:* --provider-model nvidia-custom:main:nvidia-custom-main --artifacts-dir /tmp/quality-gate-live-smoke
Tested: bun run quality:gate --mode baseline --allow-live --only desktop-smoke:* --provider-model current:current:current-runtime --artifacts-dir /tmp/quality-gate-desktop-smoke-fixed
Tested: git diff --check
Not-tested: Full live release mode with multiple providers in hosted CI; provider credentials and quota remain maintainer-controlled.
2026-05-06 16:25:10 +08:00
程序员阿江(Relakkes)
d1f3b1f91b test: wait for desktop repository launch readiness
The branch label can render before the parent composer receives the launch-ready callback, especially after the main branch notification UI changes added more render work. The test now waits for the same enabled Run state a user can interact with before submitting.

Constraint: The product intentionally disables Run while repository context is still resolving
Rejected: Loosen the create-session assertion | the assertion is still the behavior this flow must guarantee
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- src/pages/EmptySession.test.tsx --run
2026-05-06 14:54:17 +08:00
程序员阿江(Relakkes)
d1bf65d107 Merge desktop repository launch safety into main
This brings the desktop branch/worktree launch flow into the local main checkout after validation in the feature worktree. The merge keeps the feature commit intact while preserving the newer main history.

Constraint: Local main already contains newer notification routing work
Confidence: high
Scope-risk: moderate
Tested: ALLOW_CLI_CORE_CHANGE=1 bun run quality:pr in the feature worktree before merge
Tested: /tmp business-flow script with dirty checkout, checked-out branch, isolated worktree, missing branch, non-git, missing directory, and real LLM session
Tested: agent-browser desktop UI flow across dirty, checked-out, non-git, branch search, recent-project, and Run scenarios
2026-05-06 14:52:21 +08:00
程序员阿江(Relakkes)
f262ec3029 feat: protect desktop branch launches with worktree isolation
Desktop sessions now resolve repository launch intent before creation, so users can pick a branch, choose whether to isolate it in a worktree, and get stable error messages instead of silent branch-switch failures. The server owns the Git safety checks and session metadata so the UI and real agent runtime agree on the actual working directory.

Constraint: Direct branch switching must not overwrite or hide uncommitted user changes
Constraint: Desktop worktree branches must stay out of normal branch selection and recent-project labels
Rejected: Let the UI call git directly | server-side checks keep session metadata and runtime launch paths consistent
Rejected: Auto-switch dirty checkouts | users need an explicit isolated-worktree choice to protect local edits
Confidence: high
Scope-risk: moderate
Directive: Do not relax dirty-worktree or checked-out-branch guards without adding equivalent business-flow tests
Tested: ALLOW_CLI_CORE_CHANGE=1 bun run quality:pr
Tested: /tmp business-flow script with dirty checkout, checked-out branch, isolated worktree, missing branch, non-git, missing directory, and real LLM session
Tested: agent-browser desktop UI flow across dirty, checked-out, non-git, branch search, recent-project, and Run scenarios
2026-05-06 14:51:46 +08:00
程序员阿江(Relakkes)
b8e335f7bd feat: route desktop notifications to target sessions
Desktop notifications now carry a narrow target payload so clicking a permission, completion, or scheduled-task notification can reopen the matching tab and reconnect the session. macOS uses the native notification bridge for tap callbacks, while the shared desktop notification layer also accepts plugin action payloads where the platform exposes them.

Constraint: Notification clicks need to activate existing desktop tabs without adding a new navigation state channel.
Rejected: Store only notification ids and infer the active session later | stale notifications would point at the wrong session after tab changes.
Confidence: high
Scope-risk: moderate
Directive: Keep notification targets serializable and versioned through desktopNotifications before adding new target types.
Tested: bun run quality:pr with ALLOW_CLI_CORE_CHANGE=1; desktop unit tests; server tests; native sidecar build and cargo check; docs build.
Not-tested: Packaged Windows toast activation runtime; current fallback depends on Tauri notification action delivery.
2026-05-06 14:00:32 +08:00
程序员阿江(Relakkes)
1cd90dc66a feat: let users opt out of bundled Computer Use
Computer Use is useful when explicitly needed, but exposing its MCP tools by default creates unnecessary desktop-control surface for users who want coding-only sessions. This adds a shared disable path for CLI flags, environment, and desktop settings while keeping preauthorized app state in one config file.

The same change also preserves Windows and WSL shell startup behavior by applying the MSYS argument-conversion guard only on WSL-bound launches.

Constraint: Computer Use MCP must not be exposed to the Coding Agent when disabled

Constraint: Desktop settings and CLI sessions need to read the same persisted Computer Use config

Rejected: Environment-only disable switch | desktop users need a persistent Settings control

Rejected: Remove Computer Use setup entirely | enabled sessions still need the existing built-in MCP path

Confidence: high

Scope-risk: moderate

Directive: Keep every new Computer Use entrypoint wired through loadStoredComputerUseConfig or the CLI disable flag before adding MCP tools

Tested: bun test src/utils/computerUse/gates.test.ts src/utils/computerUse/preauthorizedConfig.test.ts src/server/__tests__/computer-use-api.test.ts src/utils/shell/wslInterop.test.ts desktop/src/pages/ComputerUseSettings.test.tsx

Tested: bun run check:server; bun run check:desktop; bun run check:docs; bun run check:policy; bun run check:native; git diff --check

Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh; codesign verify; hdiutil verify; built CLI Computer Use E2E exposure and disable checks

Not-tested: Full screenshot/control action after granting macOS Screen Recording permission on this machine
2026-05-06 11:40:49 +08:00
程序员阿江(Relakkes)
4e9c6dbda1 Keep cross-platform tray menu imports available
Linux release builds use MenuBuilder for the shared tray menu, while MenuItemBuilder and SubmenuBuilder are only used in the macOS native menu bar. Gate only the macOS-only imports so Linux builds no longer warn about them and still compile the shared tray path.

Constraint: Linux builds compile the shared tray setup path and require MenuBuilder

Constraint: MenuItemBuilder and SubmenuBuilder are only referenced inside cfg(target_os = "macos")

Rejected: Gate the whole tauri::menu import on macOS | Linux still needs MenuBuilder for tray menu construction

Confidence: high

Scope-risk: narrow

Directive: Do not gate MenuBuilder by platform unless setup_system_tray is also made platform-specific

Tested: cargo fmt --check

Tested: git diff --check

Not-tested: Local Linux cargo check beyond system GTK/WebKit pkg-config setup; GitHub release Linux job is the verification surface
2026-05-05 23:27:26 +08:00