vibe-coding-master 0.0.16 → 0.2.0
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 +74 -41
- package/dist/backend/api/artifact-routes.js +5 -5
- package/dist/backend/api/harness-routes.js +8 -0
- package/dist/backend/api/message-routes.js +4 -4
- package/dist/backend/api/round-routes.js +4 -2
- package/dist/backend/server.js +8 -2
- package/dist/backend/services/artifact-service.js +12 -12
- package/dist/backend/services/claude-hook-service.js +1 -1
- package/dist/backend/services/harness-service.js +579 -5
- package/dist/backend/services/message-service.js +71 -137
- package/dist/backend/services/project-service.js +4 -1
- package/dist/backend/services/round-service.js +14 -52
- package/dist/backend/services/session-service.js +1 -3
- package/dist/backend/services/task-service.js +16 -17
- package/dist/backend/templates/handoff.js +64 -26
- package/dist/backend/templates/harness/architect-agent.js +42 -12
- package/dist/backend/templates/harness/claude-root.js +42 -18
- package/dist/backend/templates/harness/coder-agent.js +15 -11
- package/dist/backend/templates/harness/known-issues-doc.js +22 -0
- package/dist/backend/templates/harness/project-manager-agent.js +66 -15
- package/dist/backend/templates/harness/pull-request-template.js +29 -0
- package/dist/backend/templates/harness/reviewer-agent.js +40 -12
- package/dist/backend/templates/harness/vcm-final-acceptance-skill.js +105 -0
- package/dist/backend/templates/harness/vcm-harness-bootstrap-skill.js +78 -0
- package/dist/backend/templates/harness/vcm-long-running-validation-skill.js +50 -0
- package/dist/backend/templates/harness/vcm-route-message-skill.js +86 -0
- package/dist/backend/templates/message-envelope.js +1 -0
- package/dist/backend/templates/role-command.js +7 -1
- package/dist/shared/validation/artifact-check.js +14 -9
- package/dist-frontend/assets/index-CrY5Ryps.js +90 -0
- package/dist-frontend/assets/index-CvvtrrCN.css +32 -0
- package/dist-frontend/index.html +2 -2
- package/docs/cc-best-practices.md +434 -192
- package/docs/full-harness-baseline.md +254 -0
- package/docs/product-design.md +31 -28
- package/docs/v0.2-implementation-plan.md +379 -0
- package/docs/vcm-cc-best-practices.md +449 -0
- package/package.json +3 -1
- package/scripts/harness-tools/generate-module-index +298 -0
- package/scripts/harness-tools/generate-public-surface +692 -0
- package/scripts/install-vcm-harness.mjs +1607 -0
- package/scripts/uninstall-vcm-harness.mjs +490 -0
- package/scripts/verify-package.mjs +4 -0
- package/dist-frontend/assets/index-CvtyKEfS.js +0 -89
- package/dist-frontend/assets/index-jEkUTnIY.css +0 -32
- package/docs/v1-architecture-design.md +0 -1009
- package/docs/v1-implementation-plan.md +0 -1376
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ VCM is designed for long-running coding work where one Claude Code conversation
|
|
|
11
11
|
|
|
12
12
|
Each role runs as a real Claude Code process inside an embedded terminal. The GUI lets the user start, stop, resume, restart, switch, observe, and manually intervene in those sessions without juggling separate terminal windows.
|
|
13
13
|
|
|
14
|
-
## Current
|
|
14
|
+
## Current Capabilities
|
|
15
15
|
|
|
16
16
|
- GUI-first task workspace.
|
|
17
17
|
- Collapsible sidebar with repository connection, settings, harness status, task creation, and task list.
|
|
@@ -25,7 +25,9 @@ Each role runs as a real Claude Code process inside an embedded terminal. The GU
|
|
|
25
25
|
- `--dangerously-skip-permissions`
|
|
26
26
|
- PM-mediated role messaging through VCM-dispatched route files.
|
|
27
27
|
- Manual and automatic orchestration modes.
|
|
28
|
-
- VCM harness
|
|
28
|
+
- Two-stage VCM harness setup: deterministic fixed install plus AI-assisted bootstrap.
|
|
29
|
+
- VCM-managed root rules, four role agents, repo-local VCM skills, Claude Code hooks, generated-context tools, and PR template.
|
|
30
|
+
- Rust generated context for module indexing and crate-external public surface indexing.
|
|
29
31
|
- Translation panel powered by an OpenAI-compatible low-cost model.
|
|
30
32
|
- Durable task state, session state, raw terminal logs, handoff artifacts, and message history.
|
|
31
33
|
|
|
@@ -134,14 +136,15 @@ Important container notes:
|
|
|
134
136
|
1. Start VCM.
|
|
135
137
|
2. Open the GUI.
|
|
136
138
|
3. In the sidebar, open `Repository Path`, enter a repository path or choose one from `Recent`, then click `Connect`.
|
|
137
|
-
4. Review `VCM Harness`; if files need install/update, click `Install / Update`.
|
|
138
|
-
5.
|
|
139
|
-
6.
|
|
140
|
-
7.
|
|
141
|
-
8.
|
|
142
|
-
9.
|
|
143
|
-
10.
|
|
144
|
-
11.
|
|
139
|
+
4. Review `VCM Harness`; if fixed files need install/update, click `Install / Update`.
|
|
140
|
+
5. If bootstrap checks are incomplete, click `Run Bootstrap` and let the visible Claude Code bootstrap session fill project-specific docs and generated context.
|
|
141
|
+
6. Review and commit harness changes when they look right.
|
|
142
|
+
7. Create a task from `New Task` with a single task name.
|
|
143
|
+
8. Select the task from `Tasks`.
|
|
144
|
+
9. Use the role tabs in the task header to switch between `Project Manager`, `Architect`, `Coder`, and `Reviewer`.
|
|
145
|
+
10. Choose the permission mode for the active role.
|
|
146
|
+
11. Click `Start`, `Resume`, `Restart`, or `Stop` as needed.
|
|
147
|
+
12. Talk mostly to `project-manager`; let PM coordinate the other roles through VCM messaging.
|
|
145
148
|
|
|
146
149
|
The recommended flow is:
|
|
147
150
|
|
|
@@ -171,13 +174,13 @@ The `Create worktree and branch` option is selected by default when creating a t
|
|
|
171
174
|
|
|
172
175
|
VCM will not create worktrees per role. `project-manager`, `architect`, `coder`, and `reviewer` for the same task share the same task worktree.
|
|
173
176
|
|
|
174
|
-
The user can turn this option off. In that mode, VCM creates
|
|
177
|
+
The user can turn this option off. In that mode, VCM creates app-local task metadata, creates the handoff structure in the connected repository, records the current branch, and starts role sessions from the connected repository path.
|
|
175
178
|
|
|
176
179
|
VCM will not offer a separate `Create task worktree` button after a task exists, and a task should not be switched to another branch/worktree mode after creation.
|
|
177
180
|
|
|
178
181
|
Because worktrees live under `.claude/worktrees/`, the connected repository must ignore both `.ai/vcm/` and `.claude/worktrees/`. 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`.
|
|
179
182
|
|
|
180
|
-
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
|
|
183
|
+
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 app-local task record, 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.
|
|
181
184
|
|
|
182
185
|
## Sidebar UI
|
|
183
186
|
|
|
@@ -186,7 +189,7 @@ The left sidebar is intentionally compact and collapsible:
|
|
|
186
189
|
- `Repository Path`: path input on one row; `Recent` and `Connect` on the next row.
|
|
187
190
|
- `Repository`: connected path, branch, and working tree state. `Working tree: uncommitted changes` means `git status --porcelain` is not empty.
|
|
188
191
|
- `Settings`: `Theme`, `Round alert`, `Try alert`, `Messages`, and `Events`.
|
|
189
|
-
- `VCM Harness`: status
|
|
192
|
+
- `VCM Harness`: fixed-install status, bootstrap completion checks, and the bootstrap terminal when one is running.
|
|
190
193
|
- `New Task`: one `task name` input.
|
|
191
194
|
- `Tasks`: task list and task status.
|
|
192
195
|
|
|
@@ -194,7 +197,9 @@ All sidebar sections are collapsed by default. When no task is selected, `Reposi
|
|
|
194
197
|
|
|
195
198
|
## Translation
|
|
196
199
|
|
|
197
|
-
The
|
|
200
|
+
The task header has a global `Translate` button next to `Close Task`. It opens a translation panel beside the embedded terminal for the role consoles and keeps the same on/off setting while switching roles. The terminal and translation panel split the available width evenly.
|
|
201
|
+
|
|
202
|
+
The task header does not include a manual `Refresh` button. Task status, role status, messages, orchestration state, and round completion state refresh automatically. The remaining `Refresh` button lives only in the sidebar `VCM Harness` section and is for rechecking harness files.
|
|
198
203
|
|
|
199
204
|
Translation settings are local and stored in:
|
|
200
205
|
|
|
@@ -228,18 +233,31 @@ Translation behavior:
|
|
|
228
233
|
|
|
229
234
|
## Project Harness
|
|
230
235
|
|
|
231
|
-
VCM works best when the connected repository contains VCM collaboration rules as normal project files.
|
|
236
|
+
VCM works best when the connected repository contains VCM collaboration rules as normal project files. Harness setup has two stages.
|
|
237
|
+
|
|
238
|
+
Fixed install is deterministic. It installs or updates VCM-owned files and managed blocks:
|
|
232
239
|
|
|
233
240
|
```text
|
|
234
241
|
CLAUDE.md
|
|
235
242
|
.gitignore
|
|
243
|
+
.claude/settings.json
|
|
236
244
|
.claude/agents/project-manager.md
|
|
237
245
|
.claude/agents/architect.md
|
|
238
246
|
.claude/agents/coder.md
|
|
239
247
|
.claude/agents/reviewer.md
|
|
248
|
+
.claude/skills/vcm-route-message.md
|
|
249
|
+
.claude/skills/vcm-final-acceptance.md
|
|
250
|
+
.claude/skills/vcm-long-running-validation.md
|
|
251
|
+
.claude/skills/vcm-harness-bootstrap.md
|
|
252
|
+
.ai/vcm-harness-manifest.json
|
|
253
|
+
.ai/tools/generate-module-index
|
|
254
|
+
.ai/tools/generate-public-surface
|
|
255
|
+
.ai/tools/run-long-check
|
|
256
|
+
.ai/tools/watch-job
|
|
257
|
+
.github/pull_request_template.md
|
|
240
258
|
```
|
|
241
259
|
|
|
242
|
-
If a
|
|
260
|
+
If a managed-block file already exists, VCM preserves user-authored content and only inserts or replaces the VCM block:
|
|
243
261
|
|
|
244
262
|
```md
|
|
245
263
|
<!-- VCM:BEGIN version=1 -->
|
|
@@ -256,11 +274,24 @@ For `.gitignore`, VCM uses a gitignore-native managed block:
|
|
|
256
274
|
# VCM:END
|
|
257
275
|
```
|
|
258
276
|
|
|
259
|
-
`.ai/vcm/` is the active VCM local control area, and `.claude/worktrees/` is the Claude-compatible task worktree area.
|
|
277
|
+
`.ai/vcm/` is the active VCM local control area, and `.claude/worktrees/` is the Claude-compatible task worktree area. VCM keeps the task index in app-local project state under `~/.vcm/projects/`; each task runtime repo keeps its own session, message, orchestration, and translation state.
|
|
260
278
|
|
|
261
279
|
VCM also JSON-merges `.claude/settings.json` to install Claude Code `UserPromptSubmit` and `Stop` hooks. The hooks post directly to the local VCM backend, so roles do not need a VCM CLI command to confirm delivery or report turn completion.
|
|
262
280
|
|
|
263
|
-
|
|
281
|
+
Bootstrap is AI-assisted. VCM starts a visible temporary Claude Code session in the connected repository and asks it to use the `vcm-harness-bootstrap` skill. Bootstrap fills project-specific content and generated context:
|
|
282
|
+
|
|
283
|
+
```text
|
|
284
|
+
CLAUDE.md project context outside the VCM managed block
|
|
285
|
+
docs/ARCHITECTURE.md
|
|
286
|
+
<module>/ARCHITECTURE.md
|
|
287
|
+
docs/TESTING.md
|
|
288
|
+
.ai/generated/module-index.json
|
|
289
|
+
.ai/generated/public-surface.json
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
The generated-context tools currently target Rust projects. Non-Rust repositories can still install the fixed harness, but generated context should be treated as unsupported until project-specific generators exist.
|
|
293
|
+
|
|
294
|
+
After applying harness changes or completing bootstrap, VCM reports the exact files changed or checks completed and reminds the user to review and commit them before starting long-running work.
|
|
264
295
|
|
|
265
296
|
Role sessions learn VCM rules from `CLAUDE.md` and `.claude/agents/*.md`. VCM does not paste a long context block into the terminal at session start.
|
|
266
297
|
|
|
@@ -276,8 +307,10 @@ Claude Code role
|
|
|
276
307
|
-> ends the Claude Code turn
|
|
277
308
|
-> Stop hook calls VCM backend directly
|
|
278
309
|
-> VCM scans pending route files
|
|
279
|
-
-> VCM validates
|
|
280
|
-
->
|
|
310
|
+
-> VCM validates and dispatches at most one pending route file
|
|
311
|
+
-> VCM records dispatchingAt and the GUI switches to the target role
|
|
312
|
+
-> VCM snapshots only actually delivered message history
|
|
313
|
+
-> UserPromptSubmit hook records acceptedAt and clears the matching route file
|
|
281
314
|
```
|
|
282
315
|
|
|
283
316
|
Examples:
|
|
@@ -294,23 +327,23 @@ Runtime message and handoff files:
|
|
|
294
327
|
.ai/vcm/messages/<task>.jsonl # under the task runtime repo
|
|
295
328
|
.ai/vcm/orchestration/<task>.json # under the task runtime repo
|
|
296
329
|
.ai/vcm/handoffs/messages/<from-role>-<to-role>.md
|
|
297
|
-
.ai/vcm/handoffs/role-commands/
|
|
298
330
|
.ai/vcm/handoffs/logs/
|
|
299
331
|
```
|
|
300
332
|
|
|
301
|
-
Each directed role route has exactly one message file. If a role changes its mind during one turn, it edits the same route file instead of creating another message. A blank file means no pending message; a non-empty file means pending work for VCM to submit.
|
|
333
|
+
Each directed role route has exactly one message file. Route messages are the only dynamic task-dispatch files. If a role changes its mind during one turn, it edits the same route file instead of creating another message. A blank file means no pending message; a non-empty file means pending work for VCM to submit.
|
|
302
334
|
|
|
303
335
|
## Orchestration Modes
|
|
304
336
|
|
|
305
|
-
VCM has a task-level `Auto orchestration` switch in the
|
|
337
|
+
VCM has a task-level `Auto orchestration` switch in the role console toolbar.
|
|
306
338
|
|
|
307
339
|
When it is off, VCM is in manual mode:
|
|
308
340
|
|
|
309
341
|
- Roles may write pending route files under `.ai/vcm/handoffs/messages/`.
|
|
310
342
|
- Messages appear in the `Messages` modal.
|
|
311
343
|
- The user can inspect them.
|
|
312
|
-
- The current GUI shows sequence, timestamp,
|
|
313
|
-
- `Mark All Done`
|
|
344
|
+
- The current GUI shows newest message history first with stable increasing sequence numbers, timestamp, body preview, path, `Copy`, `Mark All Done`, and `Delete All`.
|
|
345
|
+
- `Mark All Done` clears non-empty pending route files after the user manually copied or handled stuck handoff content.
|
|
346
|
+
- `Delete All` removes message history from the Messages modal without touching pending route files.
|
|
314
347
|
- The user decides what to do next by copying or manually acting on the message.
|
|
315
348
|
- VCM does not write to the target terminal or press Enter for the user.
|
|
316
349
|
|
|
@@ -319,14 +352,15 @@ When it is on, VCM is in auto mode:
|
|
|
319
352
|
- Backend policy still applies.
|
|
320
353
|
- Roles write pending route files under `.ai/vcm/handoffs/messages/`.
|
|
321
354
|
- On Claude Code `Stop`, VCM scans pending route files.
|
|
322
|
-
- If the target role session is running
|
|
323
|
-
-
|
|
324
|
-
-
|
|
325
|
-
-
|
|
326
|
-
-
|
|
355
|
+
- If the target role session is running and idle, VCM writes a `[VCM MESSAGE]` envelope to the target terminal and submits it.
|
|
356
|
+
- Just before terminal submission, VCM records `dispatchingAt`, waits briefly for the GUI to switch tabs, then writes to the embedded terminal.
|
|
357
|
+
- After successful terminal write, VCM snapshots the delivered body as message history.
|
|
358
|
+
- Claude Code `UserPromptSubmit` confirms that the prompt was accepted; VCM stores `acceptedAt` and clears the source route file if it still contains the same message.
|
|
359
|
+
- When the GUI observes a newly dispatching auto message, it switches the active role tab to that message's target role before the message is submitted.
|
|
360
|
+
- VCM enforces sequential turn-taking from hook state: a role that has accepted a prompt is busy until its `Stop` hook fires.
|
|
327
361
|
- Additional pending files to a busy target role remain non-empty and are not written to that terminal.
|
|
328
362
|
- When the target role later reaches `Stop`, VCM scans again and may deliver the next pending route file.
|
|
329
|
-
- If auto orchestration gets stuck after a manual copy/paste recovery, `Mark All Done` clears
|
|
363
|
+
- If auto orchestration gets stuck after a manual copy/paste recovery, `Mark All Done` clears pending route files. It does not mutate message history.
|
|
330
364
|
|
|
331
365
|
VCM Harness injects Claude Code `UserPromptSubmit` and `Stop` hooks into `.claude/settings.json`. Role tabs become `running` when Claude Code accepts a prompt and `idle` after `Stop`; VCM also marks a role `running` immediately after it writes a message to that embedded terminal. The terminal process status is still tracked separately. The injected role rules require a role to end its turn after writing or updating a message route file, rather than polling, looping, or waiting for another role inside the same Claude Code turn.
|
|
332
366
|
|
|
@@ -334,9 +368,9 @@ The implementation keeps only the active manual/auto orchestration mode. It does
|
|
|
334
368
|
|
|
335
369
|
## Round Completion Alerts
|
|
336
370
|
|
|
337
|
-
VCM detects conversation completion from hook-driven role activity state, not PTY silence. `UserPromptSubmit` marks a role `running`, and `Stop` marks that role `idle` with a stop timestamp.
|
|
371
|
+
VCM detects conversation completion from hook-driven role activity state, not PTY silence or message history. `UserPromptSubmit` marks a role `running`, and `Stop` marks that role `idle` with a stop timestamp.
|
|
338
372
|
|
|
339
|
-
For role chains, VCM waits for the
|
|
373
|
+
For role chains, VCM waits for the final role to reach hook `Stop`. For example, if PM sends work to Coder and Coder sends a result back to PM, the round is not complete when Coder finishes; it is complete only after PM reaches `Stop` for the final response. Pending route files block completion because more dispatch work is waiting; message history does not define completion.
|
|
340
374
|
|
|
341
375
|
When `Round alert` is enabled, the frontend polls the task round state, deduplicates each completion id, shows a small `Round complete` prompt, and plays the local completion chime.
|
|
342
376
|
|
|
@@ -361,19 +395,17 @@ For a connected repository, VCM uses:
|
|
|
361
395
|
|
|
362
396
|
```text
|
|
363
397
|
~/.vcm/projects/<project-id>/config.json
|
|
364
|
-
|
|
398
|
+
~/.vcm/projects/<project-id>/tasks/<task>.json
|
|
365
399
|
<baseRepoRoot>/.claude/worktrees/<task>/
|
|
366
400
|
<taskRepoRoot>/.ai/vcm/sessions/<task>.json
|
|
367
401
|
<taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
|
|
368
402
|
<taskRepoRoot>/.ai/vcm/orchestration/<task>.json
|
|
369
403
|
<taskRepoRoot>/.ai/vcm/translation/<task>/
|
|
370
404
|
<taskRepoRoot>/.ai/vcm/handoffs/architecture-plan.md
|
|
371
|
-
<taskRepoRoot>/.ai/vcm/handoffs/
|
|
372
|
-
<taskRepoRoot>/.ai/vcm/handoffs/validation-log.md
|
|
405
|
+
<taskRepoRoot>/.ai/vcm/handoffs/known-issues.md
|
|
373
406
|
<taskRepoRoot>/.ai/vcm/handoffs/review-report.md
|
|
374
407
|
<taskRepoRoot>/.ai/vcm/handoffs/docs-sync-report.md
|
|
375
408
|
<taskRepoRoot>/.ai/vcm/handoffs/messages/<from-role>-<to-role>.md
|
|
376
|
-
<taskRepoRoot>/.ai/vcm/handoffs/role-commands/{architect,coder,reviewer}.md
|
|
377
409
|
<taskRepoRoot>/.ai/vcm/handoffs/logs/{project-manager,architect,coder,reviewer}.log
|
|
378
410
|
```
|
|
379
411
|
|
|
@@ -410,7 +442,7 @@ npm run build
|
|
|
410
442
|
|
|
411
443
|
- VCM does not use tmux.
|
|
412
444
|
- VCM does not auto-confirm Claude Code permission prompts.
|
|
413
|
-
- VCM does not isolate roles with separate worktrees
|
|
445
|
+
- VCM does not isolate roles with separate worktrees; roles for one task share one task worktree.
|
|
414
446
|
- VCM does not translate Claude output from raw PTY output; translation reads Claude transcript JSONL files.
|
|
415
447
|
- VCM does not write translation output into handoff artifacts unless a user or role explicitly copies it there.
|
|
416
448
|
- Role file writes happen in the task worktree when a task has a worktree.
|
|
@@ -419,6 +451,7 @@ npm run build
|
|
|
419
451
|
See also:
|
|
420
452
|
|
|
421
453
|
- `docs/product-design.md`
|
|
422
|
-
- `docs/
|
|
423
|
-
- `docs/
|
|
424
|
-
- `docs/
|
|
454
|
+
- `docs/v0.2-implementation-plan.md`
|
|
455
|
+
- `docs/vcm-cc-best-practices.md`
|
|
456
|
+
- `docs/full-harness-baseline.md`
|
|
457
|
+
- `docs/cc-best-practices.md` is archived and no longer maintained.
|
|
@@ -87,11 +87,8 @@ function artifactNameToPath(paths, artifactName) {
|
|
|
87
87
|
if (artifactName === "architecture-plan.md") {
|
|
88
88
|
return paths.architecturePlanPath;
|
|
89
89
|
}
|
|
90
|
-
if (artifactName === "
|
|
91
|
-
return paths.
|
|
92
|
-
}
|
|
93
|
-
if (artifactName === "validation-log.md") {
|
|
94
|
-
return paths.validationLogPath;
|
|
90
|
+
if (artifactName === "known-issues.md") {
|
|
91
|
+
return paths.knownIssuesPath;
|
|
95
92
|
}
|
|
96
93
|
if (artifactName === "review-report.md") {
|
|
97
94
|
return paths.reviewReportPath;
|
|
@@ -99,6 +96,9 @@ function artifactNameToPath(paths, artifactName) {
|
|
|
99
96
|
if (artifactName === "docs-sync-report.md") {
|
|
100
97
|
return paths.docsSyncReportPath;
|
|
101
98
|
}
|
|
99
|
+
if (artifactName === "final-acceptance.md") {
|
|
100
|
+
return paths.finalAcceptancePath;
|
|
101
|
+
}
|
|
102
102
|
throw new VcmError({
|
|
103
103
|
code: "ARTIFACT_UNKNOWN",
|
|
104
104
|
message: `Unknown artifact: ${artifactName}`,
|
|
@@ -8,6 +8,14 @@ export function registerHarnessRoutes(app, deps) {
|
|
|
8
8
|
const project = await requireCurrentProject(deps.projectService);
|
|
9
9
|
return deps.harnessService.applyHarness(project.repoRoot);
|
|
10
10
|
});
|
|
11
|
+
app.get("/api/projects/harness/bootstrap", async () => {
|
|
12
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
13
|
+
return deps.harnessService.getBootstrapStatus(project.repoRoot);
|
|
14
|
+
});
|
|
15
|
+
app.post("/api/projects/harness/bootstrap/start", async (request) => {
|
|
16
|
+
const project = await requireCurrentProject(deps.projectService);
|
|
17
|
+
return deps.harnessService.startHarnessBootstrap(project.repoRoot, request.body ?? {});
|
|
18
|
+
});
|
|
11
19
|
}
|
|
12
20
|
async function requireCurrentProject(projectService) {
|
|
13
21
|
const project = await projectService.getCurrentProject();
|
|
@@ -9,10 +9,6 @@ export function registerMessageRoutes(app, deps) {
|
|
|
9
9
|
const context = await getRouteContext(deps, request.params.taskSlug);
|
|
10
10
|
return deps.messageService.listPendingRouteFiles(context);
|
|
11
11
|
});
|
|
12
|
-
app.post("/api/tasks/:taskSlug/messages/scan", async (request) => {
|
|
13
|
-
const context = await getRouteContext(deps, request.params.taskSlug);
|
|
14
|
-
return deps.messageService.scanAndDispatchPendingRouteFiles(context);
|
|
15
|
-
});
|
|
16
12
|
app.post("/api/tasks/:taskSlug/messages/mark-all-done", async (request) => {
|
|
17
13
|
const context = await getRouteContext(deps, request.params.taskSlug);
|
|
18
14
|
return deps.messageService.markAllDone({
|
|
@@ -20,6 +16,10 @@ export function registerMessageRoutes(app, deps) {
|
|
|
20
16
|
clearRouteFiles: true
|
|
21
17
|
});
|
|
22
18
|
});
|
|
19
|
+
app.delete("/api/tasks/:taskSlug/messages/history", async (request) => {
|
|
20
|
+
const context = await getRouteContext(deps, request.params.taskSlug);
|
|
21
|
+
return deps.messageService.deleteMessageHistory(context);
|
|
22
|
+
});
|
|
23
23
|
app.get("/api/tasks/:taskSlug/orchestration", async (request) => {
|
|
24
24
|
const context = await getRouteContext(deps, request.params.taskSlug);
|
|
25
25
|
return deps.messageService.getOrchestrationState(context);
|
|
@@ -7,16 +7,18 @@ export function registerRoundRoutes(app, deps) {
|
|
|
7
7
|
const task = await deps.taskService.loadTask(project.repoRoot, request.params.taskSlug);
|
|
8
8
|
const taskRepoRoot = getTaskRuntimeRepoRoot(task);
|
|
9
9
|
const sessions = await deps.sessionService.listRoleSessions(project.repoRoot, request.params.taskSlug);
|
|
10
|
-
const
|
|
10
|
+
const pendingRoutes = await deps.messageService.listPendingRouteFiles({
|
|
11
11
|
repoRoot: project.repoRoot,
|
|
12
|
+
taskRepoRoot,
|
|
12
13
|
stateRepoRoot: taskRepoRoot,
|
|
13
14
|
stateRoot: config.stateRoot,
|
|
15
|
+
handoffDir: task.handoffDir,
|
|
14
16
|
taskSlug: request.params.taskSlug
|
|
15
17
|
});
|
|
16
18
|
return deps.roundService.getTaskRoundState({
|
|
17
19
|
taskSlug: request.params.taskSlug,
|
|
18
20
|
sessions,
|
|
19
|
-
|
|
21
|
+
pendingRouteCount: pendingRoutes.length
|
|
20
22
|
});
|
|
21
23
|
});
|
|
22
24
|
}
|
package/dist/backend/server.js
CHANGED
|
@@ -10,7 +10,7 @@ import { createClaudeHookService } from "./services/claude-hook-service.js";
|
|
|
10
10
|
import { createGitAdapter } from "./adapters/git-adapter.js";
|
|
11
11
|
import { createAppSettingsService } from "./services/app-settings-service.js";
|
|
12
12
|
import { createClaudeTranscriptService } from "./services/claude-transcript-service.js";
|
|
13
|
-
import { createHarnessService } from "./services/harness-service.js";
|
|
13
|
+
import { createHarnessService, createScriptFixedHarnessInstaller } from "./services/harness-service.js";
|
|
14
14
|
import { createNodeFileSystemAdapter } from "./adapters/filesystem.js";
|
|
15
15
|
import { createNodePtyTerminalRuntime } from "./runtime/node-pty-runtime.js";
|
|
16
16
|
import { createOpenAiCompatibleTranslationProvider } from "./adapters/translation-provider.js";
|
|
@@ -128,8 +128,14 @@ export function createDefaultServerDeps(options = {}) {
|
|
|
128
128
|
const runtime = createNodePtyTerminalRuntime({ fs });
|
|
129
129
|
const registry = createSessionRegistry();
|
|
130
130
|
const artifactService = createArtifactService(fs);
|
|
131
|
-
const harnessService = createHarnessService({ fs });
|
|
132
131
|
const projectService = createProjectService({ fs, git, claude, appSettings });
|
|
132
|
+
const harnessService = createHarnessService({
|
|
133
|
+
fs,
|
|
134
|
+
runtime,
|
|
135
|
+
projectService,
|
|
136
|
+
apiUrl: options.apiUrl,
|
|
137
|
+
runFixedInstaller: createScriptFixedHarnessInstaller(path.join(getAppRoot(), "scripts/install-vcm-harness.mjs"))
|
|
138
|
+
});
|
|
133
139
|
const taskService = createTaskService({ fs, git, artifactService, projectService });
|
|
134
140
|
const sessionService = createSessionService({
|
|
135
141
|
fs,
|
|
@@ -3,14 +3,14 @@ import { DISPATCHABLE_ROLES, ROLE_NAMES } from "../../shared/constants.js";
|
|
|
3
3
|
import { checkMarkdownArtifact } from "../../shared/validation/artifact-check.js";
|
|
4
4
|
import { VcmError } from "../errors.js";
|
|
5
5
|
import { resolveRepoPath } from "../adapters/filesystem.js";
|
|
6
|
-
import { renderArchitecturePlanTemplate, renderDocsSyncReportTemplate,
|
|
6
|
+
import { renderArchitecturePlanTemplate, renderDocsSyncReportTemplate, renderFinalAcceptanceTemplate, renderKnownIssuesTemplate, renderMessageRouteTemplate, renderReviewReportTemplate } from "../templates/handoff.js";
|
|
7
7
|
import { renderRoleCommandTemplate } from "../templates/role-command.js";
|
|
8
8
|
const ARTIFACT_PATH_KEYS = [
|
|
9
9
|
["architecture-plan", "architecturePlanPath"],
|
|
10
|
-
["
|
|
11
|
-
["validation-log", "validationLogPath"],
|
|
10
|
+
["known-issues", "knownIssuesPath"],
|
|
12
11
|
["review-report", "reviewReportPath"],
|
|
13
|
-
["docs-sync-report", "docsSyncReportPath"]
|
|
12
|
+
["docs-sync-report", "docsSyncReportPath"],
|
|
13
|
+
["final-acceptance", "finalAcceptancePath"]
|
|
14
14
|
];
|
|
15
15
|
const ROLE_COMMAND_PLACEHOLDER_PATTERN = /(^|\n)\s*(TBD|status:\s*draft)\s*(\n|$)/i;
|
|
16
16
|
const DEFAULT_MESSAGE_ROUTES = [
|
|
@@ -45,10 +45,10 @@ export function createArtifactService(fs) {
|
|
|
45
45
|
},
|
|
46
46
|
messageRoutePaths: getDefaultMessageRoutePaths(messagesDir),
|
|
47
47
|
architecturePlanPath: path.posix.join(handoffDir, "architecture-plan.md"),
|
|
48
|
-
|
|
49
|
-
validationLogPath: path.posix.join(handoffDir, "validation-log.md"),
|
|
48
|
+
knownIssuesPath: path.posix.join(handoffDir, "known-issues.md"),
|
|
50
49
|
reviewReportPath: path.posix.join(handoffDir, "review-report.md"),
|
|
51
|
-
docsSyncReportPath: path.posix.join(handoffDir, "docs-sync-report.md")
|
|
50
|
+
docsSyncReportPath: path.posix.join(handoffDir, "docs-sync-report.md"),
|
|
51
|
+
finalAcceptancePath: path.posix.join(handoffDir, "final-acceptance.md")
|
|
52
52
|
};
|
|
53
53
|
},
|
|
54
54
|
getMessageRoutePath(handoffDir, fromRole, toRole) {
|
|
@@ -65,14 +65,14 @@ export function createArtifactService(fs) {
|
|
|
65
65
|
async createArtifactTemplates(input) {
|
|
66
66
|
const paths = await this.ensureHandoffStructure(input);
|
|
67
67
|
const files = [
|
|
68
|
-
[paths.roleCommandPaths.architect, renderRoleCommandTemplate(input.taskSlug, "architect")],
|
|
69
|
-
[paths.roleCommandPaths.coder, renderRoleCommandTemplate(input.taskSlug, "coder")],
|
|
70
|
-
[paths.roleCommandPaths.reviewer, renderRoleCommandTemplate(input.taskSlug, "reviewer")],
|
|
68
|
+
[paths.roleCommandPaths.architect, renderRoleCommandTemplate(input.taskSlug, "architect", input.repoRoot, input.branch)],
|
|
69
|
+
[paths.roleCommandPaths.coder, renderRoleCommandTemplate(input.taskSlug, "coder", input.repoRoot, input.branch)],
|
|
70
|
+
[paths.roleCommandPaths.reviewer, renderRoleCommandTemplate(input.taskSlug, "reviewer", input.repoRoot, input.branch)],
|
|
71
71
|
[paths.architecturePlanPath, renderArchitecturePlanTemplate(input.taskSlug)],
|
|
72
|
-
[paths.
|
|
73
|
-
[paths.validationLogPath, renderValidationLogTemplate(input.taskSlug)],
|
|
72
|
+
[paths.knownIssuesPath, renderKnownIssuesTemplate(input.taskSlug)],
|
|
74
73
|
[paths.reviewReportPath, renderReviewReportTemplate(input.taskSlug)],
|
|
75
74
|
[paths.docsSyncReportPath, renderDocsSyncReportTemplate(input.taskSlug)],
|
|
75
|
+
[paths.finalAcceptancePath, renderFinalAcceptanceTemplate(input.taskSlug)],
|
|
76
76
|
...Object.values(paths.messageRoutePaths).map((messagePath) => [
|
|
77
77
|
messagePath,
|
|
78
78
|
renderMessageRouteTemplate()
|