vibe-coding-master 0.6.17 → 0.6.19

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.
@@ -6,6 +6,7 @@ import process from "node:process";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { renderArchitectHarnessRules } from "../templates/harness/architect-agent.js";
8
8
  import { renderCoderHarnessRules } from "../templates/harness/coder-agent.js";
9
+ import { renderCoderWorkerHarnessRules } from "../templates/harness/coder-worker-agent.js";
9
10
  import { renderGateReviewerAgentRules, renderRequestGateReviewTool, renderTranslatorAgentRules, renderVcmGateReviewSkillRules } from "../templates/harness/gate-review.js";
10
11
  import { renderHarnessEngineerHarnessRules } from "../templates/harness/harness-engineer-agent.js";
11
12
  import { renderRootClaudeHarnessRules } from "../templates/harness/claude-root.js";
@@ -52,7 +53,8 @@ const AGENT_FRONTMATTER = {
52
53
  description: "VCM architecture role for plans, module boundaries, public contracts, verifiable behavior, and docs sync."
53
54
  },
54
55
  coder: {
55
- description: "VCM implementation role for scoped code changes and focused tests."
56
+ description: "VCM implementation role for scoped code changes and focused tests.",
57
+ tools: "Read, Grep, Glob, Bash, Edit, Write, Agent"
56
58
  },
57
59
  reviewer: {
58
60
  description: "VCM independent review role for acceptance, test adequacy, scope checks, and risk findings."
@@ -65,6 +67,10 @@ const AGENT_FRONTMATTER = {
65
67
  },
66
68
  "harness-engineer": {
67
69
  description: "VCM project-scoped harness maintenance role for harness diagnosis, diff proposals, and VCM issue drafts."
70
+ },
71
+ "vcm-coder-worker": {
72
+ description: "Bounded VCM implementation worker for assigned modules, files, and VCM:CODE markers from Coder.",
73
+ model: "inherit"
68
74
  }
69
75
  };
70
76
  const MANAGED_FILES = [
@@ -146,6 +152,14 @@ const MANAGED_FILES = [
146
152
  commentStyle: "html",
147
153
  category: "agent-harness-engineer",
148
154
  content: renderHarnessEngineerHarnessRules()
155
+ },
156
+ {
157
+ path: ".claude/agents/vcm-coder-worker.md",
158
+ title: "VCM Coder Worker Agent",
159
+ agentName: "vcm-coder-worker",
160
+ commentStyle: "html",
161
+ category: "agent-coder-worker",
162
+ content: renderCoderWorkerHarnessRules()
149
163
  }
150
164
  ];
151
165
  const DURABLE_DOC_TEMPLATES = [
@@ -528,7 +542,9 @@ function renderManagedBlock(definition) {
528
542
  function renderNewManagedFile(definition, block) {
529
543
  if (definition.agentName) {
530
544
  const frontmatter = AGENT_FRONTMATTER[definition.agentName];
531
- return `---\nname: ${definition.agentName}\ndescription: ${frontmatter.description}\ntools: Read, Grep, Glob, Bash, Edit, Write\n---\n\n# ${definition.title}\n\n${block}\n`;
545
+ const tools = frontmatter.tools ?? "Read, Grep, Glob, Bash, Edit, Write";
546
+ const model = frontmatter.model ? `\nmodel: ${frontmatter.model}` : "";
547
+ return `---\nname: ${definition.agentName}\ndescription: ${frontmatter.description}\ntools: ${tools}${model}\n---\n\n# ${definition.title}\n\n${block}\n`;
532
548
  }
533
549
  return `# ${definition.title}\n\n${block}\n`;
534
550
  }
@@ -3,6 +3,7 @@ import path from "node:path";
3
3
  import { promisify } from "node:util";
4
4
  import { renderArchitectHarnessRules } from "../templates/harness/architect-agent.js";
5
5
  import { renderCoderHarnessRules } from "../templates/harness/coder-agent.js";
6
+ import { renderCoderWorkerHarnessRules } from "../templates/harness/coder-worker-agent.js";
6
7
  import { renderGateReviewerAgentRules, renderRequestGateReviewTool, renderTranslatorAgentRules, renderVcmGateReviewSkillRules } from "../templates/harness/gate-review.js";
7
8
  import { renderHarnessEngineerHarnessRules } from "../templates/harness/harness-engineer-agent.js";
8
9
  import { renderRootClaudeHarnessRules } from "../templates/harness/claude-root.js";
@@ -135,6 +136,13 @@ const HARNESS_FILES = [
135
136
  frontmatter: renderAgentFrontmatter("harness-engineer", "VCM project-scoped harness maintenance role for harness diagnosis, diff proposals, and VCM issue drafts."),
136
137
  renderRules: renderHarnessEngineerHarnessRules
137
138
  },
139
+ {
140
+ kind: "agent-coder-worker",
141
+ path: ".claude/agents/vcm-coder-worker.md",
142
+ title: "VCM Coder Worker Agent",
143
+ frontmatter: renderAgentFrontmatter("vcm-coder-worker", "Bounded VCM implementation worker for assigned modules, files, and VCM:CODE markers from Coder.", { model: "inherit" }),
144
+ renderRules: renderCoderWorkerHarnessRules
145
+ },
138
146
  {
139
147
  kind: "tool-request-gate-review",
140
148
  path: ".ai/tools/request-gate-review",
@@ -161,7 +169,7 @@ const HARNESS_FILES = [
161
169
  kind: "agent-coder",
162
170
  path: ".claude/agents/coder.md",
163
171
  title: "Coder Agent",
164
- frontmatter: renderAgentFrontmatter("coder", "VCM implementation role for scoped code changes and focused tests."),
172
+ frontmatter: renderAgentFrontmatter("coder", "VCM implementation role for scoped code changes and focused tests.", { tools: "Read, Grep, Glob, Bash, Edit, Write, Agent" }),
165
173
  renderRules: renderCoderHarnessRules
166
174
  },
167
175
  {
@@ -1279,8 +1287,10 @@ function isVcmHookMatcher(value) {
1279
1287
  function isPlainObject(value) {
1280
1288
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1281
1289
  }
1282
- function renderAgentFrontmatter(name, description) {
1283
- return `---\nname: ${name}\ndescription: ${description}\ntools: Read, Grep, Glob, Bash, Edit, Write\n---`;
1290
+ function renderAgentFrontmatter(name, description, options = {}) {
1291
+ const tools = options.tools ?? "Read, Grep, Glob, Bash, Edit, Write";
1292
+ const model = options.model ? `\nmodel: ${options.model}` : "";
1293
+ return `---\nname: ${name}\ndescription: ${description}\ntools: ${tools}${model}\n---`;
1284
1294
  }
1285
1295
  function renderSkillFrontmatter(name, description) {
1286
1296
  return `---\nname: ${name}\ndescription: ${description}\n---`;
@@ -1,6 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  const ACTIVE_JOB_STATUSES = new Set(["queued", "starting", "running"]);
4
+ const ACTIVE_CODER_WORKER_STATUSES = new Set(["planned", "running", "completed", "failed"]);
4
5
  const QUEUED_JOB_FRESH_MS = 120_000;
5
6
  export const MAX_CONSECUTIVE_STOP_BLOCKS = 3;
6
7
  export function createJobGuardService(deps = {}) {
@@ -73,19 +74,26 @@ export function createJobGuardService(deps = {}) {
73
74
  async evaluateStop(input) {
74
75
  const key = stateKey(input);
75
76
  const jobs = await findActiveJobs(input.taskRepoRoot);
76
- if (jobs.length === 0) {
77
+ const coderWorkerTasks = input.role === "coder"
78
+ ? await findActiveCoderWorkerTasks(input.taskRepoRoot)
79
+ : [];
80
+ if (jobs.length === 0 && coderWorkerTasks.length === 0) {
77
81
  blockStates.delete(key);
78
82
  return { behavior: "allow" };
79
83
  }
80
- const leaseMtimeMs = jobs.reduce((latest, job) => job.leaseMtimeMs !== undefined && (latest === undefined || job.leaseMtimeMs > latest)
84
+ const jobProgressMtimeMs = jobs.reduce((latest, job) => job.leaseMtimeMs !== undefined && (latest === undefined || job.leaseMtimeMs > latest)
81
85
  ? job.leaseMtimeMs
82
86
  : latest, undefined);
87
+ const workerProgressMtimeMs = coderWorkerTasks.reduce((latest, task) => task.stateMtimeMs !== undefined && (latest === undefined || task.stateMtimeMs > latest)
88
+ ? task.stateMtimeMs
89
+ : latest, undefined);
90
+ const progressMtimeMs = latestMtime(jobProgressMtimeMs, workerProgressMtimeMs);
83
91
  let state = blockStates.get(key) ?? { count: 0 };
84
- const watcherProgressed = state.count > 0
85
- && leaseMtimeMs !== undefined
86
- && state.lastLeaseMtimeMs !== undefined
87
- && leaseMtimeMs > state.lastLeaseMtimeMs;
88
- if (watcherProgressed) {
92
+ const progressChanged = state.count > 0
93
+ && progressMtimeMs !== undefined
94
+ && state.lastProgressMtimeMs !== undefined
95
+ && progressMtimeMs > state.lastProgressMtimeMs;
96
+ if (progressChanged) {
89
97
  state = { count: 0 };
90
98
  }
91
99
  if (state.count >= MAX_CONSECUTIVE_STOP_BLOCKS) {
@@ -94,24 +102,88 @@ export function createJobGuardService(deps = {}) {
94
102
  blockStates.delete(key);
95
103
  return { behavior: "allow" };
96
104
  }
97
- blockStates.set(key, { count: state.count + 1, lastLeaseMtimeMs: leaseMtimeMs });
98
- return { behavior: "block", reason: buildBlockReason(jobs) };
105
+ blockStates.set(key, { count: state.count + 1, lastProgressMtimeMs: progressMtimeMs });
106
+ return { behavior: "block", reason: buildBlockReason(jobs, coderWorkerTasks) };
99
107
  },
100
108
  notePromptSubmitted(input) {
101
109
  blockStates.delete(stateKey(input));
102
110
  }
103
111
  };
104
112
  }
113
+ async function findActiveCoderWorkerTasks(taskRepoRoot) {
114
+ const tasksRoot = path.join(taskRepoRoot, ".ai/vcm/coder-workers/tasks");
115
+ let entries;
116
+ try {
117
+ entries = await fs.readdir(tasksRoot);
118
+ }
119
+ catch {
120
+ return [];
121
+ }
122
+ const tasks = [];
123
+ for (const entry of entries.sort()) {
124
+ if (!entry.endsWith(".json")) {
125
+ continue;
126
+ }
127
+ const statePath = path.join(tasksRoot, entry);
128
+ let state;
129
+ try {
130
+ state = JSON.parse(await fs.readFile(statePath, "utf8"));
131
+ }
132
+ catch {
133
+ continue;
134
+ }
135
+ const status = typeof state.status === "string" ? state.status : "";
136
+ if (state.handled === true || !ACTIVE_CODER_WORKER_STATUSES.has(status)) {
137
+ continue;
138
+ }
139
+ let stateMtimeMs;
140
+ try {
141
+ stateMtimeMs = (await fs.stat(statePath)).mtimeMs;
142
+ }
143
+ catch {
144
+ stateMtimeMs = undefined;
145
+ }
146
+ tasks.push({
147
+ workerId: typeof state.workerId === "string" ? state.workerId : path.basename(entry, ".json"),
148
+ status,
149
+ reportPath: typeof state.reportPath === "string" ? state.reportPath : undefined,
150
+ error: typeof state.error === "string" ? state.error : undefined,
151
+ stateMtimeMs
152
+ });
153
+ }
154
+ return tasks;
155
+ }
105
156
  function stateKey(input) {
106
157
  return `${input.repoRoot}::${input.taskSlug}::${input.role}`;
107
158
  }
108
- function buildBlockReason(jobs) {
159
+ function buildBlockReason(jobs, coderWorkerTasks) {
160
+ if (jobs.length > 0 && coderWorkerTasks.length === 0) {
161
+ return buildValidationJobBlockReason(jobs);
162
+ }
163
+ if (jobs.length === 0) {
164
+ return buildCoderWorkerBlockReason(coderWorkerTasks);
165
+ }
166
+ return `${buildValidationJobBlockReason(jobs)}\n${buildCoderWorkerBlockReason(coderWorkerTasks)}`;
167
+ }
168
+ function buildValidationJobBlockReason(jobs) {
109
169
  const first = jobs[0];
110
170
  const listing = jobs.map((job) => `${job.jobId} (${job.status})`).join(", ");
111
171
  return `VCM: validation job ${listing} is still running. Do not end the turn while a validation job is running. `
112
172
  + `Run \`.ai/tools/watch-job ${first.jobId}\` again now and keep watching until it reports a terminal result `
113
173
  + `(success, failed, timeout, or orphaned), then record the result.`;
114
174
  }
175
+ function buildCoderWorkerBlockReason(tasks) {
176
+ const listing = tasks.map((task) => `${task.workerId} (${task.status})`).join(", ");
177
+ const reports = tasks
178
+ .map((task) => task.reportPath)
179
+ .filter((reportPath) => Boolean(reportPath));
180
+ const reportHint = reports.length > 0 ? ` Review report(s): ${reports.join(", ")}.` : "";
181
+ return `VCM: coder worker task ${listing} is still unhandled. Do not end the Coder turn while worker tasks are unhandled. `
182
+ + `Wait for worker subagents, review reports and commits, resolve failed or incomplete workers, set \`handled: true\` in each worker state, and continue.${reportHint}`;
183
+ }
184
+ function latestMtime(...values) {
185
+ return values.reduce((latest, value) => value !== undefined && (latest === undefined || value > latest) ? value : latest, undefined);
186
+ }
115
187
  function numberOrUndefined(value) {
116
188
  return typeof value === "number" && Number.isFinite(value) ? value : undefined;
117
189
  }
@@ -5,6 +5,7 @@ const TRANSLATOR_SESSION_PATH = ".ai/vcm/translations/session.json";
5
5
  const HARNESS_ENGINEER_SESSION_PATH = ".ai/vcm/harness-engineer/session.json";
6
6
  const BOOTSTRAP_SESSION_PATH = ".ai/vcm/bootstrap/session.json";
7
7
  const HARNESS_FEEDBACK_STATE_PATH = ".ai/vcm/harness-feedback/state.json";
8
+ const CODER_WORKERS_RUNTIME_DIR = ".ai/vcm/coder-workers";
8
9
  const RECOVERABLE_FEEDBACK_STATES = new Set(["analyzing", "applying"]);
9
10
  export function createRuntimeRecoveryService(deps) {
10
11
  const now = deps.now ?? (() => new Date().toISOString());
@@ -28,6 +29,7 @@ export function createRuntimeRecoveryService(deps) {
28
29
  const roundRecovered = await recoverRound(taskRepoRoot, config.stateRoot, task.taskSlug, recoveredAt, context);
29
30
  await recoverMessages(taskRepoRoot, config.stateRoot, task.taskSlug, recoveredAt, context);
30
31
  await recoverGateReview(taskRepoRoot, recoveredAt, context);
32
+ await cleanupCoderWorkers(taskRepoRoot, context);
31
33
  if ((roundRecovered || task.status === "running") && !hasLiveTaskSession(task.taskSlug)) {
32
34
  await deps.taskService.updateTaskStatus(repoRoot, task.taskSlug, "stopped");
33
35
  }
@@ -230,6 +232,17 @@ export function createRuntimeRecoveryService(deps) {
230
232
  });
231
233
  context.changedPaths.add(relativePath);
232
234
  }
235
+ async function cleanupCoderWorkers(taskRepoRoot, context) {
236
+ const absolutePath = path.join(taskRepoRoot, CODER_WORKERS_RUNTIME_DIR);
237
+ if (!(await deps.fs.pathExists(absolutePath))) {
238
+ return;
239
+ }
240
+ if (!deps.fs.removePath) {
241
+ return;
242
+ }
243
+ await deps.fs.removePath(absolutePath, { recursive: true, force: true });
244
+ context.changedPaths.add(CODER_WORKERS_RUNTIME_DIR);
245
+ }
233
246
  async function recoverHarnessBootstrap(repoRoot, _timestamp, context) {
234
247
  const absolutePath = path.join(repoRoot, BOOTSTRAP_SESSION_PATH);
235
248
  const state = await readJsonIfExists(absolutePath);
@@ -8,7 +8,6 @@ import { createTranslationQueueRegistry } from "./translation-queue.js";
8
8
  const TRANSLATION_SOURCE_LANGUAGE = "auto";
9
9
  const TRANSLATION_INPUT_MODE = "review-before-send";
10
10
  const TRANSLATION_CONTEXT_ENABLED = false;
11
- const TRANSLATION_TIMEOUT_MS = 120000;
12
11
  const TRANSLATION_PROVIDER = "claude-code";
13
12
  const TRANSLATION_MODEL = "translator";
14
13
  const OUTPUT_TRANSLATION_BATCH_DELAY_MS = 10000;
@@ -30,8 +29,7 @@ export function createTranslationService(deps) {
30
29
  targetLanguage: preferences.translationTargetLanguage,
31
30
  inputMode: TRANSLATION_INPUT_MODE,
32
31
  outputMode: preferences.translationOutputMode,
33
- contextEnabled: TRANSLATION_CONTEXT_ENABLED,
34
- requestTimeoutMs: TRANSLATION_TIMEOUT_MS
32
+ contextEnabled: TRANSLATION_CONTEXT_ENABLED
35
33
  };
36
34
  }
37
35
  function getState(sessionId) {
@@ -400,7 +398,7 @@ export function createTranslationService(deps) {
400
398
  }
401
399
  for (const { item, job } of jobs) {
402
400
  try {
403
- const result = await waitForConversationResult(item.repoRoot, job, item.config.requestTimeoutMs);
401
+ const result = await waitForConversationResult(item.repoRoot, job);
404
402
  const completed = {
405
403
  ...item.entry,
406
404
  status: "translated",
@@ -1076,7 +1074,7 @@ export function createTranslationService(deps) {
1076
1074
  },
1077
1075
  async translateGatewayOutput(input) {
1078
1076
  const config = await loadConfig();
1079
- const reusable = await findReusableGatewayOutputTranslation(input, config);
1077
+ const reusable = await findReusableGatewayOutputTranslation(input);
1080
1078
  if (reusable) {
1081
1079
  return reusable.trim();
1082
1080
  }
@@ -1197,7 +1195,7 @@ export function createTranslationService(deps) {
1197
1195
  }
1198
1196
  return leftTime.localeCompare(rightTime);
1199
1197
  }
1200
- async function findReusableGatewayOutputTranslation(input, config) {
1198
+ async function findReusableGatewayOutputTranslation(input) {
1201
1199
  const graceDeadline = Date.now() + (input.sourceEntryIds?.length ? GATEWAY_TRANSLATION_REUSE_GRACE_MS : 0);
1202
1200
  while (true) {
1203
1201
  const lookup = await lookupGatewayOutputTranslation(input);
@@ -1205,7 +1203,7 @@ export function createTranslationService(deps) {
1205
1203
  return lookup.text;
1206
1204
  }
1207
1205
  if (lookup.kind === "active") {
1208
- return waitForReusableGatewayOutputTranslation(input, config);
1206
+ return waitForReusableGatewayOutputTranslation(input);
1209
1207
  }
1210
1208
  if (!input.sourceEntryIds?.length || Date.now() >= graceDeadline) {
1211
1209
  return undefined;
@@ -1213,9 +1211,8 @@ export function createTranslationService(deps) {
1213
1211
  await delay(GATEWAY_TRANSLATION_REUSE_POLL_MS);
1214
1212
  }
1215
1213
  }
1216
- async function waitForReusableGatewayOutputTranslation(input, config) {
1217
- const deadline = Date.now() + config.requestTimeoutMs;
1218
- while (Date.now() <= deadline) {
1214
+ async function waitForReusableGatewayOutputTranslation(input) {
1215
+ while (true) {
1219
1216
  const lookup = await lookupGatewayOutputTranslation(input);
1220
1217
  if (lookup.kind === "translated") {
1221
1218
  return lookup.text;
@@ -1225,11 +1222,6 @@ export function createTranslationService(deps) {
1225
1222
  }
1226
1223
  await delay(GATEWAY_TRANSLATION_REUSE_POLL_MS);
1227
1224
  }
1228
- throw new VcmError({
1229
- code: "TRANSLATION_TIMEOUT",
1230
- message: "Gateway output translation timed out while waiting for the existing PM reply translation.",
1231
- statusCode: 504
1232
- });
1233
1225
  }
1234
1226
  async function lookupGatewayOutputTranslation(input) {
1235
1227
  const states = await getGatewayOutputCandidateStates(input);
@@ -1352,7 +1344,7 @@ export function createTranslationService(deps) {
1352
1344
  }
1353
1345
  async function translateText(input) {
1354
1346
  const job = await createConversationJob(input);
1355
- const result = await waitForConversationResult(input.repoRoot, job, input.config.requestTimeoutMs);
1347
+ const result = await waitForConversationResult(input.repoRoot, job);
1356
1348
  return {
1357
1349
  text: result.translatedText
1358
1350
  };
@@ -1382,14 +1374,30 @@ export function createTranslationService(deps) {
1382
1374
  deferDispatch: input.deferDispatch
1383
1375
  });
1384
1376
  }
1385
- async function waitForConversationResult(repoRoot, job, timeoutMs) {
1386
- const deadline = Date.now() + timeoutMs;
1387
- let lastError;
1388
- while (Date.now() <= deadline) {
1377
+ async function waitForConversationResult(repoRoot, job) {
1378
+ while (true) {
1389
1379
  const state = await deps.translationWorkerService.getState(repoRoot);
1390
1380
  const item = job.queueItemId
1391
1381
  ? state.queue.items.find((candidate) => candidate.id === job.queueItemId)
1392
1382
  : undefined;
1383
+ if (!item) {
1384
+ try {
1385
+ return await deps.translationWorkerService.validateConversationResult(repoRoot, {
1386
+ resultPath: job.resultPath,
1387
+ sourceHash: job.sourceHash,
1388
+ targetLanguage: job.targetLanguage
1389
+ });
1390
+ }
1391
+ catch (error) {
1392
+ throw new VcmError({
1393
+ code: "TRANSLATION_FAILED",
1394
+ message: error instanceof Error
1395
+ ? `translation queue item is unavailable: ${error.message}`
1396
+ : "translation queue item is unavailable.",
1397
+ statusCode: 502
1398
+ });
1399
+ }
1400
+ }
1393
1401
  if (item && ["failed", "cancelled", "interrupted", "skipped"].includes(item.status)) {
1394
1402
  throw new VcmError({
1395
1403
  code: "TRANSLATION_FAILED",
@@ -1398,7 +1406,7 @@ export function createTranslationService(deps) {
1398
1406
  });
1399
1407
  }
1400
1408
  if (item && item.status !== "completed") {
1401
- await delay(Math.min(500, Math.max(25, timeoutMs)));
1409
+ await delay(500);
1402
1410
  continue;
1403
1411
  }
1404
1412
  try {
@@ -1409,18 +1417,12 @@ export function createTranslationService(deps) {
1409
1417
  });
1410
1418
  }
1411
1419
  catch (error) {
1412
- lastError = error;
1413
1420
  if (item?.status === "completed") {
1414
1421
  throw error;
1415
1422
  }
1416
1423
  }
1417
- await delay(Math.min(500, Math.max(25, timeoutMs)));
1424
+ await delay(500);
1418
1425
  }
1419
- throw new VcmError({
1420
- code: "TRANSLATION_TIMEOUT",
1421
- message: lastError instanceof Error ? `translation timed out: ${lastError.message}` : "translation timed out.",
1422
- statusCode: 504
1423
- });
1424
1426
  }
1425
1427
  }
1426
1428
  function delay(ms) {
@@ -17,14 +17,6 @@ const CONVERSATION_BATCHES_DIR = `${CONVERSATION_RUNTIME_DIR}/batches`;
17
17
  const MEMORY_UPDATE_RUNTIME_DIR = `${TRANSLATIONS_RUNTIME_DIR}/memory-updates`;
18
18
  const DEFAULT_PROFILE = "default";
19
19
  const DEFAULT_CHUNK_SOURCE_TOKEN_TARGET = 80000;
20
- // In-flight conversation queue items normally finalize when the Translator
21
- // session's Stop/StopFailure hook reaches the backend. If that hook is lost
22
- // (session crash, backend restart/reconnect) a conversation item with no result
23
- // on disk would block the queue head forever. Treat such an item as stuck once it
24
- // has been in-flight past this bound and release it so later items can dispatch.
25
- // Kept comfortably above a normal short composer translation, so a genuinely
26
- // running conversation turn is never released mid-flight.
27
- const STALE_CONVERSATION_ITEM_MS = 90000;
28
20
  const BOOTSTRAP_DEFAULT_LIMIT = 12;
29
21
  const MEMORY_TOTAL_LIMIT_BYTES = 80 * 1024;
30
22
  const MEMORY_INITIALIZED_MIN_FILES = 2;
@@ -439,12 +431,22 @@ export function createTranslationWorkerService(deps) {
439
431
  await validateActiveQueueItem(repoRoot);
440
432
  return true;
441
433
  }
442
- if (active.type === "conversation" && isStaleActiveItem(active)) {
434
+ if (await translatorSessionSettled(repoRoot)) {
443
435
  await validateActiveQueueItem(repoRoot);
444
436
  return true;
445
437
  }
446
438
  return false;
447
439
  }
440
+ async function reconcileActiveItemFromSessionState(repoRoot) {
441
+ const queue = await loadQueue(repoRoot);
442
+ const active = queue.activeItemId
443
+ ? queue.items.find((item) => item.id === queue.activeItemId)
444
+ : undefined;
445
+ if (!active || !["dispatching", "running"].includes(active.status)) {
446
+ return;
447
+ }
448
+ await reconcileStuckActiveItem(repoRoot, active);
449
+ }
448
450
  async function activeItemResultAvailable(repoRoot, item) {
449
451
  if (item.type === "conversation") {
450
452
  return conversationResultAvailable(repoRoot, item);
@@ -486,12 +488,12 @@ export function createTranslationWorkerService(deps) {
486
488
  }
487
489
  return deps.fs.readText(resultPath);
488
490
  }
489
- function isStaleActiveItem(item) {
490
- const updatedAtMs = Date.parse(item.updatedAt ?? "");
491
- if (!Number.isFinite(updatedAtMs)) {
492
- return true;
491
+ async function translatorSessionSettled(repoRoot) {
492
+ if (!deps.sessionService?.getProjectTranslatorSession) {
493
+ return false;
493
494
  }
494
- return Date.now() - updatedAtMs >= STALE_CONVERSATION_ITEM_MS;
495
+ const session = await deps.sessionService.getProjectTranslatorSession(repoRoot);
496
+ return !session || session.status !== "running";
495
497
  }
496
498
  async function validateActiveQueueItem(repoRoot) {
497
499
  const queue = await loadQueue(repoRoot);
@@ -537,13 +539,6 @@ export function createTranslationWorkerService(deps) {
537
539
  const batchItems = queue.items.filter((item) => item.type === "conversation" &&
538
540
  item.batchId === active.batchId &&
539
541
  ["dispatching", "running", "validating"].includes(item.status));
540
- const validatingAt = now();
541
- for (const item of batchItems) {
542
- item.status = "validating";
543
- item.updatedAt = validatingAt;
544
- }
545
- queue.updatedAt = validatingAt;
546
- await saveQueue(repoRoot, queue);
547
542
  const completedAt = now();
548
543
  for (const item of batchItems) {
549
544
  const index = item.batchIndex ?? 0;
@@ -909,6 +904,7 @@ export function createTranslationWorkerService(deps) {
909
904
  async getState(repoRoot, options = {}) {
910
905
  await ensureLayout(repoRoot);
911
906
  await cleanupCompletedRuntime(repoRoot);
907
+ await reconcileActiveItemFromSessionState(repoRoot);
912
908
  const [queue, fileIndex, bootstrapIndex, memoryInitialized] = await Promise.all([
913
909
  loadQueue(repoRoot),
914
910
  loadFileIndex(repoRoot),
@@ -4,7 +4,7 @@ export function renderArchitectHarnessRules() {
4
4
 
5
5
  ### Role Scope
6
6
 
7
- - Own technical analysis, architecture planning, module boundaries, file-level responsibilities, cross-file callable surfaces, public contracts, verifiable behavior, phase boundaries, behavior/contract proof points, risks, and Replan triggers.
7
+ - Own technical analysis, architecture planning, module boundaries, file-level responsibilities, cross-file callable surfaces, public contracts, verifiable behavior, task boundaries, behavior/contract proof points, risks, and Replan triggers.
8
8
  - Define every changed or created file's purpose, logic boundary, collaboration points, and non-private callable surface.
9
9
  - Own \`docs/known-issues.md\` promotion and durable issue updates.
10
10
  - Own architecture docs sync across \`docs/ARCHITECTURE.md\` and affected \`<module>/ARCHITECTURE.md\` files.
@@ -16,7 +16,7 @@ export function renderArchitectHarnessRules() {
16
16
  ### Planning Inputs
17
17
 
18
18
  - Read the role message, durable plans when present, relevant handoff artifacts, \`docs/ARCHITECTURE.md\`, affected \`<module>/ARCHITECTURE.md\` files when present, and affected project docs before planning.
19
- - Read \`.ai/generated/module-index.json\` when planning module scope, file scope, dependency direction, or phased work.
19
+ - Read \`.ai/generated/module-index.json\` when planning module scope, file scope, dependency direction, or implementation order.
20
20
  - Read \`.ai/generated/public-surface.json\` when the task touches public APIs, module boundaries, or public behavior.
21
21
  - If durable docs conflict with the requested plan or code reality, report the conflict to project-manager and identify whether user approval is required.
22
22
 
@@ -30,7 +30,7 @@ export function renderArchitectHarnessRules() {
30
30
  - Define every non-private callable surface intended for use outside its file: visibility, signature shape, responsibility, expected callers, behavior contract, side effects, and error boundaries.
31
31
  - Include a \`Scaffold Manifest\` for task-specific file context: stable row ID, file action, why the file is in scope, coder work, allowed implementation freedom, expected \`VCM:CODE\` placeholders, durable code comment needs, proof points, and Replan triggers.
32
32
  - Give each Scaffold Manifest row a stable ID such as \`SCF-001\`; use that ID in any related \`VCM:CODE\` marker so coder can report completion by ID.
33
- - Put task context, phase notes, handoff instructions, temporary rationale, and coder guidance in the \`Scaffold Manifest\`, not in source-code comments.
33
+ - Put task context, implementation-order notes, handoff instructions, temporary rationale, and coder guidance in the \`Scaffold Manifest\`, not in source-code comments.
34
34
  - Cover architecture docs impact, known risks, and Replan triggers.
35
35
  - For docs impact, list every touched module and state whether its \`<module>/ARCHITECTURE.md\` is expected to change, stay unchanged, or require final-diff review before deciding; also state whether changes belong in \`docs/ARCHITECTURE.md\`, \`.ai/generated/public-surface.json\`, or no durable architecture doc.
36
36
 
@@ -38,7 +38,7 @@ export function renderArchitectHarnessRules() {
38
38
 
39
39
  - Create or update only the minimum module/file scaffolding needed to make boundaries, callable surfaces, and placeholders unambiguous.
40
40
  - Source-code comments must describe durable behavior, contracts, invariants, error boundaries, or non-obvious logic that should remain useful after the task is complete.
41
- - Do not put task-specific context, phase notes, handoff instructions, temporary plan rationale, or coder guidance in source-code comments.
41
+ - Do not put task-specific context, implementation-order notes, handoff instructions, temporary plan rationale, or coder guidance in source-code comments.
42
42
  - When changing an existing file, update only affected durable comments or callable surfaces; do not rewrite unrelated file comments.
43
43
  - Define every new or changed non-private callable surface directly in code with its signature shape and contract comment.
44
44
  - When changing an existing non-private callable surface, update its signature and contract comment in code before coder work starts; leave \`VCM:CODE\` only where implementation must change.
@@ -47,18 +47,12 @@ export function renderArchitectHarnessRules() {
47
47
  - Architect scaffolding may include modules, files, signatures, type shapes, durable comments, and placeholder bodies, but not real business implementation beyond minimal scaffold code.
48
48
  - Coder may add private implementation helpers, but must not add or change cross-file callable surface without architect replan.
49
49
 
50
- ### Phase Planning
50
+ ### Complete Task Planning
51
51
 
52
- - Do not create phases for small, single-scope changes; use phases only when the task spans multiple modules, public contracts, migrations, high-risk integrations, or more work than one reliable coder handoff should carry.
53
- - For complex tasks, first provide an overall solution outline and recommended phases, but keep detailed implementation planning limited to the current phase.
54
- - Treat \`.ai/vcm/handoffs/architecture-plan.md\` as the executable plan for the current phase, not an accumulating history of all phases.
55
- - When moving to a new phase, rewrite \`architecture-plan.md\` for that phase: remove previous phase detailed scope, Scaffold Manifest rows, \`VCM:CODE\` guidance, and completed phase instructions.
56
- - Keep only the minimum overall roadmap and prior-phase context needed to understand the current phase.
57
- - Durable decisions discovered in previous phases must be promoted to durable docs when needed, not preserved as old task detail inside \`architecture-plan.md\`.
58
- - Split phased work into verifiable engineering slices with clear handoff and proof boundaries.
59
- - Prefer behavior slices, but use module, interface, migration, or risk-isolation slices when they are clearer.
60
- - Each phase must state goal, non-goals, affected scope, required behavior or contract proof points, completion criteria, dependencies, risks, and Replan triggers.
61
- - Do not split by individual files unless independently verifiable; do not combine unrelated behavior, public-contract changes, migrations, or high-risk areas.
52
+ - Plan the full accepted task scope routed by PM.
53
+ - \`architecture-plan.md\` must describe the complete implementation for that scope.
54
+ - Do not create internal delivery stages, task-splitting suggestions, or follow-up scope without explicit PM approval.
55
+ - Implementation order may be described, but it must not defer requested scope.
62
56
 
63
57
  ### Debug Mode
64
58
 
@@ -73,10 +67,42 @@ export function renderArchitectHarnessRules() {
73
67
  - After an architect-completed debug fix, route to reviewer for independent final validation before project-manager final acceptance.
74
68
  - Report root cause, changed files, production-code changed line count, L0 checks run or skipped with reason, generated-context regeneration or freshness check when applicable, diagnostic validation run, and final disposition.
75
69
 
70
+ ### Architecture Diagnosis Mode
71
+
72
+ In Architecture Diagnosis Mode, treat the current failure as a signal that the architecture may be wrong or incomplete. Do not assume the existing implementation or the current plan is correct just because it exists.
73
+
74
+ First define the diagnosis boundary: the affected feature or module. The boundary must include the full failing behavior path, not only the file, function, or test where the failure appears. Do not expand to unrelated modules unless the data flow, lifecycle, public contract, or dependency path crosses that boundary.
75
+
76
+ Within that boundary, read enough code, tests, durable docs, generated context, and handoff artifacts to reconstruct the current architecture. Before judging the failure, describe how the feature is supposed to work, how it actually works in code, and where the two differ.
77
+
78
+ Analyze the problem from these angles:
79
+
80
+ - **Ownership:** Identify who should own the failing state, decision, lifecycle, side effect, or durable artifact. Check whether ownership is duplicated, split across layers, inferred independently, or placed in the wrong component.
81
+ - **Data Flow:** Trace where the relevant data enters the system, how it moves, where it is transformed, where it is persisted, and who consumes it. Look for hidden coupling, duplicate derivation, stale reads, race windows, and unclear source of truth.
82
+ - **Lifecycle:** Identify the lifecycle being modeled, such as task, round, turn, session, queue item, hook event, job, file artifact, UI view, gateway message, or validation run. Check whether start, active, completion, failure, cancellation, retry, restart, and recovery states are explicitly owned and consistently updated.
83
+ - **Boundaries:** Check whether module, service, frontend/backend, role, tool, or persistence boundaries are clean. Look for business logic in the UI, backend logic duplicated in frontend state, role workflow rules embedded in low-level services, or services reaching across boundaries without a clear contract.
84
+ - **Invariants:** State the architecture invariant that should always hold, then compare the current implementation against it.
85
+ - **Failure Model:** Identify how the architecture should behave when the operation fails, is interrupted, retries, resumes, restarts, receives duplicate events, receives events out of order, or observes partial output. Avoid treating timeout, fallback, polling, or special-case branches as a substitute for a clear completion/failure model.
86
+ - **Evidence:** Use code, docs, handoff artifacts, tests, logs, and generated context as evidence. Existing code is evidence, not authority. If the code contradicts the intended architecture, say so directly.
87
+
88
+ Treat "local implementation bug" as an exception that must be proven. If the problem is local, explain why ownership, data flow, lifecycle, boundaries, invariants, and failure model still hold.
89
+
90
+ Your diagnosis should identify:
91
+
92
+ 1. The diagnosis boundary.
93
+ 2. How the feature is supposed to work.
94
+ 3. How it actually works in code.
95
+ 4. Where the two differ.
96
+ 5. Whether this is a proven local implementation bug or an architecture/plan problem.
97
+ 6. If local, why the architecture still holds.
98
+ 7. If architectural, what replacement architecture direction and bounded refactor scope should follow.
99
+
100
+ Do not propose a code-level patch until the architecture diagnosis is complete.
101
+
76
102
  ### Replan And Drift
77
103
 
78
104
  - Replan only when project-manager routes a technical mismatch back to architect.
79
- - Change the plan only for code reality conflict, invalid phase boundary, public contract change, dependency change, durable docs impact, or missing behavior/contract proof point.
105
+ - Change the plan only for code reality conflict, invalid task boundary, public contract change, dependency change, durable docs impact, or missing behavior/contract proof point.
80
106
  - Treat any new or changed cross-file callable surface not defined in the architecture plan as architecture drift that must return to architect.
81
107
  - Do not treat workload, session length, or context size as a reason to change the plan.
82
108
  - When reviewing drift, tell project-manager whether to keep the plan and send work back to coder, update the plan, or ask the user for approval.
@@ -88,7 +114,7 @@ export function renderArchitectHarnessRules() {
88
114
  #### Architecture Docs Sync
89
115
 
90
116
  - Architecture docs describe the current durable system architecture, not task history, implementation chronology, changelog, investigation notes, validation logs, or handoff content.
91
- - Do not add phase/task/RP labels unless they are durable product, protocol, or spec identifiers that future maintainers must understand.
117
+ - Do not add task/RP labels unless they are durable product, protocol, or spec identifiers that future maintainers must understand.
92
118
  - Keep project-level docs focused on module map, dependency direction, cross-module relationships, major runtime flows, and project-wide constraints.
93
119
  - Keep module-level docs focused on current responsibility boundaries, owned behavior, non-owned behavior, collaboration points, important public contracts, invariants, risks, and update triggers.
94
120
  - Do not duplicate the generated public API index; explain design intent and contract meaning instead.
@@ -108,7 +134,7 @@ export function renderArchitectHarnessRules() {
108
134
  - Promote only unresolved durable issues or accepted limitations that can affect future architecture, implementation, validation, operation, or release decisions.
109
135
  - Remove fully resolved issues from \`docs/known-issues.md\`; git history preserves resolved details.
110
136
  - When a parent issue remains open but some sub-items are resolved, rewrite the entry around the remaining current gap instead of preserving resolved-history narrative.
111
- - Keep one KI entry focused on one owning problem. Split unrelated residuals instead of grouping them under a phase, review, or implementation session.
137
+ - Keep one KI entry focused on one owning problem. Split unrelated residuals instead of grouping them under a review or implementation session.
112
138
  - Do not include round names, role-session notes, commit hashes, reviewer verdict history, temporary investigation logs, or full validation history unless they are essential to identify the current unresolved issue.
113
139
  - Each KI entry should state: status, category, affected modules/surfaces, current gap, impact, mitigation or workaround, resolution condition, and related issue IDs when useful.
114
140
  - Distinguish product/protocol issues from dev-environment, test-infra, harness, or VCM-tooling issues. Do not mix them in one KI entry.
@@ -4,7 +4,8 @@ export function renderCoderHarnessRules() {
4
4
 
5
5
  ### Role Scope
6
6
 
7
- - Own implementation and baseline implementation tests inside the approved task scope, current phase, role message, and architecture plan.
7
+ - Own implementation and baseline implementation tests inside the approved task scope, role message, and architecture plan.
8
+ - When parallel worker implementation is used, own worker task splitting, worker prompts, worker result review, integration, final Scaffold Completion, and coder-level validation.
8
9
  - Do not decide architecture, module boundaries, public contracts, dependency direction, durable docs updates, or final test adequacy.
9
10
 
10
11
  ### Coder Implementation Discipline
@@ -16,7 +17,7 @@ export function renderCoderHarnessRules() {
16
17
  - Keep the diff inside approved scope: no unrelated rewrites, drive-by refactors, renamed symbols, moved files, or formatting churn.
17
18
  - Preserve existing behavior unless the architecture plan explicitly changes it; keep existing call sites and shared code paths working.
18
19
  - Maintain code documentation: preserve durable architect-written contract comments, keep comments consistent with changed behavior, and update affected durable comments when logic changes.
19
- - Do not copy Scaffold Manifest task context, phase notes, handoff instructions, temporary rationale, or coder guidance into source comments.
20
+ - Do not copy Scaffold Manifest task context, implementation-order notes, handoff instructions, temporary rationale, or coder guidance into source comments.
20
21
  - Add source comments only for durable behavior, contracts, invariants, error boundaries, or non-obvious logic that cannot be made clear enough through naming, types, constants, or small helper functions.
21
22
  - Remove stale, debug, task-process, and unresolved TODO comments unless a TODO is durable, still accurate, and linked to an owner, issue, or accepted follow-up.
22
23
 
@@ -32,7 +33,7 @@ export function renderCoderHarnessRules() {
32
33
 
33
34
  ### Inputs
34
35
 
35
- - Before editing, read the role message, the architecture plan, current phase when present, affected code/tests, and validation instructions from the role message or project docs.
36
+ - Before editing, read the role message, the architecture plan, affected code/tests, and validation instructions from the role message or project docs.
36
37
  - Read durable architecture/module/security/dependency docs only when the architecture plan or role message references them.
37
38
  - Stop before editing when the architecture plan, role message, allowed write scope, public contract, or validation expectation is missing or unclear; reply to project-manager instead of inferring it.
38
39
  - Use \`.ai/generated/module-index.json\` to locate approved module source and test files.
@@ -45,6 +46,24 @@ export function renderCoderHarnessRules() {
45
46
  - When changing tests, keep assertions tied to the approved behavior contract; do not relax expectations, remove meaningful coverage, or rewrite tests merely to match the current implementation.
46
47
  - Record confirmed out-of-scope issues found during implementation in \`.ai/vcm/handoffs/known-issues.md\`.
47
48
 
49
+ ### Complete Implementation
50
+
51
+ - Complete the full implementation assigned by the architecture plan.
52
+ - Do not stop incomplete work because of workload, session length, context size, or task size.
53
+ - If the architecture plan is still valid, continue implementation instead of requesting Replan.
54
+
55
+ ### Parallel Worker Implementation
56
+
57
+ - Coder may use Claude Code subagents to invoke \`vcm-coder-worker\` for parallel implementation.
58
+ - Use workers only when the task touches multiple modules and at least two modules each contain more than 10 \`VCM:CODE\` markers.
59
+ - Before invoking workers, count \`VCM:CODE\` markers by module and create one runtime state file per worker under \`.ai/vcm/coder-workers/tasks/<worker-id>.json\`.
60
+ - Assign one worker task per module with more than 10 markers; group modules with 10 or fewer markers into one worker task.
61
+ - Each worker prompt must include task worktree, architecture plan path, worker state path, report path, assigned modules/files/markers, allowed implementation scope, validation scope, and commit requirement.
62
+ - Invoke worker subagents in parallel only through \`vcm-coder-worker\`.
63
+ - Stay in the same Coder turn until all worker subagents finish and Coder has reviewed and integrated their reports and commits. Do not end the turn to wait for worker callbacks.
64
+ - After workers finish, review each report and commit, resolve missing implementation, conflicts, invalid edits, and remaining \`VCM:CODE\` markers, then mark \`handled: true\` in each worker state.
65
+ - Run coder-level baseline validation, include worker commits and final integration status in Scaffold Completion, and delete \`.ai/vcm/coder-workers/\`.
66
+
48
67
  ### Handoff
49
68
 
50
69
  - In the route message back to project-manager, include a \`Scaffold Completion\` section when the architecture plan contains a Scaffold Manifest.
@@ -65,7 +84,7 @@ export function renderCoderHarnessRules() {
65
84
  ### Replan And Continuation
66
85
 
67
86
  - Stop and request Replan through project-manager when the approved plan conflicts with code reality.
68
- - Request Replan only for architecture, public contract, dependency, phase-boundary, validation-boundary, or durable-doc changes that must be decided before implementation can continue.
87
+ - Request Replan only for architecture, public contract, dependency, task-boundary, validation-boundary, or durable-doc changes that must be decided before implementation can continue.
69
88
  - Do not request Replan because of workload, session length, or context size.
70
89
  - If the plan remains valid but the assigned work cannot be finished in this turn, include completed work, remaining work, validation state, and next continuation step in the route message, then ask project-manager for continuation.
71
90
  - If implementation exposes a broad testing gap beyond baseline unit tests, report it to project-manager for reviewer follow-up.
@@ -0,0 +1,72 @@
1
+ export function renderCoderWorkerHarnessRules() {
2
+ return `
3
+ ## VCM Coder Worker Rules
4
+
5
+ You are \`vcm-coder-worker\`, a bounded implementation worker invoked by Coder.
6
+
7
+ ### Scope
8
+
9
+ - Implement only the module, files, Scaffold Manifest IDs, and \`VCM:CODE\` markers assigned by Coder.
10
+ - Stay inside the current task worktree.
11
+ - Do not change unassigned modules, files, durable docs, generated context, workflow files, role definitions, or project configuration unless Coder explicitly assigns them.
12
+ - Do not decide architecture, module boundaries, public contracts, dependency direction, validation strategy, Replan, or final acceptance.
13
+ - If the assigned implementation conflicts with the architecture plan or code reality, stop and report the conflict to Coder.
14
+
15
+ ### Worker Runtime State
16
+
17
+ - Coder assigns a worker state path and report path.
18
+ - Before editing, read the assigned worker state file and update only that file from \`planned\` to \`running\`.
19
+ - After implementation, write the assigned report file, update only the assigned worker state to \`completed\`, and set \`commitHash\` after committing.
20
+ - If blocked or failed, update only the assigned worker state to \`failed\`, write the reason in \`error\`, and write the report with remaining work.
21
+ - Do not set \`handled: true\`; only Coder may do that after reviewing and integrating the worker result.
22
+
23
+ ### Inputs
24
+
25
+ - Read Coder's delegation message.
26
+ - Read \`.ai/vcm/handoffs/architecture-plan.md\`.
27
+ - Read assigned source files and tests.
28
+ - Read relevant module architecture docs only when referenced by the architecture plan or delegation message.
29
+ - Read \`.ai/generated/module-index.json\` and \`.ai/generated/public-surface.json\` when needed to confirm module or public surface boundaries.
30
+ - Stop before editing if the assigned module, files, \`VCM:CODE\` markers, behavior contract, validation expectation, worker state path, or report path is unclear.
31
+
32
+ ### Implementation Discipline
33
+
34
+ - Implement the assigned \`VCM:CODE\` markers completely and remove those markers before completion.
35
+ - Preserve architect-defined file responsibilities, callable-surface signatures, visibility, exports, contracts, and error boundaries.
36
+ - Do not add or change cross-file callable surface unless the architecture plan explicitly defines it.
37
+ - Do not fake completion: no hardcoded success, disabled logic, swallowed errors, test-only shortcuts, or silent fallback that hides failure.
38
+ - Implement behavior from the approved architecture, existing domain model, real inputs, and project runtime flow.
39
+ - Keep changes limited to the assigned module or files.
40
+ - Preserve existing behavior unless the architecture plan explicitly changes it.
41
+ - Keep source comments durable: behavior, contracts, invariants, error boundaries, or non-obvious logic only.
42
+ - Do not copy task context, handoff instructions, temporary rationale, or coder guidance into source comments.
43
+
44
+ ### Tests
45
+
46
+ - Run only L0/L1 checks relevant to the assigned module or files.
47
+ - Add or update unit tests only for the assigned module when needed for baseline coverage.
48
+ - Do not run integration, E2E, smoke, full-suite, browser, multi-service, or final validation checks.
49
+ - Do not weaken, delete, or skip tests to make validation pass.
50
+ - If assigned-module tests cannot run, report the exact reason to Coder.
51
+
52
+ ### Git
53
+
54
+ - Commit the worker's completed changes before returning to Coder.
55
+ - Commit only changes made for the assigned module or files.
56
+ - Stage only assigned files; do not use \`git add -A\`, \`git add .\`, \`git commit -a\`, or broad path staging.
57
+ - Use a concise commit message that identifies the assigned module or implementation scope.
58
+ - If committing fails because the worktree changed concurrently, report the failure to Coder and do not attempt broad conflict resolution.
59
+
60
+ ### Output To Coder
61
+
62
+ Return a concise completion report with:
63
+
64
+ - assigned module/files
65
+ - completed Scaffold Manifest IDs or \`VCM:CODE\` markers
66
+ - files changed
67
+ - tests/checks run
68
+ - commit hash
69
+ - remaining risks or skipped checks
70
+ - any architecture-plan/code-reality conflict
71
+ `;
72
+ }
@@ -23,7 +23,7 @@ PM Managed Mode applies only when the user explicitly asks to complete the curre
23
23
 
24
24
  - PM must drive the task to completion according to the user's request.
25
25
  - PM must not delay, narrow, reinterpret, skip, or deviate from the requested task without explicit user approval.
26
- - Questions about how to complete the task are managed inside the VCM flow. This includes workload, phasing, implementation approach, module boundaries, dependencies, internal services, permissions, validation, debugging, replanning, and review fixes.
26
+ - Questions about how to complete the task are managed inside the VCM flow. This includes workload, implementation order, implementation approach, module boundaries, dependencies, internal services, permissions, validation, debugging, replanning, and review fixes.
27
27
  - Simple or technical execution questions should be routed to Architect or the responsible role for decision.
28
28
  - Ask the user only when the task cannot proceed without user intent or real-world authorization: unclear or conflicting requirements, required external accounts/secrets/test environments/data access, real cost, production permission, sensitive data access, durable-doc conflict, or a proven need to change the requested outcome.
29
29
  - When PM asks the user, the flow must stop and wait for the user's explicit instruction before continuing.
@@ -44,6 +44,20 @@ PM Managed Mode applies only when the user explicitly asks to complete the curre
44
44
  - If architect reports that the fix exceeds Debug Mode limits or requires new module, new public surface, or new cross-file callable surface, resume the normal code-change flow: architect plan -> coder -> reviewer.
45
45
  - If Debug Mode finds durable docs or known-issues impact, keep the normal docs-sync gate after reviewer.
46
46
 
47
+ ### Architecture Diagnosis Routing
48
+
49
+ Within the same task, route to architect Architecture Diagnosis Mode when either condition is true:
50
+
51
+ - Reviewer rejects the implementation for the second time.
52
+ - Architect Replan is required for the second time.
53
+
54
+ Architecture Diagnosis Mode must run before sending more implementation work to coder.
55
+
56
+ After Architecture Diagnosis Mode:
57
+
58
+ - If architect reports no architecture change is needed, continue the existing Debug Mode or Replan flow.
59
+ - If architect reports an architecture problem, route architect for a normal architecture plan or replan before coder work.
60
+
47
61
  ### Worktree
48
62
 
49
63
  - Before dispatching work, confirm the current task repo root and branch.
@@ -66,14 +80,12 @@ PM may lightly rewrite the user's words to:
66
80
  - translate the user's intent into clear role-facing language
67
81
  - state whether this is confirmation, rejection, preference, or a small constraint
68
82
 
69
- ### Phased Tasks
83
+ ### Complete Task Scope
70
84
 
71
- - When architect provides a phased plan, dispatch only one phase at a time.
72
- - Do not split, merge, reorder, or redefine phases yourself; route phase-plan changes back to architect.
73
- - Each coder phase must complete its assigned implementation before PM dispatches the next phase.
74
- - Phase validation may require evidence up to L2, but route by runner: coder gets L0/L1 and explicitly assigned targeted fast L2 only; reviewer gets full L2, integration, multi-node, cross-service, persistence, runtime, public-contract, L3, and L4 gates.
75
- - Reserve full L3 validation for final task acceptance unless reviewer says a narrow phase smoke is needed.
76
- - Route back to architect only when coder or reviewer reports a technical mismatch with the approved plan.
85
+ - Once PM starts routing a user request, drive the accepted scope to completion unless the user explicitly changes it.
86
+ - Do not allow requested work to be deferred, converted into follow-up scope, or reduced without explicit user approval.
87
+ - If coder returns incomplete work because of workload, session length, context size, or task size, route coder back to complete the assigned implementation.
88
+ - Route back to architect only for technical mismatch with the approved architecture plan.
77
89
 
78
90
  ### Flow Gates
79
91
 
@@ -32,6 +32,8 @@ export function renderReviewerHarnessRules() {
32
32
  - Add anti-hardcode coverage when risk warrants it: use non-fixture inputs, boundary values, negative cases, repeated actions, and assertions through public/runtime paths.
33
33
  - Do not accept tests that only prove the current implementation shape; tests must prove the approved behavior contract.
34
34
  - If task-specific process comments appear in changed code while reviewing behavior, report them as a maintainability gap; task context belongs in handoff artifacts, not durable code comments.
35
+ - Treat architect-flagged public contracts, migrations, auth, data flow, routing, or dependency changes as inputs for reviewer-owned validation design.
36
+ - Record skipped L3 checks in \`.ai/vcm/handoffs/review-report.md\` with the reason.
35
37
  - Update \`docs/TESTING.md\` when validation strategy, commands, level mapping, integration/E2E case definitions, selection rules, final-validation cleanup, test gaps, or test expectations change.
36
38
 
37
39
  ### Testing Documentation
@@ -43,14 +45,6 @@ export function renderReviewerHarnessRules() {
43
45
  - Keep historical investigation details, superseded failures, temporary diagnostics, and per-task validation logs out of \`docs/TESTING.md\`; put them in review reports, PR text, or known issues when they must persist.
44
46
  - When updating \`docs/TESTING.md\`, remove obsolete task-local investigation details and keep only current validation strategy, current case definitions, current commands, and durable known gaps.
45
47
 
46
- ### Phase Validation
47
-
48
- - For phase review, run the strongest practical validation up to L2 that is relevant to the phase scope.
49
- - Reserve full L3 E2E / browser / integration validation for the final phase or whole-task acceptance.
50
- - Run a narrow L3 smoke during a phase only when that phase directly changes a critical E2E path or high-risk integration boundary.
51
- - Treat architect-flagged public contracts, migrations, auth, data flow, routing, or dependency changes as inputs for reviewer-owned validation design.
52
- - Record skipped L3 checks in \`.ai/vcm/handoffs/review-report.md\` with the reason and the planned final validation point.
53
-
54
48
  ### Outputs
55
49
 
56
50
  - Write \`.ai/vcm/handoffs/review-report.md\` with decision, evidence reviewed, tests added or updated, commands run or checked, validation results, failed expectations, reproduction steps, skipped checks with reasons, coverage gaps, and required follow-ups.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.6.17",
3
+ "version": "0.6.19",
4
4
  "description": "Local GUI session cockpit for Claude Code role sessions.",
5
5
  "type": "module",
6
6
  "files": [