@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
@@ -0,0 +1,269 @@
1
+ ---
2
+ name: add-task
3
+ description: Add a new task to an existing sprint mid-flight — mini intake, sequential ID assignment, store write, and collate
4
+ ---
5
+
6
+ # /forge:add-task
7
+
8
+ Add a task to an existing sprint without re-running the full sprint planner.
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
+ ENGINEERING_PATH: !`node -e "try{console.log(require('./.forge/config.json').paths.engineering)}catch{console.log('engineering')}"`
20
+ STORE_ROOT: !`node -e "try{console.log(require('./.forge/config.json').paths.store)}catch{console.log('.forge/store')}"`
21
+ ```
22
+
23
+ ## Arguments
24
+
25
+ $ARGUMENTS
26
+
27
+ Parse for shortcuts:
28
+ - `--sprint <SPRINT_ID>` → skip sprint selection, use this sprint directly
29
+ - `--title <title>` → skip title prompt, use this title directly
30
+ - `--estimate <S|M|L|XL>` → skip estimate prompt, use this estimate directly
31
+
32
+ ---
33
+
34
+ ## Step 1 — Sprint Selection
35
+
36
+ List all sprints in the store:
37
+
38
+ ```sh
39
+ node "$FORGE_ROOT/tools/store-cli.cjs" list sprint
40
+ ```
41
+
42
+ If `--sprint <ID>` was provided:
43
+ - Verify the sprint exists by checking the output for the given ID.
44
+ - If not found: `× Sprint {ID} not found. Available sprints shown above.`
45
+ - If found: use it, skip to Step 2.
46
+
47
+ If no `--sprint` argument:
48
+ - Filter to sprints with status `active` or `planning` (these are the only
49
+ states where adding tasks makes sense).
50
+ - If no active/planning sprints exist:
51
+ > △ No active or planning sprints found. Create a sprint first using sprint-intake.
52
+ > Exit without making changes.
53
+ - If only one active/planning sprint: auto-select it and tell the user:
54
+ > 〇 Auto-selected sprint: **{SPRINT_ID}** — {title}
55
+ - If multiple: present a numbered list and ask the user to choose:
56
+ > Which sprint should receive the new task?
57
+ >
58
+ > | # | Sprint | Title | Status | Tasks |
59
+ > |---|--------|-------|--------|-------|
60
+ > | 1 | FORGE-S09 | Calibration, Guardrails, and Bug Closure | active | 9 |
61
+ > | ... |
62
+ >
63
+ > ── Reply with a number.
64
+
65
+ ---
66
+
67
+ ## Step 2 — Mini-Intake Interview
68
+
69
+ Conduct a focused interview to capture what is needed for immediate implementation.
70
+
71
+ ### Title
72
+
73
+ If `--title` was provided, use it. Otherwise ask:
74
+
75
+ > What is the task title?
76
+ > ── A short, imperative description (e.g. "Add health-check command")
77
+
78
+ ### Objective
79
+
80
+ Ask:
81
+
82
+ > What does this task achieve?
83
+ > ── One paragraph: user-facing value or technical goal.
84
+
85
+ ### Acceptance Criteria
86
+
87
+ Ask:
88
+
89
+ > What are the acceptance criteria?
90
+ > ── List the concrete, testable outcomes that mark this task as done.
91
+ > ── Include `node --check` and `validate-store --dry-run` if the task touches `forge/` code.
92
+
93
+ ### Estimate
94
+
95
+ If `--estimate` was provided, use it. Otherwise ask:
96
+
97
+ > What is the estimate?
98
+ > ── **S** (under 1 hour) / **M** (1-3 hours) / **L** (3-6 hours) / **XL** (6+ hours)
99
+
100
+ ### Pipeline (optional)
101
+
102
+ Ask:
103
+
104
+ > Which pipeline should this task use?
105
+ > ── Press Enter for **default**, or type a named pipeline (e.g. `hotfix`).
106
+
107
+ If the user presses Enter or types "default", set pipeline to `"default"`.
108
+ If the user provides a name, verify it exists:
109
+ ```sh
110
+ node "$FORGE_ROOT/tools/manage-config.cjs" pipeline get {NAME} 2>/dev/null
111
+ ```
112
+ If not found:
113
+ > △ Pipeline `{NAME}` not found. Using **default**.
114
+ Set pipeline to `"default"`.
115
+
116
+ ---
117
+
118
+ ## Step 3 — Assign Task ID
119
+
120
+ Determine the next sequential task number within the selected sprint.
121
+
122
+ 1. Read the sprint record:
123
+ ```sh
124
+ node "$FORGE_ROOT/tools/store-cli.cjs" read sprint {SPRINT_ID} --json
125
+ ```
126
+ 2. Parse `taskIds` from the sprint JSON. Each task ID follows the pattern
127
+ `{PREFIX}-S{NN}-T{NN}` (e.g. `FORGE-S09-T07`).
128
+ 3. Extract the T-numbers (the `NN` part after `T`), find the maximum.
129
+ 4. The next task number is `max + 1`, zero-padded to 2 digits.
130
+ 5. Construct the task ID: `{PREFIX}-{SNN}-T{next}` (e.g. `FORGE-S09-T10`).
131
+
132
+ Example: If `taskIds` contains `FORGE-S09-T01` through `FORGE-S09-T09`,
133
+ the next task ID is `FORGE-S09-T10`.
134
+
135
+ ---
136
+
137
+ ## Step 4 — Derive Directory Slug
138
+
139
+ Convert the task title to a lower-kebab-case slug for the directory name:
140
+
141
+ 1. Lowercase the title.
142
+ 2. Replace each sequence of non-alphanumeric characters with a single hyphen.
143
+ 3. Remove leading and trailing hyphens.
144
+ 4. Truncate to 30 characters.
145
+ 5. Remove trailing hyphens after truncation.
146
+
147
+ This follows the `deriveSlug()` algorithm from `seed-store.cjs`.
148
+
149
+ The task directory name is: `{TASK_ID}-{slug}`
150
+ For example: `FORGE-S09-T10-close-bugs`
151
+
152
+ ---
153
+
154
+ ## Step 5 — Create Task Directory and TASK_PROMPT.md
155
+
156
+ Create the task directory:
157
+
158
+ ```sh
159
+ mkdir -p {ENGINEERING_PATH}/sprints/{SPRINT_DIR}/{TASK_DIR}
160
+ ```
161
+
162
+ Where:
163
+ - `SPRINT_DIR` is the sprint's directory name (from the sprint record's `path`
164
+ field, or derived as `{SPRINT_ID}-{slug}` if no `path` field)
165
+ - `TASK_DIR` is `{TASK_ID}-{slug}` from Step 4
166
+
167
+ Write `TASK_PROMPT.md` using the project's template. Read the template first:
168
+
169
+ ```sh
170
+ cat .forge/templates/TASK_PROMPT_TEMPLATE.md
171
+ ```
172
+
173
+ Fill in all placeholders:
174
+ - `{TASK_ID}` — the assigned task ID
175
+ - `{TASK_TITLE}` — the title from the interview
176
+ - `{SPRINT_ID}` — the selected sprint ID
177
+ - `{S/M/L/XL}` — the estimate
178
+ - `default *(or specify a named pipeline)*` — the pipeline choice
179
+ - Objective, Acceptance Criteria, Context, Plugin Artifacts, Operational Impact —
180
+ from the interview answers
181
+
182
+ Write the file:
183
+ ```
184
+ {ENGINEERING_PATH}/sprints/{SPRINT_DIR}/{TASK_DIR}/TASK_PROMPT.md
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Step 6 — Write Task Record to Store
190
+
191
+ Construct the task JSON record:
192
+
193
+ ```json
194
+ {
195
+ "taskId": "{TASK_ID}",
196
+ "feature_id": null,
197
+ "sprintId": "{SPRINT_ID}",
198
+ "title": "{TITLE}",
199
+ "status": "planned",
200
+ "path": "{ENGINEERING_PATH}/sprints/{SPRINT_DIR}/{TASK_DIR}",
201
+ "estimate": "{S|M|L|XL}",
202
+ "dependencies": [],
203
+ "pipeline": "{PIPELINE}"
204
+ }
205
+ ```
206
+
207
+ Write it via the store custodian:
208
+
209
+ ```sh
210
+ node "$FORGE_ROOT/tools/store-cli.cjs" write task '{TASK_JSON}'
211
+ ```
212
+
213
+ If the write fails (validation error), report the error and ask the user
214
+ to fix the data. Do not proceed until the store accepts the record.
215
+
216
+ ---
217
+
218
+ ## Step 7 — Update Sprint Record
219
+
220
+ Read the current sprint record:
221
+
222
+ ```sh
223
+ node "$FORGE_ROOT/tools/store-cli.cjs" read sprint {SPRINT_ID} --json
224
+ ```
225
+
226
+ Append the new task ID to the `taskIds` array. Write the updated sprint:
227
+
228
+ ```sh
229
+ node "$FORGE_ROOT/tools/store-cli.cjs" write sprint '{UPDATED_SPRINT_JSON}'
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Step 8 — Collate
235
+
236
+ Run collate to regenerate views (MASTER_INDEX.md, COST_REPORT.md, etc.):
237
+
238
+ ```sh
239
+ node "$FORGE_ROOT/tools/collate.cjs"
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Step 9 — Confirm
245
+
246
+ Display a summary (substitute `{PREFIX}` with `PROJECT_PREFIX.toLowerCase()`):
247
+
248
+ ```
249
+ 〇 Task added successfully!
250
+
251
+ ID: {TASK_ID}
252
+ Sprint: {SPRINT_ID}
253
+ Directory: {ENGINEERING_PATH}/sprints/{SPRINT_DIR}/{TASK_DIR}/
254
+ Prompt: {ENGINEERING_PATH}/sprints/{SPRINT_DIR}/{TASK_DIR}/TASK_PROMPT.md
255
+ Estimate: {ESTIMATE}
256
+ Pipeline: {PIPELINE}
257
+
258
+ ── Next steps:
259
+ 1. Run /{PREFIX}:run-task {TASK_ID} to execute the full pipeline.
260
+ 2. Or run /{PREFIX}:plan {TASK_ID} to plan it first.
261
+ ```
262
+
263
+ ---
264
+
265
+ ## On error
266
+
267
+ If any step fails unexpectedly, describe what went wrong and ask:
268
+
269
+ > "This looks like a Forge bug. Would you like to file a report to help improve it? Run `/forge:report-bug` — I'll pre-fill the report from this conversation."
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: ask
3
+ description: Ask Forge anything — project status, config, workflows, commands, version, or how-to questions
4
+ ---
5
+
6
+ # /forge:ask
7
+
8
+ Single conversational entry point for all Forge intent.
9
+
10
+ ## Locate plugin root
11
+
12
+ ```
13
+ FORGE_ROOT: !`echo "${CLAUDE_PLUGIN_ROOT}"`
14
+ ```
15
+
16
+ ## Open with oracle banner
17
+
18
+ ```sh
19
+ node "$FORGE_ROOT/tools/banners.cjs" oracle
20
+ node "$FORGE_ROOT/tools/banners.cjs" --subtitle "🏮 灯 Tomoshibi — your Forge concierge"
21
+ ```
22
+
23
+ ## Soft config check
24
+
25
+ Check whether `.forge/config.json` exists in the current working directory.
26
+ Project-status and config queries require it; Forge KB and workflow questions do not.
27
+ Store the result as `HAS_CONFIG` — pass it through to the oracle so it can handle
28
+ queries gracefully when config is absent.
29
+
30
+ ## Invoke oracle
31
+
32
+ Read `$FORGE_ROOT/agents/tomoshibi.md` and follow it exactly.
33
+ The user's question is: $ARGUMENTS
34
+
35
+ ## On error
36
+
37
+ If any step above fails unexpectedly, describe what went wrong and ask:
38
+
39
+ > "This looks like a Forge bug. Would you like to file a report to help improve it? Run `/forge:report-bug` — I'll pre-fill the report from this conversation."
40
+
41
+ ## Arguments
42
+
43
+ $ARGUMENTS
@@ -0,0 +1,356 @@
1
+ ---
2
+ name: calibrate
3
+ description: Detect drift between the knowledge base and agent definitions, propose surgical regeneration patches, and apply approved patches
4
+ ---
5
+
6
+ # /forge:calibrate
7
+
8
+ Detect drift between the knowledge base and agent definitions, categorize drift
9
+ by type, propose typed surgical patches as structured regeneration targets,
10
+ gate on explicit Architect approval, and write approved patches to the
11
+ calibration history.
12
+
13
+ ## Locate the Forge plugin
14
+
15
+ ```
16
+ FORGE_ROOT: !`echo "${CLAUDE_PLUGIN_ROOT}"`
17
+ ```
18
+
19
+ Read `.forge/config.json`. If it does not exist, stop and tell the user to run
20
+ `/forge:init` first.
21
+
22
+ Resolve tools from the plugin:
23
+ ```
24
+ FORGE_ROOT: !`echo "${CLAUDE_PLUGIN_ROOT}"`
25
+ ```
26
+
27
+ All tool invocations in this command use `node "$FORGE_ROOT/tools/<tool>.cjs"`.
28
+
29
+ ## Arguments
30
+
31
+ $ARGUMENTS
32
+
33
+ | Argument | Purpose |
34
+ |----------|---------|
35
+ | `--path <dir>` | Run calibration against a different project directory instead of the current working directory. Accepts an absolute path or a path relative to the current directory. |
36
+
37
+ ---
38
+
39
+ ## Step 0 — Structural-element readiness check
40
+
41
+ Before the KB drift check, verify that installed structural elements are current
42
+ with the active plugin version. This check is advisory — it does not block the
43
+ existing KB-level drift detection in Steps 2–8.
44
+
45
+ 1. Read current plugin version from `$FORGE_ROOT/.claude-plugin/plugin.json` → `currentVersion`.
46
+
47
+ 2. Check for `.forge/structure-versions.json` (relative to `PROJECT_ROOT` — defer
48
+ `PROJECT_ROOT` resolution to Step 1; for this step, assume current working directory
49
+ if `--path` was not yet parsed):
50
+
51
+ - **File present**: Read `basePackVersion` and `currentSnapshot` from the file.
52
+
53
+ - If `basePackVersion === currentVersion`, emit:
54
+ > 〇 Structural elements current — snapshot {currentSnapshot} (plugin v{basePackVersion})
55
+
56
+ - If `basePackVersion !== currentVersion`, emit:
57
+ > △ Structural element drift detected — installed elements were generated from plugin v{basePackVersion}; current plugin is v{currentVersion}. Run `/forge:update` to refresh structural elements.
58
+
59
+ - **File absent**: emit:
60
+ > ◇ structure-versions.json absent — project predates snapshot versioning. Run `/forge:update` to install the versioning system.
61
+
62
+ 3. Continue to Step 1 regardless of the readiness check result. The check is informational only.
63
+
64
+ ---
65
+
66
+ ## Step 1 — Locate plugin root and config
67
+
68
+ Resolve `$FORGE_ROOT` from `$CLAUDE_PLUGIN_ROOT`.
69
+
70
+ Parse `$ARGUMENTS` for `--path <dir>`:
71
+ - If present, `PROJECT_ROOT = <dir>` (absolute or relative to the current working directory — resolve to absolute).
72
+ - If absent, `PROJECT_ROOT = .` (current working directory).
73
+
74
+ All file paths below are relative to `PROJECT_ROOT`. All shell tool invocations
75
+ must be run from `PROJECT_ROOT`:
76
+ ```sh
77
+ cd "$PROJECT_ROOT" && node "$FORGE_ROOT/tools/..."
78
+ ```
79
+
80
+ Read `$PROJECT_ROOT/.forge/config.json`. If absent, emit:
81
+ > △ No Forge instance found — run `/forge:init` to create one.
82
+
83
+ Exit early.
84
+
85
+ ## Step 2 — Establish or verify calibration baseline
86
+
87
+ Read `calibrationBaseline` from `$PROJECT_ROOT/.forge/config.json`.
88
+
89
+ ### If absent — auto-initialize
90
+
91
+ When `calibrationBaseline` is missing, compute and write the initial baseline
92
+ using the same algorithm as `/forge:init` Phase 5/6-b:
93
+
94
+ 1. Read `$FORGE_ROOT/.claude-plugin/plugin.json` → `version`.
95
+ 2. Resolve KB path:
96
+ ```sh
97
+ cd "$PROJECT_ROOT" && node -e "const cfg=JSON.parse(require('fs').readFileSync('.forge/config.json','utf8')); console.log((cfg.paths&&cfg.paths.engineering)||'engineering')"
98
+ ```
99
+ 3. Compute `MASTER_INDEX.md` hash (strip blank lines + `<!--` lines, SHA-256):
100
+ ```sh
101
+ cd "$PROJECT_ROOT" && node -e "const crypto=require('crypto'),fs=require('fs'); const cfg=JSON.parse(fs.readFileSync('.forge/config.json','utf8')); const engPath=(cfg.paths&&cfg.paths.engineering)||'engineering'; const lines=fs.readFileSync(engPath+'/MASTER_INDEX.md','utf8').split('\n').filter(l=>l.trim()&&!l.trim().startsWith('<!--')); console.log(crypto.createHash('sha256').update(lines.join('\n')).digest('hex'))"
102
+ ```
103
+ 4. List completed sprint IDs from `.forge/store/sprints/`:
104
+ ```sh
105
+ cd "$PROJECT_ROOT" && node -e "const fs=require('fs'),p='.forge/store/sprints'; try{const files=fs.readdirSync(p).filter(f=>f.endsWith('.json')); const done=files.map(f=>JSON.parse(fs.readFileSync(p+'/'+f,'utf8'))).filter(s=>['done','retrospective-done'].includes(s.status)).map(s=>s.sprintId); console.log(JSON.stringify(done));}catch(e){console.log('[]')}"
106
+ ```
107
+ 5. Get current date: `date -u +"%Y-%m-%d"`
108
+ 6. Write `calibrationBaseline` to config:
109
+ ```sh
110
+ cd "$PROJECT_ROOT" && node -e "
111
+ const fs = require('fs');
112
+ const cfgPath = '.forge/config.json';
113
+ const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
114
+ cfg.calibrationBaseline = {
115
+ lastCalibrated: '<date>',
116
+ version: '<plugin version>',
117
+ masterIndexHash: '<hash>',
118
+ sprintsCovered: <sprint IDs array>
119
+ };
120
+ fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + '\n');
121
+ "
122
+ ```
123
+
124
+ Emit:
125
+
126
+ > 〇 Baseline established — calibration baseline written to config (version: `{version}`, sprints covered: {N})
127
+
128
+ Exit. The next `/forge:calibrate` run will use this baseline for drift detection.
129
+
130
+ ### If present — proceed to drift detection
131
+
132
+ Continue to Step 3.
133
+
134
+ ## Step 3 — Detect drift
135
+
136
+ Compute current `MASTER_INDEX.md` hash using the same algorithm as
137
+ `/forge:init` Phase 5:
138
+
139
+ ```sh
140
+ cd "$PROJECT_ROOT" && node -e "const crypto=require('crypto'),fs=require('fs'); const cfg=JSON.parse(fs.readFileSync('.forge/config.json','utf8')); const engPath=(cfg.paths&&cfg.paths.engineering)||'engineering'; const lines=fs.readFileSync(engPath+'/MASTER_INDEX.md','utf8').split('\n').filter(l=>l.trim()&&!l.trim().startsWith('<!--')); console.log(crypto.createHash('sha256').update(lines.join('\n')).digest('hex'))"
141
+ ```
142
+
143
+ Compare against `calibrationBaseline.masterIndexHash` in config:
144
+
145
+ - **Match** — emit:
146
+
147
+ > 〇 KB calibrated — no drift since last calibration (last: `{calibrationBaseline.lastCalibrated}`, version: `{calibrationBaseline.version}`)
148
+
149
+ Exit. No further steps needed.
150
+
151
+ - **Mismatch** — proceed to Step 4.
152
+
153
+ ## Step 4 — Categorize drift
154
+
155
+ Read `$PROJECT_ROOT/engineering/MASTER_INDEX.md` and identify which sections
156
+ changed by comparing content areas against the calibration baseline's
157
+ `sprintsCovered`. Read sprint task records from
158
+ `$PROJECT_ROOT/.forge/store/tasks/` and `$PROJECT_ROOT/.forge/store/sprints/`
159
+ to determine what changed since the last calibration.
160
+
161
+ Categorize each detected drift into one of four categories:
162
+
163
+ | Category | Detection Trigger | Regeneration Targets |
164
+ |---|---|---|
165
+ | **Technical** | Changes in stack, routing, database, deployment, processes, architecture, schemas, conventions, stack-checklist sections | `personas:engineer`, `skills:engineer-skills`, `skills:supervisor-skills` |
166
+ | **Business** | Changes in entity-model, domain, features, business-domain sections | `personas` (full rebuild — all personas need contextual awareness) |
167
+ | **Retrospective** | Iron-law learnings from completed sprints since last calibration | `personas:<role>` where role had the gap (user specifies at prompt) |
168
+ | **Acceptance criteria** | New acceptance criteria patterns from sprint outcomes | `personas:product-manager`, `skills:qa-engineer` |
169
+
170
+ For each detected category, build a structured patch entry:
171
+
172
+ ```json
173
+ {
174
+ "category": "technical",
175
+ "detectedAt": "<ISO date>",
176
+ "targets": ["personas:engineer", "skills:engineer-skills", "skills:supervisor-skills"],
177
+ "evidence": "<brief description of what changed>"
178
+ }
179
+ ```
180
+
181
+ ## Step 5 — Propose patches
182
+
183
+ Present all detected drift categories and their proposed regeneration targets
184
+ to the user. Format:
185
+
186
+ ```
187
+ ## Calibration Drift Report
188
+
189
+ △ Drift detected — {N} categories since last calibration ({lastCalibrated})
190
+
191
+ ### Category 1: Technical
192
+ Evidence: {what changed}
193
+ Proposed regeneration:
194
+ · personas:engineer
195
+ · skills:engineer-skills
196
+ · skills:supervisor-skills
197
+
198
+ ### Category 2: Business
199
+ ...
200
+
201
+ Apply patches? [Y] Apply all [r] Review individually [n] Skip
202
+ ```
203
+
204
+ If no drift categories are detected (hash mismatch but no identifiable
205
+ section-level changes), emit:
206
+
207
+ > △ Drift detected in MASTER_INDEX.md but no specific category changes identified. Run `/forge:regenerate` to do a full rebuild.
208
+
209
+ Exit.
210
+
211
+ ### Enhancement agent delegation (structural-element drift)
212
+
213
+ After presenting the KB-level patch proposals above, also offer enhancement agent Phase 3
214
+ for structural-element drift detection. This is an opt-in upgrade path:
215
+
216
+ ```
217
+ ── Enhancement agent available: run structural-element drift detection?
218
+ This compares .forge/ personas, skills, and workflows against the current codebase state.
219
+ [E] Run enhancement agent (Phase 3) [n] Skip
220
+ ```
221
+
222
+ If the user selects `[E]`, read and follow `$FORGE_ROOT/meta/workflows/meta-enhance.md`
223
+ with `--phase 3` explicitly (do not rely on the default). Pass `$PROJECT_ROOT` context.
224
+ The enhancement workflow handles its own approval gate and snapshot creation — return
225
+ to this calibrate flow after it completes.
226
+
227
+ If `meta-enhance.md` is absent (older plugin version), emit:
228
+
229
+ > ◇ Enhancement agent not available — run `/forge:update` to install it.
230
+
231
+ ## Step 6 — Architect approval gate
232
+
233
+ For each proposed patch, require explicit approval before any regeneration.
234
+ No changes are applied without Architect sign-off.
235
+
236
+ - **`[Y]`**: Approve all patches and proceed to Step 7.
237
+ - **`[r]`**: Walk through each patch, approve or skip individually.
238
+ - **`[n]`**: Exit without changes.
239
+
240
+ Build the list of approved patches (targets the user confirmed) and the list
241
+ of skipped patches (targets the user declined). Both lists are recorded in
242
+ Step 8.
243
+
244
+ ## Step 7 — Execute approved patches
245
+
246
+ For each approved patch target, invoke `/forge:regenerate <category> <sub-target>`
247
+ by reading and following `$FORGE_ROOT/commands/regenerate.md`.
248
+
249
+ Execute in this order (matching the update command's regeneration order):
250
+ 1. Personas (full rebuild or single file)
251
+ 2. Skills (full rebuild or single file)
252
+
253
+ If any `/forge:regenerate` invocation fails:
254
+ - Record the patch as `applied: false` in the calibration history (Step 8).
255
+ - Emit: `△ Regeneration failed for <target> — skipping.`
256
+ - Continue with remaining approved patches.
257
+
258
+ After all patches are applied (or failed), run the generation manifest check:
259
+
260
+ ```sh
261
+ cd "$PROJECT_ROOT" && node "$FORGE_ROOT/tools/check-structure.cjs" --path "$PROJECT_ROOT"
262
+ ```
263
+
264
+ If the tool is absent (file not found), skip this check silently.
265
+
266
+ ## Step 8 — Update calibration state
267
+
268
+ Recompute the calibration baseline (same algorithm as `/forge:init` Phase 5):
269
+
270
+ 1. Compute new `MASTER_INDEX.md` hash:
271
+ ```sh
272
+ cd "$PROJECT_ROOT" && node -e "const crypto=require('crypto'),fs=require('fs'); const cfg=JSON.parse(fs.readFileSync('.forge/config.json','utf8')); const engPath=(cfg.paths&&cfg.paths.engineering)||'engineering'; const lines=fs.readFileSync(engPath+'/MASTER_INDEX.md','utf8').split('\n').filter(l=>l.trim()&&!l.trim().startsWith('<!--')); console.log(crypto.createHash('sha256').update(lines.join('\n')).digest('hex'))"
273
+ ```
274
+ 2. List completed sprint IDs from `.forge/store/sprints/`:
275
+ ```sh
276
+ cd "$PROJECT_ROOT" && node -e "const fs=require('fs'),p='.forge/store/sprints'; try{const files=fs.readdirSync(p).filter(f=>f.endsWith('.json')); const done=files.map(f=>JSON.parse(fs.readFileSync(p+'/'+f,'utf8'))).filter(s=>['done','retrospective-done'].includes(s.status)).map(s=>s.sprintId); console.log(JSON.stringify(done));}catch(e){console.log('[]')}"
277
+ ```
278
+ 3. Get current date: `date -u +"%Y-%m-%d"`
279
+ 4. Get current plugin version: read `$FORGE_ROOT/.claude-plugin/plugin.json` → `version`
280
+
281
+ Update `$PROJECT_ROOT/.forge/config.json`:
282
+ 1. Replace `calibrationBaseline` with the newly computed values:
283
+ ```json
284
+ {
285
+ "lastCalibrated": "<ISO date>",
286
+ "version": "<plugin version>",
287
+ "masterIndexHash": "<new SHA-256 hash>",
288
+ "sprintsCovered": ["<sprint IDs>"]
289
+ }
290
+ ```
291
+ 2. Append the calibration run entry to the `calibrationHistory` array. If the
292
+ array does not exist yet, create it:
293
+
294
+ ```json
295
+ {
296
+ "calibrationHistory": [
297
+ {
298
+ "date": "<ISO date>",
299
+ "version": "<plugin version>",
300
+ "categories": ["technical", "business"],
301
+ "patches": [
302
+ {"target": "personas:engineer", "type": "regenerate", "applied": true},
303
+ {"target": "skills:supervisor-skills", "type": "regenerate", "applied": true},
304
+ {"target": "skills:engineer-skills", "type": "regenerate", "applied": false}
305
+ ]
306
+ }
307
+ ]
308
+ }
309
+ ```
310
+
311
+ Each patch entry records:
312
+ - `target`: the regeneration target (e.g. `personas:engineer`, `skills:supervisor-skills`)
313
+ - `type`: always `"regenerate"` (the only supported patch type)
314
+ - `applied`: `true` if the patch was approved and regeneration succeeded, `false` if skipped or failed
315
+
316
+ Write the updated config using the established pattern:
317
+ ```sh
318
+ cd "$PROJECT_ROOT" && node -e "
319
+ const fs = require('fs');
320
+ const cfgPath = '.forge/config.json';
321
+ const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
322
+ cfg.calibrationBaseline = { /* new values */ };
323
+ if (!cfg.calibrationHistory) cfg.calibrationHistory = [];
324
+ cfg.calibrationHistory.push({ /* new entry */ });
325
+ fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + '\n');
326
+ "
327
+ ```
328
+
329
+ Alternatively, use `node "$FORGE_ROOT/tools/manage-config.cjs" set` if available.
330
+
331
+ ## Step 9 — Summary
332
+
333
+ Emit the final summary:
334
+
335
+ ```
336
+ ## 〇 Calibration Complete
337
+
338
+ Patches applied: {N} of {M}
339
+ Regenerated: {list of successfully applied targets}
340
+ Baseline updated: {new lastCalibrated date}
341
+
342
+ ── Run /forge:health to verify knowledge base currency.
343
+ ```
344
+
345
+ If any patches failed, add:
346
+
347
+ ```
348
+ △ Failed patches: {list of failed targets}
349
+ ── Re-run /forge:calibrate or manually /forge:regenerate the failed targets.
350
+ ```
351
+
352
+ ## On error
353
+
354
+ If any step above fails unexpectedly, describe what went wrong and ask:
355
+
356
+ > "This looks like a Forge bug. Would you like to file a report to help improve it? Run `/forge:report-bug` — I'll pre-fill the report from this conversation."