vibe-coding-master 0.0.14 → 0.0.15

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.
@@ -28,10 +28,9 @@ File:
28
28
  Current package facts:
29
29
 
30
30
  - package name: `vibe-coding-master`
31
- - current version: `0.0.10`
31
+ - current version: `0.0.14`
32
32
  - type: ESM
33
33
  - `bin.vcm`: `dist/main.js`
34
- - `bin.vcmctl`: `dist/cli/vcmctl.js`
35
34
  - published files: `dist`, `dist-frontend`, `docs`, `scripts`, `README.md`
36
35
 
37
36
  Scripts:
@@ -59,8 +58,6 @@ It verifies required files, shebangs, packaged static path behavior, and fronten
59
58
  ```text
60
59
  src/
61
60
  main.ts
62
- cli/
63
- vcmctl.ts
64
61
  shared/
65
62
  constants.ts
66
63
  types/
@@ -108,23 +105,24 @@ Responsibilities:
108
105
  - serve `dist-frontend` through backend in production mode
109
106
  - close backend/Vite on `SIGINT`
110
107
 
111
- ### `src/cli/vcmctl.ts`
108
+ ### Removed CLI Surface
112
109
 
113
- CLI commands:
110
+ The target design removes `vcmctl` completely. Role sessions must not call a VCM CLI to send messages or hook events.
114
111
 
115
- - `vcmctl send`
116
- - `vcmctl reply`
117
- - `vcmctl result`
118
- - `vcmctl inbox`
119
- - `vcmctl ready`
112
+ Remove:
120
113
 
121
- Environment required in role sessions:
114
+ - `src/cli/vcmctl.ts`
115
+ - `bin.vcmctl` from `package.json`
116
+ - packaged `dist/cli/vcmctl.js`
117
+ - `VCM_CTL_COMMAND` session environment
118
+ - harness rules that mention `vcmctl`
119
+
120
+ Role sessions still receive enough environment for direct hook POSTs and backend-aware terminal delivery:
122
121
 
123
122
  - `VCM_API_URL`
124
123
  - `VCM_TASK_SLUG`
125
124
  - `VCM_ROLE`
126
-
127
- Role sessions receive these env vars from `SessionService`.
125
+ - `VCM_SESSION_ID`
128
126
 
129
127
  ## 5. Shared Layer
130
128
 
@@ -239,10 +237,10 @@ Defines:
239
237
  - `VcmOrchestrationMode`
240
238
  - `VcmRoleMessage`
241
239
  - `VcmOrchestrationState`
242
- - `SendRoleMessageRequest`
243
- - `SendRoleMessageResult`
240
+ - `VcmRouteFile`
241
+ - `VcmRouteFileDispatchResult`
244
242
 
245
- The state type includes `paused` for backend/API compatibility. The current GUI only exposes manual/auto.
243
+ The state type should only expose the current manual/auto mode. Remove compatibility-only paused state when deleting `vcmctl`.
246
244
 
247
245
  ### `src/shared/types/round.ts`
248
246
 
@@ -679,41 +677,61 @@ In task-worktree mode:
679
677
  Exports:
680
678
 
681
679
  - `MessageService`
682
- - input interfaces
680
+ - `ScanPendingRouteFilesInput`
681
+ - `DispatchPendingRouteFileInput`
682
+ - `RouteFileRecord`
683
683
  - `createMessageService(deps)`
684
684
 
685
685
  Responsibilities:
686
686
 
687
687
  - list messages
688
- - send messages
689
- - confirm submitted messages from Claude Code `UserPromptSubmit` hooks
688
+ - scan route-file outboxes after Claude Code `Stop`
689
+ - snapshot pending route-file messages
690
690
  - mark all open messages done for manual recovery
691
- - stage/approve/reject messages
692
691
  - get/update orchestration state
693
692
  - enforce message policy
694
693
  - enforce per-target-role in-flight delivery
695
- - queue extra messages for a busy target role
696
- - acknowledge a role's active message when that role sends `vcmctl reply` or `vcmctl result`
697
- - deliver the next queued message for that role after acknowledgement
694
+ - leave non-empty route files pending when a target role is busy, unavailable, or terminal submission fails
695
+ - deliver the next pending route file when a target role becomes idle
698
696
  - persist message snapshots
699
- - write message body markdown
700
- - write staged or delivering messages to target terminal
697
+ - archive dispatched route-file bodies before clearing source files
698
+ - submit route-file messages to the target terminal
701
699
 
702
700
  In task-worktree mode:
703
701
 
704
702
  - message snapshots live under `task.worktreePath/.ai/vcm/messages`
705
703
  - orchestration state lives under `task.worktreePath/.ai/vcm/orchestration`
706
- - message body files live under `task.worktreePath/.ai/vcm/handoffs/messages`
704
+ - pending route files live under `task.worktreePath/.ai/vcm/handoffs/messages`
707
705
  - terminal delivery uses the runtime session for the role, whose cwd is the task worktree
708
706
  - message mutations are serialized per task inside the VCM process to avoid concurrent API calls bypassing the in-flight check
709
707
 
710
- Auto-delivery state:
711
-
712
- - `send` writes the envelope and Enter, then stores `delivering`
713
- - `UserPromptSubmit` hook with the same message id stores `submitted`
714
- - `delivering`, `submitted`, `delivered`, and `staged` all count as active for per-role turn-taking
715
- - target-role `vcmctl reply` / `vcmctl result` acknowledges the active message and releases the next queued message
716
- - `markAllDone` appends `acknowledged` snapshots for open messages so the user can recover after manually copying or sending stuck queued work
708
+ Route-file protocol:
709
+
710
+ - route file name is `<from-role>-<to-role>.md`
711
+ - the filename is the authoritative route; frontmatter cannot override `from` or `to`
712
+ - blank or whitespace-only files are ignored
713
+ - non-empty files are pending
714
+ - each directed route has exactly one pending file, so repeated sends by the same role to the same target become edits to the same file
715
+ - VCM scans after every `Stop` hook
716
+ - VCM scans the stopped role's outgoing files and pending files targeting newly idle roles
717
+ - VCM delivers at most one route file per target role per scan
718
+ - if several files target the same idle role, choose oldest modified time, then route name
719
+ - successful terminal submission snapshots the body, stores `submitted`, then clears the source route file
720
+ - failed, blocked, manual, or unavailable delivery leaves the source route file unchanged
721
+ - `markAllDone` appends `acknowledged` snapshots and may clear pending route files only after user confirmation
722
+
723
+ Required service functions:
724
+
725
+ - `listMessages(taskSlug): Promise<VcmRoleMessage[]>`
726
+ - `listPendingRouteFiles(repoRoot, taskSlug): Promise<RouteFileRecord[]>`
727
+ - `scanAndDispatchPendingRouteFiles(input: { repoRoot: string; taskSlug: string; stoppedRole: RoleName }): Promise<void>`
728
+ - `readRouteFile(path): Promise<RouteFileRecord | null>`
729
+ - `dispatchPendingRouteFile(record): Promise<VcmRouteFileDispatchResult>`
730
+ - `appendMessageSnapshot(message): Promise<void>`
731
+ - `clearRouteFile(path): Promise<void>`
732
+ - `markAllDone(taskSlug, options): Promise<MarkAllMessagesDoneResult>`
733
+
734
+ `dispatchPendingRouteFile` must snapshot before clearing. Clearing means truncating the route file to an empty string, not deleting it.
717
735
 
718
736
  ### `src/backend/services/claude-hook-service.ts`
719
737
 
@@ -724,11 +742,11 @@ Exports:
724
742
 
725
743
  Responsibilities:
726
744
 
727
- - accept Claude Code hook events from `vcmctl hook-event`
728
- - support only `UserPromptSubmit` and `Stop` in V1
745
+ - accept Claude Code `Stop` hook events directly over HTTP
729
746
  - map hook events to the current VCM project, task, role, and persisted Claude session id
730
- - update `RoleSessionRecord.activityStatus`: `UserPromptSubmit -> running`, `Stop -> idle`
731
- - call `MessageService.confirmPromptSubmitted` when a `UserPromptSubmit` prompt contains a VCM message id
747
+ - update `RoleSessionRecord.activityStatus`: `Stop -> idle`
748
+ - call `MessageService.scanAndDispatchPendingRouteFiles` after recording the stop event
749
+ - never require `vcmctl hook-event`
732
750
 
733
751
  ### `src/backend/services/command-dispatcher.ts`
734
752
 
@@ -739,7 +757,7 @@ Exports:
739
757
  - `CommandDispatcherDeps`
740
758
  - `createCommandDispatcher(deps)`
741
759
 
742
- Compatibility role-command dispatch only. Preferred orchestration is `MessageService` plus `vcmctl`.
760
+ Obsolete role-command dispatch path. Remove this as part of the route-file messaging migration; preferred orchestration is `MessageService` scanning `.ai/vcm/handoffs/messages/<from-role>-<to-role>.md` after `Stop`.
743
761
 
744
762
  ### `src/backend/services/harness-service.ts`
745
763
 
@@ -871,9 +889,8 @@ Responsibilities:
871
889
  - map `activityStatus: "running"` to role state `answering`
872
890
  - map `activityStatus: "idle"` plus `lastStopAt` to role state `idle`
873
891
  - evaluate task-level round completion from messages plus role states
874
- - wait for the latest active delivering/submitted/delivered/staged target role in PM -> role -> PM chains
892
+ - wait for the latest active submitted target role in PM -> role -> PM chains
875
893
  - ignore completion while queued or pending messages exist
876
- - keep `stopSession` and `stopTask` as no-op lifecycle compatibility hooks
877
894
 
878
895
  ## 9. Backend API
879
896
 
@@ -897,10 +914,10 @@ Registers HTTP routes and the terminal WebSocket.
897
914
  - `src/backend/api/project-routes.ts`: health, recent paths, connect/current project
898
915
  - `src/backend/api/harness-routes.ts`: harness status/apply
899
916
  - `src/backend/api/task-routes.ts`: tasks, task status, and Close Task cleanup endpoint; Close Task stops running role sessions before translation/task cleanup
900
- - `src/backend/api/session-routes.ts`: session lifecycle and dispatch compatibility endpoint
901
- - `src/backend/api/artifact-routes.ts`: artifact, role command, and log reads/writes
902
- - `src/backend/api/message-routes.ts`: messages, Mark All Done recovery, and orchestration
903
- - `src/backend/api/claude-hook-routes.ts`: Claude Code `UserPromptSubmit` and `Stop` hook receiver
917
+ - `src/backend/api/session-routes.ts`: session lifecycle
918
+ - `src/backend/api/artifact-routes.ts`: artifact and log reads/writes
919
+ - `src/backend/api/message-routes.ts`: message history, pending route files, Mark All Done recovery, and orchestration
920
+ - `src/backend/api/claude-hook-routes.ts`: Claude Code `Stop` hook receiver
904
921
  - `src/backend/api/round-routes.ts`: task round completion state
905
922
  - `src/backend/api/translation-routes.ts`: settings, prompt previews, provider test, start/poll, input/send, clear/retry
906
923
 
@@ -977,6 +994,7 @@ It calls:
977
994
  - artifact endpoints
978
995
  - message endpoints
979
996
  - orchestration endpoints
997
+ - route-file inspection endpoints for the Messages modal
980
998
  - round completion endpoint
981
999
  - translation endpoints
982
1000
 
@@ -1100,7 +1118,7 @@ Exports:
1100
1118
  - `getMessageCounts(messages)`
1101
1119
  - `MessageTimeline(props)`
1102
1120
 
1103
- Used inside the Messages modal. Current UI rows show sequence, timestamp, route, type, status, body preview, body path, and a `Copy` button. The modal header includes `Mark All Done` for manual recovery from stuck queued/in-flight messages. Stage/approve/reject backend APIs remain compatibility paths, but those buttons are not displayed in the current modal.
1121
+ Used inside the Messages modal. Current UI rows show sequence, timestamp, route, type, status, body preview, source route file path, and a `Copy` button. The modal header includes `Mark All Done` for manual recovery from stuck queued/in-flight messages. Stage/approve/reject backend APIs should be removed with the route-file migration.
1104
1122
 
1105
1123
  ### `src/frontend/components/event-log.tsx`
1106
1124
 
@@ -1147,7 +1165,7 @@ Exports:
1147
1165
 
1148
1166
  Renders permission select and session lifecycle buttons.
1149
1167
 
1150
- There is no visible primary `Send Command` button in the current toolbar. Role-command dispatch remains backend compatibility.
1168
+ There is no visible primary `Send Command` button in the current toolbar. Role-command dispatch should be removed with the route-file migration.
1151
1169
 
1152
1170
  ### `src/frontend/components/translation-panel.tsx`
1153
1171
 
@@ -1224,8 +1242,8 @@ Task workspace:
1224
1242
 
1225
1243
  Round completion:
1226
1244
 
1227
- - task state follows the latest active delivering/submitted/delivered/staged message target role
1228
- - role activity uses `UserPromptSubmit -> running` and `Stop -> idle`
1245
+ - task state follows the latest active submitted message target role
1246
+ - role activity uses VCM terminal submit -> `running` and Claude Code `Stop` -> `idle`
1229
1247
  - PM -> role -> PM chains complete after PM's final hook `Stop`, not after the intermediate role's `Stop`
1230
1248
  - queued or pending messages keep the round active
1231
1249
  - frontend dedupes `completionId` before showing a prompt or playing sound
@@ -1271,7 +1289,7 @@ Messages:
1271
1289
 
1272
1290
  ```text
1273
1291
  <taskRepoRoot>/.ai/vcm/messages/<task>.jsonl
1274
- <taskRepoRoot>/.ai/vcm/handoffs/messages/<message-id>.md
1292
+ <taskRepoRoot>/.ai/vcm/handoffs/messages/<from-role>-<to-role>.md
1275
1293
  ```
1276
1294
 
1277
1295
  Orchestration:
@@ -1330,7 +1348,7 @@ For frontend layout changes, also verify manually:
1330
1348
  - Messages modal opens from sidebar Settings
1331
1349
  - Events modal opens from sidebar Settings
1332
1350
  - Auto orchestration toggles on/off from the role toolbar
1333
- - Auto orchestration switches to the target role tab when a new message is confirmed by `UserPromptSubmit`
1351
+ - Auto orchestration switches to the target role tab when VCM submits a route-file message
1334
1352
  - Round alert can be toggled from sidebar Settings and fires once after a chained round truly completes
1335
1353
  - `Enter` in translation composer translates/sends
1336
1354
  - `Shift+Enter` inserts newline
@@ -1350,6 +1368,8 @@ Do not reintroduce these into V1 docs or UI unless the product direction changes
1350
1368
  - optional title input in New Task
1351
1369
  - `Dirty: yes/no` sidebar label
1352
1370
  - role command dispatch as the primary orchestration path
1371
+ - `vcmctl` as an active CLI or agent-facing message path
1372
+ - `UserPromptSubmit` as the delivery confirmation mechanism
1353
1373
  - per-role worktrees
1354
1374
  - switching a task to another branch/worktree after creation
1355
1375
  - a separate `Create task worktree` button outside task creation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "description": "Local GUI session cockpit for Claude Code role sessions.",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,8 +11,7 @@
11
11
  "README.md"
12
12
  ],
13
13
  "bin": {
14
- "vcm": "dist/main.js",
15
- "vcmctl": "dist/cli/vcmctl.js"
14
+ "vcm": "dist/main.js"
16
15
  },
17
16
  "engines": {
18
17
  "node": "^20.0.0 || >=22.0.0"
@@ -7,7 +7,6 @@ const requiredFiles = [
7
7
  "package.json",
8
8
  "scripts/fix-node-pty-spawn-helper.mjs",
9
9
  "dist/main.js",
10
- "dist/cli/vcmctl.js",
11
10
  "dist/backend/server.js",
12
11
  "dist/backend/api/harness-routes.js",
13
12
  "dist/backend/runtime/node-pty-runtime.js",
@@ -40,14 +39,12 @@ async function main() {
40
39
  const pkg = JSON.parse(await readText("package.json"));
41
40
  assertArrayIncludes(pkg.files, requiredFileEntries, "package.json files");
42
41
  assertEqual(pkg.bin?.vcm, "dist/main.js", "package.json bin.vcm");
43
- assertEqual(pkg.bin?.vcmctl, "dist/cli/vcmctl.js", "package.json bin.vcmctl");
44
42
 
45
43
  for (const file of requiredFiles) {
46
44
  await assertFile(file);
47
45
  }
48
46
 
49
47
  await assertStartsWith("dist/main.js", "#!/usr/bin/env node", "vcm bin shebang");
50
- await assertStartsWith("dist/cli/vcmctl.js", "#!/usr/bin/env node", "vcmctl bin shebang");
51
48
 
52
49
  const server = await readText("dist/backend/server.js");
53
50
  assertIncludes(server, 'path.join(getAppRoot(), "dist-frontend")', "packaged static dir must resolve from app root");
@@ -1,171 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from "node:fs/promises";
3
- async function main(argv = process.argv.slice(2)) {
4
- const [command, ...rest] = argv;
5
- if (!command || command === "--help" || command === "-h") {
6
- printHelp();
7
- return;
8
- }
9
- if (command === "send") {
10
- const options = parseOptions(rest);
11
- await sendMessage({
12
- fromRole: getEnvRole(),
13
- toRole: requireOption(options.to, "--to"),
14
- type: options.type ?? "task",
15
- body: await resolveBody(options),
16
- artifactRefs: options.artifactRefs
17
- });
18
- return;
19
- }
20
- if (command === "reply" || command === "result") {
21
- const options = parseOptions(rest);
22
- await sendMessage({
23
- fromRole: getEnvRole(),
24
- toRole: "project-manager",
25
- type: command === "result" ? "result" : options.type ?? "question",
26
- body: await resolveBody(options),
27
- artifactRefs: options.artifactRefs
28
- });
29
- return;
30
- }
31
- if (command === "inbox") {
32
- const response = await fetchJson(`${getApiUrl()}/api/tasks/${encodeURIComponent(getTaskSlug())}/messages`);
33
- console.log(JSON.stringify(response, null, 2));
34
- return;
35
- }
36
- if (command === "hook-event") {
37
- await sendHookEvent(await readStdinJson());
38
- return;
39
- }
40
- if (command === "ready") {
41
- console.log("ready: VCM readiness signaling is planned for a later phase.");
42
- return;
43
- }
44
- throw new Error(`Unknown vcmctl command: ${command}`);
45
- }
46
- async function sendMessage(input) {
47
- const result = await fetchJson(`${getApiUrl()}/api/tasks/${encodeURIComponent(getTaskSlug())}/messages`, {
48
- method: "POST",
49
- body: JSON.stringify(input),
50
- headers: {
51
- "content-type": "application/json"
52
- }
53
- });
54
- console.log(JSON.stringify(result, null, 2));
55
- }
56
- async function sendHookEvent(event) {
57
- const input = {
58
- taskSlug: getTaskSlug(),
59
- role: getEnvRole(),
60
- event
61
- };
62
- await fetchJson(`${getApiUrl()}/api/hooks/claude-code`, {
63
- method: "POST",
64
- body: JSON.stringify(input),
65
- headers: {
66
- "content-type": "application/json"
67
- }
68
- });
69
- }
70
- async function readStdinJson() {
71
- const chunks = [];
72
- for await (const chunk of process.stdin) {
73
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
74
- }
75
- const raw = Buffer.concat(chunks).toString("utf8").trim();
76
- if (!raw) {
77
- return {};
78
- }
79
- return JSON.parse(raw);
80
- }
81
- function parseOptions(args) {
82
- const options = {
83
- artifactRefs: []
84
- };
85
- for (let index = 0; index < args.length; index += 1) {
86
- const arg = args[index];
87
- if (arg === "--to") {
88
- options.to = requireValue(args, index += 1);
89
- }
90
- else if (arg === "--type") {
91
- options.type = requireValue(args, index += 1);
92
- }
93
- else if (arg === "--body") {
94
- options.body = requireValue(args, index += 1);
95
- }
96
- else if (arg === "--body-file") {
97
- options.bodyFile = requireValue(args, index += 1);
98
- }
99
- else if (arg === "--artifact") {
100
- options.artifactRefs.push(requireValue(args, index += 1));
101
- }
102
- else {
103
- throw new Error(`Unknown option: ${arg}`);
104
- }
105
- }
106
- return options;
107
- }
108
- async function resolveBody(options) {
109
- if (options.bodyFile) {
110
- return fs.readFile(options.bodyFile, "utf8");
111
- }
112
- if (options.body) {
113
- return options.body;
114
- }
115
- throw new Error("Message body is required. Use --body or --body-file.");
116
- }
117
- function requireValue(args, index) {
118
- const value = args[index];
119
- if (!value) {
120
- throw new Error("Missing option value.");
121
- }
122
- return value;
123
- }
124
- function requireOption(value, name) {
125
- if (!value) {
126
- throw new Error(`Missing required option: ${name}`);
127
- }
128
- return value;
129
- }
130
- async function fetchJson(url, init = {}) {
131
- const response = await fetch(url, init);
132
- if (!response.ok) {
133
- const payload = await response.json().catch(() => null);
134
- const message = payload?.error?.hint
135
- ? `${payload.error.message} ${payload.error.hint}`
136
- : payload?.error?.message ?? `Request failed: ${response.status}`;
137
- throw new Error(message);
138
- }
139
- return response.json();
140
- }
141
- function getApiUrl() {
142
- return process.env.VCM_API_URL ?? "http://127.0.0.1:4173";
143
- }
144
- function getTaskSlug() {
145
- return requireEnv("VCM_TASK_SLUG");
146
- }
147
- function getEnvRole() {
148
- return requireEnv("VCM_ROLE");
149
- }
150
- function requireEnv(name) {
151
- const value = process.env[name];
152
- if (!value) {
153
- throw new Error(`${name} is not set.`);
154
- }
155
- return value;
156
- }
157
- function printHelp() {
158
- console.log(`vcmctl
159
-
160
- Usage:
161
- vcmctl send --to coder --type task --body-file /tmp/message.md
162
- vcmctl reply --type blocked --body "Need clarification."
163
- vcmctl result --body-file /tmp/result.md --artifact .ai/vcm/handoffs/implementation-log.md
164
- vcmctl inbox
165
- vcmctl hook-event < hook-payload.json
166
- `);
167
- }
168
- main().catch((error) => {
169
- console.error(error.message);
170
- process.exit(1);
171
- });