vibe-coding-master 0.4.0 → 0.4.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/README.md CHANGED
@@ -486,7 +486,7 @@ For `.gitignore`, VCM uses a gitignore-native managed block:
486
486
 
487
487
  VCM also JSON-merges `.claude/settings.json` to install Claude Code `PreToolUse`, `UserPromptSubmit`, `Stop`, and `PermissionRequest` hooks plus a managed `env.BASH_DEFAULT_TIMEOUT_MS` so foreground watch windows fit inside the Bash tool timeout. 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. The `Stop` hook forwards the backend response to Claude Code, which lets VCM block turn-end while a validation job is still running.
488
488
 
489
- 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:
489
+ Bootstrap is AI-assisted. VCM starts or resumes the project-scoped Harness Engineer 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:
490
490
 
491
491
  ```text
492
492
  CLAUDE.md project context outside the VCM managed block
@@ -167,14 +167,6 @@ export function createDefaultServerDeps(options = {}) {
167
167
  const registry = createSessionRegistry();
168
168
  const artifactService = createArtifactService(fs);
169
169
  const projectService = createProjectService({ fs, git, appSettings });
170
- const harnessService = createHarnessService({
171
- fs,
172
- git,
173
- runtime,
174
- projectService,
175
- apiUrl: options.apiUrl,
176
- runFixedInstaller: createScriptFixedHarnessInstaller(path.join(getAppRoot(), "scripts/install-vcm-harness.mjs"))
177
- });
178
170
  const taskService = createTaskService({ fs, git, artifactService, projectService });
179
171
  const sessionService = createSessionService({
180
172
  fs,
@@ -186,6 +178,13 @@ export function createDefaultServerDeps(options = {}) {
186
178
  taskService,
187
179
  apiUrl: options.apiUrl
188
180
  });
181
+ const harnessService = createHarnessService({
182
+ fs,
183
+ git,
184
+ runtime,
185
+ harnessEngineerSessions: sessionService,
186
+ runFixedInstaller: createScriptFixedHarnessInstaller(path.join(getAppRoot(), "scripts/install-vcm-harness.mjs"))
187
+ });
189
188
  const commandDispatcher = createCommandDispatcher({
190
189
  runtime,
191
190
  sessionService,
@@ -264,6 +263,7 @@ export function createDefaultServerDeps(options = {}) {
264
263
  translationService,
265
264
  appSettings,
266
265
  runtime,
266
+ harnessService,
267
267
  gatewayService,
268
268
  jobGuard: createJobGuardService(),
269
269
  translationWorkerService
@@ -83,6 +83,11 @@ export function createClaudeHookService(deps) {
83
83
  transcriptPath: stringOrUndefined(input.event.transcript_path),
84
84
  cwd: stringOrUndefined(input.event.cwd)
85
85
  });
86
+ await deps.harnessService?.recordHarnessBootstrapHook(context.project.repoRoot, {
87
+ eventName,
88
+ sessionId: session?.id,
89
+ claudeSessionId: stringOrUndefined(input.event.session_id)
90
+ });
86
91
  return {
87
92
  ok: true,
88
93
  eventName,
@@ -1,4 +1,3 @@
1
- import { randomUUID } from "node:crypto";
2
1
  import { execFile } from "node:child_process";
3
2
  import path from "node:path";
4
3
  import { promisify } from "node:util";
@@ -19,10 +18,8 @@ import { submitTerminalInput } from "../runtime/terminal-submit.js";
19
18
  import { VcmError } from "../errors.js";
20
19
  import { bumpHarnessRevision, readHarnessRevisionState } from "./harness-revision.js";
21
20
  const execFileAsync = promisify(execFile);
22
- const BOOTSTRAP_TASK_SLUG = "__vcm-harness-bootstrap__";
23
- const BOOTSTRAP_RUNTIME_ROLE = "project-manager";
24
- const BOOTSTRAP_LOG_PATH = ".ai/vcm/bootstrap/bootstrap.log";
25
21
  const BOOTSTRAP_SESSION_PATH = ".ai/vcm/bootstrap/session.json";
22
+ const HARNESS_ENGINEER_SESSION_PATH = ".ai/vcm/harness-engineer/session.json";
26
23
  export const VCM_HARNESS_VERSION = 1;
27
24
  const MANAGED_BLOCK_PATTERN = /<!-- VCM:BEGIN(?:\s+version=(\d+))? -->[\s\S]*?<!-- VCM:END -->/m;
28
25
  const HASH_MANAGED_BLOCK_PATTERN = /# VCM:BEGIN(?:\s+version=(\d+))?\n[\s\S]*?# VCM:END/m;
@@ -307,7 +304,7 @@ export function createHarnessService(deps) {
307
304
  return getHarnessBootstrapStatus(deps, repoRoot, now);
308
305
  },
309
306
  async startHarnessBootstrap(repoRoot, input = {}) {
310
- const session = await launchHarnessBootstrapSession(deps, repoRoot, now, input, { forceFresh: false });
307
+ const session = await ensureHarnessEngineerForBootstrap(deps, repoRoot, now, input);
311
308
  const nextStatus = await getHarnessBootstrapStatus(deps, repoRoot, now);
312
309
  return {
313
310
  status: {
@@ -319,11 +316,7 @@ export function createHarnessService(deps) {
319
316
  };
320
317
  },
321
318
  async restartHarnessBootstrap(repoRoot, input = {}) {
322
- const existing = await getCurrentHarnessBootstrapSession(deps, repoRoot, now);
323
- if (existing && deps.runtime?.getSession(existing.id)) {
324
- await deps.runtime.stop(existing.id);
325
- }
326
- const session = await launchHarnessBootstrapSession(deps, repoRoot, now, input, { forceFresh: true });
319
+ const session = await restartHarnessEngineerForBootstrap(deps, repoRoot, now, input);
327
320
  const nextStatus = await getHarnessBootstrapStatus(deps, repoRoot, now);
328
321
  return {
329
322
  status: {
@@ -335,26 +328,20 @@ export function createHarnessService(deps) {
335
328
  };
336
329
  },
337
330
  async stopHarnessBootstrap(repoRoot) {
338
- const existing = await getCurrentHarnessBootstrapSession(deps, repoRoot, now);
331
+ const existing = await getCurrentHarnessEngineerBootstrapSession(deps, repoRoot);
339
332
  if (!existing) {
340
333
  throw new VcmError({
341
334
  code: "HARNESS_BOOTSTRAP_SESSION_MISSING",
342
- message: "Harness bootstrap terminal has not been started.",
335
+ message: "Harness Engineer session has not been started.",
343
336
  statusCode: 404
344
337
  });
345
338
  }
346
- if (deps.runtime?.getSession(existing.id)) {
347
- await deps.runtime.stop(existing.id);
348
- }
349
- await persistHarnessBootstrapSession(deps.fs, repoRoot, {
350
- ...existing,
351
- status: "exited",
352
- updatedAt: now()
353
- });
339
+ await deps.harnessEngineerSessions?.stopProjectHarnessEngineerSession(repoRoot);
340
+ await clearHarnessBootstrapRunState(deps.fs, repoRoot);
354
341
  return getHarnessBootstrapStatus(deps, repoRoot, now);
355
342
  },
356
343
  async runHarnessBootstrap(repoRoot) {
357
- if (!deps.runtime) {
344
+ if (!deps.runtime || !deps.harnessEngineerSessions) {
358
345
  throw new VcmError({
359
346
  code: "HARNESS_BOOTSTRAP_UNAVAILABLE",
360
347
  message: "Harness bootstrap sessions are not available in this VCM runtime.",
@@ -366,11 +353,20 @@ export function createHarnessService(deps) {
366
353
  if (!session || session.status !== "running" || !deps.runtime.getSession(session.id)) {
367
354
  throw new VcmError({
368
355
  code: "HARNESS_BOOTSTRAP_SESSION_NOT_RUNNING",
369
- message: "Start the Harness Bootstrap terminal before running bootstrap.",
356
+ message: "Start the Harness Engineer session before running bootstrap.",
370
357
  statusCode: 409
371
358
  });
372
359
  }
373
360
  const prompt = buildHarnessBootstrapPrompt(repoRoot);
361
+ const timestamp = now();
362
+ await persistHarnessBootstrapRunState(deps.fs, repoRoot, {
363
+ version: 1,
364
+ status: "running",
365
+ sessionId: session.id,
366
+ claudeSessionId: session.claudeSessionId,
367
+ startedAt: timestamp,
368
+ updatedAt: timestamp
369
+ });
374
370
  await submitTerminalInput(deps.runtime, session.id, prompt);
375
371
  const nextStatus = await getHarnessBootstrapStatus(deps, repoRoot, now);
376
372
  return {
@@ -381,6 +377,21 @@ export function createHarnessService(deps) {
381
377
  session,
382
378
  prompt
383
379
  };
380
+ },
381
+ async recordHarnessBootstrapHook(repoRoot, input) {
382
+ const state = await loadPersistedHarnessBootstrapRunState(deps.fs, repoRoot);
383
+ if (state?.status !== "running" || !matchesBootstrapRunState(state, input)) {
384
+ return getHarnessBootstrapStatus(deps, repoRoot, now);
385
+ }
386
+ const timestamp = now();
387
+ await persistHarnessBootstrapRunState(deps.fs, repoRoot, {
388
+ ...state,
389
+ status: input.eventName === "Stop" ? "complete" : state.status,
390
+ completedAt: input.eventName === "Stop" ? timestamp : state.completedAt,
391
+ updatedAt: timestamp,
392
+ lastHookEvent: input.eventName
393
+ });
394
+ return getHarnessBootstrapStatus(deps, repoRoot, now);
384
395
  }
385
396
  };
386
397
  }
@@ -400,8 +411,8 @@ function dedupeHarnessChanges(changedFiles) {
400
411
  }
401
412
  return changes;
402
413
  }
403
- async function launchHarnessBootstrapSession(deps, repoRoot, now, input, options) {
404
- if (!deps.runtime || !deps.projectService) {
414
+ async function ensureHarnessEngineerForBootstrap(deps, repoRoot, now, input) {
415
+ if (!deps.harnessEngineerSessions) {
405
416
  throw new VcmError({
406
417
  code: "HARNESS_BOOTSTRAP_UNAVAILABLE",
407
418
  message: "Harness bootstrap sessions are not available in this VCM runtime.",
@@ -409,56 +420,62 @@ async function launchHarnessBootstrapSession(deps, repoRoot, now, input, options
409
420
  });
410
421
  }
411
422
  const currentStatus = await getHarnessBootstrapStatus(deps, repoRoot, now);
412
- if (!options.forceFresh && currentStatus.session?.status === "running") {
423
+ if (currentStatus.session?.status === "running") {
413
424
  return currentStatus.session;
414
425
  }
415
- if (!currentStatus.canStart && !(options.forceFresh && currentStatus.session?.status === "running")) {
426
+ if (!currentStatus.canStart) {
416
427
  throw new VcmError({
417
428
  code: "HARNESS_BOOTSTRAP_NOT_READY",
418
429
  message: "Install the fixed VCM harness before starting harness bootstrap.",
419
430
  statusCode: 409
420
431
  });
421
432
  }
422
- const config = await deps.projectService.loadConfig(repoRoot);
423
- const claudeSessionId = randomUUID();
424
- const permissionMode = normalizeClaudePermissionMode(input.permissionMode);
425
- const model = normalizeClaudeModel(input.model);
426
- const effort = normalizeClaudeEffort(input.effort);
427
- const command = buildClaudeStartCommand(config.claudeCommand, permissionMode, claudeSessionId, model, effort);
428
- const logPath = path.join(repoRoot, BOOTSTRAP_LOG_PATH);
429
- const runtimeSession = await deps.runtime.createSession({
430
- taskSlug: BOOTSTRAP_TASK_SLUG,
431
- role: BOOTSTRAP_RUNTIME_ROLE,
432
- command: command.command,
433
- args: command.args,
434
- cwd: repoRoot,
435
- env: {
436
- VCM_API_URL: deps.apiUrl,
437
- VCM_TASK_REPO_ROOT: repoRoot,
438
- VCM_HARNESS_BOOTSTRAP: "1",
439
- VCM_SESSION_ID: claudeSessionId
440
- },
441
- cols: input.cols,
442
- rows: input.rows,
443
- logPath
444
- });
445
- const session = {
446
- id: runtimeSession.id,
447
- claudeSessionId,
448
- status: runtimeSession.status === "crashed" ? "crashed" : runtimeSession.status === "exited" ? "exited" : "running",
449
- command: command.display,
450
- permissionMode,
451
- model,
452
- effort,
453
- cwd: repoRoot,
454
- logPath: BOOTSTRAP_LOG_PATH,
455
- startedAt: runtimeSession.startedAt,
456
- updatedAt: now(),
457
- lastOutputAt: runtimeSession.lastOutputAt,
458
- exitCode: runtimeSession.exitCode
433
+ return toHarnessBootstrapSession(await deps.harnessEngineerSessions.ensureProjectHarnessEngineerSession(repoRoot, input));
434
+ }
435
+ async function restartHarnessEngineerForBootstrap(deps, repoRoot, now, input) {
436
+ if (!deps.harnessEngineerSessions) {
437
+ throw new VcmError({
438
+ code: "HARNESS_BOOTSTRAP_UNAVAILABLE",
439
+ message: "Harness bootstrap sessions are not available in this VCM runtime.",
440
+ statusCode: 501
441
+ });
442
+ }
443
+ const currentStatus = await getHarnessBootstrapStatus(deps, repoRoot, now);
444
+ if (!currentStatus.canStart) {
445
+ throw new VcmError({
446
+ code: "HARNESS_BOOTSTRAP_NOT_READY",
447
+ message: "Install the fixed VCM harness before starting harness bootstrap.",
448
+ statusCode: 409
449
+ });
450
+ }
451
+ return toHarnessBootstrapSession(await deps.harnessEngineerSessions.restartProjectHarnessEngineerSession(repoRoot, input));
452
+ }
453
+ async function getCurrentHarnessEngineerBootstrapSession(deps, repoRoot) {
454
+ const session = await deps.harnessEngineerSessions?.getProjectHarnessEngineerSession(repoRoot);
455
+ return session ? toHarnessBootstrapSession(session) : undefined;
456
+ }
457
+ function toHarnessBootstrapSession(session) {
458
+ return {
459
+ id: session.id,
460
+ claudeSessionId: session.claudeSessionId,
461
+ status: toBootstrapSessionStatus(session.status),
462
+ command: session.command,
463
+ permissionMode: session.permissionMode,
464
+ model: session.model,
465
+ effort: session.effort,
466
+ cwd: session.cwd,
467
+ logPath: HARNESS_ENGINEER_SESSION_PATH,
468
+ startedAt: session.startedAt,
469
+ updatedAt: session.updatedAt,
470
+ lastOutputAt: session.lastOutputAt,
471
+ exitCode: session.exitCode
459
472
  };
460
- await persistHarnessBootstrapSession(deps.fs, repoRoot, session);
461
- return session;
473
+ }
474
+ function toBootstrapSessionStatus(status) {
475
+ if (status === "running" || status === "crashed" || status === "exited" || status === "resumable") {
476
+ return status;
477
+ }
478
+ return status === "missing" ? "resumable" : "exited";
462
479
  }
463
480
  function normalizeHarnessGitPath(value) {
464
481
  if (!value || value.includes("\0") || path.posix.isAbsolute(value)) {
@@ -909,26 +926,28 @@ async function getHarnessBootstrapStatus(deps, repoRoot, now) {
909
926
  await checkModuleArchitectureDocs(deps.fs, repoRoot, moduleIndex),
910
927
  await checkFilledMarkdown(deps.fs, repoRoot, "docs/TESTING.md", "Testing doc", "testing-doc")
911
928
  ];
912
- const session = await getCurrentHarnessBootstrapSession(deps, repoRoot, now);
929
+ const runState = await loadPersistedHarnessBootstrapRunState(deps.fs, repoRoot);
930
+ const session = await getCurrentHarnessEngineerBootstrapSession(deps, repoRoot);
913
931
  const fixedHarnessReady = checks[0]?.status === "ok";
914
932
  const projectChecks = checks.slice(1);
915
933
  const projectComplete = projectChecks.every((check) => check.status === "ok");
916
934
  const projectStarted = projectChecks.some((check) => check.status === "ok" || check.status === "incomplete");
935
+ const runActive = runState?.status === "running" && session?.status === "running";
917
936
  const status = !fixedHarnessReady
918
937
  ? "not_ready"
919
- : session?.status === "running"
938
+ : runActive
920
939
  ? "running"
921
- : projectComplete
940
+ : runState?.status === "complete" || projectComplete
922
941
  ? "complete"
923
942
  : projectStarted
924
943
  ? "incomplete"
925
944
  : "not_started";
926
945
  return {
927
946
  status,
928
- canStart: fixedHarnessReady && session?.status !== "running",
947
+ canStart: fixedHarnessReady && !runActive,
929
948
  checks,
930
949
  session,
931
- warnings: bootstrapWarnings(status, checks, session)
950
+ warnings: bootstrapWarnings(status, checks, session, runState)
932
951
  };
933
952
  }
934
953
  async function checkFixedHarness(fs, repoRoot) {
@@ -1129,74 +1148,47 @@ function isFilledMarkdown(content) {
1129
1148
  .filter((line) => line && !line.startsWith("#"));
1130
1149
  return meaningfulLines.join("\n").length >= 120;
1131
1150
  }
1132
- async function getCurrentHarnessBootstrapSession(deps, repoRoot, now) {
1133
- const persisted = await loadPersistedHarnessBootstrapSession(deps.fs, repoRoot);
1134
- const runtimeSession = deps.runtime
1135
- ?.listSessions(BOOTSTRAP_TASK_SLUG)
1136
- .find((session) => session.id === persisted?.id || session.status === "running");
1137
- if (runtimeSession) {
1138
- const session = {
1139
- id: runtimeSession.id,
1140
- claudeSessionId: persisted?.claudeSessionId ?? runtimeSession.id,
1141
- status: runtimeSession.status === "crashed" ? "crashed" : runtimeSession.status === "exited" ? "exited" : "running",
1142
- command: persisted?.command ?? "claude",
1143
- permissionMode: persisted?.permissionMode,
1144
- model: persisted?.model,
1145
- effort: persisted?.effort,
1146
- cwd: persisted?.cwd ?? repoRoot,
1147
- logPath: persisted?.logPath ?? BOOTSTRAP_LOG_PATH,
1148
- startedAt: runtimeSession.startedAt,
1149
- updatedAt: now(),
1150
- lastOutputAt: runtimeSession.lastOutputAt,
1151
- exitCode: runtimeSession.exitCode
1152
- };
1153
- await persistHarnessBootstrapSession(deps.fs, repoRoot, session);
1154
- return session;
1155
- }
1156
- if (persisted?.status === "running") {
1157
- return {
1158
- ...persisted,
1159
- status: "resumable",
1160
- updatedAt: now()
1161
- };
1162
- }
1163
- return undefined;
1164
- }
1165
- async function loadPersistedHarnessBootstrapSession(fs, repoRoot) {
1151
+ async function loadPersistedHarnessBootstrapRunState(fs, repoRoot) {
1166
1152
  const payload = await readOptionalJsonObject(fs, repoRoot, BOOTSTRAP_SESSION_PATH);
1167
1153
  if (!payload) {
1168
1154
  return undefined;
1169
1155
  }
1170
- if (typeof payload.id !== "string" ||
1171
- typeof payload.claudeSessionId !== "string" ||
1172
- typeof payload.command !== "string" ||
1173
- typeof payload.cwd !== "string" ||
1174
- typeof payload.logPath !== "string" ||
1156
+ if (payload.version !== 1 ||
1175
1157
  typeof payload.updatedAt !== "string") {
1176
1158
  return undefined;
1177
1159
  }
1178
1160
  const status = payload.status;
1179
- if (status !== "running" && status !== "exited" && status !== "crashed" && status !== "resumable") {
1161
+ if (status !== "running" && status !== "complete") {
1180
1162
  return undefined;
1181
1163
  }
1182
1164
  return {
1183
- id: payload.id,
1184
- claudeSessionId: payload.claudeSessionId,
1165
+ version: 1,
1185
1166
  status,
1186
- command: payload.command,
1187
- permissionMode: normalizeClaudePermissionMode(payload.permissionMode),
1188
- model: normalizeClaudeModel(payload.model),
1189
- effort: normalizeClaudeEffort(payload.effort),
1190
- cwd: payload.cwd,
1191
- logPath: payload.logPath,
1167
+ sessionId: typeof payload.sessionId === "string" ? payload.sessionId : undefined,
1168
+ claudeSessionId: typeof payload.claudeSessionId === "string" ? payload.claudeSessionId : undefined,
1192
1169
  startedAt: typeof payload.startedAt === "string" ? payload.startedAt : undefined,
1170
+ completedAt: typeof payload.completedAt === "string" ? payload.completedAt : undefined,
1193
1171
  updatedAt: payload.updatedAt,
1194
- lastOutputAt: typeof payload.lastOutputAt === "string" ? payload.lastOutputAt : undefined,
1195
- exitCode: typeof payload.exitCode === "number" || payload.exitCode === null ? payload.exitCode : undefined
1172
+ lastHookEvent: isHarnessBootstrapHookEvent(payload.lastHookEvent) ? payload.lastHookEvent : undefined
1196
1173
  };
1197
1174
  }
1198
- async function persistHarnessBootstrapSession(fs, repoRoot, session) {
1199
- await fs.writeJsonAtomic(resolveHarnessPath(repoRoot, BOOTSTRAP_SESSION_PATH), session);
1175
+ async function persistHarnessBootstrapRunState(fs, repoRoot, state) {
1176
+ await fs.writeJsonAtomic(resolveHarnessPath(repoRoot, BOOTSTRAP_SESSION_PATH), state);
1177
+ }
1178
+ async function clearHarnessBootstrapRunState(fs, repoRoot) {
1179
+ await fs.removePath?.(resolveHarnessPath(repoRoot, BOOTSTRAP_SESSION_PATH), { force: true });
1180
+ }
1181
+ function isHarnessBootstrapHookEvent(value) {
1182
+ return value === "Stop" || value === "StopFailure" || value === "UserPromptSubmit" || value === "PostCompact";
1183
+ }
1184
+ function matchesBootstrapRunState(state, input) {
1185
+ if (state.sessionId && input.sessionId && state.sessionId !== input.sessionId) {
1186
+ return false;
1187
+ }
1188
+ if (state.claudeSessionId && input.claudeSessionId && state.claudeSessionId !== input.claudeSessionId) {
1189
+ return false;
1190
+ }
1191
+ return true;
1200
1192
  }
1201
1193
  async function readOptionalText(fs, repoRoot, relativePath) {
1202
1194
  const absolutePath = resolveHarnessPath(repoRoot, relativePath);
@@ -1220,13 +1212,16 @@ async function readOptionalJsonObject(fs, repoRoot, relativePath) {
1220
1212
  return undefined;
1221
1213
  }
1222
1214
  }
1223
- function bootstrapWarnings(status, checks, session) {
1215
+ function bootstrapWarnings(status, checks, session, runState) {
1224
1216
  const warnings = [];
1225
1217
  if (status === "not_ready") {
1226
1218
  warnings.push("Install or update the fixed VCM harness before running harness bootstrap.");
1227
1219
  }
1228
1220
  if (session?.status === "resumable") {
1229
- warnings.push("The previous bootstrap terminal is no longer active; start bootstrap again or finish the remaining files manually.");
1221
+ warnings.push("The Harness Engineer session is resumable; resume it before running harness bootstrap.");
1222
+ }
1223
+ if (runState?.status === "running" && session?.status !== "running") {
1224
+ warnings.push("The previous bootstrap run did not finish with an active Harness Engineer session; resume the session or run bootstrap again.");
1230
1225
  }
1231
1226
  const unknownChecks = checks.filter((check) => check.status === "unknown");
1232
1227
  if (unknownChecks.length > 0) {
@@ -1234,56 +1229,6 @@ function bootstrapWarnings(status, checks, session) {
1234
1229
  }
1235
1230
  return warnings;
1236
1231
  }
1237
- function buildClaudeStartCommand(command = "claude", permissionMode = "default", claudeSessionId, model = "default", effort = "default") {
1238
- const args = ["--session-id", claudeSessionId, "--model", model];
1239
- if (effort === "ultracode") {
1240
- args.push("--settings", JSON.stringify({ ultracode: true }));
1241
- }
1242
- else if (effort !== "default") {
1243
- args.push("--effort", effort);
1244
- }
1245
- if (permissionMode === "bypassPermissions") {
1246
- args.push("--permission-mode", "bypassPermissions");
1247
- }
1248
- return {
1249
- command,
1250
- args,
1251
- display: [command, ...args].map(formatDisplayArg).join(" ")
1252
- };
1253
- }
1254
- function formatDisplayArg(value) {
1255
- if (/^[A-Za-z0-9_./:=@+-]+$/.test(value)) {
1256
- return value;
1257
- }
1258
- return `'${value.replaceAll("'", "'\\''")}'`;
1259
- }
1260
- function normalizeClaudePermissionMode(value) {
1261
- return value === "bypassPermissions" || value === "dangerously-skip-permissions"
1262
- ? "bypassPermissions"
1263
- : "default";
1264
- }
1265
- function normalizeClaudeModel(value) {
1266
- if (value === "best"
1267
- || value === "fable"
1268
- || value === "opus"
1269
- || value === "opus[1m]"
1270
- || value === "claude-opus-4-8"
1271
- || value === "claude-opus-4-8[1m]") {
1272
- return value;
1273
- }
1274
- return "default";
1275
- }
1276
- function normalizeClaudeEffort(value) {
1277
- if (value === "low"
1278
- || value === "medium"
1279
- || value === "high"
1280
- || value === "xhigh"
1281
- || value === "max"
1282
- || value === "ultracode") {
1283
- return value;
1284
- }
1285
- return "default";
1286
- }
1287
1232
  function buildHarnessBootstrapPrompt(repoRoot) {
1288
1233
  return `Use the vcm-harness-bootstrap skill to finish the VCM harness bootstrap for this repository.
1289
1234