vibe-coding-master 0.0.1
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/LICENSE +201 -0
- package/README.md +226 -0
- package/dist/backend/adapters/claude-adapter.js +38 -0
- package/dist/backend/adapters/command-runner.js +33 -0
- package/dist/backend/adapters/filesystem.js +60 -0
- package/dist/backend/adapters/git-adapter.js +33 -0
- package/dist/backend/api/artifact-routes.js +109 -0
- package/dist/backend/api/message-routes.js +90 -0
- package/dist/backend/api/project-routes.js +17 -0
- package/dist/backend/api/session-routes.js +64 -0
- package/dist/backend/api/task-routes.js +30 -0
- package/dist/backend/errors.js +29 -0
- package/dist/backend/runtime/node-pty-runtime.js +162 -0
- package/dist/backend/runtime/session-registry.js +36 -0
- package/dist/backend/runtime/terminal-runtime.js +1 -0
- package/dist/backend/server.js +159 -0
- package/dist/backend/services/artifact-service.js +170 -0
- package/dist/backend/services/command-dispatcher.js +37 -0
- package/dist/backend/services/message-service.js +217 -0
- package/dist/backend/services/project-service.js +71 -0
- package/dist/backend/services/session-service.js +221 -0
- package/dist/backend/services/status-service.js +21 -0
- package/dist/backend/services/task-service.js +88 -0
- package/dist/backend/templates/handoff.js +76 -0
- package/dist/backend/templates/message-envelope.js +27 -0
- package/dist/backend/templates/role-command.js +21 -0
- package/dist/backend/templates/role-messaging-context.js +44 -0
- package/dist/backend/ws/terminal-ws.js +60 -0
- package/dist/cli/vcmctl.js +141 -0
- package/dist/main.js +63 -0
- package/dist/shared/constants.js +45 -0
- package/dist/shared/types/api.js +1 -0
- package/dist/shared/types/artifact.js +1 -0
- package/dist/shared/types/message.js +1 -0
- package/dist/shared/types/project.js +1 -0
- package/dist/shared/types/role.js +1 -0
- package/dist/shared/types/session.js +1 -0
- package/dist/shared/types/task.js +1 -0
- package/dist/shared/types/terminal.js +1 -0
- package/dist/shared/validation/artifact-check.js +64 -0
- package/dist/shared/validation/slug-check.js +22 -0
- package/dist-frontend/assets/index-Bah6k-Ix.css +32 -0
- package/dist-frontend/assets/index-EMaQuIB6.js +58 -0
- package/dist-frontend/index.html +13 -0
- package/docs/cc-best-practices.md +2142 -0
- package/docs/product-design.md +1597 -0
- package/docs/v1-architecture-design.md +1431 -0
- package/docs/v1-implementation-plan.md +1949 -0
- package/docs/v1-message-bus-orchestration-design.md +534 -0
- package/package.json +60 -0
- package/scripts/clean-build.mjs +12 -0
- package/scripts/fix-node-pty-spawn-helper.mjs +31 -0
|
@@ -0,0 +1,1949 @@
|
|
|
1
|
+
# VibeCodingMaster V1 实施计划
|
|
2
|
+
|
|
3
|
+
版本:v0.2
|
|
4
|
+
日期:2026-05-29
|
|
5
|
+
状态:实施计划草案
|
|
6
|
+
依据:
|
|
7
|
+
|
|
8
|
+
- `docs/product-design.md`
|
|
9
|
+
- `docs/v1-architecture-design.md`
|
|
10
|
+
- `docs/cc-best-practices.md`
|
|
11
|
+
|
|
12
|
+
## 1. 实施目标
|
|
13
|
+
|
|
14
|
+
V1 实现一个本地 GUI Session Cockpit,让用户可以在一个任务工作台中启动、切换、查看、输入和管理多个 Claude Code role sessions。
|
|
15
|
+
|
|
16
|
+
V1 完成后,用户应能:
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
Open VibeCodingMaster
|
|
20
|
+
-> Select repo
|
|
21
|
+
-> New task
|
|
22
|
+
-> Start project-manager session
|
|
23
|
+
-> Start architect session
|
|
24
|
+
-> Switch between role sessions
|
|
25
|
+
-> Type directly into embedded Claude Code terminals
|
|
26
|
+
-> View role commands, logs, and handoff artifacts
|
|
27
|
+
-> Send role command to target session from GUI
|
|
28
|
+
-> Restart / stop role sessions
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
V1 不再以手动 CLI 或手动终端控制为主路径。
|
|
32
|
+
|
|
33
|
+
V1 不实现:
|
|
34
|
+
|
|
35
|
+
- 自动生成完整 Task Spec。
|
|
36
|
+
- 自动识别 public contract / test contract。
|
|
37
|
+
- 自动执行 validation commands。
|
|
38
|
+
- 自动 Cross-Model Review。
|
|
39
|
+
- 自动创建 PR。
|
|
40
|
+
- SaaS 多用户协作。
|
|
41
|
+
- 完整 Desktop 打包和自动更新。
|
|
42
|
+
- 多 worktree 自动管理。
|
|
43
|
+
|
|
44
|
+
## 2. 关键约束
|
|
45
|
+
|
|
46
|
+
1. GUI 是用户主入口,CLI 只用于启动 dev server、调试和 smoke test。
|
|
47
|
+
2. Claude Code role session 必须在 embedded terminal 中可见、可输入、可重启。
|
|
48
|
+
3. Project Manager 不直接无限制控制其他 role sessions。
|
|
49
|
+
4. Role command 必须先落盘到 `.ai/handoffs/<task-slug>/role-commands/<role>.md`。
|
|
50
|
+
5. GUI 读取 role command,用户点击发送后,backend 只向目标 terminal 写入短指令。
|
|
51
|
+
6. Backend 可以程序化写入和监听 embedded terminal,但 V1 只允许用户触发的 command dispatch,不自动确认权限,不自动串联驱动角色。
|
|
52
|
+
7. Terminal output 只作为调试信息;长期事实源是 handoff artifacts。
|
|
53
|
+
8. Raw terminal stream 必须持续写入 `.ai/handoffs/<task-slug>/logs/<role>.log`。
|
|
54
|
+
9. V1 只做 artifact 存在性和标题完整性检查,不判断内容质量。
|
|
55
|
+
10. 状态必须能从 backend session registry、terminal process state、repo artifacts、`.vcm` metadata 恢复。
|
|
56
|
+
11. V1 不把每个 role 放到独立 worktree。同一任务默认共享当前 repo working directory。
|
|
57
|
+
12. V1 默认遵守 single-writer rule,但主要通过流程提示、role status 和 review gate 实现,不做强制 sandbox。
|
|
58
|
+
|
|
59
|
+
## 3. 技术选型
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
Language: TypeScript
|
|
63
|
+
Runtime: Node.js LTS
|
|
64
|
+
Frontend: React + Vite
|
|
65
|
+
Terminal UI: xterm.js
|
|
66
|
+
Backend: Fastify + ws
|
|
67
|
+
Terminal runtime: node-pty
|
|
68
|
+
Process execution: execa
|
|
69
|
+
State storage: JSON files
|
|
70
|
+
Test runner: Vitest + Playwright
|
|
71
|
+
Module format: ESM / NodeNext
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 4. 目标目录结构
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
VibeCodingMaster/
|
|
78
|
+
package.json
|
|
79
|
+
tsconfig.json
|
|
80
|
+
tsconfig.node.json
|
|
81
|
+
vite.config.ts
|
|
82
|
+
vitest.config.ts
|
|
83
|
+
playwright.config.ts
|
|
84
|
+
index.html
|
|
85
|
+
README.md
|
|
86
|
+
docs/
|
|
87
|
+
product-design.md
|
|
88
|
+
v1-architecture-design.md
|
|
89
|
+
v1-implementation-plan.md
|
|
90
|
+
cc-best-practices.md
|
|
91
|
+
|
|
92
|
+
src/
|
|
93
|
+
main.ts
|
|
94
|
+
|
|
95
|
+
shared/
|
|
96
|
+
constants.ts
|
|
97
|
+
types/
|
|
98
|
+
api.ts
|
|
99
|
+
artifact.ts
|
|
100
|
+
project.ts
|
|
101
|
+
role.ts
|
|
102
|
+
session.ts
|
|
103
|
+
task.ts
|
|
104
|
+
terminal.ts
|
|
105
|
+
validation/
|
|
106
|
+
artifact-check.ts
|
|
107
|
+
slug-check.ts
|
|
108
|
+
|
|
109
|
+
frontend/
|
|
110
|
+
app.tsx
|
|
111
|
+
main.tsx
|
|
112
|
+
styles.css
|
|
113
|
+
routes/
|
|
114
|
+
project-dashboard.tsx
|
|
115
|
+
task-workspace.tsx
|
|
116
|
+
components/
|
|
117
|
+
app-shell.tsx
|
|
118
|
+
event-log.tsx
|
|
119
|
+
repo-connect-form.tsx
|
|
120
|
+
role-session-tabs.tsx
|
|
121
|
+
session-console.tsx
|
|
122
|
+
session-toolbar.tsx
|
|
123
|
+
status-badge.tsx
|
|
124
|
+
task-nav.tsx
|
|
125
|
+
terminal/
|
|
126
|
+
terminal-client.ts
|
|
127
|
+
xterm-view.tsx
|
|
128
|
+
state/
|
|
129
|
+
api-client.ts
|
|
130
|
+
app-store.ts
|
|
131
|
+
session-store.ts
|
|
132
|
+
|
|
133
|
+
backend/
|
|
134
|
+
server.ts
|
|
135
|
+
api/
|
|
136
|
+
artifact-routes.ts
|
|
137
|
+
project-routes.ts
|
|
138
|
+
session-routes.ts
|
|
139
|
+
task-routes.ts
|
|
140
|
+
ws/
|
|
141
|
+
terminal-ws.ts
|
|
142
|
+
runtime/
|
|
143
|
+
node-pty-runtime.ts
|
|
144
|
+
session-registry.ts
|
|
145
|
+
terminal-runtime.ts
|
|
146
|
+
services/
|
|
147
|
+
artifact-service.ts
|
|
148
|
+
command-dispatcher.ts
|
|
149
|
+
project-service.ts
|
|
150
|
+
session-service.ts
|
|
151
|
+
status-service.ts
|
|
152
|
+
task-service.ts
|
|
153
|
+
adapters/
|
|
154
|
+
claude-adapter.ts
|
|
155
|
+
command-runner.ts
|
|
156
|
+
filesystem.ts
|
|
157
|
+
git-adapter.ts
|
|
158
|
+
templates/
|
|
159
|
+
handoff.ts
|
|
160
|
+
role-command.ts
|
|
161
|
+
validation/
|
|
162
|
+
environment-check.ts
|
|
163
|
+
|
|
164
|
+
tests/
|
|
165
|
+
unit/
|
|
166
|
+
shared/
|
|
167
|
+
backend/
|
|
168
|
+
frontend/
|
|
169
|
+
integration/
|
|
170
|
+
api/
|
|
171
|
+
runtime/
|
|
172
|
+
e2e/
|
|
173
|
+
task-workspace.spec.ts
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## 5. Package 和配置文件
|
|
177
|
+
|
|
178
|
+
### 5.1 `package.json`
|
|
179
|
+
|
|
180
|
+
职责:
|
|
181
|
+
|
|
182
|
+
- 声明本地开发命令。
|
|
183
|
+
- 声明 build、test、typecheck、e2e 命令。
|
|
184
|
+
- 保留 `vcm` binary 用于启动本地 GUI dev/prod server。
|
|
185
|
+
|
|
186
|
+
计划字段:
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"type": "module",
|
|
191
|
+
"bin": {
|
|
192
|
+
"vcm": "./dist/main.js"
|
|
193
|
+
},
|
|
194
|
+
"scripts": {
|
|
195
|
+
"dev": "tsx src/main.ts --dev",
|
|
196
|
+
"build": "tsc -p tsconfig.node.json && vite build",
|
|
197
|
+
"start": "node dist/main.js",
|
|
198
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.node.json --noEmit",
|
|
199
|
+
"test": "vitest run",
|
|
200
|
+
"test:watch": "vitest",
|
|
201
|
+
"e2e": "playwright test"
|
|
202
|
+
},
|
|
203
|
+
"dependencies": {
|
|
204
|
+
"@fastify/static": "^7.0.0",
|
|
205
|
+
"@xterm/addon-fit": "^0.10.0",
|
|
206
|
+
"@xterm/addon-web-links": "^0.11.0",
|
|
207
|
+
"@xterm/xterm": "^5.5.0",
|
|
208
|
+
"execa": "^9.0.0",
|
|
209
|
+
"fastify": "^5.0.0",
|
|
210
|
+
"node-pty": "^1.0.0",
|
|
211
|
+
"react": "^19.0.0",
|
|
212
|
+
"react-dom": "^19.0.0",
|
|
213
|
+
"ws": "^8.0.0",
|
|
214
|
+
"zod": "^3.0.0"
|
|
215
|
+
},
|
|
216
|
+
"devDependencies": {
|
|
217
|
+
"@playwright/test": "^1.0.0",
|
|
218
|
+
"@types/node": "^22.0.0",
|
|
219
|
+
"@types/react": "^19.0.0",
|
|
220
|
+
"@types/react-dom": "^19.0.0",
|
|
221
|
+
"@types/ws": "^8.0.0",
|
|
222
|
+
"@vitejs/plugin-react": "^4.0.0",
|
|
223
|
+
"tsx": "^4.0.0",
|
|
224
|
+
"typescript": "^5.0.0",
|
|
225
|
+
"vite": "^6.0.0",
|
|
226
|
+
"vitest": "^2.0.0"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 5.2 `tsconfig.json`
|
|
232
|
+
|
|
233
|
+
职责:
|
|
234
|
+
|
|
235
|
+
- 类型检查前端和 shared 代码。
|
|
236
|
+
- 使用 JSX。
|
|
237
|
+
- 不输出文件。
|
|
238
|
+
|
|
239
|
+
关键配置:
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"compilerOptions": {
|
|
244
|
+
"target": "ES2022",
|
|
245
|
+
"module": "ESNext",
|
|
246
|
+
"moduleResolution": "Bundler",
|
|
247
|
+
"jsx": "react-jsx",
|
|
248
|
+
"strict": true,
|
|
249
|
+
"esModuleInterop": true,
|
|
250
|
+
"skipLibCheck": true,
|
|
251
|
+
"types": ["vite/client"]
|
|
252
|
+
},
|
|
253
|
+
"include": ["src/frontend/**/*.ts", "src/frontend/**/*.tsx", "src/shared/**/*.ts"]
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 5.3 `tsconfig.node.json`
|
|
258
|
+
|
|
259
|
+
职责:
|
|
260
|
+
|
|
261
|
+
- 编译 backend、main 和 shared 代码到 `dist/`。
|
|
262
|
+
- 使用 NodeNext ESM。
|
|
263
|
+
|
|
264
|
+
关键配置:
|
|
265
|
+
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"compilerOptions": {
|
|
269
|
+
"target": "ES2022",
|
|
270
|
+
"module": "NodeNext",
|
|
271
|
+
"moduleResolution": "NodeNext",
|
|
272
|
+
"rootDir": "src",
|
|
273
|
+
"outDir": "dist",
|
|
274
|
+
"strict": true,
|
|
275
|
+
"esModuleInterop": true,
|
|
276
|
+
"skipLibCheck": true
|
|
277
|
+
},
|
|
278
|
+
"include": ["src/main.ts", "src/backend/**/*.ts", "src/shared/**/*.ts"]
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### 5.4 `vite.config.ts`
|
|
283
|
+
|
|
284
|
+
职责:
|
|
285
|
+
|
|
286
|
+
- 构建 React frontend。
|
|
287
|
+
- 开发时代理 API 和 WebSocket 到 local backend。
|
|
288
|
+
|
|
289
|
+
导出定义:
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
export default defineConfig({
|
|
293
|
+
plugins: [react()],
|
|
294
|
+
root: ".",
|
|
295
|
+
build: {
|
|
296
|
+
outDir: "dist-frontend"
|
|
297
|
+
},
|
|
298
|
+
server: {
|
|
299
|
+
port: 5173,
|
|
300
|
+
proxy: {
|
|
301
|
+
"/api": "http://localhost:4173",
|
|
302
|
+
"/ws": {
|
|
303
|
+
target: "ws://localhost:4173",
|
|
304
|
+
ws: true
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### 5.5 `vitest.config.ts`
|
|
312
|
+
|
|
313
|
+
职责:
|
|
314
|
+
|
|
315
|
+
- 运行 unit 和 integration tests。
|
|
316
|
+
- 使用 node environment。
|
|
317
|
+
|
|
318
|
+
导出定义:
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
export default defineConfig({
|
|
322
|
+
test: {
|
|
323
|
+
environment: "node",
|
|
324
|
+
include: ["tests/unit/**/*.test.ts", "tests/integration/**/*.test.ts"]
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### 5.6 `playwright.config.ts`
|
|
330
|
+
|
|
331
|
+
职责:
|
|
332
|
+
|
|
333
|
+
- 运行 GUI smoke tests。
|
|
334
|
+
- 启动 `npm run dev` 作为 webServer。
|
|
335
|
+
|
|
336
|
+
导出定义:
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
export default defineConfig({
|
|
340
|
+
testDir: "tests/e2e",
|
|
341
|
+
webServer: {
|
|
342
|
+
command: "npm run dev",
|
|
343
|
+
url: "http://localhost:5173",
|
|
344
|
+
reuseExistingServer: true
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### 5.7 `src/main.ts`
|
|
350
|
+
|
|
351
|
+
职责:
|
|
352
|
+
|
|
353
|
+
- 启动 local backend。
|
|
354
|
+
- 在 dev 模式提示 Vite URL。
|
|
355
|
+
- 在 prod 模式 serve frontend static assets。
|
|
356
|
+
|
|
357
|
+
导出定义:
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
export interface MainOptions {
|
|
361
|
+
dev?: boolean;
|
|
362
|
+
host?: string;
|
|
363
|
+
port?: number;
|
|
364
|
+
open?: boolean;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export function parseMainArgs(argv: string[]): MainOptions;
|
|
368
|
+
|
|
369
|
+
export async function main(argv?: string[]): Promise<void>;
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## 6. Shared 类型层
|
|
373
|
+
|
|
374
|
+
### 6.1 `src/shared/types/role.ts`
|
|
375
|
+
|
|
376
|
+
职责:
|
|
377
|
+
|
|
378
|
+
- 定义 V1 role 集合和状态。
|
|
379
|
+
|
|
380
|
+
导出定义:
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
export type RoleName =
|
|
384
|
+
| "project-manager"
|
|
385
|
+
| "architect"
|
|
386
|
+
| "coder"
|
|
387
|
+
| "reviewer";
|
|
388
|
+
|
|
389
|
+
export type DispatchableRole =
|
|
390
|
+
| "architect"
|
|
391
|
+
| "coder"
|
|
392
|
+
| "reviewer";
|
|
393
|
+
|
|
394
|
+
export type RoleStatus =
|
|
395
|
+
| "not_started"
|
|
396
|
+
| "starting"
|
|
397
|
+
| "running"
|
|
398
|
+
| "waiting"
|
|
399
|
+
| "blocked"
|
|
400
|
+
| "done"
|
|
401
|
+
| "resumable"
|
|
402
|
+
| "crashed"
|
|
403
|
+
| "exited"
|
|
404
|
+
| "missing"
|
|
405
|
+
| "unknown";
|
|
406
|
+
|
|
407
|
+
export interface RoleDefinition {
|
|
408
|
+
name: RoleName;
|
|
409
|
+
label: string;
|
|
410
|
+
commandAgent: string;
|
|
411
|
+
dispatchable: boolean;
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### 6.2 `src/shared/constants.ts`
|
|
416
|
+
|
|
417
|
+
职责:
|
|
418
|
+
|
|
419
|
+
- 定义固定 role、artifact 文件名、默认端口。
|
|
420
|
+
|
|
421
|
+
导出定义:
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
export const DEFAULT_BACKEND_PORT = 4173;
|
|
425
|
+
export const DEFAULT_FRONTEND_PORT = 5173;
|
|
426
|
+
|
|
427
|
+
export const ROLE_DEFINITIONS: readonly RoleDefinition[];
|
|
428
|
+
export const ROLE_NAMES: readonly RoleName[];
|
|
429
|
+
export const DISPATCHABLE_ROLES: readonly DispatchableRole[];
|
|
430
|
+
|
|
431
|
+
export function isRoleName(value: string): value is RoleName;
|
|
432
|
+
export function isDispatchableRole(value: string): value is DispatchableRole;
|
|
433
|
+
export function getRoleDefinition(role: RoleName): RoleDefinition;
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### 6.3 `src/shared/types/project.ts`
|
|
437
|
+
|
|
438
|
+
职责:
|
|
439
|
+
|
|
440
|
+
- 定义 repo 连接和项目配置。
|
|
441
|
+
|
|
442
|
+
导出定义:
|
|
443
|
+
|
|
444
|
+
```ts
|
|
445
|
+
export interface ProjectConfig {
|
|
446
|
+
version: 1;
|
|
447
|
+
repoRoot: string;
|
|
448
|
+
defaultRoles: RoleName[];
|
|
449
|
+
handoffRoot: string;
|
|
450
|
+
stateRoot: string;
|
|
451
|
+
terminalBackend: "node-pty";
|
|
452
|
+
claudeCommand: string;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
export interface ProjectSummary {
|
|
456
|
+
repoRoot: string;
|
|
457
|
+
branch: string;
|
|
458
|
+
isDirty: boolean;
|
|
459
|
+
config: ProjectConfig;
|
|
460
|
+
warnings: string[];
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export interface ConnectProjectRequest {
|
|
464
|
+
repoPath: string;
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 6.4 `src/shared/types/task.ts`
|
|
469
|
+
|
|
470
|
+
职责:
|
|
471
|
+
|
|
472
|
+
- 定义 task metadata。
|
|
473
|
+
|
|
474
|
+
导出定义:
|
|
475
|
+
|
|
476
|
+
```ts
|
|
477
|
+
export type TaskStatus =
|
|
478
|
+
| "created"
|
|
479
|
+
| "planning"
|
|
480
|
+
| "running"
|
|
481
|
+
| "blocked"
|
|
482
|
+
| "stopped"
|
|
483
|
+
| "done";
|
|
484
|
+
|
|
485
|
+
export interface TaskRecord {
|
|
486
|
+
version: 1;
|
|
487
|
+
taskSlug: string;
|
|
488
|
+
title?: string;
|
|
489
|
+
createdAt: string;
|
|
490
|
+
updatedAt: string;
|
|
491
|
+
repoRoot: string;
|
|
492
|
+
branch: string;
|
|
493
|
+
handoffDir: string;
|
|
494
|
+
status: TaskStatus;
|
|
495
|
+
specPath?: string;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export interface CreateTaskRequest {
|
|
499
|
+
taskSlug: string;
|
|
500
|
+
title?: string;
|
|
501
|
+
specPath?: string;
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### 6.5 `src/shared/types/session.ts`
|
|
506
|
+
|
|
507
|
+
职责:
|
|
508
|
+
|
|
509
|
+
- 定义 role session metadata 和 task session summary。
|
|
510
|
+
|
|
511
|
+
导出定义:
|
|
512
|
+
|
|
513
|
+
```ts
|
|
514
|
+
export type ClaudePermissionMode =
|
|
515
|
+
| "default"
|
|
516
|
+
| "bypassPermissions"
|
|
517
|
+
| "dangerously-skip-permissions";
|
|
518
|
+
|
|
519
|
+
export interface RoleSessionRecord {
|
|
520
|
+
id: string;
|
|
521
|
+
claudeSessionId: string;
|
|
522
|
+
taskSlug: string;
|
|
523
|
+
role: RoleName;
|
|
524
|
+
status: RoleStatus;
|
|
525
|
+
command: string;
|
|
526
|
+
permissionMode: ClaudePermissionMode;
|
|
527
|
+
cwd: string;
|
|
528
|
+
terminalBackend: "node-pty";
|
|
529
|
+
pid?: number;
|
|
530
|
+
logPath: string;
|
|
531
|
+
roleCommandPath?: string;
|
|
532
|
+
handoffArtifactPath?: string;
|
|
533
|
+
startedAt?: string;
|
|
534
|
+
updatedAt: string;
|
|
535
|
+
lastOutputAt?: string;
|
|
536
|
+
exitCode?: number | null;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export interface TaskSessionRecord {
|
|
540
|
+
version: 1;
|
|
541
|
+
taskSlug: string;
|
|
542
|
+
updatedAt: string;
|
|
543
|
+
roles: Record<RoleName, RoleSessionPointer>;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
export interface RoleSessionPointer {
|
|
547
|
+
id: string | null;
|
|
548
|
+
claudeSessionId?: string;
|
|
549
|
+
status: RoleStatus;
|
|
550
|
+
record?: RoleSessionRecord;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export interface StartRoleSessionRequest {
|
|
554
|
+
cols?: number;
|
|
555
|
+
rows?: number;
|
|
556
|
+
permissionMode?: ClaudePermissionMode;
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### 6.6 `src/shared/types/terminal.ts`
|
|
561
|
+
|
|
562
|
+
职责:
|
|
563
|
+
|
|
564
|
+
- 定义 WebSocket terminal 消息和事件。
|
|
565
|
+
|
|
566
|
+
导出定义:
|
|
567
|
+
|
|
568
|
+
```ts
|
|
569
|
+
export type ClientTerminalMessage =
|
|
570
|
+
| { type: "input"; data: string }
|
|
571
|
+
| { type: "resize"; cols: number; rows: number };
|
|
572
|
+
|
|
573
|
+
export type ServerTerminalMessage =
|
|
574
|
+
| { type: "output"; data: string }
|
|
575
|
+
| { type: "status"; status: RoleStatus }
|
|
576
|
+
| { type: "exit"; exitCode: number | null }
|
|
577
|
+
| { type: "error"; message: string };
|
|
578
|
+
|
|
579
|
+
export interface TerminalEvent {
|
|
580
|
+
id: string;
|
|
581
|
+
sessionId: string;
|
|
582
|
+
taskSlug: string;
|
|
583
|
+
role: RoleName;
|
|
584
|
+
type: "input" | "output" | "status" | "exit" | "error" | "dispatch";
|
|
585
|
+
timestamp: string;
|
|
586
|
+
data?: string;
|
|
587
|
+
status?: RoleStatus;
|
|
588
|
+
exitCode?: number | null;
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### 6.7 `src/shared/types/artifact.ts`
|
|
593
|
+
|
|
594
|
+
职责:
|
|
595
|
+
|
|
596
|
+
- 定义 handoff artifact paths 和 schema check。
|
|
597
|
+
|
|
598
|
+
导出定义:
|
|
599
|
+
|
|
600
|
+
```ts
|
|
601
|
+
export type ArtifactKind =
|
|
602
|
+
| "architecture-plan"
|
|
603
|
+
| "implementation-log"
|
|
604
|
+
| "validation-log"
|
|
605
|
+
| "review-report";
|
|
606
|
+
|
|
607
|
+
export interface HandoffPaths {
|
|
608
|
+
handoffDir: string;
|
|
609
|
+
roleCommandsDir: string;
|
|
610
|
+
logsDir: string;
|
|
611
|
+
roleCommandPaths: Record<DispatchableRole, string>;
|
|
612
|
+
roleLogPaths: Record<RoleName, string>;
|
|
613
|
+
architecturePlanPath: string;
|
|
614
|
+
implementationLogPath: string;
|
|
615
|
+
validationLogPath: string;
|
|
616
|
+
reviewReportPath: string;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export interface ArtifactCheckResult {
|
|
620
|
+
kind: ArtifactKind;
|
|
621
|
+
path: string;
|
|
622
|
+
exists: boolean;
|
|
623
|
+
isEmpty: boolean;
|
|
624
|
+
missingHeadings: string[];
|
|
625
|
+
status: "missing" | "empty" | "incomplete" | "ok";
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
export interface ArtifactSummary {
|
|
629
|
+
paths: HandoffPaths;
|
|
630
|
+
checks: ArtifactCheckResult[];
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### 6.8 `src/shared/types/api.ts`
|
|
635
|
+
|
|
636
|
+
职责:
|
|
637
|
+
|
|
638
|
+
- 定义统一 API response。
|
|
639
|
+
|
|
640
|
+
导出定义:
|
|
641
|
+
|
|
642
|
+
```ts
|
|
643
|
+
export interface ApiSuccess<T> {
|
|
644
|
+
ok: true;
|
|
645
|
+
data: T;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
export interface ApiFailure {
|
|
649
|
+
ok: false;
|
|
650
|
+
error: {
|
|
651
|
+
code: string;
|
|
652
|
+
message: string;
|
|
653
|
+
hint?: string;
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
export type ApiResponse<T> = ApiSuccess<T> | ApiFailure;
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
## 7. Shared Validation
|
|
661
|
+
|
|
662
|
+
### 7.1 `src/shared/validation/slug-check.ts`
|
|
663
|
+
|
|
664
|
+
导出定义:
|
|
665
|
+
|
|
666
|
+
```ts
|
|
667
|
+
export interface SlugValidationResult {
|
|
668
|
+
valid: boolean;
|
|
669
|
+
reason?: string;
|
|
670
|
+
suggestion?: string;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
export function isValidTaskSlug(value: string): boolean;
|
|
674
|
+
export function validateTaskSlug(value: string): SlugValidationResult;
|
|
675
|
+
export function assertValidTaskSlug(value: string): string;
|
|
676
|
+
export function suggestTaskSlug(value: string): string;
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
### 7.2 `src/shared/validation/artifact-check.ts`
|
|
680
|
+
|
|
681
|
+
导出定义:
|
|
682
|
+
|
|
683
|
+
```ts
|
|
684
|
+
export const REQUIRED_ARCHITECTURE_PLAN_HEADINGS: readonly string[];
|
|
685
|
+
export const REQUIRED_IMPLEMENTATION_LOG_HEADINGS: readonly string[];
|
|
686
|
+
export const REQUIRED_REVIEW_REPORT_HEADINGS: readonly string[];
|
|
687
|
+
|
|
688
|
+
export function getRequiredHeadings(kind: ArtifactKind): readonly string[];
|
|
689
|
+
export function parseMarkdownHeadings(content: string): string[];
|
|
690
|
+
export function findMissingHeadings(content: string, required: readonly string[]): string[];
|
|
691
|
+
export function checkMarkdownArtifact(kind: ArtifactKind, path: string, content: string | null): ArtifactCheckResult;
|
|
692
|
+
export function checkValidationLogArtifact(path: string, content: string | null): ArtifactCheckResult;
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
## 8. Backend Adapter 层
|
|
696
|
+
|
|
697
|
+
### 8.1 `src/backend/adapters/command-runner.ts`
|
|
698
|
+
|
|
699
|
+
职责:
|
|
700
|
+
|
|
701
|
+
- 封装 `execa`。
|
|
702
|
+
- 供 git / claude check 使用。
|
|
703
|
+
|
|
704
|
+
导出定义:
|
|
705
|
+
|
|
706
|
+
```ts
|
|
707
|
+
export interface RunCommandOptions {
|
|
708
|
+
cwd?: string;
|
|
709
|
+
reject?: boolean;
|
|
710
|
+
env?: NodeJS.ProcessEnv;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
export interface RunCommandResult {
|
|
714
|
+
stdout: string;
|
|
715
|
+
stderr: string;
|
|
716
|
+
exitCode: number;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
export interface CommandRunner {
|
|
720
|
+
run(command: string, args: string[], options?: RunCommandOptions): Promise<RunCommandResult>;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
export function createDefaultCommandRunner(): CommandRunner;
|
|
724
|
+
export function normalizeCommandError(error: unknown): RunCommandResult;
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
### 8.2 `src/backend/adapters/filesystem.ts`
|
|
728
|
+
|
|
729
|
+
职责:
|
|
730
|
+
|
|
731
|
+
- 封装文件读写、JSON 读写、目录创建。
|
|
732
|
+
|
|
733
|
+
导出定义:
|
|
734
|
+
|
|
735
|
+
```ts
|
|
736
|
+
export interface FileSystemAdapter {
|
|
737
|
+
pathExists(path: string): Promise<boolean>;
|
|
738
|
+
ensureDir(path: string): Promise<void>;
|
|
739
|
+
readText(path: string): Promise<string>;
|
|
740
|
+
writeText(path: string, content: string): Promise<void>;
|
|
741
|
+
appendText(path: string, content: string): Promise<void>;
|
|
742
|
+
readJson<T>(path: string): Promise<T>;
|
|
743
|
+
writeJsonAtomic<T>(path: string, value: T): Promise<void>;
|
|
744
|
+
ensureFile(path: string, content: string, options?: EnsureFileOptions): Promise<boolean>;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
export interface EnsureFileOptions {
|
|
748
|
+
overwrite?: boolean;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
export function createNodeFileSystemAdapter(): FileSystemAdapter;
|
|
752
|
+
export function resolveRepoPath(repoRoot: string, repoRelativePath: string): string;
|
|
753
|
+
export function toRepoRelativePath(repoRoot: string, absolutePath: string): string;
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
### 8.3 `src/backend/adapters/git-adapter.ts`
|
|
757
|
+
|
|
758
|
+
职责:
|
|
759
|
+
|
|
760
|
+
- 检查 Git repo 和 branch 状态。
|
|
761
|
+
|
|
762
|
+
导出定义:
|
|
763
|
+
|
|
764
|
+
```ts
|
|
765
|
+
export interface GitAdapter {
|
|
766
|
+
isGitRepo(cwd: string): Promise<boolean>;
|
|
767
|
+
getRepoRoot(cwd: string): Promise<string>;
|
|
768
|
+
getCurrentBranch(repoRoot: string): Promise<string>;
|
|
769
|
+
isDirty(repoRoot: string): Promise<boolean>;
|
|
770
|
+
getDiffSummary(repoRoot: string): Promise<string>;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
export function createGitAdapter(runner: CommandRunner): GitAdapter;
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### 8.4 `src/backend/adapters/claude-adapter.ts`
|
|
777
|
+
|
|
778
|
+
职责:
|
|
779
|
+
|
|
780
|
+
- 检查 Claude Code 是否安装。
|
|
781
|
+
- 生成 role session 启动命令。
|
|
782
|
+
|
|
783
|
+
导出定义:
|
|
784
|
+
|
|
785
|
+
```ts
|
|
786
|
+
export interface ClaudeAdapter {
|
|
787
|
+
isAvailable(command?: string): Promise<boolean>;
|
|
788
|
+
getVersion(command?: string): Promise<string>;
|
|
789
|
+
buildRoleStartCommand(
|
|
790
|
+
role: RoleName,
|
|
791
|
+
command?: string,
|
|
792
|
+
permissionMode?: ClaudePermissionMode
|
|
793
|
+
): { command: string; args: string[]; display: string };
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
export function createClaudeAdapter(runner: CommandRunner): ClaudeAdapter;
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
## 9. Backend Runtime 层
|
|
800
|
+
|
|
801
|
+
### 9.1 `src/backend/runtime/terminal-runtime.ts`
|
|
802
|
+
|
|
803
|
+
职责:
|
|
804
|
+
|
|
805
|
+
- 定义 terminal runtime 抽象。
|
|
806
|
+
- 让上层业务不依赖 node-pty 细节。
|
|
807
|
+
|
|
808
|
+
导出定义:
|
|
809
|
+
|
|
810
|
+
```ts
|
|
811
|
+
export interface CreateTerminalSessionInput {
|
|
812
|
+
taskSlug: string;
|
|
813
|
+
role: RoleName;
|
|
814
|
+
command: string;
|
|
815
|
+
args: string[];
|
|
816
|
+
cwd: string;
|
|
817
|
+
env?: NodeJS.ProcessEnv;
|
|
818
|
+
cols?: number;
|
|
819
|
+
rows?: number;
|
|
820
|
+
logPath: string;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
export interface TerminalSession {
|
|
824
|
+
id: string;
|
|
825
|
+
taskSlug: string;
|
|
826
|
+
role: RoleName;
|
|
827
|
+
status: RoleStatus;
|
|
828
|
+
pid?: number;
|
|
829
|
+
startedAt: string;
|
|
830
|
+
lastOutputAt?: string;
|
|
831
|
+
exitCode?: number | null;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
export type TerminalEventListener = (event: TerminalEvent) => void;
|
|
835
|
+
export type Unsubscribe = () => void;
|
|
836
|
+
|
|
837
|
+
export interface TerminalRuntime {
|
|
838
|
+
createSession(input: CreateTerminalSessionInput): Promise<TerminalSession>;
|
|
839
|
+
getSession(sessionId: string): TerminalSession | undefined;
|
|
840
|
+
getSessionByRole(taskSlug: string, role: RoleName): TerminalSession | undefined;
|
|
841
|
+
listSessions(taskSlug?: string): TerminalSession[];
|
|
842
|
+
write(sessionId: string, data: string): void;
|
|
843
|
+
resize(sessionId: string, cols: number, rows: number): void;
|
|
844
|
+
stop(sessionId: string): Promise<void>;
|
|
845
|
+
restart(sessionId: string): Promise<TerminalSession>;
|
|
846
|
+
subscribe(sessionId: string, listener: TerminalEventListener): Unsubscribe;
|
|
847
|
+
}
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
### 9.2 `src/backend/runtime/node-pty-runtime.ts`
|
|
851
|
+
|
|
852
|
+
职责:
|
|
853
|
+
|
|
854
|
+
- 实现 `TerminalRuntime`。
|
|
855
|
+
- 使用 node-pty 承载 Claude Code 交互式 session。
|
|
856
|
+
- 将 output 写入 logs 并推送给 subscribers。
|
|
857
|
+
|
|
858
|
+
导出定义:
|
|
859
|
+
|
|
860
|
+
```ts
|
|
861
|
+
export interface NodePtyRuntimeDeps {
|
|
862
|
+
fs: FileSystemAdapter;
|
|
863
|
+
now?: () => string;
|
|
864
|
+
id?: () => string;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
export function createNodePtyTerminalRuntime(deps: NodePtyRuntimeDeps): TerminalRuntime;
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
实现规则:
|
|
871
|
+
|
|
872
|
+
- `createSession` 使用 `pty.spawn(command, args, { cwd, env, cols, rows })`。
|
|
873
|
+
- 监听 `onData`:
|
|
874
|
+
- append 到 log。
|
|
875
|
+
- emit `TerminalEvent`。
|
|
876
|
+
- 更新 `lastOutputAt`。
|
|
877
|
+
- 监听 `onExit`:
|
|
878
|
+
- 更新 `status` 为 `exited` 或 `crashed`。
|
|
879
|
+
- emit `exit` event。
|
|
880
|
+
- `write` 写入 pty。
|
|
881
|
+
- `resize` 调用 pty resize。
|
|
882
|
+
- `stop` kill pty 并更新状态。
|
|
883
|
+
|
|
884
|
+
### 9.3 Programmatic I/O Boundary
|
|
885
|
+
|
|
886
|
+
V1 的 backend 允许程序化读写 embedded terminal:
|
|
887
|
+
|
|
888
|
+
- `runtime.write(sessionId, data)`:向指定 role session 写入 terminal input。
|
|
889
|
+
- `runtime.subscribe(sessionId, listener)`:监听 terminal output、status、exit 和 error event。
|
|
890
|
+
- `terminal-ws`:把用户在 GUI terminal 中输入的内容转发给 runtime。
|
|
891
|
+
- `command-dispatcher`:在用户点击 Send Command 后,向目标 session 写入短指令。
|
|
892
|
+
|
|
893
|
+
V1 允许的自动化边界:
|
|
894
|
+
|
|
895
|
+
- 用户在 GUI terminal 里的输入可以原样转发。
|
|
896
|
+
- 用户点击 Send Command 后,backend 可以写入 `Please read and execute the role command at: <path>`。
|
|
897
|
+
- Backend 可以监听 output 并写入 raw log。
|
|
898
|
+
- Backend 可以根据 output/exit event 更新轻量状态和 GUI 提示。
|
|
899
|
+
|
|
900
|
+
V1 明确不做:
|
|
901
|
+
|
|
902
|
+
- 不自动确认 Claude Code permission prompt。
|
|
903
|
+
- 不由 Project Manager 自动向 Architect/Coder/Reviewer 连续下发命令。
|
|
904
|
+
- 不由 Architect 输出自动触发 Coder。
|
|
905
|
+
- 不由 Coder 输出自动触发 Reviewer。
|
|
906
|
+
- 不根据 terminal output 自动执行高风险下一步。
|
|
907
|
+
|
|
908
|
+
### 9.4 `src/backend/runtime/session-registry.ts`
|
|
909
|
+
|
|
910
|
+
职责:
|
|
911
|
+
|
|
912
|
+
- 保存 backend 内存中的 live sessions。
|
|
913
|
+
- 将 runtime state 转为 GUI 可展示状态。
|
|
914
|
+
|
|
915
|
+
导出定义:
|
|
916
|
+
|
|
917
|
+
```ts
|
|
918
|
+
export interface SessionRegistry {
|
|
919
|
+
upsert(session: RoleSessionRecord): void;
|
|
920
|
+
get(sessionId: string): RoleSessionRecord | undefined;
|
|
921
|
+
getByRole(taskSlug: string, role: RoleName): RoleSessionRecord | undefined;
|
|
922
|
+
list(taskSlug?: string): RoleSessionRecord[];
|
|
923
|
+
updateStatus(sessionId: string, status: RoleStatus, patch?: Partial<RoleSessionRecord>): void;
|
|
924
|
+
remove(sessionId: string): void;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
export function createSessionRegistry(): SessionRegistry;
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
## 10. Backend Service 层
|
|
931
|
+
|
|
932
|
+
### 10.1 `src/backend/services/project-service.ts`
|
|
933
|
+
|
|
934
|
+
职责:
|
|
935
|
+
|
|
936
|
+
- 连接 repo。
|
|
937
|
+
- 创建 `.vcm/config.json`。
|
|
938
|
+
- 检查 Claude Code、branch、dirty state。
|
|
939
|
+
|
|
940
|
+
导出定义:
|
|
941
|
+
|
|
942
|
+
```ts
|
|
943
|
+
export interface ProjectService {
|
|
944
|
+
connectProject(input: ConnectProjectInput): Promise<ProjectSummary>;
|
|
945
|
+
getCurrentProject(): Promise<ProjectSummary | null>;
|
|
946
|
+
loadConfig(repoRoot: string): Promise<ProjectConfig>;
|
|
947
|
+
saveConfig(config: ProjectConfig, force?: boolean): Promise<void>;
|
|
948
|
+
getConfigPath(repoRoot: string): string;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
export interface ProjectServiceDeps {
|
|
952
|
+
fs: FileSystemAdapter;
|
|
953
|
+
git: GitAdapter;
|
|
954
|
+
claude: ClaudeAdapter;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
export function createProjectService(deps: ProjectServiceDeps): ProjectService;
|
|
958
|
+
export function buildDefaultProjectConfig(repoRoot: string): ProjectConfig;
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
### 10.2 `src/backend/services/task-service.ts`
|
|
962
|
+
|
|
963
|
+
职责:
|
|
964
|
+
|
|
965
|
+
- 创建任务 metadata。
|
|
966
|
+
- 创建 handoff structure。
|
|
967
|
+
- 读取任务列表和单个任务。
|
|
968
|
+
|
|
969
|
+
导出定义:
|
|
970
|
+
|
|
971
|
+
```ts
|
|
972
|
+
export interface TaskService {
|
|
973
|
+
createTask(repoRoot: string, input: CreateTaskRequest): Promise<TaskRecord>;
|
|
974
|
+
listTasks(repoRoot: string): Promise<TaskRecord[]>;
|
|
975
|
+
loadTask(repoRoot: string, taskSlug: string): Promise<TaskRecord>;
|
|
976
|
+
saveTask(repoRoot: string, task: TaskRecord): Promise<void>;
|
|
977
|
+
updateTaskStatus(repoRoot: string, taskSlug: string, status: TaskStatus): Promise<TaskRecord>;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
export interface TaskServiceDeps {
|
|
981
|
+
fs: FileSystemAdapter;
|
|
982
|
+
git: GitAdapter;
|
|
983
|
+
artifactService: ArtifactService;
|
|
984
|
+
projectService: Pick<ProjectService, "loadConfig">;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
export function createTaskService(deps: TaskServiceDeps): TaskService;
|
|
988
|
+
```
|
|
989
|
+
|
|
990
|
+
### 10.3 `src/backend/services/artifact-service.ts`
|
|
991
|
+
|
|
992
|
+
职责:
|
|
993
|
+
|
|
994
|
+
- 创建 handoff 目录结构。
|
|
995
|
+
- 创建 artifact 模板。
|
|
996
|
+
- 读写 role command。
|
|
997
|
+
- 检查 artifact 状态。
|
|
998
|
+
- 追加 raw logs。
|
|
999
|
+
|
|
1000
|
+
导出定义:
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
export interface ArtifactService {
|
|
1004
|
+
getHandoffPaths(repoRoot: string, handoffDir: string): HandoffPaths;
|
|
1005
|
+
ensureHandoffStructure(input: EnsureHandoffStructureInput): Promise<HandoffPaths>;
|
|
1006
|
+
createArtifactTemplates(input: CreateArtifactTemplatesInput): Promise<string[]>;
|
|
1007
|
+
listArtifacts(input: ListArtifactsInput): Promise<ArtifactSummary>;
|
|
1008
|
+
readArtifact(input: ReadArtifactInput): Promise<string>;
|
|
1009
|
+
readRoleCommand(input: ReadRoleCommandInput): Promise<string>;
|
|
1010
|
+
saveRoleCommand(input: SaveRoleCommandInput): Promise<void>;
|
|
1011
|
+
appendRoleLog(input: AppendRoleLogInput): Promise<void>;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
export interface EnsureHandoffStructureInput {
|
|
1015
|
+
repoRoot: string;
|
|
1016
|
+
taskSlug: string;
|
|
1017
|
+
handoffDir: string;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
export interface CreateArtifactTemplatesInput {
|
|
1021
|
+
repoRoot: string;
|
|
1022
|
+
taskSlug: string;
|
|
1023
|
+
handoffDir: string;
|
|
1024
|
+
overwrite?: boolean;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
export interface ListArtifactsInput {
|
|
1028
|
+
repoRoot: string;
|
|
1029
|
+
taskSlug: string;
|
|
1030
|
+
handoffDir: string;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
export interface ReadArtifactInput {
|
|
1034
|
+
repoRoot: string;
|
|
1035
|
+
path: string;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
export interface ReadRoleCommandInput {
|
|
1039
|
+
repoRoot: string;
|
|
1040
|
+
handoffDir: string;
|
|
1041
|
+
role: DispatchableRole;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
export interface SaveRoleCommandInput {
|
|
1045
|
+
repoRoot: string;
|
|
1046
|
+
handoffDir: string;
|
|
1047
|
+
role: DispatchableRole;
|
|
1048
|
+
content: string;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
export interface AppendRoleLogInput {
|
|
1052
|
+
repoRoot: string;
|
|
1053
|
+
handoffDir: string;
|
|
1054
|
+
role: RoleName;
|
|
1055
|
+
content: string;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
export function createArtifactService(fs: FileSystemAdapter): ArtifactService;
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
### 10.4 `src/backend/services/session-service.ts`
|
|
1062
|
+
|
|
1063
|
+
职责:
|
|
1064
|
+
|
|
1065
|
+
- 启动、停止、重启 role session。
|
|
1066
|
+
- 同步 runtime、registry 和 `.vcm/sessions` metadata。
|
|
1067
|
+
- 首次启动生成 `claudeSessionId`,并使用 `claude --agent <role> --session-id <uuid>`。
|
|
1068
|
+
- 异常中断或 backend 重启后,从 `.vcm/sessions/<task-slug>.json` 恢复 role metadata。
|
|
1069
|
+
- Resume 使用 `claude --agent <role> --resume <claudeSessionId>` 创建新的 embedded terminal。
|
|
1070
|
+
- Restart 优先复用已有 `claudeSessionId`,避免丢失长任务上下文。
|
|
1071
|
+
|
|
1072
|
+
导出定义:
|
|
1073
|
+
|
|
1074
|
+
```ts
|
|
1075
|
+
export interface SessionService {
|
|
1076
|
+
listSessions(repoRoot: string, taskSlug: string): Promise<RoleSessionRecord[]>;
|
|
1077
|
+
startRoleSession(input: StartRoleSessionInput): Promise<RoleSessionRecord>;
|
|
1078
|
+
resumeRoleSession(input: StartRoleSessionInput): Promise<RoleSessionRecord>;
|
|
1079
|
+
stopRoleSession(input: StopRoleSessionInput): Promise<RoleSessionRecord>;
|
|
1080
|
+
restartRoleSession(input: RestartRoleSessionInput): Promise<RoleSessionRecord>;
|
|
1081
|
+
getRoleSession(repoRoot: string, taskSlug: string, role: RoleName): Promise<RoleSessionRecord | null>;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
export interface StartRoleSessionInput {
|
|
1085
|
+
repoRoot: string;
|
|
1086
|
+
taskSlug: string;
|
|
1087
|
+
role: RoleName;
|
|
1088
|
+
cols?: number;
|
|
1089
|
+
rows?: number;
|
|
1090
|
+
permissionMode?: ClaudePermissionMode;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
export interface StopRoleSessionInput {
|
|
1094
|
+
repoRoot: string;
|
|
1095
|
+
taskSlug: string;
|
|
1096
|
+
role: RoleName;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
export interface RestartRoleSessionInput extends StopRoleSessionInput {
|
|
1100
|
+
cols?: number;
|
|
1101
|
+
rows?: number;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
export interface SessionServiceDeps {
|
|
1105
|
+
claude: ClaudeAdapter;
|
|
1106
|
+
runtime: TerminalRuntime;
|
|
1107
|
+
registry: SessionRegistry;
|
|
1108
|
+
taskService: TaskService;
|
|
1109
|
+
artifactService: ArtifactService;
|
|
1110
|
+
projectService: Pick<ProjectService, "loadConfig">;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
export function createSessionService(deps: SessionServiceDeps): SessionService;
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
### 10.5 `src/backend/services/command-dispatcher.ts`
|
|
1117
|
+
|
|
1118
|
+
职责:
|
|
1119
|
+
|
|
1120
|
+
- 从 role command artifact 读取命令。
|
|
1121
|
+
- 将短指令写入目标 role terminal。
|
|
1122
|
+
- 记录 dispatch event。
|
|
1123
|
+
|
|
1124
|
+
导出定义:
|
|
1125
|
+
|
|
1126
|
+
```ts
|
|
1127
|
+
export interface CommandDispatcher {
|
|
1128
|
+
dispatchRoleCommand(input: DispatchRoleCommandInput): Promise<DispatchRoleCommandResult>;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
export interface DispatchRoleCommandInput {
|
|
1132
|
+
repoRoot: string;
|
|
1133
|
+
taskSlug: string;
|
|
1134
|
+
role: DispatchableRole;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
export interface DispatchRoleCommandResult {
|
|
1138
|
+
taskSlug: string;
|
|
1139
|
+
role: DispatchableRole;
|
|
1140
|
+
commandPath: string;
|
|
1141
|
+
instruction: string;
|
|
1142
|
+
dispatchedAt: string;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
export interface CommandDispatcherDeps {
|
|
1146
|
+
runtime: TerminalRuntime;
|
|
1147
|
+
sessionService: SessionService;
|
|
1148
|
+
taskService: TaskService;
|
|
1149
|
+
artifactService: ArtifactService;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
export function createCommandDispatcher(deps: CommandDispatcherDeps): CommandDispatcher;
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
实现规则:
|
|
1156
|
+
|
|
1157
|
+
- role command 文件缺失时失败。
|
|
1158
|
+
- role command 文件为空时失败。
|
|
1159
|
+
- role command 文件仍是模板或包含 `TBD` / `status: draft` 时失败。
|
|
1160
|
+
- role command 必须使用当前 VCM task 的 canonical path:`.ai/handoffs/<task-slug>/role-commands/<role>.md`。
|
|
1161
|
+
- Project Manager 启动时,backend 必须向 session 注入 task context,明确 `taskSlug`、`handoffDir` 和三个 role command 路径。
|
|
1162
|
+
- 目标 role session 未运行时失败并提示启动 session。
|
|
1163
|
+
- `instruction` 必须是短文本:
|
|
1164
|
+
- 只有用户通过 GUI 点击 Send Command 时才调用 dispatch。
|
|
1165
|
+
- dispatch 不解析 Claude Code 输出,不自动重试,不自动确认权限。
|
|
1166
|
+
- dispatch 成功后只记录 event,不继续触发下一个 role。
|
|
1167
|
+
|
|
1168
|
+
```text
|
|
1169
|
+
Please read and execute the role command at: <path>
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
### 10.6 `src/backend/services/status-service.ts`
|
|
1173
|
+
|
|
1174
|
+
职责:
|
|
1175
|
+
|
|
1176
|
+
- 汇总 task、sessions、artifacts、events。
|
|
1177
|
+
|
|
1178
|
+
导出定义:
|
|
1179
|
+
|
|
1180
|
+
```ts
|
|
1181
|
+
export interface TaskStatusReport {
|
|
1182
|
+
task: TaskRecord;
|
|
1183
|
+
sessions: RoleSessionRecord[];
|
|
1184
|
+
artifacts: ArtifactSummary;
|
|
1185
|
+
warnings: string[];
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
export interface StatusService {
|
|
1189
|
+
getTaskStatus(repoRoot: string, taskSlug: string): Promise<TaskStatusReport>;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
export interface StatusServiceDeps {
|
|
1193
|
+
taskService: TaskService;
|
|
1194
|
+
sessionService: SessionService;
|
|
1195
|
+
artifactService: ArtifactService;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
export function createStatusService(deps: StatusServiceDeps): StatusService;
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
## 11. Backend API 层
|
|
1202
|
+
|
|
1203
|
+
### 11.1 `src/backend/server.ts`
|
|
1204
|
+
|
|
1205
|
+
职责:
|
|
1206
|
+
|
|
1207
|
+
- 创建 Fastify server。
|
|
1208
|
+
- 注册 API routes。
|
|
1209
|
+
- 注册 WebSocket terminal bridge。
|
|
1210
|
+
- Serve frontend assets。
|
|
1211
|
+
|
|
1212
|
+
导出定义:
|
|
1213
|
+
|
|
1214
|
+
```ts
|
|
1215
|
+
export interface CreateServerOptions {
|
|
1216
|
+
host?: string;
|
|
1217
|
+
port?: number;
|
|
1218
|
+
staticDir?: string;
|
|
1219
|
+
dev?: boolean;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
export interface ServerDeps {
|
|
1223
|
+
projectService: ProjectService;
|
|
1224
|
+
taskService: TaskService;
|
|
1225
|
+
sessionService: SessionService;
|
|
1226
|
+
artifactService: ArtifactService;
|
|
1227
|
+
commandDispatcher: CommandDispatcher;
|
|
1228
|
+
statusService: StatusService;
|
|
1229
|
+
runtime: TerminalRuntime;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
export function createServer(deps: ServerDeps, options?: CreateServerOptions): Promise<FastifyInstance>;
|
|
1233
|
+
export async function startServer(options?: CreateServerOptions): Promise<{ url: string; close(): Promise<void> }>;
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
### 11.2 `src/backend/api/project-routes.ts`
|
|
1237
|
+
|
|
1238
|
+
Routes:
|
|
1239
|
+
|
|
1240
|
+
```text
|
|
1241
|
+
GET /api/health
|
|
1242
|
+
POST /api/projects/connect
|
|
1243
|
+
GET /api/projects/current
|
|
1244
|
+
GET /api/projects/harness
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
导出定义:
|
|
1248
|
+
|
|
1249
|
+
```ts
|
|
1250
|
+
export function registerProjectRoutes(app: FastifyInstance, deps: ProjectRouteDeps): void;
|
|
1251
|
+
|
|
1252
|
+
export interface ProjectRouteDeps {
|
|
1253
|
+
projectService: ProjectService;
|
|
1254
|
+
}
|
|
1255
|
+
```
|
|
1256
|
+
|
|
1257
|
+
### 11.3 `src/backend/api/task-routes.ts`
|
|
1258
|
+
|
|
1259
|
+
Routes:
|
|
1260
|
+
|
|
1261
|
+
```text
|
|
1262
|
+
GET /api/tasks
|
|
1263
|
+
POST /api/tasks
|
|
1264
|
+
GET /api/tasks/:taskSlug
|
|
1265
|
+
GET /api/tasks/:taskSlug/status
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
导出定义:
|
|
1269
|
+
|
|
1270
|
+
```ts
|
|
1271
|
+
export function registerTaskRoutes(app: FastifyInstance, deps: TaskRouteDeps): void;
|
|
1272
|
+
|
|
1273
|
+
export interface TaskRouteDeps {
|
|
1274
|
+
projectService: ProjectService;
|
|
1275
|
+
taskService: TaskService;
|
|
1276
|
+
statusService: StatusService;
|
|
1277
|
+
}
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1280
|
+
### 11.4 `src/backend/api/session-routes.ts`
|
|
1281
|
+
|
|
1282
|
+
Routes:
|
|
1283
|
+
|
|
1284
|
+
```text
|
|
1285
|
+
GET /api/tasks/:taskSlug/sessions
|
|
1286
|
+
POST /api/tasks/:taskSlug/sessions/:role/start
|
|
1287
|
+
POST /api/tasks/:taskSlug/sessions/:role/stop
|
|
1288
|
+
POST /api/tasks/:taskSlug/sessions/:role/resume
|
|
1289
|
+
POST /api/tasks/:taskSlug/sessions/:role/restart
|
|
1290
|
+
POST /api/tasks/:taskSlug/sessions/:role/dispatch
|
|
1291
|
+
```
|
|
1292
|
+
|
|
1293
|
+
导出定义:
|
|
1294
|
+
|
|
1295
|
+
```ts
|
|
1296
|
+
export function registerSessionRoutes(app: FastifyInstance, deps: SessionRouteDeps): void;
|
|
1297
|
+
|
|
1298
|
+
export interface SessionRouteDeps {
|
|
1299
|
+
projectService: ProjectService;
|
|
1300
|
+
sessionService: SessionService;
|
|
1301
|
+
commandDispatcher: CommandDispatcher;
|
|
1302
|
+
}
|
|
1303
|
+
```
|
|
1304
|
+
|
|
1305
|
+
### 11.5 `src/backend/api/artifact-routes.ts`
|
|
1306
|
+
|
|
1307
|
+
Routes:
|
|
1308
|
+
|
|
1309
|
+
```text
|
|
1310
|
+
GET /api/tasks/:taskSlug/artifacts
|
|
1311
|
+
GET /api/tasks/:taskSlug/artifacts/:artifactName
|
|
1312
|
+
GET /api/tasks/:taskSlug/role-commands/:role
|
|
1313
|
+
PUT /api/tasks/:taskSlug/role-commands/:role
|
|
1314
|
+
GET /api/tasks/:taskSlug/logs/:role
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
导出定义:
|
|
1318
|
+
|
|
1319
|
+
```ts
|
|
1320
|
+
export function registerArtifactRoutes(app: FastifyInstance, deps: ArtifactRouteDeps): void;
|
|
1321
|
+
|
|
1322
|
+
export interface ArtifactRouteDeps {
|
|
1323
|
+
projectService: ProjectService;
|
|
1324
|
+
taskService: TaskService;
|
|
1325
|
+
artifactService: ArtifactService;
|
|
1326
|
+
}
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
### 11.6 `src/backend/ws/terminal-ws.ts`
|
|
1330
|
+
|
|
1331
|
+
职责:
|
|
1332
|
+
|
|
1333
|
+
- 处理 `/ws/tasks/:taskSlug/sessions/:role`。
|
|
1334
|
+
- 将 runtime events 推送给前端。
|
|
1335
|
+
- 将前端 input/resize 写回 runtime。
|
|
1336
|
+
|
|
1337
|
+
导出定义:
|
|
1338
|
+
|
|
1339
|
+
```ts
|
|
1340
|
+
export interface TerminalWsDeps {
|
|
1341
|
+
projectService: ProjectService;
|
|
1342
|
+
sessionService: SessionService;
|
|
1343
|
+
runtime: TerminalRuntime;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
export function registerTerminalWebSocket(server: FastifyInstance, deps: TerminalWsDeps): void;
|
|
1347
|
+
|
|
1348
|
+
export function parseClientTerminalMessage(raw: string): ClientTerminalMessage;
|
|
1349
|
+
export function serializeServerTerminalMessage(message: ServerTerminalMessage): string;
|
|
1350
|
+
```
|
|
1351
|
+
|
|
1352
|
+
## 12. Frontend 层
|
|
1353
|
+
|
|
1354
|
+
### 12.1 `src/frontend/main.tsx`
|
|
1355
|
+
|
|
1356
|
+
职责:
|
|
1357
|
+
|
|
1358
|
+
- 挂载 React app。
|
|
1359
|
+
|
|
1360
|
+
导出定义:
|
|
1361
|
+
|
|
1362
|
+
```ts
|
|
1363
|
+
export function bootstrap(): void;
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
### 12.2 `src/frontend/app.tsx`
|
|
1367
|
+
|
|
1368
|
+
职责:
|
|
1369
|
+
|
|
1370
|
+
- 应用顶层路由和布局。
|
|
1371
|
+
|
|
1372
|
+
导出定义:
|
|
1373
|
+
|
|
1374
|
+
```tsx
|
|
1375
|
+
export function App(): JSX.Element;
|
|
1376
|
+
```
|
|
1377
|
+
|
|
1378
|
+
### 12.3 `src/frontend/state/api-client.ts`
|
|
1379
|
+
|
|
1380
|
+
职责:
|
|
1381
|
+
|
|
1382
|
+
- 封装 REST API。
|
|
1383
|
+
|
|
1384
|
+
导出定义:
|
|
1385
|
+
|
|
1386
|
+
```ts
|
|
1387
|
+
export interface ApiClient {
|
|
1388
|
+
connectProject(input: ConnectProjectRequest): Promise<ProjectSummary>;
|
|
1389
|
+
getCurrentProject(): Promise<ProjectSummary | null>;
|
|
1390
|
+
listTasks(): Promise<TaskRecord[]>;
|
|
1391
|
+
createTask(input: CreateTaskRequest): Promise<TaskRecord>;
|
|
1392
|
+
getTask(taskSlug: string): Promise<TaskRecord>;
|
|
1393
|
+
getTaskStatus(taskSlug: string): Promise<TaskStatusReport>;
|
|
1394
|
+
listSessions(taskSlug: string): Promise<RoleSessionRecord[]>;
|
|
1395
|
+
startRoleSession(taskSlug: string, role: RoleName, input?: StartRoleSessionRequest): Promise<RoleSessionRecord>;
|
|
1396
|
+
stopRoleSession(taskSlug: string, role: RoleName): Promise<RoleSessionRecord>;
|
|
1397
|
+
restartRoleSession(taskSlug: string, role: RoleName, input?: StartRoleSessionRequest): Promise<RoleSessionRecord>;
|
|
1398
|
+
dispatchRoleCommand(taskSlug: string, role: DispatchableRole): Promise<DispatchRoleCommandResult>;
|
|
1399
|
+
listArtifacts(taskSlug: string): Promise<ArtifactSummary>;
|
|
1400
|
+
readRoleCommand(taskSlug: string, role: DispatchableRole): Promise<string>;
|
|
1401
|
+
saveRoleCommand(taskSlug: string, role: DispatchableRole, content: string): Promise<void>;
|
|
1402
|
+
readLog(taskSlug: string, role: RoleName): Promise<string>;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
export function createApiClient(baseUrl?: string): ApiClient;
|
|
1406
|
+
```
|
|
1407
|
+
|
|
1408
|
+
### 12.4 `src/frontend/terminal/terminal-client.ts`
|
|
1409
|
+
|
|
1410
|
+
职责:
|
|
1411
|
+
|
|
1412
|
+
- 封装 terminal WebSocket。
|
|
1413
|
+
|
|
1414
|
+
导出定义:
|
|
1415
|
+
|
|
1416
|
+
```ts
|
|
1417
|
+
export interface TerminalClient {
|
|
1418
|
+
connect(): void;
|
|
1419
|
+
disconnect(): void;
|
|
1420
|
+
sendInput(data: string): void;
|
|
1421
|
+
resize(cols: number, rows: number): void;
|
|
1422
|
+
onMessage(listener: (message: ServerTerminalMessage) => void): Unsubscribe;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
export function createTerminalClient(input: CreateTerminalClientInput): TerminalClient;
|
|
1426
|
+
|
|
1427
|
+
export interface CreateTerminalClientInput {
|
|
1428
|
+
taskSlug: string;
|
|
1429
|
+
role: RoleName;
|
|
1430
|
+
baseUrl?: string;
|
|
1431
|
+
}
|
|
1432
|
+
```
|
|
1433
|
+
|
|
1434
|
+
### 12.5 `src/frontend/terminal/xterm-view.tsx`
|
|
1435
|
+
|
|
1436
|
+
职责:
|
|
1437
|
+
|
|
1438
|
+
- 渲染 xterm.js。
|
|
1439
|
+
- 连接 TerminalClient。
|
|
1440
|
+
- 处理 fit、resize、input、output。
|
|
1441
|
+
|
|
1442
|
+
导出定义:
|
|
1443
|
+
|
|
1444
|
+
```tsx
|
|
1445
|
+
export interface XtermViewProps {
|
|
1446
|
+
taskSlug: string;
|
|
1447
|
+
role: RoleName;
|
|
1448
|
+
active: boolean;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
export function XtermView(props: XtermViewProps): JSX.Element;
|
|
1452
|
+
```
|
|
1453
|
+
|
|
1454
|
+
### 12.6 `src/frontend/components/session-console.tsx`
|
|
1455
|
+
|
|
1456
|
+
职责:
|
|
1457
|
+
|
|
1458
|
+
- 展示单个 role session。
|
|
1459
|
+
- 在 Start / Restart 上方提供三档权限模式选择。
|
|
1460
|
+
- 未启动时显示 Start。
|
|
1461
|
+
- 已启动时显示 terminal。
|
|
1462
|
+
|
|
1463
|
+
导出定义:
|
|
1464
|
+
|
|
1465
|
+
```tsx
|
|
1466
|
+
export interface SessionConsoleProps {
|
|
1467
|
+
taskSlug: string;
|
|
1468
|
+
role: RoleName;
|
|
1469
|
+
session?: RoleSessionRecord;
|
|
1470
|
+
active: boolean;
|
|
1471
|
+
permissionMode: ClaudePermissionMode;
|
|
1472
|
+
onPermissionModeChange(mode: ClaudePermissionMode): void;
|
|
1473
|
+
onStart(role: RoleName): Promise<void>;
|
|
1474
|
+
onResume(role: RoleName): Promise<void>;
|
|
1475
|
+
onStop(role: RoleName): Promise<void>;
|
|
1476
|
+
onRestart(role: RoleName): Promise<void>;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
export function SessionConsole(props: SessionConsoleProps): JSX.Element;
|
|
1480
|
+
```
|
|
1481
|
+
|
|
1482
|
+
### 12.7 `src/frontend/components/role-session-tabs.tsx`
|
|
1483
|
+
|
|
1484
|
+
职责:
|
|
1485
|
+
|
|
1486
|
+
- 渲染 PM / Architect / Coder / Reviewer tabs。
|
|
1487
|
+
- 展示 status badge。
|
|
1488
|
+
|
|
1489
|
+
导出定义:
|
|
1490
|
+
|
|
1491
|
+
```tsx
|
|
1492
|
+
export interface RoleSessionTabsProps {
|
|
1493
|
+
activeRole: RoleName;
|
|
1494
|
+
sessions: RoleSessionRecord[];
|
|
1495
|
+
onRoleChange(role: RoleName): void;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
export function RoleSessionTabs(props: RoleSessionTabsProps): JSX.Element;
|
|
1499
|
+
```
|
|
1500
|
+
|
|
1501
|
+
### 12.8 `src/frontend/components/event-log.tsx`
|
|
1502
|
+
|
|
1503
|
+
职责:
|
|
1504
|
+
|
|
1505
|
+
- 展示产品级事件摘要。
|
|
1506
|
+
|
|
1507
|
+
导出定义:
|
|
1508
|
+
|
|
1509
|
+
```tsx
|
|
1510
|
+
export interface EventLogProps {
|
|
1511
|
+
events: TerminalEvent[];
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
export function EventLog(props: EventLogProps): JSX.Element;
|
|
1515
|
+
```
|
|
1516
|
+
|
|
1517
|
+
### 12.9 `src/frontend/routes/project-dashboard.tsx`
|
|
1518
|
+
|
|
1519
|
+
职责:
|
|
1520
|
+
|
|
1521
|
+
- 展示 repo 连接表单、任务列表和 harness health。
|
|
1522
|
+
|
|
1523
|
+
导出定义:
|
|
1524
|
+
|
|
1525
|
+
```tsx
|
|
1526
|
+
export function ProjectDashboard(): JSX.Element;
|
|
1527
|
+
```
|
|
1528
|
+
|
|
1529
|
+
### 12.10 `src/frontend/routes/task-workspace.tsx`
|
|
1530
|
+
|
|
1531
|
+
职责:
|
|
1532
|
+
|
|
1533
|
+
- 任务运行时主界面。
|
|
1534
|
+
- 组合 TaskNav、RoleSessionTabs、SessionConsole、EventLog。
|
|
1535
|
+
- 不渲染独立 ArtifactPanel;handoff files 保留在任务目录中。
|
|
1536
|
+
|
|
1537
|
+
导出定义:
|
|
1538
|
+
|
|
1539
|
+
```tsx
|
|
1540
|
+
export interface TaskWorkspaceProps {
|
|
1541
|
+
taskSlug: string;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
export function TaskWorkspace(props: TaskWorkspaceProps): JSX.Element;
|
|
1545
|
+
```
|
|
1546
|
+
|
|
1547
|
+
## 13. Templates
|
|
1548
|
+
|
|
1549
|
+
### 13.1 `src/backend/templates/handoff.ts`
|
|
1550
|
+
|
|
1551
|
+
导出定义:
|
|
1552
|
+
|
|
1553
|
+
```ts
|
|
1554
|
+
export function renderArchitecturePlanTemplate(taskSlug: string): string;
|
|
1555
|
+
export function renderImplementationLogTemplate(taskSlug: string): string;
|
|
1556
|
+
export function renderValidationLogTemplate(taskSlug: string): string;
|
|
1557
|
+
export function renderReviewReportTemplate(taskSlug: string): string;
|
|
1558
|
+
```
|
|
1559
|
+
|
|
1560
|
+
### 13.2 `src/backend/templates/role-command.ts`
|
|
1561
|
+
|
|
1562
|
+
导出定义:
|
|
1563
|
+
|
|
1564
|
+
```ts
|
|
1565
|
+
export function renderRoleCommandTemplate(taskSlug: string, role: DispatchableRole): string;
|
|
1566
|
+
export function renderDispatchInstruction(commandPath: string): string;
|
|
1567
|
+
```
|
|
1568
|
+
|
|
1569
|
+
`renderDispatchInstruction` 必须返回单行短指令:
|
|
1570
|
+
|
|
1571
|
+
```text
|
|
1572
|
+
Please read and execute the role command at: <commandPath>
|
|
1573
|
+
```
|
|
1574
|
+
|
|
1575
|
+
## 14. 核心调用链
|
|
1576
|
+
|
|
1577
|
+
### 14.1 启动应用
|
|
1578
|
+
|
|
1579
|
+
```text
|
|
1580
|
+
main
|
|
1581
|
+
-> startServer
|
|
1582
|
+
-> create services/adapters/runtime
|
|
1583
|
+
-> register REST routes
|
|
1584
|
+
-> register terminal WebSocket
|
|
1585
|
+
-> serve frontend
|
|
1586
|
+
```
|
|
1587
|
+
|
|
1588
|
+
### 14.2 连接 repo
|
|
1589
|
+
|
|
1590
|
+
```text
|
|
1591
|
+
ProjectDashboard
|
|
1592
|
+
-> api.connectProject
|
|
1593
|
+
-> POST /api/projects/connect
|
|
1594
|
+
-> projectService.connectProject
|
|
1595
|
+
-> git.getRepoRoot
|
|
1596
|
+
-> git.getCurrentBranch
|
|
1597
|
+
-> git.isDirty
|
|
1598
|
+
-> claude.isAvailable
|
|
1599
|
+
-> fs.writeJsonAtomic(.vcm/config.json)
|
|
1600
|
+
```
|
|
1601
|
+
|
|
1602
|
+
### 14.3 创建任务
|
|
1603
|
+
|
|
1604
|
+
```text
|
|
1605
|
+
ProjectDashboard / TaskWorkspace
|
|
1606
|
+
-> api.createTask
|
|
1607
|
+
-> POST /api/tasks
|
|
1608
|
+
-> taskService.createTask
|
|
1609
|
+
-> assertValidTaskSlug
|
|
1610
|
+
-> artifactService.ensureHandoffStructure
|
|
1611
|
+
-> artifactService.createArtifactTemplates
|
|
1612
|
+
-> fs.writeJsonAtomic(.vcm/tasks/<task-slug>.json)
|
|
1613
|
+
```
|
|
1614
|
+
|
|
1615
|
+
### 14.4 启动 role session
|
|
1616
|
+
|
|
1617
|
+
```text
|
|
1618
|
+
SessionConsole Start
|
|
1619
|
+
-> api.startRoleSession
|
|
1620
|
+
-> POST /api/tasks/:taskSlug/sessions/:role/start
|
|
1621
|
+
-> sessionService.startRoleSession
|
|
1622
|
+
-> claude.buildRoleStartCommand
|
|
1623
|
+
-> runtime.createSession
|
|
1624
|
+
-> node-pty spawn
|
|
1625
|
+
-> registry.upsert
|
|
1626
|
+
-> write session metadata
|
|
1627
|
+
```
|
|
1628
|
+
|
|
1629
|
+
### 14.5 Terminal 输入输出
|
|
1630
|
+
|
|
1631
|
+
```text
|
|
1632
|
+
XtermView
|
|
1633
|
+
-> TerminalClient WebSocket
|
|
1634
|
+
-> input message
|
|
1635
|
+
-> terminal-ws
|
|
1636
|
+
-> runtime.write
|
|
1637
|
+
-> node-pty
|
|
1638
|
+
-> output event
|
|
1639
|
+
-> append role log
|
|
1640
|
+
-> WebSocket output message
|
|
1641
|
+
-> xterm.write
|
|
1642
|
+
```
|
|
1643
|
+
|
|
1644
|
+
### 14.6 下发 role command
|
|
1645
|
+
|
|
1646
|
+
```text
|
|
1647
|
+
Role toolbar Send Command
|
|
1648
|
+
-> api.dispatchRoleCommand
|
|
1649
|
+
-> POST /api/tasks/:taskSlug/sessions/:role/dispatch
|
|
1650
|
+
-> commandDispatcher.dispatchRoleCommand
|
|
1651
|
+
-> artifactService.readRoleCommand
|
|
1652
|
+
-> sessionService.getRoleSession
|
|
1653
|
+
-> runtime.write(short instruction)
|
|
1654
|
+
-> registry event
|
|
1655
|
+
```
|
|
1656
|
+
|
|
1657
|
+
### 14.7 Handoff files
|
|
1658
|
+
|
|
1659
|
+
V1 主界面不展示 artifact 状态。handoff files 和 role commands 仍由 backend templates / services 管理,供 Claude Code sessions 和 dispatch 流程使用。
|
|
1660
|
+
|
|
1661
|
+
## 15. 测试计划
|
|
1662
|
+
|
|
1663
|
+
### 15.1 Unit Tests
|
|
1664
|
+
|
|
1665
|
+
`tests/unit/shared/slug-check.test.ts`
|
|
1666
|
+
|
|
1667
|
+
- accepts valid task slugs。
|
|
1668
|
+
- rejects uppercase、underscore、space、path traversal。
|
|
1669
|
+
- suggests normalized slugs。
|
|
1670
|
+
|
|
1671
|
+
`tests/unit/shared/artifact-check.test.ts`
|
|
1672
|
+
|
|
1673
|
+
- parses headings。
|
|
1674
|
+
- detects missing headings。
|
|
1675
|
+
- validates handoff templates。
|
|
1676
|
+
- validates `validation-log` not-run reason。
|
|
1677
|
+
|
|
1678
|
+
`tests/unit/backend/artifact-service.test.ts`
|
|
1679
|
+
|
|
1680
|
+
- creates handoff directory。
|
|
1681
|
+
- creates role command files。
|
|
1682
|
+
- does not overwrite existing files by default。
|
|
1683
|
+
- returns artifact summary statuses。
|
|
1684
|
+
|
|
1685
|
+
`tests/unit/backend/command-dispatcher.test.ts`
|
|
1686
|
+
|
|
1687
|
+
- rejects missing command。
|
|
1688
|
+
- rejects empty command。
|
|
1689
|
+
- rejects not-started target session。
|
|
1690
|
+
- writes only short instruction to runtime。
|
|
1691
|
+
|
|
1692
|
+
`tests/unit/backend/session-registry.test.ts`
|
|
1693
|
+
|
|
1694
|
+
- upserts sessions。
|
|
1695
|
+
- finds by task + role。
|
|
1696
|
+
- updates status。
|
|
1697
|
+
- removes sessions。
|
|
1698
|
+
|
|
1699
|
+
`tests/unit/frontend/api-client.test.ts`
|
|
1700
|
+
|
|
1701
|
+
- unwraps successful API responses。
|
|
1702
|
+
- throws useful errors for API failures。
|
|
1703
|
+
|
|
1704
|
+
`tests/unit/frontend/terminal-client.test.ts`
|
|
1705
|
+
|
|
1706
|
+
- serializes input and resize messages。
|
|
1707
|
+
- dispatches output/status/exit messages to listeners。
|
|
1708
|
+
|
|
1709
|
+
### 15.2 Integration Tests
|
|
1710
|
+
|
|
1711
|
+
`tests/integration/api/project-routes.test.ts`
|
|
1712
|
+
|
|
1713
|
+
- connects repo fixture。
|
|
1714
|
+
- writes `.vcm/config.json`。
|
|
1715
|
+
- returns branch and dirty warning。
|
|
1716
|
+
|
|
1717
|
+
`tests/integration/api/task-routes.test.ts`
|
|
1718
|
+
|
|
1719
|
+
- creates task。
|
|
1720
|
+
- writes `.vcm/tasks/<task-slug>.json`。
|
|
1721
|
+
- creates handoff artifacts。
|
|
1722
|
+
|
|
1723
|
+
`tests/integration/runtime/node-pty-runtime.test.ts`
|
|
1724
|
+
|
|
1725
|
+
- starts a simple shell command fixture。
|
|
1726
|
+
- streams output。
|
|
1727
|
+
- writes log file。
|
|
1728
|
+
- handles exit。
|
|
1729
|
+
|
|
1730
|
+
`tests/integration/api/session-routes.test.ts`
|
|
1731
|
+
|
|
1732
|
+
- starts role session with fake runtime。
|
|
1733
|
+
- stops role session。
|
|
1734
|
+
- restarts role session。
|
|
1735
|
+
- dispatches role command.
|
|
1736
|
+
|
|
1737
|
+
### 15.3 E2E Tests
|
|
1738
|
+
|
|
1739
|
+
`tests/e2e/task-workspace.spec.ts`
|
|
1740
|
+
|
|
1741
|
+
- open GUI。
|
|
1742
|
+
- connect temp repo。
|
|
1743
|
+
- create task。
|
|
1744
|
+
- see Task Workspace。
|
|
1745
|
+
- start fake project-manager session。
|
|
1746
|
+
- see terminal output。
|
|
1747
|
+
- switch to architect tab。
|
|
1748
|
+
- see Start button。
|
|
1749
|
+
- verify the main workspace has no right-side artifact panel。
|
|
1750
|
+
|
|
1751
|
+
V1 e2e 可以使用 fake Claude command,避免真实消耗 Claude Code tokens。
|
|
1752
|
+
|
|
1753
|
+
### 15.4 Manual Smoke Test
|
|
1754
|
+
|
|
1755
|
+
在真实 repo 中执行:
|
|
1756
|
+
|
|
1757
|
+
```text
|
|
1758
|
+
npm install
|
|
1759
|
+
npm run dev
|
|
1760
|
+
open http://localhost:5173
|
|
1761
|
+
Select repo
|
|
1762
|
+
Create demo-task
|
|
1763
|
+
Start project-manager
|
|
1764
|
+
Start architect
|
|
1765
|
+
Type in PM terminal
|
|
1766
|
+
Send architect command
|
|
1767
|
+
Verify logs/architect.log
|
|
1768
|
+
Verify artifact status
|
|
1769
|
+
Restart coder
|
|
1770
|
+
Refresh browser
|
|
1771
|
+
Verify session state recovers
|
|
1772
|
+
```
|
|
1773
|
+
|
|
1774
|
+
## 16. 实施里程碑
|
|
1775
|
+
|
|
1776
|
+
### Milestone 1: Project Reshape and Local GUI Shell
|
|
1777
|
+
|
|
1778
|
+
文件:
|
|
1779
|
+
|
|
1780
|
+
- `package.json`
|
|
1781
|
+
- `tsconfig.json`
|
|
1782
|
+
- `tsconfig.node.json`
|
|
1783
|
+
- `vite.config.ts`
|
|
1784
|
+
- `src/main.ts`
|
|
1785
|
+
- `src/backend/server.ts`
|
|
1786
|
+
- `src/frontend/main.tsx`
|
|
1787
|
+
- `src/frontend/app.tsx`
|
|
1788
|
+
- `src/frontend/routes/project-dashboard.tsx`
|
|
1789
|
+
|
|
1790
|
+
验收:
|
|
1791
|
+
|
|
1792
|
+
- `npm run dev` 启动 backend + frontend。
|
|
1793
|
+
- 浏览器打开 Project Dashboard。
|
|
1794
|
+
- `/api/health` 返回 ok。
|
|
1795
|
+
|
|
1796
|
+
### Milestone 2: Shared Types, Validation, and Artifacts
|
|
1797
|
+
|
|
1798
|
+
文件:
|
|
1799
|
+
|
|
1800
|
+
- `src/shared/types/*.ts`
|
|
1801
|
+
- `src/shared/validation/*.ts`
|
|
1802
|
+
- `src/backend/templates/*.ts`
|
|
1803
|
+
- `src/backend/services/artifact-service.ts`
|
|
1804
|
+
- `src/backend/services/task-service.ts`
|
|
1805
|
+
- `src/backend/api/task-routes.ts`
|
|
1806
|
+
|
|
1807
|
+
验收:
|
|
1808
|
+
|
|
1809
|
+
- GUI 可以创建 task。
|
|
1810
|
+
- `.ai/handoffs/<task-slug>/` 被创建。
|
|
1811
|
+
- Handoff artifacts 在任务目录中被创建。
|
|
1812
|
+
|
|
1813
|
+
### Milestone 3: Repo Connect and Project Service
|
|
1814
|
+
|
|
1815
|
+
文件:
|
|
1816
|
+
|
|
1817
|
+
- `src/backend/adapters/*.ts`
|
|
1818
|
+
- `src/backend/services/project-service.ts`
|
|
1819
|
+
- `src/backend/validation/environment-check.ts`
|
|
1820
|
+
- `src/backend/api/project-routes.ts`
|
|
1821
|
+
- `src/frontend/components/repo-connect-form.tsx`
|
|
1822
|
+
|
|
1823
|
+
验收:
|
|
1824
|
+
|
|
1825
|
+
- GUI 可以选择/输入 repo path。
|
|
1826
|
+
- backend 检查 Git repo 和 Claude Code。
|
|
1827
|
+
- `.vcm/config.json` 被创建。
|
|
1828
|
+
- main/master 和 dirty state 显示 warning。
|
|
1829
|
+
|
|
1830
|
+
### Milestone 4: Embedded Terminal Runtime
|
|
1831
|
+
|
|
1832
|
+
文件:
|
|
1833
|
+
|
|
1834
|
+
- `src/backend/runtime/terminal-runtime.ts`
|
|
1835
|
+
- `src/backend/runtime/node-pty-runtime.ts`
|
|
1836
|
+
- `src/backend/runtime/session-registry.ts`
|
|
1837
|
+
- `src/backend/ws/terminal-ws.ts`
|
|
1838
|
+
- `src/frontend/terminal/terminal-client.ts`
|
|
1839
|
+
- `src/frontend/terminal/xterm-view.tsx`
|
|
1840
|
+
- `src/frontend/components/session-console.tsx`
|
|
1841
|
+
|
|
1842
|
+
验收:
|
|
1843
|
+
|
|
1844
|
+
- GUI 可以启动 fake role session。
|
|
1845
|
+
- xterm.js 显示 output。
|
|
1846
|
+
- 用户输入能写入 backend runtime。
|
|
1847
|
+
- output 写入 raw log。
|
|
1848
|
+
- resize 工作。
|
|
1849
|
+
|
|
1850
|
+
### Milestone 5: Role Session Cockpit
|
|
1851
|
+
|
|
1852
|
+
文件:
|
|
1853
|
+
|
|
1854
|
+
- `src/backend/services/session-service.ts`
|
|
1855
|
+
- `src/backend/api/session-routes.ts`
|
|
1856
|
+
- `src/frontend/components/role-session-tabs.tsx`
|
|
1857
|
+
- `src/frontend/components/session-toolbar.tsx`
|
|
1858
|
+
- `src/frontend/components/status-badge.tsx`
|
|
1859
|
+
- `src/frontend/routes/task-workspace.tsx`
|
|
1860
|
+
- `src/frontend/state/session-store.ts`
|
|
1861
|
+
|
|
1862
|
+
验收:
|
|
1863
|
+
|
|
1864
|
+
- PM / Architect / Coder / Reviewer tabs 可切换。
|
|
1865
|
+
- 每个 role 可 start / stop / restart。
|
|
1866
|
+
- 状态 badge 正确显示。
|
|
1867
|
+
- 页面刷新后可重新加载 task/session 状态。
|
|
1868
|
+
|
|
1869
|
+
### Milestone 6: GUI Role Command Dispatch
|
|
1870
|
+
|
|
1871
|
+
文件:
|
|
1872
|
+
|
|
1873
|
+
- `src/backend/services/command-dispatcher.ts`
|
|
1874
|
+
- `src/frontend/components/event-log.tsx`
|
|
1875
|
+
|
|
1876
|
+
验收:
|
|
1877
|
+
|
|
1878
|
+
- 用户点击目标 role toolbar 的 Send Command。
|
|
1879
|
+
- backend 写入短指令到 architect runtime。
|
|
1880
|
+
- dispatch event 出现在 Event Log。
|
|
1881
|
+
- 不发送未落盘长 prompt。
|
|
1882
|
+
|
|
1883
|
+
### Milestone 7: Acceptance and Hardening
|
|
1884
|
+
|
|
1885
|
+
内容:
|
|
1886
|
+
|
|
1887
|
+
- unit tests。
|
|
1888
|
+
- integration tests。
|
|
1889
|
+
- e2e smoke。
|
|
1890
|
+
- README 更新。
|
|
1891
|
+
- GUI 错误态。
|
|
1892
|
+
- empty/missing/incomplete artifact 状态。
|
|
1893
|
+
- Claude Code 缺失提示。
|
|
1894
|
+
- process crashed 提示。
|
|
1895
|
+
|
|
1896
|
+
验收:
|
|
1897
|
+
|
|
1898
|
+
- `npm run typecheck` 通过。
|
|
1899
|
+
- `npm test` 通过。
|
|
1900
|
+
- `npm run build` 通过。
|
|
1901
|
+
- `npm run e2e` 通过或有明确 fake Claude 限制说明。
|
|
1902
|
+
|
|
1903
|
+
## 17. 最终 V1 验收清单
|
|
1904
|
+
|
|
1905
|
+
- [ ] GUI 可以启动。
|
|
1906
|
+
- [ ] 用户可以连接本地 Git repo。
|
|
1907
|
+
- [ ] GUI 显示 repo path、branch、dirty warning。
|
|
1908
|
+
- [ ] 用户可以创建 task workspace。
|
|
1909
|
+
- [ ] 系统创建 `.vcm/config.json`。
|
|
1910
|
+
- [ ] 系统创建 `.vcm/tasks/<task-slug>.json`。
|
|
1911
|
+
- [ ] 系统创建 `.ai/handoffs/<task-slug>/role-commands/`。
|
|
1912
|
+
- [ ] 系统创建 `.ai/handoffs/<task-slug>/logs/`。
|
|
1913
|
+
- [ ] 系统创建 architecture / implementation / validation / review artifact templates。
|
|
1914
|
+
- [ ] GUI 显示 PM / Architect / Coder / Reviewer tabs。
|
|
1915
|
+
- [ ] 用户可以启动 project-manager session。
|
|
1916
|
+
- [ ] 用户可以启动 architect session。
|
|
1917
|
+
- [ ] embedded terminal 可以显示 Claude Code output。
|
|
1918
|
+
- [ ] 用户可以直接在 embedded terminal 中输入。
|
|
1919
|
+
- [ ] terminal output 被保存到 role log。
|
|
1920
|
+
- [ ] 用户可以从 GUI 发送 role command 到目标 role session。
|
|
1921
|
+
- [ ] backend 只发送短指令,不粘贴完整长 prompt。
|
|
1922
|
+
- [ ] 用户可以 stop / restart role session。
|
|
1923
|
+
- [ ] 页面刷新后可以恢复 task/session 可见状态。
|
|
1924
|
+
- [ ] Claude Code 缺失时 GUI 有清晰提示。
|
|
1925
|
+
- [ ] 进程 crashed/exited 时 GUI 有清晰提示。
|
|
1926
|
+
|
|
1927
|
+
## 18. 需要延后到 V2 的接口
|
|
1928
|
+
|
|
1929
|
+
V1 文件中可以预留类型或接口,但不实现完整功能:
|
|
1930
|
+
|
|
1931
|
+
- `ReviewAdapter`:后续接 Cross-Model Reviewer。
|
|
1932
|
+
- `ValidationRunner`:后续自动运行 validation commands。
|
|
1933
|
+
- `WorktreeManager`:后续实现 one task -> one branch -> one worktree。
|
|
1934
|
+
- `SessionPersistenceService`:后续增强 backend lifecycle、session registry 持久化、raw log replay 和恢复体验。
|
|
1935
|
+
- `DesktopShell`:后续用 Electron 或 Tauri 打包。
|
|
1936
|
+
- `PermissionHookManager`:后续生成 role-specific Claude Code permission hooks。
|
|
1937
|
+
|
|
1938
|
+
V1 的判断标准是:
|
|
1939
|
+
|
|
1940
|
+
```text
|
|
1941
|
+
少做智能判断
|
|
1942
|
+
多做状态可见
|
|
1943
|
+
少自动修改代码
|
|
1944
|
+
多沉淀 artifacts
|
|
1945
|
+
少解析终端语义
|
|
1946
|
+
多保留 raw logs
|
|
1947
|
+
少暴露终端编排细节
|
|
1948
|
+
多提供 GUI 操作入口
|
|
1949
|
+
```
|