369 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
71ce980f1c fix: make goal completion durable through stop hooks
The goal command now uses a session Stop hook as the durable completion mechanism and removes the separate evaluator path. Completion output is persisted as local command output so CLI streams, transcripts, and desktop history all see the same completed state.

Desktop keeps active goals in a compact header strip and lets completed goals render in the conversation flow, which avoids the old duplicate pinned card behavior while preserving visibility for running goals.

Constraint: /goal state has to survive transcript replay and desktop session restore.
Rejected: Keep the legacy evaluator alongside Stop hooks | duplicate completion paths made desktop state drift and hid the final card.
Confidence: high
Scope-risk: moderate
Directive: Keep goal completion events on the local_command transcript path unless desktop history restore is changed at the same time.
Tested: bun test src/goals/goalState.test.ts src/query/stopHooks.test.ts src/commands/goal/goal.test.tsx src/commands/headless.test.ts src/server/__tests__/ws-memory-events.test.ts src/server/__tests__/sessions.test.ts
Tested: bun run check:server
Tested: bun run check:desktop
Tested: real /tmp /goal CLI run 98fb4bb2-52da-4850-bc8e-e5e1cc0e4c51 with deepseek-v4-pro and WebUI screenshot verification
Not-tested: Remote release workflow
2026-05-18 22:30:18 +08:00
程序员阿江(Relakkes)
8ee4bf682a fix: restore local main fixes stranded in worktrees
Bring back the narrow, previously validated sidebar recovery and Windows x64 sidecar compatibility fixes that were present on worktree branches but absent from the canonical local main checkout. The broader worktree branch is intentionally not merged because it would replay unrelated history and risk dropping current main work.

Constraint: The local main worktree already contains unrelated Settings and portable storage edits, so only the recovery hunks are staged.

Rejected: Merge 1506086927/main wholesale | its history includes broad rollback/replay commits that would remove current main changes.

Confidence: high

Scope-risk: narrow

Directive: Recover future worktree fixes by cherry-picking or staging narrow hunks; do not merge drifted worktree branches wholesale.

Tested: cd desktop && bun run test -- --run src/components/layout/Sidebar.test.tsx scripts/build-sidecars.test.ts

Not-tested: Full bun run verify due unrelated dirty Settings/portable-storage worktree changes.
2026-05-18 22:28:04 +08:00
程序员阿江(Relakkes)
4b76319781 Merge background task UI state fix into main
This brings the detached worktree fix for desktop background-task visibility into the local main branch while preserving the main branch updates that landed after the worktree base.

Constraint: The source worktree was detached from an older main ancestor
Rejected: Fast-forward merge | local main has newer commits and cannot fast-forward to the detached worktree commit
Confidence: high
Scope-risk: narrow
Tested: bun run verify
Not-tested: No live provider baseline was run because this was a desktop UI state fix and the PR gate used non-live checks
2026-05-18 15:14:20 +08:00
程序员阿江(Relakkes)
3511f30978 fix(desktop): prevent completed turns from hiding active background work
The CLI can emit a completed assistant turn while local background bash or task work continues. The desktop transcript and header now keep that background activity visible without converting the composer into a global stop state.

Constraint: Preserve CLI turn semantics where message_complete means the current assistant turn is done, not every background task is finished
Rejected: Treat background tasks as composer-active generation | this blocks follow-up input even though the CLI keeps the session responsive
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- --run src/components/chat/MessageList.test.tsx src/components/chat/ChatInput.test.tsx src/pages/ActiveSession.test.tsx
Tested: bun run check:desktop
Tested: bun run verify
2026-05-18 15:12:49 +08:00
程序员阿江(Relakkes)
0506452a1b Merge commit '2b5bf56475c5a8afd2ccd40df4e63e58d4d88c87' 2026-05-18 14:41:13 +08:00
程序员阿江(Relakkes)
2b5bf56475 Make selection actions track selected text instead of the cursor
The add-to-chat popover was keyed off the mouse-up location, so broad selections could cover the selected text and stale popovers could remain visible. Shared placement and dismissal logic now anchors the action to the selected range, prefers the space above the selection like Codex App, and clears stale selections on outside clicks.

Constraint: Desktop chat and workspace previews share the same selection affordance and must keep their existing add-reference behavior.

Rejected: Keep cursor-based placement | it can hide selected text and makes multi-line selections unpredictable.

Confidence: high

Scope-risk: moderate

Directive: Keep future selection actions range-anchored and outside-click dismissible across chat and workspace surfaces.

Tested: bun run check:desktop

Tested: Browser verification on http://127.0.0.1:5174 showed the popover above selection, no overlap, and outside click clearing it.

Not-tested: Native packaged Tauri window.

Related: https://github.com/NanmiCoder/cc-haha/issues/484
2026-05-18 14:40:56 +08:00
程序员阿江(Relakkes)
6ff76171af fix: preserve unsent desktop prompts across tab switches
Desktop non-session tabs unmount the active chat composer, so component-local draft refs disappeared before users returned to the session. Move the draft into per-session chat state and save it at session-switch and unmount boundaries, then clear it after submit.

Constraint: Settings and terminal tabs replace ActiveSession in ContentRouter.
Rejected: Persist drafts in localStorage | would add unnecessary persistence migration surface for a runtime-only draft.
Confidence: high
Scope-risk: narrow
Directive: Keep composer draft state scoped per session; do not move it back into component-only refs without covering unmount and remount.
Tested: bun run test src/components/chat/ChatInput.test.tsx --run
Tested: bun run check:desktop
Tested: bun run verify
2026-05-18 14:40:52 +08:00
程序员阿江(Relakkes)
331372e866 Keep multi-question replies isolated in AskUserQuestion
AskUserQuestion used one free-text value for every tab, so typing a custom response on one question leaked into the next and option selection could erase another question's answer. Store free-text answers per question index and submit the per-question answer map so mixed custom and option replies stay intact.

Constraint: Multiple questions share one AskUserQuestion component instance
Rejected: Keep a single free-text fallback | it cannot distinguish which question owns the custom reply
Confidence: high
Scope-risk: narrow
Directive: Keep custom text and option state scoped to a question index when changing this component
Tested: Reproduced in Web UI on 127.0.0.1:1420 with server 127.0.0.1:4678 and deepseek-v4-pro in /private/tmp
Tested: cd desktop && bun run test -- AskUserQuestion.test.tsx --run
Tested: bun run verify
Not-tested: none
2026-05-18 14:23:47 +08:00
程序员阿江(Relakkes)
8ecc757729 Hide unfinished goal command entrypoints
The goal implementation is being kept in the tree for later redesign, but the CLI and desktop slash-command surfaces should not advertise or route new users into it while the long-running goal experience is incomplete. Existing transcript parsing and goal event rendering remain intact so historical sessions still load.

Constraint: Keep the implementation code available for future iteration while removing discoverable entrypoints.
Confidence: high
Scope-risk: narrow
Directive: Do not re-expose /goal until the persistent goal/runtime design is revisited.
Tested: bun test src/commands/headless.test.ts
Tested: cd desktop && bun run test -- composerUtils.test.ts pages.test.tsx
Tested: NODE_ENV=test ANTHROPIC_API_KEY=dummy bun -e getCommands assertion for hidden goal command
2026-05-17 00:05:50 +08:00
程序员阿江(Relakkes)
d2d27b3845 Avoid noisy stopped states for background agents
Goal sessions were showing stopped background-agent cards because the parent model used TaskStop after reading enough partial review output. That writes a killed task notification, which the desktop then rendered like a failure.

TaskStop and async agent launch guidance now make cancellation an exceptional action rather than a normal cleanup step. Stopped background-agent transcript cards also render as neutral interrupted events instead of error-styled failures.

Constraint: Background agent task notifications must remain truthful; killed tasks still surface as stopped instead of being hidden.

Rejected: Hide stopped notifications in /goal sessions | this would mask real user cancellations and runaway-task stops.

Confidence: medium

Scope-risk: narrow

Directive: Do not encourage parent turns to kill background agents only because partial output was read.

Tested: cd desktop && bun run test src/components/chat/MessageList.test.tsx -t "renders stopped background agents as neutral transcript events"

Tested: cd desktop && bun run lint

Tested: bun run check:server
2026-05-16 23:04:02 +08:00
程序员阿江(Relakkes)
45b6674726 Place goal background work in the transcript
Goal runs spawn visible background work while the conversation is active, so the desktop should show those events at their actual transcript position instead of pinning a separate panel above the chat. The UI now renders background task records as inline message events, repairs restored task state from transcript notifications, and keeps later task updates on the original event card.

Constraint: Existing transcripts only persist terminal task notifications, so the server now preserves their timestamps for deterministic restore ordering.

Rejected: Keep the page-level background-agent panel | it occluded the session content and duplicated message-flow information.

Confidence: high

Scope-risk: moderate

Directive: Background task message timestamps intentionally stay fixed after insertion; update the task content without moving the card in the transcript.

Tested: cd desktop && bun run test -- src/stores/chatStore.test.ts src/pages/ActiveSession.test.tsx src/components/chat/MessageList.test.tsx

Tested: cd desktop && bun run lint

Tested: bun test src/server/__tests__/sessions.test.ts
2026-05-16 21:38:52 +08:00
程序员阿江(Relakkes)
2d7d11d822 Reduce formula-heavy chat render cost
Formula-heavy conversations were still expensive after removing the fixed-height virtual chat window because every render repeated KaTeX expansion and HTML post-processing. Keep readable math, but reduce the DOM and CPU cost by rendering KaTeX without the hidden MathML copy, caching repeated formula output, and memoizing enhanced HTML parts outside the JSX render path.

Constraint: H5 streaming scroll follow behavior must remain unchanged
Rejected: Restore fixed-height virtualization | it caused blank gaps for variable-height math and code messages
Rejected: Disable LaTeX rendering | formula readability is a user-facing feature
Confidence: medium
Scope-risk: narrow
Directive: Do not reintroduce estimated-height chat virtualization without measured row heights for math-heavy messages
Tested: cd desktop && bun run test -- MarkdownRenderer.test.tsx MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: git diff --check
Not-tested: Manual desktop scroll trace on the user's formula-heavy production conversation
2026-05-16 17:14:15 +08:00
程序员阿江(Relakkes)
5e899bb1a1 Restore reliable long chat scrolling
The fixed-height virtual window introduced after v0.2.6 assumed every rendered chat item was 96px tall. Real desktop messages include markdown, math, code blocks, tool groups, and agent cards with highly variable heights, so scrolling history could replace real content with incorrectly sized blank spacer regions and make tab restoration janky.

Remove that unsafe virtualization layer and keep the existing direct scroll restoration behavior. The regression tests now keep long mixed-height transcripts and tool-call histories mounted so variable-height rows cannot disappear behind fake spacer math again.

Constraint: Desktop chat rows have unbounded variable height from markdown, KaTeX, code, tool, and agent output.
Rejected: Tune the 96px estimate | any constant row height still fails for mixed markdown and tool output.
Rejected: Add measured virtualization now | larger change surface than needed for the production white-gap regression.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce chat virtualization without real row-height measurement and scroll restore coverage.
Tested: cd desktop && bun run test -- MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: git diff --check
2026-05-16 16:45:59 +08:00
程序员阿江(Relakkes)
7f74f1bde7 Prevent removed goal subcommands from replacing goals
The simplified /goal surface only supports setting a condition and clearing it. Removed subcommand names such as status were still valid free-form objectives, so a user trying the old query flow could overwrite the real goal with a goal named status and make the desktop state look stuck in progress.

Constraint: /goal should stay as /goal <condition> and /goal clear for the prelaunch simplified UX

Rejected: Reintroduce /goal status | it expands the command surface the product direction intentionally removed

Confidence: high

Scope-risk: narrow

Directive: Do not add pseudo subcommands back to the desktop picker unless the CLI command surface is deliberately expanded again

Tested: bun test src/commands/goal/goal.test.tsx src/goals/goalState.test.ts src/goals/goalEvaluator.test.ts src/server/__tests__/ws-memory-events.test.ts

Tested: cd desktop && bun run test -- --run src/components/chat/composerUtils.test.ts src/__tests__/pages.test.tsx src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx
2026-05-16 14:00:48 +08:00
程序员阿江(Relakkes)
5c5c5933f0 Preserve composer command popovers after drag-drop support
Drag-drop support made the composer panel clip overflow so the
stateful slash and file popovers still opened but were hidden above
the panel. Restore visible overflow on the drop target while keeping
the drop overlay and attachment flow intact, then lock both active
and empty composer surfaces with regression coverage.

Constraint: Drag-drop attachments must continue using the existing path-only composer pipeline
Rejected: Move slash and file menus outside the composer tree | broader portal refactor not needed for this regression
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce overflow clipping on composer panels without proving bottom-full popovers still render
Tested: cd desktop && bun run test -- --run src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: Browser smoke at http://127.0.0.1:1421/?serverUrl=http%3A%2F%2F127.0.0.1%3A3456 for / and @src popovers
Tested: bun run check:desktop
2026-05-16 13:49:21 +08:00
程序员阿江(Relakkes)
b6fcd9e422 Merge readable math rendering into desktop main
Bring the desktop markdown LaTeX renderer back into the local main line
without folding unrelated local release edits into the merge commit.

Constraint: Local main had uncommitted release changes, so they were preserved outside the merge and restored afterward
Confidence: high
Scope-risk: narrow
Directive: Keep future markdown rendering changes covered by focused renderer tests before broad desktop gates
Tested: bun run test --run src/components/markdown/MarkdownRenderer.test.tsx
Tested: bun run lint
Tested: bun run build
Tested: WebUI complex formula screenshot and 390px viewport overflow check
Not-tested: Full desktop gate still has unrelated /goal command hint expectation drift
2026-05-16 13:29:59 +08:00
程序员阿江(Relakkes)
7d2836643c Render model math as readable desktop markdown
Desktop assistant responses previously showed LaTeX source for common
model outputs. The markdown renderer now extracts math outside code spans
and fences, renders it through KaTeX, and applies chat-safe layout rules
for inline, block, multiline, matrix, and long-form formulas.

Constraint: Desktop chat already forces long markdown text to wrap, so KaTeX internals must opt out of that wrapping while display blocks handle overflow locally
Rejected: Render all dollar-delimited text blindly | currency and escaped dollar text would become false-positive formulas
Confidence: high
Scope-risk: narrow
Directive: Keep math extraction before marked parsing and preserve code fence protection when extending markdown rendering
Tested: bun run test --run src/components/markdown/MarkdownRenderer.test.tsx
Tested: bun run lint
Tested: bun run build
Tested: WebUI complex formula screenshot and 390px viewport overflow check
Not-tested: Full desktop gate still has unrelated /goal command hint expectation drift
2026-05-16 13:29:08 +08:00
程序员阿江(Relakkes)
390c18d82c Let desktop users attach files by dropping them into the composer
A user-requested drag target should reuse the existing attachment pipeline instead
of creating a second upload path. The composer now handles browser DataTransfer
drops and Tauri native drag-drop events, while keeping desktop attachments
path-only so large files are not serialized into chat payloads. The fallback
/goal metadata is also aligned with the existing desktop command surface because
the desktop gate exercises that menu while validating composer behavior.

Constraint: Desktop attachments must remain path-only to avoid inflated websocket payloads
Rejected: Read dropped desktop files with FileReader | would reintroduce large inline data payloads
Confidence: high
Scope-risk: moderate
Directive: Do not replace the Tauri drag-drop path conversion with data URLs without rerunning payload-size regression coverage
Tested: cd desktop && bun run test -- --run src/lib/composerAttachments.test.ts src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: bun run check:desktop
Tested: agent-browser overlay and dropped-chip smoke at http://127.0.0.1:1421/?serverUrl=http%3A%2F%2F127.0.0.1%3A3456
Tested: bun run verify
Not-tested: Finder-to-packaged-.app manual drag smoke
2026-05-16 13:18:59 +08:00
程序员阿江(Relakkes)
818dc7a178 Merge simplified goal command into main
This merge carries the set/clear /goal behavior from the Codex worktree into local main while preserving main's memory-style desktop goal cards and compact active-goal banner.

Constraint: Local main already had unrelated version/Tauri/release-note worktree changes and a newer goal UI style.\nRejected: Overwrite main's goal card UI with the worktree version | user wanted the memory-style visual direction already present on main.\nConfidence: high\nScope-risk: moderate\nTested: bun test src/commands/goal/goal.test.tsx src/goals/goalState.test.ts src/goals/goalEvaluator.test.ts src/server/__tests__/ws-memory-events.test.ts src/server/__tests__/conversations.test.ts\nTested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx src/pages/ActiveSession.test.tsx src/components/chat/composerUtils.test.ts\nNot-tested: Full bun run verify on main was not rerun after merge because unrelated dirty release/version files are present in the main worktree.
2026-05-16 03:35:53 +08:00
程序员阿江(Relakkes)
606f3c0dc2 Simplify goal command into an immediate set-clear loop
The previous /goal surface exposed management subcommands that made the CLI and desktop behavior hard to reason about. This keeps the user-facing command close to Claude Code's set/clear interaction while preserving historical transcript hydration and the existing evaluator loop.

Constraint: Desktop must see a live goal event before the model reaches the next tool call.\nRejected: Keep status/pause/resume/complete slash subcommands | requested UX is only set and clear.\nConfidence: high\nScope-risk: moderate\nDirective: Keep /goal user-facing syntax compact; extend internals without expanding the slash picker unless product explicitly asks.\nTested: bun test src/commands/goal/goal.test.tsx src/goals/goalState.test.ts src/goals/goalEvaluator.test.ts src/server/__tests__/ws-memory-events.test.ts src/server/__tests__/conversations.test.ts\nTested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx src/pages/ActiveSession.test.tsx src/components/chat/composerUtils.test.ts\nTested: bun run check:server\nTested: cd desktop && bun run lint\nTested: cd desktop && bun run build\nTested: ./bin/claude-haha -p '/goal smoke verify immediate goal output' --output-format stream-json --include-partial-messages --max-turns 1 --no-session-persistence --verbose emitted immediate system.local_command_output before model stream\nTested: ./bin/claude-haha -p '/goal clear' --output-format stream-json --include-partial-messages --max-turns 1 --no-session-persistence --verbose exited with duration_api_ms=0 and No active goal\nNot-tested: Browser click smoke was blocked by Chrome DevTools transport closing and Computer Use cgWindowNotFound on this machine.
2026-05-16 03:28:48 +08:00
程序员阿江(Relakkes)
40852a804d Align goal UI with memory activity blocks
Goal status previously used a standalone success-card treatment, which made /goal look visually detached from the transcript. Rework the active goal strip and goal event cards to use the same compact memory/tool-result visual language.

Constraint: Preserve /goal state visibility while reducing alert-like chrome.

Rejected: Continue tuning only goal colors | the layout still read as a separate alert instead of transcript state.

Confidence: high

Scope-risk: narrow

Tested: cd desktop && bun run test -- --run src/components/chat/MessageList.test.tsx src/pages/ActiveSession.test.tsx src/theme/globals.test.ts

Tested: cd desktop && bun run test -- --run src/components/chat/MessageList.test.tsx src/pages/ActiveSession.test.tsx

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build
2026-05-16 02:28:14 +08:00
程序员阿江(Relakkes)
d76c09c3d6 Restore /goal as a single desktop slash command
The desktop composer had treated /goal lifecycle arguments as standalone slash-command rows. That made the UI look like /goal had second-level commands even though the CLI contract is one /goal command with arguments.

Constraint: Keep /goal status/pause/resume/complete/clear usable as CLI arguments.

Rejected: Keep pseudo subcommands in the picker | it contradicts the slash command model and confuses objective entry.

Confidence: high

Scope-risk: narrow

Tested: cd desktop && bun run test -- --run src/components/chat/composerUtils.test.ts src/__tests__/pages.test.tsx src/pages/EmptySession.test.tsx

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build
2026-05-16 01:59:06 +08:00
程序员阿江(Relakkes)
7dc0b59784 Refine goal UI around memory theme tokens
Goal status needed to read like persistent agent state, not a success alert. Reuse the Memory surface language and expose goal-specific aliases so the visual treatment follows each supported desktop theme.\n\nConstraint: Must keep /goal visible in both active-session chrome and transcript events.\nRejected: Continue using success tokens | they made the UI look like a warning/success card and clashed with white/dark themes.\nConfidence: high\nScope-risk: narrow\nTested: cd desktop && bun run test -- --run src/pages/ActiveSession.test.tsx src/components/chat/MessageList.test.tsx src/theme/globals.test.ts\nTested: cd desktop && bun run lint\nTested: cd desktop && bun run build\nTested: Chrome screenshot fixture for light, white, and dark goal UI tokens.
2026-05-16 01:49:38 +08:00
程序员阿江(Relakkes)
291dd3e07d Refine goal UI around memory theme tokens
Goal status needed to read like persistent agent state, not a success alert. Reuse the Memory surface language and expose goal-specific aliases so the visual treatment follows each supported desktop theme.\n\nConstraint: Must keep /goal visible in both active-session chrome and transcript events.\nRejected: Continue using success tokens | they made the UI look like a warning/success card and clashed with white/dark themes.\nConfidence: high\nScope-risk: narrow\nTested: cd desktop && bun run test -- --run src/pages/ActiveSession.test.tsx src/components/chat/MessageList.test.tsx src/theme/globals.test.ts\nTested: cd desktop && bun run lint\nTested: cd desktop && bun run build\nTested: Chrome screenshot fixture for light, white, and dark goal UI tokens.
2026-05-16 01:44:42 +08:00
程序员阿江(Relakkes)
929ddd0ebe Refine goal session presentation
Goal sessions need to feel like an ongoing agent-loop state, not a large success alert dropped into the chat. The UI now uses compact status and event treatments, and session titles stay anchored to the original goal objective instead of later /goal status commands.

Constraint: /goal history uses local_command transcript entries and later status checks can append fresh AI titles.
Rejected: Keep the existing green cards | they duplicate the objective, consume too much vertical space, and read as one-off notifications instead of durable loop state.
Confidence: high
Scope-risk: narrow
Directive: Goal status UI should remain compact and stateful; do not reintroduce large centered cards for routine lifecycle events.
Tested: bun test src/server/__tests__/sessions.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx src/pages/ActiveSession.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: Browser preview at 127.0.0.1:5179 with real session 3e9117d5-b792-43c9-bf57-7aec2b124f7e on desktop and mobile viewport
Not-tested: Packaged macOS app rebuild.
2026-05-16 01:28:09 +08:00
程序员阿江(Relakkes)
e77dd6d3cb Expose goal subcommands in desktop composer
The CLI supports /goal status, pause, resume, complete, clear, and --tokens as arguments, but the desktop composer only showed the top-level /goal entry and closed completion after the space. Users could run the commands if they knew them, yet the UI made them look unavailable.

Constraint: Keep CLI semantics unchanged; this is a desktop discovery and completion fix only

Rejected: Add separate CLI slash commands for every goal subcommand | would diverge from the actual command surface

Confidence: high

Scope-risk: narrow

Directive: Keep /goal subcommands as argument completions unless the CLI command model gains first-class nested slash commands

Tested: cd desktop && bun run test -- --run src/components/chat/composerUtils.test.ts src/components/chat/ChatInput.test.tsx

Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx src/pages/ActiveSession.test.tsx

Tested: cd desktop && bun run lint

Not-tested: live desktop manual interaction after restarting the app
2026-05-16 00:21:06 +08:00
程序员阿江(Relakkes)
b4a5c09b11 fix: expose plugin skills in new session slash commands
New desktop sessions populated slash suggestions from the session endpoint before the CLI had emitted init metadata. That endpoint only scanned user and project skill directories, while the plugin settings view and global skills API already saw enabled plugin skills such as superpowers. The session endpoint now reuses the global skill listing and merges it with any cached CLI slash commands, and both composer surfaces rank command-name matches before broad description matches so /su surfaces superpowers first.

Constraint: New sessions need plugin skills before the first real user turn starts the CLI.

Rejected: Start or restart a hidden CLI process on plugin enable | heavier than needed and still misses the REST slash-command fallback path.

Confidence: high

Scope-risk: moderate

Directive: Keep session slash commands and /api/skills on the same skill discovery path when changing plugin skill loading.

Tested: bun test src/server/__tests__/skills.test.ts src/server/__tests__/plugins.test.ts src/server/__tests__/sessions.test.ts

Tested: cd desktop && bun run test --run src/components/chat/composerUtils.test.ts src/pages/EmptySession.test.tsx src/components/chat/ChatInput.test.tsx

Tested: bun run check:server

Tested: cd desktop && bun run lint

Not-tested: Manual desktop click-through in the packaged app.
2026-05-16 00:03:44 +08:00
程序员阿江(Relakkes)
62713f30de Merge commit '376fc6de' 2026-05-15 23:27:02 +08:00
程序员阿江(Relakkes)
376fc6de62 Make /goal durable across CLI and desktop sessions
The goal flow needs to drive the agent loop and remain visible after desktop reconnects, so this change treats /goal output as a structured lifecycle signal across CLI, server, and desktop history restoration.

Constraint: The current TypeScript CLI does not share Codex's Rust app-server thread-goal database, so persistence is reconstructed from the existing session transcript.

Rejected: UI-only goal badges | would leave the CLI self-loop unable to recover active or completed goals after process restart.

Rejected: Add a new persisted store | larger migration surface than needed for the existing transcript-backed session model.

Confidence: high

Scope-risk: moderate

Directive: Keep future goal state changes mirrored in transcript-visible local command output or introduce a real migration-backed store.

Tested: bun test src/goals/goalEvaluator.test.ts src/goals/goalState.test.ts

Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/pages/ActiveSession.test.tsx src/components/chat/MessageList.test.tsx

Tested: bun run verify

Not-tested: Live provider baseline with a real model-driven goal loop.
2026-05-15 23:26:54 +08:00
程序员阿江(Relakkes)
80291715b4 fix: stop restored chats snapping to latest
Restored transcripts can still present stale running state while their final markdown and tool output continue to reflow. Resize-driven auto-follow now stays enabled only for live resizable output, so readers can scroll up after completion while active streams still remain pinned.

Constraint: Old H5 sessions can reconnect with stale non-idle UI state even when the transcript has an end_turn.
Rejected: Disable resize following entirely | active H5 streaming would regress when rendered content grows after tokens arrive.
Confidence: high
Scope-risk: narrow
Directive: Do not broaden ResizeObserver auto-follow without a restored completed-session regression test.
Tested: cd desktop && bun run test -- MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: Browser smoke on session 85862799-ec6b-43d0-b3b8-6e9fd9130954 kept scrollTop at 320 after content resize.
2026-05-15 21:58:31 +08:00
程序员阿江(Relakkes)
5871af11d4 Always reveal newly sent chat prompts
Sending from history must move the transcript to the new turn even if session state has not yet advanced from idle. The previous guard tied the jump to chatState, so a user_text tail that landed before thinking/streaming would be skipped permanently because the tail id no longer changed.

Constraint: The same MessageList path serves desktop and H5 chat.

Rejected: Wait for chatState to become thinking before scrolling | that misses updates where the message id is already recorded.

Confidence: high

Scope-risk: narrow

Directive: New user_text tail messages are intentional navigation events and must override historical scroll position.

Tested: cd desktop && bun run test -- MessageList.test.tsx

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build

Tested: git diff --check
2026-05-15 20:41:32 +08:00
程序员阿江(Relakkes)
76d472376b Keep H5 chat scrolling inside the message pane
iPhone Chrome uses the iOS WebKit viewport model, so using scrollIntoView on the transcript sentinel can ask the browser to scroll ancestor containers, including the page viewport. That is risky with the fixed bottom composer and can expose blank page space when the latest button is clicked. This keeps all latest-message movement scoped to the chat scroll element and follows post-render height changes while streaming.

Constraint: H5 and desktop share MessageList, but the H5 browser runs through iOS WebKit viewport behavior.

Rejected: Keep bottomRef.scrollIntoView with container options | container support is not reliable enough and the default still targets all scrollable ancestors.

Confidence: high

Scope-risk: narrow

Directive: Do not reintroduce transcript scrollIntoView without real iPhone Chrome verification.

Tested: cd desktop && bun run test -- MessageList.test.tsx

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build

Tested: git diff --check
2026-05-15 20:38:54 +08:00
程序员阿江(Relakkes)
059d2f0ee0 Merge desktop plugin hot refresh into main 2026-05-15 19:51:22 +08:00
程序员阿江(Relakkes)
de63d82633 fix: keep desktop plugin changes visible without restarting chats
Plugin enablement already has a live CLI reload control path, so desktop now applies plugin changes by refreshing the active session instead of waiting for a future conversation startup. The server forwards reload_plugins to the active CLI session, refreshes session slash-command cache, and notifies the client. The desktop plugin store automatically reloads after mutating plugin state, and the empty-session composer refetches skills when plugin capabilities change.

Constraint: Existing CLI exposes reload_plugins as the supported hot-refresh mechanism for commands, agents, plugins, and MCP state.

Rejected: Start a hidden replacement CLI process | higher cost, extra process lifecycle risk, and less precise than the existing control channel.

Confidence: high

Scope-risk: moderate

Directive: Keep plugin refresh routed through reload_plugins unless the CLI control contract is removed or changed.

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

Tested: cd desktop && bun run test --run src/stores/pluginStore.test.ts src/__tests__/pluginsSettings.test.tsx src/pages/EmptySession.test.tsx

Tested: bun run check:server

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build

Not-tested: bun run check:desktop is blocked by a pre-existing color-mix compatibility failure in desktop/src/theme/globals.css.
2026-05-15 19:51:01 +08:00
程序员阿江(Relakkes)
765d4244b4 Merge sidebar project controls cleanup 2026-05-15 19:37:15 +08:00
程序员阿江(Relakkes)
7bc22e971a Keep chat pinned to the newest turn during active output
H5 browsers can lag behind smooth scroll animations when streaming text grows, and sending a new prompt should always return the reader to the live turn even if they were browsing history. The message list now writes the scroll container directly while preserving the existing opt-out for manual history reading during assistant streaming.

Constraint: H5 and desktop share MessageList behavior
Rejected: Force-scroll on every streaming update | would break reading historical content during long replies
Confidence: high
Scope-risk: narrow
Directive: Preserve manual history reading except when a new user prompt is appended
Tested: cd desktop && bun run test -- MessageList.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Not-tested: Full check:desktop remains blocked by the existing vite-config color-mix assertion in globals.css
2026-05-15 19:37:07 +08:00
程序员阿江(Relakkes)
ba1ab98c2e fix: reduce risky sidebar controls to project organization
The sidebar now groups conversations by project, so the embedded project picker in the search box duplicated the main navigation model and hid state inside a compact icon. Remove that picker and its store state, leaving search as plain text filtering and keeping the project header menu focused on organization and sorting.

The archive-all entry was also hidden because a broad destructive action does not belong in the lightweight project menu.

Constraint: Project grouping is now the primary project navigation surface.
Rejected: Keep the embedded project picker hidden in place | it would leave dead filtering state and a stale recovery path.
Rejected: Keep archive-all in the header menu | broad destructive actions are too risky for this surface.
Confidence: high
Scope-risk: moderate
Directive: Do not reintroduce broad session deletion or hidden project filters into the sidebar header without a dedicated reviewed management flow.
Tested: cd desktop && bun run test src/components/layout/Sidebar.test.tsx src/stores/sessionStore.test.ts src/components/layout/TabBar.test.tsx
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
2026-05-15 19:36:52 +08:00
程序员阿江(Relakkes)
02f23d6e3b Keep desktop memory paths aligned with runtime
Desktop memory settings already resolves project memory through the current sanitized project directory, while spawned CLI sessions could compute an older path variant and fail to read indexed memory files. Pin the child runtime to the same memory directory and let memory preview links open related markdown files directly from the rendered panel.

Constraint: Existing memory files may already live under both legacy underscore and current hyphenated project directories.
Rejected: Symlink or merge memory directories | it could mix stale legacy memory entries into the active project index.
Confidence: high
Scope-risk: moderate
Directive: Keep Settings memory discovery and spawned CLI memory context on the same project identity before changing either sanitizer.
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/memory.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run test -- MemorySettings MarkdownRenderer
Tested: cd desktop && bun run build
Tested: Browser smoke on local Vite/server for memory preview link navigation
Not-tested: bun run check:desktop still has pre-existing vite-config color-mix guard failure in desktop/src/theme/globals.css
2026-05-15 19:34:16 +08:00
程序员阿江(Relakkes)
4e969475f2 Improve session project sidebar controls
The session sidebar already uses project grouping, so the change adds header-level project actions instead of replacing project row controls. Sorting and organization choices are persisted through the existing desktop UI preferences file and mirrored into local cache for startup continuity.

Constraint: Keep the existing project tree, drag ordering, pinning, hiding, and Finder project-row actions intact.

Rejected: Replacing project row actions with the header menu | row-level Finder and per-project session actions are still useful and already covered by tests.

Confidence: high

Scope-risk: moderate

Directive: Do not store sidebar organization in global Claude settings; keep it under cc-haha desktop-ui preferences.

Tested: cd desktop && bun run test -- src/components/layout/Sidebar.test.tsx

Tested: bun test src/server/__tests__/desktop-ui-preferences.test.ts

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run build
2026-05-15 16:49:18 +08:00
程序员阿江(Relakkes)
5d9d1b009e Persist sidebar project preferences across desktop and H5
Sidebar project ordering, pinning, and hidden-project state must survive
browser access to the same local server, so the UI now stores these
preferences under the cc-haha config directory and keeps localStorage as
a migration/cache fallback.

Constraint: Browser and H5 localStorage is isolated from the Tauri WebView
Rejected: Keep sidebar project preferences only in localStorage | browser sessions would not share state
Rejected: Reuse cc-haha/settings.json | provider and H5 access settings should stay separate
Confidence: high
Scope-risk: moderate
Directive: Keep sidebar hide/remove semantics non-destructive; do not delete transcript files for project removal
Tested: cd desktop && bun run test -- src/components/layout/Sidebar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/desktop-ui-preferences.test.ts
Tested: bun run check:persistence-upgrade
Tested: bun run check:server
2026-05-15 16:30:39 +08:00
程序员阿江(Relakkes)
0e78439f9d Group desktop sessions by project root
The desktop sidebar needed a project-first navigation model that keeps worktree sessions attached to their source project instead of scattering them as separate paths. The UI now renders sessions under project groups with project-level actions and persisted ordering, while the server exposes a logical project root for worktree transcripts.

Constraint: Existing memory directory tree work must remain separate from the session sidebar behavior.

Rejected: Group by raw transcript projectPath | worktree paths fragment the same repository into multiple sidebar projects.

Confidence: high

Scope-risk: moderate

Directive: Keep future sidebar grouping keyed by projectRoot before projectPath so isolated worktrees stay under their source repository.

Tested: cd desktop && bun run test -- src/components/layout/Sidebar.test.tsx

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

Tested: git diff --check
2026-05-15 16:01:36 +08:00
程序员阿江(Relakkes)
6d166f43d8 fix: keep desktop attachments path-only
Desktop file attachment selection was inlining every selected file as a data URL before sending the websocket message. Large multi-file sends could inflate the renderer request body by tens of megabytes before the server had a chance to materialize uploads.

Route Tauri file selection through the native dialog so desktop sends absolute paths, while preserving browser fallback data URLs for H5. Cover both active-session and draft-session composers plus a payload-size regression case.

Constraint: Browser/H5 cannot rely on local absolute file paths, so the existing FileReader fallback remains for non-Tauri runtimes.
Rejected: Raise websocket/body limits | would keep renderer memory pressure and still send file bytes unnecessarily.
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce FileReader data URLs for Tauri desktop file-picker attachments without measuring websocket payload size.
Tested: cd desktop && bun run test src/lib/composerAttachments.test.ts src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: /tmp complex-project reproduction showed 12x3MB old inline payload at 50,333,174 bytes versus path-only payload around 1-2KB
Not-tested: Full desktop lint/build due unrelated existing Sidebar.tsx type errors in the dirty worktree
Related: https://github.com/NanmiCoder/cc-haha/issues/444
2026-05-15 10:55:35 +08:00
程序员阿江(Relakkes)
36b86343d5 Merge desktop memory theme polish into main
The detached worktree contains the verified desktop memory activity styling fix. Merge it into local main while preserving the existing main-line desktop changes and keeping the worktree commit as a separate decision record.

Constraint: Local main already diverged from the detached worktree and is ahead of origin
Rejected: Cherry-pick the worktree commit | would lose the explicit worktree merge topology the user requested
Confidence: high
Scope-risk: narrow
Directive: Preserve main-line desktop changes when resolving future memory-theme edits
Tested: cd desktop && bun run test src/components/chat/MessageList.test.tsx --run
Tested: cd desktop && bun run test src/components/layout/Sidebar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
2026-05-14 23:13:38 +08:00
程序员阿江(Relakkes)
667b86303f Prevent memory activity from clashing with desktop themes
Memory tool activity inherited the global warm brand treatment, which made the new desktop memory surface feel detached from white and dark themes. The component now uses memory-specific tokens with a quieter teal family, and the sidebar settings dock is made opaque so scrolling sessions cannot show through it.

Constraint: Desktop memory activity must remain readable across light, white, and dark themes without reusing the classic warm brand surface
Rejected: Keep using color-mix with --color-brand | preserves the original warm tint mismatch in white theme
Confidence: high
Scope-risk: narrow
Directive: Keep memory activity colors on memory-specific tokens instead of generic brand tokens
Tested: cd desktop && bun run test src/components/chat/MessageList.test.tsx --run
Tested: cd desktop && bun run test src/components/layout/Sidebar.test.tsx --run
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Tested: Browser smoke screenshots for light, white, and dark memory activity previews
2026-05-14 23:13:02 +08:00
程序员阿江(Relakkes)
0b1eb2c5b8 fix: acknowledge desktop copy completion
Copy actions that did not use CopyButton could succeed silently, leaving users unsure whether the clipboard changed. Show localized success toasts for H5 URL, QR link, and workspace path copies, and report a generic copy failure when the shared clipboard helper cannot write.

Constraint: Copy must keep working across macOS, Linux, and Windows Tauri WebViews, so the existing web Clipboard API plus textarea execCommand fallback remains the platform-neutral mechanism.

Rejected: Add native OS-specific clipboard calls | unnecessary surface area when the current web fallback already covers the desktop WebView contexts.

Confidence: high

Scope-risk: narrow

Directive: Copy surfaces that cannot visibly change their own button text should emit a toast on success or failure.

Tested: cd desktop && bun run test -- --run src/__tests__/generalSettings.test.tsx src/components/workspace/WorkspacePanel.test.tsx src/i18n/index.test.tsx

Tested: bun run check:desktop

Tested: bun run verify (passed=10 failed=0 skipped=0)

Not-tested: Manual OS matrix on Linux and Windows; behavior uses platform-neutral browser clipboard APIs inside Tauri.
2026-05-14 23:05:14 +08:00
程序员阿江(Relakkes)
9ddaf29b4e merge: land desktop tab bar height tuning
Bring the focused titlebar-density fix from the Codex worktree into local main. The patch only adjusts the desktop tab strip height baseline and its regression test, leaving existing local workspace edits untouched.

Constraint: Local main has unrelated uncommitted desktop settings/workspace edits that must be preserved
Rejected: Broad staging before merge | would mix unrelated local work into this landing
Confidence: high
Scope-risk: narrow
Directive: Keep this merge limited to the tab bar height patch; do not treat unrelated dirty files as part of this change
Tested: cd desktop && bunx vitest run src/components/layout/TabBar.test.tsx
Tested: bun run check:desktop
Not-tested: Push or PR creation; user asked for local main merge only
2026-05-14 23:04:32 +08:00
程序员阿江(Relakkes)
25936a2f4b fix: reduce desktop tab bar visual crowding
The previous tab strip height made session titles and toolbar affordances feel cramped. Increase the shared titlebar height token for tabs, overflow controls, and the native drag gutter so the top chrome reads as a deliberate desktop titlebar while preserving the existing drag, close, and toolbar interactions.

Constraint: Keep the change scoped to the desktop tab strip and avoid changing session state, ordering, or window-control behavior
Rejected: Increase only the outer bar height | tab hit targets and overflow controls would remain visually misaligned
Confidence: high
Scope-risk: narrow
Directive: Keep tab, overflow button, and drag-gutter heights aligned when changing this titlebar again
Tested: cd desktop && bunx vitest run src/components/layout/TabBar.test.tsx
Tested: bun run check:desktop
Tested: Browser smoke on Vite with tab bar measured at about 44px and toolbar controls centered
Not-tested: Native packaged Tauri window rendering on Windows titlebar controls
2026-05-14 23:04:16 +08:00
程序员阿江(Relakkes)
a9bd96f8b0 fix: keep empty-session launch controls visually attached
The active empty-session composer used the same launch controls as the new-session surface but rendered them outside the glass panel, creating an inconsistent gap between the prompt box and project/branch/worktree selectors. Embed the desktop hero launch row in the composer panel and keep the existing mobile and post-message context-chip paths unchanged.

Constraint: Preserve the existing new-session composer layout and shared RepositoryLaunchControls behavior.
Rejected: Adjust outer margins only | would keep the active empty-session DOM structurally different from the already-correct new-session composer.
Confidence: high
Scope-risk: narrow
Tested: cd desktop && bun run test -- src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: cd desktop && bun run lint
Tested: git diff --check
Tested: agent-browser DOM check confirmed the launch row is inside chat-input-panel with 1px bottom gap
Not-tested: Full bun run verify gate
2026-05-14 23:02:28 +08:00
程序员阿江(Relakkes)
c39a8331c7 merge: integrate reliable desktop copy fallback
Bring the detached worktree clipboard fix onto local main while preserving main's existing desktop responsiveness work.

Constraint: Local main and the detached worktree diverged from e070c4a0, so this requires a merge commit instead of a fast-forward.

Confidence: high

Scope-risk: narrow

Directive: Keep desktop copy controls on the shared fallback helper when adding new copy surfaces.

Tested: bun run verify (passed=7 failed=0 skipped=3) in /Users/nanmi/.codex/worktrees/ec25/claude-code-haha before merge

Not-tested: Post-merge full gate on local main; merge applies the verified six-file desktop patch onto a clean local main.
2026-05-14 22:44:26 +08:00
程序员阿江(Relakkes)
5898e02e01 fix: keep desktop copy actions reliable
Several desktop copy entry points still called navigator.clipboard directly, which can fail or report success inconsistently in Tauri and browser test contexts. Route those copy actions through the existing textarea execCommand fallback helper and cover the fallback paths for startup diagnostics, markdown copy controls, and workspace file paths.

Constraint: Clipboard API is not reliable in every desktop/browser context.

Rejected: Leave direct navigator.clipboard calls in isolated components | repeats the diagnostics copy failure mode and creates inconsistent copy behavior.

Confidence: high

Scope-risk: narrow

Directive: New desktop copy controls should use copyTextToClipboard or CopyButton instead of calling navigator.clipboard directly.

Tested: cd desktop && bun run lint

Tested: cd desktop && bun run test -- --run src/components/markdown/MarkdownRenderer.test.tsx src/components/layout/StartupErrorView.test.tsx src/components/workspace/WorkspacePanel.test.tsx src/__tests__/diagnosticsSettings.test.tsx src/components/chat/MessageList.test.tsx

Tested: bun run check:desktop

Tested: bun run check:native

Tested: bun run check:coverage

Tested: bun run verify (passed=7 failed=0 skipped=3)

Not-tested: Live provider baseline; not required for this desktop-only clipboard fix.
2026-05-14 22:44:00 +08:00