vibe-coding-master 0.0.15 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>VibeCodingMaster</title>
7
- <script type="module" crossorigin src="/assets/index-QhzvzTMZ.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-jEkUTnIY.css">
7
+ <script type="module" crossorigin src="/assets/index-DK2F4LFT.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-D40qaonx.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -56,6 +56,7 @@ Behavioral guardrails:
56
56
  - When multiple interpretations are reasonable, do not choose silently; explain the difference and tradeoff, and ask for confirmation when needed.
57
57
  - Prefer the simplest solution that satisfies the task; do not add unrequested features, configuration, extension points, or abstractions.
58
58
  - Touch only files required by the task; do not clean up, format, or refactor adjacent code opportunistically.
59
+ - When the current task replaces a mechanism, remove obsolete code, stale paths, dead branches, legacy adapters, and unused compatibility shims. Do not preserve backward compatibility with stale code unless the user explicitly asks for it.
59
60
  - Clean up only unused imports, variables, functions, or test leftovers created by the current change.
60
61
  - Report-but-don't-act: when noticing an issue outside the current task scope (unrelated dead code, doc drift, adjacent bug, architecture concern, security smell), record it in `.ai/state/known-issues.md` and continue; do not act on it without an explicit task.
61
62
  - Every diff line must trace to the task goal, public contract, test contract, or required documentation sync.
@@ -243,17 +243,17 @@ The old `Dirty: yes/no` label is not used. The UI uses `Working tree: clean` or
243
243
  `Settings` contains:
244
244
 
245
245
  - `Theme` button, cycling through `System`, `Light`, and `Dark`.
246
- - `Round alert` button, on by default, controlling the completion prompt and sound.
246
+ - `Round alert` button, on by default, controlling the completion prompt and soft two-note completion chime.
247
247
  - `Try alert` button, firing the same completion prompt and sound for local verification.
248
248
  - `Messages` button, opening a modal list of role messages.
249
249
  - `Events` button, opening a modal list of runtime UI events for the current task.
250
250
 
251
251
  The default theme mode is `System`, which follows the OS/browser color-scheme preference. The entire application chrome, sidebar, forms, modals, status badges, and workspace panels must support both light and dark rendering. Embedded terminals keep their terminal-native dark styling.
252
252
 
253
- When `Round alert` is on, VCM shows a compact in-app prompt and plays a short local sound after a full conversation round truly ends.
253
+ When `Round alert` is on, VCM shows a compact in-app prompt and plays a short, soft, two-note local chime after a full conversation round truly ends.
254
254
  `Try alert` must work even when no conversation has just completed so the user can verify browser sound and notification behavior.
255
255
 
256
- There is no separate `Pause orchestration` or `Resume orchestration` control in the GUI. The current product model is one on/off toggle in the active role toolbar, immediately to the left of `Translate`.
256
+ There is no separate `Pause orchestration` or `Resume orchestration` control in the GUI. The current product model is one on/off toggle in the active role toolbar.
257
257
 
258
258
  `VCM Harness` shows whether VCM managed blocks are installed/up to date in the project rules files and `.gitignore`.
259
259
 
@@ -274,9 +274,11 @@ The worktree/branch path is the recommended VCM task model, but the user may cle
274
274
  The task workspace header is one compact row:
275
275
 
276
276
  ```text
277
- TASK WORKSPACE <task> <branch> <worktree> [Project Manager] [Architect] [Coder] [Reviewer] [Refresh]
277
+ <task> [Project Manager] [Architect] [Coder] [Reviewer] [Translate] [Close Task]
278
278
  ```
279
279
 
280
+ The header does not show `TASK WORKSPACE`, branch, or worktree path. Task branch/worktree details remain task metadata, but they are not first-row chrome.
281
+
280
282
  Role tabs show the session status for each role.
281
283
 
282
284
  The main task workspace only renders the active role console. Messages and Events are opened from the sidebar.
@@ -292,7 +294,6 @@ Controls:
292
294
  - `Resume`.
293
295
  - `Restart`.
294
296
  - `Stop`.
295
- - `Translate` toggle.
296
297
 
297
298
  Permission modes:
298
299
 
@@ -316,7 +317,7 @@ The split should stay close to 50/50 width. Both panes expand vertically to fill
316
317
 
317
318
  ## 8. Round Completion Detection
318
319
 
319
- VCM detects answer completion from VCM's hook-driven role activity state, not from terminal silence.
320
+ VCM detects answer completion from VCM's hook-driven role activity state, not from terminal silence or message history.
320
321
 
321
322
  Backend role state:
322
323
 
@@ -326,10 +327,10 @@ Backend role state:
326
327
 
327
328
  Task-level round state:
328
329
 
329
- - If VCM role messages exist, the latest active `submitted` message defines the current target role.
330
- - A PM -> Coder -> PM chain completes only when the latest target role, PM, reaches hook `Stop`.
331
- - Queued or pending messages prevent completion because more role work is waiting.
332
- - If no VCM role message is involved, the latest direct role `Stop` can complete the round.
330
+ - The latest role with a real hook `Stop` is the completion source when no role is still running.
331
+ - A PM -> Coder -> PM chain completes only when the final role, PM, reaches hook `Stop`.
332
+ - Pending route files prevent completion because more role work is waiting, but message history does not define completion.
333
+ - If no VCM role message is involved, the latest direct role `Stop` can still complete the round.
333
334
 
334
335
  The frontend polls this task-level round state. It deduplicates `completionId`, then shows the prompt and plays the sound only once per completed round.
335
336
 
@@ -471,8 +472,8 @@ Default route policy:
471
472
 
472
473
  Stop-triggered scan:
473
474
 
474
- - VCM injects a Claude Code `Stop` hook into `.claude/settings.json`.
475
- - The hook does not call `vcmctl`; it POSTs directly to the local VCM backend.
475
+ - VCM injects Claude Code `UserPromptSubmit` and `Stop` hooks into `.claude/settings.json`.
476
+ - The hooks do not call `vcmctl`; they POST directly to the local VCM backend.
476
477
  - When any role stops, VCM marks that role idle, then scans pending route files.
477
478
  - VCM scans the stopped role's outgoing files and also any pending files targeting newly idle roles, so messages that were blocked by a busy target can be delivered after that target stops.
478
479
  - VCM reads only stable, non-empty files and ignores blank files.
@@ -481,33 +482,36 @@ Stop-triggered scan:
481
482
 
482
483
  Manual mode:
483
484
 
484
- - message status becomes `pending_approval` when the target role is running
485
+ - role route files stay non-empty as pending handoffs
485
486
  - user opens `Messages`
486
- - message rows show sequence, timestamp, status, body preview, path, and `Copy`
487
- - `Mark All Done` marks open message records as `acknowledged` after the user manually handled stuck messages
487
+ - message rows show newest delivered history first with stable increasing sequence, timestamp, body preview, path, and `Copy`
488
+ - `Mark All Done` clears pending route files after the user manually handled stuck handoff content
489
+ - `Delete All` removes message history without touching pending route files
488
490
  - user decides whether to copy or manually act on the message
489
491
  - VCM does not write to the target terminal or submit Enter
490
492
  - VCM does not clear the source route file until the user marks it done or VCM later dispatches it in auto mode
491
493
 
492
494
  Auto mode:
493
495
 
494
- - if the target role is idle and has no active delivered message, VCM writes a `[VCM MESSAGE]` envelope to that role's embedded terminal and submits Enter
495
- - terminal write success stores a durable message snapshot and marks the delivery `submitted`
496
- - after VCM successfully submits the message to Claude Code, VCM archives the body in message history and clears the source route file
496
+ - if the target role is running and hook-idle, VCM writes a `[VCM MESSAGE]` envelope to that role's embedded terminal and submits Enter
497
+ - before writing to the terminal, VCM stores `dispatchingAt` and waits briefly so the GUI can switch to the target role tab first
498
+ - terminal write success stores a durable delivered message snapshot
499
+ - Claude Code `UserPromptSubmit` confirms the accepted prompt, stores `acceptedAt`, and clears the source route file if it still contains that same message
497
500
  - if the target role is not running, is busy, or terminal submission fails, VCM leaves the route file non-empty so it remains pending
498
- - when VCM dispatches a message, the GUI switches to the target role tab so the user can watch execution
501
+ - when VCM records `dispatchingAt`, the GUI switches to the target role tab so the user can watch the terminal receive and execute the message
499
502
  - the target role answers by writing its own route file back to the next role and then ending its turn
500
- - `Mark All Done` is a manual recovery action for stuck orchestration. It marks open message records as `acknowledged` and may clear route files only after the user confirms the pending file contents were manually handled.
503
+ - `Mark All Done` is a manual recovery action for stuck orchestration. It clears route files only after the user confirms the pending file contents were manually handled.
501
504
 
502
505
  VCM Harness injects Claude Code hooks into `.claude/settings.json`:
503
506
 
507
+ - `UserPromptSubmit`: posts directly to the VCM backend, marks the role running, and confirms any matching VCM message by recording `acceptedAt`
504
508
  - `Stop`: posts directly to the VCM backend, marks the role idle, and triggers pending route-file dispatch
505
509
 
506
- VCM does not need `UserPromptSubmit` for message delivery in this design. Role activity becomes running when VCM submits user or message input to the embedded terminal, and returns to idle on `Stop`.
510
+ VCM uses `UserPromptSubmit` as the Claude Code acceptance signal. A successful PTY write only proves VCM delivered text to the embedded terminal; `UserPromptSubmit` proves Claude Code accepted the prompt.
507
511
 
508
512
  The injected role rules require asynchronous file messaging: after writing or updating a route file, the role must end the current Claude Code turn and wait for VCM to deliver a later reply. Roles must not poll files, start shell loops, or keep the turn open waiting for another role to answer, and they must not use Claude Code Task/Subagent for VCM role delegation.
509
513
 
510
- There is no `vcmctl` in the target design. The only hook entrypoint is direct HTTP from Claude Code hooks to the local VCM backend.
514
+ There is no `vcmctl` in the target design. Hook entrypoints are direct HTTP from Claude Code hooks to the local VCM backend.
511
515
 
512
516
  ## 13. Translation
513
517
 
@@ -539,7 +543,7 @@ Prompt slots:
539
543
  - `zh-to-en-with-context`
540
544
  - `en-to-zh`
541
545
 
542
- The settings modal shows all three prompt slots as direct editors. `Reset prompts` restores every prompt to its built-in default. The modal does not include separate enable/output/input-mode switches; opening the role toolbar `Translate` panel is the translation on/off control, and the panel-level `Auto-send` toggle controls whether translated user input is submitted automatically.
546
+ The settings modal shows all three prompt slots as direct editors. `Reset prompts` restores every prompt to its built-in default. The modal does not include separate enable/output/input-mode switches; opening the task header `Translate` panel is the translation on/off control, and the panel-level `Auto-send` toggle controls whether translated user input is submitted automatically.
543
547
 
544
548
  ### Claude Output Translation
545
549
 
@@ -605,7 +609,7 @@ Translation panel `Auto-send` is separate from task `Auto orchestration`:
605
609
  - `Auto-send` on: translate and send if there is no translation warning.
606
610
  - `Auto-send` off: translate to English draft and wait for user send.
607
611
 
608
- Task `Auto orchestration` is an adjacent toolbar button to the left of `Translate` and uses the same compact selected/unselected button styling.
612
+ Task `Auto orchestration` is a compact selected/unselected button in the role console toolbar. `Translate` is a global task header toggle next to `Close Task`; it opens/closes the translation split for all role consoles, so switching roles keeps the same translation setting.
609
613
 
610
614
  ## 14. Local State
611
615
 
@@ -689,7 +693,7 @@ VCM V1 is successful when:
689
693
  - Roles can route messages by writing fixed route files under `.ai/vcm/handoffs/messages/`.
690
694
  - Manual orchestration lets the user inspect pending route-file messages without auto-submitting Enter.
691
695
  - Auto orchestration can deliver pending route-file messages to idle running target roles.
692
- - Auto orchestration switches to the target role tab when VCM submits a route-file message.
696
+ - Auto orchestration switches to the target role tab when VCM records `dispatchingAt`, before VCM submits the route-file message.
693
697
  - Round completion detection waits for the final role in a chained conversation and can alert with prompt plus sound.
694
698
  - Translation settings save to `~/.vcm/settings.json`.
695
699
  - Translation reads Claude transcript JSONL reliably after start, resume, and restart.
@@ -110,10 +110,11 @@ Responsibilities:
110
110
 
111
111
  - Fetch task status, messages, orchestration state, and round state.
112
112
  - Poll those every three seconds.
113
- - Render compact header with task title, branch, immutable worktree path, role tabs, Refresh, and red `Close Task`.
113
+ - Render compact header with task title, role tabs, global `Translate`, and red `Close Task`.
114
114
  - Hold per-role permission mode selection.
115
+ - Hold global translation toggle state and pass it to every role console.
115
116
  - Hold task orchestration state and pass its on/off control to the active role console.
116
- - Detect newly submitted auto-orchestration messages from VCM dispatch and switch the active role tab to the target role.
117
+ - Detect newly dispatching auto-orchestration messages from VCM dispatch and switch the active role tab to the target role before terminal submission.
117
118
  - Emit task round state to `App` so completion alerts can be deduplicated and displayed.
118
119
  - Render one `SessionConsole` per role but only show the active role.
119
120
  - Emit messages/orchestration/events back to `App` so sidebar stays synchronized.
@@ -127,8 +128,8 @@ File:
127
128
  Responsibilities:
128
129
 
129
130
  - Render role session controls and embedded terminal.
130
- - Render `Auto orchestration` immediately to the left of `Translate`, using the same compact toggle styling.
131
- - Render the translation split panel when `Translate` is enabled.
131
+ - Render `Auto orchestration` using compact toggle styling.
132
+ - Render the translation split panel when the task-level `Translate` header toggle is enabled.
132
133
 
133
134
  Responsibilities:
134
135
 
@@ -575,29 +576,31 @@ Policy:
575
576
  Manual mode:
576
577
 
577
578
  ```text
578
- role writes route file -> Stop hook -> VCM records pending snapshot -> Messages modal -> Copy/manual action
579
+ role writes route file -> Stop hook -> route file remains pending -> Messages modal -> Copy/manual action
579
580
  ```
580
581
 
581
- The current GUI shows sequence, timestamp, status, route file path, body preview, `Copy`, and `Mark All Done`. VCM leaves the route file non-empty until the user confirms the pending content was handled or auto mode later dispatches it.
582
+ The current GUI shows message history sequence, timestamp, route file path, body preview, `Copy`, and `Mark All Done`. VCM leaves the route file non-empty until the user confirms the pending content was handled or auto mode later dispatches it.
582
583
 
583
584
  Auto mode:
584
585
 
585
586
  ```text
586
587
  role writes route file
587
588
  Stop hook -> VCM scans pending route files
588
- target idle and running -> VCM writes envelope + Enter -> submitted
589
- submitted -> VCM archives body -> clears source route file
589
+ target idle and running -> dispatchingAt snapshot -> GUI switches target role tab
590
+ brief pre-dispatch delay -> VCM writes envelope + Enter -> delivered history snapshot
591
+ UserPromptSubmit hook -> VCM records acceptedAt
592
+ acceptedAt -> VCM clears source route file if it still contains the same message
590
593
  target busy/unavailable/failure -> source route file remains non-empty
591
594
  target Stop hook -> VCM scans again and may deliver next pending route file
592
595
  ```
593
596
 
594
- The backend pastes a `[VCM MESSAGE]` envelope into the target terminal, then sends Enter as a separate terminal input event. A successful terminal submit is the delivery point for this design. VCM snapshots the message body before clearing the source route file so the message history remains auditable. Delivery is serialized per target role; VCM never sends two pending route files into the same target role during one scan.
597
+ The backend records a `dispatchingAt` snapshot before terminal submission. The frontend polls message history frequently enough to switch to the target role during the short pre-dispatch delay. The backend then pastes a `[VCM MESSAGE]` envelope into the target terminal and sends Enter as a separate terminal input event. A successful terminal write creates a delivered message-history snapshot. Claude Code `UserPromptSubmit` is the acceptance confirmation that stores `acceptedAt`. VCM snapshots the message body before clearing the source route file so the message history remains auditable. Delivery is serialized by hook state; VCM does not send to a target role that is still running from an accepted prompt.
595
598
 
596
- VCM Harness owns Claude Code hook injection through `.claude/settings.json`. The target design injects only `Stop`. The hook posts directly to a local VCM backend endpoint and does not use `vcmctl`. `Stop` switches the role activity badge to `idle` and triggers a pending route-file scan. VCM marks a role `running` when it submits user input or a VCM message to that embedded terminal. VCM does not use Claude Code Subagent hooks for role delegation.
599
+ VCM Harness owns Claude Code hook injection through `.claude/settings.json`. The target design injects `UserPromptSubmit` and `Stop`. Hooks post directly to a local VCM backend endpoint and do not use `vcmctl`. `UserPromptSubmit` confirms accepted prompts and switches the role activity badge to `running`; `Stop` switches the role activity badge to `idle` and triggers a pending route-file scan. VCM also marks a role `running` immediately after it submits user input or a VCM message to that embedded terminal. VCM does not use Claude Code Subagent hooks for role delegation.
597
600
 
598
- `Mark All Done` is a manual recovery action for stuck orchestration. It appends `acknowledged` snapshots for open messages and, after user confirmation, clears pending route files that the user already handled manually.
601
+ `Mark All Done` is a manual recovery action for stuck orchestration. After user confirmation, it clears pending route files that the user already handled manually. `Delete All` rewrites message history to remove all delivered/accepted records while preserving pending route files.
599
602
 
600
- The message service also serializes message mutations per task inside the VCM process so concurrent API calls cannot bypass the per-role in-flight check.
603
+ The message service also serializes message mutations per task inside the VCM process so concurrent hook/API calls cannot race route-file dispatch and acceptance confirmation.
601
604
 
602
605
  The backend should not keep compatibility-only message command paths after this migration. Removing `vcmctl` is part of the target simplification.
603
606
 
@@ -630,17 +633,18 @@ Mapping:
630
633
 
631
634
  Task-level completion:
632
635
 
633
- - If a message is currently `submitted`, the latest such message defines the round target.
634
- - In a PM -> role -> PM chain, completion follows the newest active message, so the round completes after PM emits hook `Stop` for the final response.
635
- - Queued or pending messages prevent completion.
636
- - If no VCM message is in the round, the latest direct role `Stop` can still produce a completion state.
636
+ - Role hook state defines completion. Message history does not define the completed role.
637
+ - If any role is `answering`, `using_tools`, `waiting_user`, or `abnormal`, the round remains active.
638
+ - When no role is active, the latest role with `lastStopAt` is the completion source.
639
+ - In a PM -> role -> PM chain, completion therefore happens after PM emits hook `Stop` for the final response.
640
+ - Pending route files prevent completion because more routing/recovery work is waiting.
637
641
 
638
642
  Frontend behavior:
639
643
 
640
644
  - `TaskWorkspace` polls the round endpoint with the other task state.
641
645
  - `App` stores the sidebar `Round alert` preference in `~/.vcm/settings.json`.
642
646
  - `Try alert` is frontend-only and calls the same round completion notice/sound path without persisting any setting.
643
- - `App` deduplicates `completionId`, then shows a small `Round complete` prompt and plays a short Web Audio tone when alerts are enabled.
647
+ - `App` deduplicates `completionId`, then shows a small `Round complete` prompt and plays a short two-note Web Audio chime when alerts are enabled.
644
648
 
645
649
  ## 13. Role Command Compatibility
646
650
 
@@ -707,7 +711,7 @@ Managed block:
707
711
  # VCM:END
708
712
  ```
709
713
 
710
- `.claude/settings.json` is JSON-merged by the harness. VCM preserves existing settings and adds a `Stop` hook that posts directly to the local VCM backend using the session-provided VCM API URL, task slug, role, and Claude session id. The hook must not call `vcmctl`.
714
+ `.claude/settings.json` is JSON-merged by the harness. VCM preserves existing settings and adds `UserPromptSubmit` and `Stop` hooks that post directly to the local VCM backend using the session-provided VCM API URL, task slug, role, and Claude session id. The hooks must not call `vcmctl`.
711
715
 
712
716
  The service:
713
717
 
@@ -888,16 +892,19 @@ Messages:
888
892
 
889
893
  ```text
890
894
  GET /api/tasks/:taskSlug/messages
891
- GET /api/tasks/:taskSlug/messages/pending-route-files
892
- POST /api/tasks/:taskSlug/messages/scan
895
+ GET /api/tasks/:taskSlug/messages/pending-routes
893
896
  POST /api/tasks/:taskSlug/messages/mark-all-done
897
+ DELETE /api/tasks/:taskSlug/messages/history
894
898
  GET /api/tasks/:taskSlug/orchestration
895
899
  PUT /api/tasks/:taskSlug/orchestration
896
900
  ```
897
901
 
902
+ There is no public message scan or dispatch endpoint. Pending route-file dispatch is triggered only by the Claude Code `Stop` hook through the backend hook service.
903
+
898
904
  Claude Code hooks:
899
905
 
900
906
  ```text
907
+ POST /api/hooks/claude-code
901
908
  POST /api/hooks/claude-code/stop
902
909
  ```
903
910
 
@@ -233,7 +233,6 @@ Defines:
233
233
 
234
234
  - `VcmMessageActor`
235
235
  - `VcmMessageType`
236
- - `VcmMessageStatus`
237
236
  - `VcmOrchestrationMode`
238
237
  - `VcmRoleMessage`
239
238
  - `VcmOrchestrationState`
@@ -251,7 +250,7 @@ Defines:
251
250
  - `VcmRoleTurnState`
252
251
  - `VcmTaskRoundState`
253
252
 
254
- Round state is task-level. It reports the latest active/completed role, queued and pending message counts, and a stable `completionId` for frontend notification dedupe.
253
+ Round state is task-level. It reports the latest active/completed role, pending route-file count, and a stable `completionId` for frontend notification dedupe.
255
254
 
256
255
  ### `src/shared/types/translation.ts`
257
256
 
@@ -690,7 +689,7 @@ Responsibilities:
690
689
  - mark all open messages done for manual recovery
691
690
  - get/update orchestration state
692
691
  - enforce message policy
693
- - enforce per-target-role in-flight delivery
692
+ - enforce per-target-role hook-driven busy/idle delivery
694
693
  - leave non-empty route files pending when a target role is busy, unavailable, or terminal submission fails
695
694
  - deliver the next pending route file when a target role becomes idle
696
695
  - persist message snapshots
@@ -703,7 +702,7 @@ In task-worktree mode:
703
702
  - orchestration state lives under `task.worktreePath/.ai/vcm/orchestration`
704
703
  - pending route files live under `task.worktreePath/.ai/vcm/handoffs/messages`
705
704
  - terminal delivery uses the runtime session for the role, whose cwd is the task worktree
706
- - message mutations are serialized per task inside the VCM process to avoid concurrent API calls bypassing the in-flight check
705
+ - message mutations are serialized per task inside the VCM process to avoid concurrent dispatch and confirmation races
707
706
 
708
707
  Route-file protocol:
709
708
 
@@ -713,12 +712,16 @@ Route-file protocol:
713
712
  - non-empty files are pending
714
713
  - each directed route has exactly one pending file, so repeated sends by the same role to the same target become edits to the same file
715
714
  - VCM scans after every `Stop` hook
715
+ - Stop hook handling is the only code path allowed to trigger automatic route-file dispatch; do not expose a frontend or public API scan/dispatch endpoint.
716
716
  - VCM scans the stopped role's outgoing files and pending files targeting newly idle roles
717
717
  - VCM delivers at most one route file per target role per scan
718
718
  - if several files target the same idle role, choose oldest modified time, then route name
719
- - successful terminal submission snapshots the body, stores `submitted`, then clears the source route file
719
+ - before terminal write, store a `dispatchingAt` snapshot and wait briefly so the GUI can switch to the target role tab
720
+ - successful terminal write snapshots the delivered body as message history
721
+ - `UserPromptSubmit` confirms Claude Code accepted the prompt, stores `acceptedAt`, then clears the source route file if it still contains that same message
720
722
  - failed, blocked, manual, or unavailable delivery leaves the source route file unchanged
721
- - `markAllDone` appends `acknowledged` snapshots and may clear pending route files only after user confirmation
723
+ - `markAllDone` may clear pending route files only after user confirmation; it does not mutate message history
724
+ - `deleteMessageHistory` rewrites the latest message snapshot file to remove all message history; it must not clear pending route files
722
725
 
723
726
  Required service functions:
724
727
 
@@ -730,6 +733,7 @@ Required service functions:
730
733
  - `appendMessageSnapshot(message): Promise<void>`
731
734
  - `clearRouteFile(path): Promise<void>`
732
735
  - `markAllDone(taskSlug, options): Promise<MarkAllMessagesDoneResult>`
736
+ - `deleteMessageHistory(taskSlug): Promise<DeleteMessageHistoryResult>`
733
737
 
734
738
  `dispatchPendingRouteFile` must snapshot before clearing. Clearing means truncating the route file to an empty string, not deleting it.
735
739
 
@@ -742,9 +746,10 @@ Exports:
742
746
 
743
747
  Responsibilities:
744
748
 
745
- - accept Claude Code `Stop` hook events directly over HTTP
749
+ - accept Claude Code `UserPromptSubmit` and `Stop` hook events directly over HTTP
746
750
  - map hook events to the current VCM project, task, role, and persisted Claude session id
747
- - update `RoleSessionRecord.activityStatus`: `Stop -> idle`
751
+ - update `RoleSessionRecord.activityStatus`: `UserPromptSubmit -> running`, `Stop -> idle`
752
+ - call `MessageService.confirmPromptSubmitted` when `UserPromptSubmit` includes a VCM message envelope
748
753
  - call `MessageService.scanAndDispatchPendingRouteFiles` after recording the stop event
749
754
  - never require `vcmctl hook-event`
750
755
 
@@ -888,9 +893,9 @@ Responsibilities:
888
893
  - read hook-driven role activity from `RoleSessionRecord`
889
894
  - map `activityStatus: "running"` to role state `answering`
890
895
  - map `activityStatus: "idle"` plus `lastStopAt` to role state `idle`
891
- - evaluate task-level round completion from messages plus role states
892
- - wait for the latest active submitted target role in PM -> role -> PM chains
893
- - ignore completion while queued or pending messages exist
896
+ - evaluate task-level round completion from hook-driven role states
897
+ - use pending route-file count to keep the round active while more dispatch work exists
898
+ - complete PM -> role -> PM chains only after the final role's hook `Stop`
894
899
 
895
900
  ## 9. Backend API
896
901
 
@@ -917,7 +922,7 @@ Registers HTTP routes and the terminal WebSocket.
917
922
  - `src/backend/api/session-routes.ts`: session lifecycle
918
923
  - `src/backend/api/artifact-routes.ts`: artifact and log reads/writes
919
924
  - `src/backend/api/message-routes.ts`: message history, pending route files, Mark All Done recovery, and orchestration
920
- - `src/backend/api/claude-hook-routes.ts`: Claude Code `Stop` hook receiver
925
+ - `src/backend/api/claude-hook-routes.ts`: Claude Code `UserPromptSubmit` and `Stop` hook receiver
921
926
  - `src/backend/api/round-routes.ts`: task round completion state
922
927
  - `src/backend/api/translation-routes.ts`: settings, prompt previews, provider test, start/poll, input/send, clear/retry
923
928
 
@@ -937,7 +942,7 @@ Terminal WebSocket forwards PTY output/input/resize.
937
942
 
938
943
  Translation does not use WebSocket. The backend writes cached translation events under `<taskRepoRoot>/.ai/vcm/translation/<task>/<role>/<session-id>.jsonl`; the frontend polls `GET /api/translation/sessions/:sessionId/events?after=<cursor>`. The cursor is the next expected seq, so `after=18` means seq `1..17` can be removed and seq `18+` should be returned.
939
944
 
940
- Round completion is HTTP-polled too. `GET /api/tasks/:taskSlug/round` returns `VcmTaskRoundState` from hook-driven role activity and message state; it is not a WebSocket stream.
945
+ Round completion is HTTP-polled too. `GET /api/tasks/:taskSlug/round` returns `VcmTaskRoundState` from hook-driven role activity plus pending-message blockers; it is not a WebSocket stream.
941
946
 
942
947
  ## 10. Backend Templates
943
948
 
@@ -1066,9 +1071,8 @@ Exports:
1066
1071
 
1067
1072
  Responsibilities:
1068
1073
 
1069
- - task header with role tabs and refresh
1074
+ - task header with task title, role tabs, global `Translate`, and `Close Task`
1070
1075
  - red `Close Task` action with destructive confirmation
1071
- - show branch and immutable worktree path for the active task
1072
1076
  - status/message/orchestration refresh
1073
1077
  - round state refresh
1074
1078
  - periodic polling
@@ -1118,7 +1122,7 @@ Exports:
1118
1122
  - `getMessageCounts(messages)`
1119
1123
  - `MessageTimeline(props)`
1120
1124
 
1121
- Used inside the Messages modal. Current UI rows show sequence, timestamp, route, type, status, body preview, source route file path, and a `Copy` button. The modal header includes `Mark All Done` for manual recovery from stuck queued/in-flight messages. Stage/approve/reject backend APIs should be removed with the route-file migration.
1125
+ Used inside the Messages modal. Current UI rows show newest message history first with stable increasing sequence numbers, timestamp, route, type, body preview, source route file path, and a `Copy` button. The modal header includes `Mark All Done` for clearing manually handled pending route files and `Delete All` for removing message history. Stage/approve/reject backend APIs should be removed with the route-file migration.
1122
1126
 
1123
1127
  ### `src/frontend/components/event-log.tsx`
1124
1128
 
@@ -1230,7 +1234,7 @@ Sidebar:
1230
1234
  - `Repository Path` default open only when no task is selected
1231
1235
  - `Settings` includes `Theme`, `Round alert`, `Try alert`, `Messages`, and `Events`
1232
1236
  - `Theme` cycles through `System`, `Light`, and `Dark`; `System` follows the browser/OS color-scheme preference
1233
- - `Round alert` is on by default and controls the in-app completion prompt plus short sound
1237
+ - `Round alert` is on by default and controls the in-app completion prompt plus a soft two-note completion chime
1234
1238
  - `Try alert` calls the same prompt/sound path without waiting for a real completed round
1235
1239
 
1236
1240
  Task workspace:
@@ -1238,19 +1242,20 @@ Task workspace:
1238
1242
  - role tabs in the first header row
1239
1243
  - messages/events are not in main workspace
1240
1244
  - active role console fills available space
1241
- - `Auto orchestration` appears immediately to the left of `Translate` and uses the same compact toggle style
1245
+ - `Auto orchestration` is a compact role console toggle
1242
1246
 
1243
1247
  Round completion:
1244
1248
 
1245
- - task state follows the latest active submitted message target role
1246
- - role activity uses VCM terminal submit -> `running` and Claude Code `Stop` -> `idle`
1249
+ - task round completion follows hook-driven role activity, not message history
1250
+ - role activity uses Claude Code `UserPromptSubmit` -> `running` and Claude Code `Stop` -> `idle`; VCM terminal submit also optimistically marks the target role `running`
1247
1251
  - PM -> role -> PM chains complete after PM's final hook `Stop`, not after the intermediate role's `Stop`
1248
- - queued or pending messages keep the round active
1252
+ - pending route files keep the round active
1249
1253
  - frontend dedupes `completionId` before showing a prompt or playing sound
1250
1254
 
1251
1255
  Translation:
1252
1256
 
1253
- - top role toolbar button label is `✅ Translate` when on and `× Translate` when off
1257
+ - task header button label is `✅ Translate` when on and `× Translate` when off
1258
+ - the task header `Translate` toggle is global across all four role consoles
1254
1259
  - translation panel `Auto-send` label is `✅ Auto-send` when on and `× Auto-send` when off
1255
1260
  - panel uses terminal-like dark styling
1256
1261
  - composer height is compact
@@ -1348,7 +1353,7 @@ For frontend layout changes, also verify manually:
1348
1353
  - Messages modal opens from sidebar Settings
1349
1354
  - Events modal opens from sidebar Settings
1350
1355
  - Auto orchestration toggles on/off from the role toolbar
1351
- - Auto orchestration switches to the target role tab when VCM submits a route-file message
1356
+ - Auto orchestration switches to the target role tab when VCM records `dispatchingAt`, before VCM submits the route-file message
1352
1357
  - Round alert can be toggled from sidebar Settings and fires once after a chained round truly completes
1353
1358
  - `Enter` in translation composer translates/sends
1354
1359
  - `Shift+Enter` inserts newline
@@ -1369,7 +1374,6 @@ Do not reintroduce these into V1 docs or UI unless the product direction changes
1369
1374
  - `Dirty: yes/no` sidebar label
1370
1375
  - role command dispatch as the primary orchestration path
1371
1376
  - `vcmctl` as an active CLI or agent-facing message path
1372
- - `UserPromptSubmit` as the delivery confirmation mechanism
1373
1377
  - per-role worktrees
1374
1378
  - switching a task to another branch/worktree after creation
1375
1379
  - a separate `Create task worktree` button outside task creation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "Local GUI session cockpit for Claude Code role sessions.",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,32 +0,0 @@
1
- /**
2
- * Copyright (c) 2014 The xterm.js authors. All rights reserved.
3
- * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
4
- * https://github.com/chjj/term.js
5
- * @license MIT
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- *
25
- * Originally forked from (with the author's permission):
26
- * Fabrice Bellard's javascript vt100 for jslinux:
27
- * http://bellard.org/jslinux/
28
- * Copyright (c) 2011 Fabrice Bellard
29
- * The original design remains. The terminal itself
30
- * has been extended to include xterm CSI codes, among
31
- * other features.
32
- */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}:root{color-scheme:light;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;background:#f5f2ea;color:#1c2024;line-height:1.5}html,body,#root{height:100%}*{box-sizing:border-box}body{margin:0;min-width:320px;min-height:100vh;background:#f5f2ea}button,input,select,textarea{font:inherit}button{border:1px solid #9ba6ad;background:#f8f7f2;color:#1d252b;border-radius:6px;min-height:34px;padding:6px 10px;cursor:pointer}button:hover:not(:disabled){background:#eef4f2;border-color:#607d74}button:disabled{cursor:not-allowed;opacity:.55}.danger-button{border-color:#b84a45;background:#fff1ee;color:#8d211d;font-weight:750}.danger-button:hover:not(:disabled){border-color:#8d211d;background:#ffe2dc}input,select,textarea:not(.xterm-helper-textarea){width:100%;border:1px solid #b9b0a1;border-radius:6px;background:#fffdf8;color:#202326;padding:8px 10px}textarea:not(.xterm-helper-textarea){min-height:240px;resize:vertical;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px}h1,h2,p{margin-top:0}h1{margin-bottom:4px;font-size:26px;line-height:1.15}h2{margin-bottom:10px;font-size:14px;letter-spacing:0}.app-shell{display:grid;grid-template-columns:minmax(280px,320px) minmax(0,1fr);height:100vh;min-height:0;overflow:hidden}.app-shell.is-sidebar-collapsed{grid-template-columns:46px minmax(0,1fr)}.app-sidebar{position:relative;min-width:0;border-right:1px solid #d3c9b8;background:#fbfaf6;padding:14px;overflow:auto}.app-shell.is-sidebar-collapsed .app-sidebar{overflow:hidden;padding:8px}.sidebar-toggle{position:absolute;top:10px;right:10px;z-index:2;display:grid;place-items:center;width:28px;min-height:28px;padding:0;background:#fffdf8}.sidebar-toggle:before{width:8px;height:8px;border-color:currentColor;border-style:solid;border-width:0 2px 2px 0;content:"";transform:translate(2px) rotate(135deg)}.app-shell.is-sidebar-collapsed .sidebar-toggle{left:9px;right:auto}.app-shell.is-sidebar-collapsed .sidebar-toggle:before{transform:translate(-2px) rotate(-45deg)}.sidebar-content{min-width:0}.app-shell.is-sidebar-collapsed .sidebar-content{width:0;opacity:0;pointer-events:none}.app-main{min-width:0;height:100%;padding:14px 16px;overflow:auto}.brand-header{display:flex;gap:12px;align-items:baseline;margin-bottom:10px;padding-right:34px}.brand-header strong{font-size:18px}.brand-header span,.muted,.workspace-branch,.workspace-worktree{color:#667071;font-size:13px}.sidebar-section{margin-bottom:8px;border:1px solid #e0d6c7;border-radius:8px;background:#fffdfa;overflow:hidden}.sidebar-section-toggle{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;width:100%;min-height:34px;border:0;border-radius:0;background:transparent;color:#1c2024;font-size:13px;font-weight:750;text-align:left}.sidebar-section-toggle:hover{background:#f5f1e8}.sidebar-section-toggle[aria-expanded=true]{border-bottom:1px solid #ece5d9}.sidebar-section-chevron{width:8px;height:8px;border-color:currentColor;border-style:solid;border-width:0 2px 2px 0;transform:rotate(45deg)}.sidebar-section-toggle[aria-expanded=true] .sidebar-section-chevron{transform:rotate(-135deg)}.sidebar-section-content{padding:8px}.repo-connect,.project-summary,.harness-panel,.task-create{margin:0}.inline-form{display:grid;grid-template-columns:minmax(0,1fr);gap:8px}.inline-form.has-recent-paths{grid-template-columns:minmax(0,1fr) auto}.inline-form>input{grid-column:1 / -1}.inline-form>button{justify-self:end}.inline-form.has-recent-paths>button{justify-self:auto}.repo-recent-select{min-width:0;max-width:none}.project-summary dl{display:grid;gap:8px;margin:0}.project-summary div{min-width:0}.project-summary dt{color:#6c6255;font-size:12px}.project-summary dd{margin:0;overflow-wrap:anywhere;font-size:13px}.warnings,.error-banner{border:1px solid #c87b54;background:#fff4ed;color:#6f3218;border-radius:6px;padding:10px 12px}.round-notice{position:fixed;right:20px;bottom:20px;z-index:30;display:grid;gap:2px;min-width:220px;max-width:min(360px,calc(100vw - 40px));border:1px solid #2f6f73;border-radius:8px;background:#e8f4f2;color:#123f43;box-shadow:0 14px 32px #1f242b29;padding:10px 12px}.round-notice strong{font-size:13px}.round-notice span{font-size:12px}.warnings{margin:12px 0 0;padding-left:26px;font-size:13px}.harness-panel{display:grid;gap:8px}.harness-panel-header{display:flex;justify-content:space-between;gap:8px;align-items:center}.harness-panel-header h2,.harness-panel-header p,.harness-result p{margin-bottom:0}.harness-actions{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.harness-file-list{display:grid;gap:6px;margin:0;padding:0;list-style:none}.harness-file-list li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;border:1px solid #ece5d9;border-radius:6px;padding:6px 8px;background:#fffdfa}.harness-file-list span{overflow:hidden;font-size:12px;font-weight:650;text-overflow:ellipsis;white-space:nowrap}.harness-changes,.harness-result{border:1px solid #e0d6c7;border-radius:6px;padding:8px;background:#f8f7f2;font-size:12px}.harness-changes h3{margin:0 0 4px;font-size:12px}.harness-changes ul,.harness-result ul{margin:0;padding-left:18px}.task-create form{display:grid;gap:8px}.task-create-preview{display:grid;gap:2px;border:1px solid #e0d6c7;border-radius:6px;background:#f8f7f2;padding:6px 8px}.task-create-option{display:flex;align-items:center;gap:8px;color:#1f242b;font-size:13px;font-weight:700}.task-create-option input{width:16px;height:16px;margin:0}.task-create-preview span{color:#255f3d;font-size:12px;font-weight:700}.task-create-preview small{overflow:hidden;color:#687273;font-size:11px;text-overflow:ellipsis;white-space:nowrap}.task-nav{display:grid;gap:8px}.task-nav-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;text-align:left}.task-nav-item.is-active,.role-tab.is-active{border-color:#2f6f73;background:#e8f1ef}.sidebar-settings{display:grid;gap:8px}.sidebar-settings button{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:center;width:100%;text-align:left}.sidebar-settings .settings-toggle.is-active{border-color:#2f6f73;background:#e8f1ef}.sidebar-settings .theme-mode-toggle span:last-child{font-weight:750}.workspace-header{display:grid;grid-template-columns:minmax(180px,auto) minmax(420px,1fr) auto auto;gap:16px;align-items:center;margin-bottom:6px}.workspace-title-line{display:flex;flex-wrap:wrap;gap:10px;align-items:baseline;min-width:0}.workspace-title-line h1{margin-bottom:0;font-size:18px;line-height:1.15}.workspace-branch{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.workspace-worktree{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.eyebrow{color:#7a5c2f;font-size:12px;font-weight:700;text-transform:uppercase}.role-tabs{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin-bottom:8px;min-width:0}.workspace-header .role-tabs{margin-bottom:0}.role-tab{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;align-items:center;min-height:30px;padding:4px 8px;text-align:left}.workspace-grid{display:grid;grid-template-columns:minmax(0,1fr);flex:1;gap:10px;align-items:stretch;min-height:0}.workspace-main{min-width:0;min-height:0;display:flex;flex-direction:column;gap:8px}.role-console-stack{min-width:0;min-height:0;flex:1;display:flex;flex-direction:column}.role-console-panel{min-width:0;min-height:0;flex:1;display:none}.role-console-panel.is-active{display:flex;flex-direction:column}.session-console,.message-panel,.event-log,.empty-workspace{border:1px solid #d6d0c6;border-radius:8px;background:#fffdf8;padding:10px}.task-workspace{display:flex;flex-direction:column;gap:8px;height:100%;min-height:0}.session-console{display:grid;grid-template-rows:auto minmax(0,1fr);gap:8px;flex:1;height:100%;min-height:0}.session-console-top{display:flex;gap:10px;align-items:center;justify-content:space-between}.session-console-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:flex-end}.session-controls{display:flex;flex-wrap:wrap;gap:8px;align-items:center;justify-content:space-between;margin:0 0 8px}.permission-mode-field{display:grid;grid-template-columns:auto minmax(180px,260px);gap:8px;align-items:center;width:fit-content;max-width:100%}.permission-mode-field span{color:#5f6a6c;font-size:13px;font-weight:650}.permission-mode-field small{display:block;color:#7b8587;font-size:11px;font-weight:500;line-height:1.2}.permission-mode-field select{width:100%;min-height:30px;border:1px solid #b9b0a1;border-radius:6px;background:#fffdf8;color:#202326;padding:4px 8px}.session-toolbar{display:flex;flex-wrap:wrap;gap:6px;justify-content:flex-end}.session-toolbar button{min-height:30px;padding:4px 9px}.translation-toggle{display:inline-flex;align-items:center;justify-content:center;min-height:28px;border:1px solid #b5bec4;border-radius:6px;background:#fffefa;color:#4f5558;font-size:12px;font-weight:650;padding:3px 10px;white-space:nowrap}.translation-toggle.is-active{border-color:#2f7e84;background:#e8f4f2;color:#145e64}.translation-settings-grid input[type=checkbox]{width:auto}.session-console-body{display:grid;grid-template-columns:minmax(0,1fr);min-width:0;min-height:0;height:100%}.session-console-body.has-translation{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px;align-items:stretch}.terminal-pane,.translation-pane{display:grid;min-width:0;min-height:0;height:100%}.terminal-frame,.terminal-empty{width:100%;height:100%;min-height:0;border-radius:6px;overflow:hidden;background:#111316}.terminal-empty{display:grid;place-items:center;align-content:center;gap:8px;color:#d6d0c6;border:1px solid #292d31}.translation-panel{display:grid;grid-template-rows:auto minmax(0,1fr) auto;gap:8px;height:100%;min-height:0;border:1px solid #292d31;border-radius:6px;background:#0d1117;color:#d6deeb;padding:8px;min-width:0;width:100%;overflow:hidden;font-family:Menlo,Monaco,Consolas,monospace}.translation-panel-header{display:grid;gap:3px}.translation-panel-titlebar,.translation-panel-actions,.translation-status-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center;justify-content:space-between}.translation-panel-header h2,.translation-panel-header p{margin-bottom:0}.translation-panel-titlebar h2{font-size:16px}.translation-panel-header p,.translation-composer span{color:#8b949e;font-size:12px}.translation-panel-actions button{border-color:#3a4149;background:#161b22;color:#d6deeb;min-height:26px;padding:2px 8px;font-size:12px}.translation-panel-actions button:hover:not(:disabled),.translation-composer-actions button:hover:not(:disabled){border-color:#58a6ff;background:#1f2937}.translation-panel-actions .auto-send-toggle.is-active{border-color:#56d364;background:#12261a;color:#d6deeb}.translation-panel-actions{justify-content:flex-end}.translation-status-row{flex-wrap:nowrap}.translation-status-row p:last-child{flex:0 0 auto;text-align:right}.translation-entry-list{display:grid;align-content:start;gap:8px;min-height:0;min-width:0;overflow-x:hidden;overflow-y:auto;scrollbar-color:#4b5563 #0d1117}.translation-entry{border:0;border-radius:0;background:transparent;min-width:0;max-width:100%;padding:0}.translation-entry.is-user-input{border-top:4px solid #3a4149;margin-top:14px;padding-top:14px}.translation-entry.is-user-input:first-child{margin-top:0}.translation-entry pre{box-sizing:border-box;margin:0;max-height:none;max-width:100%;min-width:0;overflow:visible;white-space:pre-wrap;overflow-wrap:anywhere;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px;line-height:1.45;color:#d6deeb}.translation-markdown{max-width:100%;min-width:0;color:#d6deeb;font-size:12px;line-height:1.55;overflow-wrap:anywhere}.translation-markdown>:first-child{margin-top:0}.translation-markdown>:last-child{margin-bottom:0}.translation-markdown p,.translation-markdown ul,.translation-markdown ol,.translation-markdown blockquote,.translation-markdown pre,.translation-markdown table{margin:0 0 8px}.translation-markdown h1,.translation-markdown h2,.translation-markdown h3,.translation-markdown h4,.translation-markdown h5,.translation-markdown h6{margin:10px 0 6px;color:#f0f6fc;font-weight:700;line-height:1.25}.translation-markdown h1{font-size:17px}.translation-markdown h2{font-size:15px}.translation-markdown h3,.translation-markdown h4,.translation-markdown h5,.translation-markdown h6{font-size:13px}.translation-markdown ul,.translation-markdown ol{padding-left:22px}.translation-markdown li{margin:2px 0}.translation-markdown .task-list-item{list-style:none}.translation-markdown input[type=checkbox]{width:13px;height:13px;margin:0 6px 0 0;accent-color:#56d364}.translation-markdown blockquote{border-left:3px solid #3a4149;color:#b7c0ca;padding-left:10px}.translation-markdown a{color:#79c0ff}.translation-markdown code{border-radius:4px;background:#161b22;color:#f0f6fc;padding:1px 4px;font-family:Menlo,Monaco,Consolas,monospace;font-size:.95em}.translation-markdown pre{overflow-x:auto;border:1px solid #292d31;border-radius:6px;background:#111316;padding:8px;white-space:pre}.translation-markdown pre code{background:transparent;padding:0}.translation-markdown table{display:block;max-width:100%;overflow-x:auto;border-collapse:collapse}.translation-markdown img{max-width:100%;border-radius:4px}.translation-markdown th,.translation-markdown td{border:1px solid #30363d;padding:4px 6px;text-align:left;vertical-align:top}.translation-markdown hr{border:0;border-top:1px solid #292d31;margin:10px 0}.translation-entry.is-tool-output pre{display:block;overflow:hidden;color:#7d8590;text-overflow:ellipsis;white-space:nowrap;width:100%}.translation-entry-note{margin:2px 0 0;color:#6e7681;font-size:10px;line-height:1.35}.translation-entry-note.is-error{color:#a3715f}.translation-composer{display:grid;gap:6px;border-top:1px solid #292d31;padding-top:8px}.translation-composer-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;align-items:stretch}.translation-composer textarea{width:100%;min-height:38px;max-height:88px;border-color:#3a4149;background:#0d1117;color:#d6deeb;font-family:inherit;font-size:12px;line-height:1.35;resize:vertical}.translation-composer textarea::placeholder{color:#7d8590}.translation-composer textarea::selection{background:#8b949e59;color:#fff}.translation-composer textarea:focus,.translation-composer textarea:focus-visible{border-color:#4b5563;outline:none;box-shadow:none}.translation-composer-actions{display:grid;align-content:start;gap:6px;min-width:104px}.translation-composer-actions button{border-color:#3a4149;background:#161b22;color:#d6deeb;width:100%;min-height:38px;padding:4px 9px;font-size:12px}.translation-panel .muted{color:#8b949e}.translation-panel .error-banner{border-color:#da7b72;background:#2d1518;color:#ffdcd7}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:20;display:grid;place-items:center;background:#181c1f61;padding:18px}.translation-settings-modal{display:grid;gap:12px;width:min(980px,100%);max-height:min(760px,92vh);overflow:auto;border:1px solid #d6d0c6;border-radius:8px;background:#fffdf8;padding:14px}.message-modal,.event-modal{display:grid;grid-template-rows:auto minmax(0,1fr);gap:12px;width:min(980px,100%);max-height:min(760px,92vh);overflow:hidden;border:1px solid #d6d0c6;border-radius:8px;background:#fffdf8;padding:14px}.translation-settings-modal header,.message-modal header,.event-modal header,.translation-settings-modal footer{display:flex;gap:8px;align-items:center;justify-content:space-between}.translation-prompt-settings{display:grid;gap:10px;border-top:1px solid #ece5d9;padding-top:12px}.translation-prompt-settings header{display:flex;gap:10px;align-items:end;justify-content:space-between}.translation-prompt-settings h3,.translation-prompt-settings p{margin-bottom:0}.translation-prompt-settings h3{font-size:13px}.translation-prompt-settings textarea{min-height:120px;max-height:260px;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px}.translation-prompt-stack{display:grid;gap:10px}.translation-prompt-stack label{display:grid;gap:4px}.translation-prompt-stack span{color:#4f5558;font-size:12px;font-weight:650}.translation-settings-modal h2,.message-modal h2,.message-modal p,.event-modal h2,.event-modal p,.translation-settings-modal p{margin-bottom:0}.translation-settings-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.translation-settings-grid label{display:grid;gap:4px}.translation-settings-grid span{color:#4f5558;font-size:12px;font-weight:650}.translation-settings-grid select,.translation-prompt-settings select{min-height:34px;border:1px solid #b9b0a1;border-radius:6px;background:#fffdf8;color:#202326;padding:6px 10px}.translation-test-result{border-radius:6px;padding:8px;font-size:13px}.translation-test-result.is-ok{border:1px solid #6ea77e;background:#e6f3e9;color:#245334}.translation-test-result.is-error{border:1px solid #c46e5f;background:#fae9e6;color:#6f2b21}.message-panel{display:grid;gap:8px}.message-modal .message-panel,.event-modal .event-log{min-height:0;overflow:auto;border:0;background:transparent;padding:0}.message-panel-header{display:flex;justify-content:space-between;gap:12px;align-items:center}.message-panel-header h2,.message-panel-header p{margin-bottom:0}.message-controls,.message-mode-toggle,.modal-actions,.message-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.message-mode-toggle{color:#4f5558;font-size:13px;font-weight:650}.message-mode-toggle input{width:auto}.message-list{display:grid;gap:8px;margin:0;padding:0;list-style:none}.message-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:start;border:1px solid #ece5d9;border-radius:6px;padding:8px;background:#fffdfa}.message-meta{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:4px}.message-meta time,.message-meta span:not(.status-badge),.message-reason,.message-path{color:#667071;font-size:12px}.message-sequence{min-width:32px;color:#1f242b;font-weight:800}.message-actions button{min-height:30px;padding:4px 10px}.message-item p{display:-webkit-box;margin-bottom:4px;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2}.message-reason,.message-path{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.event-log ol{margin:0;padding-left:22px;font-size:13px}.event-log{max-height:92px;overflow:auto}.event-log h2{margin-bottom:4px;font-size:13px}.event-log p{margin-bottom:0}.event-log li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:66px;min-height:20px;border-radius:999px;padding:2px 8px;border:1px solid #c7c1b8;background:#f2eee7;color:#4f5558;font-size:11px;white-space:nowrap}.status-running,.status-ok{border-color:#6ea77e;background:#e6f3e9;color:#245334}.status-idle{border-color:#9aa3a8;background:#edf0f1;color:#465056}.status-blocked,.status-crashed,.status-missing,.status-empty{border-color:#c46e5f;background:#fae9e6;color:#6f2b21}.status-waiting,.status-starting,.status-incomplete{border-color:#c4a34e;background:#f7efcf;color:#604e16}.status-exited,.status-done,.status-resumable,.status-staged,.status-delivering,.status-submitted,.status-delivered,.status-acknowledged{border-color:#7b98b8;background:#e9f0f8;color:#2e4e70}.status-pending_approval,.status-queued,.status-translating,.status-ready,.status-create,.status-insert,.status-update{border-color:#c4a34e;background:#f7efcf;color:#604e16}.status-rejected,.status-failed,.status-delivery_failed,.status-response_ready_missing_result,.status-cancelled,.status-blocked{border-color:#c46e5f;background:#fae9e6;color:#6f2b21}.status-pending{border-color:#c7c1b8;background:#f2eee7;color:#4f5558}.status-translated,.status-preserved{border-color:#7b98b8;background:#e9f0f8;color:#2e4e70}.empty-workspace{max-width:680px}@media(max-width:980px){.app-shell,.workspace-grid{grid-template-columns:1fr}.app-sidebar{border-right:0;border-bottom:1px solid #d3c9b8}.role-tabs{grid-template-columns:repeat(2,minmax(0,1fr))}.session-console-body.has-translation,.translation-settings-grid{grid-template-columns:1fr}}@media(max-width:560px){.app-main,.app-sidebar{padding:12px}.workspace-header,.inline-form,.inline-form.has-recent-paths{grid-template-columns:1fr;display:grid}.role-tabs{grid-template-columns:1fr}.terminal-frame,.terminal-empty{min-height:300px;height:54vh}.permission-mode-field{grid-template-columns:1fr;width:100%}}:root[data-theme=dark]{color-scheme:dark;background:#0d1117;color:#e6edf3}:root[data-theme=dark] body,:root[data-theme=dark] .app-main{background:#0d1117;color:#e6edf3}:root[data-theme=dark] button{border-color:#3d4652;background:#161b22;color:#e6edf3}:root[data-theme=dark] button:hover:not(:disabled){border-color:#58a6ff;background:#1f2937}:root[data-theme=dark] input,:root[data-theme=dark] select,:root[data-theme=dark] textarea:not(.xterm-helper-textarea){border-color:#3d4652;background:#0d1117;color:#e6edf3}:root[data-theme=dark] input::placeholder,:root[data-theme=dark] textarea::placeholder{color:#7d8590}:root[data-theme=dark] .danger-button{border-color:#da7b72;background:#2d1518;color:#ffdcd7}:root[data-theme=dark] .danger-button:hover:not(:disabled){border-color:#ffa198;background:#3d1f23}:root[data-theme=dark] .app-sidebar{border-color:#30363d;background:#0f141b}:root[data-theme=dark] .sidebar-toggle{background:#161b22}:root[data-theme=dark] .brand-header span,:root[data-theme=dark] .muted,:root[data-theme=dark] .workspace-branch,:root[data-theme=dark] .workspace-worktree,:root[data-theme=dark] .message-meta time,:root[data-theme=dark] .message-meta span:not(.status-badge),:root[data-theme=dark] .message-reason,:root[data-theme=dark] .message-path{color:#8b949e}:root[data-theme=dark] .sidebar-section,:root[data-theme=dark] .session-console,:root[data-theme=dark] .message-panel,:root[data-theme=dark] .event-log,:root[data-theme=dark] .empty-workspace,:root[data-theme=dark] .translation-settings-modal,:root[data-theme=dark] .message-modal,:root[data-theme=dark] .event-modal{border-color:#30363d;background:#11161d}:root[data-theme=dark] .sidebar-section-toggle{color:#e6edf3}:root[data-theme=dark] .sidebar-section-toggle:hover{background:#161b22}:root[data-theme=dark] .sidebar-section-toggle[aria-expanded=true],:root[data-theme=dark] .translation-prompt-settings{border-color:#30363d}:root[data-theme=dark] .project-summary dt,:root[data-theme=dark] .permission-mode-field span,:root[data-theme=dark] .translation-settings-grid span,:root[data-theme=dark] .translation-prompt-stack span,:root[data-theme=dark] .message-mode-toggle{color:#b7c0ca}:root[data-theme=dark] .permission-mode-field small,:root[data-theme=dark] .task-create-preview small{color:#8b949e}:root[data-theme=dark] .warnings,:root[data-theme=dark] .error-banner{border-color:#da7b72;background:#2d1518;color:#ffdcd7}:root[data-theme=dark] .round-notice{border-color:#56d4dd;background:#10262b;color:#d6fbff;box-shadow:0 14px 32px #0104097a}:root[data-theme=dark] .harness-file-list li,:root[data-theme=dark] .harness-changes,:root[data-theme=dark] .harness-result,:root[data-theme=dark] .task-create-preview,:root[data-theme=dark] .message-item{border-color:#30363d;background:#0d1117}:root[data-theme=dark] .task-create-option{color:#e6edf3}:root[data-theme=dark] .task-create-preview span{color:#7ee787}:root[data-theme=dark] .message-sequence{color:#f0f6fc}:root[data-theme=dark] .eyebrow{color:#d29922}:root[data-theme=dark] .task-nav-item.is-active,:root[data-theme=dark] .role-tab.is-active,:root[data-theme=dark] .sidebar-settings .settings-toggle.is-active,:root[data-theme=dark] .translation-toggle.is-active{border-color:#56d4dd;background:#10262b;color:#d6fbff}:root[data-theme=dark] .translation-toggle{border-color:#3d4652;background:#161b22;color:#b7c0ca}:root[data-theme=dark] .permission-mode-field select,:root[data-theme=dark] .translation-settings-grid select,:root[data-theme=dark] .translation-prompt-settings select{border-color:#3d4652;background:#0d1117;color:#e6edf3}:root[data-theme=dark] .terminal-empty{border-color:#30363d}:root[data-theme=dark] .modal-backdrop{background:#010409b8}:root[data-theme=dark] .message-modal .message-panel,:root[data-theme=dark] .event-modal .event-log{background:transparent}:root[data-theme=dark] .status-badge{border-color:#3d4652;background:#161b22;color:#d6deeb}:root[data-theme=dark] .translation-test-result.is-ok,:root[data-theme=dark] .status-running,:root[data-theme=dark] .status-ok{border-color:#3fb950;background:#12261a;color:#aff5b4}:root[data-theme=dark] .status-idle{border-color:#69717d;background:#20262f;color:#d6deeb}:root[data-theme=dark] .translation-test-result.is-error,:root[data-theme=dark] .status-blocked,:root[data-theme=dark] .status-crashed,:root[data-theme=dark] .status-missing,:root[data-theme=dark] .status-empty,:root[data-theme=dark] .status-rejected,:root[data-theme=dark] .status-failed,:root[data-theme=dark] .status-delivery_failed,:root[data-theme=dark] .status-response_ready_missing_result,:root[data-theme=dark] .status-cancelled{border-color:#f85149;background:#2d1518;color:#ffdcd7}:root[data-theme=dark] .status-waiting,:root[data-theme=dark] .status-starting,:root[data-theme=dark] .status-incomplete,:root[data-theme=dark] .status-pending_approval,:root[data-theme=dark] .status-queued,:root[data-theme=dark] .status-translating,:root[data-theme=dark] .status-ready,:root[data-theme=dark] .status-create,:root[data-theme=dark] .status-insert,:root[data-theme=dark] .status-update{border-color:#d29922;background:#2d2208;color:#f8e3a1}:root[data-theme=dark] .status-exited,:root[data-theme=dark] .status-done,:root[data-theme=dark] .status-resumable,:root[data-theme=dark] .status-staged,:root[data-theme=dark] .status-delivering,:root[data-theme=dark] .status-submitted,:root[data-theme=dark] .status-delivered,:root[data-theme=dark] .status-acknowledged,:root[data-theme=dark] .status-translated,:root[data-theme=dark] .status-preserved{border-color:#388bfd;background:#10223a;color:#c9e2ff}:root[data-theme=dark] .status-pending{border-color:#3d4652;background:#161b22;color:#d6deeb}