@entelligentsia/forgecli 0.6.6 → 0.7.6

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 +88 -0
  2. package/README.md +28 -1
  3. package/dist/bin/forge.js +20 -0
  4. package/dist/bin/forge.js.map +1 -1
  5. package/dist/extensions/forgecli/approve.d.ts +24 -0
  6. package/dist/extensions/forgecli/approve.js +202 -0
  7. package/dist/extensions/forgecli/approve.js.map +1 -0
  8. package/dist/extensions/forgecli/audience-gate.d.ts +4 -0
  9. package/dist/extensions/forgecli/audience-gate.js +8 -5
  10. package/dist/extensions/forgecli/audience-gate.js.map +1 -1
  11. package/dist/extensions/forgecli/collate.d.ts +24 -0
  12. package/dist/extensions/forgecli/collate.js +199 -0
  13. package/dist/extensions/forgecli/collate.js.map +1 -0
  14. package/dist/extensions/forgecli/commit.d.ts +24 -0
  15. package/dist/extensions/forgecli/commit.js +202 -0
  16. package/dist/extensions/forgecli/commit.js.map +1 -0
  17. package/dist/extensions/forgecli/fix-bug.d.ts +75 -0
  18. package/dist/extensions/forgecli/fix-bug.js +1133 -0
  19. package/dist/extensions/forgecli/fix-bug.js.map +1 -0
  20. package/dist/extensions/forgecli/forge-commands.js +7 -0
  21. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  22. package/dist/extensions/forgecli/forge-init.js +16 -8
  23. package/dist/extensions/forgecli/forge-init.js.map +1 -1
  24. package/dist/extensions/forgecli/forge-subagent.d.ts +29 -0
  25. package/dist/extensions/forgecli/forge-subagent.js +14 -1
  26. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  27. package/dist/extensions/forgecli/hook-dispatcher.d.ts +53 -1
  28. package/dist/extensions/forgecli/hook-dispatcher.js +47 -1
  29. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  30. package/dist/extensions/forgecli/hooks/post-init-hook.d.ts +15 -0
  31. package/dist/extensions/forgecli/hooks/post-init-hook.js +127 -0
  32. package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -0
  33. package/dist/extensions/forgecli/hooks/post-sprint-hook.d.ts +37 -0
  34. package/dist/extensions/forgecli/hooks/post-sprint-hook.js +166 -0
  35. package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -0
  36. package/dist/extensions/forgecli/index.js +47 -0
  37. package/dist/extensions/forgecli/index.js.map +1 -1
  38. package/dist/extensions/forgecli/review-code.d.ts +24 -0
  39. package/dist/extensions/forgecli/review-code.js +202 -0
  40. package/dist/extensions/forgecli/review-code.js.map +1 -0
  41. package/dist/extensions/forgecli/review-plan.d.ts +24 -0
  42. package/dist/extensions/forgecli/review-plan.js +203 -0
  43. package/dist/extensions/forgecli/review-plan.js.map +1 -0
  44. package/dist/extensions/forgecli/run-sprint.d.ts +18 -0
  45. package/dist/extensions/forgecli/run-sprint.js +33 -1
  46. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  47. package/dist/extensions/forgecli/run-task.d.ts +21 -2
  48. package/dist/extensions/forgecli/run-task.js +33 -9
  49. package/dist/extensions/forgecli/run-task.js.map +1 -1
  50. package/dist/extensions/forgecli/session-registry.d.ts +10 -0
  51. package/dist/extensions/forgecli/session-registry.js +9 -0
  52. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  53. package/dist/extensions/forgecli/validate.d.ts +24 -0
  54. package/dist/extensions/forgecli/validate.js +202 -0
  55. package/dist/extensions/forgecli/validate.js.map +1 -0
  56. package/dist/extensions/forgecli/wf-engine/engine.d.ts +23 -0
  57. package/dist/extensions/forgecli/wf-engine/engine.js +384 -0
  58. package/dist/extensions/forgecli/wf-engine/engine.js.map +1 -0
  59. package/dist/extensions/forgecli/wf-engine/event-parser.d.ts +6 -0
  60. package/dist/extensions/forgecli/wf-engine/event-parser.js +29 -0
  61. package/dist/extensions/forgecli/wf-engine/event-parser.js.map +1 -0
  62. package/dist/extensions/forgecli/wf-engine/id-gen.d.ts +6 -0
  63. package/dist/extensions/forgecli/wf-engine/id-gen.js +17 -0
  64. package/dist/extensions/forgecli/wf-engine/id-gen.js.map +1 -0
  65. package/dist/extensions/forgecli/wf-engine/loader.d.ts +2 -0
  66. package/dist/extensions/forgecli/wf-engine/loader.js +100 -0
  67. package/dist/extensions/forgecli/wf-engine/loader.js.map +1 -0
  68. package/dist/extensions/forgecli/wf-engine/predicate.d.ts +7 -0
  69. package/dist/extensions/forgecli/wf-engine/predicate.js +36 -0
  70. package/dist/extensions/forgecli/wf-engine/predicate.js.map +1 -0
  71. package/dist/extensions/forgecli/wf-engine/prompt-compiler.d.ts +15 -0
  72. package/dist/extensions/forgecli/wf-engine/prompt-compiler.js +23 -0
  73. package/dist/extensions/forgecli/wf-engine/prompt-compiler.js.map +1 -0
  74. package/dist/extensions/forgecli/wf-engine/register.d.ts +9 -0
  75. package/dist/extensions/forgecli/wf-engine/register.js +59 -0
  76. package/dist/extensions/forgecli/wf-engine/register.js.map +1 -0
  77. package/dist/extensions/forgecli/wf-engine/remit-check.d.ts +6 -0
  78. package/dist/extensions/forgecli/wf-engine/remit-check.js +42 -0
  79. package/dist/extensions/forgecli/wf-engine/remit-check.js.map +1 -0
  80. package/dist/extensions/forgecli/wf-engine/state-store.d.ts +13 -0
  81. package/dist/extensions/forgecli/wf-engine/state-store.js +43 -0
  82. package/dist/extensions/forgecli/wf-engine/state-store.js.map +1 -0
  83. package/dist/extensions/forgecli/wf-engine/types.d.ts +66 -0
  84. package/dist/extensions/forgecli/wf-engine/types.js +2 -0
  85. package/dist/extensions/forgecli/wf-engine/types.js.map +1 -0
  86. package/dist/extensions/forgecli/wf-engine/worker.d.ts +11 -0
  87. package/dist/extensions/forgecli/wf-engine/worker.js +50 -0
  88. package/dist/extensions/forgecli/wf-engine/worker.js.map +1 -0
  89. package/dist/forge-payload/.base-pack/workflows/_fragments/context-injection.md +10 -4
  90. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +12 -0
  91. package/dist/forge-payload/.schemas/bug.schema.json +4 -2
  92. package/dist/forge-payload/.schemas/event.schema.json +22 -3
  93. package/dist/forge-payload/commands/add-pipeline.md +342 -0
  94. package/dist/forge-payload/commands/add-task.md +269 -0
  95. package/dist/forge-payload/commands/ask.md +43 -0
  96. package/dist/forge-payload/commands/calibrate.md +356 -0
  97. package/dist/forge-payload/commands/config.md +202 -0
  98. package/dist/forge-payload/commands/enhance.md +38 -0
  99. package/dist/forge-payload/commands/health.md +225 -0
  100. package/dist/forge-payload/commands/init.md +165 -0
  101. package/dist/forge-payload/commands/materialize.md +119 -0
  102. package/dist/forge-payload/commands/migrate.md +160 -0
  103. package/dist/forge-payload/commands/quiz-agent.md +38 -0
  104. package/dist/forge-payload/commands/regenerate.md +673 -0
  105. package/dist/forge-payload/commands/remove.md +174 -0
  106. package/dist/forge-payload/commands/report-bug.md +191 -0
  107. package/dist/forge-payload/commands/store-query.md +73 -0
  108. package/dist/forge-payload/commands/store-repair.md +187 -0
  109. package/dist/forge-payload/commands/update-tools.md +56 -0
  110. package/dist/forge-payload/commands/update.md +1376 -0
  111. package/dist/forge-payload/tools/preflight-gate.cjs +2 -1
  112. package/dist/forge-payload/tools/read-verdict.cjs +41 -8
  113. package/dist/forge-payload/tools/store-cli.cjs +4 -3
  114. package/node_modules/argparse/CHANGELOG.md +216 -0
  115. package/node_modules/argparse/LICENSE +254 -0
  116. package/node_modules/argparse/README.md +84 -0
  117. package/node_modules/argparse/argparse.js +3707 -0
  118. package/node_modules/argparse/lib/sub.js +67 -0
  119. package/node_modules/argparse/lib/textwrap.js +440 -0
  120. package/node_modules/argparse/package.json +31 -0
  121. package/node_modules/cliui/CHANGELOG.md +121 -0
  122. package/node_modules/color-convert/CHANGELOG.md +54 -0
  123. package/node_modules/esprima/ChangeLog +235 -0
  124. package/node_modules/js-yaml/LICENSE +21 -0
  125. package/node_modules/js-yaml/README.md +247 -0
  126. package/node_modules/js-yaml/bin/js-yaml.js +126 -0
  127. package/node_modules/js-yaml/dist/js-yaml.js +3880 -0
  128. package/node_modules/js-yaml/dist/js-yaml.min.js +2 -0
  129. package/node_modules/js-yaml/dist/js-yaml.mjs +3856 -0
  130. package/node_modules/js-yaml/index.js +47 -0
  131. package/node_modules/js-yaml/lib/common.js +59 -0
  132. package/node_modules/js-yaml/lib/dumper.js +965 -0
  133. package/node_modules/js-yaml/lib/exception.js +55 -0
  134. package/node_modules/js-yaml/lib/loader.js +1733 -0
  135. package/node_modules/js-yaml/lib/schema/core.js +11 -0
  136. package/node_modules/js-yaml/lib/schema/default.js +22 -0
  137. package/node_modules/js-yaml/lib/schema/failsafe.js +17 -0
  138. package/node_modules/js-yaml/lib/schema/json.js +19 -0
  139. package/node_modules/js-yaml/lib/schema.js +121 -0
  140. package/node_modules/js-yaml/lib/snippet.js +101 -0
  141. package/node_modules/js-yaml/lib/type/binary.js +125 -0
  142. package/node_modules/js-yaml/lib/type/bool.js +35 -0
  143. package/node_modules/js-yaml/lib/type/float.js +97 -0
  144. package/node_modules/js-yaml/lib/type/int.js +156 -0
  145. package/node_modules/js-yaml/lib/type/map.js +8 -0
  146. package/node_modules/js-yaml/lib/type/merge.js +12 -0
  147. package/node_modules/js-yaml/lib/type/null.js +35 -0
  148. package/node_modules/js-yaml/lib/type/omap.js +44 -0
  149. package/node_modules/js-yaml/lib/type/pairs.js +53 -0
  150. package/node_modules/js-yaml/lib/type/seq.js +8 -0
  151. package/node_modules/js-yaml/lib/type/set.js +29 -0
  152. package/node_modules/js-yaml/lib/type/str.js +8 -0
  153. package/node_modules/js-yaml/lib/type/timestamp.js +88 -0
  154. package/node_modules/js-yaml/lib/type.js +66 -0
  155. package/node_modules/js-yaml/package.json +66 -0
  156. package/node_modules/mz/HISTORY.md +66 -0
  157. package/node_modules/proper-lockfile/CHANGELOG.md +108 -0
  158. package/node_modules/source-map/CHANGELOG.md +301 -0
  159. package/node_modules/thenify/History.md +11 -0
  160. package/node_modules/thenify-all/History.md +11 -0
  161. package/node_modules/y18n/CHANGELOG.md +100 -0
  162. package/node_modules/yargs/CHANGELOG.md +88 -0
  163. package/node_modules/yargs-parser/CHANGELOG.md +263 -0
  164. package/package.json +6 -2
  165. package/workflows/lead-qualifier/prompts/digest.md +44 -0
  166. package/workflows/lead-qualifier/prompts/draft-outreach.md +44 -0
  167. package/workflows/lead-qualifier/prompts/enrich.md +52 -0
  168. package/workflows/lead-qualifier/prompts/intake.md +48 -0
  169. package/workflows/lead-qualifier/prompts/mark-cold.md +38 -0
  170. package/workflows/lead-qualifier/prompts/score.md +45 -0
  171. package/workflows/lead-qualifier/workflow.yaml +95 -0
  172. package/workflows/research-brief/prompts/brief-synthesize.md +43 -0
  173. package/workflows/research-brief/prompts/intake.md +51 -0
  174. package/workflows/research-brief/prompts/source-critique.md +38 -0
  175. package/workflows/research-brief/prompts/source-score.md +38 -0
  176. package/workflows/research-brief/prompts/source-summarize.md +54 -0
  177. package/workflows/research-brief/workflow.yaml +66 -0
  178. package/dist/extensions/forgecli/session-monitor-widget.d.ts +0 -37
  179. package/dist/extensions/forgecli/session-monitor-widget.js +0 -320
  180. package/dist/extensions/forgecli/session-monitor-widget.js.map +0 -1
  181. package/dist/extensions/forgecli/session-monitor.d.ts +0 -2
  182. package/dist/extensions/forgecli/session-monitor.js +0 -135
  183. package/dist/extensions/forgecli/session-monitor.js.map +0 -1
@@ -34,15 +34,21 @@ else:
34
34
 
35
35
  ## Prior Phase Summary Block
36
36
 
37
- Re-read the task record from disk after each phase so summaries accumulate:
37
+ Re-read the record from disk after each phase so summaries accumulate.
38
+ For bugs, pass `record_type="bug"` to read from the bugs store path.
38
39
 
39
40
  ```python
40
- task_record_fresh = read_json(f".forge/store/tasks/{task_id}.json")
41
- summaries = (task_record_fresh or {}).get("summaries", {})
41
+ # record_type: "task" (default) or "bug"
42
+ if record_type == "bug":
43
+ record_fresh = read_json(f".forge/store/bugs/{record_id}.json")
44
+ else:
45
+ record_fresh = read_json(f".forge/store/tasks/{record_id}.json")
46
+ summaries = (record_fresh or {}).get("summaries", {})
42
47
 
43
48
  SUMMARY_PHASE_LABELS = {
44
49
  "plan": "Plan", "review_plan": "Plan review",
45
- "implementation": "Implementation", "code_review": "Code review", "validation": "Validation"
50
+ "implementation": "Implementation", "code_review": "Code review",
51
+ "validation": "Validation", "approve": "Approve", "triage": "Triage"
46
52
  }
47
53
  summary_lines = []
48
54
  for phase_key, label in SUMMARY_PHASE_LABELS.items():
@@ -47,6 +47,11 @@ deps:
47
47
  node "$FORGE_ROOT/tools/store-cli.cjs" read bug {BUG_ID} --json
48
48
  - Reproduce the bug: create a failing test case or a reproduction script
49
49
  - Confirm the root cause via codebase research
50
+ - After creating the bug record, transition to in-progress:
51
+ ```sh
52
+ node "$FORGE_ROOT/tools/store-cli.cjs" update-status bug {BUG_ID} status triaged
53
+ node "$FORGE_ROOT/tools/store-cli.cjs" update-status bug {BUG_ID} status in-progress
54
+ ```
50
55
 
51
56
  2. Plan:
52
57
  - Generate BUG_FIX_PLAN.md following the plan template
@@ -75,6 +80,9 @@ deps:
75
80
  - **After Implement phase:**
76
81
  Write `IMPLEMENTATION-SUMMARY.json` with `key_changes` and `verdict: "n/a"`.
77
82
  Then: `node "$FORGE_ROOT/tools/store-cli.cjs" set-bug-summary {bug_id} implementation ...SUMMARY.json`
83
+ - **After Approve phase:**
84
+ Write `APPROVE-SUMMARY.json` with `objective`, `verdict` (approved|revision), and `artifact_ref`.
85
+ Then: `node "$FORGE_ROOT/tools/store-cli.cjs" set-bug-summary {bug_id} approve ...APPROVE-SUMMARY.json`
78
86
  - If set-bug-summary exits non-zero, fix the JSON and retry before proceeding.
79
87
 
80
88
  6. Finalize:
@@ -245,6 +253,8 @@ identical to `meta-orchestrate.md` — see that file's "Phase Gates" section
245
253
  for the directive reference.
246
254
 
247
255
  ```gates phase=plan-fix
256
+ forbid bug.status == blocked
257
+ forbid bug.status == escalated
248
258
  forbid bug.status == fixed
249
259
  forbid bug.status == abandoned
250
260
  ```
@@ -254,6 +264,8 @@ artifact {engineering}/bugs/{bug}/BUG_FIX_PLAN.md min=200
254
264
  ```
255
265
 
256
266
  ```gates phase=implement
267
+ forbid bug.status == blocked
268
+ forbid bug.status == escalated
257
269
  artifact {engineering}/bugs/{bug}/BUG_FIX_PLAN.md min=200
258
270
  after review-plan = approved
259
271
  forbid bug.status == fixed
@@ -9,7 +9,7 @@
9
9
  "title": { "type": "string" },
10
10
  "description": { "type": "string" },
11
11
  "severity": { "type": "string", "enum": ["critical", "major", "minor"] },
12
- "status": { "type": "string", "enum": ["reported", "triaged", "in-progress", "fixed", "verified"] },
12
+ "status": { "type": "string", "enum": ["reported", "triaged", "in-progress", "fixed", "approved", "verified"] },
13
13
  "path": { "type": "string" },
14
14
  "rootCauseCategory": {
15
15
  "type": "string",
@@ -26,10 +26,12 @@
26
26
  "description": "Terse structured summaries of phase artifacts. Optional; full artifacts on disk remain authoritative.",
27
27
  "properties": {
28
28
  "plan": { "$ref": "#/$defs/phaseSummary" },
29
+ "triage": { "$ref": "#/$defs/phaseSummary" },
29
30
  "review_plan": { "$ref": "#/$defs/phaseSummary" },
30
31
  "implementation": { "$ref": "#/$defs/phaseSummary" },
31
32
  "code_review": { "$ref": "#/$defs/phaseSummary" },
32
- "validation": { "$ref": "#/$defs/phaseSummary" }
33
+ "validation": { "$ref": "#/$defs/phaseSummary" },
34
+ "approve": { "$ref": "#/$defs/phaseSummary" }
33
35
  },
34
36
  "additionalProperties": false
35
37
  }
@@ -10,6 +10,7 @@
10
10
  "properties": {
11
11
  "eventId": { "type": "string" },
12
12
  "taskId": { "type": "string" },
13
+ "bugId": { "type": "string" },
13
14
  "sprintId": { "type": "string" },
14
15
  "role": { "type": "string" },
15
16
  "action": { "type": "string" },
@@ -56,7 +57,11 @@
56
57
  "task-committed",
57
58
  "sprint-complete",
58
59
  "sprint-halted",
59
- "bug-fixed"
60
+ "bug-fixed",
61
+
62
+ "bug-triaged", "fix-planned", "fix-review-passed", "fix-review-failed",
63
+ "fix-implemented", "fix-code-review-passed", "fix-code-review-failed",
64
+ "fix-approved", "bug-committed"
60
65
  ]
61
66
  },
62
67
  "workflow": { "type": "string" },
@@ -99,8 +104,7 @@
99
104
  "enum": [
100
105
  "task-planned", "plan-complete", "plan-approved",
101
106
  "task-implemented", "review-passed", "review-failed",
102
- "task-approved", "task-validated", "task-committed",
103
- "bug-fixed"
107
+ "task-approved", "task-validated", "task-committed"
104
108
  ]
105
109
  }
106
110
  },
@@ -108,6 +112,21 @@
108
112
  },
109
113
  "then": { "required": ["taskId", "phase", "iteration"] }
110
114
  },
115
+ {
116
+ "if": {
117
+ "properties": {
118
+ "type": {
119
+ "enum": [
120
+ "bug-triaged", "fix-planned", "fix-review-passed", "fix-review-failed",
121
+ "fix-implemented", "fix-code-review-passed", "fix-code-review-failed",
122
+ "fix-approved", "bug-committed", "bug-fixed"
123
+ ]
124
+ }
125
+ },
126
+ "required": ["type"]
127
+ },
128
+ "then": { "required": ["bugId", "phase", "iteration"] }
129
+ },
111
130
  {
112
131
  "if": { "properties": { "type": { "const": "sprint-complete" } }, "required": ["type"] },
113
132
  "then": {
@@ -0,0 +1,342 @@
1
+ ---
2
+ name: add-pipeline
3
+ description: Conversational pipeline manager — add, customize, view, or remove Forge pipelines and their phase commands
4
+ ---
5
+
6
+ # /forge:add-pipeline
7
+
8
+ 🌊 **Pipeline Manager** — I guide you through building and rewiring pipelines.
9
+
10
+ ## Setup
11
+
12
+ ```
13
+ FORGE_ROOT: !`echo "${CLAUDE_PLUGIN_ROOT}"`
14
+ ```
15
+
16
+ Read project config values:
17
+ ```
18
+ PROJECT_PREFIX: !`node -e "try{console.log(require('./.forge/config.json').project.prefix)}catch{console.log('PROJECT')}"`
19
+ CUSTOM_COMMANDS_DIR: !`node -e "try{console.log(require('./.forge/config.json').paths.customCommands)}catch{console.log('engineering/commands')}"`
20
+ ```
21
+
22
+ ## Arguments
23
+
24
+ $ARGUMENTS
25
+
26
+ Parse for shortcuts:
27
+ - `--list` → jump directly to **View mode**
28
+ - `--remove <name>` → jump directly to **Remove mode** for that name
29
+ - A plain pipeline name with no other flags → jump to **Add/Edit mode** pre-filled with that name
30
+
31
+ ---
32
+
33
+ ## Opening conversation
34
+
35
+ If no shortcut was triggered, greet the user and ask intent:
36
+
37
+ > 🌊 **Pipeline Manager**
38
+ >
39
+ > What would you like to do?
40
+ >
41
+ > **1.** Add a new pipeline
42
+ > **2.** Customize an existing pipeline — override phases, swap commands, change models, rewire
43
+ > **3.** View configured pipelines
44
+ > **4.** Remove a pipeline
45
+ >
46
+ > ── Reply with a number, or just describe what you need.
47
+
48
+ Interpret free-text generously:
49
+ - "I want to change the model on the review phase" → mode 2
50
+ - "add a pipeline for hotfixes" / "new pipeline" → mode 1
51
+ - "show me what's configured" / "list" → mode 3
52
+ - "delete X" / "remove X" → mode 4
53
+
54
+ ---
55
+
56
+ ## Mode 1 — Add new pipeline
57
+
58
+ ### Step 1 — Understand the use case
59
+
60
+ Ask:
61
+
62
+ > What kind of tasks should this pipeline handle?
63
+ > ── Describe the use case in a sentence or two.
64
+ > ── Example: "Data science tasks — need a schema validation step before coding begins"
65
+
66
+ From the description, suggest a pipeline name. The name must be `[a-z0-9_-]`:
67
+
68
+ > How about **`{suggested-name}`**? Does that work, or would you prefer something else?
69
+
70
+ Wait for confirmation or a new name.
71
+
72
+ ### Step 2 — Phase-by-phase walkthrough
73
+
74
+ Display the standard phases as a starting point:
75
+
76
+ > Here are the standard Forge phases. For each one I'll ask whether to keep it as-is,
77
+ > adjust the model, replace it with a different command, skip it, or create a new custom command.
78
+ >
79
+ > | # | Phase role | Default command | Default model |
80
+ > |---|-----------|----------------|---------------|
81
+ > | 1 | plan | `plan` | sonnet |
82
+ > | 2 | review-plan | `review-plan` | opus |
83
+ > | 3 | implement | `implement` | sonnet |
84
+ > | 4 | review-code | `review-code` | opus |
85
+ > | 5 | validate | `validate` | opus |
86
+ > | 6 | approve | `approve` | opus |
87
+ > | 7 | commit | `commit` | haiku |
88
+ >
89
+ > ── Walk me through phase by phase, or describe your whole pipeline at once.
90
+
91
+ For each phase the user wants to customise, ask what they're trying to achieve before
92
+ asking for a command name. Based on their description of intent, suggest the right approach:
93
+
94
+ | Intent | Suggested approach |
95
+ |--------|-------------------|
96
+ | Stricter review, same role | Custom command with tighter instructions |
97
+ | Faster / cheaper phase | Keep command, lower the model (e.g. sonnet → haiku) |
98
+ | Domain-specific validation | New custom command |
99
+ | Skip a phase entirely | Remove it from the phase list |
100
+ | Different agent persona | New custom command |
101
+
102
+ For any phase using a custom command — check whether it exists before collecting more input:
103
+ ```sh
104
+ ls {CUSTOM_COMMANDS_DIR}/{name}.md 2>/dev/null || ls .claude/commands/{name}.md 2>/dev/null
105
+ ```
106
+ If it doesn't exist → go to **Custom Command Creation** below, then return here.
107
+
108
+ ### Step 3 — Check for existing pipeline
109
+
110
+ ```sh
111
+ node "$FORGE_ROOT/tools/manage-config.cjs" pipeline get {PIPELINE_NAME} 2>/dev/null
112
+ ```
113
+
114
+ If output is non-empty, show the existing pipeline and ask:
115
+ > △ A pipeline named `{name}` already exists (shown above).
116
+ > Replace it, edit it instead, or pick a different name?
117
+
118
+ If "edit it" → switch to **Mode 2** for this pipeline, pre-filled with current phases.
119
+
120
+ ### Step 4 → Preview and confirm (see Shared section)
121
+
122
+ ---
123
+
124
+ ## Mode 2 — Customize existing pipeline
125
+
126
+ ### Step 1 — Select pipeline
127
+
128
+ List current pipelines:
129
+ ```sh
130
+ node "$FORGE_ROOT/tools/manage-config.cjs" list-pipelines
131
+ ```
132
+
133
+ If no pipelines exist:
134
+ > △ No pipelines configured yet. Would you like to add one? (Say yes to go to mode 1.)
135
+
136
+ If only one pipeline exists, select it automatically. Otherwise ask:
137
+ > Which pipeline would you like to customize?
138
+
139
+ ### Step 2 — Show current phases
140
+
141
+ ```sh
142
+ node "$FORGE_ROOT/tools/manage-config.cjs" pipeline get {PIPELINE_NAME}
143
+ ```
144
+
145
+ Display the output as-is. It already renders as a phase table.
146
+
147
+ ### Step 3 — Understand the change
148
+
149
+ Ask:
150
+
151
+ > What would you like to change?
152
+ >
153
+ > - **Override** a phase with a different command
154
+ > - **Change model** for one or more phases
155
+ > - **Add** a new phase at a specific position
156
+ > - **Remove** a phase
157
+ > - **Reorder** (rewire) the phases
158
+ >
159
+ > ── Describe what you need in plain language.
160
+
161
+ Listen to intent first, then collect specifics. Examples of intent-to-action mapping:
162
+
163
+ | User says | Action |
164
+ |-----------|--------|
165
+ | "I want a stricter security review" | Override `review-code` with a custom security-focused command |
166
+ | "skip plan review, we move fast" | Remove the `review-plan` phase |
167
+ | "use haiku for planning to save cost" | Update `model` on the `plan` phase to `haiku` |
168
+ | "add a data validation step before coding" | Insert a new `review-plan`-role phase before `implement` |
169
+ | "swap out the architect with my own approval command" | Override `approve` with a custom command |
170
+
171
+ For model changes — after the user names the phases, ask which model:
172
+ > Options: `haiku` (fast/cheap), `sonnet` (balanced), `opus` (thorough)
173
+
174
+ For phase overrides with a custom command — check if the command exists, then go to
175
+ **Custom Command Creation** if not.
176
+
177
+ For reordering — show the current sequence, ask for the new order, verify no
178
+ revision-loop is broken (a `review-*` phase needs a preceding non-review phase to
179
+ loop back to).
180
+
181
+ ### Step 4 → Preview and confirm (see Shared section)
182
+
183
+ ---
184
+
185
+ ## Mode 3 — View
186
+
187
+ ```sh
188
+ node "$FORGE_ROOT/tools/manage-config.cjs" list-pipelines
189
+ ```
190
+
191
+ If no pipelines are configured, say so and offer to add one.
192
+
193
+ If pipelines exist, offer to drill into one:
194
+ > ── To see a pipeline's full phase detail, tell me its name.
195
+
196
+ For a named pipeline:
197
+ ```sh
198
+ node "$FORGE_ROOT/tools/manage-config.cjs" pipeline get {NAME}
199
+ ```
200
+
201
+ ---
202
+
203
+ ## Mode 4 — Remove
204
+
205
+ If no name was provided, list pipelines and ask which to remove.
206
+
207
+ Check for tasks referencing this pipeline:
208
+ ```sh
209
+ grep -rl '"pipeline": "{NAME}"' .forge/store/tasks/ 2>/dev/null
210
+ ```
211
+
212
+ If any found:
213
+ > △ {N} task(s) reference `{NAME}`. They will fall back to the default pipeline at runtime.
214
+ > The tasks themselves won't be modified — only the routing changes.
215
+ >
216
+ > Confirm removal? (yes / no)
217
+
218
+ On confirmation:
219
+ ```sh
220
+ node "$FORGE_ROOT/tools/manage-config.cjs" pipeline remove {NAME}
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Custom Command Creation
226
+
227
+ When a phase needs a command that doesn't exist yet, guide the user through creating it.
228
+
229
+ Tell the user:
230
+
231
+ > The command **`{name}`** doesn't exist yet. I can create it now.
232
+ >
233
+ > A few questions:
234
+ >
235
+ > 1. **What should it do?**
236
+ > Describe the behavior — what it evaluates, produces, or enforces.
237
+ >
238
+ > 2. **What persona should it have?**
239
+ > Describe the agent's character and constraints.
240
+ > Example: "Strict data validator — refuses to approve if schema files are missing"
241
+ >
242
+ > 3. **What artifact does it produce?**
243
+ > Example: `SCHEMA_REVIEW.md`, `VALIDATION_REPORT.md`
244
+
245
+ From the answers, determine:
246
+ - **Persona symbol** — pick based on the phase role:
247
+ - Plan / implement / commit phases → 🌱
248
+ - Review phases → 🌿
249
+ - Approval / sign-off phases → ⛰️
250
+ - Domain-specific validator → 🌿
251
+ - Flow controller → 🌊
252
+ - Analysis / investigation → 🍂
253
+ - **Announcement line** — first-person, present tense, one sentence
254
+ - **Next status** — derive from the phase role (e.g. `review-plan` → `plan-approved` or `plan-revision-required`)
255
+
256
+ Use `.forge/templates/CUSTOM_COMMAND_TEMPLATE.md` as the scaffold. Fill in all
257
+ `{PLACEHOLDER}` values from the conversation.
258
+
259
+ Ensure the directory exists and write the file:
260
+ ```sh
261
+ mkdir -p {CUSTOM_COMMANDS_DIR}
262
+ ```
263
+
264
+ Create: `{CUSTOM_COMMANDS_DIR}/{name}.md`
265
+
266
+ Set the phase's `workflow` field to `"{CUSTOM_COMMANDS_DIR}/{name}.md"` in the pipeline
267
+ being built. This allows the orchestrator to read and follow the file directly — the
268
+ command name is used for display and manual reference only.
269
+
270
+ Confirm:
271
+ > 〇 Created `{CUSTOM_COMMANDS_DIR}/{name}.md`
272
+ > ── Review and edit it before running a task with this pipeline.
273
+ > ── The orchestrator will read it directly via the `workflow` field.
274
+
275
+ Return to the phase walkthrough where you left off.
276
+
277
+ ---
278
+
279
+ ## Shared: Preview and confirm
280
+
281
+ Before writing, construct the full pipeline JSON and display it clearly:
282
+
283
+ > 🌊 Here's the pipeline as it will be saved:
284
+ >
285
+ > **`{name}`** — {description}
286
+ >
287
+ > | # | Role | Command | Workflow | Model | maxIter |
288
+ > |---|------|---------|----------|-------|---------|
289
+ > | 1 | plan | `plan` | (built-in) | sonnet | — |
290
+ > | 2 | review-plan | `schema-validator` | `engineering/commands/schema-validator.md` | sonnet | 3 |
291
+ > ...
292
+ >
293
+ > ── Save this pipeline? (yes / edit / cancel)
294
+
295
+ - **yes** → proceed to Write
296
+ - **edit** → return to the relevant collection step
297
+ - **cancel** → exit without writing, no changes made
298
+
299
+ ---
300
+
301
+ ## Shared: Write
302
+
303
+ Invoke the tool:
304
+ ```sh
305
+ node "$FORGE_ROOT/tools/manage-config.cjs" pipeline add {NAME} --description "{DESCRIPTION}" --phases '{PHASES_JSON}'
306
+ ```
307
+
308
+ `PHASES_JSON` is a JSON array where each element includes `command`, `role`, `model`,
309
+ and — when a custom command was created — `workflow`. Example:
310
+ ```json
311
+ [
312
+ {"command": "plan", "role": "plan", "model": "sonnet"},
313
+ {"command": "schema-validator", "role": "review-plan", "model": "sonnet",
314
+ "workflow": "engineering/commands/schema-validator.md", "maxIterations": 3},
315
+ {"command": "implement", "role": "implement", "model": "sonnet"},
316
+ {"command": "review-code", "role": "review-code", "model": "opus"},
317
+ {"command": "approve", "role": "approve", "model": "opus"},
318
+ {"command": "commit", "role": "commit", "model": "haiku"}
319
+ ]
320
+ ```
321
+
322
+ On success, print next steps:
323
+
324
+ ```
325
+ 〇 Pipeline '{NAME}' saved to .forge/config.json.
326
+
327
+ ── Next steps:
328
+ 1. If you created custom commands, review them in {CUSTOM_COMMANDS_DIR}/
329
+ and fill in any {PLACEHOLDER} sections before running a task.
330
+ 2. Assign this pipeline to a task: set "pipeline": "{NAME}" in the task's
331
+ .forge/store/tasks/{TASK_ID}.json, or let the sprint planner auto-assign it.
332
+ 3. Run /forge:regenerate to update the orchestrator's pipeline routing.
333
+ ```
334
+
335
+ ---
336
+
337
+ ## On error
338
+
339
+ If any step fails unexpectedly:
340
+ > × Something went wrong: {error}
341
+ >
342
+ > ── This may be a Forge bug. Run `/forge:report-bug` and I'll pre-fill the report.