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.
- package/README.md +18 -14
- package/dist/backend/api/message-routes.js +4 -4
- package/dist/backend/api/round-routes.js +4 -2
- package/dist/backend/services/claude-hook-service.js +1 -1
- package/dist/backend/services/message-service.js +71 -137
- package/dist/backend/services/round-service.js +14 -52
- package/dist/backend/templates/harness/project-manager-agent.js +1 -0
- package/dist-frontend/assets/index-D40qaonx.css +32 -0
- package/dist-frontend/assets/{index-CvtyKEfS.js → index-DK2F4LFT.js} +42 -41
- package/dist-frontend/index.html +2 -2
- package/docs/cc-best-practices.md +1 -0
- package/docs/product-design.md +23 -20
- package/docs/v1-architecture-design.md +23 -18
- package/docs/v1-implementation-plan.md +22 -19
- package/package.json +1 -1
- package/dist-frontend/assets/index-jEkUTnIY.css +0 -32
package/dist-frontend/index.html
CHANGED
|
@@ -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-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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.
|
package/docs/product-design.md
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
-
|
|
330
|
-
- A PM -> Coder -> PM chain completes only when the
|
|
331
|
-
-
|
|
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
|
-
-
|
|
485
|
+
- role route files stay non-empty as pending handoffs
|
|
485
486
|
- user opens `Messages`
|
|
486
|
-
- message rows show sequence, timestamp,
|
|
487
|
-
- `Mark All Done`
|
|
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
|
|
495
|
-
-
|
|
496
|
-
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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`
|
|
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 ->
|
|
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,
|
|
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 ->
|
|
589
|
-
|
|
590
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
-
|
|
635
|
-
-
|
|
636
|
-
-
|
|
637
|
-
-
|
|
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-
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
-
|
|
720
|
-
-
|
|
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`
|
|
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
|
|
894
|
-
-
|
|
895
|
-
-
|
|
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
|
|
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
|
|
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,
|
|
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`
|
|
1245
|
+
- `Auto orchestration` is a compact role console toggle
|
|
1244
1246
|
|
|
1245
1247
|
Round completion:
|
|
1246
1248
|
|
|
1247
|
-
- task
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
|
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,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}
|