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
The sidebar title area also needs to participate in Electron's CSS app-region chrome. Mark only the sidebar title/header region as draggable and keep the full sidebar body out of the drag region so session rows, search controls, and project actions remain normal interactions.
Constraint: Electron window dragging is driven by CSS app-region regions after the migration
Rejected: Keep the sidebar-wide startDragging mouse handler | Electron does not use that as the active drag path and it misses the left title gap
Confidence: high
Scope-risk: narrow
Directive: Keep sidebar body interactions outside the drag region unless a real titlebar affordance is added there
Tested: cd desktop && bun run test src/components/layout/Sidebar.test.tsx --run
Tested: bun run check:desktop
Separate quarantine review enforcement from server and coverage file selection so expired review dates fail only the governance lane.
Refresh stale server quarantine suites and keep only the live provider test quarantined for non-live PR gates.
Tested: bun run check:policy
Tested: bun run check:server
Tested: bun run check:coverage
Tested: bun run verify
Tested: git diff --check
Confidence: high
Scope-risk: moderate
Drop the explanatory comment added earlier - notifications work as-is, so the
notification service stays byte-for-byte identical to main.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a CSP meta tag that hardens default-src/object-src/base-uri while keeping
script/style 'unsafe-inline'+'unsafe-eval' (Emotion CSS-in-JS injects runtime
<style> tags, the startup watchdog is inline, shiki/mermaid/Vite use eval) and a
permissive connect-src (localhost sidecar + ws + https) so renderer fetches and
dev HMR keep working. Needs a runtime smoke on dev + packaged builds before any
tightening.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- serverRuntime injects CLAUDE_CODE_POWERSHELL_PATH from the user's chosen shell
(readDesktopTerminalConfig + resolveDesktopTerminalShell) on Windows, so the
agent PowerShellTool honors the same shell as the UI terminal. Best-effort:
never blocks startup, never overrides an explicit env var, only forwards
pwsh/powershell selections (not cmd/custom). Regression from the Tauri build.
- document that notificationPermissionState reflects OS capability, not macOS
authorization (no Electron API exists; the 'failed' lifecycle is the real
signal) instead of calling the non-existent systemPreferences.getNotificationSettings
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
killSidecar gains a sync flag (spawnSync taskkill on Windows); serverRuntime
stopAll threads it through; before-quit now shuts down synchronously so the
Windows taskkill completes before the process exits.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- applyWindowsAppUserModelId() so Windows attributes toast notifications to the
app (kept in sync with build.appId via a test); no-op on macOS/Linux
- main window: setWindowOpenHandler denies uncontrolled popups, routes http(s)
links to the system browser; intentionally no will-navigate guard so dev HMR
reloads keep working
- preview view: denies popups + blocks non-http(s) navigation (file:/custom
schemes) while allowing in-page http(s) browsing
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- mac.notarize=true + hardenedRuntime + entitlements so a signed CI release
actually notarizes (gatekeeper smoke + Squirrel.Mac auto-update need it)
- entitlements grant disable-library-validation for the Bun sidecar/node-pty
- local unsigned build passes -c.mac.notarize=false so electron:package still
works without an Apple account
- release signing-preflight now hard-requires only the Apple secrets; Windows
cert is optional (unsigned NSIS still auto-updates, just SmartScreen warning)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bare absolute paths like /icons/bilibili.svg failed under Electron's
file:// protocol. Route them through publicAssetPath so they resolve
against the relative base URL, matching the GitHub and app icons.
The Electron packaging output directory is generated locally and should stay out of source control alongside the existing desktop build output ignores.
Constraint: desktop/electron-dist/ is local build output, not a product source artifact.
Confidence: high
Scope-risk: narrow
Tested: git check-ignore -v desktop/electron-dist/
Tested: git diff --check
Electron handles custom draggable chrome through CSS app-region rules, not the old runtime startDragging path. Mark the tab strip and empty scroll gutter as native drag regions while keeping tab items and controls explicitly no-drag so tab reordering and close/tool buttons keep receiving pointer events.
Constraint: Electron drag regions swallow pointer events unless interactive children are marked no-drag
Rejected: Keep calling startDragging from the empty gutter | Electron desktopHost does not expose that as the active migration path
Confidence: high
Scope-risk: narrow
Directive: Do not mark tab items themselves as drag regions without revalidating tab reorder behavior
Tested: cd desktop && bun run test src/components/layout/TabBar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: bun run check:desktop
/agent should behave like a normal session prompt that tells the main model to use the selected Agent tool. The previous forked command path buffered the subagent run behind local command output and forced desktop clients to wait for command completion instead of seeing the normal Agent interaction stream.
Constraint: Desktop /agent must preserve ordinary chat/session semantics and still require /agent <agent> <prompt>.
Rejected: Keep slash_agent SDK event bridging | it preserves the separate forked execution path instead of fixing the product flow.
Confidence: high
Scope-risk: moderate
Directive: Do not move /agent back to context: fork without proving the desktop normal Agent tool stream still works.
Tested: bun test src/commands/agent.test.ts src/utils/processUserInput/processSlashCommand.test.ts src/server/__tests__/ws-memory-events.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx
Tested: git diff --check
Not-tested: bun run check:server is blocked before source checks by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
The chat reference action was still tied too closely to message-local
mouseup timing, and the floating fixed-position control stayed inside
virtualized message DOM. In Electron Chromium that made multi-line ranges
race selection settlement and let transformed ancestors offset the button
away from the viewport position we calculated.
This reads settled document selections after pointerup/selectionchange,
portals the action to document.body, and prefers right-side placement for
multi-line selections.
Constraint: Electron Chromium selectionchange can settle after message-local mouse events
Rejected: Keep the popover inside the message node | transformed/virtualized ancestors offset fixed positioning in real browser layout
Confidence: high
Scope-risk: narrow
Directive: Keep chat selection actions portaled; do not reparent under virtualized message rows without browser-coordinate verification
Tested: cd desktop && bun run test -- src/components/chat/MessageList.test.tsx
Tested: bun run check:desktop
Tested: Playwright Chromium smoke for multi-line selection, single-line selection, and outside-click dismissal on local desktop harness
The desktop /agent slash path runs before the normal query loop, so the old implementation waited for the forked command to finish and only surfaced the final local-command stdout. Emit foreground slash-agent task events from /agent, drain SDK events while QueryEngine waits for pre-query slash processing, and allow those current-turn events through the WebSocket pre-send mute gate.
Constraint: /agent is a forked slash command that does not produce ordinary assistant deltas until its final stdout is synthesized.
Rejected: Frontend-only loading state | would not expose real forked-agent progress or tool/tool-result updates.
Confidence: high
Scope-risk: moderate
Directive: Keep slash_agent task events scoped to /agent; ordinary slash command stdout and /goal event handling should remain on the existing local-command paths.
Tested: bun test src/QueryEngine.test.ts src/utils/processUserInput/processSlashCommand.test.ts src/server/__tests__/ws-memory-events.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx
Not-tested: bun run check:server is blocked by expired quarantine review entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Async title refresh runs after assistant output, so provider prompts can be biased by assistant language and English title examples. The title language now resolves from the first meaningful user message before consulting the response-language fallback, then retries once when a generated title violates that language.
Constraint: Desktop response-language settings still control assistant prose, not automatic title metadata when the first user message has a clear language
Rejected: Follow response-language setting for every generated title | Chinese sessions flip to English when replies are configured in English
Rejected: Persist mismatched generated titles after retry failure | preserves a bad UX over the safer first-message placeholder
Confidence: high
Scope-risk: moderate
Directive: Do not change automatic title language precedence without re-testing image/text first-turn sessions and English-response-language sessions
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts -t "refreshes the first-turn AI title"
Tested: git diff --check
Tested: real MiniMax-M3 /tmp session 58a47fcd-6f9d-4685-bc73-f9317e3f330e with temporary response language english; assistant replied English and final aiTitle was 标题语言验证
Not-tested: bun run check:server blocked before tests by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Desktop title generation previously upgraded the first sidebar title from the raw user prompt before assistant output existed. That made image-plus-text sessions vulnerable to keeping a title based only on the user's initial wording. This moves polished title generation to completed turns, reuses the CLI title prompt and transcript extractor, and routes title calls through the configured haiku model with a retry when disabled thinking is rejected.
Constraint: The first user message still needs an immediate placeholder title so the sidebar is responsive.
Rejected: Generate the AI title before assistant output | image-derived context is only available after the assistant turn completes.
Confidence: high
Scope-risk: moderate
Directive: Keep polished automatic titles tied to completed transcript turns, not pre-response user prompts.
Tested: bun test src/server/__tests__/title-service.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts -t "refreshes the first-turn AI title"
Tested: git diff --check
Tested: Real MiniMax-M3 /tmp session f89073ed-3467-492a-b63c-e1886c146a3a with image attachment wrote ai-title "Validate session title generation"
Not-tested: bun run check:server is blocked by existing expired quarantine manifest entries
MiniMax's official M3 model page and release notes describe M3 as supporting up to a 1M-token context window with a guaranteed minimum of 512K. Keep the built-in MiniMax preset aligned with that official default instead of inheriting the older 204.8K MiniMax generation limit.
Constraint: Official MiniMax M3 docs state the M3 API supports up to 1M tokens context window.
Rejected: Keep 204800 and rely on manual provider overrides | that makes the built-in MiniMax preset wrong for new users.
Confidence: high
Scope-risk: narrow
Directive: Do not copy MiniMax-M2.7's 204.8K window onto MiniMax-M3 without re-checking official M3 docs.
Related: https://www.minimax.io/models/text/m3
Related: https://www.minimax.io/blog/minimax-m3
Tested: git diff --check
Tested: bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/providers-real.test.ts src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts src/utils/__tests__/context.test.ts
Not-tested: bun run check:server blocked before execution by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Desktop chat can fall back to persisted transcript estimates when live inspection context is unavailable. That path previously only used built-in model windows, so custom provider settings such as MiniMax-M3 with a 1,000,000-token window still displayed the default 200,000-token estimate. Resolve transcript context windows from the session or active provider runtime env first, then fall back to built-ins.
Constraint: Provider model context windows are stored in provider runtime env, not always in the server process env.
Rejected: Change the built-in MiniMax-M3 window to 1,000,000 | upstream preset correctly keeps MiniMax-M3 at 204,800 by default, while user overrides must remain provider-specific.
Confidence: high
Scope-risk: moderate
Directive: Keep transcript estimates aligned with session/provider runtime env before consulting built-in model defaults.
Tested: git diff --check
Tested: bun test src/server/__tests__/conversations.test.ts --test-name-pattern "active provider model context windows|Sonnet 4.6 transcript usage|low-trust media"
Tested: bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Tested: bun test src/server/__tests__/conversations.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Not-tested: bun run check:server blocked before execution by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Remote main includes PR #694, which updates the MiniMax preset to MiniMax-M3 and removes deprecated built-in MiniMax context-window entries. Merge that provider baseline before applying the transcript context-window estimate fix so the local line keeps upstream provider defaults.
Constraint: Remote main advanced independently with PR #694 while local main carried unreleased commits.
Rejected: Reset local main to origin/main | would discard local-only main commits.
Confidence: high
Scope-risk: moderate
Directive: Preserve MiniMax-M3 provider preset changes when touching provider context-window logic.
Tested: bun test src/server/__tests__/conversations.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/utils/__tests__/context.test.ts src/utils/__tests__/contextBudget.test.ts
Not-tested: bun run check:server blocked by expired quarantine entries: server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Chat selection references could miss drag gestures that ended outside the
message bubble after the Electron migration. The chat transcript now tracks
selection gestures at the document pointer-up boundary and repositions the
shared selection action near the selected text with above-then-right placement.
Constraint: Electron/WebView selection ranges are not always stable during the message-local mouseup event
Rejected: Add a new selection popover system | the existing shared selection hook already covers chat and workspace dismissal behavior
Confidence: high
Scope-risk: narrow
Directive: Keep chat and workspace selection popovers on the shared positioning/dismissal hook unless their behavior intentionally diverges
Tested: bun run test -- src/components/chat/MessageList.test.tsx -t "selected-message action"
Tested: bun run test -- src/components/chat/MessageList.test.tsx
Tested: bun run check:desktop
Tested: in-app browser smoke at http://127.0.0.1:5181/ with zero console errors
Not-tested: Packaged Electron manual drag selection smoke
Related: #351
Selecting a concrete /agent entry from the composer suggestions should prepare the command and leave focus in the editor so the user can type the required prompt. The Enter send shortcut still applies after the suggestion menu is closed, and exact non-agent slash commands keep their existing direct execution path when they remain highlighted.
Constraint: The desktop composer supports configurable Enter vs Ctrl/Cmd+Enter sending.
Rejected: Special-case only /agent entries | the highlighted suggestion should consistently win while the menu is open.
Confidence: high
Scope-risk: narrow
Directive: Keep ChatInput and EmptySession slash-key handling aligned with shared send shortcut behavior.
Tested: cd desktop && bun run test -- --run src/components/chat/composerUtils.test.ts src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: bun run check:desktop
Not-tested: Live backend agent-list integration beyond mocked desktop composer coverage.
Electron was showing the main BrowserWindow before renderer load completed, so macOS could paint a blank window surface behind the menu bar. Persisted y=0 window state could also restore the titlebar under the menu-bar work area on external displays. Delay the initial show until the renderer entry is loaded, clamp restored macOS bounds into the display workArea, skip the macOS status-bar tray, and unhide the app before focusing restored windows.
Constraint: macOS external displays expose menu-bar and status-item chrome differently from Windows and Linux.
Rejected: Remove the native application menu | it would break expected macOS menu behavior without fixing the pre-load window surface.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce pre-load main-window show without validating macOS external-display menu-bar rendering.
Tested: cd desktop && bun test electron/services/windows.test.ts electron/services/tray.test.ts electron/services/singleInstance.test.ts electron/services/menu.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Tested: git diff --check
Not-tested: Live dual-external-monitor screenshot smoke.
Complete the Electron replacement boundary before merging by removing the renderer-side Tauri host fallback, tightening H5/browser access so only desktop navigation is tokenless, and moving desktop release publication to a tag-driven GitHub Actions matrix with a single final publish job.
Constraint: H5/browser capability access must not gain tokenless access through localhost or retired Tauri origins
Constraint: Desktop release artifacts must be built by GitHub Actions from version tags, not treated as local build outputs
Rejected: Keep localhost browser origins trusted for convenience | local browser contexts can access loopback services and must use the H5 token path
Rejected: Publish from each matrix job | partial releases can be created before all platforms finish
Confidence: high
Scope-risk: broad
Directive: Do not reintroduce Tauri origins or localhost browser origins into the trusted desktop origin set without a reviewed security design
Tested: bun test src/server/__tests__/h5-access-policy.test.ts src/server/__tests__/h5-access-auth.test.ts src/server/__tests__/diagnostics-service.test.ts src/server/middleware/cors.test.ts
Tested: bun test scripts/pr/release-workflow.test.ts scripts/release-update-metadata.test.ts
Tested: bun run check:desktop
Tested: bun run check:native
Tested: git diff --check
Not-tested: bun run check:server is blocked by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Electron desktop runs network-sensitive OpenAI OAuth token exchange in the sidecar process, so the sidecar now receives system proxy env derived from Electron's cross-platform proxy resolver and the OAuth token client uses the existing proxy fetch options. General manual proxy settings also document and preserve authenticated proxy URLs.
The macOS fullscreen black-screen path is addressed by avoiding native fullscreen Spaces for app fullscreen toggles and by leaving fullscreen before hiding or closing the window.
Constraint: Electron packaged apps may not inherit shell HTTPS_PROXY env when launched from Finder.
Constraint: Manual authenticated proxies must remain standard HTTP(S) proxy URLs for Bun/undici compatibility.
Rejected: Store proxy username and password as separate fields | would require new secret-storage semantics and migration beyond this bugfix.
Rejected: Use native macOS fullscreen Spaces for the desktop app | reproduced black-screen behavior when hiding/closing from fullscreen.
Confidence: high
Scope-risk: moderate
Directive: Do not remove sidecar proxy env injection without retesting OpenAI OAuth from a packaged app launched outside a shell.
Tested: bun test src/services/openaiAuth/client.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts
Tested: bun test src/server/__tests__/network-settings.test.ts
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx --run
Tested: cd desktop && bun run check:electron
Tested: git diff --check
Not-tested: bun run check:server blocked by expired quarantine entries server:cron-scheduler, server:providers-real, server:tasks, server:e2e:business-flow, server:e2e:full-flow
Not-tested: live OpenAI OAuth through a corporate authenticated proxy