vibe-coding-master 0.5.2 → 0.5.4
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/dist/backend/gateway/gateway-service.js +2 -73
- package/dist/backend/services/claude-hook-service.js +69 -34
- package/dist/backend/services/claude-transcript-reply.js +107 -0
- package/dist/backend/services/round-service.js +139 -26
- package/dist/backend/services/session-service.js +54 -27
- package/dist/shared/constants.js +10 -0
- package/dist-frontend/assets/{index-BaDS9Ohj.js → index-C0CdYJxv.js} +3 -3
- package/dist-frontend/index.html +1 -1
- package/package.json +1 -1
|
@@ -135,15 +135,23 @@ export function createSessionService(deps) {
|
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
await deps.fs.ensureDir(resolveRepoPath(repoRoot, TRANSLATION_DIR));
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
// Project-level tool sessions always launch (and resume) from the base
|
|
139
|
+
// repoRoot. Claude anchors a session transcript to its first-launch cwd and
|
|
140
|
+
// `/cd` never relocates that transcript, so a constant repoRoot anchor keeps
|
|
141
|
+
// `claude --resume` valid even after the prior task worktree is deleted. The
|
|
142
|
+
// active task worktree is entered afterwards via `/cd`
|
|
143
|
+
// (migrateRunningProjectToolSessionCwd), and the task root is also exposed
|
|
144
|
+
// independently of pty cwd via VCM_TASK_REPO_ROOT.
|
|
145
|
+
const launchCwd = repoRoot;
|
|
146
|
+
// `claude --resume` restores the session's last working directory, so a resumed
|
|
147
|
+
// session is already at its persisted cwd (not the repoRoot spawn cwd). Track that
|
|
148
|
+
// restored cwd so the `/cd` migrate below fires only on an actual switch; a fresh
|
|
149
|
+
// session genuinely starts at repoRoot.
|
|
150
|
+
const sessionCwd = launchMode === "resume" ? persisted?.cwd ?? launchCwd : launchCwd;
|
|
141
151
|
const claudeSessionId = resumeClaudeSessionId ?? "";
|
|
142
|
-
const transcriptPath =
|
|
143
|
-
?
|
|
144
|
-
:
|
|
145
|
-
? claudeTranscriptPath(launchCwd, resumeClaudeSessionId)
|
|
146
|
-
: undefined;
|
|
152
|
+
const transcriptPath = resumeClaudeSessionId
|
|
153
|
+
? claudeTranscriptPath(repoRoot, resumeClaudeSessionId)
|
|
154
|
+
: undefined;
|
|
147
155
|
const startCommand = {
|
|
148
156
|
...deps.claude.buildRoleStartCommand(TRANSLATOR_ROLE, config.claudeCommand, permissionMode, resumeClaudeSessionId, launchMode === "resume", model, effort),
|
|
149
157
|
cwd: launchCwd
|
|
@@ -158,7 +166,10 @@ export function createSessionService(deps) {
|
|
|
158
166
|
VCM_API_URL: deps.apiUrl,
|
|
159
167
|
VCM_BASE_REPO_ROOT: repoRoot,
|
|
160
168
|
VCM_TASK_REPO_ROOT: taskContext.taskRepoRoot,
|
|
161
|
-
VCM_TASK_SLUG
|
|
169
|
+
// Project-scoped sessions report their project sentinel as VCM_TASK_SLUG so
|
|
170
|
+
// hook payloads match this session's record and cannot be attributed to the
|
|
171
|
+
// active task; VCM_TASK_REPO_ROOT remains the active worktree.
|
|
172
|
+
VCM_TASK_SLUG: PROJECT_TRANSLATOR_SCOPE,
|
|
162
173
|
VCM_ROLE: TRANSLATOR_ROLE,
|
|
163
174
|
VCM_SESSION_ID: claudeSessionId || undefined
|
|
164
175
|
},
|
|
@@ -179,7 +190,7 @@ export function createSessionService(deps) {
|
|
|
179
190
|
permissionMode,
|
|
180
191
|
model,
|
|
181
192
|
effort,
|
|
182
|
-
cwd:
|
|
193
|
+
cwd: sessionCwd,
|
|
183
194
|
terminalBackend: "node-pty",
|
|
184
195
|
pid: runtimeSession.pid,
|
|
185
196
|
startedAt: runtimeSession.startedAt,
|
|
@@ -215,15 +226,19 @@ export function createSessionService(deps) {
|
|
|
215
226
|
});
|
|
216
227
|
}
|
|
217
228
|
await deps.fs.ensureDir(resolveRepoPath(repoRoot, HARNESS_ENGINEER_DIR));
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
229
|
+
// See launchProjectTranslatorSession: project-level tool sessions launch and
|
|
230
|
+
// resume from the base repoRoot so the transcript anchor stays stable and
|
|
231
|
+
// resume never depends on a possibly-deleted task worktree. The active task
|
|
232
|
+
// worktree is entered afterwards via `/cd`.
|
|
233
|
+
const launchCwd = repoRoot;
|
|
234
|
+
// `claude --resume` restores the session's last working directory, so a resumed
|
|
235
|
+
// session is already at its persisted cwd (not the repoRoot spawn cwd). Track that
|
|
236
|
+
// restored cwd so the `/cd` migrate below fires only on an actual switch.
|
|
237
|
+
const sessionCwd = launchMode === "resume" ? persisted?.cwd ?? launchCwd : launchCwd;
|
|
221
238
|
const claudeSessionId = resumeClaudeSessionId ?? "";
|
|
222
|
-
const transcriptPath =
|
|
223
|
-
?
|
|
224
|
-
:
|
|
225
|
-
? claudeTranscriptPath(launchCwd, resumeClaudeSessionId)
|
|
226
|
-
: undefined;
|
|
239
|
+
const transcriptPath = resumeClaudeSessionId
|
|
240
|
+
? claudeTranscriptPath(repoRoot, resumeClaudeSessionId)
|
|
241
|
+
: undefined;
|
|
227
242
|
const startCommand = {
|
|
228
243
|
...deps.claude.buildRoleStartCommand(HARNESS_ENGINEER_ROLE, config.claudeCommand, permissionMode, resumeClaudeSessionId, launchMode === "resume", model, effort),
|
|
229
244
|
cwd: launchCwd
|
|
@@ -238,7 +253,10 @@ export function createSessionService(deps) {
|
|
|
238
253
|
VCM_API_URL: deps.apiUrl,
|
|
239
254
|
VCM_BASE_REPO_ROOT: repoRoot,
|
|
240
255
|
VCM_TASK_REPO_ROOT: taskContext.taskRepoRoot,
|
|
241
|
-
VCM_TASK_SLUG
|
|
256
|
+
// Project-scoped sessions report their project sentinel as VCM_TASK_SLUG so
|
|
257
|
+
// hook payloads match this session's record and cannot be attributed to the
|
|
258
|
+
// active task; VCM_TASK_REPO_ROOT remains the active worktree.
|
|
259
|
+
VCM_TASK_SLUG: PROJECT_HARNESS_ENGINEER_SCOPE,
|
|
242
260
|
VCM_ROLE: HARNESS_ENGINEER_ROLE,
|
|
243
261
|
VCM_SESSION_ID: claudeSessionId || undefined
|
|
244
262
|
},
|
|
@@ -259,7 +277,7 @@ export function createSessionService(deps) {
|
|
|
259
277
|
permissionMode,
|
|
260
278
|
model,
|
|
261
279
|
effort,
|
|
262
|
-
cwd:
|
|
280
|
+
cwd: sessionCwd,
|
|
263
281
|
terminalBackend: "node-pty",
|
|
264
282
|
pid: runtimeSession.pid,
|
|
265
283
|
startedAt: runtimeSession.startedAt,
|
|
@@ -305,13 +323,13 @@ export function createSessionService(deps) {
|
|
|
305
323
|
await submitTerminalInput(deps.runtime, session.id, formatClaudeCdCommand(targetCwd), {
|
|
306
324
|
enterDelayMs: PROJECT_TOOL_CD_ENTER_DELAY_MS
|
|
307
325
|
});
|
|
326
|
+
// `cwd` tracks the logical `/cd` target only. The transcript stays anchored at
|
|
327
|
+
// the first-launch cwd (repoRoot for project tools), so transcriptPath must
|
|
328
|
+
// not be recomputed from targetCwd here.
|
|
308
329
|
const updated = {
|
|
309
330
|
...session,
|
|
310
331
|
cwd: targetCwd,
|
|
311
332
|
previousCwd: session.cwd,
|
|
312
|
-
transcriptPath: session.claudeSessionId
|
|
313
|
-
? claudeTranscriptPath(targetCwd, session.claudeSessionId)
|
|
314
|
-
: session.transcriptPath,
|
|
315
333
|
updatedAt: timestamp
|
|
316
334
|
};
|
|
317
335
|
deps.registry.upsert(normalizeProjectScopedRecordForPersistence(updated));
|
|
@@ -329,7 +347,11 @@ export function createSessionService(deps) {
|
|
|
329
347
|
const permissionMode = normalizeClaudePermissionMode(session.permissionMode);
|
|
330
348
|
const model = normalizeClaudeModel(session.model);
|
|
331
349
|
const effort = normalizeClaudeEffort(session.effort);
|
|
332
|
-
|
|
350
|
+
// Spawn (`claude --resume`) always anchors at the base repoRoot so resume works
|
|
351
|
+
// even if the persisted task cwd was deleted. `--resume` then restores the
|
|
352
|
+
// session's own last cwd (tracked on `session.cwd`), so the `/cd` migrate below
|
|
353
|
+
// fires only when that restored cwd differs from the target worktree.
|
|
354
|
+
const launchCwd = repoRoot;
|
|
333
355
|
const startCommand = {
|
|
334
356
|
...deps.claude.buildRoleStartCommand(session.role, config.claudeCommand, permissionMode, session.claudeSessionId, true, model, effort),
|
|
335
357
|
cwd: launchCwd
|
|
@@ -359,13 +381,14 @@ export function createSessionService(deps) {
|
|
|
359
381
|
permissionMode,
|
|
360
382
|
model,
|
|
361
383
|
effort,
|
|
362
|
-
cwd: launchCwd,
|
|
363
384
|
pid: runtimeSession.pid,
|
|
364
385
|
startedAt: runtimeSession.startedAt,
|
|
365
386
|
updatedAt: timestamp,
|
|
366
387
|
lastOutputAt: runtimeSession.lastOutputAt,
|
|
367
388
|
exitCode: runtimeSession.exitCode,
|
|
368
|
-
transcriptPath: session.
|
|
389
|
+
transcriptPath: session.claudeSessionId
|
|
390
|
+
? claudeTranscriptPath(repoRoot, session.claudeSessionId)
|
|
391
|
+
: session.transcriptPath
|
|
369
392
|
};
|
|
370
393
|
deps.registry.upsert(normalizeProjectScopedRecordForPersistence(resumed));
|
|
371
394
|
await persistProjectScopedToolSession(repoRoot, resumed);
|
|
@@ -1264,5 +1287,9 @@ function normalizeClaudeEffort(value) {
|
|
|
1264
1287
|
return "default";
|
|
1265
1288
|
}
|
|
1266
1289
|
function formatClaudeCdCommand(targetCwd) {
|
|
1267
|
-
|
|
1290
|
+
// Claude Code's `/cd` slash command takes the literal remainder of the line as
|
|
1291
|
+
// the path, so the target must NOT be wrapped in quotes (quotes are taken as part
|
|
1292
|
+
// of the path and the cd fails). Paths with spaces are still fine unquoted; a
|
|
1293
|
+
// newline is the only unsafe character and is rejected by assertSafeCwdTarget.
|
|
1294
|
+
return `/cd ${targetCwd}`;
|
|
1268
1295
|
}
|
package/dist/shared/constants.js
CHANGED
|
@@ -84,6 +84,16 @@ export function isHarnessEngineerToolRoleName(value) {
|
|
|
84
84
|
export function isDispatchableRole(value) {
|
|
85
85
|
return DISPATCHABLE_ROLES.includes(value);
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Roles that address the human operator. When a role in this set ends its turn
|
|
89
|
+
* with no onward route message, the flow is treated as awaiting a user decision
|
|
90
|
+
* (see the `awaiting-user` flow-pause reason). Single source of truth for that
|
|
91
|
+
* predicate.
|
|
92
|
+
*/
|
|
93
|
+
export const USER_FACING_ROLES = ["project-manager"];
|
|
94
|
+
export function isUserFacingRole(value) {
|
|
95
|
+
return USER_FACING_ROLES.includes(value);
|
|
96
|
+
}
|
|
87
97
|
export function getRoleDefinition(role) {
|
|
88
98
|
const definition = ROLE_DEFINITIONS.find((candidate) => candidate.name === role);
|
|
89
99
|
if (!definition) {
|