vibe-coding-master 0.0.10 → 0.0.12
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 +21 -16
- package/dist/backend/api/task-routes.js +9 -0
- package/dist/backend/server.js +1 -0
- package/dist/backend/services/project-service.js +2 -2
- package/dist/backend/services/task-service.js +30 -4
- package/dist/backend/templates/harness/claude-root.js +2 -2
- package/dist/cli/vcmctl.js +1 -1
- package/dist-frontend/assets/{index-DPyKuEOz.css → index-Bi4X3GSR.css} +1 -1
- package/dist-frontend/assets/{index-B1vIIwLq.js → index-DaHXq14j.js} +2 -2
- package/dist-frontend/index.html +2 -2
- package/docs/cc-best-practices.md +14 -15
- package/docs/product-design.md +25 -21
- package/docs/v1-architecture-design.md +25 -23
- package/docs/v1-implementation-plan.md +46 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -181,7 +181,7 @@ VCM will not offer a separate `Create task worktree` button after a task exists,
|
|
|
181
181
|
|
|
182
182
|
Because worktrees live under `.ai/vcm/worktrees/`, the connected repository must ignore `.ai/vcm/`. Apply the VCM Harness before creating tasks so `.gitignore` contains the managed ignore block. The base repository must also be clean because the task branch/worktree is created from the connected repo's current `HEAD`.
|
|
183
183
|
|
|
184
|
-
When a task is complete, VCM provides a red `Close Task` action. Closing a
|
|
184
|
+
When a task is complete, VCM provides a red `Close Task` action. Closing a task shows a destructive confirmation, stops VCM-managed running role sessions for that task, then deletes the task worktree, deletes the task branch by default, removes the base task index entry, and removes task runtime metadata. VCM does not preflight running sessions or uncommitted changes before closing. Tasks created without a worktree only remove VCM metadata because they do not own a separate branch/worktree.
|
|
185
185
|
|
|
186
186
|
## Sidebar UI
|
|
187
187
|
|
|
@@ -207,7 +207,7 @@ Translation settings are local and stored in:
|
|
|
207
207
|
~/.vcm/settings.json
|
|
208
208
|
```
|
|
209
209
|
|
|
210
|
-
The same file stores recent repository paths. The translation API key is stored locally under `translation.secrets.apiKey`; it is not written to the connected repository, `.ai/handoffs`, raw terminal logs, or git diffs.
|
|
210
|
+
The same file stores recent repository paths. The translation API key is stored locally under `translation.secrets.apiKey`; it is not written to the connected repository, `.ai/vcm/handoffs`, raw terminal logs, or git diffs.
|
|
211
211
|
|
|
212
212
|
The sidebar `Settings` section also stores the UI theme preference in this file. The default is `system`, which follows the OS/browser color-scheme preference; users can cycle between `System`, `Light`, and `Dark`.
|
|
213
213
|
|
|
@@ -283,18 +283,18 @@ Examples that roles can run inside their terminal:
|
|
|
283
283
|
```bash
|
|
284
284
|
vcmctl send --to coder --type task --body-file /tmp/message.md
|
|
285
285
|
vcmctl reply --type blocked --body "Need clarification."
|
|
286
|
-
vcmctl result --body-file /tmp/result.md --artifact .ai/handoffs/
|
|
286
|
+
vcmctl result --body-file /tmp/result.md --artifact .ai/vcm/handoffs/implementation-log.md
|
|
287
287
|
vcmctl inbox
|
|
288
288
|
```
|
|
289
289
|
|
|
290
|
-
|
|
290
|
+
Runtime message and handoff files:
|
|
291
291
|
|
|
292
292
|
```text
|
|
293
293
|
.ai/vcm/messages/<task>.jsonl # under the task runtime repo
|
|
294
294
|
.ai/vcm/orchestration/<task>.json # under the task runtime repo
|
|
295
|
-
.ai/handoffs
|
|
296
|
-
.ai/handoffs
|
|
297
|
-
.ai/handoffs
|
|
295
|
+
.ai/vcm/handoffs/messages/<message-id>.md
|
|
296
|
+
.ai/vcm/handoffs/role-commands/
|
|
297
|
+
.ai/vcm/handoffs/logs/
|
|
298
298
|
```
|
|
299
299
|
|
|
300
300
|
The backend also keeps a compatibility role-command dispatch endpoint, but the primary workflow is PM-mediated `vcmctl` messaging.
|
|
@@ -308,8 +308,9 @@ When it is off, VCM is in manual mode:
|
|
|
308
308
|
- Roles may send messages through `vcmctl`.
|
|
309
309
|
- Messages appear in the `Messages` modal.
|
|
310
310
|
- The user can inspect them.
|
|
311
|
-
-
|
|
312
|
-
-
|
|
311
|
+
- The current GUI shows sequence, timestamp, status, body preview, path, and a `Copy` button for each message.
|
|
312
|
+
- The user decides what to do next by copying or manually acting on the message.
|
|
313
|
+
- VCM does not write to the target terminal or press Enter for the user.
|
|
313
314
|
|
|
314
315
|
When it is on, VCM is in auto mode:
|
|
315
316
|
|
|
@@ -320,6 +321,8 @@ When it is on, VCM is in auto mode:
|
|
|
320
321
|
|
|
321
322
|
The backend state model still contains a `paused` field for compatibility with existing API routes, but the current GUI exposes only a single on/off orchestration toggle.
|
|
322
323
|
|
|
324
|
+
The backend still exposes stage/approve/reject compatibility APIs for automation and future UI work. They are not primary controls in the current Messages modal.
|
|
325
|
+
|
|
323
326
|
## Resume Behavior
|
|
324
327
|
|
|
325
328
|
Each role session stores its Claude session id and transcript path under:
|
|
@@ -347,17 +350,19 @@ For a connected repository, VCM uses:
|
|
|
347
350
|
<taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
348
351
|
<taskRepoRoot>/.ai/vcm/orchestration/<task>.json
|
|
349
352
|
<taskRepoRoot>/.ai/vcm/translation/<task>/
|
|
350
|
-
<taskRepoRoot>/.ai/handoffs
|
|
351
|
-
<taskRepoRoot>/.ai/handoffs
|
|
352
|
-
<taskRepoRoot>/.ai/handoffs
|
|
353
|
-
<taskRepoRoot>/.ai/handoffs
|
|
354
|
-
<taskRepoRoot>/.ai/handoffs
|
|
355
|
-
<taskRepoRoot>/.ai/handoffs
|
|
356
|
-
<taskRepoRoot>/.ai/handoffs
|
|
353
|
+
<taskRepoRoot>/.ai/vcm/handoffs/architecture-plan.md
|
|
354
|
+
<taskRepoRoot>/.ai/vcm/handoffs/implementation-log.md
|
|
355
|
+
<taskRepoRoot>/.ai/vcm/handoffs/validation-log.md
|
|
356
|
+
<taskRepoRoot>/.ai/vcm/handoffs/review-report.md
|
|
357
|
+
<taskRepoRoot>/.ai/vcm/handoffs/docs-sync-report.md
|
|
358
|
+
<taskRepoRoot>/.ai/vcm/handoffs/role-commands/{architect,coder,reviewer}.md
|
|
359
|
+
<taskRepoRoot>/.ai/vcm/handoffs/logs/{project-manager,architect,coder,reviewer}.log
|
|
357
360
|
```
|
|
358
361
|
|
|
359
362
|
The project config is stored under `~/.vcm` so it is durable local app state and is not hidden inside a Git-ignored repository directory. For worktree-backed tasks, `taskRepoRoot` is `<baseRepoRoot>/.ai/vcm/worktrees/<task>`; for inline tasks, `taskRepoRoot` is the connected base repo.
|
|
360
363
|
|
|
364
|
+
Because handoffs are scoped to `taskRepoRoot` without an extra task-name directory, VCM allows only one active inline task per connected repository. Use the default worktree mode for parallel tasks.
|
|
365
|
+
|
|
361
366
|
## Packaging
|
|
362
367
|
|
|
363
368
|
The npm package publishes built output, not raw TypeScript entry files. `package.json` includes:
|
|
@@ -20,10 +20,19 @@ export function registerTaskRoutes(app, deps) {
|
|
|
20
20
|
app.post("/api/tasks/:taskSlug/cleanup", async (request) => {
|
|
21
21
|
const project = await requireCurrentProject(deps.projectService);
|
|
22
22
|
const task = await deps.taskService.loadTask(project.repoRoot, request.params.taskSlug);
|
|
23
|
+
await stopRunningRoleSessions(deps, project.repoRoot, request.params.taskSlug);
|
|
23
24
|
await deps.translationService.stopTask(getTaskRuntimeRepoRoot(task), request.params.taskSlug, { clearCache: true });
|
|
24
25
|
return deps.taskService.cleanupTask(project.repoRoot, request.params.taskSlug, request.body ?? {});
|
|
25
26
|
});
|
|
26
27
|
}
|
|
28
|
+
async function stopRunningRoleSessions(deps, repoRoot, taskSlug) {
|
|
29
|
+
const sessions = await deps.sessionService.listRoleSessions(repoRoot, taskSlug);
|
|
30
|
+
for (const session of sessions) {
|
|
31
|
+
if (session.status === "running") {
|
|
32
|
+
await deps.sessionService.stopRoleSession(repoRoot, taskSlug, session.role);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
27
36
|
async function requireCurrentProject(projectService) {
|
|
28
37
|
const project = await projectService.getCurrentProject();
|
|
29
38
|
if (!project) {
|
package/dist/backend/server.js
CHANGED
|
@@ -54,6 +54,7 @@ export async function createServer(deps, options = {}) {
|
|
|
54
54
|
registerTaskRoutes(app, {
|
|
55
55
|
projectService: deps.projectService,
|
|
56
56
|
taskService: deps.taskService,
|
|
57
|
+
sessionService: deps.sessionService,
|
|
57
58
|
statusService: deps.statusService,
|
|
58
59
|
translationService: deps.translationService
|
|
59
60
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { ROLE_NAMES } from "../../shared/constants.js";
|
|
3
3
|
import { VcmError } from "../errors.js";
|
|
4
|
-
const DEFAULT_HANDOFF_ROOT = ".ai/handoffs";
|
|
4
|
+
const DEFAULT_HANDOFF_ROOT = ".ai/vcm/handoffs";
|
|
5
5
|
const DEFAULT_STATE_ROOT = ".ai/vcm";
|
|
6
6
|
export function createProjectService(deps) {
|
|
7
7
|
let currentProject = null;
|
|
@@ -116,7 +116,7 @@ function normalizeProjectConfig(input, repoRoot) {
|
|
|
116
116
|
version: 1,
|
|
117
117
|
repoRoot,
|
|
118
118
|
defaultRoles: input.defaultRoles?.length ? input.defaultRoles : fallback.defaultRoles,
|
|
119
|
-
handoffRoot:
|
|
119
|
+
handoffRoot: DEFAULT_HANDOFF_ROOT,
|
|
120
120
|
stateRoot: DEFAULT_STATE_ROOT,
|
|
121
121
|
terminalBackend: "node-pty",
|
|
122
122
|
claudeCommand: input.claudeCommand || fallback.claudeCommand
|
|
@@ -30,6 +30,17 @@ export function createTaskService(deps) {
|
|
|
30
30
|
hint: "Apply VCM Harness first so .gitignore contains the VCM managed block."
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
+
if (!shouldCreateWorktree) {
|
|
34
|
+
const activeInlineTask = await findActiveInlineTask(deps.fs, repoRoot, config.stateRoot);
|
|
35
|
+
if (activeInlineTask) {
|
|
36
|
+
throw new VcmError({
|
|
37
|
+
code: "INLINE_TASK_EXISTS",
|
|
38
|
+
message: `An inline task already exists: ${activeInlineTask.taskSlug}`,
|
|
39
|
+
statusCode: 409,
|
|
40
|
+
hint: "Close the existing inline task first, or enable Create worktree and branch for this task."
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
33
44
|
if (shouldCreateWorktree && worktreePath) {
|
|
34
45
|
if (await deps.git.branchExists(repoRoot, taskBranch)) {
|
|
35
46
|
throw new VcmError({
|
|
@@ -75,7 +86,7 @@ export function createTaskService(deps) {
|
|
|
75
86
|
repoRoot,
|
|
76
87
|
worktreePath,
|
|
77
88
|
branch: taskBranch,
|
|
78
|
-
handoffDir:
|
|
89
|
+
handoffDir: config.handoffRoot,
|
|
79
90
|
status: "created",
|
|
80
91
|
specPath: input.specPath,
|
|
81
92
|
cleanupStatus: "active"
|
|
@@ -146,7 +157,7 @@ export function createTaskService(deps) {
|
|
|
146
157
|
const config = await deps.projectService.loadConfig(repoRoot);
|
|
147
158
|
const task = await this.loadTask(repoRoot, taskSlug);
|
|
148
159
|
const taskRepoRoot = getTaskRuntimeRepoRoot(task);
|
|
149
|
-
const statePaths = getTaskStatePaths(repoRoot, taskRepoRoot, config.stateRoot, taskSlug);
|
|
160
|
+
const statePaths = getTaskStatePaths(repoRoot, taskRepoRoot, config.stateRoot, config.handoffRoot, taskSlug);
|
|
150
161
|
const removedStatePaths = [];
|
|
151
162
|
const cleanedAt = now();
|
|
152
163
|
if (task.worktreePath) {
|
|
@@ -187,13 +198,28 @@ async function ensureTaskRuntimeStateDirs(fs, taskRepoRoot, stateRoot) {
|
|
|
187
198
|
await fs.ensureDir(path.join(taskRepoRoot, stateRoot, "orchestration"));
|
|
188
199
|
await fs.ensureDir(path.join(taskRepoRoot, stateRoot, "translation"));
|
|
189
200
|
}
|
|
190
|
-
function
|
|
201
|
+
async function findActiveInlineTask(fs, repoRoot, stateRoot) {
|
|
202
|
+
const tasksDir = path.join(repoRoot, stateRoot, "tasks");
|
|
203
|
+
if (!(await fs.pathExists(tasksDir))) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
const entries = await fs.readDir(tasksDir);
|
|
207
|
+
for (const entry of entries.filter((candidate) => candidate.endsWith(".json"))) {
|
|
208
|
+
const task = await fs.readJson(path.join(tasksDir, entry));
|
|
209
|
+
if (!task.worktreePath && task.cleanupStatus !== "cleaned") {
|
|
210
|
+
return task;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
function getTaskStatePaths(baseRepoRoot, taskRepoRoot, stateRoot, handoffRoot, taskSlug) {
|
|
191
216
|
return [
|
|
192
217
|
path.join(baseRepoRoot, stateRoot, "tasks", `${taskSlug}.json`),
|
|
193
218
|
path.join(taskRepoRoot, stateRoot, "sessions", `${taskSlug}.json`),
|
|
194
219
|
path.join(taskRepoRoot, stateRoot, "messages", `${taskSlug}.jsonl`),
|
|
195
220
|
path.join(taskRepoRoot, stateRoot, "orchestration", `${taskSlug}.json`),
|
|
196
|
-
path.join(taskRepoRoot, stateRoot, "translation", taskSlug)
|
|
221
|
+
path.join(taskRepoRoot, stateRoot, "translation", taskSlug),
|
|
222
|
+
path.join(taskRepoRoot, handoffRoot)
|
|
197
223
|
];
|
|
198
224
|
}
|
|
199
225
|
function assertTaskWorktreePath(repoRoot, stateRoot, worktreePath) {
|
|
@@ -3,9 +3,9 @@ export function renderRootClaudeHarnessRules() {
|
|
|
3
3
|
|
|
4
4
|
- This repository uses VibeCodingMaster for multi-session Claude Code work.
|
|
5
5
|
- User-facing work starts with the project-manager role.
|
|
6
|
-
- Canonical task handoffs live under .ai/handoffs
|
|
6
|
+
- Canonical task handoffs live under .ai/vcm/handoffs/ inside the current task runtime repo.
|
|
7
7
|
- Use only the current task's handoff directory for task-specific artifacts.
|
|
8
|
-
- Do not create or write .ai/handoffs
|
|
8
|
+
- Do not create or write task handoffs outside .ai/vcm/handoffs/ for the current task.
|
|
9
9
|
- Use vcmctl for role-to-role messaging instead of asking the user to copy prompts.
|
|
10
10
|
- Non-PM roles only reply to project-manager; they do not message other roles directly.
|
|
11
11
|
- High-risk decisions involving schema, auth, permissions, payment, billing, security, data deletion, or unclear user intent must stop for project-manager/user approval.
|
package/dist/cli/vcmctl.js
CHANGED
|
@@ -131,7 +131,7 @@ function printHelp() {
|
|
|
131
131
|
Usage:
|
|
132
132
|
vcmctl send --to coder --type task --body-file /tmp/message.md
|
|
133
133
|
vcmctl reply --type blocked --body "Need clarification."
|
|
134
|
-
vcmctl result --body-file /tmp/result.md --artifact .ai/handoffs/
|
|
134
|
+
vcmctl result --body-file /tmp/result.md --artifact .ai/vcm/handoffs/implementation-log.md
|
|
135
135
|
vcmctl inbox
|
|
136
136
|
`);
|
|
137
137
|
}
|
|
@@ -29,4 +29,4 @@
|
|
|
29
29
|
* The original design remains. The terminal itself
|
|
30
30
|
* has been extended to include xterm CSI codes, among
|
|
31
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}.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}.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;height:100%;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{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 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,.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-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-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{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-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,:root[data-theme=dark] .workflow-summary p{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] .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] .workflow-steps li,: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] .workflow-steps span{color:#d6deeb}: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] .workflow-steps li.is-current,: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] .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-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-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}
|
|
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}.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}.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;height:100%;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{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,.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-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-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{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-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,:root[data-theme=dark] .workflow-summary p{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] .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] .workflow-steps li,: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] .workflow-steps span{color:#d6deeb}: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] .workflow-steps li.is-current,: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] .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-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-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}
|
|
@@ -83,6 +83,6 @@ WARNING: This link could potentially be dangerous`)){const p=window.open();if(p)
|
|
|
83
83
|
`))+1))}const _="#".repeat(S),a=l.enter("headingAtx"),u=l.enter("phrasing");b.move(_+" ");let h=l.containerPhrasing(i,{before:"# ",after:`
|
|
84
84
|
`,...b.current()});return/^[\t ]/.test(h)&&(h=Os(h.charCodeAt(0))+h.slice(1)),h=h?_+" "+h:_,l.options.closeAtx&&(h+=" "+_),u(),a(),h}bm.peek=ZC;function bm(i){return i.value||""}function ZC(){return"<"}Cm.peek=JC;function Cm(i,s,l,o){const S=Tc(l),b=S==='"'?"Quote":"Apostrophe",_=l.enter("image");let a=l.enter("label");const u=l.createTracker(o);let h=u.move("![");return h+=u.move(l.safe(i.alt,{before:h,after:"]",...u.current()})),h+=u.move("]("),a(),!i.url&&i.title||/[\0- \u007F]/.test(i.url)?(a=l.enter("destinationLiteral"),h+=u.move("<"),h+=u.move(l.safe(i.url,{before:h,after:">",...u.current()})),h+=u.move(">")):(a=l.enter("destinationRaw"),h+=u.move(l.safe(i.url,{before:h,after:i.title?" ":")",...u.current()}))),a(),i.title&&(a=l.enter(`title${b}`),h+=u.move(" "+S),h+=u.move(l.safe(i.title,{before:h,after:S,...u.current()})),h+=u.move(S),a()),h+=u.move(")"),_(),h}function JC(){return"!"}wm.peek=ew;function wm(i,s,l,o){const S=i.referenceType,b=l.enter("imageReference");let _=l.enter("label");const a=l.createTracker(o);let u=a.move("![");const h=l.safe(i.alt,{before:u,after:"]",...a.current()});u+=a.move(h+"]["),_();const g=l.stack;l.stack=[],_=l.enter("reference");const c=l.safe(l.associationId(i),{before:u,after:"]",...a.current()});return _(),l.stack=g,b(),S==="full"||!h||h!==c?u+=a.move(c+"]"):S==="shortcut"?u=u.slice(0,-1):u+=a.move("]"),u}function ew(){return"!"}xm.peek=tw;function xm(i,s,l){let o=i.value||"",S="`",b=-1;for(;new RegExp("(^|[^`])"+S+"([^`]|$)").test(o);)S+="`";for(/[^ \r\n]/.test(o)&&(/^[ \r\n]/.test(o)&&/[ \r\n]$/.test(o)||/^`|`$/.test(o))&&(o=" "+o+" ");++b<l.unsafe.length;){const _=l.unsafe[b],a=l.compilePattern(_);let u;if(_.atBreak)for(;u=a.exec(o);){let h=u.index;o.charCodeAt(h)===10&&o.charCodeAt(h-1)===13&&h--,o=o.slice(0,h)+" "+o.slice(u.index+1)}}return S+o+S}function tw(){return"`"}function Em(i,s){const l=Sc(i);return!!(!s.options.resourceLink&&i.url&&!i.title&&i.children&&i.children.length===1&&i.children[0].type==="text"&&(l===i.url||"mailto:"+l===i.url)&&/^[a-z][a-z+.-]+:/i.test(i.url)&&!/[\0- <>\u007F]/.test(i.url))}km.peek=iw;function km(i,s,l,o){const S=Tc(l),b=S==='"'?"Quote":"Apostrophe",_=l.createTracker(o);let a,u;if(Em(i,l)){const g=l.stack;l.stack=[],a=l.enter("autolink");let c=_.move("<");return c+=_.move(l.containerPhrasing(i,{before:c,after:">",..._.current()})),c+=_.move(">"),a(),l.stack=g,c}a=l.enter("link"),u=l.enter("label");let h=_.move("[");return h+=_.move(l.containerPhrasing(i,{before:h,after:"](",..._.current()})),h+=_.move("]("),u(),!i.url&&i.title||/[\0- \u007F]/.test(i.url)?(u=l.enter("destinationLiteral"),h+=_.move("<"),h+=_.move(l.safe(i.url,{before:h,after:">",..._.current()})),h+=_.move(">")):(u=l.enter("destinationRaw"),h+=_.move(l.safe(i.url,{before:h,after:i.title?" ":")",..._.current()}))),u(),i.title&&(u=l.enter(`title${b}`),h+=_.move(" "+S),h+=_.move(l.safe(i.title,{before:h,after:S,..._.current()})),h+=_.move(S),u()),h+=_.move(")"),a(),h}function iw(i,s,l){return Em(i,l)?"<":"["}Am.peek=nw;function Am(i,s,l,o){const S=i.referenceType,b=l.enter("linkReference");let _=l.enter("label");const a=l.createTracker(o);let u=a.move("[");const h=l.containerPhrasing(i,{before:u,after:"]",...a.current()});u+=a.move(h+"]["),_();const g=l.stack;l.stack=[],_=l.enter("reference");const c=l.safe(l.associationId(i),{before:u,after:"]",...a.current()});return _(),l.stack=g,b(),S==="full"||!h||h!==c?u+=a.move(c+"]"):S==="shortcut"?u=u.slice(0,-1):u+=a.move("]"),u}function nw(){return"["}function Dc(i){const s=i.options.bullet||"*";if(s!=="*"&&s!=="+"&&s!=="-")throw new Error("Cannot serialize items with `"+s+"` for `options.bullet`, expected `*`, `+`, or `-`");return s}function rw(i){const s=Dc(i),l=i.options.bulletOther;if(!l)return s==="*"?"-":"*";if(l!=="*"&&l!=="+"&&l!=="-")throw new Error("Cannot serialize items with `"+l+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(l===s)throw new Error("Expected `bullet` (`"+s+"`) and `bulletOther` (`"+l+"`) to be different");return l}function sw(i){const s=i.options.bulletOrdered||".";if(s!=="."&&s!==")")throw new Error("Cannot serialize items with `"+s+"` for `options.bulletOrdered`, expected `.` or `)`");return s}function Tm(i){const s=i.options.rule||"*";if(s!=="*"&&s!=="-"&&s!=="_")throw new Error("Cannot serialize rules with `"+s+"` for `options.rule`, expected `*`, `-`, or `_`");return s}function lw(i,s,l,o){const S=l.enter("list"),b=l.bulletCurrent;let _=i.ordered?sw(l):Dc(l);const a=i.ordered?_==="."?")":".":rw(l);let u=s&&l.bulletLastUsed?_===l.bulletLastUsed:!1;if(!i.ordered){const g=i.children?i.children[0]:void 0;if((_==="*"||_==="-")&&g&&(!g.children||!g.children[0])&&l.stack[l.stack.length-1]==="list"&&l.stack[l.stack.length-2]==="listItem"&&l.stack[l.stack.length-3]==="list"&&l.stack[l.stack.length-4]==="listItem"&&l.indexStack[l.indexStack.length-1]===0&&l.indexStack[l.indexStack.length-2]===0&&l.indexStack[l.indexStack.length-3]===0&&(u=!0),Tm(l)===_&&g){let c=-1;for(;++c<i.children.length;){const C=i.children[c];if(C&&C.type==="listItem"&&C.children&&C.children[0]&&C.children[0].type==="thematicBreak"){u=!0;break}}}}u&&(_=a),l.bulletCurrent=_;const h=l.containerFlow(i,o);return l.bulletLastUsed=_,l.bulletCurrent=b,S(),h}function aw(i){const s=i.options.listItemIndent||"one";if(s!=="tab"&&s!=="one"&&s!=="mixed")throw new Error("Cannot serialize items with `"+s+"` for `options.listItemIndent`, expected `tab`, `one`, or `mixed`");return s}function ow(i,s,l,o){const S=aw(l);let b=l.bulletCurrent||Dc(l);s&&s.type==="list"&&s.ordered&&(b=(typeof s.start=="number"&&s.start>-1?s.start:1)+(l.options.incrementListMarker===!1?0:s.children.indexOf(i))+b);let _=b.length+1;(S==="tab"||S==="mixed"&&(s&&s.type==="list"&&s.spread||i.spread))&&(_=Math.ceil(_/4)*4);const a=l.createTracker(o);a.move(b+" ".repeat(_-b.length)),a.shift(_);const u=l.enter("listItem"),h=l.indentLines(l.containerFlow(i,a.current()),g);return u(),h;function g(c,C,w){return C?(w?"":" ".repeat(_))+c:(w?b:b+" ".repeat(_-b.length))+c}}function uw(i,s,l,o){const S=l.enter("paragraph"),b=l.enter("phrasing"),_=l.containerPhrasing(i,o);return b(),S(),_}const cw=da(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function hw(i,s,l,o){return(i.children.some(function(_){return cw(_)})?l.containerPhrasing:l.containerFlow).call(l,i,o)}function fw(i){const s=i.options.strong||"*";if(s!=="*"&&s!=="_")throw new Error("Cannot serialize strong with `"+s+"` for `options.strong`, expected `*`, or `_`");return s}Dm.peek=dw;function Dm(i,s,l,o){const S=fw(l),b=l.enter("strong"),_=l.createTracker(o),a=_.move(S+S);let u=_.move(l.containerPhrasing(i,{after:S,before:a,..._.current()}));const h=u.charCodeAt(0),g=oa(o.before.charCodeAt(o.before.length-1),h,S);g.inside&&(u=Os(h)+u.slice(1));const c=u.charCodeAt(u.length-1),C=oa(o.after.charCodeAt(0),c,S);C.inside&&(u=u.slice(0,-1)+Os(c));const w=_.move(S+S);return b(),l.attentionEncodeSurroundingInfo={after:C.outside,before:g.outside},a+u+w}function dw(i,s,l){return l.options.strong||"*"}function pw(i,s,l,o){return l.safe(i.value,o)}function _w(i){const s=i.options.ruleRepetition||3;if(s<3)throw new Error("Cannot serialize rules with repetition `"+s+"` for `options.ruleRepetition`, expected `3` or more");return s}function mw(i,s,l){const o=(Tm(l)+(l.options.ruleSpaces?" ":"")).repeat(_w(l));return l.options.ruleSpaces?o.slice(0,-1):o}const Rm={blockquote:UC,break:T_,code:YC,definition:KC,emphasis:ym,hardBreak:T_,heading:QC,html:bm,image:Cm,imageReference:wm,inlineCode:xm,link:km,linkReference:Am,list:lw,listItem:ow,paragraph:uw,root:hw,strong:Dm,text:pw,thematicBreak:mw};function gw(){return{enter:{table:vw,tableData:D_,tableHeader:D_,tableRow:yw},exit:{codeText:bw,table:Sw,tableData:Ju,tableHeader:Ju,tableRow:Ju}}}function vw(i){const s=i._align;this.enter({type:"table",align:s.map(function(l){return l==="none"?null:l}),children:[]},i),this.data.inTable=!0}function Sw(i){this.exit(i),this.data.inTable=void 0}function yw(i){this.enter({type:"tableRow",children:[]},i)}function Ju(i){this.exit(i)}function D_(i){this.enter({type:"tableCell",children:[]},i)}function bw(i){let s=this.resume();this.data.inTable&&(s=s.replace(/\\([\\|])/g,Cw));const l=this.stack[this.stack.length-1];l.type,l.value=s,this.exit(i)}function Cw(i,s){return s==="|"?s:i}function ww(i){const s=i||{},l=s.tableCellPadding,o=s.tablePipeAlign,S=s.stringLength,b=l?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:`
|
|
85
85
|
`,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:C,table:_,tableCell:u,tableRow:a}};function _(w,T,x,v){return h(g(w,x,v),w.align)}function a(w,T,x,v){const p=c(w,x,v),d=h([p]);return d.slice(0,d.indexOf(`
|
|
86
|
-
`))}function u(w,T,x,v){const p=x.enter("tableCell"),d=x.enter("phrasing"),m=x.containerPhrasing(w,{...v,before:b,after:b});return d(),p(),m}function h(w,T){return NC(w,{align:T,alignDelimiters:o,padding:l,stringLength:S})}function g(w,T,x){const v=w.children;let p=-1;const d=[],m=T.enter("table");for(;++p<v.length;)d[p]=c(v[p],T,x);return m(),d}function c(w,T,x){const v=w.children;let p=-1;const d=[],m=T.enter("tableRow");for(;++p<v.length;)d[p]=u(v[p],w,T,x);return m(),d}function C(w,T,x){let v=Rm.inlineCode(w,T,x);return x.stack.includes("tableCell")&&(v=v.replace(/\|/g,"\\$&")),v}}function xw(){return{exit:{taskListCheckValueChecked:R_,taskListCheckValueUnchecked:R_,paragraph:kw}}}function Ew(){return{unsafe:[{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{listItem:Aw}}}function R_(i){const s=this.stack[this.stack.length-2];s.type,s.checked=i.type==="taskListCheckValueChecked"}function kw(i){const s=this.stack[this.stack.length-2];if(s&&s.type==="listItem"&&typeof s.checked=="boolean"){const l=this.stack[this.stack.length-1];l.type;const o=l.children[0];if(o&&o.type==="text"){const S=s.children;let b=-1,_;for(;++b<S.length;){const a=S[b];if(a.type==="paragraph"){_=a;break}}_===l&&(o.value=o.value.slice(1),o.value.length===0?l.children.shift():l.position&&o.position&&typeof o.position.start.offset=="number"&&(o.position.start.column++,o.position.start.offset++,l.position.start=Object.assign({},o.position.start)))}}this.exit(i)}function Aw(i,s,l,o){const S=i.children[0],b=typeof i.checked=="boolean"&&S&&S.type==="paragraph",_="["+(i.checked?"x":" ")+"] ",a=l.createTracker(o);b&&a.move(_);let u=Rm.listItem(i,s,l,{...o,...a.current()});return b&&(u=u.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/,h)),u;function h(g){return g+_}}function Tw(){return[lC(),AC(),LC(),gw(),xw()]}function Dw(i){return{extensions:[aC(),TC(i),MC(),ww(i),Ew()]}}const Rw={tokenize:Hw,partial:!0},Lm={tokenize:Nw,partial:!0},Mm={tokenize:jw,partial:!0},Om={tokenize:Uw,partial:!0},Lw={tokenize:Iw,partial:!0},Bm={name:"wwwAutolink",tokenize:Bw,previous:Hm},zm={name:"protocolAutolink",tokenize:zw,previous:Nm},qi={name:"emailAutolink",tokenize:Ow,previous:jm},wi={};function Mw(){return{text:wi}}let jn=48;for(;jn<123;)wi[jn]=qi,jn++,jn===58?jn=65:jn===91&&(jn=97);wi[43]=qi;wi[45]=qi;wi[46]=qi;wi[95]=qi;wi[72]=[qi,zm];wi[104]=[qi,zm];wi[87]=[qi,Bm];wi[119]=[qi,Bm];function Ow(i,s,l){const o=this;let S,b;return _;function _(c){return!cc(c)||!jm.call(o,o.previous)||Rc(o.events)?l(c):(i.enter("literalAutolink"),i.enter("literalAutolinkEmail"),a(c))}function a(c){return cc(c)?(i.consume(c),a):c===64?(i.consume(c),u):l(c)}function u(c){return c===46?i.check(Lw,g,h)(c):c===45||c===95||Dt(c)?(b=!0,i.consume(c),u):g(c)}function h(c){return i.consume(c),S=!0,u}function g(c){return b&&S&&Mt(o.previous)?(i.exit("literalAutolinkEmail"),i.exit("literalAutolink"),s(c)):l(c)}}function Bw(i,s,l){const o=this;return S;function S(_){return _!==87&&_!==119||!Hm.call(o,o.previous)||Rc(o.events)?l(_):(i.enter("literalAutolink"),i.enter("literalAutolinkWww"),i.check(Rw,i.attempt(Lm,i.attempt(Mm,b),l),l)(_))}function b(_){return i.exit("literalAutolinkWww"),i.exit("literalAutolink"),s(_)}}function zw(i,s,l){const o=this;let S="",b=!1;return _;function _(c){return(c===72||c===104)&&Nm.call(o,o.previous)&&!Rc(o.events)?(i.enter("literalAutolink"),i.enter("literalAutolinkHttp"),S+=String.fromCodePoint(c),i.consume(c),a):l(c)}function a(c){if(Mt(c)&&S.length<5)return S+=String.fromCodePoint(c),i.consume(c),a;if(c===58){const C=S.toLowerCase();if(C==="http"||C==="https")return i.consume(c),u}return l(c)}function u(c){return c===47?(i.consume(c),b?h:(b=!0,u)):l(c)}function h(c){return c===null||sa(c)||et(c)||Un(c)||ca(c)?l(c):i.attempt(Lm,i.attempt(Mm,g),l)(c)}function g(c){return i.exit("literalAutolinkHttp"),i.exit("literalAutolink"),s(c)}}function Hw(i,s,l){let o=0;return S;function S(_){return(_===87||_===119)&&o<3?(o++,i.consume(_),S):_===46&&o===3?(i.consume(_),b):l(_)}function b(_){return _===null?l(_):s(_)}}function Nw(i,s,l){let o,S,b;return _;function _(h){return h===46||h===95?i.check(Om,u,a)(h):h===null||et(h)||Un(h)||h!==45&&ca(h)?u(h):(b=!0,i.consume(h),_)}function a(h){return h===95?o=!0:(S=o,o=void 0),i.consume(h),_}function u(h){return S||o||!b?l(h):s(h)}}function jw(i,s){let l=0,o=0;return S;function S(_){return _===40?(l++,i.consume(_),S):_===41&&o<l?b(_):_===33||_===34||_===38||_===39||_===41||_===42||_===44||_===46||_===58||_===59||_===60||_===63||_===93||_===95||_===126?i.check(Om,s,b)(_):_===null||et(_)||Un(_)?s(_):(i.consume(_),S)}function b(_){return _===41&&o++,i.consume(_),S}}function Uw(i,s,l){return o;function o(a){return a===33||a===34||a===39||a===41||a===42||a===44||a===46||a===58||a===59||a===63||a===95||a===126?(i.consume(a),o):a===38?(i.consume(a),b):a===93?(i.consume(a),S):a===60||a===null||et(a)||Un(a)?s(a):l(a)}function S(a){return a===null||a===40||a===91||et(a)||Un(a)?s(a):o(a)}function b(a){return Mt(a)?_(a):l(a)}function _(a){return a===59?(i.consume(a),o):Mt(a)?(i.consume(a),_):l(a)}}function Iw(i,s,l){return o;function o(b){return i.consume(b),S}function S(b){return Dt(b)?l(b):s(b)}}function Hm(i){return i===null||i===40||i===42||i===95||i===91||i===93||i===126||et(i)}function Nm(i){return!Mt(i)}function jm(i){return!(i===47||cc(i))}function cc(i){return i===43||i===45||i===46||i===95||Dt(i)}function Rc(i){let s=i.length,l=!1;for(;s--;){const o=i[s][1];if((o.type==="labelLink"||o.type==="labelImage")&&!o._balanced){l=!0;break}if(o._gfmAutolinkLiteralWalkedInto){l=!1;break}}return i.length>0&&!l&&(i[i.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),l}const Pw={tokenize:Ww,partial:!0};function Fw(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:Gw,continuation:{tokenize:Kw},exit:Xw}},text:{91:{name:"gfmFootnoteCall",tokenize:Yw},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:qw,resolveTo:Vw}}}}function qw(i,s,l){const o=this;let S=o.events.length;const b=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let _;for(;S--;){const u=o.events[S][1];if(u.type==="labelImage"){_=u;break}if(u.type==="gfmFootnoteCall"||u.type==="labelLink"||u.type==="label"||u.type==="image"||u.type==="link")break}return a;function a(u){if(!_||!_._balanced)return l(u);const h=pi(o.sliceSerialize({start:_.end,end:o.now()}));return h.codePointAt(0)!==94||!b.includes(h.slice(1))?l(u):(i.enter("gfmFootnoteCallLabelMarker"),i.consume(u),i.exit("gfmFootnoteCallLabelMarker"),s(u))}}function Vw(i,s){let l=i.length;for(;l--;)if(i[l][1].type==="labelImage"&&i[l][0]==="enter"){i[l][1];break}i[l+1][1].type="data",i[l+3][1].type="gfmFootnoteCallLabelMarker";const o={type:"gfmFootnoteCall",start:Object.assign({},i[l+3][1].start),end:Object.assign({},i[i.length-1][1].end)},S={type:"gfmFootnoteCallMarker",start:Object.assign({},i[l+3][1].end),end:Object.assign({},i[l+3][1].end)};S.end.column++,S.end.offset++,S.end._bufferIndex++;const b={type:"gfmFootnoteCallString",start:Object.assign({},S.end),end:Object.assign({},i[i.length-1][1].start)},_={type:"chunkString",contentType:"string",start:Object.assign({},b.start),end:Object.assign({},b.end)},a=[i[l+1],i[l+2],["enter",o,s],i[l+3],i[l+4],["enter",S,s],["exit",S,s],["enter",b,s],["enter",_,s],["exit",_,s],["exit",b,s],i[i.length-2],i[i.length-1],["exit",o,s]];return i.splice(l,i.length-l+1,...a),i}function Yw(i,s,l){const o=this,S=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let b=0,_;return a;function a(c){return i.enter("gfmFootnoteCall"),i.enter("gfmFootnoteCallLabelMarker"),i.consume(c),i.exit("gfmFootnoteCallLabelMarker"),u}function u(c){return c!==94?l(c):(i.enter("gfmFootnoteCallMarker"),i.consume(c),i.exit("gfmFootnoteCallMarker"),i.enter("gfmFootnoteCallString"),i.enter("chunkString").contentType="string",h)}function h(c){if(b>999||c===93&&!_||c===null||c===91||et(c))return l(c);if(c===93){i.exit("chunkString");const C=i.exit("gfmFootnoteCallString");return S.includes(pi(o.sliceSerialize(C)))?(i.enter("gfmFootnoteCallLabelMarker"),i.consume(c),i.exit("gfmFootnoteCallLabelMarker"),i.exit("gfmFootnoteCall"),s):l(c)}return et(c)||(_=!0),b++,i.consume(c),c===92?g:h}function g(c){return c===91||c===92||c===93?(i.consume(c),b++,h):h(c)}}function Gw(i,s,l){const o=this,S=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let b,_=0,a;return u;function u(T){return i.enter("gfmFootnoteDefinition")._container=!0,i.enter("gfmFootnoteDefinitionLabel"),i.enter("gfmFootnoteDefinitionLabelMarker"),i.consume(T),i.exit("gfmFootnoteDefinitionLabelMarker"),h}function h(T){return T===94?(i.enter("gfmFootnoteDefinitionMarker"),i.consume(T),i.exit("gfmFootnoteDefinitionMarker"),i.enter("gfmFootnoteDefinitionLabelString"),i.enter("chunkString").contentType="string",g):l(T)}function g(T){if(_>999||T===93&&!a||T===null||T===91||et(T))return l(T);if(T===93){i.exit("chunkString");const x=i.exit("gfmFootnoteDefinitionLabelString");return b=pi(o.sliceSerialize(x)),i.enter("gfmFootnoteDefinitionLabelMarker"),i.consume(T),i.exit("gfmFootnoteDefinitionLabelMarker"),i.exit("gfmFootnoteDefinitionLabel"),C}return et(T)||(a=!0),_++,i.consume(T),T===92?c:g}function c(T){return T===91||T===92||T===93?(i.consume(T),_++,g):g(T)}function C(T){return T===58?(i.enter("definitionMarker"),i.consume(T),i.exit("definitionMarker"),S.includes(b)||S.push(b),Ie(i,w,"gfmFootnoteDefinitionWhitespace")):l(T)}function w(T){return s(T)}}function Kw(i,s,l){return i.check(Hs,s,i.attempt(Pw,s,l))}function Xw(i){i.exit("gfmFootnoteDefinition")}function Ww(i,s,l){const o=this;return Ie(i,S,"gfmFootnoteDefinitionIndent",5);function S(b){const _=o.events[o.events.length-1];return _&&_[1].type==="gfmFootnoteDefinitionIndent"&&_[2].sliceSerialize(_[1],!0).length===4?s(b):l(b)}}function $w(i){let l=(i||{}).singleTilde;const o={name:"strikethrough",tokenize:b,resolveAll:S};return l==null&&(l=!0),{text:{126:o},insideSpan:{null:[o]},attentionMarkers:{null:[126]}};function S(_,a){let u=-1;for(;++u<_.length;)if(_[u][0]==="enter"&&_[u][1].type==="strikethroughSequenceTemporary"&&_[u][1]._close){let h=u;for(;h--;)if(_[h][0]==="exit"&&_[h][1].type==="strikethroughSequenceTemporary"&&_[h][1]._open&&_[u][1].end.offset-_[u][1].start.offset===_[h][1].end.offset-_[h][1].start.offset){_[u][1].type="strikethroughSequence",_[h][1].type="strikethroughSequence";const g={type:"strikethrough",start:Object.assign({},_[h][1].start),end:Object.assign({},_[u][1].end)},c={type:"strikethroughText",start:Object.assign({},_[h][1].end),end:Object.assign({},_[u][1].start)},C=[["enter",g,a],["enter",_[h][1],a],["exit",_[h][1],a],["enter",c,a]],w=a.parser.constructs.insideSpan.null;w&&Zt(C,C.length,0,ha(w,_.slice(h+1,u),a)),Zt(C,C.length,0,[["exit",c,a],["enter",_[u][1],a],["exit",_[u][1],a],["exit",g,a]]),Zt(_,h-1,u-h+3,C),u=h+C.length-2;break}}for(u=-1;++u<_.length;)_[u][1].type==="strikethroughSequenceTemporary"&&(_[u][1].type="data");return _}function b(_,a,u){const h=this.previous,g=this.events;let c=0;return C;function C(T){return h===126&&g[g.length-1][1].type!=="characterEscape"?u(T):(_.enter("strikethroughSequenceTemporary"),w(T))}function w(T){const x=Dr(h);if(T===126)return c>1?u(T):(_.consume(T),c++,w);if(c<2&&!l)return u(T);const v=_.exit("strikethroughSequenceTemporary"),p=Dr(T);return v._open=!p||p===2&&!!x,v._close=!x||x===2&&!!p,a(T)}}}class Qw{constructor(){this.map=[]}add(s,l,o){Zw(this,s,l,o)}consume(s){if(this.map.sort(function(b,_){return b[0]-_[0]}),this.map.length===0)return;let l=this.map.length;const o=[];for(;l>0;)l-=1,o.push(s.slice(this.map[l][0]+this.map[l][1]),this.map[l][2]),s.length=this.map[l][0];o.push(s.slice()),s.length=0;let S=o.pop();for(;S;){for(const b of S)s.push(b);S=o.pop()}this.map.length=0}}function Zw(i,s,l,o){let S=0;if(!(l===0&&o.length===0)){for(;S<i.map.length;){if(i.map[S][0]===s){i.map[S][1]+=l,i.map[S][2].push(...o);return}S+=1}i.map.push([s,l,o])}}function Jw(i,s){let l=!1;const o=[];for(;s<i.length;){const S=i[s];if(l){if(S[0]==="enter")S[1].type==="tableContent"&&o.push(i[s+1][1].type==="tableDelimiterMarker"?"left":"none");else if(S[1].type==="tableContent"){if(i[s-1][1].type==="tableDelimiterMarker"){const b=o.length-1;o[b]=o[b]==="left"?"center":"right"}}else if(S[1].type==="tableDelimiterRow")break}else S[0]==="enter"&&S[1].type==="tableDelimiterRow"&&(l=!0);s+=1}return o}function ex(){return{flow:{null:{name:"table",tokenize:tx,resolveAll:ix}}}}function tx(i,s,l){const o=this;let S=0,b=0,_;return a;function a(j){let P=o.events.length-1;for(;P>-1;){const Y=o.events[P][1].type;if(Y==="lineEnding"||Y==="linePrefix")P--;else break}const V=P>-1?o.events[P][1].type:null,q=V==="tableHead"||V==="tableRow"?A:u;return q===A&&o.parser.lazy[o.now().line]?l(j):q(j)}function u(j){return i.enter("tableHead"),i.enter("tableRow"),h(j)}function h(j){return j===124||(_=!0,b+=1),g(j)}function g(j){return j===null?l(j):Ce(j)?b>1?(b=0,o.interrupt=!0,i.exit("tableRow"),i.enter("lineEnding"),i.consume(j),i.exit("lineEnding"),w):l(j):ze(j)?Ie(i,g,"whitespace")(j):(b+=1,_&&(_=!1,S+=1),j===124?(i.enter("tableCellDivider"),i.consume(j),i.exit("tableCellDivider"),_=!0,g):(i.enter("data"),c(j)))}function c(j){return j===null||j===124||et(j)?(i.exit("data"),g(j)):(i.consume(j),j===92?C:c)}function C(j){return j===92||j===124?(i.consume(j),c):c(j)}function w(j){return o.interrupt=!1,o.parser.lazy[o.now().line]?l(j):(i.enter("tableDelimiterRow"),_=!1,ze(j)?Ie(i,T,"linePrefix",o.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(j):T(j))}function T(j){return j===45||j===58?v(j):j===124?(_=!0,i.enter("tableCellDivider"),i.consume(j),i.exit("tableCellDivider"),x):R(j)}function x(j){return ze(j)?Ie(i,v,"whitespace")(j):v(j)}function v(j){return j===58?(b+=1,_=!0,i.enter("tableDelimiterMarker"),i.consume(j),i.exit("tableDelimiterMarker"),p):j===45?(b+=1,p(j)):j===null||Ce(j)?E(j):R(j)}function p(j){return j===45?(i.enter("tableDelimiterFiller"),d(j)):R(j)}function d(j){return j===45?(i.consume(j),d):j===58?(_=!0,i.exit("tableDelimiterFiller"),i.enter("tableDelimiterMarker"),i.consume(j),i.exit("tableDelimiterMarker"),m):(i.exit("tableDelimiterFiller"),m(j))}function m(j){return ze(j)?Ie(i,E,"whitespace")(j):E(j)}function E(j){return j===124?T(j):j===null||Ce(j)?!_||S!==b?R(j):(i.exit("tableDelimiterRow"),i.exit("tableHead"),s(j)):R(j)}function R(j){return l(j)}function A(j){return i.enter("tableRow"),L(j)}function L(j){return j===124?(i.enter("tableCellDivider"),i.consume(j),i.exit("tableCellDivider"),L):j===null||Ce(j)?(i.exit("tableRow"),s(j)):ze(j)?Ie(i,L,"whitespace")(j):(i.enter("data"),k(j))}function k(j){return j===null||j===124||et(j)?(i.exit("data"),L(j)):(i.consume(j),j===92?O:k)}function O(j){return j===92||j===124?(i.consume(j),k):k(j)}}function ix(i,s){let l=-1,o=!0,S=0,b=[0,0,0,0],_=[0,0,0,0],a=!1,u=0,h,g,c;const C=new Qw;for(;++l<i.length;){const w=i[l],T=w[1];w[0]==="enter"?T.type==="tableHead"?(a=!1,u!==0&&(L_(C,s,u,h,g),g=void 0,u=0),h={type:"table",start:Object.assign({},T.start),end:Object.assign({},T.end)},C.add(l,0,[["enter",h,s]])):T.type==="tableRow"||T.type==="tableDelimiterRow"?(o=!0,c=void 0,b=[0,0,0,0],_=[0,l+1,0,0],a&&(a=!1,g={type:"tableBody",start:Object.assign({},T.start),end:Object.assign({},T.end)},C.add(l,0,[["enter",g,s]])),S=T.type==="tableDelimiterRow"?2:g?3:1):S&&(T.type==="data"||T.type==="tableDelimiterMarker"||T.type==="tableDelimiterFiller")?(o=!1,_[2]===0&&(b[1]!==0&&(_[0]=_[1],c=na(C,s,b,S,void 0,c),b=[0,0,0,0]),_[2]=l)):T.type==="tableCellDivider"&&(o?o=!1:(b[1]!==0&&(_[0]=_[1],c=na(C,s,b,S,void 0,c)),b=_,_=[b[1],l,0,0])):T.type==="tableHead"?(a=!0,u=l):T.type==="tableRow"||T.type==="tableDelimiterRow"?(u=l,b[1]!==0?(_[0]=_[1],c=na(C,s,b,S,l,c)):_[1]!==0&&(c=na(C,s,_,S,l,c)),S=0):S&&(T.type==="data"||T.type==="tableDelimiterMarker"||T.type==="tableDelimiterFiller")&&(_[3]=l)}for(u!==0&&L_(C,s,u,h,g),C.consume(s.events),l=-1;++l<s.events.length;){const w=s.events[l];w[0]==="enter"&&w[1].type==="table"&&(w[1]._align=Jw(s.events,l))}return i}function na(i,s,l,o,S,b){const _=o===1?"tableHeader":o===2?"tableDelimiter":"tableData",a="tableContent";l[0]!==0&&(b.end=Object.assign({},Ar(s.events,l[0])),i.add(l[0],0,[["exit",b,s]]));const u=Ar(s.events,l[1]);if(b={type:_,start:Object.assign({},u),end:Object.assign({},u)},i.add(l[1],0,[["enter",b,s]]),l[2]!==0){const h=Ar(s.events,l[2]),g=Ar(s.events,l[3]),c={type:a,start:Object.assign({},h),end:Object.assign({},g)};if(i.add(l[2],0,[["enter",c,s]]),o!==2){const C=s.events[l[2]],w=s.events[l[3]];if(C[1].end=Object.assign({},w[1].end),C[1].type="chunkText",C[1].contentType="text",l[3]>l[2]+1){const T=l[2]+1,x=l[3]-l[2]-1;i.add(T,x,[])}}i.add(l[3]+1,0,[["exit",c,s]])}return S!==void 0&&(b.end=Object.assign({},Ar(s.events,S)),i.add(S,0,[["exit",b,s]]),b=void 0),b}function L_(i,s,l,o,S){const b=[],_=Ar(s.events,l);S&&(S.end=Object.assign({},_),b.push(["exit",S,s])),o.end=Object.assign({},_),b.push(["exit",o,s]),i.add(l+1,0,b)}function Ar(i,s){const l=i[s],o=l[0]==="enter"?"start":"end";return l[1][o]}const nx={name:"tasklistCheck",tokenize:sx};function rx(){return{text:{91:nx}}}function sx(i,s,l){const o=this;return S;function S(u){return o.previous!==null||!o._gfmTasklistFirstContentOfListItem?l(u):(i.enter("taskListCheck"),i.enter("taskListCheckMarker"),i.consume(u),i.exit("taskListCheckMarker"),b)}function b(u){return et(u)?(i.enter("taskListCheckValueUnchecked"),i.consume(u),i.exit("taskListCheckValueUnchecked"),_):u===88||u===120?(i.enter("taskListCheckValueChecked"),i.consume(u),i.exit("taskListCheckValueChecked"),_):l(u)}function _(u){return u===93?(i.enter("taskListCheckMarker"),i.consume(u),i.exit("taskListCheckMarker"),i.exit("taskListCheck"),a):l(u)}function a(u){return Ce(u)?s(u):ze(u)?i.check({tokenize:lx},s,l)(u):l(u)}}function lx(i,s,l){return Ie(i,o,"whitespace");function o(S){return S===null?l(S):s(S)}}function ax(i){return W_([Mw(),Fw(),$w(i),ex(),rx()])}const ox={};function ux(i){const s=this,l=i||ox,o=s.data(),S=o.micromarkExtensions||(o.micromarkExtensions=[]),b=o.fromMarkdownExtensions||(o.fromMarkdownExtensions=[]),_=o.toMarkdownExtensions||(o.toMarkdownExtensions=[]);S.push(ax(l)),b.push(Tw()),_.push(Dw(l))}function cx({settings:i,busy:s=!1,promptPreviews:l,testResult:o,onSave:S,onTest:b,onClose:_}){const[a,u]=ge.useState(i),[h,g]=ge.useState(i.apiKey??"");return ge.useEffect(()=>{u(i),g(i.apiKey??"")},[i]),F.jsx("div",{className:"modal-backdrop",children:F.jsxs("section",{className:"translation-settings-modal",role:"dialog","aria-modal":"true","aria-label":"Translation Settings",children:[F.jsxs("header",{children:[F.jsxs("div",{children:[F.jsx("h2",{children:"Translation Settings"}),F.jsx("p",{children:"Use an OpenAI-compatible endpoint for the embedded translation panel."})]}),F.jsx("button",{type:"button",onClick:_,children:"Close"})]}),F.jsxs("div",{className:"translation-settings-grid",children:[F.jsxs("label",{children:[F.jsx("span",{children:"Base URL"}),F.jsx("input",{value:a.baseUrl,onChange:c=>u({...a,baseUrl:c.target.value}),placeholder:"https://api.openai.com/v1"})]}),F.jsxs("label",{children:[F.jsx("span",{children:"API key"}),F.jsx("input",{value:h,onChange:c=>g(c.target.value),placeholder:"API key",autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:!1,type:"text"})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Model"}),F.jsx("input",{value:a.model,onChange:c=>u({...a,model:c.target.value})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Target language"}),F.jsx("input",{value:a.targetLanguage,onChange:c=>u({...a,targetLanguage:c.target.value})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Use context"}),F.jsx("input",{checked:a.contextEnabled,type:"checkbox",onChange:c=>u({...a,contextEnabled:c.target.checked})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Timeout ms"}),F.jsx("input",{min:3e3,type:"number",value:a.requestTimeoutMs,onChange:c=>u({...a,requestTimeoutMs:Number(c.target.value)})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Temperature"}),F.jsx("input",{min:0,max:1,step:.1,type:"number",value:a.temperature,onChange:c=>u({...a,temperature:Number(c.target.value)})})]})]}),F.jsxs("section",{className:"translation-prompt-settings",children:[F.jsxs("header",{children:[F.jsxs("div",{children:[F.jsx("h3",{children:"Translation Prompts"}),F.jsx("p",{children:"Edit the three cc-pm style prompt slots directly."})]}),F.jsx("button",{type:"button",disabled:s,onClick:()=>u({...a,prompts:void 0}),children:"Reset prompts"})]}),F.jsx("div",{className:"translation-prompt-stack",children:l.map(c=>F.jsxs("label",{children:[F.jsx("span",{children:c.label}),F.jsx("textarea",{value:fx(a,c),onChange:C=>u({...a,prompts:hx(a.prompts,c.key,C.target.value,c.defaultPrompt)})})]},c.key))})]}),o?F.jsx("div",{className:o.ok?"translation-test-result is-ok":"translation-test-result is-error",children:o.ok?`Connection ok: ${o.model} in ${o.elapsedMs}ms`:o.error}):null,F.jsxs("footer",{children:[F.jsx("button",{type:"button",disabled:s,onClick:b,children:"Test Connection"}),F.jsx("button",{type:"button",disabled:s,onClick:()=>void S({...a,enabled:!0,translateOutput:!0,translateUserInput:!0,inputMode:"review-before-send"},h.trim()),children:"Save"})]})]})})}function hx(i,s,l,o){const S={...i??{}};return l.trim()&&l!==o?S[s]=l:delete S[s],Object.keys(S).length>0?S:void 0}function fx(i,s){var l;return((l=i.prompts)==null?void 0:l[s.key])??s.defaultPrompt}function dx({active:i=!0,taskSlug:s,role:l,sessionId:o}){const[S,b]=ge.useState(null),[_,a]=ge.useState([]),[u,h]=ge.useState(""),[g,c]=ge.useState(!1),[C,w]=ge.useState(!1),[T,x]=ge.useState(!1),[v,p]=ge.useState("ready"),[d,m]=ge.useState(""),[E,R]=ge.useState(Date.now()),[A,L]=ge.useState(!1),[k,O]=ge.useState(""),[j,P]=ge.useState(!1),[V,q]=ge.useState([]),[Y,$]=ge.useState(),[G,J]=ge.useState(0),ne=ge.useRef(i),z=ge.useRef(1),M=ge.useRef(null);ge.useEffect(()=>{ne.current=i},[i]),ge.useEffect(()=>{Promise.all([je.getTranslationSettings(),je.getTranslationPrompts()]).then(([Q,de])=>{b(Q),q(de)}).catch(Q=>O(Q.message))},[]),ge.useEffect(()=>{a([]),O(""),p("ready"),m(""),z.current=1;let Q=!1,de;const pe=()=>{Q||(de=window.setTimeout(ke,ne.current?200:1e3))},ke=async()=>{if(!Q)try{const xe=await je.pollTranslationSession(o,z.current);if(Q)return;H(xe.events),z.current=xe.nextCursor,p(xe.status),ne.current&&m(bx(new Date().toISOString()))}catch(xe){Q||O(xe instanceof Error?xe.message:"Translation poll failed.")}finally{pe()}};return je.startTranslationSession(s,l).then(xe=>{Q||(p(xe.status),z.current=xe.nextCursor,ke())}).catch(xe=>{Q||O(xe instanceof Error?xe.message:"Translation start failed.")}),()=>{Q=!0,de!==void 0&&window.clearTimeout(de)}},[o,s,l,G]),ge.useEffect(()=>{var Q;i&&((Q=M.current)==null||Q.scrollIntoView({block:"nearest"}))},[i,_.length]);const B=_x(_);ge.useEffect(()=>{if(!B)return;R(Date.now());const Q=window.setInterval(()=>R(Date.now()),250);return()=>window.clearInterval(Q)},[B]);async function I(Q=!1){if(S){L(!0),O(""),c(!1);try{const de=await je.translateUserInput(s,l,{text:u,mode:Q?"auto-send":"review-before-send",useContext:S.contextEnabled,send:Q});x(de.contextUsed),de.sent?(h(""),c(!1)):(h(de.englishPreview),c(!0))}catch(de){O(de instanceof Error?de.message:"Translation failed.")}finally{L(!1)}}}function H(Q){if(Q.length===0)return;for(const pe of Q)pe.type==="status"?p(pe.status):pe.type==="error"&&O(pe.message);const de=Q.filter(pe=>pe.type==="entry");de.length>0&&a(pe=>de.reduce((ke,xe)=>Sx(ke,xe.entry),pe))}async function ie(){if(u.trim()){L(!0),O("");try{await je.sendTranslatedInput(s,l,{englishText:u}),h(""),c(!1),x(!1)}catch(Q){O(Q instanceof Error?Q.message:"Failed to send English input.")}finally{L(!1)}}}function he(Q){Q.key!=="Enter"||Q.shiftKey||Q.nativeEvent.isComposing||(Q.preventDefault(),!A&&u.trim()&&(g?ie():I(C)))}async function fe(Q,de){L(!0),O("");try{const pe=await je.updateTranslationSettings({...Q,...de!==void 0?{apiKey:de}:{}}),ke=await je.getTranslationPrompts();b(pe),q(ke),P(!1),J(xe=>xe+1)}catch(pe){O(pe instanceof Error?pe.message:"Failed to save translation settings.")}finally{L(!1)}}async function X(){L(!0),O("");try{$(await je.testTranslationProvider())}catch(Q){O(Q instanceof Error?Q.message:"Provider test failed.")}finally{L(!1)}}async function N(){a([]),z.current=1,await je.clearTranslationSession(o).catch(Q=>O(Q.message))}if(!S)return F.jsx("aside",{className:"translation-panel",children:F.jsx("p",{className:"muted",children:"Loading translation settings..."})});const re=mx(_,v,E);return F.jsxs("aside",{className:"translation-panel",children:[F.jsxs("header",{className:"translation-panel-header",children:[F.jsxs("div",{className:"translation-panel-titlebar",children:[F.jsx("h2",{children:"Translation"}),F.jsxs("div",{className:"translation-panel-actions",children:[F.jsx("button",{"aria-pressed":C,className:`auto-send-toggle${C?" is-active":""}`,type:"button",onClick:()=>w(Q=>!Q),children:C?"✅ Auto-send":"× Auto-send"}),F.jsx("button",{type:"button",onClick:()=>P(!0),children:"Settings"}),F.jsx("button",{type:"button",onClick:()=>void N(),children:"Clear"})]})]}),F.jsxs("div",{className:"translation-status-row",children:[F.jsxs("p",{children:[S.model," · ",re,T?" · context used":""]}),F.jsx("p",{children:d?`poll ${d}`:"poll -"})]})]}),k?F.jsx("div",{className:"error-banner",children:k}):null,F.jsxs("div",{className:"translation-entry-list",children:[_.length===0?F.jsx("p",{className:"muted",children:"Translated Claude Code output will appear here."}):null,_.map(Q=>F.jsx(px,{entry:Q},Q.id)),F.jsx("div",{ref:M})]}),F.jsx("div",{className:"translation-composer",children:F.jsxs("div",{className:"translation-composer-row",children:[F.jsx("textarea",{value:u,onChange:Q=>{h(Q.target.value),Q.target.value.trim()||c(!1)},onKeyDown:he,placeholder:"输入中文,先翻译成英文工程指令..."}),F.jsx("div",{className:"translation-composer-actions",children:F.jsx("button",{type:"button",disabled:A||!g||!u.trim(),onClick:()=>void ie(),children:"Send English"})})]})}),j?F.jsx(cx,{settings:S,busy:A,promptPreviews:V,testResult:Y,onSave:fe,onTest:X,onClose:()=>P(!1)}):null]})}function px({entry:i}){const s=vx(i),l=i.sourceKind==="tool-output";return F.jsxs("article",{className:`translation-entry is-${i.sourceKind}`,children:[l?F.jsx("pre",{children:s}):F.jsx("div",{className:"translation-markdown",children:F.jsx($b,{remarkPlugins:[ux],children:s})}),i.warning?F.jsx("p",{className:"translation-entry-note",children:i.warning}):null,i.error?F.jsx("p",{className:"translation-entry-note is-error",children:i.error}):null]})}function _x(i){const s=i.find(Um);return(s==null?void 0:s.translationStartedAt)??(s==null?void 0:s.createdAt)}function mx(i,s,l){const o=i.find(Um);if(o)return`translating ${yx(Math.max(0,l-gx(o)))}`;const S=i.at(-1);return(S==null?void 0:S.status)==="failed"||s==="failed"?"error":s}function Um(i){return i.status==="queued"||i.status==="translating"}function gx(i){const s=Date.parse(i.translationStartedAt??i.createdAt);return Number.isFinite(s)?s:Date.now()}function vx(i){return i.status==="queued"||i.status==="translating"?i.sourceText:i.status==="translated"?i.translatedText:i.translatedText||i.sourceText}function Sx(i,s){return i.findIndex(o=>o.id===s.id)===-1?[...i,s]:i.map(o=>o.id===s.id?s:o)}function yx(i){if(i<1e3)return`${Math.max(.1,i/1e3).toFixed(1)}s`;const s=i/1e3;if(s<60)return`${s.toFixed(1)}s`;const l=Math.floor(s/60),o=Math.floor(s%60).toString().padStart(2,"0");return`${l}:${o}`}function bx(i){const s=new Date(i);return Number.isNaN(s.getTime())?i:s.toLocaleTimeString()}function Cx({role:i,session:s,permissionMode:l,active:o=!0,busy:S,onPermissionModeChange:b,onStart:_,onResume:a,onStop:u,onRestart:h,onTerminalEvent:g}){const[c,C]=ge.useState(!1);return F.jsxs("section",{className:"session-console",children:[F.jsxs("div",{className:"session-console-top",children:[F.jsx(NS,{role:i,session:s,permissionMode:l,busy:S,onPermissionModeChange:b,onStart:_,onResume:a,onStop:u,onRestart:h}),F.jsx("button",{"aria-pressed":c,className:`translation-toggle${c?" is-active":""}`,type:"button",onClick:()=>C(w=>!w),children:c?"✅ Translate":"× Translate"})]}),(s==null?void 0:s.status)==="running"?F.jsx(wx,{active:o,onTerminalEvent:g,role:i,session:s,taskSlug:s.taskSlug,translationEnabled:c}):F.jsxs("div",{className:"terminal-empty",children:[F.jsx("strong",{children:i}),F.jsx("span",{children:s!=null&&s.claudeSessionId?"Resume this role to reconnect its Claude Code conversation.":"Start this role to open an embedded Claude Code terminal."})]})]})}function wx({active:i,onTerminalEvent:s,role:l,session:o,taskSlug:S,translationEnabled:b}){return F.jsxs("div",{className:b?"session-console-body has-translation":"session-console-body",children:[F.jsx("div",{className:"terminal-pane",children:F.jsx(zS,{sessionId:o.id,active:i,onEvent:s},o.id)}),b?F.jsx("div",{className:"translation-pane",children:F.jsx(dx,{active:i,taskSlug:S,role:l,sessionId:o.id},o.id)}):null]})}function xx({task:i,activeRole:s,onTaskChanged:l,onActiveRoleChange:o,onWorkflowChanged:S,onMessagesChanged:b,onOrchestrationChanged:_,onEventsChanged:a}){const[u,h]=ge.useState(null),[g,c]=ge.useState({"project-manager":"default",architect:"default",coder:"default",reviewer:"default"}),[C,w]=ge.useState(!1),[T,x]=ge.useState(""),[v,p]=ge.useState([]),d=ge.useCallback(async()=>{const[L,k,O]=await Promise.all([je.getTaskStatus(i.taskSlug),je.listMessages(i.taskSlug),je.getOrchestrationState(i.taskSlug)]);h(L),S==null||S(L.workflow),b==null||b(k),_==null||_(O)},[b,_,S,i.taskSlug]);ge.useEffect(()=>{d().catch(L=>x(L.message))},[d]),ge.useEffect(()=>{p([]),a==null||a([])},[a,i.taskSlug]),ge.useEffect(()=>{c(L=>{let k=!1;const O={...L};for(const j of(u==null?void 0:u.sessions)??[])O[j.role]!==j.permissionMode&&(O[j.role]=j.permissionMode,k=!0);return k?O:L})},[u==null?void 0:u.sessions]),ge.useEffect(()=>{const L=window.setInterval(()=>{Promise.all([je.getTaskStatus(i.taskSlug),je.listMessages(i.taskSlug),je.getOrchestrationState(i.taskSlug)]).then(([k,O,j])=>{h(k),S==null||S(k.workflow),b==null||b(O),_==null||_(j)}).catch(k=>x(k.message))},3e3);return()=>window.clearInterval(L)},[b,_,S,i.taskSlug]);async function m(L){w(!0),x("");try{await L(),await d(),await l()}catch(k){x(k instanceof Error?k.message:"Action failed.")}finally{w(!1)}}async function E(){const L=i.worktreePath?[`Close task "${i.taskSlug}"?`,"","This is destructive:",`- deletes the task worktree: ${i.worktreePath}`,`- deletes the Git branch: ${i.branch}`,"- deletes VCM task/session/message/orchestration state","","VCM will not check running sessions or uncommitted changes before closing."].join(`
|
|
87
|
-
`):[`Close task "${i.taskSlug}"?`,"","This task was created without a separate worktree/branch.","VCM will delete task/session/message/orchestration state only.","","VCM will not check running sessions or uncommitted changes before closing."].join(`
|
|
86
|
+
`))}function u(w,T,x,v){const p=x.enter("tableCell"),d=x.enter("phrasing"),m=x.containerPhrasing(w,{...v,before:b,after:b});return d(),p(),m}function h(w,T){return NC(w,{align:T,alignDelimiters:o,padding:l,stringLength:S})}function g(w,T,x){const v=w.children;let p=-1;const d=[],m=T.enter("table");for(;++p<v.length;)d[p]=c(v[p],T,x);return m(),d}function c(w,T,x){const v=w.children;let p=-1;const d=[],m=T.enter("tableRow");for(;++p<v.length;)d[p]=u(v[p],w,T,x);return m(),d}function C(w,T,x){let v=Rm.inlineCode(w,T,x);return x.stack.includes("tableCell")&&(v=v.replace(/\|/g,"\\$&")),v}}function xw(){return{exit:{taskListCheckValueChecked:R_,taskListCheckValueUnchecked:R_,paragraph:kw}}}function Ew(){return{unsafe:[{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{listItem:Aw}}}function R_(i){const s=this.stack[this.stack.length-2];s.type,s.checked=i.type==="taskListCheckValueChecked"}function kw(i){const s=this.stack[this.stack.length-2];if(s&&s.type==="listItem"&&typeof s.checked=="boolean"){const l=this.stack[this.stack.length-1];l.type;const o=l.children[0];if(o&&o.type==="text"){const S=s.children;let b=-1,_;for(;++b<S.length;){const a=S[b];if(a.type==="paragraph"){_=a;break}}_===l&&(o.value=o.value.slice(1),o.value.length===0?l.children.shift():l.position&&o.position&&typeof o.position.start.offset=="number"&&(o.position.start.column++,o.position.start.offset++,l.position.start=Object.assign({},o.position.start)))}}this.exit(i)}function Aw(i,s,l,o){const S=i.children[0],b=typeof i.checked=="boolean"&&S&&S.type==="paragraph",_="["+(i.checked?"x":" ")+"] ",a=l.createTracker(o);b&&a.move(_);let u=Rm.listItem(i,s,l,{...o,...a.current()});return b&&(u=u.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/,h)),u;function h(g){return g+_}}function Tw(){return[lC(),AC(),LC(),gw(),xw()]}function Dw(i){return{extensions:[aC(),TC(i),MC(),ww(i),Ew()]}}const Rw={tokenize:Hw,partial:!0},Lm={tokenize:Nw,partial:!0},Mm={tokenize:jw,partial:!0},Om={tokenize:Uw,partial:!0},Lw={tokenize:Iw,partial:!0},Bm={name:"wwwAutolink",tokenize:Bw,previous:Hm},zm={name:"protocolAutolink",tokenize:zw,previous:Nm},qi={name:"emailAutolink",tokenize:Ow,previous:jm},wi={};function Mw(){return{text:wi}}let jn=48;for(;jn<123;)wi[jn]=qi,jn++,jn===58?jn=65:jn===91&&(jn=97);wi[43]=qi;wi[45]=qi;wi[46]=qi;wi[95]=qi;wi[72]=[qi,zm];wi[104]=[qi,zm];wi[87]=[qi,Bm];wi[119]=[qi,Bm];function Ow(i,s,l){const o=this;let S,b;return _;function _(c){return!cc(c)||!jm.call(o,o.previous)||Rc(o.events)?l(c):(i.enter("literalAutolink"),i.enter("literalAutolinkEmail"),a(c))}function a(c){return cc(c)?(i.consume(c),a):c===64?(i.consume(c),u):l(c)}function u(c){return c===46?i.check(Lw,g,h)(c):c===45||c===95||Dt(c)?(b=!0,i.consume(c),u):g(c)}function h(c){return i.consume(c),S=!0,u}function g(c){return b&&S&&Mt(o.previous)?(i.exit("literalAutolinkEmail"),i.exit("literalAutolink"),s(c)):l(c)}}function Bw(i,s,l){const o=this;return S;function S(_){return _!==87&&_!==119||!Hm.call(o,o.previous)||Rc(o.events)?l(_):(i.enter("literalAutolink"),i.enter("literalAutolinkWww"),i.check(Rw,i.attempt(Lm,i.attempt(Mm,b),l),l)(_))}function b(_){return i.exit("literalAutolinkWww"),i.exit("literalAutolink"),s(_)}}function zw(i,s,l){const o=this;let S="",b=!1;return _;function _(c){return(c===72||c===104)&&Nm.call(o,o.previous)&&!Rc(o.events)?(i.enter("literalAutolink"),i.enter("literalAutolinkHttp"),S+=String.fromCodePoint(c),i.consume(c),a):l(c)}function a(c){if(Mt(c)&&S.length<5)return S+=String.fromCodePoint(c),i.consume(c),a;if(c===58){const C=S.toLowerCase();if(C==="http"||C==="https")return i.consume(c),u}return l(c)}function u(c){return c===47?(i.consume(c),b?h:(b=!0,u)):l(c)}function h(c){return c===null||sa(c)||et(c)||Un(c)||ca(c)?l(c):i.attempt(Lm,i.attempt(Mm,g),l)(c)}function g(c){return i.exit("literalAutolinkHttp"),i.exit("literalAutolink"),s(c)}}function Hw(i,s,l){let o=0;return S;function S(_){return(_===87||_===119)&&o<3?(o++,i.consume(_),S):_===46&&o===3?(i.consume(_),b):l(_)}function b(_){return _===null?l(_):s(_)}}function Nw(i,s,l){let o,S,b;return _;function _(h){return h===46||h===95?i.check(Om,u,a)(h):h===null||et(h)||Un(h)||h!==45&&ca(h)?u(h):(b=!0,i.consume(h),_)}function a(h){return h===95?o=!0:(S=o,o=void 0),i.consume(h),_}function u(h){return S||o||!b?l(h):s(h)}}function jw(i,s){let l=0,o=0;return S;function S(_){return _===40?(l++,i.consume(_),S):_===41&&o<l?b(_):_===33||_===34||_===38||_===39||_===41||_===42||_===44||_===46||_===58||_===59||_===60||_===63||_===93||_===95||_===126?i.check(Om,s,b)(_):_===null||et(_)||Un(_)?s(_):(i.consume(_),S)}function b(_){return _===41&&o++,i.consume(_),S}}function Uw(i,s,l){return o;function o(a){return a===33||a===34||a===39||a===41||a===42||a===44||a===46||a===58||a===59||a===63||a===95||a===126?(i.consume(a),o):a===38?(i.consume(a),b):a===93?(i.consume(a),S):a===60||a===null||et(a)||Un(a)?s(a):l(a)}function S(a){return a===null||a===40||a===91||et(a)||Un(a)?s(a):o(a)}function b(a){return Mt(a)?_(a):l(a)}function _(a){return a===59?(i.consume(a),o):Mt(a)?(i.consume(a),_):l(a)}}function Iw(i,s,l){return o;function o(b){return i.consume(b),S}function S(b){return Dt(b)?l(b):s(b)}}function Hm(i){return i===null||i===40||i===42||i===95||i===91||i===93||i===126||et(i)}function Nm(i){return!Mt(i)}function jm(i){return!(i===47||cc(i))}function cc(i){return i===43||i===45||i===46||i===95||Dt(i)}function Rc(i){let s=i.length,l=!1;for(;s--;){const o=i[s][1];if((o.type==="labelLink"||o.type==="labelImage")&&!o._balanced){l=!0;break}if(o._gfmAutolinkLiteralWalkedInto){l=!1;break}}return i.length>0&&!l&&(i[i.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),l}const Pw={tokenize:Ww,partial:!0};function Fw(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:Gw,continuation:{tokenize:Kw},exit:Xw}},text:{91:{name:"gfmFootnoteCall",tokenize:Yw},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:qw,resolveTo:Vw}}}}function qw(i,s,l){const o=this;let S=o.events.length;const b=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let _;for(;S--;){const u=o.events[S][1];if(u.type==="labelImage"){_=u;break}if(u.type==="gfmFootnoteCall"||u.type==="labelLink"||u.type==="label"||u.type==="image"||u.type==="link")break}return a;function a(u){if(!_||!_._balanced)return l(u);const h=pi(o.sliceSerialize({start:_.end,end:o.now()}));return h.codePointAt(0)!==94||!b.includes(h.slice(1))?l(u):(i.enter("gfmFootnoteCallLabelMarker"),i.consume(u),i.exit("gfmFootnoteCallLabelMarker"),s(u))}}function Vw(i,s){let l=i.length;for(;l--;)if(i[l][1].type==="labelImage"&&i[l][0]==="enter"){i[l][1];break}i[l+1][1].type="data",i[l+3][1].type="gfmFootnoteCallLabelMarker";const o={type:"gfmFootnoteCall",start:Object.assign({},i[l+3][1].start),end:Object.assign({},i[i.length-1][1].end)},S={type:"gfmFootnoteCallMarker",start:Object.assign({},i[l+3][1].end),end:Object.assign({},i[l+3][1].end)};S.end.column++,S.end.offset++,S.end._bufferIndex++;const b={type:"gfmFootnoteCallString",start:Object.assign({},S.end),end:Object.assign({},i[i.length-1][1].start)},_={type:"chunkString",contentType:"string",start:Object.assign({},b.start),end:Object.assign({},b.end)},a=[i[l+1],i[l+2],["enter",o,s],i[l+3],i[l+4],["enter",S,s],["exit",S,s],["enter",b,s],["enter",_,s],["exit",_,s],["exit",b,s],i[i.length-2],i[i.length-1],["exit",o,s]];return i.splice(l,i.length-l+1,...a),i}function Yw(i,s,l){const o=this,S=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let b=0,_;return a;function a(c){return i.enter("gfmFootnoteCall"),i.enter("gfmFootnoteCallLabelMarker"),i.consume(c),i.exit("gfmFootnoteCallLabelMarker"),u}function u(c){return c!==94?l(c):(i.enter("gfmFootnoteCallMarker"),i.consume(c),i.exit("gfmFootnoteCallMarker"),i.enter("gfmFootnoteCallString"),i.enter("chunkString").contentType="string",h)}function h(c){if(b>999||c===93&&!_||c===null||c===91||et(c))return l(c);if(c===93){i.exit("chunkString");const C=i.exit("gfmFootnoteCallString");return S.includes(pi(o.sliceSerialize(C)))?(i.enter("gfmFootnoteCallLabelMarker"),i.consume(c),i.exit("gfmFootnoteCallLabelMarker"),i.exit("gfmFootnoteCall"),s):l(c)}return et(c)||(_=!0),b++,i.consume(c),c===92?g:h}function g(c){return c===91||c===92||c===93?(i.consume(c),b++,h):h(c)}}function Gw(i,s,l){const o=this,S=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let b,_=0,a;return u;function u(T){return i.enter("gfmFootnoteDefinition")._container=!0,i.enter("gfmFootnoteDefinitionLabel"),i.enter("gfmFootnoteDefinitionLabelMarker"),i.consume(T),i.exit("gfmFootnoteDefinitionLabelMarker"),h}function h(T){return T===94?(i.enter("gfmFootnoteDefinitionMarker"),i.consume(T),i.exit("gfmFootnoteDefinitionMarker"),i.enter("gfmFootnoteDefinitionLabelString"),i.enter("chunkString").contentType="string",g):l(T)}function g(T){if(_>999||T===93&&!a||T===null||T===91||et(T))return l(T);if(T===93){i.exit("chunkString");const x=i.exit("gfmFootnoteDefinitionLabelString");return b=pi(o.sliceSerialize(x)),i.enter("gfmFootnoteDefinitionLabelMarker"),i.consume(T),i.exit("gfmFootnoteDefinitionLabelMarker"),i.exit("gfmFootnoteDefinitionLabel"),C}return et(T)||(a=!0),_++,i.consume(T),T===92?c:g}function c(T){return T===91||T===92||T===93?(i.consume(T),_++,g):g(T)}function C(T){return T===58?(i.enter("definitionMarker"),i.consume(T),i.exit("definitionMarker"),S.includes(b)||S.push(b),Ie(i,w,"gfmFootnoteDefinitionWhitespace")):l(T)}function w(T){return s(T)}}function Kw(i,s,l){return i.check(Hs,s,i.attempt(Pw,s,l))}function Xw(i){i.exit("gfmFootnoteDefinition")}function Ww(i,s,l){const o=this;return Ie(i,S,"gfmFootnoteDefinitionIndent",5);function S(b){const _=o.events[o.events.length-1];return _&&_[1].type==="gfmFootnoteDefinitionIndent"&&_[2].sliceSerialize(_[1],!0).length===4?s(b):l(b)}}function $w(i){let l=(i||{}).singleTilde;const o={name:"strikethrough",tokenize:b,resolveAll:S};return l==null&&(l=!0),{text:{126:o},insideSpan:{null:[o]},attentionMarkers:{null:[126]}};function S(_,a){let u=-1;for(;++u<_.length;)if(_[u][0]==="enter"&&_[u][1].type==="strikethroughSequenceTemporary"&&_[u][1]._close){let h=u;for(;h--;)if(_[h][0]==="exit"&&_[h][1].type==="strikethroughSequenceTemporary"&&_[h][1]._open&&_[u][1].end.offset-_[u][1].start.offset===_[h][1].end.offset-_[h][1].start.offset){_[u][1].type="strikethroughSequence",_[h][1].type="strikethroughSequence";const g={type:"strikethrough",start:Object.assign({},_[h][1].start),end:Object.assign({},_[u][1].end)},c={type:"strikethroughText",start:Object.assign({},_[h][1].end),end:Object.assign({},_[u][1].start)},C=[["enter",g,a],["enter",_[h][1],a],["exit",_[h][1],a],["enter",c,a]],w=a.parser.constructs.insideSpan.null;w&&Zt(C,C.length,0,ha(w,_.slice(h+1,u),a)),Zt(C,C.length,0,[["exit",c,a],["enter",_[u][1],a],["exit",_[u][1],a],["exit",g,a]]),Zt(_,h-1,u-h+3,C),u=h+C.length-2;break}}for(u=-1;++u<_.length;)_[u][1].type==="strikethroughSequenceTemporary"&&(_[u][1].type="data");return _}function b(_,a,u){const h=this.previous,g=this.events;let c=0;return C;function C(T){return h===126&&g[g.length-1][1].type!=="characterEscape"?u(T):(_.enter("strikethroughSequenceTemporary"),w(T))}function w(T){const x=Dr(h);if(T===126)return c>1?u(T):(_.consume(T),c++,w);if(c<2&&!l)return u(T);const v=_.exit("strikethroughSequenceTemporary"),p=Dr(T);return v._open=!p||p===2&&!!x,v._close=!x||x===2&&!!p,a(T)}}}class Qw{constructor(){this.map=[]}add(s,l,o){Zw(this,s,l,o)}consume(s){if(this.map.sort(function(b,_){return b[0]-_[0]}),this.map.length===0)return;let l=this.map.length;const o=[];for(;l>0;)l-=1,o.push(s.slice(this.map[l][0]+this.map[l][1]),this.map[l][2]),s.length=this.map[l][0];o.push(s.slice()),s.length=0;let S=o.pop();for(;S;){for(const b of S)s.push(b);S=o.pop()}this.map.length=0}}function Zw(i,s,l,o){let S=0;if(!(l===0&&o.length===0)){for(;S<i.map.length;){if(i.map[S][0]===s){i.map[S][1]+=l,i.map[S][2].push(...o);return}S+=1}i.map.push([s,l,o])}}function Jw(i,s){let l=!1;const o=[];for(;s<i.length;){const S=i[s];if(l){if(S[0]==="enter")S[1].type==="tableContent"&&o.push(i[s+1][1].type==="tableDelimiterMarker"?"left":"none");else if(S[1].type==="tableContent"){if(i[s-1][1].type==="tableDelimiterMarker"){const b=o.length-1;o[b]=o[b]==="left"?"center":"right"}}else if(S[1].type==="tableDelimiterRow")break}else S[0]==="enter"&&S[1].type==="tableDelimiterRow"&&(l=!0);s+=1}return o}function ex(){return{flow:{null:{name:"table",tokenize:tx,resolveAll:ix}}}}function tx(i,s,l){const o=this;let S=0,b=0,_;return a;function a(j){let P=o.events.length-1;for(;P>-1;){const Y=o.events[P][1].type;if(Y==="lineEnding"||Y==="linePrefix")P--;else break}const V=P>-1?o.events[P][1].type:null,q=V==="tableHead"||V==="tableRow"?A:u;return q===A&&o.parser.lazy[o.now().line]?l(j):q(j)}function u(j){return i.enter("tableHead"),i.enter("tableRow"),h(j)}function h(j){return j===124||(_=!0,b+=1),g(j)}function g(j){return j===null?l(j):Ce(j)?b>1?(b=0,o.interrupt=!0,i.exit("tableRow"),i.enter("lineEnding"),i.consume(j),i.exit("lineEnding"),w):l(j):ze(j)?Ie(i,g,"whitespace")(j):(b+=1,_&&(_=!1,S+=1),j===124?(i.enter("tableCellDivider"),i.consume(j),i.exit("tableCellDivider"),_=!0,g):(i.enter("data"),c(j)))}function c(j){return j===null||j===124||et(j)?(i.exit("data"),g(j)):(i.consume(j),j===92?C:c)}function C(j){return j===92||j===124?(i.consume(j),c):c(j)}function w(j){return o.interrupt=!1,o.parser.lazy[o.now().line]?l(j):(i.enter("tableDelimiterRow"),_=!1,ze(j)?Ie(i,T,"linePrefix",o.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(j):T(j))}function T(j){return j===45||j===58?v(j):j===124?(_=!0,i.enter("tableCellDivider"),i.consume(j),i.exit("tableCellDivider"),x):R(j)}function x(j){return ze(j)?Ie(i,v,"whitespace")(j):v(j)}function v(j){return j===58?(b+=1,_=!0,i.enter("tableDelimiterMarker"),i.consume(j),i.exit("tableDelimiterMarker"),p):j===45?(b+=1,p(j)):j===null||Ce(j)?E(j):R(j)}function p(j){return j===45?(i.enter("tableDelimiterFiller"),d(j)):R(j)}function d(j){return j===45?(i.consume(j),d):j===58?(_=!0,i.exit("tableDelimiterFiller"),i.enter("tableDelimiterMarker"),i.consume(j),i.exit("tableDelimiterMarker"),m):(i.exit("tableDelimiterFiller"),m(j))}function m(j){return ze(j)?Ie(i,E,"whitespace")(j):E(j)}function E(j){return j===124?T(j):j===null||Ce(j)?!_||S!==b?R(j):(i.exit("tableDelimiterRow"),i.exit("tableHead"),s(j)):R(j)}function R(j){return l(j)}function A(j){return i.enter("tableRow"),L(j)}function L(j){return j===124?(i.enter("tableCellDivider"),i.consume(j),i.exit("tableCellDivider"),L):j===null||Ce(j)?(i.exit("tableRow"),s(j)):ze(j)?Ie(i,L,"whitespace")(j):(i.enter("data"),k(j))}function k(j){return j===null||j===124||et(j)?(i.exit("data"),L(j)):(i.consume(j),j===92?O:k)}function O(j){return j===92||j===124?(i.consume(j),k):k(j)}}function ix(i,s){let l=-1,o=!0,S=0,b=[0,0,0,0],_=[0,0,0,0],a=!1,u=0,h,g,c;const C=new Qw;for(;++l<i.length;){const w=i[l],T=w[1];w[0]==="enter"?T.type==="tableHead"?(a=!1,u!==0&&(L_(C,s,u,h,g),g=void 0,u=0),h={type:"table",start:Object.assign({},T.start),end:Object.assign({},T.end)},C.add(l,0,[["enter",h,s]])):T.type==="tableRow"||T.type==="tableDelimiterRow"?(o=!0,c=void 0,b=[0,0,0,0],_=[0,l+1,0,0],a&&(a=!1,g={type:"tableBody",start:Object.assign({},T.start),end:Object.assign({},T.end)},C.add(l,0,[["enter",g,s]])),S=T.type==="tableDelimiterRow"?2:g?3:1):S&&(T.type==="data"||T.type==="tableDelimiterMarker"||T.type==="tableDelimiterFiller")?(o=!1,_[2]===0&&(b[1]!==0&&(_[0]=_[1],c=na(C,s,b,S,void 0,c),b=[0,0,0,0]),_[2]=l)):T.type==="tableCellDivider"&&(o?o=!1:(b[1]!==0&&(_[0]=_[1],c=na(C,s,b,S,void 0,c)),b=_,_=[b[1],l,0,0])):T.type==="tableHead"?(a=!0,u=l):T.type==="tableRow"||T.type==="tableDelimiterRow"?(u=l,b[1]!==0?(_[0]=_[1],c=na(C,s,b,S,l,c)):_[1]!==0&&(c=na(C,s,_,S,l,c)),S=0):S&&(T.type==="data"||T.type==="tableDelimiterMarker"||T.type==="tableDelimiterFiller")&&(_[3]=l)}for(u!==0&&L_(C,s,u,h,g),C.consume(s.events),l=-1;++l<s.events.length;){const w=s.events[l];w[0]==="enter"&&w[1].type==="table"&&(w[1]._align=Jw(s.events,l))}return i}function na(i,s,l,o,S,b){const _=o===1?"tableHeader":o===2?"tableDelimiter":"tableData",a="tableContent";l[0]!==0&&(b.end=Object.assign({},Ar(s.events,l[0])),i.add(l[0],0,[["exit",b,s]]));const u=Ar(s.events,l[1]);if(b={type:_,start:Object.assign({},u),end:Object.assign({},u)},i.add(l[1],0,[["enter",b,s]]),l[2]!==0){const h=Ar(s.events,l[2]),g=Ar(s.events,l[3]),c={type:a,start:Object.assign({},h),end:Object.assign({},g)};if(i.add(l[2],0,[["enter",c,s]]),o!==2){const C=s.events[l[2]],w=s.events[l[3]];if(C[1].end=Object.assign({},w[1].end),C[1].type="chunkText",C[1].contentType="text",l[3]>l[2]+1){const T=l[2]+1,x=l[3]-l[2]-1;i.add(T,x,[])}}i.add(l[3]+1,0,[["exit",c,s]])}return S!==void 0&&(b.end=Object.assign({},Ar(s.events,S)),i.add(S,0,[["exit",b,s]]),b=void 0),b}function L_(i,s,l,o,S){const b=[],_=Ar(s.events,l);S&&(S.end=Object.assign({},_),b.push(["exit",S,s])),o.end=Object.assign({},_),b.push(["exit",o,s]),i.add(l+1,0,b)}function Ar(i,s){const l=i[s],o=l[0]==="enter"?"start":"end";return l[1][o]}const nx={name:"tasklistCheck",tokenize:sx};function rx(){return{text:{91:nx}}}function sx(i,s,l){const o=this;return S;function S(u){return o.previous!==null||!o._gfmTasklistFirstContentOfListItem?l(u):(i.enter("taskListCheck"),i.enter("taskListCheckMarker"),i.consume(u),i.exit("taskListCheckMarker"),b)}function b(u){return et(u)?(i.enter("taskListCheckValueUnchecked"),i.consume(u),i.exit("taskListCheckValueUnchecked"),_):u===88||u===120?(i.enter("taskListCheckValueChecked"),i.consume(u),i.exit("taskListCheckValueChecked"),_):l(u)}function _(u){return u===93?(i.enter("taskListCheckMarker"),i.consume(u),i.exit("taskListCheckMarker"),i.exit("taskListCheck"),a):l(u)}function a(u){return Ce(u)?s(u):ze(u)?i.check({tokenize:lx},s,l)(u):l(u)}}function lx(i,s,l){return Ie(i,o,"whitespace");function o(S){return S===null?l(S):s(S)}}function ax(i){return W_([Mw(),Fw(),$w(i),ex(),rx()])}const ox={};function ux(i){const s=this,l=i||ox,o=s.data(),S=o.micromarkExtensions||(o.micromarkExtensions=[]),b=o.fromMarkdownExtensions||(o.fromMarkdownExtensions=[]),_=o.toMarkdownExtensions||(o.toMarkdownExtensions=[]);S.push(ax(l)),b.push(Tw()),_.push(Dw(l))}function cx({settings:i,busy:s=!1,promptPreviews:l,testResult:o,onSave:S,onTest:b,onClose:_}){const[a,u]=ge.useState(i),[h,g]=ge.useState(i.apiKey??"");return ge.useEffect(()=>{u(i),g(i.apiKey??"")},[i]),F.jsx("div",{className:"modal-backdrop",children:F.jsxs("section",{className:"translation-settings-modal",role:"dialog","aria-modal":"true","aria-label":"Translation Settings",children:[F.jsxs("header",{children:[F.jsxs("div",{children:[F.jsx("h2",{children:"Translation Settings"}),F.jsx("p",{children:"Use an OpenAI-compatible endpoint for the embedded translation panel."})]}),F.jsx("button",{type:"button",onClick:_,children:"Close"})]}),F.jsxs("div",{className:"translation-settings-grid",children:[F.jsxs("label",{children:[F.jsx("span",{children:"Base URL"}),F.jsx("input",{value:a.baseUrl,onChange:c=>u({...a,baseUrl:c.target.value}),placeholder:"https://api.openai.com/v1"})]}),F.jsxs("label",{children:[F.jsx("span",{children:"API key"}),F.jsx("input",{value:h,onChange:c=>g(c.target.value),placeholder:"API key",autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:!1,type:"text"})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Model"}),F.jsx("input",{value:a.model,onChange:c=>u({...a,model:c.target.value})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Target language"}),F.jsx("input",{value:a.targetLanguage,onChange:c=>u({...a,targetLanguage:c.target.value})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Use context"}),F.jsx("input",{checked:a.contextEnabled,type:"checkbox",onChange:c=>u({...a,contextEnabled:c.target.checked})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Timeout ms"}),F.jsx("input",{min:3e3,type:"number",value:a.requestTimeoutMs,onChange:c=>u({...a,requestTimeoutMs:Number(c.target.value)})})]}),F.jsxs("label",{children:[F.jsx("span",{children:"Temperature"}),F.jsx("input",{min:0,max:1,step:.1,type:"number",value:a.temperature,onChange:c=>u({...a,temperature:Number(c.target.value)})})]})]}),F.jsxs("section",{className:"translation-prompt-settings",children:[F.jsxs("header",{children:[F.jsxs("div",{children:[F.jsx("h3",{children:"Translation Prompts"}),F.jsx("p",{children:"Edit the three cc-pm style prompt slots directly."})]}),F.jsx("button",{type:"button",disabled:s,onClick:()=>u({...a,prompts:void 0}),children:"Reset prompts"})]}),F.jsx("div",{className:"translation-prompt-stack",children:l.map(c=>F.jsxs("label",{children:[F.jsx("span",{children:c.label}),F.jsx("textarea",{value:fx(a,c),onChange:C=>u({...a,prompts:hx(a.prompts,c.key,C.target.value,c.defaultPrompt)})})]},c.key))})]}),o?F.jsx("div",{className:o.ok?"translation-test-result is-ok":"translation-test-result is-error",children:o.ok?`Connection ok: ${o.model} in ${o.elapsedMs}ms`:o.error}):null,F.jsxs("footer",{children:[F.jsx("button",{type:"button",disabled:s,onClick:b,children:"Test Connection"}),F.jsx("button",{type:"button",disabled:s,onClick:()=>void S({...a,enabled:!0,translateOutput:!0,translateUserInput:!0,inputMode:"review-before-send"},h.trim()),children:"Save"})]})]})})}function hx(i,s,l,o){const S={...i??{}};return l.trim()&&l!==o?S[s]=l:delete S[s],Object.keys(S).length>0?S:void 0}function fx(i,s){var l;return((l=i.prompts)==null?void 0:l[s.key])??s.defaultPrompt}function dx({active:i=!0,taskSlug:s,role:l,sessionId:o}){const[S,b]=ge.useState(null),[_,a]=ge.useState([]),[u,h]=ge.useState(""),[g,c]=ge.useState(!1),[C,w]=ge.useState(!1),[T,x]=ge.useState(!1),[v,p]=ge.useState("ready"),[d,m]=ge.useState(""),[E,R]=ge.useState(Date.now()),[A,L]=ge.useState(!1),[k,O]=ge.useState(""),[j,P]=ge.useState(!1),[V,q]=ge.useState([]),[Y,$]=ge.useState(),[G,J]=ge.useState(0),ne=ge.useRef(i),z=ge.useRef(1),M=ge.useRef(null);ge.useEffect(()=>{ne.current=i},[i]),ge.useEffect(()=>{Promise.all([je.getTranslationSettings(),je.getTranslationPrompts()]).then(([Q,de])=>{b(Q),q(de)}).catch(Q=>O(Q.message))},[]),ge.useEffect(()=>{a([]),O(""),p("ready"),m(""),z.current=1;let Q=!1,de;const pe=()=>{Q||(de=window.setTimeout(ke,ne.current?200:1e3))},ke=async()=>{if(!Q)try{const xe=await je.pollTranslationSession(o,z.current);if(Q)return;H(xe.events),z.current=xe.nextCursor,p(xe.status),ne.current&&m(bx(new Date().toISOString()))}catch(xe){Q||O(xe instanceof Error?xe.message:"Translation poll failed.")}finally{pe()}};return je.startTranslationSession(s,l).then(xe=>{Q||(p(xe.status),z.current=xe.nextCursor,ke())}).catch(xe=>{Q||O(xe instanceof Error?xe.message:"Translation start failed.")}),()=>{Q=!0,de!==void 0&&window.clearTimeout(de)}},[o,s,l,G]),ge.useEffect(()=>{var Q;i&&((Q=M.current)==null||Q.scrollIntoView({block:"nearest"}))},[i,_.length]);const B=_x(_);ge.useEffect(()=>{if(!B)return;R(Date.now());const Q=window.setInterval(()=>R(Date.now()),250);return()=>window.clearInterval(Q)},[B]);async function I(Q=!1){if(S){L(!0),O(""),c(!1);try{const de=await je.translateUserInput(s,l,{text:u,mode:Q?"auto-send":"review-before-send",useContext:S.contextEnabled,send:Q});x(de.contextUsed),de.sent?(h(""),c(!1)):(h(de.englishPreview),c(!0))}catch(de){O(de instanceof Error?de.message:"Translation failed.")}finally{L(!1)}}}function H(Q){if(Q.length===0)return;for(const pe of Q)pe.type==="status"?p(pe.status):pe.type==="error"&&O(pe.message);const de=Q.filter(pe=>pe.type==="entry");de.length>0&&a(pe=>de.reduce((ke,xe)=>Sx(ke,xe.entry),pe))}async function ie(){if(u.trim()){L(!0),O("");try{await je.sendTranslatedInput(s,l,{englishText:u}),h(""),c(!1),x(!1)}catch(Q){O(Q instanceof Error?Q.message:"Failed to send English input.")}finally{L(!1)}}}function he(Q){Q.key!=="Enter"||Q.shiftKey||Q.nativeEvent.isComposing||(Q.preventDefault(),!A&&u.trim()&&(g?ie():I(C)))}async function fe(Q,de){L(!0),O("");try{const pe=await je.updateTranslationSettings({...Q,...de!==void 0?{apiKey:de}:{}}),ke=await je.getTranslationPrompts();b(pe),q(ke),P(!1),J(xe=>xe+1)}catch(pe){O(pe instanceof Error?pe.message:"Failed to save translation settings.")}finally{L(!1)}}async function X(){L(!0),O("");try{$(await je.testTranslationProvider())}catch(Q){O(Q instanceof Error?Q.message:"Provider test failed.")}finally{L(!1)}}async function N(){a([]),z.current=1,await je.clearTranslationSession(o).catch(Q=>O(Q.message))}if(!S)return F.jsx("aside",{className:"translation-panel",children:F.jsx("p",{className:"muted",children:"Loading translation settings..."})});const re=mx(_,v,E);return F.jsxs("aside",{className:"translation-panel",children:[F.jsxs("header",{className:"translation-panel-header",children:[F.jsxs("div",{className:"translation-panel-titlebar",children:[F.jsx("h2",{children:"Translation"}),F.jsxs("div",{className:"translation-panel-actions",children:[F.jsx("button",{"aria-pressed":C,className:`auto-send-toggle${C?" is-active":""}`,type:"button",onClick:()=>w(Q=>!Q),children:C?"✅ Auto-send":"× Auto-send"}),F.jsx("button",{type:"button",onClick:()=>P(!0),children:"Settings"}),F.jsx("button",{type:"button",onClick:()=>void N(),children:"Clear"})]})]}),F.jsxs("div",{className:"translation-status-row",children:[F.jsxs("p",{children:[S.model," · ",re,T?" · context used":""]}),F.jsx("p",{children:d?`poll ${d}`:"poll -"})]})]}),k?F.jsx("div",{className:"error-banner",children:k}):null,F.jsxs("div",{className:"translation-entry-list",children:[_.length===0?F.jsx("p",{className:"muted",children:"Translated Claude Code output will appear here."}):null,_.map(Q=>F.jsx(px,{entry:Q},Q.id)),F.jsx("div",{ref:M})]}),F.jsx("div",{className:"translation-composer",children:F.jsxs("div",{className:"translation-composer-row",children:[F.jsx("textarea",{value:u,onChange:Q=>{h(Q.target.value),Q.target.value.trim()||c(!1)},onKeyDown:he,placeholder:"输入中文,先翻译成英文工程指令..."}),F.jsx("div",{className:"translation-composer-actions",children:F.jsx("button",{type:"button",disabled:A||!g||!u.trim(),onClick:()=>void ie(),children:"Send English"})})]})}),j?F.jsx(cx,{settings:S,busy:A,promptPreviews:V,testResult:Y,onSave:fe,onTest:X,onClose:()=>P(!1)}):null]})}function px({entry:i}){const s=vx(i),l=i.sourceKind==="tool-output",o=i.direction==="user-input-to-english",S=["translation-entry",`is-${i.sourceKind}`,o?"is-user-input":""].filter(Boolean).join(" ");return F.jsxs("article",{className:S,children:[l?F.jsx("pre",{children:s}):F.jsx("div",{className:"translation-markdown",children:F.jsx($b,{remarkPlugins:[ux],children:s})}),i.warning?F.jsx("p",{className:"translation-entry-note",children:i.warning}):null,i.error?F.jsx("p",{className:"translation-entry-note is-error",children:i.error}):null]})}function _x(i){const s=i.find(Um);return(s==null?void 0:s.translationStartedAt)??(s==null?void 0:s.createdAt)}function mx(i,s,l){const o=i.find(Um);if(o)return`translating ${yx(Math.max(0,l-gx(o)))}`;const S=i.at(-1);return(S==null?void 0:S.status)==="failed"||s==="failed"?"error":s}function Um(i){return i.status==="queued"||i.status==="translating"}function gx(i){const s=Date.parse(i.translationStartedAt??i.createdAt);return Number.isFinite(s)?s:Date.now()}function vx(i){return i.status==="queued"||i.status==="translating"?i.sourceText:i.status==="translated"?i.translatedText:i.translatedText||i.sourceText}function Sx(i,s){return i.findIndex(o=>o.id===s.id)===-1?[...i,s]:i.map(o=>o.id===s.id?s:o)}function yx(i){if(i<1e3)return`${Math.max(.1,i/1e3).toFixed(1)}s`;const s=i/1e3;if(s<60)return`${s.toFixed(1)}s`;const l=Math.floor(s/60),o=Math.floor(s%60).toString().padStart(2,"0");return`${l}:${o}`}function bx(i){const s=new Date(i);return Number.isNaN(s.getTime())?i:s.toLocaleTimeString()}function Cx({role:i,session:s,permissionMode:l,active:o=!0,busy:S,onPermissionModeChange:b,onStart:_,onResume:a,onStop:u,onRestart:h,onTerminalEvent:g}){const[c,C]=ge.useState(!1);return F.jsxs("section",{className:"session-console",children:[F.jsxs("div",{className:"session-console-top",children:[F.jsx(NS,{role:i,session:s,permissionMode:l,busy:S,onPermissionModeChange:b,onStart:_,onResume:a,onStop:u,onRestart:h}),F.jsx("button",{"aria-pressed":c,className:`translation-toggle${c?" is-active":""}`,type:"button",onClick:()=>C(w=>!w),children:c?"✅ Translate":"× Translate"})]}),(s==null?void 0:s.status)==="running"?F.jsx(wx,{active:o,onTerminalEvent:g,role:i,session:s,taskSlug:s.taskSlug,translationEnabled:c}):F.jsxs("div",{className:"terminal-empty",children:[F.jsx("strong",{children:i}),F.jsx("span",{children:s!=null&&s.claudeSessionId?"Resume this role to reconnect its Claude Code conversation.":"Start this role to open an embedded Claude Code terminal."})]})]})}function wx({active:i,onTerminalEvent:s,role:l,session:o,taskSlug:S,translationEnabled:b}){return F.jsxs("div",{className:b?"session-console-body has-translation":"session-console-body",children:[F.jsx("div",{className:"terminal-pane",children:F.jsx(zS,{sessionId:o.id,active:i,onEvent:s},o.id)}),b?F.jsx("div",{className:"translation-pane",children:F.jsx(dx,{active:i,taskSlug:S,role:l,sessionId:o.id},o.id)}):null]})}function xx({task:i,activeRole:s,onTaskChanged:l,onActiveRoleChange:o,onWorkflowChanged:S,onMessagesChanged:b,onOrchestrationChanged:_,onEventsChanged:a}){const[u,h]=ge.useState(null),[g,c]=ge.useState({"project-manager":"default",architect:"default",coder:"default",reviewer:"default"}),[C,w]=ge.useState(!1),[T,x]=ge.useState(""),[v,p]=ge.useState([]),d=ge.useCallback(async()=>{const[L,k,O]=await Promise.all([je.getTaskStatus(i.taskSlug),je.listMessages(i.taskSlug),je.getOrchestrationState(i.taskSlug)]);h(L),S==null||S(L.workflow),b==null||b(k),_==null||_(O)},[b,_,S,i.taskSlug]);ge.useEffect(()=>{d().catch(L=>x(L.message))},[d]),ge.useEffect(()=>{p([]),a==null||a([])},[a,i.taskSlug]),ge.useEffect(()=>{c(L=>{let k=!1;const O={...L};for(const j of(u==null?void 0:u.sessions)??[])O[j.role]!==j.permissionMode&&(O[j.role]=j.permissionMode,k=!0);return k?O:L})},[u==null?void 0:u.sessions]),ge.useEffect(()=>{const L=window.setInterval(()=>{Promise.all([je.getTaskStatus(i.taskSlug),je.listMessages(i.taskSlug),je.getOrchestrationState(i.taskSlug)]).then(([k,O,j])=>{h(k),S==null||S(k.workflow),b==null||b(O),_==null||_(j)}).catch(k=>x(k.message))},3e3);return()=>window.clearInterval(L)},[b,_,S,i.taskSlug]);async function m(L){w(!0),x("");try{await L(),await d(),await l()}catch(k){x(k instanceof Error?k.message:"Action failed.")}finally{w(!1)}}async function E(){const L=i.worktreePath?[`Close task "${i.taskSlug}"?`,"","This is destructive:","- stops VCM-managed running role sessions for this task",`- deletes the task worktree: ${i.worktreePath}`,`- deletes the Git branch: ${i.branch}`,"- deletes VCM task/session/message/orchestration state","","VCM will not check running sessions or uncommitted changes before closing."].join(`
|
|
87
|
+
`):[`Close task "${i.taskSlug}"?`,"","This task was created without a separate worktree/branch.","VCM will stop VCM-managed running role sessions for this task.","VCM will delete task/session/message/orchestration state only.","","VCM will not check running sessions or uncommitted changes before closing."].join(`
|
|
88
88
|
`);if(window.confirm(L)){w(!0),x("");try{await je.cleanupTask(i.taskSlug,{force:!0,deleteBranch:!!i.worktreePath,forceDeleteBranch:!0}),R(`closed ${i.taskSlug}`),await l()}catch(O){x(O instanceof Error?O.message:"Close task failed.")}finally{w(!1)}}}function R(L){p(k=>{const O=[...k,`${new Date().toLocaleTimeString()} ${L}`];return a==null||a(O),O})}function A(L,k){c(O=>({...O,[L]:k}))}return F.jsxs("div",{className:"task-workspace",children:[F.jsxs("header",{className:"workspace-header",children:[F.jsxs("div",{className:"workspace-title-line",children:[F.jsx("span",{className:"eyebrow",children:"Task Workspace"}),F.jsx("h1",{children:i.title||i.taskSlug}),F.jsx("span",{className:"workspace-branch",children:i.branch}),i.worktreePath?F.jsx("span",{className:"workspace-worktree",children:i.worktreePath}):null]}),F.jsx(AS,{activeRole:s,sessions:(u==null?void 0:u.sessions)??[],onSelect:o}),F.jsx("button",{type:"button",onClick:()=>void d(),children:"Refresh"}),F.jsx("button",{className:"danger-button",type:"button",disabled:C,onClick:()=>void E(),children:"Close Task"})]}),T?F.jsx("div",{className:"error-banner",children:T}):null,F.jsx("div",{className:"workspace-grid",children:F.jsx("div",{className:"workspace-main",children:F.jsx("div",{className:"role-console-stack",children:ua.map(L=>{const k=L.name,O=k===s,j=O_((u==null?void 0:u.sessions)??[],k);return F.jsx("div",{className:O?"role-console-panel is-active":"role-console-panel","aria-hidden":!O,children:F.jsx(Cx,{role:k,session:j,permissionMode:g[k],active:O,busy:C,onPermissionModeChange:P=>A(k,P),onStart:()=>void m(async()=>{await je.startRoleSession(i.taskSlug,k,{cols:100,rows:28,permissionMode:g[k]}),R(`started ${k} with ${g[k]}`)}),onResume:()=>void m(async()=>{await je.resumeRoleSession(i.taskSlug,k,{cols:100,rows:28,permissionMode:g[k]}),R(`resumed ${k} with ${g[k]}`)}),onStop:()=>void m(async()=>{await je.stopRoleSession(i.taskSlug,k),R(`stopped ${k}`)}),onRestart:()=>void m(async()=>{await je.restartRoleSession(i.taskSlug,k,{cols:100,rows:28,permissionMode:g[k]}),R(`restarted ${k} with ${g[k]}`)}),onTerminalEvent:P=>R(`${L.label}: ${P}`)})},k)})})})})]})}function Ex(){const[i,s]=ge.useState(null),[l,o]=ge.useState([]),[S,b]=ge.useState(null),[_,a]=ge.useState(null),[u,h]=ge.useState([]),[g,c]=ge.useState(null),[C,w]=ge.useState(null),[T,x]=ge.useState(null),[v,p]=ge.useState(null),[d,m]=ge.useState(null),[E,R]=ge.useState("project-manager"),[A,L]=ge.useState("system"),[k,O]=ge.useState(!1),[j,P]=ge.useState(!1),[V,q]=ge.useState(""),Y=ge.useMemo(()=>pS(u,g),[u,g]),$=ge.useCallback(N=>{Y!=null&&Y.taskSlug&&w({taskSlug:Y.taskSlug,workflow:N})},[Y==null?void 0:Y.taskSlug]),G=ge.useCallback(N=>{Y!=null&&Y.taskSlug&&x({taskSlug:Y.taskSlug,messages:N})},[Y==null?void 0:Y.taskSlug]),J=ge.useCallback(N=>{Y!=null&&Y.taskSlug&&p({taskSlug:Y.taskSlug,orchestration:N})},[Y==null?void 0:Y.taskSlug]),ne=ge.useCallback(N=>{Y!=null&&Y.taskSlug&&m({taskSlug:Y.taskSlug,events:N})},[Y==null?void 0:Y.taskSlug]);async function z(){const N=await je.listTasks();return h(N),c(re=>{var Q;return re&&N.some(de=>de.taskSlug===re)?re:((Q=N[0])==null?void 0:Q.taskSlug)??null}),N}async function M(){const N=await je.getHarnessStatus();return b(N),N}async function B(){const N=await je.getRecentRepositoryPaths();return o(N),N}async function I(N){const[re,Q]=await Promise.all([je.listMessages(N),je.getOrchestrationState(N)]);x({taskSlug:N,messages:re}),p({taskSlug:N,orchestration:Q})}ge.useEffect(()=>{Promise.all([je.getCurrentProject(),je.getRecentRepositoryPaths(),je.getAppPreferences()]).then(async([N,re,Q])=>{s(N),o(re),L(Q.themeMode),N&&await Promise.all([z(),M()])}).catch(N=>q(N.message))},[]),ge.useEffect(()=>{const N=window.matchMedia("(prefers-color-scheme: dark)"),re=()=>O(N.matches);return re(),N.addEventListener("change",re),()=>N.removeEventListener("change",re)},[]),ge.useEffect(()=>{const N=A==="system"?k?"dark":"light":A;document.documentElement.dataset.theme=N,document.documentElement.dataset.themeMode=A},[k,A]);async function H(N){P(!0),q("");try{await N()}catch(re){q(re instanceof Error?re.message:"Action failed.")}finally{P(!1)}}const ie=C&&C.taskSlug===(Y==null?void 0:Y.taskSlug)?C.workflow:null,he=T&&T.taskSlug===(Y==null?void 0:Y.taskSlug)?T.messages:[],fe=v&&v.taskSlug===(Y==null?void 0:Y.taskSlug)?v.orchestration:null,X=d&&d.taskSlug===(Y==null?void 0:Y.taskSlug)?d.events:[];return F.jsxs(dS,{sidebar:F.jsx(wS,{project:i,recentRepositoryPaths:l,tasks:u,activeTaskSlug:(Y==null?void 0:Y.taskSlug)??null,workflow:ie,messages:he,orchestration:fe,events:X,harnessStatus:S,harnessApplyResult:_,busy:j,onConnect:N=>H(async()=>{const re=await je.connectProject({repoPath:N});s(re),a(null),await Promise.all([z(),M(),B()])}),onRefreshHarness:()=>H(async()=>{a(null),await M()}),onApplyHarness:()=>H(async()=>{const N=await je.applyHarness();a(N),await M()}),onCreateTask:N=>H(async()=>{const re=await je.createTask(N);await z(),c(re.taskSlug)}),onSelectTask:c,onOrchestrationModeChange:N=>{Y&&H(async()=>{const re=await je.updateOrchestrationState(Y.taskSlug,{mode:N});p({taskSlug:Y.taskSlug,orchestration:re})})},themeMode:A,onThemeModeChange:N=>{L(N),H(async()=>{const re=await je.updateAppPreferences({themeMode:N});L(re.themeMode)})},onStageMessage:N=>{H(async()=>{const re=await je.stageMessage(N.taskSlug,N.id);R(re.toRole),await I(N.taskSlug)})},onRejectMessage:N=>{H(async()=>{await je.rejectMessage(N.taskSlug,N.id),await I(N.taskSlug)})},onOpenMessageRole:R}),children:[V?F.jsx("div",{className:"error-banner",children:V}):null,i&&Y?F.jsx(xx,{task:Y,activeRole:E,onTaskChanged:async()=>{await z()},onActiveRoleChange:R,onWorkflowChanged:$,onMessagesChanged:G,onOrchestrationChanged:J,onEventsChanged:ne}):F.jsxs("section",{className:"empty-workspace",children:[F.jsx("h1",{children:i?"Create a task to open the workspace":"Connect a repository to begin"}),F.jsx("p",{children:i?"Tasks create local role commands, logs, and handoff artifacts for the selected repository.":"VibeCodingMaster will create a local task workspace, role sessions, logs, and handoff artifacts."})]})]})}const Im=document.getElementById("root");if(!Im)throw new Error("Missing #root element.");fS.createRoot(Im).render(F.jsx(ge.StrictMode,{children:F.jsx(Ex,{})}));
|
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-DaHXq14j.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Bi4X3GSR.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
|
@@ -97,13 +97,12 @@ repo/
|
|
|
97
97
|
|
|
98
98
|
.ai/
|
|
99
99
|
vcm/ # ignored local VCM control state
|
|
100
|
-
|
|
101
|
-
handoffs/
|
|
102
|
-
<task-slug>/
|
|
100
|
+
handoffs/
|
|
103
101
|
architecture-plan.md
|
|
104
102
|
implementation-log.md
|
|
105
103
|
validation-log.md
|
|
106
104
|
review-report.md
|
|
105
|
+
task-specs/
|
|
107
106
|
state/
|
|
108
107
|
progress.md
|
|
109
108
|
decisions.md
|
|
@@ -213,7 +212,7 @@ Role-specific behavior lives in `.claude/agents/`.
|
|
|
213
212
|
- Default core roles are `project-manager`, `architect`, `coder`, and `reviewer`.
|
|
214
213
|
- The `project-manager` role owns user communication, task routing, role commands, handoff verification, final status reporting, and PR preparation after required gates pass.
|
|
215
214
|
- Do not let one coding session own architecture/plan decisions, implementation, final testing responsibility, and review.
|
|
216
|
-
- Role outputs are exchanged through `.ai/handoffs
|
|
215
|
+
- Role outputs are exchanged through `.ai/vcm/handoffs/`, not through chat history.
|
|
217
216
|
- When the required role route includes `architect`, coding must not start until the architecture and plan artifact exists.
|
|
218
217
|
- If the current session was not started with the required role, stop and ask the user to restart with `claude --agent <role>`; do not pretend to be that role inside the wrong session.
|
|
219
218
|
- Critical global rules may be repeated in role agent files for defense in depth, but repeated rules must use stable rule IDs and be checked by `tools/check-agent-rules`. Do not maintain untracked manual copies.
|
|
@@ -628,7 +627,7 @@ Role command examples:
|
|
|
628
627
|
```text
|
|
629
628
|
architect command:
|
|
630
629
|
read the task spec, architecture docs, module map, and relevant module-local CLAUDE.md
|
|
631
|
-
produce .ai/handoffs
|
|
630
|
+
produce .ai/vcm/handoffs/architecture-plan.md
|
|
632
631
|
define file responsibilities, public contracts, test contracts, phases, validation, and Replan triggers
|
|
633
632
|
do not edit production code
|
|
634
633
|
|
|
@@ -726,8 +725,8 @@ architect
|
|
|
726
725
|
owns architecture and plan
|
|
727
726
|
defines module boundaries, file responsibilities, public contracts, dependency direction, risk, and phases
|
|
728
727
|
owns post-review docs sync and architecture drift checks before PM final acceptance
|
|
729
|
-
outputs .ai/handoffs
|
|
730
|
-
outputs .ai/handoffs
|
|
728
|
+
outputs .ai/vcm/handoffs/architecture-plan.md
|
|
729
|
+
outputs .ai/vcm/handoffs/docs-sync-report.md when a post-review docs sync gate is required
|
|
731
730
|
must not implement production code
|
|
732
731
|
|
|
733
732
|
coder
|
|
@@ -743,7 +742,7 @@ reviewer
|
|
|
743
742
|
checks, designs, and adds missing tests when needed
|
|
744
743
|
may directly apply small, local, low-risk review fixes
|
|
745
744
|
owns complex tests, E2E coverage, regression matrix, and release-level validation recommendations
|
|
746
|
-
outputs .ai/handoffs
|
|
745
|
+
outputs .ai/vcm/handoffs/review-report.md
|
|
747
746
|
must escalate larger implementation issues to coder
|
|
748
747
|
must escalate architecture, public contract, design, or documentation drift issues to architect
|
|
749
748
|
```
|
|
@@ -781,7 +780,7 @@ Role sessions communicate through files, not memory from previous chats.
|
|
|
781
780
|
Required handoff directory:
|
|
782
781
|
|
|
783
782
|
```text
|
|
784
|
-
.ai/handoffs
|
|
783
|
+
.ai/vcm/handoffs/
|
|
785
784
|
role-commands/
|
|
786
785
|
architect.md
|
|
787
786
|
coder.md
|
|
@@ -875,7 +874,7 @@ escalate to architect:
|
|
|
875
874
|
the implementation reveals that the architecture plan is invalid
|
|
876
875
|
```
|
|
877
876
|
|
|
878
|
-
For a task with a handoff directory, `.ai/handoffs
|
|
877
|
+
For a task with a handoff directory, `.ai/vcm/handoffs/validation-log.md` is the authoritative validation record for that task. `.ai/state/validation-log.md` is only a rolling index of recent validation results across tasks.
|
|
879
878
|
|
|
880
879
|
For complex or high-risk work, the next role must not start until the required previous artifact exists and is coherent.
|
|
881
880
|
|
|
@@ -1038,7 +1037,7 @@ You are the architecture and planning role for this project.
|
|
|
1038
1037
|
|
|
1039
1038
|
# Outputs
|
|
1040
1039
|
|
|
1041
|
-
- `.ai/handoffs
|
|
1040
|
+
- `.ai/vcm/handoffs/architecture-plan.md`
|
|
1042
1041
|
|
|
1043
1042
|
# Do Not
|
|
1044
1043
|
|
|
@@ -1489,8 +1488,8 @@ Branch rules:
|
|
|
1489
1488
|
Close Task rules:
|
|
1490
1489
|
|
|
1491
1490
|
- after task completion, use VCM `Close Task` only when the user is ready to delete task-local state
|
|
1492
|
-
- for worktree-backed tasks, `Close Task` deletes the task worktree, deletes the task branch by default, and removes VCM task/session/message/orchestration metadata
|
|
1493
|
-
- `Close Task`
|
|
1491
|
+
- for worktree-backed tasks, `Close Task` deletes the task worktree, deletes the task branch by default, and removes VCM task/session/message/orchestration/handoff metadata
|
|
1492
|
+
- `Close Task` stops VCM-managed running role sessions, but it does not check uncommitted changes; finish, commit, or preserve anything important before using it
|
|
1494
1493
|
|
|
1495
1494
|
Small commits:
|
|
1496
1495
|
|
|
@@ -1613,7 +1612,7 @@ State files:
|
|
|
1613
1612
|
|
|
1614
1613
|
Validation log authority:
|
|
1615
1614
|
|
|
1616
|
-
- `.ai/handoffs
|
|
1615
|
+
- `.ai/vcm/handoffs/validation-log.md` is authoritative for one task.
|
|
1617
1616
|
- `.ai/state/validation-log.md` is a rolling index across tasks and should point to the task-level log when one exists.
|
|
1618
1617
|
- Final reports and review reports should cite the task-level validation log, not scattered chat output.
|
|
1619
1618
|
|
|
@@ -1868,7 +1867,7 @@ behavior is correct
|
|
|
1868
1867
|
- [ ] For T2+ work, architect performed post-review docs sync / architecture drift check before final PM acceptance.
|
|
1869
1868
|
- [ ] Docs updates or a docs-sync-report explain why affected architecture/module/testing/security/dependency docs are current.
|
|
1870
1869
|
- [ ] The project manager prepared final acceptance, commit, and PR only after reviewer and docs-sync gates passed or an exception was approved.
|
|
1871
|
-
- [ ] Task-level validation evidence is recorded in `.ai/handoffs
|
|
1870
|
+
- [ ] Task-level validation evidence is recorded in `.ai/vcm/handoffs/validation-log.md` when a handoff directory exists.
|
|
1872
1871
|
|
|
1873
1872
|
## Architecture
|
|
1874
1873
|
|
package/docs/product-design.md
CHANGED
|
@@ -111,13 +111,14 @@ Task creation flow:
|
|
|
111
111
|
New Task submit
|
|
112
112
|
-> validate task name
|
|
113
113
|
-> verify .ai/vcm/ is ignored
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
-> if Create worktree and branch is selected:
|
|
115
|
+
-> derive branch feature/<task-name>
|
|
116
|
+
-> derive worktree path .ai/vcm/worktrees/<task-name>
|
|
117
|
+
-> verify the base repo is clean
|
|
118
|
+
-> git worktree add -b feature/<task-name> .ai/vcm/worktrees/<task-name> <base-ref>
|
|
119
|
+
-> otherwise:
|
|
120
|
+
-> use the connected repo path and current branch
|
|
121
|
+
-> reject if another inline task is already active
|
|
121
122
|
-> create task metadata
|
|
122
123
|
-> create handoff structure inside the task runtime repo
|
|
123
124
|
-> open the task workspace with role session cwd = task runtime repo
|
|
@@ -128,6 +129,7 @@ Task close flow:
|
|
|
128
129
|
```text
|
|
129
130
|
user clicks red Close Task
|
|
130
131
|
-> show destructive confirmation
|
|
132
|
+
-> stop VCM-managed running role sessions for the task
|
|
131
133
|
-> explain that VCM deletes the task worktree and task branch
|
|
132
134
|
-> explain that VCM does not check running sessions or uncommitted changes
|
|
133
135
|
-> remove git worktree when the task owns one
|
|
@@ -136,7 +138,7 @@ user clicks red Close Task
|
|
|
136
138
|
-> remove task runtime metadata from the task runtime repo
|
|
137
139
|
```
|
|
138
140
|
|
|
139
|
-
Tasks created without a worktree do not own a separate branch/worktree, so Close Task removes only VCM metadata for those tasks.
|
|
141
|
+
Tasks created without a worktree do not own a separate branch/worktree, so Close Task stops VCM-managed running role sessions and removes only VCM metadata for those tasks.
|
|
140
142
|
|
|
141
143
|
## 5. Roles
|
|
142
144
|
|
|
@@ -168,8 +170,8 @@ The architect owns:
|
|
|
168
170
|
|
|
169
171
|
Outputs:
|
|
170
172
|
|
|
171
|
-
- `.ai/handoffs
|
|
172
|
-
- `.ai/handoffs
|
|
173
|
+
- `.ai/vcm/handoffs/architecture-plan.md`
|
|
174
|
+
- `.ai/vcm/handoffs/docs-sync-report.md`
|
|
173
175
|
|
|
174
176
|
### Coder
|
|
175
177
|
|
|
@@ -182,8 +184,8 @@ The coder owns:
|
|
|
182
184
|
|
|
183
185
|
Outputs:
|
|
184
186
|
|
|
185
|
-
- `.ai/handoffs
|
|
186
|
-
- `.ai/handoffs
|
|
187
|
+
- `.ai/vcm/handoffs/implementation-log.md`
|
|
188
|
+
- `.ai/vcm/handoffs/validation-log.md`
|
|
187
189
|
|
|
188
190
|
### Reviewer
|
|
189
191
|
|
|
@@ -197,7 +199,7 @@ The reviewer owns:
|
|
|
197
199
|
|
|
198
200
|
Output:
|
|
199
201
|
|
|
200
|
-
- `.ai/handoffs
|
|
202
|
+
- `.ai/vcm/handoffs/review-report.md`
|
|
201
203
|
|
|
202
204
|
## 6. Information Architecture
|
|
203
205
|
|
|
@@ -392,7 +394,7 @@ Role sessions get VCM behavior from `CLAUDE.md` and `.claude/agents/*.md`, not f
|
|
|
392
394
|
Each task creates:
|
|
393
395
|
|
|
394
396
|
```text
|
|
395
|
-
.ai/handoffs
|
|
397
|
+
.ai/vcm/handoffs/
|
|
396
398
|
role-commands/
|
|
397
399
|
architect.md
|
|
398
400
|
coder.md
|
|
@@ -411,7 +413,7 @@ Each task creates:
|
|
|
411
413
|
<message-id>.md
|
|
412
414
|
```
|
|
413
415
|
|
|
414
|
-
The product treats handoff files as
|
|
416
|
+
The product treats handoff files as task-local coordination facts. The terminal is useful for live interaction, but handoff files and message history are the source of truth during a task. They live under `.ai/vcm/`, are ignored by Git, and are removed by `Close Task`; final decisions that should survive must be copied into normal project docs, source, commit messages, or PR text.
|
|
415
417
|
|
|
416
418
|
The main UI no longer has a dedicated artifact panel. Artifact APIs still exist for status checks, role command compatibility, and future UI work.
|
|
417
419
|
|
|
@@ -438,9 +440,9 @@ Manual mode:
|
|
|
438
440
|
|
|
439
441
|
- message status becomes `pending_approval` when the target role is running
|
|
440
442
|
- user opens `Messages`
|
|
441
|
-
-
|
|
442
|
-
-
|
|
443
|
-
- VCM does not submit Enter
|
|
443
|
+
- message rows show sequence, timestamp, status, body preview, path, and `Copy`
|
|
444
|
+
- user decides whether to copy or manually act on the message
|
|
445
|
+
- VCM does not write to the target terminal or submit Enter
|
|
444
446
|
|
|
445
447
|
Auto mode:
|
|
446
448
|
|
|
@@ -448,7 +450,7 @@ Auto mode:
|
|
|
448
450
|
- PM remains the routing hub
|
|
449
451
|
- non-PM roles reply to PM
|
|
450
452
|
|
|
451
|
-
The backend still has
|
|
453
|
+
The backend still has `stage`, `approve`, `reject`, `paused`, and pause/resume API compatibility paths. The current GUI exposes only message copy plus manual/auto orchestration.
|
|
452
454
|
|
|
453
455
|
## 12. Translation
|
|
454
456
|
|
|
@@ -537,6 +539,8 @@ Keyboard behavior:
|
|
|
537
539
|
|
|
538
540
|
After translation succeeds, the English draft replaces the original Chinese text in the same textarea.
|
|
539
541
|
|
|
542
|
+
The translated user input is also shown in the translation panel as a conversation boundary. User-input entries have a thick divider and larger top spacing so the next Claude output reads as the answer to that prompt.
|
|
543
|
+
|
|
540
544
|
`Send English` pastes the current English text into the active role terminal, then sends Enter as a separate terminal input event.
|
|
541
545
|
|
|
542
546
|
Translation panel `Auto-send` is separate from task `Auto orchestration`:
|
|
@@ -581,10 +585,10 @@ Task worktree local files:
|
|
|
581
585
|
.ai/vcm/worktrees/<task>/.ai/vcm/messages/<task>.jsonl
|
|
582
586
|
.ai/vcm/worktrees/<task>/.ai/vcm/orchestration/<task>.json
|
|
583
587
|
.ai/vcm/worktrees/<task>/.ai/vcm/translation/<task>/
|
|
584
|
-
.ai/vcm/worktrees/<task>/.ai/handoffs
|
|
588
|
+
.ai/vcm/worktrees/<task>/.ai/vcm/handoffs/
|
|
585
589
|
```
|
|
586
590
|
|
|
587
|
-
For tasks created without a worktree, the task runtime repo is the connected base repo, so the runtime state resolves under the base repo's `.ai/vcm/`.
|
|
591
|
+
For tasks created without a worktree, the task runtime repo is the connected base repo, so the runtime state resolves under the base repo's `.ai/vcm/`. Because `.ai/vcm/handoffs/` has no task-name segment, VCM allows only one active inline task in a connected repo.
|
|
588
592
|
|
|
589
593
|
External Claude transcripts:
|
|
590
594
|
|
|
@@ -28,7 +28,7 @@ browser
|
|
|
28
28
|
-> claude --agent <role>
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
The app is local-first. It writes project control state under `.ai/vcm/`, handoff artifacts under `.ai/handoffs/` inside the active task worktree, app settings under `~/.vcm/settings.json`, and reads Claude transcript files under `~/.claude/projects/`.
|
|
31
|
+
The app is local-first. It writes project control state under `.ai/vcm/`, handoff artifacts under `.ai/vcm/handoffs/` inside the active task worktree, app settings under `~/.vcm/settings.json`, and reads Claude transcript files under `~/.claude/projects/`.
|
|
32
32
|
|
|
33
33
|
## 2. Processes And Ports
|
|
34
34
|
|
|
@@ -112,7 +112,7 @@ Responsibilities:
|
|
|
112
112
|
|
|
113
113
|
- Fetch task status, messages, and orchestration state.
|
|
114
114
|
- Poll those every three seconds.
|
|
115
|
-
- Render compact header with task title, branch, immutable worktree path, role tabs, and
|
|
115
|
+
- Render compact header with task title, branch, immutable worktree path, role tabs, Refresh, and red `Close Task`.
|
|
116
116
|
- Hold per-role permission mode selection.
|
|
117
117
|
- Render one `SessionConsole` per role but only show the active role.
|
|
118
118
|
- Emit workflow/messages/orchestration/events back to `App` so sidebar stays synchronized.
|
|
@@ -179,6 +179,7 @@ Entry:
|
|
|
179
179
|
|
|
180
180
|
Fastify registers:
|
|
181
181
|
|
|
182
|
+
- app settings routes
|
|
182
183
|
- project routes
|
|
183
184
|
- harness routes
|
|
184
185
|
- task routes
|
|
@@ -294,11 +295,13 @@ Task runtime state, source changes, and handoff artifacts live in the task runti
|
|
|
294
295
|
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/messages/<task>.jsonl
|
|
295
296
|
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/orchestration/<task>.json
|
|
296
297
|
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/translation/<task>/
|
|
297
|
-
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/handoffs
|
|
298
|
+
<baseRepoRoot>/.ai/vcm/worktrees/<task>/.ai/vcm/handoffs/
|
|
298
299
|
```
|
|
299
300
|
|
|
300
301
|
For inline tasks, `taskRepoRoot` is the connected base repo, so these same runtime paths resolve under the connected repo's `.ai/vcm/`.
|
|
301
302
|
|
|
303
|
+
Because the handoff directory is `<taskRepoRoot>/.ai/vcm/handoffs/` without a task slug segment, VCM rejects creating a second active inline task in the same connected repository. Parallel tasks should use the default worktree mode.
|
|
304
|
+
|
|
302
305
|
This split lets VCM list tasks from the base repo after worktrees are created, while each task's runtime state follows the same root as the role sessions.
|
|
303
306
|
|
|
304
307
|
### 6.2 Git Ignore Requirement
|
|
@@ -326,9 +329,10 @@ POST /api/tasks
|
|
|
326
329
|
-> assert worktreePath does not already exist
|
|
327
330
|
-> assert base repo has no uncommitted changes
|
|
328
331
|
-> git worktree add -b feature/<taskSlug> <worktreePath> <baseRef>
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
-> otherwise:
|
|
333
|
+
-> read current base repo branch
|
|
334
|
+
-> leave worktreePath undefined
|
|
335
|
+
-> reject when another inline task is already active
|
|
332
336
|
-> create handoff structure in taskRepoRoot
|
|
333
337
|
-> write central task metadata under baseRepoRoot/.ai/vcm/tasks/<task>.json
|
|
334
338
|
```
|
|
@@ -340,14 +344,18 @@ The default `baseRef` is the connected repo's current `HEAD`.
|
|
|
340
344
|
```text
|
|
341
345
|
POST /api/tasks/:taskSlug/cleanup
|
|
342
346
|
-> load task metadata
|
|
347
|
+
-> list role sessions for the task
|
|
348
|
+
-> stop each VCM-managed role session whose runtime status is running
|
|
349
|
+
-> stop translation tailers and clear task translation cache
|
|
343
350
|
-> when worktreePath exists, verify it belongs under <baseRepoRoot>/.ai/vcm/worktrees/
|
|
344
351
|
-> when worktreePath exists, git worktree remove --force <worktreePath>
|
|
345
352
|
-> when worktreePath exists, delete the task branch by default
|
|
346
353
|
-> delete base task metadata
|
|
347
354
|
-> delete task runtime session/message/orchestration/translation metadata
|
|
355
|
+
-> delete task runtime handoff directory
|
|
348
356
|
```
|
|
349
357
|
|
|
350
|
-
Close Task is intentionally destructive after user confirmation. It does not preflight running
|
|
358
|
+
Close Task is intentionally destructive after user confirmation. It actively stops VCM-managed running role sessions, but it does not preflight running sessions or uncommitted worktree changes. Tasks created without a worktree remove VCM metadata only because there is no VCM-owned branch/worktree to delete.
|
|
351
359
|
|
|
352
360
|
## 7. Task And Artifact Model
|
|
353
361
|
|
|
@@ -369,9 +377,8 @@ Each task stores:
|
|
|
369
377
|
- `taskSlug`
|
|
370
378
|
- optional `title`
|
|
371
379
|
- timestamps
|
|
372
|
-
- `
|
|
373
|
-
- `worktreePath
|
|
374
|
-
- `repoRoot` / `taskRepoRoot`
|
|
380
|
+
- `repoRoot`, which is the connected base repository
|
|
381
|
+
- optional `worktreePath`, which is the task runtime repo when present
|
|
375
382
|
- branch, always `feature/<taskSlug>` for VCM-created tasks
|
|
376
383
|
- handoff directory
|
|
377
384
|
- status
|
|
@@ -388,10 +395,12 @@ POST /api/tasks
|
|
|
388
395
|
-> write base .ai/vcm/tasks/<task>.json
|
|
389
396
|
```
|
|
390
397
|
|
|
398
|
+
Task cleanup is orchestrated by `src/backend/api/task-routes.ts` because it coordinates session stopping, translation tailer stopping, and `TaskService.cleanupTask`.
|
|
399
|
+
|
|
391
400
|
Handoff directory:
|
|
392
401
|
|
|
393
402
|
```text
|
|
394
|
-
<taskRepoRoot>/.ai/handoffs
|
|
403
|
+
<taskRepoRoot>/.ai/vcm/handoffs/
|
|
395
404
|
role-commands/
|
|
396
405
|
architect.md
|
|
397
406
|
coder.md
|
|
@@ -523,7 +532,7 @@ The runtime:
|
|
|
523
532
|
- spawns `node-pty`
|
|
524
533
|
- sets `TERM=xterm-256color`
|
|
525
534
|
- sets color-friendly env vars
|
|
526
|
-
- appends raw PTY output to `<taskRepoRoot>/.ai/handoffs
|
|
535
|
+
- appends raw PTY output to `<taskRepoRoot>/.ai/vcm/handoffs/logs/<role>.log`
|
|
527
536
|
- emits terminal output/input/exit events to WebSocket subscribers
|
|
528
537
|
- replays the log on terminal WebSocket subscribe
|
|
529
538
|
|
|
@@ -557,7 +566,7 @@ State:
|
|
|
557
566
|
```text
|
|
558
567
|
<taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
559
568
|
<taskRepoRoot>/.ai/vcm/orchestration/<task>.json
|
|
560
|
-
<taskRepoRoot>/.ai/handoffs
|
|
569
|
+
<taskRepoRoot>/.ai/vcm/handoffs/messages/<message-id>.md
|
|
561
570
|
```
|
|
562
571
|
|
|
563
572
|
Policy:
|
|
@@ -569,16 +578,10 @@ Policy:
|
|
|
569
578
|
Manual mode:
|
|
570
579
|
|
|
571
580
|
```text
|
|
572
|
-
send -> pending_approval ->
|
|
581
|
+
send -> pending_approval or queued -> Messages modal -> Copy/manual action
|
|
573
582
|
```
|
|
574
583
|
|
|
575
|
-
`Stage` writes
|
|
576
|
-
|
|
577
|
-
```text
|
|
578
|
-
Read and handle VCM message <id> at <bodyPath>
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
It does not append Enter.
|
|
584
|
+
The current GUI shows sequence, timestamp, status, body preview, path, and a `Copy` button. It does not expose Open Role, Stage, or Reject buttons. The backend still exposes stage/approve/reject routes; `Stage` writes `Read and handle VCM message <id> at <bodyPath>` without appending Enter.
|
|
582
585
|
|
|
583
586
|
Auto mode:
|
|
584
587
|
|
|
@@ -590,7 +593,6 @@ The backend pastes a `[VCM MESSAGE]` envelope into the target terminal, then sen
|
|
|
590
593
|
|
|
591
594
|
The backend still exposes pause/resume orchestration API routes and stores `paused` for compatibility. The current GUI only toggles `mode` between `manual` and `auto`.
|
|
592
595
|
|
|
593
|
-
Messages and orchestration snapshots are task runtime state under `taskRepoRoot/.ai/vcm`. Message body markdown also lives in the task worktree handoff directory.
|
|
594
596
|
Messages and orchestration snapshots are task runtime state under `taskRepoRoot/.ai/vcm`. Message body markdown also lives in the task worktree handoff directory.
|
|
595
597
|
|
|
596
598
|
## 12. Role Command Compatibility
|
|
@@ -930,7 +932,7 @@ Current boundaries:
|
|
|
930
932
|
- Translation API key is local in `~/.vcm/settings.json`.
|
|
931
933
|
- Translation output is UI/runtime state only unless a user or role copies it into a file.
|
|
932
934
|
- `.ai/vcm` is local project control state and must be ignored by Git.
|
|
933
|
-
- Task handoff artifacts live
|
|
935
|
+
- Task handoff artifacts live under `.ai/vcm/handoffs/` as task-local runtime state and are removed by Close Task. Durable conclusions belong in normal project docs, code comments, commit messages, or PR text.
|
|
934
936
|
- Task worktrees are created only during task creation; VCM does not expose branch/worktree switching APIs.
|
|
935
937
|
- Sandbox isolation should come from a devContainer, Docker container, VM, or other user-controlled environment.
|
|
936
938
|
|
|
@@ -17,7 +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
|
-
- Task creation creates one `feature/<task>` branch and one `.ai/vcm/worktrees/<task>` git worktree by default; users may clear `Create worktree and branch` to create an inline task in the connected repository/current branch.
|
|
20
|
+
- Task creation creates one `feature/<task>` branch and one `.ai/vcm/worktrees/<task>` git worktree by default; users may clear `Create worktree and branch` to create an inline task in the connected repository/current branch. Because handoffs are scoped as `.ai/vcm/handoffs/` under the task runtime repo, only one active inline task is allowed per connected repository.
|
|
21
21
|
|
|
22
22
|
## 2. Package And Build
|
|
23
23
|
|
|
@@ -28,7 +28,7 @@ File:
|
|
|
28
28
|
Current package facts:
|
|
29
29
|
|
|
30
30
|
- package name: `vibe-coding-master`
|
|
31
|
-
- current version: `0.0.
|
|
31
|
+
- current version: `0.0.10`
|
|
32
32
|
- type: ESM
|
|
33
33
|
- `bin.vcm`: `dist/main.js`
|
|
34
34
|
- `bin.vcmctl`: `dist/cli/vcmctl.js`
|
|
@@ -179,6 +179,20 @@ Important fields:
|
|
|
179
179
|
- `claudeCommand`
|
|
180
180
|
- `isDirty`
|
|
181
181
|
|
|
182
|
+
### `src/shared/types/app-settings.ts`
|
|
183
|
+
|
|
184
|
+
Defines:
|
|
185
|
+
|
|
186
|
+
- `ThemeMode`
|
|
187
|
+
- `AppPreferences`
|
|
188
|
+
- `UpdateAppPreferencesRequest`
|
|
189
|
+
|
|
190
|
+
Theme modes:
|
|
191
|
+
|
|
192
|
+
- `system`
|
|
193
|
+
- `light`
|
|
194
|
+
- `dark`
|
|
195
|
+
|
|
182
196
|
### `src/shared/types/task.ts`
|
|
183
197
|
|
|
184
198
|
Defines:
|
|
@@ -196,7 +210,7 @@ Worktree fields:
|
|
|
196
210
|
- `cleanupStatus?: "active" | "cleaned"`
|
|
197
211
|
- `cleanedAt?: string`
|
|
198
212
|
|
|
199
|
-
`CreateTaskRequest` supports `createWorktree?: boolean`. It creates a worktree and branch by default, and skips both when `createWorktree === false`.
|
|
213
|
+
`CreateTaskRequest` supports `createWorktree?: boolean`. It creates a worktree and branch by default, and skips both when `createWorktree === false`. Inline creation rejects a second active inline task in the same connected repository.
|
|
200
214
|
|
|
201
215
|
### `src/shared/types/session.ts`
|
|
202
216
|
|
|
@@ -399,8 +413,8 @@ Worktree methods:
|
|
|
399
413
|
Required safety:
|
|
400
414
|
|
|
401
415
|
- all Git commands keep command-scoped `safe.directory`
|
|
402
|
-
-
|
|
403
|
-
-
|
|
416
|
+
- `TaskService` verifies Close Task worktree paths are under `<baseRepoRoot>/.ai/vcm/worktrees/`
|
|
417
|
+
- VCM-created task branches are derived from validated task slugs as `feature/<taskSlug>`
|
|
404
418
|
|
|
405
419
|
### `src/backend/adapters/claude-adapter.ts`
|
|
406
420
|
|
|
@@ -532,10 +546,11 @@ createTask(baseRepoRoot, { taskSlug })
|
|
|
532
546
|
-> assert worktree path does not exist
|
|
533
547
|
-> git.createWorktree({ baseRepoRoot, branch, worktreePath, baseRef: HEAD })
|
|
534
548
|
-> taskRepoRoot = worktreePath
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
549
|
+
-> otherwise:
|
|
550
|
+
-> branch = current base repo branch
|
|
551
|
+
-> worktreePath = undefined
|
|
552
|
+
-> taskRepoRoot = baseRepoRoot
|
|
553
|
+
-> reject if another inline task is already active
|
|
539
554
|
-> artifactService.ensureHandoffStructure({ repoRoot: taskRepoRoot, handoffDir })
|
|
540
555
|
-> artifactService.createArtifactTemplates({ repoRoot: taskRepoRoot, handoffDir })
|
|
541
556
|
-> ensure task runtime state dirs under <taskRepoRoot>/.ai/vcm/
|
|
@@ -547,17 +562,21 @@ Close Task flow:
|
|
|
547
562
|
```text
|
|
548
563
|
cleanupTask(baseRepoRoot, taskSlug, options)
|
|
549
564
|
-> load central task record
|
|
565
|
+
-> route layer lists role sessions
|
|
566
|
+
-> route layer stops each VCM-managed role session with status running
|
|
567
|
+
-> route layer stops translation tailers and clears task translation cache
|
|
550
568
|
-> if worktreePath exists, verify it is under <baseRepoRoot>/.ai/vcm/worktrees/
|
|
551
569
|
-> if worktreePath exists, git.removeWorktree(baseRepoRoot, worktreePath, force=true)
|
|
552
570
|
-> if worktreePath exists, git.deleteBranch(baseRepoRoot, task.branch, force=true) by default
|
|
553
|
-
|
|
571
|
+
-> delete <baseRepoRoot>/.ai/vcm/tasks/<task>.json
|
|
572
|
+
-> delete <taskRepoRoot>/.ai/vcm/handoffs/
|
|
554
573
|
-> delete <taskRepoRoot>/.ai/vcm/sessions/<task>.json
|
|
555
574
|
-> delete <taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
556
575
|
-> delete <taskRepoRoot>/.ai/vcm/orchestration/<task>.json
|
|
557
576
|
-> delete <taskRepoRoot>/.ai/vcm/translation/<task>/
|
|
558
577
|
```
|
|
559
578
|
|
|
560
|
-
The UI labels this operation `Close Task`, styles it as a red destructive action, and shows a browser confirmation that names the worktree, branch, and metadata that will be deleted. VCM does not
|
|
579
|
+
The UI labels this operation `Close Task`, styles it as a red destructive action, and shows a browser confirmation that names running role-session shutdown, the worktree, branch, and metadata that will be deleted. VCM actively stops VCM-managed running role sessions, but it does not preflight running sessions or uncommitted changes before closing. Tasks created without a worktree remove VCM metadata only.
|
|
561
580
|
|
|
562
581
|
### `src/backend/services/artifact-service.ts`
|
|
563
582
|
|
|
@@ -582,13 +601,13 @@ In task-worktree mode, artifact paths are still repo-relative, but `repoRoot` mu
|
|
|
582
601
|
Primary role command path:
|
|
583
602
|
|
|
584
603
|
```text
|
|
585
|
-
.ai/handoffs
|
|
604
|
+
.ai/vcm/handoffs/role-commands/<role>.md
|
|
586
605
|
```
|
|
587
606
|
|
|
588
607
|
Legacy fallback:
|
|
589
608
|
|
|
590
609
|
```text
|
|
591
|
-
.ai/handoffs
|
|
610
|
+
.ai/vcm/handoffs/role-commands/<role>-command.md
|
|
592
611
|
```
|
|
593
612
|
|
|
594
613
|
### `src/backend/services/status-service.ts`
|
|
@@ -665,7 +684,7 @@ In task-worktree mode:
|
|
|
665
684
|
|
|
666
685
|
- message snapshots live under `task.worktreePath/.ai/vcm/messages`
|
|
667
686
|
- orchestration state lives under `task.worktreePath/.ai/vcm/orchestration`
|
|
668
|
-
- message body files live under `task.worktreePath/.ai/handoffs
|
|
687
|
+
- message body files live under `task.worktreePath/.ai/vcm/handoffs/messages`
|
|
669
688
|
- terminal delivery uses the runtime session for the role, whose cwd is the task worktree
|
|
670
689
|
|
|
671
690
|
### `src/backend/services/command-dispatcher.ts`
|
|
@@ -775,7 +794,6 @@ Exports:
|
|
|
775
794
|
- `TranslationEventListener`
|
|
776
795
|
- `TranslationServiceDeps`
|
|
777
796
|
- `createTranslationService(deps)`
|
|
778
|
-
- `formatTerminalSubmit(text)`
|
|
779
797
|
|
|
780
798
|
Responsibilities:
|
|
781
799
|
|
|
@@ -792,6 +810,8 @@ Responsibilities:
|
|
|
792
810
|
- subscribe to Claude transcript service
|
|
793
811
|
- translate prose output and preserve tool output
|
|
794
812
|
|
|
813
|
+
Terminal submission is delegated to `src/backend/runtime/terminal-submit.ts`, which bracket-pastes text, waits briefly, then sends Enter separately.
|
|
814
|
+
|
|
795
815
|
## 9. Backend API
|
|
796
816
|
|
|
797
817
|
### `src/backend/server.ts`
|
|
@@ -810,9 +830,10 @@ Registers HTTP routes and the terminal WebSocket.
|
|
|
810
830
|
|
|
811
831
|
### Route files
|
|
812
832
|
|
|
833
|
+
- `src/backend/api/app-settings-routes.ts`: UI preferences
|
|
813
834
|
- `src/backend/api/project-routes.ts`: health, recent paths, connect/current project
|
|
814
835
|
- `src/backend/api/harness-routes.ts`: harness status/apply
|
|
815
|
-
- `src/backend/api/task-routes.ts`: tasks, task status, and Close Task cleanup endpoint
|
|
836
|
+
- `src/backend/api/task-routes.ts`: tasks, task status, and Close Task cleanup endpoint; Close Task stops running role sessions before translation/task cleanup
|
|
816
837
|
- `src/backend/api/session-routes.ts`: session lifecycle and dispatch compatibility endpoint
|
|
817
838
|
- `src/backend/api/artifact-routes.ts`: artifact, role command, and log reads/writes
|
|
818
839
|
- `src/backend/api/message-routes.ts`: messages and orchestration
|
|
@@ -891,12 +912,12 @@ It calls:
|
|
|
891
912
|
- orchestration endpoints
|
|
892
913
|
- translation endpoints
|
|
893
914
|
|
|
894
|
-
|
|
915
|
+
Implemented task cleanup method:
|
|
895
916
|
|
|
896
|
-
- `listGitWorktrees()`
|
|
897
|
-
- `listGitBranches()`
|
|
898
917
|
- `cleanupTask(taskSlug, options)`
|
|
899
918
|
|
|
919
|
+
There are no branch/worktree switching APIs in the current frontend client.
|
|
920
|
+
|
|
900
921
|
### `src/frontend/state/app-store.ts`
|
|
901
922
|
|
|
902
923
|
Exports:
|
|
@@ -946,7 +967,6 @@ Responsibilities:
|
|
|
946
967
|
- harness panel
|
|
947
968
|
- task creation with one task-name field, `Create worktree and branch` checkbox selected by default, branch preview, and worktree path preview
|
|
948
969
|
- task navigation
|
|
949
|
-
- red `Close Task` action with destructive confirmation
|
|
950
970
|
|
|
951
971
|
### `src/frontend/routes/task-workspace.tsx`
|
|
952
972
|
|
|
@@ -958,6 +978,7 @@ Exports:
|
|
|
958
978
|
Responsibilities:
|
|
959
979
|
|
|
960
980
|
- task header with role tabs and refresh
|
|
981
|
+
- red `Close Task` action with destructive confirmation
|
|
961
982
|
- show branch and immutable worktree path for the active task
|
|
962
983
|
- status/message/orchestration refresh
|
|
963
984
|
- periodic polling
|
|
@@ -1016,7 +1037,7 @@ Exports:
|
|
|
1016
1037
|
- `getMessageCounts(messages)`
|
|
1017
1038
|
- `MessageTimeline(props)`
|
|
1018
1039
|
|
|
1019
|
-
Used inside the Messages modal.
|
|
1040
|
+
Used inside the Messages modal. Current UI rows show sequence, timestamp, route, type, status, body preview, body path, and a `Copy` button. Stage/approve/reject backend APIs remain compatibility paths, but those buttons are not displayed in the current modal.
|
|
1020
1041
|
|
|
1021
1042
|
### `src/frontend/components/event-log.tsx`
|
|
1022
1043
|
|
|
@@ -1082,6 +1103,7 @@ Important current behavior:
|
|
|
1082
1103
|
- tool output is preserved, dim, one-line
|
|
1083
1104
|
- prose source is replaced by translated text after completion
|
|
1084
1105
|
- prose renders Markdown with GFM support
|
|
1106
|
+
- user-input translation entries add a thick divider and larger top spacing to mark question/answer boundaries
|
|
1085
1107
|
- no separate translated-English textarea
|
|
1086
1108
|
|
|
1087
1109
|
### `src/frontend/components/translation-settings-modal.tsx`
|
|
@@ -1176,7 +1198,7 @@ Messages:
|
|
|
1176
1198
|
|
|
1177
1199
|
```text
|
|
1178
1200
|
<taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
1179
|
-
<taskRepoRoot>/.ai/handoffs
|
|
1201
|
+
<taskRepoRoot>/.ai/vcm/handoffs/messages/<message-id>.md
|
|
1180
1202
|
```
|
|
1181
1203
|
|
|
1182
1204
|
Orchestration:
|
|
@@ -1200,7 +1222,7 @@ Task worktrees:
|
|
|
1200
1222
|
Handoff artifacts:
|
|
1201
1223
|
|
|
1202
1224
|
```text
|
|
1203
|
-
.ai/handoffs
|
|
1225
|
+
.ai/vcm/handoffs/
|
|
1204
1226
|
```
|
|
1205
1227
|
|
|
1206
1228
|
Claude transcripts:
|
|
@@ -1237,7 +1259,7 @@ For frontend layout changes, also verify manually:
|
|
|
1237
1259
|
- Auto orchestration toggles on/off
|
|
1238
1260
|
- `Enter` in translation composer translates/sends
|
|
1239
1261
|
- `Shift+Enter` inserts newline
|
|
1240
|
-
- close a worktree-backed task and verify it removes the worktree, deletes the task branch, and removes central task metadata
|
|
1262
|
+
- close a worktree-backed task and verify it stops running role sessions, removes the worktree, deletes the task branch, and removes central task metadata
|
|
1241
1263
|
|
|
1242
1264
|
## 17. V1 Boundaries To Preserve
|
|
1243
1265
|
|