Two reviews of the icon swap, run independently from opposite directions,
turned up three places the new mark never reached.
The og:image was the worst. `site/index.html:20` points at
`/images/banner.png`, and that file does not come from `docs/images/banner.png`
— the one this rebrand replaced. `site/scripts/prepare-static-output.mjs:129`
copies `docs/public/` wholesale into the site root before the two selective
image passes run, and neither of those matches an absolute https:// URL, so
`docs/public/images/banner.png` is what shipped. It was a 1200x630 screenshot
of the old site: blue panels, old circular CC badge. Every link shared to
WeChat or Slack would have previewed the pre-rebrand brand while the site
itself rendered the new one. Replaced with a card built from the new lockup;
`site/dist/images/banner.png` now hashes to it.
`desktop/src-tauri/app-icon.png` is the canonical 1024 RGBA source the platform
icon set gets regenerated from. That rule lived only in the body of 3f2ce2a6c,
and nothing references the file in code, so the rebrand skipped it — breaking
an invariant that had held since the file was introduced, where it and
`desktop/public/app-icon.png` were the same git blob. Left as it was, whoever
regenerated icons next would have restored the entire old set.
Linux had no icon above 310px. electron-builder points `linux.icon` at the
whole icons directory and keeps only files named NxN, so `icon.png` (512, no
dimensions in the name) and `128x128@2x.png` (256, collides with
`128x128.png`) were both dropped, leaving a Windows Store asset as the largest
entry. Adding 256x256.png and 512x512.png takes the resolved set from 12
entries topping out at 310 to 14 topping out at 512, confirmed by running
app-builder's icon resolver against the directory.
index.html also had no favicon, and that document is what the H5 remote client
loads in a phone browser.
CI could not have caught any of this — `scripts/quality-gate/package-smoke/`
asserts nothing about icons. `desktop/icon-assets.test.ts` now pins the source
invariant, the Linux sizes, the three packaged icons and the favicon; each
assertion was checked to fail when its subject is reverted.
`app-icon.png` is a 120KB bitmap, and the seven `.svg` files beside it under
docs/images are 193 bytes each — an `<image>` tag wrapping that bitmap. So the
mark carried its own blue/cyan/orange through all six palettes while everything
around it moved, and there was nothing to recolor.
Measured the bitmap back into geometry rather than redrawing it: connected
components to separate the elements, algebraic circle fits for the arcs, angular
histograms for the openings and stroke widths. Big C is center (415,566) r=131
stroke=60, opening 160°; the second C is center (615,576) r=117 cut into two 68°
arcs; the cursor is a four-point polygon with one notch. The slight ellipticity
and unequal stroke ends were raster artifacts, so they were rounded out. The
shape is otherwise unchanged — differencing a render against the original leaves
only antialiasing.
Color maps the original's three layers onto the palette's own three: the C's take
墨 `--cc-t1`, the bar and cursor and sparkles take 朱 `--cc-ac`.
Six themes do not need six icons. Their accent resolves to two values — #96442B
across the four light palettes, #D07B52 across the two dark ones, which is the
same ochre lightened. Only the ink varies, and ink should follow body text
anyway.
The app icon stays one fixed artwork. Dock and taskbar are drawn by the OS, which
knows nothing about the in-app theme, so paper ground with ink C's ships to every
platform. Inside the app the mark is a vector on tokens and repaints per theme.
Four ideas — two C's, the bar, the cursor, two sparkles — collapse below 24px, so
every consumer sheds parts as it shrinks: sparkles above 40px, cursor above 24px,
C's and bar always. That applies inside icon.icns and icon.ico as much as in
BrandSeal.
BrandSeal was the 「哈」 glyph in a terracotta square; it is now the CC mark drawn
inline on `--color-text-primary` and `--color-brand`. Its five call sites — the
sidebar, both empty states, the H5 connect view, the gallery — follow, and the
about pane drops its `<img>` for the same component.
README leads with the horizontal lockup inside a `<picture>` so GitHub serves the
dark cut in dark mode.
`preview-agent.js` is a tracked build artifact, bundled from
desktop/src/preview-agent/ by build:preview-agent and shipped as a
packaged resource. The rollback (e9b53f68) deleted that source's
theme.ts and trimmed editBubble.ts, but never rebuilt the artifact --
it appears in neither revert's file list, so the committed blob was
last produced at ad597ffe.
The result is a bundle built from source that no longer exists: it
still carries all 12 --cc-haha-* custom properties the deleted theme.ts
defined, plus the shadcn-era brand hex, and lacks the literal styling
the current source emits. It is internally consistent so nothing
crashes -- the packaged app just renders styling that diverges from
what the repository says it should.
Rebuilt from the current source. Verified byte-stable across repeated
builds, so this does not reintroduce artifact drift.
The shadcn migration (ad597ffe) and its follow-up (5b4e224f) were
mega-commits: only ~16% of the insertions were UI work. Rolling either
one back wholesale also deletes ~3400 lines of unrelated server,
Electron, and store hardening -- and because each of those changes
shipped with its own tests, the suite stays green while the hardening
silently disappears.
This rolls back the UI layer only.
Reverted (back to c2774fc1):
- desktop/src/components, pages, features, theme, i18n
- components/ui/**, components.json, src/lib/utils.ts (cn helper)
- radix-ui, class-variance-authority, tailwind-merge deps
- src-tauri/src/lib.rs hardening: dead code, nothing compiles it
(no @tauri-apps dep, no cargo invocation anywhere, and
scripts/pr/release-workflow.test.ts asserts Tauri's absence)
Kept (identical to main):
- src/** -- WhatsApp authDir escape allowing arbitrary recursive
directory removal, computer-use tier bypass granting every
pre-authorized app full tier, plugin uninstall keepData inversion
that deleted data when asked to keep it, plugin project-scope
writing to the sidecar cwd, diagnostics share leaking provider
config, memory API TOCTOU plus atomic writes
- desktop/electron/** -- PTY leak on renderer destruction, IPC
boundary validation rejecting NaN and unbounded input
- desktop/src/stores/** -- request-id race guards
- desktop/src/api, lib/desktopHost -- kept in step with the stores
Follows main's b64069a3 in dropping the installed-skills overview.
Updated two memorySettings assertions to expect the optimistic-lock
fields the retained memory store sends.
check:desktop pass (lint clean, 225 files / 2519 passed / 1 skipped,
build ok). check:server pass (224 files / 2375 passed / 0 failed).
- Prevent EmptySession crash when settings have not loaded: fall back
to the default permission-mode display and an empty model list, and
stop undefined models responses from poisoning the settings store
- Sync Tauri terminal hardening with Electron: owner binding, input
limits, window-destroy session cleanup, malformed config fallback
- Fix Sheet/MobileBottomSheet z-order so dialogs render above sheets
- Migrate ConfirmPopover to the shadcn Button; remove dead legacy
shared form components and unused mockup pages
- Keep underscores readable in shared diagnostics, redact provider
models only on secret-scanner hits, clean stale WhatsApp login
staging dirs, and add recovery hints for corrupt computer-use config
- Token-ize find-in-page highlight colors, restore the indeterminate
progress slide animation, and tidy a11y/displayName details
Fixes#819 and #879.
The mounted BrowserSurface now drives native preview navigation when a new browser target is opened for the same session, so the WebContentsView no longer stays on the first previewed file.
The preview-agent edit bubble now clamps to the viewport, prefers placing above low selected elements, and keeps its footer controls out of the scroll body.
Tested: cd desktop && bun run test -- --run src/components/browser/BrowserSurface.test.tsx src/stores/browserPanelStore.test.ts src/components/workspace/WorkspaceFileOpenWith.test.tsx src/components/chat/CurrentTurnChangeCard.test.tsx src/preview-agent/editBubble.test.ts
Tested: bun run check:desktop
Confidence: high
Scope-risk: narrow
Use Electron WebContentsView capturePage for browser preview screenshots and selection annotations so captured images match the rendered preview.
Tested:
- cd desktop && bun run test -- electron/services/preview.test.ts src/lib/previewEvents.test.ts src/components/browser/BrowserSurface.test.tsx src/preview-agent/screenshot.test.ts src/preview-agent/picker.test.ts src/preview-agent/editBubble.test.ts
- cd desktop && bun run lint
- cd desktop && bun run build
- bun run check:desktop
- bun run check:electron
- bun run check:native
Not-tested:
- Real GUI click-through for Screenshot / Select Element; Electron runtime launch was blocked in this shell and packaged build did not enter the smoke path.
Constraint: GUI click-through smoke was blocked by local Electron launch behavior; package smoke passed but does not launch the app.
Confidence: medium
Scope-risk: narrow
Add a WhatsApp adapter backed by Baileys linked-device auth, plus desktop QR binding UI, server config endpoints, sidecar startup wiring, tests, and documentation.
Constraint: Uses WhatsApp Web linked-device auth, not Meta WhatsApp Business Cloud API.
Tested:
- cd adapters && bun run check:adapters
- bun test src/server/__tests__/adapters.test.ts
- cd desktop && bun run check:desktop
- bun run check:native
- bun run check:persistence-upgrade
- bun run check:docs
Not-tested:
- Live WhatsApp QR pairing, because no WhatsApp account/device was exercised here.
- bun run check:server, because the existing src/server/__tests__/conversations.test.ts timeout still fails independently.
Confidence: medium
Scope-risk: moderate
Introduce the Electron desktop shell alongside the existing React renderer and local Bun server boundary. The migration keeps the DesktopHost contract explicit across Tauri, Electron, and browser runtimes while adding Electron main/preload services for dialogs, shell, notifications, updates, tray/window lifecycle, terminal, preview WebContentsView, app mode, and release/package validation.
The commit also carries the latest local main desktop command updates, including agent slash entries and hidden-by-default markdown thinking details, so the packaged Electron build matches the current main UX surface.
Constraint: React renderer, local Bun server, REST/WebSocket, and sidecar boundaries must remain reusable during the migration
Constraint: macOS dev packages are ad-hoc signed and cannot prove Developer ID notarization or Gatekeeper release launch
Rejected: Browser-only smoke validation | it cannot exercise native dialogs, keychain prompts, notification behavior, or packaged app startup
Confidence: medium
Scope-risk: broad
Directive: Do not remove Tauri host support until signed Electron release artifacts pass native OS smoke on macOS, Windows, and Linux
Tested: bun run check:desktop
Tested: cd desktop && bun run check:electron
Tested: CSC_IDENTITY_AUTO_DISCOVERY=false bun run electron📦dir
Tested: bun run test:package-smoke --platform macos --package-kind dir --artifacts-dir desktop/build-artifacts/electron
Tested: Computer Use read packaged Electron app window at desktop/build-artifacts/electron/mac-arm64/Claude Code Haha.app
Not-tested: Developer ID signed/notarized Gatekeeper launch
Not-tested: Real OS notification click-to-session action
Not-tested: Windows and Linux packaged app smoke on real hosts
The desktop app can quit while a preview-driven Bash task is still running npm/vite. Bash commands are spawned as detached process groups, so killing only the CLI or shell process can leave descendant dev servers alive and make later app launches look stuck.
This gives the CLI enough shutdown budget to run cleanup, lets the native sidecar wait long enough for that server cleanup, kills detached Bash process groups before the existing tree-kill fallback, and closes the native preview WebView instead of hiding it on workbench unmount.
Constraint: CLI gracefulShutdown has a 5s failsafe, so outer desktop shutdown windows must not SIGKILL it after 2-3s
Rejected: Treat the browser preview as the dev-server owner | it only opens URLs and does not spawn npm/vite
Confidence: high
Scope-risk: moderate
Directive: Do not shorten desktop/server shutdown windows below the CLI cleanup budget without reproducing BashTool background-task teardown
Tested: bun test src/utils/ShellCommand.test.ts src/server/__tests__/conversation-service.test.ts
Tested: cd desktop && bun run test -- --run src/components/browser/BrowserSurface.test.tsx src/components/workbench/WorkbenchPanel.webview.test.tsx
Tested: cd desktop && bun run lint
Tested: bun run check:server
Tested: SKIP_INSTALL=1 ./desktop/scripts/build-macos-arm64.sh
Tested: Opened canonical app and generated DMG app; both showed visible/frontmost window and left no app/sidecar/vite processes after quit
Not-tested: Notarized release install path
Prepare the desktop release metadata and concise release notes while keeping
tagging and release publishing for a later step. The staged local build-script
updates keep desktop commands on checked-in local toolchain paths and avoid
rewriting preview-agent output when the built content is unchanged.
The persistence-upgrade gate now runs the focused desktop Vitest migration
suite in non-watch mode, matching the broader desktop quality lane and avoiding
pre-push termination during release preparation.
Constraint: Release publishing is intentionally deferred per request
Constraint: Desktop release metadata must keep package, Tauri config, Cargo metadata, and Cargo.lock aligned
Confidence: medium
Scope-risk: moderate
Directive: Do not tag v0.3.2 until release dry-run and final release verification are rerun on the release candidate
Tested: bun run scripts/release.ts 0.3.2 --dry
Tested: cd desktop && bun run lint
Tested: bun run check:persistence-upgrade
Tested: git diff --check
Not-tested: Full bun run verify
Packaged desktop shutdown was killing the server sidecar with SIGKILL on Unix, which skipped server-side cleanup for CLI subprocesses spawned by active chat sessions. The native layer now gives sidecars a SIGTERM grace window, and the server waits for active CLI sessions to exit before completing signal-driven shutdown.
Constraint: Tauri shell CommandChild::kill maps to SIGKILL on Unix.
Rejected: Only clean stale processes on next launch | leaves user-owned sessions and sockets in an unknown state after every unclean app exit.
Confidence: high
Scope-risk: moderate
Directive: Do not replace the SIGTERM grace path with direct CommandChild::kill without rechecking packaged-app process-tree shutdown.
Tested: bun test src/server/__tests__/conversation-service.test.ts
Tested: bun run check:server
Tested: bun run check:native
Tested: git diff --check
Not-tested: Fresh DMG install plus manual quit/reopen process-tree smoke.
Preview annotations should keep the selected element readable. The selected rectangle now carries a stronger translucent blue fill, while the numbered badge is a separate high-contrast fixed overlay placed outside the selected rect and clamped to the viewport.
Constraint: No issue number was provided for this task.
Constraint: Preserve the DOM-captured annotation path introduced for viewport-safe screenshots.
Rejected: Put the badge inside the selected box | it obscures compact buttons and labels.
Rejected: Return to canvas-side badge drawing | that reintroduces the separate coordinate system.
Confidence: high
Scope-risk: narrow
Directive: Keep numbered badges outside compact selected targets unless visual evidence shows a better non-obscuring placement.
Tested: cd desktop && bun run test --run src/preview-agent/screenshot.test.ts src/preview-agent/picker.test.ts src/preview-agent/metadata.test.ts src/preview-agent/protocol.test.ts src/preview-agent/bridge.test.ts src/preview-agent/editBubble.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build:preview-agent
Tested: bun run check:desktop
Tested: git diff --check
Not-tested: Real Tauri webview visual smoke.
Selection screenshots were drawing the marker after html2canvas finished by
mapping DOM coordinates onto a separate canvas. That leaves room for drift when
html2canvas renders at a different output size, the viewport is resized, or the
thumbnail is compressed. The marker is now a fixed DOM overlay captured with the
page itself, so the chosen element and its marker share the same viewport,
layout, crop, and scale path.
Constraint: No issue number was provided for this task.
Constraint: Preserve the existing selection event payload and preview bridge protocol.
Rejected: Keep canvas post-processing with more scale math | it still maintains a second coordinate system beside the rendered page.
Rejected: Keep the unused annotate module | it would preserve the stale path that caused this class of drift.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce canvas-side selection marker math unless it is proven against resized and scaled viewport captures.
Tested: cd desktop && bun run test --run src/preview-agent/screenshot.test.ts src/preview-agent/picker.test.ts src/preview-agent/metadata.test.ts src/preview-agent/protocol.test.ts src/preview-agent/bridge.test.ts src/preview-agent/editBubble.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build:preview-agent
Tested: bun run check:desktop
Tested: git diff --check
Not-tested: Real Tauri webview visual smoke.
Element selection from the local preview should preserve the visual target
the user picked and send the confirmed request directly to chat. The
screenshot now captures the visible viewport before drawing the marker, and
the selection event sends a model-facing prompt while the chat UI shows only
the annotated image and compact element label.
Constraint: No issue number was provided for this task.
Constraint: Keep the preview-agent protocol shape unchanged.
Rejected: Prefill the composer with the selection note | it keeps the old extra confirmation step and exposes implementation text in the input.
Rejected: Full-document annotation coordinates | body-relative captures drift from the viewport selection users see.
Confidence: high
Scope-risk: moderate
Directive: Do not route confirmed preview selections back through composer prefill without rechecking the Codex-style direct-send flow.
Tested: cd desktop && bun run test --run src/preview-agent/screenshot.test.ts src/lib/previewEvents.test.ts src/lib/selectionComposer.test.ts src/components/chat/AttachmentGallery.test.tsx src/stores/chatStore.test.ts
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build:preview-agent
Tested: bun run check:desktop
Tested: git diff --check
Not-tested: Real Tauri webview click-through smoke; in-app Browser automation timed out while local Vite HTTP smoke returned 200.
Large desktop installs can accumulate huge JSONL transcripts, and the sidebar session list previously loaded each requested transcript into memory on cache misses. The main branch cache from #651 handles repeated hot refreshes, so this change keeps that cache and replaces cache-miss list metadata extraction with a sequential streaming summary scan for paginated files only. It also makes Windows sidecar shutdown prefer taskkill /T so stale child processes are less likely to survive app stop paths.
Constraint: Must preserve main's short session-list cache from #651 while reducing cache-miss memory growth.
Rejected: Rely only on the #651 cache | cache expiry, first load, and pagination still hit full JSONL reads.
Rejected: Add a persistent summary index | larger persistence migration risk than needed for this issue.
Confidence: medium
Scope-risk: moderate
Directive: Do not replace the streaming scanner with full readJsonlFile calls without re-running large-transcript pressure tests.
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: bun run check:server
Tested: bun run check:native
Tested: bun run check:desktop
Tested: synthetic pressure test with 140 sessions x 1200 JSONL entries showed lower RSS growth than main baseline.
Not-tested: Windows live taskkill /T process-tree cleanup.
Wire createPicker into the preview-agent IIFE: enter/exit picker via host messages, bind DOM mousemove/click (capture phase) to picker hover/select, and on click emit a selection event carrying ElementMetadata + annotated screenshot. Route the selection event in previewEvents.ts through buildSelectionComposerText into queueComposerPrefill with the screenshot attachment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tauri's desktop webview injects window.confirm through the dialog confirm command, but the default desktop capability only allowed the message dialog command. Windows release builds could therefore reject confirm at ACL time even though the browser-facing code path looked valid in local web development.
Constraint: Tauri plugin-dialog 2.7 still exposes window.confirm as plugin:dialog|confirm in the injected webview shim.
Rejected: Grant dialog:default | broader than the specific confirm compatibility gap.
Confidence: high
Scope-risk: narrow
Directive: Keep confirm permission covered while the desktop webview exposes browser confirm shims.
Tested: cd desktop && bun run test -- --run src/__tests__/tauriCapabilities.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Not-tested: Windows release package manual smoke
Prepare the desktop release metadata, concise release notes, and the final terminal help polish for the 0.3.1 release. The release note groups the post-0.3.0 work by user-facing area instead of listing every commit, and the desktop version metadata is aligned for the tag-triggered packaging workflow.
Constraint: GitHub Release body is sourced from release-notes/v0.3.1.md in the tagged commit
Rejected: List every post-0.3.0 commit in the release note | too noisy for this patch release
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- src/pages/TerminalSettings.test.tsx --run
Tested: bun run check:desktop
Tested: bun run check:native
Tested: bun run verify (passed=8 failed=0 skipped=2)
Not-tested: Live provider release gate
Desktop portable mode depends on CLI-driven installs using the same filesystem root as the app. The installed terminal launcher now carries CLAUDE_CONFIG_DIR into macOS/Linux shell invocations and uses a Windows cmd wrapper so plugin, skill, and MCP operations do not fall back to the native home config. Moved portable bundles also rebase cached plugin install paths when the cache exists under the current config root.
Constraint: Desktop portable bundles are file-system based and must survive zip/unzip relocation.
Rejected: Copy the sidecar binary directly into user bin | it cannot inject the selected portable config directory for future CLI installs.
Rejected: Rewrite plugin install paths unconditionally | missing cache directories should remain visible as broken state instead of being silently retargeted.
Confidence: high
Scope-risk: moderate
Directive: Keep desktop launcher wrappers as env-carrying sh/cmd files; do not revert to raw sidecar copies without portable install verification.
Tested: bun test src/server/__tests__/desktop-cli-launcher.test.ts src/utils/plugins/installedPluginsManager.test.ts
Tested: cargo test portable --manifest-path desktop/src-tauri/Cargo.toml
Tested: bun run check:server
Tested: bun run check:native
Tested: macOS launcher fixture plus Computer Use Finder verification of portable marker output.
Not-tested: Windows physical desktop execution; Windows wrapper behavior is covered by unit test only.
Bump version from 0.2.9 to 0.3.0 across desktop/package.json,
tauri.conf.json, and Cargo.toml. Add v0.3.0 release notes covering
desktop long-session performance, streaming tool previews,
AskUserQuestion reliability, multi-client streaming, and H5 network
fixes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This records the v0.2.9 release notes and aligns desktop package,
Tauri, and Cargo metadata so the release script can create the final
annotated tag after manual validation.
Constraint: Release tag creation is intentionally deferred for manual smoke validation.
Rejected: Run scripts/release.ts now | it would create the release commit and annotated tag before manual review.
Confidence: high
Scope-risk: narrow
Directive: Do not create v0.2.9 tag until the manual release check is complete.
Tested: bun run scripts/release.ts 0.2.9 --dry
Tested: bun run check:native
Not-tested: Full bun run verify and live ChatGPT Official OAuth smoke
The desktop release workflow expects app version files, Cargo.lock, and release-notes/vX.Y.Z.md to agree with the tag. Bump the desktop package and Tauri metadata to 0.2.8 and add the release note that will be used as the GitHub Release body.
Constraint: The release pipeline reads release-notes/v0.2.8.md from the tagged commit.
Confidence: high
Scope-risk: narrow
Directive: Keep desktop/package.json, Cargo.toml, tauri.conf.json, Cargo.lock, and release-notes/vX.Y.Z.md aligned before tagging.
Tested: Not rerun for this metadata-only release prep commit; previous push gate passed for the workflow fix immediately before this commit.
Not-tested: Full release workflow and packaged artifact smoke after tagging.
The previous portable-mode settings were hard to discover and mostly
explained through environment variables. Users could not pick a target
folder from the desktop UI or clearly understand which config directory
would become active after switching modes.
This moves the control to a lower-priority storage section, makes the
active directory source explicit, supports choosing a portable data
folder, and prepares the desktop app for a controlled restart so the
new storage location takes effect.
Constraint: Directory picking and relaunch require the Tauri desktop runtime
Rejected: Keep environment-variable-only setup | users could not discover or validate the target path from the app
Confidence: high
Scope-risk: moderate
Tested: cd desktop && bun run test -- generalSettings settingsStore
Tested: bun run check:desktop
Tested: bun run check:native
Tested: bun run check:coverage
Tested: bun run verify
Tested: Maintainer manual desktop UI test
Not-tested: Windows relaunch path beyond existing native coverage
Remote main carries portable-mode, legacy Windows workdir recovery, and Feishu path-safety fixes while local main carries terminal shell, update proxy, slash-command, prompt-draft, AskUserQuestion, background-work, and shell-env changes. This merge keeps both lines by layering portable Bash-path defaults underneath the desktop terminal shell preference and preserving both update-proxy and app-mode settings state.
Constraint: Local main and origin/main diverged after v0.2.7 and both lines contain release-relevant desktop/runtime fixes
Rejected: Prefer either side's terminal settings wholesale | would drop either Windows portable Bash support or explicit desktop startup-shell support
Confidence: medium
Scope-risk: moderate
Directive: Keep portable Bash path as the system-default terminal fallback; explicit desktop startup-shell settings should continue to override it
Tested: cd desktop && bun run test -- --run src/pages/TerminalSettings.test.tsx src/stores/settingsStore.test.ts
Tested: cd desktop/src-tauri && cargo test terminal -- --nocapture
Tested: bun test src/server/__tests__/sessions.test.ts -t stale worktree
Tested: bun run check:desktop
Tested: bun run check:server
Tested: bun run check:native
Not-tested: Manual Windows packaged-app terminal/portable smoke
Desktop update downloads currently depend on the updater HTTP stack and can miss the proxy users already rely on for GitHub access. The change enables OS proxy discovery in the native updater client and adds a narrow manual proxy fallback scoped only to update checks and package downloads.
Constraint: Tauri updater carries the proxy from check through download, so changing proxy settings after a check must discard the pending update and re-check before install
Rejected: Reuse provider proxy settings | provider traffic and updater traffic have different scope and persistence risks
Confidence: high
Scope-risk: moderate
Directive: Keep update proxy settings scoped to app updates; do not mix them with model/provider proxy configuration without a separate migration decision
Tested: cd desktop && bun run test -- --run src/__tests__/generalSettings.test.tsx src/stores/updateStore.test.ts src/stores/settingsStore.test.ts src-tauri/tauri-config.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Not-tested: Full coverage gate intentionally skipped after maintainer said it was not needed
The desktop terminal defaulted to COMSPEC on Windows, which commonly lands on cmd.exe and makes the settings terminal feel broken for users who expect PowerShell. This change adds a desktop-only terminal startup-shell setting in Settings, keeps the existing system default untouched unless the user opts in, and resolves the selected shell inside the Tauri PTY spawn path so docked terminals, terminal tabs, and the settings terminal stay aligned.
Constraint: Existing terminal sessions and non-Windows defaults must keep their current behavior unless a Windows user explicitly changes the setting
Rejected: Reuse settings.defaultShell | that setting already controls CLI ! commands and would couple unrelated shell semantics
Rejected: Flip Windows default to pwsh automatically | too risky for users whose current COMSPEC-based terminal already works
Confidence: high
Scope-risk: moderate
Reversibility: clean
Directive: Keep desktop terminal shell selection separate from CLI shell routing unless both paths are redesigned together
Tested: cd desktop && bun run test -- src/stores/settingsStore.test.ts src/pages/TerminalSettings.test.tsx
Tested: cd desktop/src-tauri && cargo test desktop_terminal_shell_resolution -- --nocapture
Tested: bun run check:desktop
Tested: bun run check:native
Not-tested: Real interactive spawn on a physical Windows machine
The contributor PR adds useful Windows terminal and portable mode support, but it also reintroduced an older General settings zoom block and left the new native settings paths without enough regression coverage. This commit keeps the feature direction intact while removing the duplicate UI, making invalid bash paths fail at save time, and covering the portable cache and app-mode paths with focused tests.
Constraint: This commit lands directly on the contributor PR branch to avoid a long review-comment loop.
Rejected: Ask the contributor to rework the PR from scratch | the remaining issues are narrow and maintainable by us.
Confidence: high
Scope-risk: moderate
Directive: Keep future portable-mode changes covered at the native boundary and the desktop store boundary.
Tested: cd desktop && bun run test src/pages/TerminalSettings.test.tsx src/__tests__/generalSettings.test.tsx src/stores/settingsStore.test.ts
Tested: bun test src/utils/__tests__/cachePaths.test.ts
Tested: cd desktop/src-tauri && cargo test
Tested: cd desktop && bun run lint
Tested: cd desktop/src-tauri && cargo check
Tested: bun run check:server
Tested: bun run check:desktop
Not-tested: Manual Windows packaged-app portable-mode smoke; to be covered before a future release.
The release branch has moved substantially past v0.2.6, so this records the desktop version bump and the release note that will be reviewed before the tag is created. The note groups the large post-v0.2.6 range by user-facing areas instead of replaying the raw commit list.
Constraint: The user wants to push the release-prep commit for manual GitHub development testing before any tag is created.
Rejected: Run scripts/release.ts directly | it would create the release commit and annotated tag before review.
Confidence: high
Scope-risk: narrow
Directive: Do not create v0.2.7 tag until manual GitHub validation is complete.
Tested: bun run scripts/release.ts 0.2.7 --dry
Tested: git diff --check
Not-tested: Full release gate or tag-triggered release workflow.
This brings the desktop memory worktree onto local main after main advanced with opener, IM, zoom, and autonomous goal work. The conflict resolution keeps both the selected-chat reference imports and memory event settings entrypoint in MessageList, and keeps both open-targets and memory API routes in the server router.
Constraint: main and feat/desktop-memory-surface diverged across desktop chat and server routing.
Constraint: desktop Vitest runs src-tauri tests under Vitest, so the Tauri config test cannot import bun:test.
Rejected: Fast-forward merge | main carried newer local commits not present on the memory branch.
Confidence: high
Scope-risk: moderate
Directive: Keep chat selection references, memory cards, open-target routes, and memory routes together when touching these files.
Tested: bun run check:desktop
Tested: bun run check:server
Tauri WebView was allowed to call the desktop sidecar API, but the CSP still blocked image loads from that same local server, so extracted IDE icons degraded to the generic code glyph in packaged builds. macOS detection also trusted command shims before app bundles, which let stale JetBrains Toolbox scripts keep removed IDEs visible.
Constraint: Opener icons are served by the per-run desktop sidecar on localhost or 127.0.0.1
Rejected: Bundle a fixed static icon set | the product should use detected installed application icons across platforms
Rejected: Trust macOS command shims for detection | stale shims survive app removal and make the menu lie
Confidence: high
Scope-risk: narrow
Directive: Keep macOS IDE detection anchored to real app bundles before accepting command shims
Tested: bun test src/server/__tests__/open-target-service.test.ts src/server/__tests__/open-target-api.test.ts desktop/src-tauri/tauri-config.test.ts
Tested: cd desktop && bun run test -- src/api/client.test.ts src/api/openTargets.test.ts src/stores/openTargetStore.test.ts src/components/layout/OpenProjectMenu.test.tsx src/components/layout/TabBar.test.tsx
Tested: cd desktop && bun run lint
Bring the detached worktree implementation for issue #407 back into
local main while preserving a merge boundary for review and rollback.
Constraint: Local main already contains post-release-boundary desktop fixes
Confidence: high
Scope-risk: narrow
Tested: bun run verify in detached worktree before merge
Not-tested: Full gate on local main before this merge commit