@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.
- package/CHANGELOG.md +88 -0
- package/README.md +28 -1
- package/dist/bin/forge.js +20 -0
- package/dist/bin/forge.js.map +1 -1
- package/dist/extensions/forgecli/approve.d.ts +24 -0
- package/dist/extensions/forgecli/approve.js +202 -0
- package/dist/extensions/forgecli/approve.js.map +1 -0
- package/dist/extensions/forgecli/audience-gate.d.ts +4 -0
- package/dist/extensions/forgecli/audience-gate.js +8 -5
- package/dist/extensions/forgecli/audience-gate.js.map +1 -1
- package/dist/extensions/forgecli/collate.d.ts +24 -0
- package/dist/extensions/forgecli/collate.js +199 -0
- package/dist/extensions/forgecli/collate.js.map +1 -0
- package/dist/extensions/forgecli/commit.d.ts +24 -0
- package/dist/extensions/forgecli/commit.js +202 -0
- package/dist/extensions/forgecli/commit.js.map +1 -0
- package/dist/extensions/forgecli/fix-bug.d.ts +75 -0
- package/dist/extensions/forgecli/fix-bug.js +1133 -0
- package/dist/extensions/forgecli/fix-bug.js.map +1 -0
- package/dist/extensions/forgecli/forge-commands.js +7 -0
- package/dist/extensions/forgecli/forge-commands.js.map +1 -1
- package/dist/extensions/forgecli/forge-init.js +16 -8
- package/dist/extensions/forgecli/forge-init.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.d.ts +29 -0
- package/dist/extensions/forgecli/forge-subagent.js +14 -1
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/hook-dispatcher.d.ts +53 -1
- package/dist/extensions/forgecli/hook-dispatcher.js +47 -1
- package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
- package/dist/extensions/forgecli/hooks/post-init-hook.d.ts +15 -0
- package/dist/extensions/forgecli/hooks/post-init-hook.js +127 -0
- package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -0
- package/dist/extensions/forgecli/hooks/post-sprint-hook.d.ts +37 -0
- package/dist/extensions/forgecli/hooks/post-sprint-hook.js +166 -0
- package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -0
- package/dist/extensions/forgecli/index.js +47 -0
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/review-code.d.ts +24 -0
- package/dist/extensions/forgecli/review-code.js +202 -0
- package/dist/extensions/forgecli/review-code.js.map +1 -0
- package/dist/extensions/forgecli/review-plan.d.ts +24 -0
- package/dist/extensions/forgecli/review-plan.js +203 -0
- package/dist/extensions/forgecli/review-plan.js.map +1 -0
- package/dist/extensions/forgecli/run-sprint.d.ts +18 -0
- package/dist/extensions/forgecli/run-sprint.js +33 -1
- package/dist/extensions/forgecli/run-sprint.js.map +1 -1
- package/dist/extensions/forgecli/run-task.d.ts +21 -2
- package/dist/extensions/forgecli/run-task.js +33 -9
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/session-registry.d.ts +10 -0
- package/dist/extensions/forgecli/session-registry.js +9 -0
- package/dist/extensions/forgecli/session-registry.js.map +1 -1
- package/dist/extensions/forgecli/validate.d.ts +24 -0
- package/dist/extensions/forgecli/validate.js +202 -0
- package/dist/extensions/forgecli/validate.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/engine.d.ts +23 -0
- package/dist/extensions/forgecli/wf-engine/engine.js +384 -0
- package/dist/extensions/forgecli/wf-engine/engine.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/event-parser.d.ts +6 -0
- package/dist/extensions/forgecli/wf-engine/event-parser.js +29 -0
- package/dist/extensions/forgecli/wf-engine/event-parser.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/id-gen.d.ts +6 -0
- package/dist/extensions/forgecli/wf-engine/id-gen.js +17 -0
- package/dist/extensions/forgecli/wf-engine/id-gen.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/loader.d.ts +2 -0
- package/dist/extensions/forgecli/wf-engine/loader.js +100 -0
- package/dist/extensions/forgecli/wf-engine/loader.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/predicate.d.ts +7 -0
- package/dist/extensions/forgecli/wf-engine/predicate.js +36 -0
- package/dist/extensions/forgecli/wf-engine/predicate.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/prompt-compiler.d.ts +15 -0
- package/dist/extensions/forgecli/wf-engine/prompt-compiler.js +23 -0
- package/dist/extensions/forgecli/wf-engine/prompt-compiler.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/register.d.ts +9 -0
- package/dist/extensions/forgecli/wf-engine/register.js +59 -0
- package/dist/extensions/forgecli/wf-engine/register.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/remit-check.d.ts +6 -0
- package/dist/extensions/forgecli/wf-engine/remit-check.js +42 -0
- package/dist/extensions/forgecli/wf-engine/remit-check.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/state-store.d.ts +13 -0
- package/dist/extensions/forgecli/wf-engine/state-store.js +43 -0
- package/dist/extensions/forgecli/wf-engine/state-store.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/types.d.ts +66 -0
- package/dist/extensions/forgecli/wf-engine/types.js +2 -0
- package/dist/extensions/forgecli/wf-engine/types.js.map +1 -0
- package/dist/extensions/forgecli/wf-engine/worker.d.ts +11 -0
- package/dist/extensions/forgecli/wf-engine/worker.js +50 -0
- package/dist/extensions/forgecli/wf-engine/worker.js.map +1 -0
- package/dist/forge-payload/.base-pack/workflows/_fragments/context-injection.md +10 -4
- package/dist/forge-payload/.base-pack/workflows/fix_bug.md +12 -0
- package/dist/forge-payload/.schemas/bug.schema.json +4 -2
- package/dist/forge-payload/.schemas/event.schema.json +22 -3
- package/dist/forge-payload/commands/add-pipeline.md +342 -0
- package/dist/forge-payload/commands/add-task.md +269 -0
- package/dist/forge-payload/commands/ask.md +43 -0
- package/dist/forge-payload/commands/calibrate.md +356 -0
- package/dist/forge-payload/commands/config.md +202 -0
- package/dist/forge-payload/commands/enhance.md +38 -0
- package/dist/forge-payload/commands/health.md +225 -0
- package/dist/forge-payload/commands/init.md +165 -0
- package/dist/forge-payload/commands/materialize.md +119 -0
- package/dist/forge-payload/commands/migrate.md +160 -0
- package/dist/forge-payload/commands/quiz-agent.md +38 -0
- package/dist/forge-payload/commands/regenerate.md +673 -0
- package/dist/forge-payload/commands/remove.md +174 -0
- package/dist/forge-payload/commands/report-bug.md +191 -0
- package/dist/forge-payload/commands/store-query.md +73 -0
- package/dist/forge-payload/commands/store-repair.md +187 -0
- package/dist/forge-payload/commands/update-tools.md +56 -0
- package/dist/forge-payload/commands/update.md +1376 -0
- package/dist/forge-payload/tools/preflight-gate.cjs +2 -1
- package/dist/forge-payload/tools/read-verdict.cjs +41 -8
- package/dist/forge-payload/tools/store-cli.cjs +4 -3
- package/node_modules/argparse/CHANGELOG.md +216 -0
- package/node_modules/argparse/LICENSE +254 -0
- package/node_modules/argparse/README.md +84 -0
- package/node_modules/argparse/argparse.js +3707 -0
- package/node_modules/argparse/lib/sub.js +67 -0
- package/node_modules/argparse/lib/textwrap.js +440 -0
- package/node_modules/argparse/package.json +31 -0
- package/node_modules/cliui/CHANGELOG.md +121 -0
- package/node_modules/color-convert/CHANGELOG.md +54 -0
- package/node_modules/esprima/ChangeLog +235 -0
- package/node_modules/js-yaml/LICENSE +21 -0
- package/node_modules/js-yaml/README.md +247 -0
- package/node_modules/js-yaml/bin/js-yaml.js +126 -0
- package/node_modules/js-yaml/dist/js-yaml.js +3880 -0
- package/node_modules/js-yaml/dist/js-yaml.min.js +2 -0
- package/node_modules/js-yaml/dist/js-yaml.mjs +3856 -0
- package/node_modules/js-yaml/index.js +47 -0
- package/node_modules/js-yaml/lib/common.js +59 -0
- package/node_modules/js-yaml/lib/dumper.js +965 -0
- package/node_modules/js-yaml/lib/exception.js +55 -0
- package/node_modules/js-yaml/lib/loader.js +1733 -0
- package/node_modules/js-yaml/lib/schema/core.js +11 -0
- package/node_modules/js-yaml/lib/schema/default.js +22 -0
- package/node_modules/js-yaml/lib/schema/failsafe.js +17 -0
- package/node_modules/js-yaml/lib/schema/json.js +19 -0
- package/node_modules/js-yaml/lib/schema.js +121 -0
- package/node_modules/js-yaml/lib/snippet.js +101 -0
- package/node_modules/js-yaml/lib/type/binary.js +125 -0
- package/node_modules/js-yaml/lib/type/bool.js +35 -0
- package/node_modules/js-yaml/lib/type/float.js +97 -0
- package/node_modules/js-yaml/lib/type/int.js +156 -0
- package/node_modules/js-yaml/lib/type/map.js +8 -0
- package/node_modules/js-yaml/lib/type/merge.js +12 -0
- package/node_modules/js-yaml/lib/type/null.js +35 -0
- package/node_modules/js-yaml/lib/type/omap.js +44 -0
- package/node_modules/js-yaml/lib/type/pairs.js +53 -0
- package/node_modules/js-yaml/lib/type/seq.js +8 -0
- package/node_modules/js-yaml/lib/type/set.js +29 -0
- package/node_modules/js-yaml/lib/type/str.js +8 -0
- package/node_modules/js-yaml/lib/type/timestamp.js +88 -0
- package/node_modules/js-yaml/lib/type.js +66 -0
- package/node_modules/js-yaml/package.json +66 -0
- package/node_modules/mz/HISTORY.md +66 -0
- package/node_modules/proper-lockfile/CHANGELOG.md +108 -0
- package/node_modules/source-map/CHANGELOG.md +301 -0
- package/node_modules/thenify/History.md +11 -0
- package/node_modules/thenify-all/History.md +11 -0
- package/node_modules/y18n/CHANGELOG.md +100 -0
- package/node_modules/yargs/CHANGELOG.md +88 -0
- package/node_modules/yargs-parser/CHANGELOG.md +263 -0
- package/package.json +6 -2
- package/workflows/lead-qualifier/prompts/digest.md +44 -0
- package/workflows/lead-qualifier/prompts/draft-outreach.md +44 -0
- package/workflows/lead-qualifier/prompts/enrich.md +52 -0
- package/workflows/lead-qualifier/prompts/intake.md +48 -0
- package/workflows/lead-qualifier/prompts/mark-cold.md +38 -0
- package/workflows/lead-qualifier/prompts/score.md +45 -0
- package/workflows/lead-qualifier/workflow.yaml +95 -0
- package/workflows/research-brief/prompts/brief-synthesize.md +43 -0
- package/workflows/research-brief/prompts/intake.md +51 -0
- package/workflows/research-brief/prompts/source-critique.md +38 -0
- package/workflows/research-brief/prompts/source-score.md +38 -0
- package/workflows/research-brief/prompts/source-summarize.md +54 -0
- package/workflows/research-brief/workflow.yaml +66 -0
- package/dist/extensions/forgecli/session-monitor-widget.d.ts +0 -37
- package/dist/extensions/forgecli/session-monitor-widget.js +0 -320
- package/dist/extensions/forgecli/session-monitor-widget.js.map +0 -1
- package/dist/extensions/forgecli/session-monitor.d.ts +0 -2
- package/dist/extensions/forgecli/session-monitor.js +0 -135
- 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."
|