vibe-coding-master 0.4.3 → 0.4.5
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/adapters/git-adapter.js +45 -18
- package/dist/backend/api/harness-routes.js +38 -29
- package/dist/backend/services/harness-service.js +317 -121
- package/dist/backend/services/session-service.js +34 -24
- package/dist/backend/services/task-service.js +33 -20
- package/dist/backend/services/translation-service.js +1 -0
- package/dist/backend/services/translation-worker-service.js +30 -3
- package/dist/backend/templates/harness/harness-engineer-agent.js +2 -0
- package/dist/backend/templates/harness/vcm-harness-bootstrap-skill.js +11 -1
- package/dist-frontend/assets/index-Cvv4cf0U.js +95 -0
- package/dist-frontend/assets/{index-kJDZAzjD.css → index-M9t0gmj2.css} +1 -1
- package/dist-frontend/index.html +2 -2
- package/docs/product-design.md +5 -2
- package/docs/v0.4-harness-optimization-plan.md +4 -3
- package/docs/vcm-cc-best-practices.md +3 -2
- package/package.json +1 -1
- package/scripts/harness-tools/generate-public-surface +1 -1
- package/dist-frontend/assets/index-uYhgIwNK.js +0 -94
|
@@ -206,6 +206,7 @@ export function createSessionService(deps) {
|
|
|
206
206
|
return updated;
|
|
207
207
|
}
|
|
208
208
|
async function launchProjectTranslatorSession(repoRoot, input, launchMode) {
|
|
209
|
+
const taskContext = await resolveProjectToolTaskContext(repoRoot, input, "Translator");
|
|
209
210
|
const live = toRoleSessionRecordView(getRegisteredProjectTranslatorSession(deps.registry, deps.runtime), deps.runtime);
|
|
210
211
|
if (live && live.status === "running") {
|
|
211
212
|
return withHarnessRevisionView(repoRoot, live);
|
|
@@ -227,12 +228,10 @@ export function createSessionService(deps) {
|
|
|
227
228
|
});
|
|
228
229
|
}
|
|
229
230
|
await deps.fs.ensureDir(resolveRepoPath(repoRoot, TRANSLATION_DIR));
|
|
230
|
-
const transcriptPath =
|
|
231
|
-
? persisted.transcriptPath
|
|
232
|
-
: claudeTranscriptPath(repoRoot, claudeSessionId);
|
|
231
|
+
const transcriptPath = claudeTranscriptPath(taskContext.taskRepoRoot, claudeSessionId);
|
|
233
232
|
const startCommand = {
|
|
234
233
|
...deps.claude.buildRoleStartCommand(TRANSLATOR_ROLE, config.claudeCommand, permissionMode, claudeSessionId, launchMode === "resume", model, effort),
|
|
235
|
-
cwd:
|
|
234
|
+
cwd: taskContext.taskRepoRoot
|
|
236
235
|
};
|
|
237
236
|
const runtimeSession = await deps.runtime.createSession({
|
|
238
237
|
taskSlug: PROJECT_TRANSLATOR_SCOPE,
|
|
@@ -242,8 +241,8 @@ export function createSessionService(deps) {
|
|
|
242
241
|
cwd: startCommand.cwd,
|
|
243
242
|
env: {
|
|
244
243
|
VCM_API_URL: deps.apiUrl,
|
|
245
|
-
VCM_TASK_REPO_ROOT:
|
|
246
|
-
VCM_TASK_SLUG:
|
|
244
|
+
VCM_TASK_REPO_ROOT: taskContext.taskRepoRoot,
|
|
245
|
+
VCM_TASK_SLUG: taskContext.taskSlug,
|
|
247
246
|
VCM_ROLE: TRANSLATOR_ROLE,
|
|
248
247
|
VCM_SESSION_ID: claudeSessionId
|
|
249
248
|
},
|
|
@@ -278,6 +277,7 @@ export function createSessionService(deps) {
|
|
|
278
277
|
return withHarnessRevisionView(repoRoot, record);
|
|
279
278
|
}
|
|
280
279
|
async function launchProjectHarnessEngineerSession(repoRoot, input, launchMode) {
|
|
280
|
+
const taskContext = await resolveProjectToolTaskContext(repoRoot, input, "Harness Engineer");
|
|
281
281
|
const live = toRoleSessionRecordView(getRegisteredProjectHarnessEngineerSession(deps.registry, deps.runtime), deps.runtime);
|
|
282
282
|
if (live && live.status === "running") {
|
|
283
283
|
return withHarnessRevisionView(repoRoot, live);
|
|
@@ -299,12 +299,10 @@ export function createSessionService(deps) {
|
|
|
299
299
|
});
|
|
300
300
|
}
|
|
301
301
|
await deps.fs.ensureDir(resolveRepoPath(repoRoot, HARNESS_ENGINEER_DIR));
|
|
302
|
-
const transcriptPath =
|
|
303
|
-
? persisted.transcriptPath
|
|
304
|
-
: claudeTranscriptPath(repoRoot, claudeSessionId);
|
|
302
|
+
const transcriptPath = claudeTranscriptPath(taskContext.taskRepoRoot, claudeSessionId);
|
|
305
303
|
const startCommand = {
|
|
306
304
|
...deps.claude.buildRoleStartCommand(HARNESS_ENGINEER_ROLE, config.claudeCommand, permissionMode, claudeSessionId, launchMode === "resume", model, effort),
|
|
307
|
-
cwd:
|
|
305
|
+
cwd: taskContext.taskRepoRoot
|
|
308
306
|
};
|
|
309
307
|
const runtimeSession = await deps.runtime.createSession({
|
|
310
308
|
taskSlug: PROJECT_HARNESS_ENGINEER_SCOPE,
|
|
@@ -314,8 +312,8 @@ export function createSessionService(deps) {
|
|
|
314
312
|
cwd: startCommand.cwd,
|
|
315
313
|
env: {
|
|
316
314
|
VCM_API_URL: deps.apiUrl,
|
|
317
|
-
VCM_TASK_REPO_ROOT:
|
|
318
|
-
VCM_TASK_SLUG:
|
|
315
|
+
VCM_TASK_REPO_ROOT: taskContext.taskRepoRoot,
|
|
316
|
+
VCM_TASK_SLUG: taskContext.taskSlug,
|
|
319
317
|
VCM_ROLE: HARNESS_ENGINEER_ROLE,
|
|
320
318
|
VCM_SESSION_ID: claudeSessionId
|
|
321
319
|
},
|
|
@@ -349,6 +347,22 @@ export function createSessionService(deps) {
|
|
|
349
347
|
await persistHarnessEngineerSession(deps.fs, repoRoot, record);
|
|
350
348
|
return withHarnessRevisionView(repoRoot, record);
|
|
351
349
|
}
|
|
350
|
+
async function resolveProjectToolTaskContext(repoRoot, input, roleLabel) {
|
|
351
|
+
const taskSlug = input.taskSlug?.trim();
|
|
352
|
+
if (!taskSlug) {
|
|
353
|
+
throw new VcmError({
|
|
354
|
+
code: "PROJECT_TOOL_TASK_REQUIRED",
|
|
355
|
+
message: `${roleLabel} requires an active task worktree.`,
|
|
356
|
+
statusCode: 409,
|
|
357
|
+
hint: "Create or select a task, then start or resume this project tool session."
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
const task = await deps.taskService.loadTask(repoRoot, taskSlug);
|
|
361
|
+
return {
|
|
362
|
+
taskSlug: task.taskSlug,
|
|
363
|
+
taskRepoRoot: getTaskRuntimeRepoRoot(task)
|
|
364
|
+
};
|
|
365
|
+
}
|
|
352
366
|
async function notifyHarnessUpdatedForSession(repoRoot, session) {
|
|
353
367
|
const runtimeSession = deps.runtime.getSession(session.id);
|
|
354
368
|
if (!runtimeSession || runtimeSession.status !== "running") {
|
|
@@ -515,6 +529,7 @@ export function createSessionService(deps) {
|
|
|
515
529
|
}
|
|
516
530
|
if (existing?.claudeSessionId) {
|
|
517
531
|
return this.resumeProjectTranslatorSession(repoRoot, {
|
|
532
|
+
taskSlug: input.taskSlug,
|
|
518
533
|
permissionMode: input.permissionMode ?? existing.permissionMode,
|
|
519
534
|
model: input.model ?? existing.model,
|
|
520
535
|
effort: input.effort ?? existing.effort,
|
|
@@ -611,6 +626,7 @@ export function createSessionService(deps) {
|
|
|
611
626
|
}
|
|
612
627
|
if (existing?.claudeSessionId) {
|
|
613
628
|
return this.resumeProjectHarnessEngineerSession(repoRoot, {
|
|
629
|
+
taskSlug: input.taskSlug,
|
|
614
630
|
permissionMode: input.permissionMode ?? existing.permissionMode,
|
|
615
631
|
model: input.model ?? existing.model,
|
|
616
632
|
effort: input.effort ?? existing.effort,
|
|
@@ -661,12 +677,10 @@ export function createSessionService(deps) {
|
|
|
661
677
|
.then((session) => scopeProjectRoleSession(session, taskSlug));
|
|
662
678
|
}
|
|
663
679
|
if (role === TRANSLATOR_ROLE) {
|
|
664
|
-
|
|
665
|
-
return this.startProjectTranslatorSession(repoRoot, input);
|
|
680
|
+
return this.startProjectTranslatorSession(repoRoot, { ...input, taskSlug });
|
|
666
681
|
}
|
|
667
682
|
if (role === HARNESS_ENGINEER_ROLE) {
|
|
668
|
-
|
|
669
|
-
return this.startProjectHarnessEngineerSession(repoRoot, input);
|
|
683
|
+
return this.startProjectHarnessEngineerSession(repoRoot, { ...input, taskSlug });
|
|
670
684
|
}
|
|
671
685
|
return launchRoleSession(repoRoot, taskSlug, role, input, "fresh");
|
|
672
686
|
},
|
|
@@ -676,12 +690,10 @@ export function createSessionService(deps) {
|
|
|
676
690
|
.then((session) => scopeProjectRoleSession(session, taskSlug));
|
|
677
691
|
}
|
|
678
692
|
if (role === TRANSLATOR_ROLE) {
|
|
679
|
-
|
|
680
|
-
return this.resumeProjectTranslatorSession(repoRoot, input);
|
|
693
|
+
return this.resumeProjectTranslatorSession(repoRoot, { ...input, taskSlug });
|
|
681
694
|
}
|
|
682
695
|
if (role === HARNESS_ENGINEER_ROLE) {
|
|
683
|
-
|
|
684
|
-
return this.resumeProjectHarnessEngineerSession(repoRoot, input);
|
|
696
|
+
return this.resumeProjectHarnessEngineerSession(repoRoot, { ...input, taskSlug });
|
|
685
697
|
}
|
|
686
698
|
return launchRoleSession(repoRoot, taskSlug, role, input, "resume");
|
|
687
699
|
},
|
|
@@ -732,12 +744,10 @@ export function createSessionService(deps) {
|
|
|
732
744
|
return scopeProjectRoleSession(await launchProjectGateReviewerSession(repoRoot, input, "fresh", taskSlug), taskSlug);
|
|
733
745
|
}
|
|
734
746
|
if (role === TRANSLATOR_ROLE) {
|
|
735
|
-
|
|
736
|
-
return this.restartProjectTranslatorSession(repoRoot, input);
|
|
747
|
+
return this.restartProjectTranslatorSession(repoRoot, { ...input, taskSlug });
|
|
737
748
|
}
|
|
738
749
|
if (role === HARNESS_ENGINEER_ROLE) {
|
|
739
|
-
|
|
740
|
-
return this.restartProjectHarnessEngineerSession(repoRoot, input);
|
|
750
|
+
return this.restartProjectHarnessEngineerSession(repoRoot, { ...input, taskSlug });
|
|
741
751
|
}
|
|
742
752
|
const existing = await this.getRoleSession(repoRoot, taskSlug, role);
|
|
743
753
|
if (!existing) {
|
|
@@ -18,22 +18,6 @@ export function createTaskService(deps) {
|
|
|
18
18
|
statusCode: 409
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
|
-
if (!(await deps.git.isIgnored(repoRoot, `${config.stateRoot}/.probe`))) {
|
|
22
|
-
throw new VcmError({
|
|
23
|
-
code: "VCM_STATE_NOT_IGNORED",
|
|
24
|
-
message: `${config.stateRoot}/ is not ignored by Git.`,
|
|
25
|
-
statusCode: 409,
|
|
26
|
-
hint: "Apply VCM Harness first so .gitignore contains the VCM managed block."
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
if (!(await deps.git.isIgnored(repoRoot, ".claude/worktrees/.probe"))) {
|
|
30
|
-
throw new VcmError({
|
|
31
|
-
code: "VCM_WORKTREES_NOT_IGNORED",
|
|
32
|
-
message: ".claude/worktrees/ is not ignored by Git.",
|
|
33
|
-
statusCode: 409,
|
|
34
|
-
hint: "Apply VCM Harness first so .gitignore ignores Claude-compatible task worktrees."
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
21
|
if (await deps.git.branchExists(repoRoot, taskBranch)) {
|
|
38
22
|
throw new VcmError({
|
|
39
23
|
code: "TASK_BRANCH_EXISTS",
|
|
@@ -50,13 +34,13 @@ export function createTaskService(deps) {
|
|
|
50
34
|
hint: "Choose a different task name or clean up the existing worktree."
|
|
51
35
|
});
|
|
52
36
|
}
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
37
|
+
const baseVisibleChanges = await getBaseRepoVisibleChanges(deps.git, repoRoot);
|
|
38
|
+
if (baseVisibleChanges.length > 0) {
|
|
55
39
|
throw new VcmError({
|
|
56
40
|
code: "BASE_REPO_DIRTY",
|
|
57
|
-
message: "The connected repository has uncommitted changes.",
|
|
41
|
+
message: "The connected repository has uncommitted Git-visible changes.",
|
|
58
42
|
statusCode: 409,
|
|
59
|
-
hint:
|
|
43
|
+
hint: `Commit, stash, or discard these changes before creating a task worktree: ${baseVisibleChanges.slice(0, 12).join(", ")}`
|
|
60
44
|
});
|
|
61
45
|
}
|
|
62
46
|
const timestamp = now();
|
|
@@ -168,6 +152,35 @@ export function createTaskService(deps) {
|
|
|
168
152
|
export function getTaskRuntimeRepoRoot(task) {
|
|
169
153
|
return task.worktreePath;
|
|
170
154
|
}
|
|
155
|
+
async function getBaseRepoVisibleChanges(git, repoRoot) {
|
|
156
|
+
const rawStatus = await git.getStatusPorcelainV1(repoRoot);
|
|
157
|
+
return parseGitStatusPaths(rawStatus).filter((filePath) => !isVcmRuntimePath(filePath));
|
|
158
|
+
}
|
|
159
|
+
function parseGitStatusPaths(rawStatus) {
|
|
160
|
+
const records = rawStatus.split("\0").filter(Boolean);
|
|
161
|
+
const paths = [];
|
|
162
|
+
for (let index = 0; index < records.length; index += 1) {
|
|
163
|
+
const record = records[index] ?? "";
|
|
164
|
+
if (record.length < 4) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const indexStatus = record[0] ?? " ";
|
|
168
|
+
const filePath = normalizeGitStatusPath(record.slice(3));
|
|
169
|
+
paths.push(filePath);
|
|
170
|
+
if (indexStatus === "R" || indexStatus === "C") {
|
|
171
|
+
index += 1;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return paths;
|
|
175
|
+
}
|
|
176
|
+
function normalizeGitStatusPath(value) {
|
|
177
|
+
return path.posix.normalize(value).replace(/^\.\//, "");
|
|
178
|
+
}
|
|
179
|
+
function isVcmRuntimePath(repoRelativePath) {
|
|
180
|
+
return repoRelativePath.startsWith(".ai/vcm/") ||
|
|
181
|
+
repoRelativePath.startsWith(".claude/worktrees/") ||
|
|
182
|
+
repoRelativePath.startsWith(".ai/tools/__pycache__/");
|
|
183
|
+
}
|
|
171
184
|
function getTaskPath(taskStoreRoot, taskSlug) {
|
|
172
185
|
return path.join(taskStoreRoot, "tasks", `${taskSlug}.json`);
|
|
173
186
|
}
|
|
@@ -904,6 +904,7 @@ export function createTranslationService(deps) {
|
|
|
904
904
|
});
|
|
905
905
|
}
|
|
906
906
|
return deps.translationWorkerService.createConversationJob(input.repoRoot, {
|
|
907
|
+
taskSlug: input.taskSlug,
|
|
907
908
|
direction: input.direction,
|
|
908
909
|
sourceText: input.text,
|
|
909
910
|
sourceLanguage: input.sourceLanguage,
|
|
@@ -207,7 +207,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
207
207
|
queue.updatedAt = next.updatedAt;
|
|
208
208
|
await saveQueue(repoRoot, queue);
|
|
209
209
|
}
|
|
210
|
-
const session = await ensureTranslatorSession(repoRoot, next.targetLanguage);
|
|
210
|
+
const session = await ensureTranslatorSession(repoRoot, next.targetLanguage, next.taskSlug);
|
|
211
211
|
await submitTerminalInput(deps.runtime, session.id, batch?.prompt ?? await buildQueuePrompt(repoRoot, next));
|
|
212
212
|
const dispatchedAt = now();
|
|
213
213
|
for (const item of batch?.items ?? [next]) {
|
|
@@ -255,7 +255,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
255
255
|
await saveQueue(repoRoot, queue);
|
|
256
256
|
return { items: candidates, prompt };
|
|
257
257
|
}
|
|
258
|
-
async function ensureTranslatorSession(repoRoot, targetLanguage) {
|
|
258
|
+
async function ensureTranslatorSession(repoRoot, targetLanguage, taskSlug) {
|
|
259
259
|
void targetLanguage;
|
|
260
260
|
if (!deps.sessionService) {
|
|
261
261
|
throw new VcmError({
|
|
@@ -265,6 +265,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
267
|
return deps.sessionService.ensureProjectTranslatorSession(repoRoot, {
|
|
268
|
+
taskSlug,
|
|
268
269
|
model: "default",
|
|
269
270
|
effort: "medium"
|
|
270
271
|
});
|
|
@@ -873,6 +874,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
873
874
|
},
|
|
874
875
|
async createFileJob(repoRoot, input) {
|
|
875
876
|
await ensureLayout(repoRoot);
|
|
877
|
+
const taskSlug = requireTranslationTaskSlug(input.taskSlug);
|
|
876
878
|
const sourcePath = normalizeRepoRelative(input.sourcePath);
|
|
877
879
|
const absoluteSourcePath = resolveRepoPath(repoRoot, sourcePath);
|
|
878
880
|
assertInsideRepo(repoRoot, absoluteSourcePath);
|
|
@@ -925,6 +927,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
925
927
|
type: input.force ? "force-retranslate" : "file",
|
|
926
928
|
status: "queued",
|
|
927
929
|
targetLanguage,
|
|
930
|
+
taskSlug,
|
|
928
931
|
jobId,
|
|
929
932
|
requestPath: job.requestPath,
|
|
930
933
|
expectedResultPath: job.resultPath,
|
|
@@ -997,6 +1000,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
997
1000
|
},
|
|
998
1001
|
async createBootstrapRun(repoRoot, input) {
|
|
999
1002
|
await ensureLayout(repoRoot);
|
|
1003
|
+
const taskSlug = requireTranslationTaskSlug(input.taskSlug);
|
|
1000
1004
|
const targetLanguage = input.targetLanguage.trim() || "zh-CN";
|
|
1001
1005
|
const candidatePaths = (input.candidatePaths?.length
|
|
1002
1006
|
? input.candidatePaths
|
|
@@ -1020,6 +1024,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
1020
1024
|
type: "bootstrap",
|
|
1021
1025
|
status: "queued",
|
|
1022
1026
|
targetLanguage,
|
|
1027
|
+
taskSlug,
|
|
1023
1028
|
jobId: runId,
|
|
1024
1029
|
requestPath: run.requestPath,
|
|
1025
1030
|
expectedResultPath: run.reportPath,
|
|
@@ -1054,6 +1059,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
1054
1059
|
},
|
|
1055
1060
|
async createMemoryUpdate(repoRoot, input) {
|
|
1056
1061
|
await ensureLayout(repoRoot);
|
|
1062
|
+
const taskSlug = requireTranslationTaskSlug(input.taskSlug);
|
|
1057
1063
|
const targetLanguage = input.targetLanguage.trim() || "zh-CN";
|
|
1058
1064
|
const timestamp = now();
|
|
1059
1065
|
const runId = `memory-update-${Date.now()}-${createId().slice(0, 8)}`;
|
|
@@ -1065,6 +1071,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
1065
1071
|
type: "memory-update",
|
|
1066
1072
|
status: "queued",
|
|
1067
1073
|
targetLanguage,
|
|
1074
|
+
taskSlug,
|
|
1068
1075
|
jobId: runId,
|
|
1069
1076
|
requestPath
|
|
1070
1077
|
});
|
|
@@ -1130,6 +1137,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
1130
1137
|
},
|
|
1131
1138
|
async createConversationJob(repoRoot, input) {
|
|
1132
1139
|
await ensureLayout(repoRoot);
|
|
1140
|
+
const taskSlug = requireTranslationTaskSlug(input.taskSlug);
|
|
1133
1141
|
const sourceText = input.sourceText.trimEnd();
|
|
1134
1142
|
if (!sourceText.trim()) {
|
|
1135
1143
|
throw new VcmError({
|
|
@@ -1159,6 +1167,7 @@ export function createTranslationWorkerService(deps) {
|
|
|
1159
1167
|
type: "conversation",
|
|
1160
1168
|
status: "queued",
|
|
1161
1169
|
targetLanguage,
|
|
1170
|
+
taskSlug,
|
|
1162
1171
|
jobId,
|
|
1163
1172
|
requestPath: job.requestPath,
|
|
1164
1173
|
expectedResultPath: job.resultPath
|
|
@@ -1287,10 +1296,27 @@ export function createTranslationWorkerService(deps) {
|
|
|
1287
1296
|
}
|
|
1288
1297
|
},
|
|
1289
1298
|
ensureTranslatorSession(repoRoot) {
|
|
1290
|
-
|
|
1299
|
+
void repoRoot;
|
|
1300
|
+
throw new VcmError({
|
|
1301
|
+
code: "TRANSLATION_TASK_REQUIRED",
|
|
1302
|
+
message: "Translator requires an active task worktree.",
|
|
1303
|
+
statusCode: 409
|
|
1304
|
+
});
|
|
1291
1305
|
}
|
|
1292
1306
|
};
|
|
1293
1307
|
}
|
|
1308
|
+
function requireTranslationTaskSlug(value) {
|
|
1309
|
+
const taskSlug = value?.trim();
|
|
1310
|
+
if (!taskSlug) {
|
|
1311
|
+
throw new VcmError({
|
|
1312
|
+
code: "TRANSLATION_TASK_REQUIRED",
|
|
1313
|
+
message: "Translation requires an active task worktree.",
|
|
1314
|
+
statusCode: 409,
|
|
1315
|
+
hint: "Create or select a task before starting translation."
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
return taskSlug;
|
|
1319
|
+
}
|
|
1294
1320
|
async function listBrowserEntries(repoRoot, fs, currentPath, limit) {
|
|
1295
1321
|
const directoryPath = resolveRepoPath(repoRoot, currentPath);
|
|
1296
1322
|
const names = (await fs.readDir(directoryPath)).filter((name) => !isIgnoredBrowserName(name));
|
|
@@ -1496,6 +1522,7 @@ function isQueueItem(value) {
|
|
|
1496
1522
|
typeof candidate.type === "string" &&
|
|
1497
1523
|
typeof candidate.status === "string" &&
|
|
1498
1524
|
typeof candidate.targetLanguage === "string" &&
|
|
1525
|
+
typeof candidate.taskSlug === "string" &&
|
|
1499
1526
|
typeof candidate.requestPath === "string";
|
|
1500
1527
|
}
|
|
1501
1528
|
function isFileJob(value) {
|
|
@@ -27,6 +27,7 @@ You are not part of the task workflow round state.
|
|
|
27
27
|
|
|
28
28
|
- Propose harness changes as reviewable diffs.
|
|
29
29
|
- Do not silently apply edits.
|
|
30
|
+
- During a VCM-managed bootstrap run, apply permitted bootstrap edits directly in the active task worktree and commit them yourself.
|
|
30
31
|
- Do not overwrite VCM fixed managed blocks.
|
|
31
32
|
- Keep project-specific customization outside VCM managed blocks.
|
|
32
33
|
- If a fixed managed block appears wrong, draft a VCM issue instead of editing
|
|
@@ -34,6 +35,7 @@ You are not part of the task workflow round state.
|
|
|
34
35
|
- Include affected files, impacted roles, session restart/reminder impact, and
|
|
35
36
|
validation recommendations with every proposal.
|
|
36
37
|
- Do not edit production source code as part of harness maintenance.
|
|
38
|
+
- VCM does not create Harness Engineer commits after your turn.
|
|
37
39
|
|
|
38
40
|
## VCM Feedback
|
|
39
41
|
|
|
@@ -19,7 +19,9 @@ This skill is an operating procedure. It does not replace the deterministic VCM
|
|
|
19
19
|
3. Fill project context: add or update non-managed project facts in \`CLAUDE.md\` above the VCM managed block.
|
|
20
20
|
4. Fill durable docs: update \`docs/ARCHITECTURE.md\`, module-level \`ARCHITECTURE.md\` files, and \`docs/TESTING.md\` with detailed project-specific content.
|
|
21
21
|
5. Preserve user-authored content and VCM managed blocks.
|
|
22
|
-
6.
|
|
22
|
+
6. Review \`git status\` and \`git diff\`.
|
|
23
|
+
7. Stage only allowed bootstrap harness changes and create a commit in the active task worktree.
|
|
24
|
+
8. Report evidence, commit hash, final git status, unknowns, confirmation-needed areas, generation failures, and recommended deterministic VCM actions.
|
|
23
25
|
|
|
24
26
|
## Typical Outputs
|
|
25
27
|
|
|
@@ -64,12 +66,20 @@ This skill is an operating procedure. It does not replace the deterministic VCM
|
|
|
64
66
|
- Keep historical investigation details, superseded failures, temporary diagnostics, and per-task validation logs out of \`docs/TESTING.md\`.
|
|
65
67
|
- Keep reviewer ownership of validation strategy and testing documentation clear.
|
|
66
68
|
|
|
69
|
+
### Commit
|
|
70
|
+
|
|
71
|
+
- Create the bootstrap commit yourself after the allowed files are updated.
|
|
72
|
+
- Do not include product source, product tests, package manifests, lockfiles, deployment config, secrets, or VCM managed-block changes in the commit.
|
|
73
|
+
- VCM will not commit bootstrap changes after your turn.
|
|
74
|
+
|
|
67
75
|
## Final Summary
|
|
68
76
|
|
|
69
77
|
Include:
|
|
70
78
|
|
|
71
79
|
- files reviewed
|
|
72
80
|
- files drafted or updated
|
|
81
|
+
- commit hash
|
|
82
|
+
- final git status
|
|
73
83
|
- verified claims
|
|
74
84
|
- inferred claims
|
|
75
85
|
- unknowns
|