vibe-coding-master 0.7.43 → 0.7.44

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.
Files changed (42) hide show
  1. package/README.md +40 -13
  2. package/dist/backend/api/artifact-routes.js +3 -0
  3. package/dist/backend/api/harness-routes.js +16 -0
  4. package/dist/backend/api/task-routes.js +1 -0
  5. package/dist/backend/api/workflow-control-routes.js +12 -0
  6. package/dist/backend/cli/install-vcm-harness.js +21 -0
  7. package/dist/backend/server.js +3 -1
  8. package/dist/backend/services/artifact-service.js +7 -30
  9. package/dist/backend/services/auto-memory-service.js +640 -12
  10. package/dist/backend/services/claude-hook-service.js +80 -2
  11. package/dist/backend/services/gate-review-service.js +173 -74
  12. package/dist/backend/services/harness-feedback-service.js +76 -78
  13. package/dist/backend/services/harness-service.js +27 -3
  14. package/dist/backend/services/runtime-coordinator-service.js +2 -1
  15. package/dist/backend/services/status-service.js +1 -0
  16. package/dist/backend/services/translation-worker-service.js +19 -4
  17. package/dist/backend/services/workflow-control-service.js +96 -12
  18. package/dist/backend/templates/handoff.js +44 -2
  19. package/dist/backend/templates/harness/architect-agent.js +13 -7
  20. package/dist/backend/templates/harness/architect-scaffold-worker-agent.js +1 -1
  21. package/dist/backend/templates/harness/check-scaffold-ledger.js +234 -10
  22. package/dist/backend/templates/harness/claude-root.js +3 -2
  23. package/dist/backend/templates/harness/coder-agent.js +8 -0
  24. package/dist/backend/templates/harness/gate-review.js +144 -49
  25. package/dist/backend/templates/harness/harness-engineer-agent.js +25 -10
  26. package/dist/backend/templates/harness/project-manager-agent.js +16 -10
  27. package/dist/backend/templates/harness/resolve-durable-doc-assignment.js +60 -0
  28. package/dist/backend/templates/harness/tester-agent.js +13 -0
  29. package/dist/backend/templates/harness/vcm-ask-user-skill.js +82 -0
  30. package/dist/backend/templates/harness/vcm-code-navigation-skill.js +7 -5
  31. package/dist/backend/templates/harness/vcm-task-state-skill.js +2 -2
  32. package/dist/backend/templates/harness/vcm-workflow-review-skill.js +1 -1
  33. package/dist/shared/types/workflow.js +1 -0
  34. package/dist/shared/validation/artifact-check.js +3 -3
  35. package/dist/shared/validation/artifact-contract.js +1 -1
  36. package/dist/shared/validation/artifact-registry.js +16 -0
  37. package/dist-frontend/assets/{index-VW9tYPP5.js → index-BvCmrFlN.js} +49 -49
  38. package/dist-frontend/index.html +1 -1
  39. package/package.json +1 -1
  40. package/scripts/claude-plugins/vcm-lsp-bridge/.claude-plugin/plugin.json +21 -6
  41. package/scripts/harness-tools/vcm-artifact +1 -2
  42. package/scripts/harness-tools/vcm-bash-guard +1 -1
@@ -24,8 +24,9 @@ ${renderRoleMemoryRules("architect")}
24
24
  - Follow the preloaded \`vcm-code-navigation\` skill whenever work requires code definitions, implementations, references, callers, callees, or behavior paths. This applies in every Architect mode and in direct user communication.
25
25
  - LSP is mandatory and directly available for navigating project source code. Start source-code navigation with LSP. If it is unavailable, report a VCM LSP configuration failure; do not substitute source text search.
26
26
  - Use LSP definitions, implementations, references, document or workspace symbols, and incoming or outgoing calls for all source-code symbol and relationship queries.
27
- - Do not use the built-in \`Grep\` tool or shell text-search commands such as \`grep\`, \`rg\`, \`git grep\`, \`ag\`, or \`ack\` to search project source code, test code, or executable scripts. This prohibition includes locating or inferring definitions, implementations, references, callers, callees, symbols, and behavior paths.
28
- - Use Glob to locate files and Read to inspect complete code. Text search is allowed only for non-source artifacts that LSP does not model, such as documentation, configuration or data files, generated context, and logs. To inspect source comments, locate the source through LSP or Glob and use Read.
27
+ - LSP reference results are symbol-specific. An accessor, its backing field, a trait declaration, its implementation method, a wrapper, and an alias are separate symbols. Query every relevant symbol separately; one symbol's reference result cannot prove a complete semantic class. When starting from an accessor or wrapper, read its implementation, resolve its backing field, delegate, or trait item with LSP, then query those symbols too.
28
+ - Do not use the built-in \`Grep\` tool or shell text-search commands such as \`grep\`, \`rg\`, \`git grep\`, \`ag\`, or \`ack\` to search project source code, test code, or executable scripts, except for the bounded fallback below. This prohibition includes locating or inferring definitions, implementations, references, callers, callees, symbols, and behavior paths.
29
+ - Use Glob to locate files and Read to inspect complete code. Text search is allowed for non-source artifacts that LSP does not model, such as documentation, configuration or data files, generated context, and logs. For source, use exact text search only after the correct LSP operation has been run against the actual symbol and its result is demonstrably partial for a relationship LSP does not model or expose. Record the LSP operation, result, and missing relationship first; restrict the search to the already identified owning file or module; read every candidate match and verify its semantics against code and LSP. Text matches identify candidates only and are not relationship evidence.
29
30
  - Cost, latency, round trips, batching, parallelism, or an expectation of equivalent results never permits source-code text search. Wait for the role-session LSP and follow the skill's bounded retry procedure.
30
31
  - If LSP cannot resolve a required project-owned relationship, record it as unresolved. Do not replace semantic evidence with text matches.
31
32
 
@@ -109,7 +110,7 @@ ${renderRoleMemoryRules("architect")}
109
110
  - \`Scaffold Manifest\`: an item ledger — one entry per implementation item. Use columns in the exact order \`ID | Action | File | ...\`; use an ID matching \`AA-1\` through \`AAAAAA-9999\`, an Action of exactly \`create\`, \`change\`, or \`delete\`, and a backticked repo-relative File path. An item is one created body or surface, one required change site — one contiguous edit region inside an existing body or surface — or one deletion of a body, site, or file. An item not in the ledger is not in the plan; coder must not implement it. When no scaffold item exists, omit the table and write exactly \`No scaffold items.\`; an empty table is invalid.
110
111
  - Each ledger entry carries, in this column order: a unique stable ID such as \`SCF-001\`, action, exact file path, symbol or site, coder work, allowed implementation freedom, and a behavior/contract proof point. Per-file evidence, why-in-scope, and durable-comment needs live in the Module/File Plan, not in the ledger. Open-ended coverage language ("as work proceeds", "replicate", "etc.", "and others") is forbidden anywhere in the ledger.
111
112
  - IDs and markers correspond one to one: every \`create\`, \`change\`, and \`delete\` entry has exactly one \`VCM:CODE <ID>\` marker pre-placed at its declared file and site; a \`delete\` marker sits on the code to be removed and leaves with it.
112
- - The Scaffold Manifest is complete only when the ledger ID set and the tree's \`VCM:CODE\` ID set are equal, each ID appears exactly once on each side, and each marker sits in its declared file (\`.ai/tools/check-scaffold-ledger\` automates the check). Any mismatch means the plan is not complete.
113
+ - The Scaffold Manifest is complete only when the ledger ID set and the tree's \`VCM:CODE\` ID set are equal, each ID appears exactly once on each side, and each marker sits in its declared file (\`.ai/tools/check-scaffold-ledger --mode scaffold\` automates the check). Any mismatch means the plan is not complete.
113
114
  - \`Scaffold Build Evidence\`: the exact compile/typecheck commands run on the committed scaffold, their results, and the scaffold commit hash. A missing, red, or stale-hash result means the plan is not complete.
114
115
  - When the plan introduces or changes a build configuration — a new compilation target, a feature-gated or restricted-runtime variant, a new artifact type, or a build-environment constraint — scaffold that configuration and add to \`Scaffold Build Evidence\` one named check per configuration that fails when the claim is false, run green at the scaffold commit; choose proving checks from the project coding standards when defined there. A build-configuration claim without its named green check means the plan is not complete.
115
116
  - The compile/typecheck and build-configuration checks in \`Scaffold Build Evidence\` must cover every wired exemplar, so each new cross-module call path is proven compilable at the scaffold stage. A call path that exists only in plan prose, over stub scaffold that never names the surfaces it will invoke, is not proven and the plan is not complete.
@@ -212,7 +213,7 @@ The code-reading phase is complete only when:
212
213
  - every indirect callback, event, hook, queue, route, and dynamic dispatch path has been resolved
213
214
  - every relevant state reader and writer has been read
214
215
  - every relevant cross-file surface caller and consumer has been read
215
- - every semantic relationship records LSP, runtime, external-boundary, or generated-boundary evidence
216
+ - every semantic relationship records LSP, runtime, verified bounded source, external-boundary, or generated-boundary evidence
216
217
  - no unresolved project-owned symbol remains
217
218
 
218
219
  Do not diagnose the root cause or choose a fix before the Code Reading Closure is complete.
@@ -281,7 +282,12 @@ Each rewritten \`architecture-diagnosis.md\` must be a complete, self-contained
281
282
 
282
283
  ### Docs Sync
283
284
 
284
- - In Docs-Only Flow, verify claims against current code and durable docs, update the PM-assigned project documents directly, run applicable documentation checks, and commit the changes; tester completion is not required.
285
+ - For a \`[VCM Durable Documentation Assignment]\`, update the assigned durable
286
+ document and directly related documentation, run applicable documentation
287
+ checks, commit the result, and submit \`docs-update-report.md\` with the exact
288
+ assigned Assignment ID. This backend assignment does not start Docs-Only Flow.
289
+
290
+ - In Docs-Only Flow, verify claims against current code and durable docs, update the PM-assigned project documents and related documentation needed for consistency, run applicable documentation checks, commit the changes, and submit \`.ai/vcm/handoffs/docs-update-report.md\` through \`vcm-artifact\` before reporting to PM.
285
291
  - In Code-Change Flow, Architect Debug Flow, and a code-producing Architecture Diagnosis Flow, perform post-validation docs sync only when project-manager requests it after tester completes.
286
292
  - Architect Debug Branch and Architecture Diagnosis Branch do not run their own docs sync.
287
293
 
@@ -336,8 +342,8 @@ Each rewritten \`architecture-diagnosis.md\` must be a complete, self-contained
336
342
 
337
343
  #### Docs Sync Report
338
344
 
339
- - Write \`.ai/vcm/handoffs/docs-sync-report.md\` as the final result of Docs-Only Flow and for post-validation docs sync in Code-Change Flow, Architect Debug Flow, or a code-producing Architecture Diagnosis Flow. Do not write it for a Debug/Diagnosis Branch.
340
- - In Docs-Only Flow, submit the complete report before returning to PM. The report must record the decision, changed documents, evidence reviewed, checks performed, and commit.
345
+ - Write \`.ai/vcm/handoffs/docs-sync-report.md\` for post-validation docs sync in Code-Change Flow, Architect Debug Flow, or a code-producing Architecture Diagnosis Flow. Do not write it for Docs-Only Flow or a Debug/Diagnosis Branch.
346
+ - In Docs-Only Flow, submit the complete \`.ai/vcm/handoffs/docs-update-report.md\` before returning to PM. It must record the decision, changed and reviewed documents, evidence reviewed, checks performed, commit, and remaining documentation issues.
341
347
  - The report records decision, evidence reviewed, current-truth reconciliation, generated-context freshness, cross-document consistency, architecture docs, active plans, testing-doc consistency, known-issues disposition, durable-doc audit command and result, docs updated, docs left unchanged, remaining documentation risks, and handoff notes.
342
348
  - Each rewritten \`docs-sync-report.md\` must be a complete, self-contained snapshot of the current docs-sync result and must not rely on a prior report revision.
343
349
  - \`Decision\` must be \`synced\`, \`unchanged\`, or \`blocked\`.
@@ -14,7 +14,7 @@ You are \`vcm-architect-scaffold-worker\`, a foreground subagent invoked by Arch
14
14
 
15
15
  ### Validation And Commit
16
16
 
17
- - Run \`.ai/tools/check-scaffold-ledger\` and the plan's scaffold L0 compile/typecheck checks.
17
+ - Run \`.ai/tools/check-scaffold-ledger --mode scaffold\` and the plan's scaffold L0 compile/typecheck checks.
18
18
  - Commit only the scaffold changes after the ledger reconciles and required checks pass.
19
19
  - Return the commit hash, changed files, ledger result, and exact check results to Architect.
20
20
  - If the assigned scaffold cannot be completed, return the concrete failure evidence without changing the plan.
@@ -1,10 +1,17 @@
1
1
  export function renderCheckScaffoldLedgerTool() {
2
2
  return `#!/usr/bin/env python3
3
- """Scaffold-ledger reconciliation machine enforcement of the Scaffold Manifest bijection.
3
+ """Lifecycle-aware Scaffold Manifest and VCM:CODE reconciliation.
4
4
 
5
5
  The architecture plan's Scaffold Manifest is an item ledger: one entry per implementation
6
6
  item, one unique ID per entry, and exactly one \`VCM:CODE <ID>\` marker in the tree per
7
- \`create\`/\`change\`/\`delete\` entry. This tool checks:
7
+ \`create\`/\`change\`/\`delete\` entry during scaffolding. Coder then removes successful
8
+ markers and preserves failed markers. The required \`--mode\` selects that lifecycle:
9
+
10
+ - \`scaffold\`: require the ledger and tree markers to form an exact bijection;
11
+ - \`completion\`: reconcile the ledger, Coder's Scaffold Completion table, and the
12
+ final tree marker state.
13
+
14
+ The tool checks:
8
15
 
9
16
  1. the ledger header follows the mandated column order (\`ID | Action | File | ...\`),
10
17
  every data-row ID matches the documented grammar as a complete cell and is unique,
@@ -17,8 +24,9 @@ item, one unique ID per entry, and exactly one \`VCM:CODE <ID>\` marker in the t
17
24
 
18
25
  Markers are scanned in git-tracked source files only (\`.md\` files and \`.ai/\` are excluded:
19
26
  prose may quote markers legitimately). Pure read; findings go to stderr; exit 0 clean,
20
- 1 on findings. \`--plan <path>\` overrides the default plan location. No plan file at all
21
- means there is nothing to check (exit 0) — a docs-only or planning-free task.
27
+ 1 on findings. \`--plan <path>\` and \`--completion <path>\` override the default artifact
28
+ locations. No plan file at all means there is nothing to check (exit 0) — a docs-only or
29
+ planning-free task.
22
30
  """
23
31
  import argparse
24
32
  import re
@@ -27,7 +35,9 @@ import sys
27
35
  from pathlib import Path
28
36
 
29
37
  PLAN = ".ai/vcm/handoffs/architecture-plan.md"
38
+ COMPLETION = ".ai/vcm/handoffs/coder-completion.md"
30
39
  MANIFEST_HEADING = re.compile(r"^##\\s+Scaffold Manifest\\s*$")
40
+ COMPLETION_HEADING = re.compile(r"^##\\s+Scaffold Completion\\s*$")
31
41
  SECTION_HEADING = re.compile(r"^##\\s+\\S")
32
42
  ID_PATTERN = re.compile(r"[A-Z]{2,6}-\\d{1,4}")
33
43
  EMPTY_MANIFEST = "No scaffold items."
@@ -36,6 +46,8 @@ TABLE_SEPARATOR_CELL = re.compile(r":?-{3,}:?")
36
46
  # The action is read from its own cell as a whole-cell verb — never sniffed from the
37
47
  # row text, so paths or prose containing action words cannot flip an item's class.
38
48
  ACTIONS = frozenset({"create", "change", "delete"})
49
+ RESULTS = frozenset({"done", "failed"})
50
+ MARKER_STATES = frozenset({"removed", "present"})
39
51
  PATH_TOKEN = re.compile(r"\`([^\`\\s]+/[^\`\\s]+|[^\`\\s]+\\.[A-Za-z0-9]{1,8})\`")
40
52
  MARKER_ANY = re.compile(r"VCM:CODE(?![A-Za-z0-9_])")
41
53
  FORBIDDEN = [
@@ -59,6 +71,19 @@ def manifest_section(plan_text: str) -> tuple[int, list[str]] | None:
59
71
  return None if start is None else (start, lines[start:])
60
72
 
61
73
 
74
+ def completion_section(completion_text: str) -> tuple[int, list[str]] | None:
75
+ """(start line number, section lines) of the Scaffold Completion section, or None."""
76
+ lines = completion_text.splitlines()
77
+ start = None
78
+ for index, line in enumerate(lines):
79
+ if start is None:
80
+ if COMPLETION_HEADING.match(line):
81
+ start = index + 1
82
+ elif SECTION_HEADING.match(line):
83
+ return (start, lines[start : index])
84
+ return None if start is None else (start, lines[start:])
85
+
86
+
62
87
  def is_separator_row(cells: list[str]) -> bool:
63
88
  return bool(cells) and all(TABLE_SEPARATOR_CELL.fullmatch(cell.replace(" ", "")) for cell in cells)
64
89
 
@@ -168,6 +193,111 @@ def parse_ledger(section_start: int, section: list[str], plan: str) -> tuple[dic
168
193
  return entries, findings, False
169
194
 
170
195
 
196
+ def parse_completion(
197
+ section_start: int,
198
+ section: list[str],
199
+ completion: str,
200
+ ) -> tuple[dict, list[str]]:
201
+ """{id: {action, result, marker_state, line}} and completion-table findings."""
202
+ entries: dict[str, dict] = {}
203
+ findings: list[str] = []
204
+ header_line = None
205
+ separator_seen = False
206
+ for offset, line in enumerate(section):
207
+ line_no = section_start + offset + 1
208
+ stripped = line.strip()
209
+ if not stripped.startswith("|"):
210
+ continue
211
+ cells = [cell.strip() for cell in stripped.strip("|").split("|")]
212
+
213
+ if header_line is None:
214
+ header_line = line_no
215
+ head = [cell.lower() for cell in cells]
216
+ if head != ["id", "action", "result", "marker state", "proof evidence"]:
217
+ findings.append(
218
+ f"{completion}:{line_no} [completion] header columns must be exactly "
219
+ f"\`ID | Action | Result | Marker State | Proof Evidence\`"
220
+ )
221
+ continue
222
+
223
+ if not separator_seen:
224
+ if is_separator_row(cells):
225
+ separator_seen = True
226
+ continue
227
+ findings.append(
228
+ f"{completion}:{line_no} [completion] missing Markdown separator row after "
229
+ f"the Scaffold Completion header"
230
+ )
231
+ separator_seen = True
232
+ elif is_separator_row(cells):
233
+ findings.append(
234
+ f"{completion}:{line_no} [completion] unexpected separator row inside "
235
+ f"Scaffold Completion data"
236
+ )
237
+ continue
238
+
239
+ entry_id = cells[0] if cells else ""
240
+ if not ID_PATTERN.fullmatch(entry_id):
241
+ findings.append(
242
+ f"{completion}:{line_no} [completion] ID cell \`{entry_id}\` must match "
243
+ f"\`[A-Z]{{2,6}}-[0-9]{{1,4}}\` exactly"
244
+ )
245
+ continue
246
+ if entry_id in entries:
247
+ findings.append(
248
+ f"{completion}:{line_no} [completion] duplicate ID {entry_id} "
249
+ f"(first at line {entries[entry_id]['line']})"
250
+ )
251
+ continue
252
+
253
+ action = cells[1].lower() if len(cells) > 1 else ""
254
+ result = cells[2].lower() if len(cells) > 2 else ""
255
+ marker_state = cells[3].lower() if len(cells) > 3 else ""
256
+ if action not in ACTIONS:
257
+ findings.append(
258
+ f"{completion}:{line_no} [completion] {entry_id} action must be exactly "
259
+ f"create/change/delete"
260
+ )
261
+ if result not in RESULTS:
262
+ findings.append(
263
+ f"{completion}:{line_no} [completion] {entry_id} result must be exactly "
264
+ f"done/failed"
265
+ )
266
+ if marker_state not in MARKER_STATES:
267
+ findings.append(
268
+ f"{completion}:{line_no} [completion] {entry_id} Marker State must be "
269
+ f"exactly removed/present"
270
+ )
271
+ entries[entry_id] = {
272
+ "action": action,
273
+ "result": result,
274
+ "marker_state": marker_state,
275
+ "line": line_no,
276
+ }
277
+
278
+ if header_line is None:
279
+ findings.append(
280
+ f"{completion}:{section_start + 1} [completion] Scaffold Completion must "
281
+ f"contain the required table"
282
+ )
283
+ elif not separator_seen:
284
+ findings.append(
285
+ f"{completion}:{header_line} [completion] Scaffold Completion table is "
286
+ f"missing its separator row"
287
+ )
288
+ if not entries:
289
+ findings.append(
290
+ f"{completion}:{header_line or section_start + 1} [completion] Scaffold "
291
+ f"Completion contains no valid entries"
292
+ )
293
+ return entries, findings
294
+
295
+
296
+ def completion_decision(completion_text: str) -> str | None:
297
+ match = re.search(r"^Decision:\\s*(\\S+)\\s*$", completion_text, re.MULTILINE)
298
+ return match.group(1) if match else None
299
+
300
+
171
301
  def forbidden_language(section_start: int, section: list[str], plan: str) -> list[str]:
172
302
  findings = []
173
303
  for offset, line in enumerate(section):
@@ -216,9 +346,15 @@ def tree_markers(root: Path) -> tuple[dict[str, list[tuple[str, int]]], list[str
216
346
 
217
347
  def main() -> int:
218
348
  parser = argparse.ArgumentParser(
219
- description="Scaffold Manifest ledger <-> VCM:CODE marker bijection check."
349
+ description="Lifecycle-aware Scaffold Manifest and VCM:CODE reconciliation."
220
350
  )
351
+ parser.add_argument("--mode", required=True, choices=("scaffold", "completion"))
221
352
  parser.add_argument("--plan", default=None, help=f"plan path (default {PLAN})")
353
+ parser.add_argument(
354
+ "--completion",
355
+ default=None,
356
+ help=f"Coder completion path for completion mode (default {COMPLETION})",
357
+ )
222
358
  args = parser.parse_args()
223
359
 
224
360
  root = Path(__file__).resolve().parents[2]
@@ -249,11 +385,6 @@ def main() -> int:
249
385
 
250
386
  ledger_ids = set(entries)
251
387
  tree_ids = set(markers)
252
- for entry_id in sorted(ledger_ids - tree_ids):
253
- findings.append(
254
- f"{plan}:{entries[entry_id]['line']} [ledger] {entry_id} has no marker "
255
- f"in the tree -> pre-place \`VCM:CODE {entry_id}\` in its declared file"
256
- )
257
388
  for entry_id in sorted(tree_ids - ledger_ids):
258
389
  path, line_no = markers[entry_id][0]
259
390
  findings.append(
@@ -271,6 +402,94 @@ def main() -> int:
271
402
  f"declared file \`{declared}\`"
272
403
  )
273
404
 
405
+ completed = 0
406
+ failed = 0
407
+ if args.mode == "scaffold":
408
+ for entry_id in sorted(ledger_ids - tree_ids):
409
+ findings.append(
410
+ f"{plan}:{entries[entry_id]['line']} [ledger] {entry_id} has no marker "
411
+ f"in the tree -> pre-place \`VCM:CODE {entry_id}\` in its declared file"
412
+ )
413
+ elif not explicit_empty:
414
+ completion_path = Path(args.completion) if args.completion else root / COMPLETION
415
+ if not completion_path.is_file():
416
+ findings.append(
417
+ f"{completion_path}:1 [completion] completion mode requires coder-completion.md"
418
+ )
419
+ else:
420
+ completion_text = completion_path.read_text(errors="replace")
421
+ completion = str(completion_path)
422
+ completed_section = completion_section(completion_text)
423
+ if completed_section is None:
424
+ findings.append(
425
+ f"{completion_path}:1 [completion] no \`## Scaffold Completion\` section"
426
+ )
427
+ completion_entries = {}
428
+ else:
429
+ completion_entries, completion_findings = parse_completion(
430
+ *completed_section,
431
+ completion,
432
+ )
433
+ findings += completion_findings
434
+
435
+ completion_ids = set(completion_entries)
436
+ for entry_id in sorted(ledger_ids - completion_ids):
437
+ findings.append(
438
+ f"{plan}:{entries[entry_id]['line']} [completion] {entry_id} is missing "
439
+ f"from Scaffold Completion"
440
+ )
441
+ for entry_id in sorted(completion_ids - ledger_ids):
442
+ findings.append(
443
+ f"{completion}:{completion_entries[entry_id]['line']} [completion] "
444
+ f"{entry_id} has no Scaffold Manifest entry"
445
+ )
446
+
447
+ for entry_id in sorted(ledger_ids & completion_ids):
448
+ ledger_entry = entries[entry_id]
449
+ completion_entry = completion_entries[entry_id]
450
+ result = completion_entry["result"]
451
+ marker_state = completion_entry["marker_state"]
452
+ marker_count = len(markers.get(entry_id, []))
453
+ if completion_entry["action"] != ledger_entry["action"]:
454
+ findings.append(
455
+ f"{completion}:{completion_entry['line']} [completion] {entry_id} "
456
+ f"action \`{completion_entry['action']}\` does not match Scaffold "
457
+ f"Manifest action \`{ledger_entry['action']}\`"
458
+ )
459
+ if result == "done":
460
+ completed += 1
461
+ if marker_state != "removed":
462
+ findings.append(
463
+ f"{completion}:{completion_entry['line']} [completion] {entry_id} "
464
+ f"done requires Marker State \`removed\`"
465
+ )
466
+ if marker_count != 0:
467
+ findings.append(
468
+ f"{completion}:{completion_entry['line']} [completion] {entry_id} "
469
+ f"is done but {marker_count} marker(s) remain -> remove the completed marker"
470
+ )
471
+ elif result == "failed":
472
+ failed += 1
473
+ if marker_state != "present":
474
+ findings.append(
475
+ f"{completion}:{completion_entry['line']} [completion] {entry_id} "
476
+ f"failed requires Marker State \`present\`"
477
+ )
478
+ if marker_count != 1:
479
+ findings.append(
480
+ f"{completion}:{completion_entry['line']} [completion] {entry_id} "
481
+ f"failed requires exactly one preserved marker; found {marker_count}"
482
+ )
483
+
484
+ decision = completion_decision(completion_text)
485
+ expected_decision = "failed" if failed else "ready_for_review"
486
+ if decision != expected_decision:
487
+ findings.append(
488
+ f"{completion_path}:1 [completion] Decision must be "
489
+ f"\`{expected_decision}\` for the recorded item results; found "
490
+ f"\`{decision or 'missing'}\`"
491
+ )
492
+
274
493
  for finding in findings:
275
494
  sys.stderr.write(finding + "\\n")
276
495
  if findings:
@@ -278,6 +497,11 @@ def main() -> int:
278
497
  return 1
279
498
  if explicit_empty:
280
499
  print("ledger explicitly empty: 0 ledger item(s), 0 marker(s)")
500
+ elif args.mode == "completion":
501
+ print(
502
+ f"ledger completion clean: {len(ledger_ids)} ledger item(s), "
503
+ f"{completed} done, {failed} failed, {len(tree_ids)} marker(s) remain"
504
+ )
281
505
  else:
282
506
  print(
283
507
  f"ledger reconciliation clean: {len(ledger_ids)} ledger item(s), "
@@ -14,7 +14,7 @@ export function renderRootClaudeHarnessRules() {
14
14
 
15
15
  ## VCM Managed Artifacts
16
16
 
17
- - VCM-managed Markdown under \`.ai/vcm/handoffs/\`, Coder Worker reports, request-scoped Gate Review reports, route messages, memory proposals, Harness Feedback, and retrospective reports must be submitted with \`.ai/tools/vcm-artifact\`; never write or edit the authoritative path directly.
17
+ - VCM-managed Markdown under \`.ai/vcm/handoffs/\`, Coder Worker reports, request-scoped Gate Review reports, route messages, memory proposals, and Harness Feedback must be submitted with \`.ai/tools/vcm-artifact\`; never write or edit the authoritative path directly.
18
18
  - Write the candidate outside \`.ai/vcm/\`, then run \`.ai/tools/vcm-artifact <kind> --file <candidate> --mode <draft|final>\`. Dynamic artifacts also require the exact VCM-assigned \`--path\`.
19
19
  - Use \`draft\` while an allowed lifecycle remains incomplete. Use \`final\` before routing or consuming a terminal artifact. A failed submission leaves the authoritative artifact unchanged; correct every reported violation and submit again.
20
20
  - Do not route, review, or rely on a candidate file. Only the VCM-written authoritative path is workflow evidence.
@@ -61,10 +61,11 @@ If a reusable harness problem is suspected, it is enough to record a concise fee
61
61
  - 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.
62
62
  - 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.
63
63
  - 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.
64
- - Docs-Only Flow uses: \`project-manager -> architect -> project-manager completion\`.
64
+ - Docs-Only Flow uses: \`project-manager -> assigned documentation role or roles -> project-manager completion\`.
65
65
  - Validation-Only Flow uses: \`project-manager -> tester -> validation-adequacy Gate Review -> project-manager completion\`.
66
66
  - Communication-Only Flow uses: \`project-manager response or relay -> completion\`.
67
67
  - Gate Review is PM-triggered at its defined trigger points; the tool decides whether review is enabled or required.
68
+ - Ignore commits whose subject starts with \`[VCM Harness]\`. Do not review, attribute, or route those commits unless they cause a test failure. A test failure caused by a Harness commit follows the normal test-failure flow.
68
69
  - Final acceptance closes only a complete code-delivery flow; it never closes Architect Debug Branch or Architecture Diagnosis Branch.
69
70
  - PR-Preparation Flow starts only after the active delivery flow completes; every complete code-delivery flow requires final acceptance to pass.
70
71
  - If Docs-Only Flow or Validation-Only Flow reveals that the accepted outcome requires production-code, runtime-behavior, public-contract, dependency, or system-architecture changes, project-manager routes through the full Code-Change Flow.
@@ -11,6 +11,7 @@ ${renderRoleMemoryRules("coder")}
11
11
  - When parallel worker implementation is used, own worker task splitting, worker prompts, worker result inspection for assigned completion and integration, final Scaffold Completion, and coder-level validation.
12
12
  - Implement assigned file/function-level scaffold items; do not analyze, review, dispute, or redesign architecture, module boundaries, public contracts, dependency direction, durable docs strategy, validation strategy, or final test adequacy.
13
13
  - Treat the architecture plan and scaffold as execution instructions, not review targets. Do not critique, reinterpret, or challenge them during Coder work.
14
+ - In a PM-routed Docs-Only Flow, update the assigned documentation and related documentation needed for consistency without changing production code or tests.
14
15
 
15
16
  ### Code Navigation
16
17
 
@@ -76,7 +77,14 @@ ${renderRoleMemoryRules("coder")}
76
77
 
77
78
  ### Handoff
78
79
 
80
+ - For a \`[VCM Durable Documentation Assignment]\`, verify and update the assigned
81
+ durable document and directly related documentation, run applicable checks,
82
+ commit the result, and submit \`docs-update-report.md\` with the exact assigned
83
+ Assignment ID. This backend assignment does not start Docs-Only Flow.
84
+
85
+ - In Docs-Only Flow, commit the documentation changes and submit \`.ai/vcm/handoffs/docs-update-report.md\` through \`vcm-artifact\` with the decision, changed and reviewed documents, evidence, checks, commit, and remaining documentation issues. Do not submit \`coder-completion.md\` for Docs-Only work.
79
86
  - Submit \`.ai/vcm/handoffs/coder-completion.md\` before routing back to project-manager: write a candidate outside \`.ai/vcm\`, then run \`.ai/tools/vcm-artifact coder-completion --file <candidate> --mode draft|final\`. This file is the complete, self-contained current implementation completion evidence, not a log. Each revision must restate every Scaffold Manifest disposition, changed file, helper, deviation, generated-context result, baseline-test change, L0/L1 command and result, worker result, commit, and objective failure still needed to review the current implementation without a prior revision. Replace stale content instead of appending history.
87
+ - After committing the actual implementation state and before submitting a final \`coder-completion.md\`, run \`.ai/tools/check-scaffold-ledger --mode completion --completion <candidate>\`; submit the candidate only after it passes. An incomplete draft does not use completion mode.
80
88
  - \`coder-completion.md\` must include \`Decision: ready_for_review | incomplete | failed\`.
81
89
  - \`coder-completion.md\` must report every Scaffold Manifest item disposition in the fixed Scaffold Completion table, plus changed files, private helpers added, manifest deviations as report-only facts, generated context status, baseline tests added or updated, L0/L1 commands and results, worker commits and integration status when workers were used, and compile/typecheck or L0/L1 failures.
82
90
  - Use this structure: