vibe-coding-master 0.0.16 → 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-CvtyKEfS.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.
@@ -253,7 +253,7 @@ The default theme mode is `System`, which follows the OS/browser color-scheme pr
253
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
 
@@ -481,27 +482,29 @@ 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 `delivering` or `submitted` 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 `delivering`
496
- - Claude Code `UserPromptSubmit` confirms the accepted prompt, marks the message `submitted`, and clears the source route file if it still contains that same message
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
 
504
- - `UserPromptSubmit`: posts directly to the VCM backend, marks the role running, and confirms any matching VCM message from `delivering` to `submitted`
507
+ - `UserPromptSubmit`: posts directly to the VCM backend, marks the role running, and confirms any matching VCM message by recording `acceptedAt`
505
508
  - `Stop`: posts directly to the VCM backend, marks the role idle, and triggers pending route-file dispatch
506
509
 
507
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.
@@ -540,7 +543,7 @@ Prompt slots:
540
543
  - `zh-to-en-with-context`
541
544
  - `en-to-zh`
542
545
 
543
- 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.
544
547
 
545
548
  ### Claude Output Translation
546
549
 
@@ -606,7 +609,7 @@ Translation panel `Auto-send` is separate from task `Auto orchestration`:
606
609
  - `Auto-send` on: translate and send if there is no translation warning.
607
610
  - `Auto-send` off: translate to English draft and wait for user send.
608
611
 
609
- 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.
610
613
 
611
614
  ## 14. Local State
612
615
 
@@ -690,7 +693,7 @@ VCM V1 is successful when:
690
693
  - Roles can route messages by writing fixed route files under `.ai/vcm/handoffs/messages/`.
691
694
  - Manual orchestration lets the user inspect pending route-file messages without auto-submitting Enter.
692
695
  - Auto orchestration can deliver pending route-file messages to idle running target roles.
693
- - 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.
694
697
  - Round completion detection waits for the final role in a chained conversation and can alert with prompt plus sound.
695
698
  - Translation settings save to `~/.vcm/settings.json`.
696
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,30 +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 -> delivering
589
- UserPromptSubmit hook -> VCM confirms accepted prompt -> submitted
590
- submitted -> VCM clears source route file if it still contains the same message
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
591
593
  target busy/unavailable/failure -> source route file remains non-empty
592
594
  target Stop hook -> VCM scans again and may deliver next pending route file
593
595
  ```
594
596
 
595
- The backend pastes a `[VCM MESSAGE]` envelope into the target terminal, then sends Enter as a separate terminal input event. A successful terminal write creates a `delivering` snapshot. Claude Code `UserPromptSubmit` is the acceptance confirmation that moves the message to `submitted`. 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.
596
598
 
597
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.
598
600
 
599
- `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.
600
602
 
601
- 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.
602
604
 
603
605
  The backend should not keep compatibility-only message command paths after this migration. Removing `vcmctl` is part of the target simplification.
604
606
 
@@ -631,10 +633,11 @@ Mapping:
631
633
 
632
634
  Task-level completion:
633
635
 
634
- - If a message is currently `delivering` or `submitted`, the latest such message defines the round target.
635
- - 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.
636
- - Queued or pending messages prevent completion.
637
- - 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.
638
641
 
639
642
  Frontend behavior:
640
643
 
@@ -889,13 +892,15 @@ Messages:
889
892
 
890
893
  ```text
891
894
  GET /api/tasks/:taskSlug/messages
892
- GET /api/tasks/:taskSlug/messages/pending-route-files
893
- POST /api/tasks/:taskSlug/messages/scan
895
+ GET /api/tasks/:taskSlug/messages/pending-routes
894
896
  POST /api/tasks/:taskSlug/messages/mark-all-done
897
+ DELETE /api/tasks/:taskSlug/messages/history
895
898
  GET /api/tasks/:taskSlug/orchestration
896
899
  PUT /api/tasks/:taskSlug/orchestration
897
900
  ```
898
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
+
899
904
  Claude Code hooks:
900
905
 
901
906
  ```text
@@ -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,13 +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 write snapshots the body as `delivering`
720
- - `UserPromptSubmit` confirms Claude Code accepted the prompt, stores `submitted`, then clears the source route file if it still contains that same message
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
721
722
  - failed, blocked, manual, or unavailable delivery leaves the source route file unchanged
722
- - `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
723
725
 
724
726
  Required service functions:
725
727
 
@@ -731,6 +733,7 @@ Required service functions:
731
733
  - `appendMessageSnapshot(message): Promise<void>`
732
734
  - `clearRouteFile(path): Promise<void>`
733
735
  - `markAllDone(taskSlug, options): Promise<MarkAllMessagesDoneResult>`
736
+ - `deleteMessageHistory(taskSlug): Promise<DeleteMessageHistoryResult>`
734
737
 
735
738
  `dispatchPendingRouteFile` must snapshot before clearing. Clearing means truncating the route file to an empty string, not deleting it.
736
739
 
@@ -890,9 +893,9 @@ Responsibilities:
890
893
  - read hook-driven role activity from `RoleSessionRecord`
891
894
  - map `activityStatus: "running"` to role state `answering`
892
895
  - map `activityStatus: "idle"` plus `lastStopAt` to role state `idle`
893
- - evaluate task-level round completion from messages plus role states
894
- - wait for the latest active delivering/submitted target role in PM -> role -> PM chains
895
- - 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`
896
899
 
897
900
  ## 9. Backend API
898
901
 
@@ -939,7 +942,7 @@ Terminal WebSocket forwards PTY output/input/resize.
939
942
 
940
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.
941
944
 
942
- 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.
943
946
 
944
947
  ## 10. Backend Templates
945
948
 
@@ -1068,9 +1071,8 @@ Exports:
1068
1071
 
1069
1072
  Responsibilities:
1070
1073
 
1071
- - task header with role tabs and refresh
1074
+ - task header with task title, role tabs, global `Translate`, and `Close Task`
1072
1075
  - red `Close Task` action with destructive confirmation
1073
- - show branch and immutable worktree path for the active task
1074
1076
  - status/message/orchestration refresh
1075
1077
  - round state refresh
1076
1078
  - periodic polling
@@ -1120,7 +1122,7 @@ Exports:
1120
1122
  - `getMessageCounts(messages)`
1121
1123
  - `MessageTimeline(props)`
1122
1124
 
1123
- 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.
1124
1126
 
1125
1127
  ### `src/frontend/components/event-log.tsx`
1126
1128
 
@@ -1240,19 +1242,20 @@ Task workspace:
1240
1242
  - role tabs in the first header row
1241
1243
  - messages/events are not in main workspace
1242
1244
  - active role console fills available space
1243
- - `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
1244
1246
 
1245
1247
  Round completion:
1246
1248
 
1247
- - task state follows the latest active delivering/submitted message target role
1249
+ - task round completion follows hook-driven role activity, not message history
1248
1250
  - role activity uses Claude Code `UserPromptSubmit` -> `running` and Claude Code `Stop` -> `idle`; VCM terminal submit also optimistically marks the target role `running`
1249
1251
  - PM -> role -> PM chains complete after PM's final hook `Stop`, not after the intermediate role's `Stop`
1250
- - queued or pending messages keep the round active
1252
+ - pending route files keep the round active
1251
1253
  - frontend dedupes `completionId` before showing a prompt or playing sound
1252
1254
 
1253
1255
  Translation:
1254
1256
 
1255
- - 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
1256
1259
  - translation panel `Auto-send` label is `✅ Auto-send` when on and `× Auto-send` when off
1257
1260
  - panel uses terminal-like dark styling
1258
1261
  - composer height is compact
@@ -1350,7 +1353,7 @@ For frontend layout changes, also verify manually:
1350
1353
  - Messages modal opens from sidebar Settings
1351
1354
  - Events modal opens from sidebar Settings
1352
1355
  - Auto orchestration toggles on/off from the role toolbar
1353
- - 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
1354
1357
  - Round alert can be toggled from sidebar Settings and fires once after a chained round truly completes
1355
1358
  - `Enter` in translation composer translates/sends
1356
1359
  - `Shift+Enter` inserts newline
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.0.16",
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}