vibe-coding-master 0.7.29 → 0.7.30

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.
@@ -70,7 +70,8 @@ export function registerTaskRoutes(app, deps) {
70
70
  messages,
71
71
  orchestration,
72
72
  roundState,
73
- workflowState
73
+ workflowState,
74
+ architectRestart: deps.architectRestartService.getState(project.repoRoot, taskSlug)
74
75
  };
75
76
  }
76
77
  catch (error) {
@@ -84,7 +85,8 @@ export function registerTaskRoutes(app, deps) {
84
85
  updatedAt: new Date().toISOString()
85
86
  },
86
87
  roundState: degradedRoundState(taskSlug),
87
- workflowState: degradedWorkflowState(taskSlug)
88
+ workflowState: degradedWorkflowState(taskSlug),
89
+ architectRestart: deps.architectRestartService.getState(repoRoot, taskSlug)
88
90
  };
89
91
  }
90
92
  throw error;
@@ -130,7 +130,8 @@ export async function createServer(deps, options = {}) {
130
130
  messageService: deps.messageService,
131
131
  taskLaunchService: deps.taskLaunchService,
132
132
  roundService: deps.roundService,
133
- taskWorkflowService: deps.taskWorkflowService
133
+ taskWorkflowService: deps.taskWorkflowService,
134
+ architectRestartService: deps.architectRestartService
134
135
  });
135
136
  registerSessionRoutes(app, {
136
137
  projectService: deps.projectService,
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { resolveRepoPath } from "../adapters/filesystem.js";
3
- import { VcmError } from "../errors.js";
3
+ import { toVcmError, VcmError } from "../errors.js";
4
4
  import { getTaskRuntimeRepoRoot } from "./task-service.js";
5
5
  import { ARCHITECT_PLANNING_MEMORY_CANDIDATE_PATH } from "./memory-review-paths.js";
6
6
  import { validateMemoryProposal } from "./memory-proposal-validation.js";
@@ -23,40 +23,41 @@ export function createArchitectRestartService(deps) {
23
23
  async schedule(repoRoot, taskSlug) {
24
24
  const session = await requireRunningArchitect(repoRoot, taskSlug);
25
25
  await requireCompletePlan(repoRoot, taskSlug);
26
- const memoryCandidatePath = (await deps.appSettings.getPreferences()).autoMemoryEnabled
27
- ? ARCHITECT_PLANNING_MEMORY_CANDIDATE_PATH
28
- : undefined;
29
- const task = await deps.taskService.loadTask(repoRoot, taskSlug);
30
- const candidatePath = resolveRepoPath(getTaskRuntimeRepoRoot(task), ARCHITECT_PLANNING_MEMORY_CANDIDATE_PATH);
31
- if (deps.fs.removePath) {
32
- await deps.fs.removePath(candidatePath, { force: true });
33
- }
34
- else if (await deps.fs.pathExists(candidatePath)) {
35
- await deps.fs.writeText(candidatePath, "");
36
- }
37
26
  const key = taskKey(repoRoot, taskSlug);
38
27
  const existing = pendingByTask.get(key);
39
28
  if (existing?.sessionId === session.id) {
40
- existing.stopped = false;
41
- existing.deliveredMessageId = undefined;
42
- existing.acceptedMessageId = undefined;
43
- existing.gateAccepted = false;
44
- existing.executing = false;
45
- existing.memoryCandidatePath = memoryCandidatePath;
29
+ if (existing.status === "blocked") {
30
+ existing.status = "pending";
31
+ existing.blocker = undefined;
32
+ await tryRestart(existing);
33
+ return {
34
+ taskSlug,
35
+ sessionId: session.id,
36
+ status: "scheduled",
37
+ ...(existing.memoryCandidatePath
38
+ ? { memoryCandidatePath: existing.memoryCandidatePath }
39
+ : {})
40
+ };
41
+ }
46
42
  return {
47
43
  taskSlug,
48
44
  sessionId: session.id,
49
- status: "scheduled",
50
- ...(memoryCandidatePath ? { memoryCandidatePath } : {})
45
+ status: "already_scheduled",
46
+ ...(existing.memoryCandidatePath
47
+ ? { memoryCandidatePath: existing.memoryCandidatePath }
48
+ : {})
51
49
  };
52
50
  }
51
+ const memoryCandidatePath = (await deps.appSettings.getPreferences()).autoMemoryEnabled
52
+ ? ARCHITECT_PLANNING_MEMORY_CANDIDATE_PATH
53
+ : undefined;
53
54
  pendingByTask.set(key, {
54
55
  repoRoot,
55
56
  taskSlug,
56
57
  sessionId: session.id,
57
58
  stopped: false,
58
59
  gateAccepted: false,
59
- executing: false,
60
+ status: "pending",
60
61
  memoryCandidatePath
61
62
  });
62
63
  return {
@@ -66,9 +67,24 @@ export function createArchitectRestartService(deps) {
66
67
  ...(memoryCandidatePath ? { memoryCandidatePath } : {})
67
68
  };
68
69
  },
70
+ getState(repoRoot, taskSlug) {
71
+ const pending = pendingByTask.get(taskKey(repoRoot, taskSlug));
72
+ if (!pending) {
73
+ return null;
74
+ }
75
+ return {
76
+ taskSlug: pending.taskSlug,
77
+ sessionId: pending.sessionId,
78
+ status: pending.status,
79
+ ...(pending.memoryCandidatePath
80
+ ? { memoryCandidatePath: pending.memoryCandidatePath }
81
+ : {}),
82
+ ...(pending.blocker ? { blocker: { ...pending.blocker } } : {})
83
+ };
84
+ },
69
85
  async recordArchitectStop(repoRoot, taskSlug, sessionId) {
70
86
  const pending = pendingByTask.get(taskKey(repoRoot, taskSlug));
71
- if (!pending || pending.sessionId !== sessionId) {
87
+ if (!pending || pending.sessionId !== sessionId || pending.status === "blocked") {
72
88
  return;
73
89
  }
74
90
  pending.stopped = true;
@@ -79,7 +95,7 @@ export function createArchitectRestartService(deps) {
79
95
  return;
80
96
  }
81
97
  const pending = pendingByTask.get(taskKey(repoRoot, taskSlug));
82
- if (!pending) {
98
+ if (!pending || pending.status === "blocked") {
83
99
  return;
84
100
  }
85
101
  pending.deliveredMessageId = message.id;
@@ -90,7 +106,7 @@ export function createArchitectRestartService(deps) {
90
106
  return;
91
107
  }
92
108
  const pending = pendingByTask.get(taskKey(repoRoot, taskSlug));
93
- if (!pending) {
109
+ if (!pending || pending.status === "blocked") {
94
110
  return;
95
111
  }
96
112
  pending.acceptedMessageId = message.id;
@@ -98,7 +114,7 @@ export function createArchitectRestartService(deps) {
98
114
  },
99
115
  async recordArchitectureGateDisposition(repoRoot, taskSlug, accepted) {
100
116
  const pending = pendingByTask.get(taskKey(repoRoot, taskSlug));
101
- if (!pending) {
117
+ if (!pending || pending.status === "blocked") {
102
118
  return;
103
119
  }
104
120
  pending.gateAccepted = accepted;
@@ -131,7 +147,7 @@ export function createArchitectRestartService(deps) {
131
147
  }
132
148
  }
133
149
  async function tryRestart(pending) {
134
- if (pending.executing
150
+ if (pending.status !== "pending"
135
151
  || !pending.stopped
136
152
  || !pending.deliveredMessageId
137
153
  || pending.deliveredMessageId !== pending.acceptedMessageId
@@ -140,12 +156,26 @@ export function createArchitectRestartService(deps) {
140
156
  }
141
157
  const session = await deps.sessionService.getRoleSession(pending.repoRoot, pending.taskSlug, ARCHITECT_ROLE);
142
158
  if (!session
143
- || session.id !== pending.sessionId
144
- || session.status !== "running"
145
- || session.activityStatus !== "idle") {
159
+ || session.id !== pending.sessionId) {
160
+ blockPending(pending, new VcmError({
161
+ code: "ARCHITECT_RESTART_SESSION_UNAVAILABLE",
162
+ message: "Architect restart is blocked because the scheduled Architect session no longer exists.",
163
+ statusCode: 409
164
+ }));
146
165
  return;
147
166
  }
148
- pending.executing = true;
167
+ if (session.status !== "running") {
168
+ blockPending(pending, new VcmError({
169
+ code: "ARCHITECT_RESTART_SESSION_NOT_RUNNING",
170
+ message: "Architect restart is blocked because the scheduled Architect session is not running.",
171
+ statusCode: 409
172
+ }));
173
+ return;
174
+ }
175
+ if (session.activityStatus !== "idle") {
176
+ return;
177
+ }
178
+ pending.status = "executing";
149
179
  try {
150
180
  await requireCompletePlan(pending.repoRoot, pending.taskSlug);
151
181
  await requirePlanningMemoryCandidate(pending);
@@ -157,10 +187,19 @@ export function createArchitectRestartService(deps) {
157
187
  });
158
188
  pendingByTask.delete(taskKey(pending.repoRoot, pending.taskSlug));
159
189
  }
160
- catch {
161
- pending.executing = false;
190
+ catch (error) {
191
+ blockPending(pending, error);
162
192
  }
163
193
  }
194
+ function blockPending(pending, error) {
195
+ const normalized = toVcmError(error);
196
+ pending.status = "blocked";
197
+ pending.blocker = {
198
+ code: normalized.code,
199
+ message: normalized.message,
200
+ blockedAt: new Date().toISOString()
201
+ };
202
+ }
164
203
  async function requirePlanningMemoryCandidate(pending) {
165
204
  if (!pending.memoryCandidatePath) {
166
205
  return;
@@ -68,7 +68,10 @@ const SOURCE_ARTIFACTS = {
68
68
  ".ai/vcm/handoffs/test-report.md",
69
69
  "docs/TESTING.md"
70
70
  ],
71
- "code-diff": []
71
+ "code-diff": [
72
+ ".ai/vcm/handoffs/test-report.md",
73
+ ".ai/vcm/gate-reviews/validation-adequacy-review.md"
74
+ ]
72
75
  };
73
76
  const CODE_DIFF_SOURCE_ARTIFACTS = {
74
77
  coder: [
@@ -309,6 +312,39 @@ export function createGateReviewService(deps) {
309
312
  };
310
313
  }
311
314
  }
315
+ if (gate === "code-diff") {
316
+ const prerequisiteError = await readCodeDiffPrerequisiteError(deps, context, index);
317
+ if (prerequisiteError) {
318
+ index = applyGateState(index, gate, {
319
+ status: "failed",
320
+ decision: undefined,
321
+ error: prerequisiteError,
322
+ exceptionReason: undefined,
323
+ requestId: undefined,
324
+ requestPath: undefined,
325
+ inputHash: undefined,
326
+ baseCommit: undefined,
327
+ headCommit: undefined,
328
+ commits: undefined,
329
+ changedFiles: undefined,
330
+ diffStat: undefined,
331
+ codeDiffSource,
332
+ codeDiffSources: codeDiffSource ? [codeDiffSource] : undefined,
333
+ requestedAt: undefined,
334
+ startedAt: undefined,
335
+ completedAt: now(),
336
+ callbackStatus: "not_sent",
337
+ callbackError: undefined
338
+ }, now(), true);
339
+ await saveIndex(deps.fs, context.taskRepoRoot, index);
340
+ return {
341
+ status: "failed_to_start",
342
+ gate,
343
+ record: index.gates[gate],
344
+ message: prerequisiteError
345
+ };
346
+ }
347
+ }
312
348
  const codeDiffInput = gate === "code-diff"
313
349
  ? await resolveCodeDiffInput(deps, context, record)
314
350
  : undefined;
@@ -1037,6 +1073,27 @@ async function readValidationReportError(fs, taskRepoRoot) {
1037
1073
  return `${relativePath} is incomplete and cannot start validation-adequacy review. `
1038
1074
  + formatValidationArtifactFailure(check, content);
1039
1075
  }
1076
+ async function readCodeDiffPrerequisiteError(deps, context, index) {
1077
+ const reportError = await readValidationReportError(deps.fs, context.taskRepoRoot);
1078
+ if (reportError) {
1079
+ return "code-diff requires completed Tester validation. " + reportError;
1080
+ }
1081
+ const validationGate = index.gates["validation-adequacy"];
1082
+ if (!validationGate.required) {
1083
+ return undefined;
1084
+ }
1085
+ if (validationGate.status === "skipped" || validationGate.status === "overridden") {
1086
+ return undefined;
1087
+ }
1088
+ if (validationGate.status !== "completed" || validationGate.decision !== "approve") {
1089
+ return "code-diff requires the validation-adequacy Gate to complete successfully for the current Tester evidence.";
1090
+ }
1091
+ const currentValidationHash = await computeInputHash(deps, context.taskRepoRoot, "validation-adequacy");
1092
+ if (!validationGate.inputHash || validationGate.inputHash !== currentValidationHash) {
1093
+ return "code-diff requires a current validation-adequacy approval; code or test evidence changed after the recorded approval.";
1094
+ }
1095
+ return undefined;
1096
+ }
1040
1097
  async function readArchitectureEvidenceError(fs, taskRepoRoot) {
1041
1098
  const relativePath = ".ai/vcm/handoffs/architecture-evidence.md";
1042
1099
  const absolutePath = resolveRepoPath(taskRepoRoot, relativePath);
@@ -1420,7 +1477,10 @@ function getSourceArtifacts(gate, codeDiffSources) {
1420
1477
  if (gate !== "code-diff") {
1421
1478
  return SOURCE_ARTIFACTS[gate];
1422
1479
  }
1423
- return [...new Set((codeDiffSources ?? []).flatMap((source) => CODE_DIFF_SOURCE_ARTIFACTS[source]))];
1480
+ return [...new Set([
1481
+ ...SOURCE_ARTIFACTS["code-diff"],
1482
+ ...(codeDiffSources ?? []).flatMap((source) => CODE_DIFF_SOURCE_ARTIFACTS[source])
1483
+ ])];
1424
1484
  }
1425
1485
  function resolveCodeDiffSources(record, codeDiffInput, currentSource) {
1426
1486
  const continuingRecordedRange = record.baseCommit === codeDiffInput.baseCommit
@@ -115,9 +115,9 @@ ${renderRoleMemoryRules("architect")}
115
115
 
116
116
  #### Planning Completion
117
117
 
118
- - After the complete plan, scaffold, reconciliation, L0 evidence, and commits are ready, use the \`restart-architect\` skill before writing the completed Architect-to-PM route message.
119
- - If VCM returns a \`memoryCandidatePath\`, use \`vcm-propose-memory\` to write the planning-session memory candidate to that path before routing. Include only verified, durable, reusable project knowledge from planning; do not record task narrative, temporary state, unverified conclusions, or Harness rules.
120
- - After the required candidate is written, write the route message with both architecture artifacts and the plan, then end the turn. VCM keeps this session for any architecture-plan Gate revision and restarts it only after the Gate is accepted. Do not wait for or inspect the replacement session.
118
+ - Before the first completed Architect-to-PM planning route, use the \`restart-architect\` skill after the complete plan, scaffold, reconciliation, L0 evidence, and commits are ready.
119
+ - If VCM returns a \`memoryCandidatePath\`, ensure one planning-session memory candidate exists at that path before routing. Use \`vcm-propose-memory\` only when the candidate is absent. Include only verified, durable, reusable project knowledge from planning; do not record task narrative, temporary state, unverified conclusions, or Harness rules.
120
+ - Gate revision rounds reuse the same pending restart and task-level candidate; do not recreate either one. Write the latest route message with both architecture artifacts and the plan, then end the turn. VCM restarts the session only after the Gate is accepted. Do not wait for or inspect the replacement session.
121
121
 
122
122
  ### Complete Task Planning
123
123
 
@@ -51,8 +51,8 @@ If a reusable harness problem is suspected, it is enough to record a concise fee
51
51
  - All standard workflow routes among project-manager, architect, coder, and tester are PM-hub routes. Project-manager starts and advances every flow; architect, coder, and tester report blockers, failures, conflicts, incomplete work, and findings back to project-manager.
52
52
  - Code changes use: \`project-manager -> architect interview -> architect planning -> coder -> tester -> architect docs sync -> project-manager final acceptance\`.
53
53
  - Architect Debug Mode runs inside either Architect Debug Flow or Architect Debug Branch. Architecture Diagnosis Mode runs inside either Architecture Diagnosis Flow or Architecture Diagnosis Branch.
54
- - Architect Debug Flow and an Architecture Diagnosis Flow that produces code changes continue through code-diff Gate Review, tester validation, architect docs sync, and project-manager final acceptance. An analysis-only Architecture Diagnosis Flow completes from the diagnosis result.
55
- - Architect Debug Branch and Architecture Diagnosis Branch preserve the active parent flow and resume point, then return there after successful validation. They do not run their own final acceptance.
54
+ - Code-Change Flow, Architect Debug Flow, and an Architecture Diagnosis Flow that produces code changes run tester validation, validation-adequacy Gate Review, and then code-diff Gate Review before architect docs sync and project-manager final acceptance. An analysis-only Architecture Diagnosis Flow completes from the diagnosis result.
55
+ - Architect Debug Branch and Architecture Diagnosis Branch preserve the active parent flow and resume point, then return there after tester validation, validation-adequacy Gate Review, and code-diff Gate Review complete. They do not run their own final acceptance.
56
56
  - Docs-Only Flow uses: \`project-manager -> architect -> project-manager completion\`.
57
57
  - Validation-Only Flow uses: \`project-manager -> tester -> validation-adequacy Gate Review -> project-manager completion\`.
58
58
  - Communication-Only Flow uses: \`project-manager response or relay -> completion\`.
@@ -207,10 +207,12 @@ convert the result to \`pass\` or independently accept the risk.
207
207
 
208
208
  ## Code Diff Gate
209
209
 
210
- Read \`.claude/agents/coder.md\` and \`docs/CODING_STANDARDS.md\`; use
211
- architect/tester definitions only to understand implementation and test
212
- responsibility boundaries. Review every commit in the range named by VCM and
213
- nothing outside that range.
210
+ Read \`.claude/agents/coder.md\`, \`.claude/agents/tester.md\`,
211
+ \`.ai/vcm/handoffs/test-report.md\`, the current validation-adequacy Gate report,
212
+ and \`docs/CODING_STANDARDS.md\`; use the architect definition to understand
213
+ implementation responsibility boundaries. Code-diff runs only after Tester
214
+ validation and the current validation-adequacy disposition. Review every commit
215
+ in the range named by VCM and nothing outside that range.
214
216
 
215
217
  Use every code source and evidence artifact named in the VCM prompt. A source
216
218
  chain means the range contains the original implementation and later corrective
@@ -262,6 +264,11 @@ and changes outside its governing evidence. Verify callable and public-surface
262
264
  changes against their callers, exports, compatibility obligations, generated
263
265
  context, and durable documentation.
264
266
 
267
+ Use the completed test report and validation-adequacy disposition as execution
268
+ evidence while independently deciding whether the implementation handles its
269
+ required behavior and boundary cases. Do not repeat the validation-adequacy
270
+ decision.
271
+
265
272
  Inspect changed baseline tests for the changed callable units and applicable
266
273
  branches. Request changes for weakened, deleted, skipped, fabricated, or
267
274
  implementation-shaped tests, and for obvious missing baseline coverage required
@@ -464,8 +471,8 @@ Use this skill at every project-manager Gate Review trigger point and whenever V
464
471
  ## Trigger Points
465
472
 
466
473
  - \`architecture-plan\`: after the user confirms \`.ai/vcm/handoffs/architecture-brief.md\` and architect writes \`.ai/vcm/handoffs/architecture-plan.md\`, before coder dispatch.
467
- - \`validation-adequacy\`: after tester writes a terminal \`Test Result: pass|fail\` that the active flow permits to reach the gate, before post-validation docs sync or final acceptance in a code-delivery flow, or before Validation-Only Flow completion. Never request this gate for \`Test Result: incomplete\`.
468
- - \`code-diff\`: after Coder returns \`Decision: ready_for_review\`, Architect Debug Mode completes a code fix, or Architecture Diagnosis Mode completes a code fix, before PM routes to Tester. Identify the source with \`--source coder\`, \`--source architect-debug\`, or \`--source architect-diagnosis\`.
474
+ - \`validation-adequacy\`: after tester writes a terminal \`Test Result: pass|fail\` that the active flow permits to reach the gate. Never request this gate for \`Test Result: incomplete\`.
475
+ - \`code-diff\`: after Tester completes and the current validation-adequacy Gate finishes successfully for a Coder implementation, Architect Debug fix, or Architecture Diagnosis fix. Identify the production-code source with \`--source coder\`, \`--source architect-debug\`, or \`--source architect-diagnosis\`. Validation-Only Flow does not request code-diff.
469
476
 
470
477
  ## Request
471
478
 
@@ -500,6 +507,7 @@ import argparse
500
507
  import hashlib
501
508
  import json
502
509
  import os
510
+ import re
503
511
  import subprocess
504
512
  import sys
505
513
  import urllib.error
@@ -528,7 +536,10 @@ SOURCE_ARTIFACTS = {
528
536
  ".ai/vcm/handoffs/test-report.md",
529
537
  "docs/TESTING.md",
530
538
  ],
531
- "code-diff": [],
539
+ "code-diff": [
540
+ ".ai/vcm/handoffs/test-report.md",
541
+ ".ai/vcm/gate-reviews/validation-adequacy-review.md",
542
+ ],
532
543
  }
533
544
  CODE_DIFF_SOURCE_ARTIFACTS = {
534
545
  "coder": [
@@ -703,11 +714,14 @@ def code_diff_sources(gate_record: dict, source: str | None, code_diff: dict) ->
703
714
  def source_artifacts(gate: str, sources: list[str] | None) -> list[str]:
704
715
  if gate != "code-diff":
705
716
  return SOURCE_ARTIFACTS[gate]
706
- return list(dict.fromkeys(
717
+ return list(dict.fromkeys([
718
+ *SOURCE_ARTIFACTS["code-diff"],
719
+ *(
707
720
  artifact
708
721
  for source in (sources or [])
709
722
  for artifact in CODE_DIFF_SOURCE_ARTIFACTS.get(source, [])
710
- ))
723
+ ),
724
+ ]))
711
725
 
712
726
 
713
727
  def input_hash(root: Path, gate: str, sources: list[str] | None = None, gate_record=None) -> str:
@@ -787,6 +801,31 @@ def core_input_status(root: Path, gate: str) -> tuple[str, str] | None:
787
801
  return (core_artifact, "ready")
788
802
 
789
803
 
804
+ def code_diff_prerequisite_error(root: Path, index: dict) -> str | None:
805
+ report_path = root / ".ai/vcm/handoffs/test-report.md"
806
+ try:
807
+ report = report_path.read_text()
808
+ except OSError:
809
+ return "code-diff requires completed Tester validation. .ai/vcm/handoffs/test-report.md is missing."
810
+ result = re.search(r"^\\s*Test Result\\s*:\\s*(pass|fail|incomplete)\\s*$", report, re.IGNORECASE | re.MULTILINE)
811
+ if result is None:
812
+ return "code-diff requires completed Tester validation. Test Result must be exactly pass or fail."
813
+ if result.group(1).lower() == "incomplete":
814
+ return "code-diff requires completed Tester validation. Test Result is incomplete."
815
+
816
+ validation = index.get("gates", {}).get("validation-adequacy", {})
817
+ if not isinstance(validation, dict) or not validation.get("required", False):
818
+ return None
819
+ if validation.get("status") in ("skipped", "overridden"):
820
+ return None
821
+ if validation.get("status") != "completed" or validation.get("decision") != "approve":
822
+ return "code-diff requires the validation-adequacy Gate to complete successfully for the current Tester evidence."
823
+ current_hash = input_hash(root, "validation-adequacy")
824
+ if not validation.get("inputHash") or validation.get("inputHash") != current_hash:
825
+ return "code-diff requires a current validation-adequacy approval; code or test evidence changed after the recorded approval."
826
+ return None
827
+
828
+
790
829
  def request_id(gate: str) -> str:
791
830
  stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
792
831
  return f"{stamp}-{gate}-{uuid.uuid4().hex[:8]}"
@@ -883,6 +922,37 @@ def local_request(gate: str, source: str | None) -> int:
883
922
  print_result("not_required", gate=gate, message=f"{core_status[0]} is {core_status[1]}.")
884
923
  return 0
885
924
 
925
+ if gate == "code-diff":
926
+ prerequisite_error = code_diff_prerequisite_error(root, index)
927
+ if prerequisite_error:
928
+ gate_record = index["gates"].setdefault(gate, {})
929
+ gate_record.update({
930
+ "required": True,
931
+ "status": "failed",
932
+ "decision": None,
933
+ "error": prerequisite_error,
934
+ "exceptionReason": None,
935
+ "requestId": None,
936
+ "requestPath": None,
937
+ "inputHash": None,
938
+ "baseCommit": None,
939
+ "headCommit": None,
940
+ "commits": None,
941
+ "changedFiles": None,
942
+ "diffStat": None,
943
+ "requestedAt": None,
944
+ "startedAt": None,
945
+ "completedAt": now_iso(),
946
+ "callbackStatus": "not_sent",
947
+ "callbackError": None,
948
+ "updatedAt": now_iso(),
949
+ })
950
+ if index.get("activeGate") == gate:
951
+ index["activeGate"] = None
952
+ write_json(index_path, index)
953
+ print_result("failed_to_start", gate=gate, reason=prerequisite_error)
954
+ return 2
955
+
886
956
  gate_record = index["gates"].get(gate, {})
887
957
  code_diff = {}
888
958
  if gate == "code-diff":
@@ -82,7 +82,7 @@ Use this flow when the accepted task requires production-code or runtime-behavio
82
82
 
83
83
  The main flow is:
84
84
 
85
- \`Architect Interview and planning -> architecture-plan Gate -> Coder implementation -> code-diff Gate -> Tester validation -> validation-adequacy Gate -> Architect docs sync -> Final Acceptance -> completed\`
85
+ \`Architect Interview and planning -> architecture-plan Gate -> Coder implementation -> Tester validation -> validation-adequacy Gate -> code-diff Gate -> Architect docs sync -> Final Acceptance -> completed\`
86
86
 
87
87
  PM may leave this path only through the allowed branches below.
88
88
 
@@ -92,10 +92,10 @@ PM may leave this path only through the allowed branches below.
92
92
  - **Architecture Plan Revision:** If Architect planning is incomplete, route Architect again to continue the recorded planning work plan; multi-round planning against \`.ai/vcm/handoffs/planning-progress.md\` is the normal path for large plans, and PM must not press for completion within one round or accept summary-row compression in place of remaining steps. If the architecture-plan Gate returns \`request_changes\`, route the complete report to Architect, then rerun the full architecture-plan Gate after the plan and scaffold are revised.
93
93
  - **Coder Continuation:** If Coder returns \`Decision: incomplete\`, lacks the required completion artifact, or has not completed implementation and L0/L1 validation, route Coder again — this is the only route for an in-progress sweep. Problems recorded inside an incomplete report are sweep state, not routable failures; PM routes problems onward only from a post-sweep \`failed\` report carrying the consolidated per-item disposition.
94
94
  - **Coder Failure Debug:** If Coder returns \`Decision: failed\` with compile, typecheck, or L0/L1 failure evidence after implementation, suspend the main flow and enter Architect Debug Branch.
95
- - **Code-Diff Correction:** If the code-diff Gate returns \`request_changes\`, suspend the main flow and enter Architect Debug Branch with the Gate report.
96
95
  - **Tester Continuation:** If Tester returns \`Test Result: incomplete\`, route Tester again to continue the recorded remaining validation. Do not enter Debug, Diagnosis, or validation-adequacy Gate Review.
97
96
  - **Tester Failure:** If Tester returns \`Test Result: fail\` for the original Coder implementation, enter Architect Debug Branch.
98
97
  - **Validation Revision:** If the validation-adequacy Gate returns \`request_changes\`, route the report to Tester, then rerun the validation-adequacy Gate after Tester updates the tests or test report.
98
+ - **Code-Diff Correction:** If the code-diff Gate returns \`request_changes\`, suspend the main flow and enter Architect Debug Branch with the Gate report.
99
99
  - **Docs Sync Correction:** \`Decision: synced\` or \`unchanged\` continues to Final Acceptance. \`Decision: blocked\` remains at docs sync unless the report identifies an allowed Debug, Diagnosis, or user-decision branch.
100
100
  - **Final Acceptance Follow-Up:** Route \`needs-coder-follow-up\` to Coder, \`needs-architect-follow-up\` to Architect, \`needs-docs-sync\` to Architect docs sync, and \`blocked-by-user-decision\` to the user. After follow-up work, resume from the earliest affected Code-Change Flow step and repeat every downstream Gate.
101
101
  - **User Decision:** Pause only when the flow requires user intent, external authorization, or an exact user-approved exception. Resume from the suspended step after the user's decision is recorded.
@@ -146,19 +146,20 @@ Use Architect Debug Branch when another active flow is suspended to correct impl
146
146
 
147
147
  The shared path is:
148
148
 
149
- \`Architect Debug Mode -> code-diff --source architect-debug -> Tester\`
149
+ \`Architect Debug Mode -> Tester -> validation-adequacy Gate -> code-diff --source architect-debug\`
150
150
 
151
151
  #### Allowed Branches
152
152
 
153
153
  - **Normal Plan Required:** If Architect returns \`normal architecture plan required\`, enter Code-Change Flow at Architect planning. When Debug is a branch of Code-Change Flow, resume that parent flow at Architect planning.
154
- - **Code-Diff Revision:** If the code-diff Gate returns \`request_changes\`, route the report to Architect Debug Mode and rerun \`code-diff --source architect-debug\` after correction.
155
154
  - **Tester Continuation:** If Tester returns \`Test Result: incomplete\`, route Tester again to continue the recorded remaining validation.
156
155
  - **Architecture Diagnosis:** If Tester returns \`Test Result: fail\`, enter Architecture Diagnosis Branch.
156
+ - **Validation Revision:** If the validation-adequacy Gate returns \`request_changes\`, route the report to Tester, then rerun the validation-adequacy Gate after Tester updates the tests or test report.
157
+ - **Code-Diff Revision:** If the code-diff Gate returns \`request_changes\`, route the report to Architect Debug Mode. After correction, repeat Tester validation, validation-adequacy Gate, and \`code-diff --source architect-debug\`.
157
158
 
158
159
  #### Successful Exit
159
160
 
160
- - For Architect Debug Flow, Tester pass continues to \`validation-adequacy Gate -> Architect docs sync -> Final Acceptance\`.
161
- - For Architect Debug Branch, Tester pass returns to the recorded parent-flow resume point. The branch does not run its own docs sync or Final Acceptance.
161
+ - For Architect Debug Flow, code-diff approval continues to \`Architect docs sync -> Final Acceptance\`.
162
+ - For Architect Debug Branch, code-diff approval returns to the recorded parent-flow resume point after the parent flow's validation and code-diff milestones. The branch does not run its own docs sync or Final Acceptance.
162
163
 
163
164
  Architect Debug Flow or Branch never routes implementation to Coder. Architect executes Architect Debug Mode; PM owns whether the current context is a Flow or Branch and where it continues afterward.
164
165
 
@@ -175,22 +176,23 @@ Record the parent flow and resume point before entering the branch.
175
176
 
176
177
  The code-delivery path is:
177
178
 
178
- \`Architecture Diagnosis Mode -> code-diff --source architect-diagnosis -> Tester\`
179
+ \`Architecture Diagnosis Mode -> Tester -> validation-adequacy Gate -> code-diff --source architect-diagnosis\`
179
180
 
180
181
  Architecture Diagnosis Mode must run before another Debug Mode fix or Coder dispatch. Architect owns diagnosis, implementation, validation, and commit completion. Do not route Diagnosis implementation to Coder.
181
182
 
182
183
  #### Allowed Branches
183
184
 
184
- - **Code-Diff Revision:** If the code-diff Gate returns \`request_changes\`, route the report to Architecture Diagnosis Mode and rerun \`code-diff --source architect-diagnosis\` after correction.
185
185
  - **Tester Continuation:** If Tester returns \`Test Result: incomplete\`, route Tester again to continue the recorded remaining validation.
186
186
  - **Tester Failure:** If Tester returns \`Test Result: fail\` for the Diagnosis implementation, pause and report to the user. If required validation remains unavailable, ask whether the user explicitly approves retaining that exact Coverage Gap.
187
+ - **Validation Revision:** If the validation-adequacy Gate returns \`request_changes\`, route the report to Tester, then rerun the validation-adequacy Gate after Tester updates the tests or test report.
188
+ - **Code-Diff Revision:** If the code-diff Gate returns \`request_changes\`, route the report to Architecture Diagnosis Mode. After correction, repeat Tester validation, validation-adequacy Gate, and \`code-diff --source architect-diagnosis\`.
187
189
 
188
190
  #### Successful Exit
189
191
 
190
192
  - An analysis-only Architecture Diagnosis Flow completes from the diagnosis result.
191
193
  - An analysis-only Architecture Diagnosis Branch returns to the recorded parent-flow resume point.
192
- - A code-producing Architecture Diagnosis Flow continues after Tester pass to \`validation-adequacy Gate -> Architect docs sync -> Final Acceptance\`.
193
- - A code-producing Architecture Diagnosis Branch returns after Tester pass to the recorded parent-flow resume point. It does not run its own docs sync or Final Acceptance.
194
+ - A code-producing Architecture Diagnosis Flow continues after code-diff approval to \`Architect docs sync -> Final Acceptance\`.
195
+ - A code-producing Architecture Diagnosis Branch returns after code-diff approval to the recorded parent-flow resume point after the parent flow's validation and code-diff milestones. It does not run its own docs sync or Final Acceptance.
194
196
 
195
197
  After Tester Failure, PM should summarize:
196
198
 
@@ -327,15 +329,15 @@ PM may lightly rewrite the user's words to:
327
329
  - A Tester \`Test Result: incomplete\` is continuation state, not failure evidence. Route Tester again and do not run validation-adequacy Gate Review or Final Acceptance from it.
328
330
  - The Architect does not begin planning until \`architecture-brief.md\` is confirmed (this happens inside the same Architect Interview-and-planning turn, not a separate PM route). Advance to the next gate only when the required role artifact/result is complete and PM routing rules allow that gate.
329
331
  - If a required artifact is missing, stale, blocked, or asks for a decision, route the issue to the responsible role or user.
330
- - In Code-Change Flow, Architect Debug Flow, and an Architecture Diagnosis Flow that produces code changes, request Architect post-validation docs sync after Tester completes. Architect Debug Branch and Architecture Diagnosis Branch return to their recorded resume points after Tester passes.
332
+ - In Code-Change Flow, Architect Debug Flow, and an Architecture Diagnosis Flow that produces code changes, request Architect post-validation docs sync only after Tester validation, validation-adequacy Gate, and code-diff Gate complete. Architect Debug Branch and Architecture Diagnosis Branch return to their recorded resume points only after those same milestones complete.
331
333
 
332
334
  ### Gate Review Gates
333
335
 
334
336
  - Gate Review requests are mandatory and unconditional. At every trigger point, use the \`vcm-gate-review\` skill to run \`.ai/tools/request-gate-review\` with the matching gate and code source arguments without first judging whether Gate Review is enabled. The tool (via VCM) is the single source of truth for enable state; never skip the run because you assume Gate Review is off or because the worktree has no gate-review index yet.
335
337
  - The tool's first output line decides the next step: \`disabled\`, \`not_required\`, or \`already_approved\` continue the normal VCM flow; \`started\` or \`running\` stop the turn and wait for the VCM callback; \`failed_to_start\` is a hard stop — report it to the user and do not silently proceed past the gate.
336
- - Trigger points (run each unconditionally): after the architecture brief is confirmed and Architect completes planning, before coder dispatch run \`architecture-plan\`; after Tester returns a terminal \`Test Result: pass|fail\` that the active flow permits to reach the gate, before post-validation docs sync or final acceptance in a code-delivery flow, or before Validation-Only Flow completion, run \`validation-adequacy\`; after any Coder \`Decision: ready_for_review\` result run \`code-diff --source coder\`; after any Architect Debug Mode completed code fix run \`code-diff --source architect-debug\`; after any Architecture Diagnosis Mode completed code fix run \`code-diff --source architect-diagnosis\`. Never run validation-adequacy for \`Test Result: incomplete\`. Run code-diff before routing to Tester.
338
+ - Trigger points (run each unconditionally): after the architecture brief is confirmed and Architect completes planning, before coder dispatch run \`architecture-plan\`; after Tester returns a terminal \`Test Result: pass|fail\` that the active flow permits to reach the gate, run \`validation-adequacy\`; after that validation-adequacy Gate completes successfully, run \`code-diff --source coder\` for Coder implementation, \`code-diff --source architect-debug\` for an Architect Debug fix, or \`code-diff --source architect-diagnosis\` for an Architecture Diagnosis fix. Validation-Only Flow stops after validation-adequacy and does not run code-diff. Never run either post-implementation Gate for \`Test Result: incomplete\`.
337
339
  - PM does not inspect commits or decide whether code changes exist. At a \`code-diff\` trigger point, run the tool; the tool decides \`disabled\`, \`not_required\`, \`already_approved\`, or starts review.
338
- - Do not run \`code-diff\` for incomplete, failed, planning-only, Docs-Only Flow, Validation-Only Flow, PR-Preparation Flow, or Communication-Only Flow.
340
+ - Do not run \`code-diff\` before Tester completes, while validation-adequacy is unresolved, or for incomplete, unresolved failed, planning-only, Docs-Only Flow, Validation-Only Flow, PR-Preparation Flow, or Communication-Only Flow. A terminal \`fail\` with the exact required user-approved testing gap may proceed only through the recorded validation-adequacy disposition.
339
341
  - Gate Review trigger points apply only when the active delivery flow reaches that milestone. Do not run Gate Review for Communication-Only Flow.
340
342
  - On a callback, accept only \`approve\` or \`request_changes\`. Apply \`request_changes\` through the allowed branch defined by the active flow; in Code-Change Flow use Architecture Plan Revision, Code-Diff Correction, or Validation Revision according to the gate.
341
343
  - Do not ask Reviewer to choose owners, fixes, Replan, or user-intervention needs.
@@ -9,12 +9,16 @@ Run:
9
9
  .ai/tools/request-architect-restart
10
10
  \`\`\`
11
11
 
12
- If VCM reports \`scheduled\` with a non-empty \`memoryCandidatePath\`, use
13
- \`vcm-propose-memory\` to write a planning-session memory candidate to that exact
14
- path before writing the completed route. This candidate is provisional input for
15
- the later Auto Memory review; it does not edit active memory.
12
+ If VCM reports \`scheduled\` with a non-empty \`memoryCandidatePath\`, ensure
13
+ that one planning-session memory candidate exists at that exact path before
14
+ writing the completed route. Use \`vcm-propose-memory\` to create it when it is
15
+ absent. The candidate is a task-level provisional input for the later Auto
16
+ Memory review; it does not edit active memory.
16
17
 
17
- Then write the completed Architect-to-PM route message and end the turn. VCM keeps the current Architect session through any architecture-plan Gate revision rounds and restarts it only after the route is accepted by PM and that Gate is approved or explicitly excepted.
18
+ If VCM reports \`already_scheduled\`, keep the existing candidate and pending
19
+ restart. Do not recreate either one.
20
+
21
+ Then write the completed Architect-to-PM route message and end the turn. VCM keeps the current Architect session and the same pending restart through any architecture-plan Gate revision rounds, then restarts it only after the latest route is accepted by PM and that Gate is approved or explicitly excepted.
18
22
 
19
23
  Do not use this skill for incomplete planning, user clarification, Debug Mode, Architecture Diagnosis Mode, or docs sync.`;
20
24
  }
@@ -0,0 +1 @@
1
+ export {};