vibe-coding-master 0.0.7 → 0.0.8

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 `.ai/vcm/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
487
516
  ```
488
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
549
+ ```
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
@@ -722,12 +805,20 @@ Registers all routes and WebSockets.
722
805
 
723
806
  - `src/backend/api/project-routes.ts`: health, recent paths, connect/current project
724
807
  - `src/backend/api/harness-routes.ts`: harness status/apply
725
- - `src/backend/api/task-routes.ts`: tasks and task status
808
+ - `src/backend/api/task-routes.ts`: tasks, task status, task cleanup
726
809
  - `src/backend/api/session-routes.ts`: session lifecycle and dispatch compatibility endpoint
727
810
  - `src/backend/api/artifact-routes.ts`: artifact, role command, and log reads/writes
728
811
  - `src/backend/api/message-routes.ts`: messages and orchestration
729
812
  - `src/backend/api/translation-routes.ts`: settings, prompt previews, provider test, input/send, clear/retry
730
813
 
814
+ Worktree task API:
815
+
816
+ ```text
817
+ POST /api/tasks/:taskSlug/cleanup
818
+ ```
819
+
820
+ Do not add a "switch task worktree" endpoint. Worktree assignment happens only during task creation.
821
+
731
822
  ### WebSocket files
732
823
 
733
824
  - `src/backend/ws/terminal-ws.ts`
@@ -769,6 +860,7 @@ Auto delivery envelope is submitted with Enter.
769
860
  ### Harness templates
770
861
 
771
862
  - `src/backend/templates/harness/claude-root.ts`
863
+ - `src/backend/templates/harness/gitignore.ts`
772
864
  - `src/backend/templates/harness/project-manager-agent.ts`
773
865
  - `src/backend/templates/harness/architect-agent.ts`
774
866
  - `src/backend/templates/harness/coder-agent.ts`
@@ -793,6 +885,12 @@ It calls:
793
885
  - orchestration endpoints
794
886
  - translation endpoints
795
887
 
888
+ Target additions:
889
+
890
+ - `listGitWorktrees()`
891
+ - `listGitBranches()`
892
+ - `cleanupTask(taskSlug, options)`
893
+
796
894
  ### `src/frontend/state/app-store.ts`
797
895
 
798
896
  Exports:
@@ -840,8 +938,9 @@ Responsibilities:
840
938
  - messages modal
841
939
  - events modal
842
940
  - harness panel
843
- - one-field task creation
941
+ - task creation with one task-name field, checked non-optional worktree/branch indicator, branch preview, and worktree path preview
844
942
  - task navigation
943
+ - completed-task cleanup action
845
944
 
846
945
  ### `src/frontend/routes/task-workspace.tsx`
847
946
 
@@ -853,6 +952,7 @@ Exports:
853
952
  Responsibilities:
854
953
 
855
954
  - task header with role tabs and refresh
955
+ - show branch and immutable worktree path for the active task
856
956
  - status/message/orchestration refresh
857
957
  - periodic polling
858
958
  - session lifecycle actions
@@ -882,6 +982,8 @@ Layout:
882
982
  - path input row
883
983
  - recent select plus connect button row
884
984
 
985
+ This form connects the base repository. It is not used to switch an existing task to another worktree.
986
+
885
987
  ### `src/frontend/components/harness-panel.tsx`
886
988
 
887
989
  Exports:
@@ -1047,32 +1149,38 @@ App settings:
1047
1149
  Project config:
1048
1150
 
1049
1151
  ```text
1050
- .vcm/config.json
1152
+ .ai/vcm/config.json
1051
1153
  ```
1052
1154
 
1053
1155
  Task state:
1054
1156
 
1055
1157
  ```text
1056
- .vcm/tasks/<task>.json
1158
+ .ai/vcm/tasks/<task>.json
1057
1159
  ```
1058
1160
 
1059
1161
  Session state:
1060
1162
 
1061
1163
  ```text
1062
- .vcm/sessions/<task>.json
1164
+ .ai/vcm/sessions/<task>.json
1063
1165
  ```
1064
1166
 
1065
1167
  Messages:
1066
1168
 
1067
1169
  ```text
1068
- .vcm/messages/<task>.jsonl
1170
+ .ai/vcm/messages/<task>.jsonl
1069
1171
  .ai/handoffs/<task>/messages/<message-id>.md
1070
1172
  ```
1071
1173
 
1072
1174
  Orchestration:
1073
1175
 
1074
1176
  ```text
1075
- .vcm/orchestration/<task>.json
1177
+ .ai/vcm/orchestration/<task>.json
1178
+ ```
1179
+
1180
+ Task worktrees:
1181
+
1182
+ ```text
1183
+ .ai/vcm/worktrees/<task>/
1076
1184
  ```
1077
1185
 
1078
1186
  Handoff artifacts:
@@ -1101,7 +1209,11 @@ npm run verify:package
1101
1209
  For frontend layout changes, also verify manually:
1102
1210
 
1103
1211
  - connect repository
1212
+ - confirm `.ai/vcm/` is ignored before creating a task worktree
1213
+ - create task and verify branch `feature/<task>` is created
1214
+ - verify worktree path is `<baseRepoRoot>/.ai/vcm/worktrees/<task>`
1104
1215
  - open task
1216
+ - verify role sessions start with cwd set to the task worktree
1105
1217
  - role tabs stay in header
1106
1218
  - sidebar sections collapse/open correctly
1107
1219
  - embedded terminal remains visible after role switch
@@ -1111,6 +1223,7 @@ For frontend layout changes, also verify manually:
1111
1223
  - Auto orchestration toggles on/off
1112
1224
  - `Enter` in translation composer translates/sends
1113
1225
  - `Shift+Enter` inserts newline
1226
+ - mark task complete and verify cleanup removes the worktree and central task metadata
1114
1227
 
1115
1228
  ## 17. V1 Boundaries To Preserve
1116
1229
 
@@ -1126,3 +1239,6 @@ Do not reintroduce these into V1 docs or UI unless the product direction changes
1126
1239
  - optional title input in New Task
1127
1240
  - `Dirty: yes/no` sidebar label
1128
1241
  - role command dispatch as the primary orchestration path
1242
+ - per-role worktrees
1243
+ - switching a task to another branch/worktree after creation
1244
+ - 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.8",
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%}}