vibe-coding-master 0.0.7 → 0.0.9

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.
@@ -1,8 +1,8 @@
1
1
  # V1 Implementation Plan And File Map
2
2
 
3
- Last updated: 2026-05-30
3
+ Last updated: 2026-05-31
4
4
 
5
- This document is the current implementation map for VCM V1. It replaces older plan text that referenced removed files or obsolete UI behavior.
5
+ This document is the current implementation map for VCM V1.
6
6
 
7
7
  ## 1. Current Status
8
8
 
@@ -17,8 +17,7 @@ V1 is implemented as a local GUI app with:
17
17
  - API-driven message bus.
18
18
  - Translation panel based on Claude transcript JSONL tailing.
19
19
  - npm packaging with built `dist` and `dist-frontend` output.
20
-
21
- The implementation still has planned improvement space, but this file only describes code that exists now.
20
+ - Task creation creates one `feature/<task>` branch and one `.ai/vcm/worktrees/<task>` git worktree.
22
21
 
23
22
  ## 2. Package And Build
24
23
 
@@ -29,7 +28,7 @@ File:
29
28
  Current package facts:
30
29
 
31
30
  - package name: `vibe-coding-master`
32
- - current version: `0.0.6`
31
+ - current version: `0.0.7`
33
32
  - type: ESM
34
33
  - `bin.vcm`: `dist/main.js`
35
34
  - `bin.vcmctl`: `dist/cli/vcmctl.js`
@@ -190,6 +189,15 @@ Defines:
190
189
 
191
190
  Current UI sends only `taskSlug`, although the API type still permits optional `title` and `specPath`.
192
191
 
192
+ Worktree fields:
193
+
194
+ - `worktreePath: string`
195
+ - `branch: feature/<taskSlug>`
196
+ - `cleanupStatus?: "active" | "cleaned"`
197
+ - `cleanedAt?: string`
198
+
199
+ `CreateTaskRequest` creates a worktree and branch by default. The UI shows a checked `Create worktree and branch` indicator, but task worktree creation is the normal VCM task path and does not require a separate later action or a user-visible off switch.
200
+
193
201
  ### `src/shared/types/session.ts`
194
202
 
195
203
  Defines:
@@ -376,6 +384,21 @@ Important behavior:
376
384
  - accepts `.git` pointer files
377
385
  - passes per-command `safe.directory`
378
386
 
387
+ Worktree methods:
388
+
389
+ - `branchExists(repoRoot, branch): Promise<boolean>`
390
+ - `createWorktree(input): Promise<void>`
391
+ - `removeWorktree(repoRoot, worktreePath, options): Promise<void>`
392
+ - `deleteBranch(repoRoot, branch, options): Promise<void>`
393
+ - `getStatusPorcelain(repoRoot): Promise<string>`
394
+ - `isIgnored(repoRoot, repoRelativePath): Promise<boolean>`
395
+
396
+ Required safety:
397
+
398
+ - all Git commands keep command-scoped `safe.directory`
399
+ - refuse worktree paths outside `<baseRepoRoot>/.ai/vcm/worktrees/`
400
+ - refuse branch names that do not match `feature/<taskSlug>` for VCM-created tasks
401
+
379
402
  ### `src/backend/adapters/claude-adapter.ts`
380
403
 
381
404
  Exports:
@@ -461,8 +484,12 @@ Responsibilities:
461
484
  - connect repo
462
485
  - store current project in process memory
463
486
  - record recent repo paths in app settings
464
- - create `.vcm/config.json`
487
+ - create `~/.vcm/projects/<project-id>/config.json`
465
488
  - ensure base state directories
489
+ - ensure `.ai/vcm/` is ignored by Git before task-worktree creation
490
+ - expose base repo as the project control root
491
+
492
+ Repository connect should keep connecting to the base repo. Task worktrees are managed under that base repo and should not be treated as separate projects in the normal task list.
466
493
 
467
494
  ### `src/backend/services/task-service.ts`
468
495
 
@@ -479,13 +506,54 @@ Responsibilities:
479
506
  - load task
480
507
  - save task
481
508
  - update task status
509
+ - create task branch and worktree
510
+ - clean up completed task worktree and task metadata
482
511
 
483
512
  Task files:
484
513
 
485
514
  ```text
486
- .vcm/tasks/<task>.json
515
+ <baseRepoRoot>/.ai/vcm/tasks/<task>.json
516
+ ```
517
+
518
+ Create flow:
519
+
520
+ ```text
521
+ createTask(baseRepoRoot, { taskSlug })
522
+ -> assertValidTaskSlug(taskSlug)
523
+ -> branch = feature/<taskSlug>
524
+ -> worktreePath = <baseRepoRoot>/.ai/vcm/worktrees/<taskSlug>
525
+ -> assert .ai/vcm/ is ignored
526
+ -> assert base repo has no uncommitted changes
527
+ -> assert branch does not exist
528
+ -> assert worktree path does not exist
529
+ -> git.createWorktree({ baseRepoRoot, branch, worktreePath, baseRef: HEAD })
530
+ -> artifactService.ensureHandoffStructure({ repoRoot: worktreePath, handoffDir })
531
+ -> artifactService.createArtifactTemplates({ repoRoot: worktreePath, handoffDir })
532
+ -> write central task record under <baseRepoRoot>/.ai/vcm/tasks/<task>.json
533
+ ```
534
+
535
+ Cleanup flow:
536
+
537
+ ```text
538
+ cleanupTask(baseRepoRoot, taskSlug, options)
539
+ -> require all role sessions stopped
540
+ -> load central task record
541
+ -> verify worktreePath is under <baseRepoRoot>/.ai/vcm/worktrees/
542
+ -> inspect git status in worktree
543
+ -> refuse uncommitted changes unless options.force
544
+ -> git.removeWorktree(baseRepoRoot, worktreePath)
545
+ -> delete .ai/vcm/tasks/<task>.json
546
+ -> delete .ai/vcm/sessions/<task>.json
547
+ -> delete .ai/vcm/messages/<task>.jsonl
548
+ -> delete .ai/vcm/orchestration/<task>.json
487
549
  ```
488
550
 
551
+ Branch cleanup:
552
+
553
+ - keep `feature/<taskSlug>` by default
554
+ - optional `deleteBranch` only with explicit confirmation
555
+ - prefer requiring merged branch unless force-confirmed
556
+
489
557
  ### `src/backend/services/artifact-service.ts`
490
558
 
491
559
  Exports:
@@ -504,6 +572,8 @@ Responsibilities:
504
572
  - read/save role commands
505
573
  - append role logs
506
574
 
575
+ In task-worktree mode, artifact paths are still repo-relative, but `repoRoot` must be the task worktree path, not the base repo path.
576
+
507
577
  Primary role command path:
508
578
 
509
579
  ```text
@@ -551,7 +621,7 @@ Responsibilities:
551
621
  Persistence:
552
622
 
553
623
  ```text
554
- .vcm/sessions/<task>.json
624
+ <baseRepoRoot>/.ai/vcm/sessions/<task>.json
555
625
  ```
556
626
 
557
627
  Environment passed to Claude Code:
@@ -561,6 +631,12 @@ Environment passed to Claude Code:
561
631
  - `VCM_TASK_SLUG`
562
632
  - `VCM_ROLE`
563
633
 
634
+ In task-worktree mode:
635
+
636
+ - session cwd is `task.worktreePath`
637
+ - session persistence remains central under `baseRepoRoot/.ai/vcm/sessions`
638
+ - raw logs and handoff artifacts are written under the task worktree
639
+
564
640
  ### `src/backend/services/message-service.ts`
565
641
 
566
642
  Exports:
@@ -580,6 +656,12 @@ Responsibilities:
580
656
  - write message body markdown
581
657
  - write staged or delivered messages to target terminal
582
658
 
659
+ In task-worktree mode:
660
+
661
+ - message snapshots remain central under `baseRepoRoot/.ai/vcm/messages`
662
+ - message body files live under `task.worktreePath/.ai/handoffs/<task>/messages`
663
+ - terminal delivery uses the runtime session for the role, whose cwd is the task worktree
664
+
583
665
  ### `src/backend/services/command-dispatcher.ts`
584
666
 
585
667
  Exports:
@@ -603,6 +685,7 @@ Exports:
603
685
  Responsibilities:
604
686
 
605
687
  - inspect harness files
688
+ - manage `.gitignore` entries for VCM local state
606
689
  - plan create/insert/update/ok
607
690
  - apply VCM managed blocks
608
691
  - preserve user content outside managed blocks
@@ -623,13 +706,6 @@ Storage:
623
706
  ~/.vcm/settings.json
624
707
  ```
625
708
 
626
- Also migrates legacy:
627
-
628
- ```text
629
- ~/.vibe-coding-master/settings.json
630
- ~/.vibe-coding-master/translation.json
631
- ```
632
-
633
709
  ### `src/backend/services/translation-prompts.ts`
634
710
 
635
711
  Exports:
@@ -722,12 +798,20 @@ Registers all routes and WebSockets.
722
798
 
723
799
  - `src/backend/api/project-routes.ts`: health, recent paths, connect/current project
724
800
  - `src/backend/api/harness-routes.ts`: harness status/apply
725
- - `src/backend/api/task-routes.ts`: tasks and task status
801
+ - `src/backend/api/task-routes.ts`: tasks, task status, task cleanup
726
802
  - `src/backend/api/session-routes.ts`: session lifecycle and dispatch compatibility endpoint
727
803
  - `src/backend/api/artifact-routes.ts`: artifact, role command, and log reads/writes
728
804
  - `src/backend/api/message-routes.ts`: messages and orchestration
729
805
  - `src/backend/api/translation-routes.ts`: settings, prompt previews, provider test, input/send, clear/retry
730
806
 
807
+ Worktree task API:
808
+
809
+ ```text
810
+ POST /api/tasks/:taskSlug/cleanup
811
+ ```
812
+
813
+ Do not add a "switch task worktree" endpoint. Worktree assignment happens only during task creation.
814
+
731
815
  ### WebSocket files
732
816
 
733
817
  - `src/backend/ws/terminal-ws.ts`
@@ -769,6 +853,7 @@ Auto delivery envelope is submitted with Enter.
769
853
  ### Harness templates
770
854
 
771
855
  - `src/backend/templates/harness/claude-root.ts`
856
+ - `src/backend/templates/harness/gitignore.ts`
772
857
  - `src/backend/templates/harness/project-manager-agent.ts`
773
858
  - `src/backend/templates/harness/architect-agent.ts`
774
859
  - `src/backend/templates/harness/coder-agent.ts`
@@ -793,6 +878,12 @@ It calls:
793
878
  - orchestration endpoints
794
879
  - translation endpoints
795
880
 
881
+ Target additions:
882
+
883
+ - `listGitWorktrees()`
884
+ - `listGitBranches()`
885
+ - `cleanupTask(taskSlug, options)`
886
+
796
887
  ### `src/frontend/state/app-store.ts`
797
888
 
798
889
  Exports:
@@ -840,8 +931,9 @@ Responsibilities:
840
931
  - messages modal
841
932
  - events modal
842
933
  - harness panel
843
- - one-field task creation
934
+ - task creation with one task-name field, checked non-optional worktree/branch indicator, branch preview, and worktree path preview
844
935
  - task navigation
936
+ - completed-task cleanup action
845
937
 
846
938
  ### `src/frontend/routes/task-workspace.tsx`
847
939
 
@@ -853,6 +945,7 @@ Exports:
853
945
  Responsibilities:
854
946
 
855
947
  - task header with role tabs and refresh
948
+ - show branch and immutable worktree path for the active task
856
949
  - status/message/orchestration refresh
857
950
  - periodic polling
858
951
  - session lifecycle actions
@@ -882,6 +975,8 @@ Layout:
882
975
  - path input row
883
976
  - recent select plus connect button row
884
977
 
978
+ This form connects the base repository. It is not used to switch an existing task to another worktree.
979
+
885
980
  ### `src/frontend/components/harness-panel.tsx`
886
981
 
887
982
  Exports:
@@ -1047,32 +1142,39 @@ App settings:
1047
1142
  Project config:
1048
1143
 
1049
1144
  ```text
1050
- .vcm/config.json
1145
+ ~/.vcm/projects/<project-id>/config.json
1146
+ ~/.vcm/projects/index.json
1051
1147
  ```
1052
1148
 
1053
1149
  Task state:
1054
1150
 
1055
1151
  ```text
1056
- .vcm/tasks/<task>.json
1152
+ .ai/vcm/tasks/<task>.json
1057
1153
  ```
1058
1154
 
1059
1155
  Session state:
1060
1156
 
1061
1157
  ```text
1062
- .vcm/sessions/<task>.json
1158
+ .ai/vcm/sessions/<task>.json
1063
1159
  ```
1064
1160
 
1065
1161
  Messages:
1066
1162
 
1067
1163
  ```text
1068
- .vcm/messages/<task>.jsonl
1164
+ .ai/vcm/messages/<task>.jsonl
1069
1165
  .ai/handoffs/<task>/messages/<message-id>.md
1070
1166
  ```
1071
1167
 
1072
1168
  Orchestration:
1073
1169
 
1074
1170
  ```text
1075
- .vcm/orchestration/<task>.json
1171
+ .ai/vcm/orchestration/<task>.json
1172
+ ```
1173
+
1174
+ Task worktrees:
1175
+
1176
+ ```text
1177
+ .ai/vcm/worktrees/<task>/
1076
1178
  ```
1077
1179
 
1078
1180
  Handoff artifacts:
@@ -1101,7 +1203,11 @@ npm run verify:package
1101
1203
  For frontend layout changes, also verify manually:
1102
1204
 
1103
1205
  - connect repository
1206
+ - confirm `.ai/vcm/` is ignored before creating a task worktree
1207
+ - create task and verify branch `feature/<task>` is created
1208
+ - verify worktree path is `<baseRepoRoot>/.ai/vcm/worktrees/<task>`
1104
1209
  - open task
1210
+ - verify role sessions start with cwd set to the task worktree
1105
1211
  - role tabs stay in header
1106
1212
  - sidebar sections collapse/open correctly
1107
1213
  - embedded terminal remains visible after role switch
@@ -1111,6 +1217,7 @@ For frontend layout changes, also verify manually:
1111
1217
  - Auto orchestration toggles on/off
1112
1218
  - `Enter` in translation composer translates/sends
1113
1219
  - `Shift+Enter` inserts newline
1220
+ - mark task complete and verify cleanup removes the worktree and central task metadata
1114
1221
 
1115
1222
  ## 17. V1 Boundaries To Preserve
1116
1223
 
@@ -1126,3 +1233,6 @@ Do not reintroduce these into V1 docs or UI unless the product direction changes
1126
1233
  - optional title input in New Task
1127
1234
  - `Dirty: yes/no` sidebar label
1128
1235
  - role command dispatch as the primary orchestration path
1236
+ - per-role worktrees
1237
+ - switching a task to another branch/worktree after creation
1238
+ - a separate `Create task worktree` button outside task creation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
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}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{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}.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,.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}.workspace-header{display:grid;grid-template-columns:minmax(180px,auto) minmax(420px,1fr) 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}.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}.workflow-panel{display:grid;gap:8px;margin:0}.workflow-summary p{margin-bottom:0}.workflow-summary p{color:#4f5558;font-size:13px}.workflow-steps{display:grid;grid-template-columns:minmax(0,1fr);gap:6px;margin:0;padding:0;list-style:none}.workflow-steps li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;align-items:center;min-height:28px;border:1px solid #ece5d9;border-radius:6px;padding:4px 6px;background:#fffdfa}.workflow-steps li.is-current{border-color:#2f6f73;background:#e8f1ef}.workflow-steps span{overflow:hidden;color:#394246;font-size:12px;font-weight:650;text-overflow:ellipsis;white-space:nowrap}.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;min-height:0}.session-console-top{display:flex;gap:10px;align-items:center;justify-content:space-between}.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{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{min-width:0;min-height:0}.terminal-frame,.terminal-empty{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{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-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 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-entry.is-tool-output pre{display:block;overflow:hidden;color:#7d8590;text-overflow:ellipsis;white-space:nowrap;width:100%}.translation-warning{color:#ffab70;margin-bottom:6px}.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(760px,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-editor-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.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,.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 span:not(.status-badge),.message-path{color:#667071;font-size:12px}.message-item p{display:-webkit-box;margin-bottom:4px;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:2}.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-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-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-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))}.workflow-panel,.workflow-steps,.session-console-body.has-translation,.translation-settings-grid,.translation-prompt-editor-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%}}