@entelligentsia/forgecli 1.0.10 → 1.0.20

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 (183) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/dist/CHANGELOG-forge-plugin.md +211 -0
  3. package/dist/bin/forge.js +0 -0
  4. package/dist/extensions/forgecli/config-layer.js.map +1 -1
  5. package/dist/extensions/forgecli/context-governor-compaction.d.ts +83 -0
  6. package/dist/extensions/forgecli/context-governor-compaction.js +302 -0
  7. package/dist/extensions/forgecli/context-governor-compaction.js.map +1 -0
  8. package/dist/extensions/forgecli/context-governor.d.ts +173 -0
  9. package/dist/extensions/forgecli/context-governor.js +618 -0
  10. package/dist/extensions/forgecli/context-governor.js.map +1 -0
  11. package/dist/extensions/forgecli/dashboard/component.d.ts +105 -0
  12. package/dist/extensions/forgecli/dashboard/component.js +861 -0
  13. package/dist/extensions/forgecli/dashboard/component.js.map +1 -0
  14. package/dist/extensions/forgecli/dashboard/register.d.ts +2 -0
  15. package/dist/extensions/forgecli/dashboard/register.js +31 -0
  16. package/dist/extensions/forgecli/dashboard/register.js.map +1 -0
  17. package/dist/extensions/forgecli/dashboard/theme.d.ts +27 -0
  18. package/dist/extensions/forgecli/dashboard/theme.js +91 -0
  19. package/dist/extensions/forgecli/dashboard/theme.js.map +1 -0
  20. package/dist/extensions/forgecli/dashboard/view-model.d.ts +35 -0
  21. package/dist/extensions/forgecli/dashboard/view-model.js +54 -0
  22. package/dist/extensions/forgecli/dashboard/view-model.js.map +1 -0
  23. package/dist/extensions/forgecli/fix-bug.js +126 -7
  24. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  25. package/dist/extensions/forgecli/forge-artifact-tool.js +2 -1
  26. package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
  27. package/dist/extensions/forgecli/forge-commands.js +1 -0
  28. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  29. package/dist/extensions/forgecli/forge-init/phase4-register.js +53 -0
  30. package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
  31. package/dist/extensions/forgecli/forge-subagent.d.ts +20 -1
  32. package/dist/extensions/forgecli/forge-subagent.js +23 -7
  33. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  34. package/dist/extensions/forgecli/forge-tools.js +3 -1
  35. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  36. package/dist/extensions/forgecli/hook-dispatcher.d.ts +3 -1
  37. package/dist/extensions/forgecli/hook-dispatcher.js +37 -3
  38. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  39. package/dist/extensions/forgecli/index.js +38 -1
  40. package/dist/extensions/forgecli/index.js.map +1 -1
  41. package/dist/extensions/forgecli/lib/halt-advisor.d.ts +59 -0
  42. package/dist/extensions/forgecli/lib/halt-advisor.js +113 -0
  43. package/dist/extensions/forgecli/lib/halt-advisor.js.map +1 -0
  44. package/dist/extensions/forgecli/migration-engine.js +25 -12
  45. package/dist/extensions/forgecli/migration-engine.js.map +1 -1
  46. package/dist/extensions/forgecli/orchestrator-status-bar.d.ts +26 -0
  47. package/dist/extensions/forgecli/orchestrator-status-bar.js +213 -0
  48. package/dist/extensions/forgecli/orchestrator-status-bar.js.map +1 -0
  49. package/dist/extensions/forgecli/orchestrator-tree.d.ts +96 -0
  50. package/dist/extensions/forgecli/orchestrator-tree.js +390 -0
  51. package/dist/extensions/forgecli/orchestrator-tree.js.map +1 -0
  52. package/dist/extensions/forgecli/project-orientation.js +12 -8
  53. package/dist/extensions/forgecli/project-orientation.js.map +1 -1
  54. package/dist/extensions/forgecli/regenerate.d.ts +16 -0
  55. package/dist/extensions/forgecli/regenerate.js +110 -0
  56. package/dist/extensions/forgecli/regenerate.js.map +1 -1
  57. package/dist/extensions/forgecli/run-sprint.d.ts +3 -1
  58. package/dist/extensions/forgecli/run-sprint.js +34 -3
  59. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  60. package/dist/extensions/forgecli/run-task.d.ts +66 -1
  61. package/dist/extensions/forgecli/run-task.js +323 -12
  62. package/dist/extensions/forgecli/run-task.js.map +1 -1
  63. package/dist/extensions/forgecli/thread-switcher.d.ts +4 -1
  64. package/dist/extensions/forgecli/thread-switcher.js +118 -762
  65. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  66. package/dist/extensions/forgecli/viewport-events.js +32 -0
  67. package/dist/extensions/forgecli/viewport-events.js.map +1 -1
  68. package/dist/forge-payload/.base-pack/commands/fix-bug.md +1 -1
  69. package/dist/forge-payload/.base-pack/commands/run-sprint.md +1 -1
  70. package/dist/forge-payload/.base-pack/commands/run-task.md +1 -1
  71. package/dist/forge-payload/.base-pack/personas/architect.md +1 -1
  72. package/dist/forge-payload/.base-pack/personas/bug-fixer.md +1 -1
  73. package/dist/forge-payload/.base-pack/personas/collator.md +3 -3
  74. package/dist/forge-payload/.base-pack/personas/engineer.md +1 -1
  75. package/dist/forge-payload/.base-pack/personas/librarian.md +1 -1
  76. package/dist/forge-payload/.base-pack/personas/orchestrator.md +1 -1
  77. package/dist/forge-payload/.base-pack/personas/product-manager.md +1 -1
  78. package/dist/forge-payload/.base-pack/personas/qa-engineer.md +1 -1
  79. package/dist/forge-payload/.base-pack/personas/supervisor.md +1 -1
  80. package/dist/forge-payload/.base-pack/workflows/_fragments/event-emission-schema.md +1 -1
  81. package/dist/forge-payload/.base-pack/workflows/_fragments/friction-emit.md +1 -1
  82. package/dist/forge-payload/.base-pack/workflows/_fragments/iron-laws.md +1 -1
  83. package/dist/forge-payload/.base-pack/workflows/_fragments/progress-reporting.md +2 -2
  84. package/dist/forge-payload/.base-pack/workflows/_fragments/store-cli-verbs.md +11 -2
  85. package/dist/forge-payload/.base-pack/workflows/architect_approve.md +6 -7
  86. package/dist/forge-payload/.base-pack/workflows/architect_review_sprint_completion.md +2 -2
  87. package/dist/forge-payload/.base-pack/workflows/architect_sprint_intake.md +2 -2
  88. package/dist/forge-payload/.base-pack/workflows/architect_sprint_plan.md +5 -5
  89. package/dist/forge-payload/.base-pack/workflows/collator_agent.md +4 -6
  90. package/dist/forge-payload/.base-pack/workflows/commit_task.md +5 -6
  91. package/dist/forge-payload/.base-pack/workflows/enhance.md +5 -5
  92. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +15 -7
  93. package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +12 -13
  94. package/dist/forge-payload/.base-pack/workflows/plan_task.md +12 -6
  95. package/dist/forge-payload/.base-pack/workflows/review_code.md +12 -11
  96. package/dist/forge-payload/.base-pack/workflows/review_plan.md +12 -11
  97. package/dist/forge-payload/.base-pack/workflows/sprint_retrospective.md +3 -3
  98. package/dist/forge-payload/.base-pack/workflows/triage.md +12 -9
  99. package/dist/forge-payload/.base-pack/workflows/update_implementation.md +2 -2
  100. package/dist/forge-payload/.base-pack/workflows/update_plan.md +2 -2
  101. package/dist/forge-payload/.base-pack/workflows/validate_task.md +9 -9
  102. package/dist/forge-payload/.base-pack/workflows-js/wfl-fix-bug.js +490 -0
  103. package/dist/forge-payload/.base-pack/workflows-js/wfl-run-sprint.js +416 -0
  104. package/dist/forge-payload/.base-pack/workflows-js/wfl-run-task.js +608 -0
  105. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  106. package/dist/forge-payload/.schemas/config.schema.json +2 -3
  107. package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
  108. package/dist/forge-payload/.schemas/event.schema.json +16 -0
  109. package/dist/forge-payload/.schemas/migrations.json +359 -18
  110. package/dist/forge-payload/commands/health.md +29 -0
  111. package/dist/forge-payload/commands/rebuild.md +143 -15
  112. package/dist/forge-payload/commands/update.md +28 -27
  113. package/dist/forge-payload/hooks/preflight-session.cjs +99 -0
  114. package/dist/forge-payload/init/phases/phase-3-materialize.md +18 -5
  115. package/dist/forge-payload/integrity.json +7 -6
  116. package/dist/forge-payload/meta/fragments/tool-discipline.md +1 -1
  117. package/dist/forge-payload/meta/personas/meta-architect.md +1 -1
  118. package/dist/forge-payload/meta/personas/meta-bug-fixer.md +1 -1
  119. package/dist/forge-payload/meta/personas/meta-collator.md +7 -7
  120. package/dist/forge-payload/meta/personas/meta-engineer.md +1 -1
  121. package/dist/forge-payload/meta/personas/meta-orchestrator.md +1 -1
  122. package/dist/forge-payload/meta/personas/meta-supervisor.md +1 -1
  123. package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +1 -1
  124. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +1 -1
  125. package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +1 -1
  126. package/dist/forge-payload/meta/workflows/_fragments/iron-laws.md +1 -1
  127. package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +2 -2
  128. package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +11 -2
  129. package/dist/forge-payload/meta/workflows/meta-approve.md +6 -7
  130. package/dist/forge-payload/meta/workflows/meta-bug-triage.md +12 -9
  131. package/dist/forge-payload/meta/workflows/meta-collate.md +5 -7
  132. package/dist/forge-payload/meta/workflows/meta-commit.md +5 -6
  133. package/dist/forge-payload/meta/workflows/meta-enhance.md +5 -5
  134. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +35 -11
  135. package/dist/forge-payload/meta/workflows/meta-implement.md +15 -7
  136. package/dist/forge-payload/meta/workflows/meta-migrate.md +13 -14
  137. package/dist/forge-payload/meta/workflows/meta-new-sprint.md +3 -3
  138. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +138 -39
  139. package/dist/forge-payload/meta/workflows/meta-plan-sprint.md +6 -6
  140. package/dist/forge-payload/meta/workflows/meta-plan-task.md +12 -6
  141. package/dist/forge-payload/meta/workflows/meta-retro.md +4 -4
  142. package/dist/forge-payload/meta/workflows/meta-retrospective.md +4 -4
  143. package/dist/forge-payload/meta/workflows/meta-review-implementation.md +12 -11
  144. package/dist/forge-payload/meta/workflows/meta-review-plan.md +12 -11
  145. package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +3 -3
  146. package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +3 -3
  147. package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +6 -6
  148. package/dist/forge-payload/meta/workflows/meta-update-implementation.md +2 -2
  149. package/dist/forge-payload/meta/workflows/meta-update-plan.md +2 -2
  150. package/dist/forge-payload/meta/workflows/meta-validate.md +9 -9
  151. package/dist/forge-payload/schemas/config.schema.json +2 -3
  152. package/dist/forge-payload/schemas/enum-catalog.json +2 -2
  153. package/dist/forge-payload/schemas/event.schema.json +16 -0
  154. package/dist/forge-payload/schemas/structure-manifest.json +75 -73
  155. package/dist/forge-payload/skills/refresh-kb-links/SKILL.md +14 -7
  156. package/dist/forge-payload/tools/banners.cjs +29 -10
  157. package/dist/forge-payload/tools/check-structure.cjs +88 -7
  158. package/dist/forge-payload/tools/collate.cjs +48 -2
  159. package/dist/forge-payload/tools/manage-config.cjs +5 -7
  160. package/dist/forge-payload/tools/parse-gates.cjs +73 -1
  161. package/dist/forge-payload/tools/postflight-gate.cjs +298 -0
  162. package/dist/forge-payload/tools/preflight-gate.cjs +47 -0
  163. package/dist/forge-payload/tools/substitute-placeholders.cjs +5 -4
  164. package/dist/forge-payload/tools/verify-phase.cjs +17 -0
  165. package/package.json +2 -2
  166. package/dist/bin/forgecli.d.ts +0 -2
  167. package/dist/bin/forgecli.js +0 -6
  168. package/dist/bin/forgecli.js.map +0 -1
  169. package/dist/extensions/forgecli/config-tui/index.d.ts +0 -5
  170. package/dist/extensions/forgecli/config-tui/index.js +0 -5
  171. package/dist/extensions/forgecli/config-tui/index.js.map +0 -1
  172. package/dist/extensions/forgecli/loaders/persona-skill-loader.d.ts +0 -45
  173. package/dist/extensions/forgecli/loaders/persona-skill-loader.js +0 -227
  174. package/dist/extensions/forgecli/loaders/persona-skill-loader.js.map +0 -1
  175. package/dist/extensions/forgecli/loaders/template-render.d.ts +0 -20
  176. package/dist/extensions/forgecli/loaders/template-render.js +0 -85
  177. package/dist/extensions/forgecli/loaders/template-render.js.map +0 -1
  178. package/dist/extensions/forgecli/loaders/workflow-loader.d.ts +0 -41
  179. package/dist/extensions/forgecli/loaders/workflow-loader.js +0 -164
  180. package/dist/extensions/forgecli/loaders/workflow-loader.js.map +0 -1
  181. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +0 -446
  182. package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +0 -928
  183. package/dist/forge-payload/.base-pack/workflows/run_sprint.md +0 -225
@@ -21,6 +21,38 @@ deps:
21
21
  Wire the atomic workflows into a pipeline that drives a single task through
22
22
  the complete lifecycle. This is the task state machine.
23
23
 
24
+ ## Session Preflight (run once, before the phase loop)
25
+
26
+ The deterministic pre-dispatch glue — FORGE_ROOT resolution, config
27
+ reconciliation, generation-manifest state, calibration-baseline freshness,
28
+ MASTER_INDEX hashing, and the structure check — is bundled into a single
29
+ deterministic tool, `forge/tools/forge-preflight.cjs`. **Do NOT hand-run these
30
+ checks turn-by-turn.** Read the one compact blob it produces, once, at the top
31
+ of the orchestration:
32
+
33
+ 1. The SessionStart hook (`hooks/preflight-session.cjs`) primes the blob at
34
+ `.forge/cache/preflight-status.json` for any project that has a `.forge/`
35
+ directory. Read that file. If it is absent or stale, run the tool once:
36
+ `node .forge/tools/forge-preflight.cjs` and read its stdout.
37
+ 2. Branch on `blob.ok`:
38
+ - **`ok: true`** → proceed to the phase loop using `blob.forgeRoot` and the
39
+ recorded state. Do not re-derive any field the blob already carries
40
+ (`masterIndexHash`, `calibrationFresh`, `manifestState`, `structureOk`);
41
+ surface `calibrationFresh.suggest` to the operator if `fresh` is false, but
42
+ this is advisory and does not block the run.
43
+ - **`ok: false`** → **halt before phase 1** (fast-fail-safe). This is a
44
+ pre-dispatch halt: print `blob.warnings`, route through the existing
45
+ escalation idiom (see `§ Escalation Procedure`) — emit the standard
46
+ escalation event and message — and instruct the operator to fix the
47
+ surfaced preflight warning and re-run. A half-initialized run must never
48
+ proceed.
49
+
50
+ The blob is the single source of truth for these concerns for the remainder of
51
+ the run. The SessionStart hook is command-name-independent (SessionStart fires
52
+ before any command and carries no per-command signal); the scoping to
53
+ run-task / fix-bug / run-sprint contexts lives here, in the orchestration
54
+ preamble, which only those commands reach.
55
+
24
56
  ## Pipeline Phases
25
57
 
26
58
  Each phase has:
@@ -116,7 +148,7 @@ Each phase subagent is responsible for reporting its own token usage via a sidec
116
148
  Do NOT shell out to a `cost-cli.cjs` — there is no such tool.
117
149
  2. Parse the output for the five fields:
118
150
  `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `estimatedCostUSD`.
119
- 3. Write the usage sidecar via `node "$FORGE_ROOT/tools/store-cli.cjs" emit {sprintId} '{sidecar-json}' --sidecar` with the exact format:
151
+ 3. Write the usage sidecar via `node .forge/tools/store-cli.cjs emit {sprintId} '{sidecar-json}' --sidecar` with the exact format:
120
152
  ```json
121
153
  {
122
154
  "inputTokens": <integer>,
@@ -234,11 +266,26 @@ def compose_role_block(persona_noun):
234
266
  **Rollback:** set `FORGE_PROMPT_MODE=inline`. No persisted state to revert.
235
267
  The `inline` branch will be removed one version after `reference` ships.
236
268
 
269
+ > **Scope note (added FORGE-S27-T02, 2026-05-31):** `FORGE_PROMPT_MODE=inline` restores
270
+ > the **role block only** — full verbatim persona + skill file contents. It does NOT restore
271
+ > the full `MASTER_INDEX`: the overlay (`build-overlay.cjs`, line 462) is unconditional and
272
+ > delivers the same task-scoped slice in both modes. It also does NOT affect the workflow file,
273
+ > which is read verbatim from disk in both modes. There is currently no per-call escape hatch
274
+ > to the full `MASTER_INDEX` — a separate overlay-bypass flag would be required.
275
+
237
276
  ## Execution Algorithm
238
277
 
239
278
  The orchestrator MUST follow this procedure exactly. Do not deviate.
240
279
 
241
280
  ```
281
+ # --- Utility helpers ---
282
+ def safe_parse_json(text):
283
+ """Attempt to parse a JSON string; return dict or None on failure."""
284
+ try:
285
+ return json.loads(text.strip()) if text and text.strip() else None
286
+ except Exception:
287
+ return None
288
+
242
289
  # --- Persona symbol lookup (emoji, name, tagline) ---
243
290
  PERSONA_MAP = {
244
291
  "plan": ("🌱", "Engineer", "I plan what will be built before any code is written."),
@@ -314,7 +361,7 @@ for each task in dependency_sorted(tasks):
314
361
 
315
362
  # --- Clear progress log for this sprint ---
316
363
  progress_log_path = f".forge/store/events/{sprint_id}/progress.log"
317
- run_bash(f'FORGE_ROOT=$(node -e "console.log(require(\'./.forge/config.json\').paths.forgeRoot)") && node "$FORGE_ROOT/tools/store-cli.cjs" progress-clear {sprint_id}')
364
+ run_bash(f'node .forge/tools/store-cli.cjs progress-clear {sprint_id}')
318
365
 
319
366
  while i < len(phases):
320
367
  phase = phases[i]
@@ -359,9 +406,27 @@ for each task in dependency_sorted(tasks):
359
406
  agent_name = f"{task_id}:{persona_noun}:{phase.role}:{iteration}"
360
407
 
361
408
  # --- Announce phase with identity banner (badge) + task context ---
409
+ # --quiet makes banners.cjs emit zero stdout (unconditional; no isTTY branch).
410
+ # The badge is fully suppressed during the automated run_bash call — it does
411
+ # not enter the LLM context window and is not shown on the human terminal.
412
+ # The human-visible per-phase marker is the print() line below.
413
+ #
414
+ # Digest-compliance note (FORGE-S27-T03): every deterministic tool call this
415
+ # loop body makes is already digest-compliant on its success path:
416
+ # store-cli write verbs (update-status, emit, merge-sidecar, set-summary,
417
+ # progress-clear) → silent on success.
418
+ # preflight-gate.cjs → silent on success (stderr only on failure).
419
+ # read-verdict.cjs → one load-bearing token (e.g. "approved"); orchestrator
420
+ # branches on it — must not be suppressed.
421
+ # banners.cjs --badge → 1-line ANSI badge; made zero-cost via --quiet below.
422
+ # build-overlay.cjs → ~1185 chars captured into overlay_md and injected into
423
+ # the subagent prompt as Project Context. This is payload
424
+ # data, not a log — reducing it would break prompt assembly.
425
+ # Reference-mode redesign is deferred to the T02/forge-compress
426
+ # work; leave unchanged here.
362
427
  emoji, persona_name, tagline = PERSONA_MAP.get(phase.role, ("🌊", "Orchestrator", "I move tasks through their lifecycle."))
363
428
  banner_name = BANNER_MAP.get(phase.role, "forge")
364
- run_bash(f'FORGE_ROOT=$(node -e "console.log(require(\'./.forge/config.json\').paths.forgeRoot)") && node "$FORGE_ROOT/tools/banners.cjs" --badge {banner_name}')
429
+ run_bash(f'node .forge/tools/banners.cjs --badge {banner_name} --quiet')
365
430
  print(f" → {task_id} [{display_model}]\n")
366
431
 
367
432
  # --- Start progress Monitor before spawning subagent ---
@@ -374,23 +439,35 @@ for each task in dependency_sorted(tasks):
374
439
  )
375
440
 
376
441
  # --- Pre-flight gate check (see Phase Gates below) ---
377
- # Resolve FORGE_ROOT once so the CLI shim can locate the gate parser.
442
+ # Resolve FORGE_ROOT once (needed for meta/workflows fragment reads below).
378
443
  FORGE_ROOT = resolve_forge_root()
379
444
  preflight_result = run_bash(
380
- f'node "$FORGE_ROOT/tools/preflight-gate.cjs" --phase {phase.role} --task {task_id}'
445
+ f'node .forge/tools/preflight-gate.cjs --phase {phase.role} --task {task_id}'
381
446
  )
382
447
  if preflight_result.exit_code == 1:
383
448
  # Gate failed: halt the orchestrator loop for THIS task. Do not retry,
384
- # do not spawn. Missing prerequisites are listed on stderr.
385
- print(f" ✗ {task_id} {phase.role} — gate failed\n{preflight_result.stderr}")
386
- append_progress(progress_log_path, f"❌ Gate failed for {phase.role}: {preflight_result.stderr}")
387
- emit_event(task, phase, action="gate_failed", notes=preflight_result.stderr)
449
+ # do not spawn. Structured failure JSON is on stdout; human-readable detail on stderr.
450
+ # Parse the structured JSON for a user-friendly advisory.
451
+ gate_failure = safe_parse_json(preflight_result.stdout)
452
+ if gate_failure:
453
+ reason_code = gate_failure.get("reasonCode", "unknown")
454
+ gate_detail = gate_failure.get("detail", preflight_result.stderr.strip())
455
+ gate_remedy = gate_failure.get("remediation", "")
456
+ print(f" ✗ {task_id} {phase.role} — gate failed [{reason_code}]")
457
+ print(f" Detail: {gate_detail}")
458
+ print(f" Remediation: {gate_remedy}")
459
+ gate_notes = f"gate_failed [{reason_code}]: {gate_detail}"
460
+ else:
461
+ print(f" ✗ {task_id} {phase.role} — gate failed\n{preflight_result.stderr}")
462
+ gate_notes = f"gate_failed: {preflight_result.stderr}"
463
+ append_progress(progress_log_path, f"❌ Gate failed for {phase.role}: {gate_notes}")
464
+ emit_event(task, phase, action="gate_failed", notes=gate_notes)
388
465
  # ---- ESCALATION (mandatory hard stop — do NOT continue) ----
389
- run_bash(f'node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {task_id} status escalated')
466
+ run_bash(f'node .forge/tools/store-cli.cjs update-status task {task_id} status escalated')
390
467
  emit_event(task, phase, eventId=event_id, iteration=iteration,
391
468
  action="escalated", verdict="escalated",
392
- notes=f"gate_failed: {preflight_result.stderr}")
393
- print(f" ⚠ Task {task_id} escalated: gate_failed: {preflight_result.stderr}\n")
469
+ notes=gate_notes)
470
+ print(f" ⚠ Task {task_id} escalated: {gate_notes}\n")
394
471
  print(f" Review artifact: {artifact_path}\n")
395
472
  print(f" Resume with: /{phase.command} {task_id} after addressing the issues.\n")
396
473
  break # stop processing this task
@@ -398,7 +475,7 @@ for each task in dependency_sorted(tasks):
398
475
  # Misconfiguration (unknown phase, malformed gates block). Fail loud.
399
476
  print(f" ⚠ {task_id} {phase.role} — gate misconfigured\n{preflight_result.stderr}")
400
477
  # ---- ESCALATION (mandatory hard stop — do NOT continue) ----
401
- run_bash(f'node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {task_id} status escalated')
478
+ run_bash(f'node .forge/tools/store-cli.cjs update-status task {task_id} status escalated')
402
479
  emit_event(task, phase, eventId=event_id, iteration=iteration,
403
480
  action="escalated", verdict="escalated",
404
481
  notes=f"gate_misconfigured: {preflight_result.stderr}")
@@ -428,7 +505,7 @@ for each task in dependency_sorted(tasks):
428
505
 
429
506
  # --- Materialize project overlay (replaces MASTER_INDEX.md read in subagent) ---
430
507
  overlay_result = run_bash(
431
- f'node "$FORGE_ROOT/tools/build-overlay.cjs" --task {task_id} --format md'
508
+ f'node .forge/tools/build-overlay.cjs --task {task_id} --format md'
432
509
  )
433
510
  overlay_md = overlay_result.stdout if overlay_result.exit_code == 0 else ""
434
511
 
@@ -526,7 +603,7 @@ for each task in dependency_sorted(tasks):
526
603
  emit_event(task, phase, action="subagent_escalated",
527
604
  notes=f"second failure: {subagent_failure_reason(result)}")
528
605
  # ---- ESCALATION (mandatory hard stop — do NOT continue) ----
529
- run_bash(f'node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {task_id} status escalated')
606
+ run_bash(f'node .forge/tools/store-cli.cjs update-status task {task_id} status escalated')
530
607
  emit_event(task, phase, eventId=event_id, iteration=iteration,
531
608
  action="escalated", verdict="escalated",
532
609
  notes=f"subagent failed after retry: {subagent_failure_reason(result)}")
@@ -539,7 +616,7 @@ for each task in dependency_sorted(tasks):
539
616
  emit_event(task, phase, action="subagent_escalated",
540
617
  notes=f"second failure: {subagent_failure_reason(result)}")
541
618
  # ---- ESCALATION (mandatory hard stop — do NOT continue) ----
542
- run_bash(f'node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {task_id} status escalated')
619
+ run_bash(f'node .forge/tools/store-cli.cjs update-status task {task_id} status escalated')
543
620
  emit_event(task, phase, eventId=event_id, iteration=iteration,
544
621
  action="escalated", verdict="escalated",
545
622
  notes=f"subagent failed after retry: {subagent_failure_reason(result)}")
@@ -548,10 +625,9 @@ for each task in dependency_sorted(tasks):
548
625
  break
549
626
 
550
627
  # --- Sidecar merge: merge token usage written by subagent via custodian ---
551
- # The subagent wrote the sidecar via node "$FORGE_ROOT/tools/store-cli.cjs" emit {sprintId} '{sidecar-json}' --sidecar
628
+ # The subagent wrote the sidecar via node .forge/tools/store-cli.cjs emit {sprintId} '{sidecar-json}' --sidecar
552
629
  # Merge the sidecar into the canonical event and delete the sidecar file
553
- FORGE_ROOT = resolve_forge_root()
554
- run: node "$FORGE_ROOT/tools/store-cli.cjs" merge-sidecar {sprint_id} {event_id}
630
+ run: node .forge/tools/store-cli.cjs merge-sidecar {sprint_id} {event_id}
555
631
  # merge-sidecar reads the sidecar, merges token fields into the canonical event, and deletes the sidecar
556
632
  # If the sidecar does not exist, merge-sidecar exits 1 — treat as non-fatal (subagent may have skipped it)
557
633
  emit_event(task, phase, action="complete")
@@ -561,7 +637,10 @@ for each task in dependency_sorted(tasks):
561
637
  if phase.role not in ("review-plan", "review-code", "validate"):
562
638
  print(f" ✓ {task_id} {phase.role} — completed\n")
563
639
  i += 1
564
- # Compact context: all state is on disk; preserve loop bookkeeping in the summary
640
+ # State-ledger compaction: the [checkpoint] line IS the state ledger it carries
641
+ # the loop bookkeeping (task_id, sprint_id, phase_index, iteration_counts) that
642
+ # /compact must preserve verbatim. Raw tool output and subagent return text is
643
+ # shed here; do not retain it between phases. The durable state is on disk.
565
644
  print(f"[checkpoint] task={task_id} sprint={sprint_id} phase_index={i} iterations={iteration_counts}")
566
645
  /compact
567
646
  continue
@@ -572,7 +651,7 @@ for each task in dependency_sorted(tasks):
572
651
  # stdout is one of: approved | revision | n/a | unknown. Never pattern-match a
573
652
  # **Verdict:** line — the closed vocabulary lives in the tool.
574
653
  verdict_result = run_bash(
575
- f'node "$FORGE_ROOT/tools/read-verdict.cjs" --phase {phase.role} --task {task_id}'
654
+ f'node .forge/tools/read-verdict.cjs --phase {phase.role} --task {task_id}'
576
655
  )
577
656
  verdict_token = verdict_result.stdout.strip()
578
657
  if verdict_token == "approved":
@@ -586,19 +665,22 @@ for each task in dependency_sorted(tasks):
586
665
  emit_event(task, phase, action="verdict_malformed",
587
666
  notes=f"read-verdict stdout='{verdict_token}' exit={verdict_result.exit_code}")
588
667
  # ---- ESCALATION (mandatory hard stop — do NOT continue) ----
589
- run_bash(f'node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {task_id} status escalated')
668
+ run_bash(f'node .forge/tools/store-cli.cjs update-status task {task_id} status escalated')
590
669
  emit_event(task, phase, eventId=event_id, iteration=iteration,
591
670
  action="escalated", verdict="escalated",
592
671
  notes="verdict_malformed: no verdict recorded in the phase summary / record")
593
672
  print(f" ⚠ Task {task_id} escalated: verdict_malformed — no verdict recorded for {phase.role}\n")
594
- print(f" Inspect with: node \"$FORGE_ROOT/tools/read-verdict.cjs\" --phase {phase.role} --task {task_id}\n")
673
+ print(f" Inspect with: node \.forge/tools/read-verdict.cjs\" --phase {phase.role} --task {task_id}\n")
595
674
  print(f" Resume with: /{phase.command} {task_id} after addressing the issues.\n")
596
675
  break
597
676
 
598
677
  if verdict == "Approved":
599
678
  print(f" ✓ {task_id} {phase.role} — Approved\n")
600
679
  i += 1 # advance to next phase
601
- # Compact context: all state is on disk; preserve loop bookkeeping in the summary
680
+ # State-ledger compaction: the [checkpoint] line IS the state ledger it carries
681
+ # the loop bookkeeping (task_id, sprint_id, phase_index, iteration_counts) that
682
+ # /compact must preserve verbatim. Raw tool output and subagent return text is
683
+ # shed here; do not retain it between phases. The durable state is on disk.
602
684
  print(f"[checkpoint] task={task_id} sprint={sprint_id} phase_index={i} iterations={iteration_counts}")
603
685
  /compact
604
686
 
@@ -608,12 +690,12 @@ for each task in dependency_sorted(tasks):
608
690
 
609
691
  if iteration_counts[phase.command] >= phase.maxIterations: # default 3
610
692
  # ---- ESCALATION (mandatory hard stop — do NOT continue) ----
611
- run_bash(f'node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {task_id} status escalated')
693
+ run_bash(f'node .forge/tools/store-cli.cjs update-status task {task_id} status escalated')
612
694
  emit_event(task, phase, eventId=event_id, iteration=iteration,
613
695
  action="escalated", verdict="escalated",
614
696
  notes="max iterations reached")
615
697
  print(f" ⚠ Task {task_id} escalated: max iterations reached\n")
616
- print(f" Inspect with: node \"$FORGE_ROOT/tools/read-verdict.cjs\" --phase {phase.role} --task {task_id}\n")
698
+ print(f" Inspect with: node \.forge/tools/read-verdict.cjs\" --phase {phase.role} --task {task_id}\n")
617
699
  print(f" Resume with: /{phase.command} {task_id} after addressing the issues.\n")
618
700
  break
619
701
  break # stop processing this task
@@ -621,7 +703,10 @@ for each task in dependency_sorted(tasks):
621
703
  # Route back to the revision target
622
704
  target = phase.on_revision or nearest_preceding_non_review(phases, i)
623
705
  i = index_of(phases, target) # loop back
624
- # Compact context: all state is on disk; preserve loop bookkeeping in the summary
706
+ # State-ledger compaction: the [checkpoint] line IS the state ledger it carries
707
+ # the loop bookkeeping (task_id, sprint_id, phase_index, iteration_counts) that
708
+ # /compact must preserve verbatim. Raw tool output and subagent return text is
709
+ # shed here; do not retain it between phases. The durable state is on disk.
625
710
  print(f"[checkpoint] task={task_id} sprint={sprint_id} phase_index={i} iterations={iteration_counts}")
626
711
  /compact
627
712
 
@@ -696,8 +781,7 @@ enforces a closed vocabulary so typos, case drift, and reviewer prose cannot
696
781
  cause silent misclassification:
697
782
 
698
783
  ```
699
- FORGE_ROOT = resolve_forge_root()
700
- result = run_bash(f'node "$FORGE_ROOT/tools/read-verdict.cjs" --phase {phase.role} --task {task_id}')
784
+ result = run_bash(f'node .forge/tools/read-verdict.cjs --phase {phase.role} --task {task_id}')
701
785
  # stdout "approved" → approved
702
786
  # stdout "revision" → revision
703
787
  # stdout "n/a" | "unknown" → no verdict recorded (treat as malformed; do NOT guess)
@@ -724,7 +808,7 @@ applies the bug-specific phase→summary map.)
724
808
 
725
809
  When escalating to the human:
726
810
 
727
- 1. Update task status via `node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {taskId} status escalated`
811
+ 1. Update task status via `node .forge/tools/store-cli.cjs update-status task {taskId} status escalated`
728
812
  2. Emit a final event with `verdict: "escalated"` and `notes` explaining the reason
729
813
  3. Output a clear message:
730
814
  ```
@@ -880,7 +964,7 @@ subagent returns, the orchestrator:
880
964
  4. Composes the canonical event with `eventId`, `taskId`, `sprintId`, `role`,
881
965
  `action`, `phase`, `iteration` from its own task state and `tokenSource:
882
966
  "reported"` when the runtime surfaced usage.
883
- 5. Calls `node "$FORGE_ROOT/tools/store-cli.cjs" emit {sprintId} '{event-json}'`
967
+ 5. Calls `node .forge/tools/store-cli.cjs emit {sprintId} '{event-json}'`
884
968
  with the complete record.
885
969
 
886
970
  Do not include hardcoded example `model` or `provider` strings in the
@@ -904,7 +988,7 @@ Refer subagents to `.forge/schemas/event.schema.json` instead.
904
988
  Do NOT generate a "Model Assignments" table — the Model Resolution section
905
989
  above is the single source of truth.
906
990
  - **Include the sidecar merge pattern.** After each subagent returns, run
907
- `node "$FORGE_ROOT/tools/store-cli.cjs" merge-sidecar {sprintId} {eventId}` to merge token fields from the
991
+ `node .forge/tools/store-cli.cjs merge-sidecar {sprintId} {eventId}` to merge token fields from the
908
992
  sidecar into the canonical event and delete the sidecar. If the sidecar does not
909
993
  exist (merge-sidecar exits 1), treat as non-fatal and emit the event without token
910
994
  fields (graceful fallback — no error).
@@ -932,7 +1016,7 @@ Refer subagents to `.forge/schemas/event.schema.json` instead.
932
1016
  subagents do not display banners. Instead, include progress reporting instructions
933
1017
  in the subagent prompt with the agent name, progress log path, and banner key.
934
1018
  - **Include the progress IPC pattern.** Each generated orchestrator MUST:
935
- 1. Clear the progress log at task start: `node "$FORGE_ROOT/tools/store-cli.cjs" progress-clear {sprintId}`
1019
+ 1. Clear the progress log at task start: `node .forge/tools/store-cli.cjs progress-clear {sprintId}`
936
1020
  2. Compute the agent name before each spawn: `{taskId}:{persona_noun}:{phase.role}:{iteration}`
937
1021
  3. Start a Monitor on the progress log before each subagent spawn
938
1022
  4. Include progress reporting instructions in the subagent prompt (agent name,
@@ -952,13 +1036,28 @@ Refer subagents to `.forge/schemas/event.schema.json` instead.
952
1036
  `Read engineering/architecture/stack.md` calls with a single cached summary.
953
1037
  Subagents instructed by this block should read full docs **only** when the
954
1038
  summary is insufficient.
955
- - **Include post-phase /compact calls.** After each phase-exit signal (for every
956
- non-escalation outcome), the generated orchestrator MUST:
1039
+ - **Include post-phase /compact calls with state-ledger discipline.** After each
1040
+ phase-exit signal (for every non-escalation outcome), the generated orchestrator
1041
+ MUST:
957
1042
  1. Print a checkpoint line: `[checkpoint] task={task_id} sprint={sprint_id} phase_index={i} iterations={iteration_counts}`
958
1043
  2. Run `/compact` to free orchestrator context before the next phase.
959
- All durable state is on disk; the checkpoint line ensures the compact summary
960
- preserves the loop bookkeeping (task ID, sprint ID, current phase index,
961
- iteration counts). Do NOT compact on escalation the human needs full context.
1044
+
1045
+ The `[checkpoint]` line IS the state ledger. It carries the loop bookkeeping
1046
+ (task ID, sprint ID, current phase index, iteration counts) that `/compact` must
1047
+ preserve verbatim in its summary. It is not an optional debug breadcrumb — it is
1048
+ the one line the orchestrator must carry forward through each compaction boundary.
1049
+
1050
+ Raw tool output (bash stdout, subagent return blobs, multi-KB phase responses)
1051
+ is shed at every `/compact` call. The generated orchestrator MUST NOT retain
1052
+ verbatim tool output or subagent return text between phases — only the
1053
+ checkpoint ledger line and on-disk artifact pointers survive compaction.
1054
+
1055
+ The compact summary MUST contain: the checkpoint line verbatim, the task/sprint
1056
+ IDs, and the current phase index. The compact summary MUST NOT contain: raw
1057
+ subagent return text, bash stdout blobs, or multi-line phase responses.
1058
+
1059
+ Do NOT compact on escalation (verdict_malformed or max-iterations break paths) —
1060
+ the human needs the full uncompacted context to diagnose and resume.
962
1061
 
963
1062
  ## Friction Emit
964
1063
 
@@ -978,7 +1077,7 @@ When the Orchestrator detects skill friction during orchestrate-task — a refer
978
1077
 
979
1078
  1. **Subagent-experienced friction** (the persona running plan / implement /
980
1079
  validate / etc. detects skill friction). The subagent records the signal
981
- via `node "$FORGE_ROOT/tools/friction-emit.cjs" --workflow {wf} --persona {p}
1080
+ via `node .forge/tools/friction-emit.cjs --workflow {wf} --persona {p}
982
1081
  --issue {token} [--subkind {token}] [--evidence '{...}']`, which appends a
983
1082
  judgement-only record to `.forge/cache/FRICTION-{wf}.jsonl`. After the
984
1083
  subagent returns, the orchestrator drains this file, stamps the
@@ -31,8 +31,8 @@ Break sprint requirements into a set of estimated tasks with a dependency graph.
31
31
  1. Load Context:
32
32
  - Query the store to orient on current project state before reading docs:
33
33
  ```sh
34
- node "$FORGE_ROOT/tools/store-cli.cjs" nlp "latest sprint"
35
- node "$FORGE_ROOT/tools/store-cli.cjs" nlp "open bugs"
34
+ node .forge/tools/store-cli.cjs nlp "latest sprint"
35
+ node .forge/tools/store-cli.cjs nlp "open bugs"
36
36
  ```
37
37
  Use results (titles, statuses, excerpts, file refs) to skip manual MASTER_INDEX.md navigation where sufficient.
38
38
  - Read SPRINT_REQUIREMENTS.md
@@ -52,11 +52,11 @@ Break sprint requirements into a set of estimated tasks with a dependency graph.
52
52
 
53
53
  4. Documentation:
54
54
  - Write SPRINT_PLAN.md to `engineering/sprints/{sprintId}/SPRINT_PLAN.md`
55
- - Create each task via `node "$FORGE_ROOT/tools/store-cli.cjs" write task '{task-json}'`.
55
+ - Create each task via `node .forge/tools/store-cli.cjs write task '{task-json}'`.
56
56
  If the command exits non-zero or the PreToolUse hook blocks the write:
57
57
  parse the error, correct the JSON, and retry (see Store-Write Verification).
58
58
  Do not proceed to the next task until this write succeeds.
59
- - Update the sprint record with all new task IDs via `node "$FORGE_ROOT/tools/store-cli.cjs" write sprint '{updated-sprint-json}'` (the sprint JSON must include the complete `taskIds` array with all newly created task IDs).
59
+ - Update the sprint record with all new task IDs via `node .forge/tools/store-cli.cjs write sprint '{updated-sprint-json}'` (the sprint JSON must include the complete `taskIds` array with all newly created task IDs).
60
60
  If the command exits non-zero or the PreToolUse hook blocks the write:
61
61
  parse the error, correct the JSON, and retry (see Store-Write Verification).
62
62
  Do not proceed until this write succeeds.
@@ -64,7 +64,7 @@ Break sprint requirements into a set of estimated tasks with a dependency graph.
64
64
  * Folder: `engineering/sprints/{sprintId}/{taskId}/`
65
65
  * File: `TASK_PROMPT.md` — populate from `.forge/templates/TASK_PROMPT_TEMPLATE.md`
66
66
  filling in title, objective, acceptance criteria, entities, DSL/CLI changes, and operational impact
67
- - Update sprint status via `node "$FORGE_ROOT/tools/store-cli.cjs" update-status sprint {sprintId} status active`.
67
+ - Update sprint status via `node .forge/tools/store-cli.cjs update-status sprint {sprintId} status active`.
68
68
  If the command exits non-zero, parse the error and retry
69
69
  (see Store-Write Verification). Do not proceed until this write succeeds.
70
70
 
@@ -141,7 +141,7 @@ environment variable is reserved for emergency operator repair only.
141
141
  - Set token fields to `null`: `"inputTokens": null, "outputTokens": null, "estimatedCostUSD": null`.
142
142
  - Add `"source": "missing"` to sidecar JSON.
143
143
  - Log: "Token data unavailable (cost probe failed). Backfill later via estimate-usage.cjs."
144
- 4. Write the usage sidecar via `node "$FORGE_ROOT/tools/store-cli.cjs" emit {sprintId} '{sidecar-json}' --sidecar`.
144
+ 4. Write the usage sidecar via `node .forge/tools/store-cli.cjs emit {sprintId} '{sidecar-json}' --sidecar`.
145
145
  5. **NEVER skip sidecar write.** Always emit (reported or placeholder with nulls).
146
146
  - **Event Emission:** Ensure the "complete" event includes the `eventId` passed by the orchestrator.
147
147
  - **Store-Write Verification:** The generated workflow MUST include the "Store-Write
@@ -31,9 +31,8 @@ The Engineer reads the task prompt, researches the codebase, and produces an imp
31
31
  ```
32
32
 
33
33
  0a. Pre-flight Gate Check:
34
- - Resolve FORGE_ROOT (`node -e "console.log(require('./.forge/config.json').paths.forgeRoot)"`).
35
34
  - **Entity-mode resolution:** read the kickoff arguments. `--task {id}` → `entity_kind = "task"`, `record_id = {id}`. `--bug {id}` → `entity_kind = "bug"`, `record_id = {id}`. All store-cli calls below substitute `{entity_kind}` and `{record_id}` for the literal "task"/{taskId} placeholders.
36
- - Run: `node "$FORGE_ROOT/tools/preflight-gate.cjs" --phase plan --{entity_kind} {record_id}`
35
+ - Run: `node .forge/tools/preflight-gate.cjs --phase plan --{entity_kind} {record_id}`
37
36
  - Exit 1 (gate failed) → print stderr and HALT. Do not proceed; do not attempt to produce the artifact.
38
37
  - Exit 2 (misconfiguration) → print stderr and HALT.
39
38
  - Exit 0 → continue.
@@ -42,7 +41,7 @@ The Engineer reads the task prompt, researches the codebase, and produces an imp
42
41
  - If `--force` is present in the invocation arguments, skip this step entirely.
43
42
  - If `entity_kind == "bug"`, skip this step entirely (bug state is managed by meta-fix-bug.md).
44
43
  - Read current task state:
45
- `node "$FORGE_ROOT/tools/store-cli.cjs" read task {record_id} --json`
44
+ `node .forge/tools/store-cli.cjs read task {record_id} --json`
46
45
  - Extract the `status` field from the JSON output.
47
46
  - Allowed states for this phase: `draft`, `planned`, `plan-revision-required`.
48
47
  - If the current status is NOT in the allowed set:
@@ -55,7 +54,7 @@ The Engineer reads the task prompt, researches the codebase, and produces an imp
55
54
  - Read task prompt (source of truth)
56
55
  - Query the store for this task and any related entities:
57
56
  ```sh
58
- node "$FORGE_ROOT/tools/store-cli.cjs" nlp "{taskId} with sprint with feature"
57
+ node .forge/tools/store-cli.cjs nlp "{taskId} with sprint with feature"
59
58
  ```
60
59
  Use store results directly if they include title, status, sprint, and excerpt.
61
60
  - Read the architecture summary from your injected context (if present).
@@ -86,7 +85,7 @@ The Engineer reads the task prompt, researches the codebase, and produces an imp
86
85
  5. Finalize:
87
86
  - Transitions:
88
87
  - **Task mode** — legal target from this step: `draft → planned`. Out-of-band escapes (any state): `plan-revision-required`, `code-revision-required`, `blocked`, `escalated`, `abandoned`.
89
- Update status: `node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {taskId} status planned`
88
+ Update status: `node .forge/tools/store-cli.cjs update-status task {taskId} status planned`
90
89
  - **Bug mode** — NO status write. The bug remains `in-progress` until the commit phase transitions it to `fixed`. Writing `bug.status` here violates `meta-fix-bug.md § Iron Laws #2`.
91
90
  - **Do NOT emit a phase event yourself.** The orchestrator owns event emission — it composes the canonical event from runtime telemetry (model, provider, tokens, wall times) plus the SUMMARY you write in the next step. Subagents that call `store-cli emit` for phase events hallucinate runtime facts (see Plan 11 / Slice 2). Write the SUMMARY and return.
92
91
 
@@ -110,6 +109,13 @@ The Engineer reads the task prompt, researches the codebase, and produces an imp
110
109
  Or (bug mode):
111
110
  `forge_store({ command:"set-bug-summary", args:["{record_id}", "plan"] })`
112
111
  - If the set-summary call exits non-zero, fix the sidecar JSON and retry. Do not proceed without a valid summary.
112
+
113
+ 7. Post-Phase Output Guard: satisfy the `outputs` block before returning.
114
+ ```
115
+
116
+ ```outputs phase=plan
117
+ artifact {engineering}/{sprint}/{task}/PLAN.md min=200
118
+ require summaries.plan.verdict == n/a
113
119
  ```
114
120
 
115
121
  <!-- See _fragments/iron-laws.md for Iron Laws section structure guidance -->
@@ -117,7 +123,7 @@ The Engineer reads the task prompt, researches the codebase, and produces an imp
117
123
 
118
124
  - Follow the Algorithm step by step. No code, pseudocode, or implementation sketches in the plan.
119
125
  - Read `.forge/personas/architect.md` first; print the persona identity line (emoji, name, tagline) to stdout before any other tool use.
120
- - All store I/O via `forge_store` (or `node "$FORGE_ROOT/tools/store-cli.cjs"`). Never edit `.forge/store/*.json` directly.
126
+ - All store I/O via `forge_store` (or `node .forge/tools/store-cli.cjs`). Never edit `.forge/store/*.json` directly.
121
127
 
122
128
  ## Store-Write Verification
123
129
 
@@ -23,7 +23,7 @@ Close a sprint by reviewing learnings, updating the knowledge base, and improvin
23
23
 
24
24
  - Never mutate JSON records during retrospective; the store is the source of truth and retrospective flows downstream from it. Retrospective operations read store data and write markdown views only.
25
25
  - Read `.forge/personas/architect.md` first; print the persona identity line (emoji, name, tagline) to stdout before any other tool use.
26
- - All store I/O via `forge_store` (or `node "$FORGE_ROOT/tools/store-cli.cjs"`). Never edit `.forge/store/*.json` directly.
26
+ - All store I/O via `forge_store` (or `node .forge/tools/store-cli.cjs`). Never edit `.forge/store/*.json` directly.
27
27
 
28
28
  ## Algorithm
29
29
 
@@ -45,8 +45,8 @@ Close a sprint by reviewing learnings, updating the knowledge base, and improvin
45
45
 
46
46
  4. Finalize:
47
47
  - Write SPRINT_RETROSPECTIVE.md
48
- - Update sprint status via `node "$FORGE_ROOT/tools/store-cli.cjs" update-status sprint {sprintId} status retrospective-done`
49
- - Run `node "$FORGE_ROOT/tools/collate.cjs" {sprintId} --purge-events`
48
+ - Update sprint status via `node .forge/tools/store-cli.cjs update-status sprint {sprintId} status retrospective-done`
49
+ - Run `node .forge/tools/collate.cjs {sprintId} --purge-events`
50
50
  This single deterministic step: generates COST_REPORT.md from all
51
51
  accumulated events, then deletes `.forge/store/events/{sprintId}/`.
52
52
  COST_REPORT.md is the durable record; the raw event files are not
@@ -69,5 +69,5 @@ Close a sprint by reviewing learnings, updating the knowledge base, and improvin
69
69
  (Claude Code only); on any other runtime treat as unavailable and proceed.
70
70
  Do NOT shell out to a `cost-cli.cjs` — there is no such tool.
71
71
  2. Parse: `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `estimatedCostUSD`.
72
- 3. Write the usage sidecar via `node "$FORGE_ROOT/tools/store-cli.cjs" emit {sprintId} '{sidecar-json}' --sidecar`.
72
+ 3. Write the usage sidecar via `node .forge/tools/store-cli.cjs emit {sprintId} '{sidecar-json}' --sidecar`.
73
73
  - **Event Emission:** Ensure the "complete" event includes the `eventId` passed by the orchestrator.
@@ -23,7 +23,7 @@ Close a sprint by reviewing learnings, updating the knowledge base, and improvin
23
23
 
24
24
  - Never mutate JSON records during retrospective; the store is the source of truth and retrospective flows downstream from it. Retrospective operations read store data and write markdown views only.
25
25
  - Read `.forge/personas/architect.md` first; print the persona identity line (emoji, name, tagline) to stdout before any other tool use.
26
- - All store I/O via `forge_store` (or `node "$FORGE_ROOT/tools/store-cli.cjs"`). Never edit `.forge/store/*.json` directly.
26
+ - All store I/O via `forge_store` (or `node .forge/tools/store-cli.cjs`). Never edit `.forge/store/*.json` directly.
27
27
 
28
28
  ## Algorithm
29
29
 
@@ -45,8 +45,8 @@ Close a sprint by reviewing learnings, updating the knowledge base, and improvin
45
45
 
46
46
  4. Finalize:
47
47
  - Write SPRINT_RETROSPECTIVE.md
48
- - Update sprint status via `node "$FORGE_ROOT/tools/store-cli.cjs" update-status sprint {sprintId} status retrospective-done`
49
- - Run `node "$FORGE_ROOT/tools/collate.cjs" {sprintId} --purge-events`
48
+ - Update sprint status via `node .forge/tools/store-cli.cjs update-status sprint {sprintId} status retrospective-done`
49
+ - Run `node .forge/tools/collate.cjs {sprintId} --purge-events`
50
50
  This single deterministic step: generates COST_REPORT.md from all
51
51
  accumulated events, then deletes `.forge/store/events/{sprintId}/`.
52
52
  COST_REPORT.md is the durable record; the raw event files are not
@@ -69,5 +69,5 @@ Close a sprint by reviewing learnings, updating the knowledge base, and improvin
69
69
  (Claude Code only); on any other runtime treat as unavailable and proceed.
70
70
  Do NOT shell out to a `cost-cli.cjs` — there is no such tool.
71
71
  2. Parse: `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `estimatedCostUSD`.
72
- 3. Write the usage sidecar via `node "$FORGE_ROOT/tools/store-cli.cjs" emit {sprintId} '{sidecar-json}' --sidecar`.
72
+ 3. Write the usage sidecar via `node .forge/tools/store-cli.cjs emit {sprintId} '{sidecar-json}' --sidecar`.
73
73
  - **Event Emission:** Ensure the "complete" event includes the `eventId` passed by the orchestrator.
@@ -31,7 +31,7 @@ The Supervisor reviews the Engineer's implementation for correctness, quality, a
31
31
 
32
32
  - Evaluate the code against the approved PLAN.md and the original task prompt. Do not accept "it works" as a substitute for "it is correct and maintainable."
33
33
  - Read `.forge/personas/supervisor.md` first; print the persona identity line (emoji, name, tagline) to stdout before any other tool use.
34
- - All store I/O via `forge_store` (or `node "$FORGE_ROOT/tools/store-cli.cjs"`). Never edit `.forge/store/*.json` directly.
34
+ - All store I/O via `forge_store` (or `node .forge/tools/store-cli.cjs`). Never edit `.forge/store/*.json` directly.
35
35
 
36
36
  ## Store-Write Verification
37
37
 
@@ -42,9 +42,8 @@ The Supervisor reviews the Engineer's implementation for correctness, quality, a
42
42
  ```
43
43
 
44
44
  0a. Pre-flight Gate Check:
45
- - Resolve FORGE_ROOT (`node -e "console.log(require('./.forge/config.json').paths.forgeRoot)"`).
46
45
  - **Entity-mode resolution:** read the kickoff arguments. `--task {id}` → `entity_kind = "task"`, `record_id = {id}`. `--bug {id}` → `entity_kind = "bug"`, `record_id = {id}`. All store-cli calls below substitute `{entity_kind}` and `{record_id}` for the literal "task"/{taskId} placeholders.
47
- - Run: `node "$FORGE_ROOT/tools/preflight-gate.cjs" --phase review-code --{entity_kind} {record_id}`
46
+ - Run: `node .forge/tools/preflight-gate.cjs --phase review-code --{entity_kind} {record_id}`
48
47
  - Exit 1 (gate failed) → print stderr and HALT. Do not proceed; do not attempt to produce the artifact.
49
48
  - Exit 2 (misconfiguration) → print stderr and HALT.
50
49
  - Exit 0 → continue.
@@ -53,7 +52,7 @@ The Supervisor reviews the Engineer's implementation for correctness, quality, a
53
52
  - If `--force` is present in the invocation arguments, skip this step entirely.
54
53
  - If `entity_kind == "bug"`, skip this step entirely (bug state is managed by meta-fix-bug.md).
55
54
  - Read current task state:
56
- `node "$FORGE_ROOT/tools/store-cli.cjs" read task {record_id} --json`
55
+ `node .forge/tools/store-cli.cjs read task {record_id} --json`
57
56
  - Extract the `status` field from the JSON output.
58
57
  - Allowed states for this phase: `implemented`, `implementing`.
59
58
  - If the current status is NOT in the allowed set:
@@ -65,9 +64,10 @@ The Supervisor reviews the Engineer's implementation for correctness, quality, a
65
64
  - If present, extract:
66
65
  - `Iteration: N of M` — current attempt number and the configured limit
67
66
  - `Is final iteration: true/false`
68
- - If absent (user-invoked, not orchestrated): treat as iteration 1 of M, where M is
69
- read from `.forge/config.json` `maxReviewIterations` (default 3 if field absent).
70
- - Include `(iteration N of M)` in the opening line of the `CODE_REVIEW.md` artifact.
67
+ - If absent (user-invoked, not orchestrated): treat as `iteration 1`, no limit do
68
+ NOT read any iteration cap from config. The orchestrator owns loop budgets; a human
69
+ standalone re-run is the escape hatch for stuck items (forge-engineering#34).
70
+ - Include `(iteration N of M)` (orchestrated) or `(standalone review)` in the opening line of the `CODE_REVIEW.md` artifact.
71
71
  - If this is the final iteration (`N == M`) and the verdict is `Revision Required`,
72
72
  append a `### Next Steps` section to the artifact showing:
73
73
  ```
@@ -103,7 +103,7 @@ The Supervisor reviews the Engineer's implementation for correctness, quality, a
103
103
 
104
104
  6. Finalize:
105
105
  - Transitions:
106
- - **Task mode** — Update status: `node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {taskId} status review-approved` (if Approved) or `... status code-revision-required` (if Revision Required).
106
+ - **Task mode** — Update status: `node .forge/tools/store-cli.cjs update-status task {taskId} status review-approved` (if Approved) or `... status code-revision-required` (if Revision Required).
107
107
  - **Bug mode** — NO status write. The bug remains `in-progress`. The verdict signal travels through `summaries.code_review.verdict` (read by `read-verdict.cjs § BUG_PHASE_VERDICT_SOURCE`), not `bug.status`. Writing `bug.status` here violates `meta-fix-bug.md § Iron Laws #2`.
108
108
  - **Do NOT emit a phase event yourself.** The orchestrator (or kickoff handler) owns event emission — it composes the canonical event from runtime telemetry (model, provider, tokens, wall times) plus the SUMMARY you write in the next step. Subagents that call `store-cli emit` for phase events hallucinate runtime facts (see Plan 11 / Slice 2). Write the SUMMARY and return.
109
109
 
@@ -121,10 +121,11 @@ The Supervisor reviews the Engineer's implementation for correctness, quality, a
121
121
  }
122
122
  ```
123
123
  - Call (task mode):
124
- `forge_store({ command:"set-summary", entity:"task", id:"{taskId}", phase:"code_review" })`
124
+ `forge_store({ command:"set-summary", args:["{taskId}", "code_review"] })`
125
125
  Or (bug mode):
126
- `forge_store({ command:"set-bug-summary", entity:"bug", id:"{bugId}", phase:"code_review" })`
127
- - If the set-summary call exits non-zero, fix the sidecar JSON and retry. Do not proceed without a valid summary.
126
+ `forge_store({ command:"set-bug-summary", args:["{bugId}", "code_review"] })`
127
+ `args[1]` is the LITERAL phase key `code_review`, never the record id; `forge_store` has no `entity`/`id`/`phase` field (see `_fragments/store-cli-verbs.md`).
128
+ - If set-summary exits non-zero, `args[1]` was wrong — fix it to `code_review` and retry. Do not return without a valid summary; the orchestrator halts as "verdict missing" if `summaries.code_review` is absent.
128
129
  ```
129
130
 
130
131
  <!-- See _fragments/generation-instructions.md for Generation Instructions template -->