@entelligentsia/forgecli 0.10.0 → 0.11.2

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 (188) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/README.md +21 -3
  3. package/dist/CHANGELOG-forge-plugin.md +90 -0
  4. package/dist/bin/config.js +6 -0
  5. package/dist/bin/config.js.map +1 -1
  6. package/dist/extensions/forgecli/add-pipeline.d.ts +19 -0
  7. package/dist/extensions/forgecli/add-pipeline.js +143 -0
  8. package/dist/extensions/forgecli/add-pipeline.js.map +1 -0
  9. package/dist/extensions/forgecli/add-task.d.ts +20 -0
  10. package/dist/extensions/forgecli/add-task.js +154 -0
  11. package/dist/extensions/forgecli/add-task.js.map +1 -0
  12. package/dist/extensions/forgecli/calibrate.d.ts +61 -0
  13. package/dist/extensions/forgecli/calibrate.js +488 -0
  14. package/dist/extensions/forgecli/calibrate.js.map +1 -0
  15. package/dist/extensions/forgecli/fix-bug.d.ts +9 -1
  16. package/dist/extensions/forgecli/fix-bug.js +155 -45
  17. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  18. package/dist/extensions/forgecli/forge-commands.js +15 -22
  19. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  20. package/dist/extensions/forgecli/forge-subagent.d.ts +16 -1
  21. package/dist/extensions/forgecli/forge-subagent.js +45 -8
  22. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  23. package/dist/extensions/forgecli/forge-update-command.d.ts +9 -0
  24. package/dist/extensions/forgecli/forge-update-command.js +106 -7
  25. package/dist/extensions/forgecli/forge-update-command.js.map +1 -1
  26. package/dist/extensions/forgecli/health-check.d.ts +22 -1
  27. package/dist/extensions/forgecli/health-check.js +177 -4
  28. package/dist/extensions/forgecli/health-check.js.map +1 -1
  29. package/dist/extensions/forgecli/hook-dispatcher.d.ts +25 -1
  30. package/dist/extensions/forgecli/hook-dispatcher.js +104 -9
  31. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  32. package/dist/extensions/forgecli/hooks/check-update.d.ts +81 -0
  33. package/dist/extensions/forgecli/hooks/check-update.js +308 -0
  34. package/dist/extensions/forgecli/hooks/check-update.js.map +1 -0
  35. package/dist/extensions/forgecli/hooks/forge-permissions.d.ts +32 -0
  36. package/dist/extensions/forgecli/hooks/forge-permissions.js +119 -0
  37. package/dist/extensions/forgecli/hooks/forge-permissions.js.map +1 -0
  38. package/dist/extensions/forgecli/hooks/triage-error.d.ts +23 -0
  39. package/dist/extensions/forgecli/hooks/triage-error.js +62 -0
  40. package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -0
  41. package/dist/extensions/forgecli/hooks/write-guard.d.ts +28 -0
  42. package/dist/extensions/forgecli/hooks/write-guard.js +225 -0
  43. package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -0
  44. package/dist/extensions/forgecli/index.js +60 -0
  45. package/dist/extensions/forgecli/index.js.map +1 -1
  46. package/dist/extensions/forgecli/init-context.d.ts +1 -1
  47. package/dist/extensions/forgecli/init-context.js +21 -6
  48. package/dist/extensions/forgecli/init-context.js.map +1 -1
  49. package/dist/extensions/forgecli/materialize.d.ts +16 -0
  50. package/dist/extensions/forgecli/materialize.js +195 -0
  51. package/dist/extensions/forgecli/materialize.js.map +1 -0
  52. package/dist/extensions/forgecli/migrate.d.ts +19 -0
  53. package/dist/extensions/forgecli/migrate.js +258 -0
  54. package/dist/extensions/forgecli/migrate.js.map +1 -0
  55. package/dist/extensions/forgecli/migration-engine.d.ts +111 -0
  56. package/dist/extensions/forgecli/migration-engine.js +533 -0
  57. package/dist/extensions/forgecli/migration-engine.js.map +1 -0
  58. package/dist/extensions/forgecli/quiz-agent.d.ts +17 -0
  59. package/dist/extensions/forgecli/quiz-agent.js +98 -0
  60. package/dist/extensions/forgecli/quiz-agent.js.map +1 -0
  61. package/dist/extensions/forgecli/remove-command.d.ts +17 -0
  62. package/dist/extensions/forgecli/remove-command.js +124 -0
  63. package/dist/extensions/forgecli/remove-command.js.map +1 -0
  64. package/dist/extensions/forgecli/report-bug.d.ts +25 -0
  65. package/dist/extensions/forgecli/report-bug.js +159 -0
  66. package/dist/extensions/forgecli/report-bug.js.map +1 -0
  67. package/dist/extensions/forgecli/retrospective.d.ts +19 -0
  68. package/dist/extensions/forgecli/retrospective.js +156 -0
  69. package/dist/extensions/forgecli/retrospective.js.map +1 -0
  70. package/dist/extensions/forgecli/run-sprint.js +36 -3
  71. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  72. package/dist/extensions/forgecli/run-task.d.ts +9 -1
  73. package/dist/extensions/forgecli/run-task.js +66 -13
  74. package/dist/extensions/forgecli/run-task.js.map +1 -1
  75. package/dist/extensions/forgecli/session-registry.d.ts +40 -2
  76. package/dist/extensions/forgecli/session-registry.js +71 -1
  77. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  78. package/dist/extensions/forgecli/status-command.d.ts +19 -0
  79. package/dist/extensions/forgecli/status-command.js +140 -0
  80. package/dist/extensions/forgecli/status-command.js.map +1 -0
  81. package/dist/extensions/forgecli/store-query.d.ts +22 -0
  82. package/dist/extensions/forgecli/store-query.js +107 -0
  83. package/dist/extensions/forgecli/store-query.js.map +1 -0
  84. package/dist/extensions/forgecli/store-repair.d.ts +17 -0
  85. package/dist/extensions/forgecli/store-repair.js +123 -0
  86. package/dist/extensions/forgecli/store-repair.js.map +1 -0
  87. package/dist/extensions/forgecli/test-orchestrate.js +1 -0
  88. package/dist/extensions/forgecli/test-orchestrate.js.map +1 -1
  89. package/dist/extensions/forgecli/thread-switcher.js +286 -41
  90. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  91. package/dist/extensions/forgecli/transition-guard.js +7 -2
  92. package/dist/extensions/forgecli/transition-guard.js.map +1 -1
  93. package/dist/extensions/forgecli/update-tools.d.ts +23 -0
  94. package/dist/extensions/forgecli/update-tools.js +136 -0
  95. package/dist/extensions/forgecli/update-tools.js.map +1 -0
  96. package/dist/extensions/forgecli/viewport-events.js +10 -0
  97. package/dist/extensions/forgecli/viewport-events.js.map +1 -1
  98. package/dist/extensions/forgecli/viewport-renderer.d.ts +18 -0
  99. package/dist/extensions/forgecli/viewport-renderer.js +27 -0
  100. package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
  101. package/dist/extensions/forgecli/viewport-theme.js +4 -0
  102. package/dist/extensions/forgecli/viewport-theme.js.map +1 -1
  103. package/dist/extensions/forgecli/whats-new-widget.d.ts +13 -8
  104. package/dist/extensions/forgecli/whats-new-widget.js +111 -42
  105. package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
  106. package/dist/forge-payload/.base-pack/workflows/architect_approve.md +29 -3
  107. package/dist/forge-payload/.base-pack/workflows/commit_task.md +15 -8
  108. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +327 -185
  109. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +18 -10
  110. package/dist/forge-payload/.base-pack/workflows/plan_task.md +15 -9
  111. package/dist/forge-payload/.base-pack/workflows/review_code.md +14 -6
  112. package/dist/forge-payload/.base-pack/workflows/review_plan.md +18 -10
  113. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  114. package/dist/forge-payload/.schemas/bug.schema.json +3 -2
  115. package/dist/forge-payload/.schemas/config.schema.json +83 -0
  116. package/dist/forge-payload/.schemas/migrations.json +2049 -0
  117. package/dist/forge-payload/commands/regenerate.md +17 -1
  118. package/dist/forge-payload/meta/personas/README.md +16 -0
  119. package/dist/forge-payload/meta/personas/meta-architect.md +70 -0
  120. package/dist/forge-payload/meta/personas/meta-bug-fixer.md +73 -0
  121. package/dist/forge-payload/meta/personas/meta-collator.md +72 -0
  122. package/dist/forge-payload/meta/personas/meta-engineer.md +70 -0
  123. package/dist/forge-payload/meta/personas/meta-orchestrator.md +71 -0
  124. package/dist/forge-payload/meta/personas/meta-product-manager.md +82 -0
  125. package/dist/forge-payload/meta/personas/meta-qa-engineer.md +91 -0
  126. package/dist/forge-payload/meta/personas/meta-supervisor.md +92 -0
  127. package/dist/forge-payload/meta/skill-recommendations.md +154 -0
  128. package/dist/forge-payload/meta/skills/meta-architect-skills.md +43 -0
  129. package/dist/forge-payload/meta/skills/meta-bug-fixer-skills.md +43 -0
  130. package/dist/forge-payload/meta/skills/meta-collator-skills.md +41 -0
  131. package/dist/forge-payload/meta/skills/meta-engineer-skills.md +43 -0
  132. package/dist/forge-payload/meta/skills/meta-generic-skills.md +58 -0
  133. package/dist/forge-payload/meta/skills/meta-qa-engineer-skills.md +46 -0
  134. package/dist/forge-payload/meta/skills/meta-supervisor-skills.md +43 -0
  135. package/dist/forge-payload/meta/store-schema/bug.schema.md +71 -0
  136. package/dist/forge-payload/meta/store-schema/event.schema.md +76 -0
  137. package/dist/forge-payload/meta/store-schema/feature.schema.md +65 -0
  138. package/dist/forge-payload/meta/store-schema/sprint.schema.md +64 -0
  139. package/dist/forge-payload/meta/store-schema/task.schema.md +78 -0
  140. package/dist/forge-payload/meta/templates/meta-code-review.md +26 -0
  141. package/dist/forge-payload/meta/templates/meta-plan-review.md +28 -0
  142. package/dist/forge-payload/meta/templates/meta-plan.md +28 -0
  143. package/dist/forge-payload/meta/templates/meta-progress.md +25 -0
  144. package/dist/forge-payload/meta/templates/meta-retrospective.md +28 -0
  145. package/dist/forge-payload/meta/templates/meta-sprint-manifest.md +26 -0
  146. package/dist/forge-payload/meta/templates/meta-sprint-requirements.md +91 -0
  147. package/dist/forge-payload/meta/templates/meta-task-prompt.md +26 -0
  148. package/dist/forge-payload/meta/tool-specs/collate.spec.md +88 -0
  149. package/dist/forge-payload/meta/tool-specs/generation-manifest.spec.md +139 -0
  150. package/dist/forge-payload/meta/tool-specs/manage-config.spec.md +143 -0
  151. package/dist/forge-payload/meta/tool-specs/seed-store.spec.md +91 -0
  152. package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +328 -0
  153. package/dist/forge-payload/meta/tool-specs/validate-store.spec.md +191 -0
  154. package/dist/forge-payload/meta/workflows/_fragments/context-injection.md +75 -0
  155. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +73 -0
  156. package/dist/forge-payload/meta/workflows/_fragments/finalize.md +13 -0
  157. package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +73 -0
  158. package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +38 -0
  159. package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +39 -0
  160. package/dist/forge-payload/meta/workflows/meta-approve.md +119 -0
  161. package/dist/forge-payload/meta/workflows/meta-collate.md +89 -0
  162. package/dist/forge-payload/meta/workflows/meta-commit.md +93 -0
  163. package/dist/forge-payload/meta/workflows/meta-enhance.md +286 -0
  164. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +501 -0
  165. package/dist/forge-payload/meta/workflows/meta-implement.md +132 -0
  166. package/dist/forge-payload/meta/workflows/meta-migrate.md +455 -0
  167. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +993 -0
  168. package/dist/forge-payload/meta/workflows/meta-plan-task.md +133 -0
  169. package/dist/forge-payload/meta/workflows/meta-quiz-agent.md +135 -0
  170. package/dist/forge-payload/meta/workflows/meta-retrospective.md +65 -0
  171. package/dist/forge-payload/meta/workflows/meta-review-implementation.md +119 -0
  172. package/dist/forge-payload/meta/workflows/meta-review-plan.md +108 -0
  173. package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +65 -0
  174. package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +76 -0
  175. package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +147 -0
  176. package/dist/forge-payload/meta/workflows/meta-update-implementation.md +76 -0
  177. package/dist/forge-payload/meta/workflows/meta-update-plan.md +76 -0
  178. package/dist/forge-payload/meta/workflows/meta-validate.md +111 -0
  179. package/dist/forge-payload/tools/check-structure.cjs +344 -0
  180. package/dist/forge-payload/tools/collate.cjs +34 -9
  181. package/dist/forge-payload/tools/list-skills.js +76 -0
  182. package/dist/forge-payload/tools/parse-gates.cjs +8 -2
  183. package/dist/forge-payload/tools/store-cli.cjs +56 -11
  184. package/dist/forge-payload/tools/store.cjs +61 -0
  185. package/dist/forge-payload/tools/substitute-placeholders.cjs +60 -8
  186. package/dist/forge-payload/tools/validate-store.cjs +6 -2
  187. package/dist/forge-payload/tools/verify-integrity.cjs +86 -0
  188. package/package.json +2 -2
@@ -0,0 +1,455 @@
1
+ ---
2
+ requirements:
3
+ reasoning: High
4
+ context: High
5
+ speed: Low
6
+ audience: orchestrator-only
7
+ deps:
8
+ personas: [engineer]
9
+ skills: [engineer, generic]
10
+ templates: []
11
+ sub_workflows: []
12
+ kb_docs: []
13
+ config_fields: [paths.engineering]
14
+ ---
15
+
16
+ # Meta-Workflow: Structural Migration (v0.x → v0.40)
17
+
18
+ ## Purpose
19
+
20
+ Translate a prose-heavy v0.x `.forge/` instance into the v0.40 format:
21
+ `project-context.json` (T02 schema) + clean base-pack substitution (T03) +
22
+ `structure-versions.json` snapshot tracking (T05). Every operation is
23
+ reversible, guarded by user confirmation, and idempotent on re-run.
24
+
25
+ **Trigger:** Invoked by `/forge:migrate` when the user passes `--structural`
26
+ or when `.forge/structure-versions.json` is absent (pre-T05 install detected).
27
+
28
+ **Scope:** v0.x → v0.40 only. Installs older than v0.x should use
29
+ `/forge:health` → `/forge:update` to reach a supported baseline first.
30
+
31
+ ---
32
+
33
+ ## Pre-conditions
34
+
35
+ - `/forge:init` has run: `.forge/config.json` exists and is readable.
36
+ - `.forge/structure-versions.json` is absent OR `--structural` was passed.
37
+ - The Forge plugin root is resolvable:
38
+ ```sh
39
+ export FORGE_ROOT=$(node -e "console.log(require('./.forge/config.json').paths.forgeRoot)")
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Algorithm
45
+
46
+ ### Phase 0 — Pre-flight
47
+
48
+ **0a. Verify init has completed.**
49
+
50
+ Check that `.forge/config.json` exists. If it does not, stop:
51
+
52
+ > "Forge has not been initialised in this project. Run `/forge:init` first."
53
+
54
+ Read `FORGE_ROOT` from `.forge/config.json`.
55
+
56
+ **0b. Detect install generation.**
57
+
58
+ ```sh
59
+ ls .forge/structure-versions.json 2>/dev/null && echo "EXISTS" || echo "ABSENT"
60
+ ```
61
+
62
+ - If `structure-versions.json` EXISTS: this is a post-T05 install. Warn the
63
+ user that structural migration is not needed and offer to run the standard
64
+ store-schema migration (Steps 1–7 of `/forge:migrate`) instead. Stop.
65
+ - If ABSENT: proceed (pre-T05 install confirmed).
66
+
67
+ **0c. Check for in-progress sentinel (idempotency).**
68
+
69
+ ```sh
70
+ ls .forge/archive/pre-migration/.migration-in-progress 2>/dev/null && echo "FOUND" || echo "NOT_FOUND"
71
+ ```
72
+
73
+ If FOUND:
74
+
75
+ - Check if a draft `project-context.json` already exists AND is valid JSON:
76
+ ```sh
77
+ node -e "JSON.parse(require('fs').readFileSync('.forge/project-context.json','utf8')); console.log('VALID');" 2>/dev/null || echo "INVALID_OR_ABSENT"
78
+ ```
79
+ - Resume heuristic: sentinel exists AND `.forge/project-context.json` exists AND
80
+ validates against the schema → offer resume (ask user: "A previous migration
81
+ was interrupted. A draft project-context.json already exists. Resume from
82
+ Phase 2 (confirm and write)? [Y/n/restart]"). If user chooses restart, remove
83
+ the sentinel file and continue as a fresh run.
84
+ - Otherwise (no valid draft): offer fresh restart.
85
+
86
+ **0d. Create sentinel directory FIRST, then write sentinel file.**
87
+
88
+ ORDER IS MANDATORY — writing the file before the directory fails:
89
+
90
+ ```sh
91
+ mkdir -p .forge/archive/pre-migration/
92
+ echo "in-progress" > .forge/archive/pre-migration/.migration-in-progress
93
+ ```
94
+
95
+ Record the migration start timestamp:
96
+ ```sh
97
+ MIGRATION_START=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
98
+ ```
99
+
100
+ ---
101
+
102
+ ### Phase 1 — Read and Extract
103
+
104
+ Read all existing `.forge/` artifacts in five categories and extract
105
+ project-specific content. Generic boilerplate lines (role definitions,
106
+ algorithm steps, universal Iron Laws) are skipped.
107
+
108
+ **Security note:** All extracted strings are copied verbatim into
109
+ `project-context.json` field values. They are never executed or evaluated.
110
+ Downstream T03 substitution (`substitute-placeholders.cjs`) treats all values
111
+ as opaque text strings and only replaces the canonical `REQUIRED_KEYS` +
112
+ `RUNTIME_PASSTHROUGH_KEYS` placeholder set. No arbitrary code paths are opened
113
+ by the extracted content.
114
+
115
+ #### Extraction categories
116
+
117
+ | Category | Files | Extraction targets |
118
+ |---|---|---|
119
+ | Config | `.forge/config.json` | All fields — direct mapping (highest confidence) |
120
+ | Personas | `.forge/personas/*.md` | Project name, prefix, KB path, impact categories, entity refs, skill directives |
121
+ | Skills | `.forge/skills/*.md` (esp. engineer, architect) | Stack summary, key directories, commands, technical debt, verification commands |
122
+ | Workflows | `.forge/workflows/*.md` | Project prefix occurrences, task ID format, branching convention, deployment environments |
123
+ | Templates | `.forge/templates/*.md` | Hardcoded project-specific values (task ID format, prefix, paths) |
124
+
125
+ #### Extraction rules
126
+
127
+ - **Config fields** → direct mapping to `project-context.json` (highest confidence).
128
+ - **`PROJECT_NAME`, `PREFIX` patterns** in persona/skill files → extract by pattern.
129
+ - **`{{KEY}}` tokens that survived substitution** → attempt to fill from KB; if
130
+ not resolvable, flag for user review.
131
+ - **Specific project paths, entity names, stack references** → extract with moderate confidence.
132
+ - **Generic boilerplate** (role definitions, algorithm steps, universal rules) → skip.
133
+
134
+ #### Target `project-context.json` fields (19 string-leaf fields)
135
+
136
+ These are the 19 scalar string leaves of `project-context.schema.json` that
137
+ count toward the ≥80% (≥15 of 19) population threshold:
138
+
139
+ 1. `project.name`
140
+ 2. `project.prefix`
141
+ 3. `project.description`
142
+ 4. `project.commands.test`
143
+ 5. `project.commands.build`
144
+ 6. `project.commands.deploy`
145
+ 7. `architecture.frameworks.backend`
146
+ 8. `architecture.frameworks.frontend`
147
+ 9. `architecture.frameworks.database`
148
+ 10. `architecture.dataAccess`
149
+ 11. `architecture.deployment`
150
+ 12. `conventions.branching`
151
+ 13. `conventions.taskIdFormat`
152
+ 14. `deployment.impactNotes`
153
+ 15. `verification.typeCheck`
154
+ 16. `verification.lint`
155
+ 17. `verification.test`
156
+ 18. `verification.build`
157
+ 19. `verification.infraBuild`
158
+
159
+ #### No-data-loss guarantee
160
+
161
+ Any project-specific fact that cannot be confidently mapped to a
162
+ `project-context.json` field MUST be written to
163
+ `.forge/archive/pre-migration/MIGRATION_NOTES.md` for manual review. It must
164
+ never be silently dropped.
165
+
166
+ Format for each item in `MIGRATION_NOTES.md`:
167
+ ```
168
+ ## Unresolved: <short description>
169
+ Source: <file>:<line range>
170
+ Extracted: <verbatim text>
171
+ Suggested mapping: <field name or "none — needs manual review">
172
+ ```
173
+
174
+ Also document in `MIGRATION_NOTES.md`:
175
+ - The old plugin version detection result: if a `version` field was found in any
176
+ `.forge/store/sprints/*.json` record, record it as
177
+ `"derived-from-sprint-updated-<date>"`. Otherwise record `"unknown-pre-v0.40"`.
178
+ This provides an audit trace for future reviews.
179
+ - Note: the plugin version in `$FORGE_ROOT/.claude-plugin/plugin.json` reflects
180
+ the *new* installed plugin version and is NOT used to determine the pre-migration
181
+ version.
182
+
183
+ Produce a draft `project-context.json` covering all extractable T02 fields.
184
+ Fields that cannot be confidently populated are left at their schema defaults.
185
+
186
+ ---
187
+
188
+ ### Phase 2 — Synthesise and Show (Confirmation Gate)
189
+
190
+ Display the synthesised `project-context.json` to the user. Show:
191
+
192
+ 1. The full JSON content (or a diff from schema defaults if large).
193
+ 2. A summary line:
194
+ ```
195
+ String fields populated: N / 19
196
+ Items needing review: K (see MIGRATION_NOTES.md)
197
+ ```
198
+ 3. The archive plan:
199
+ ```
200
+ Files to archive: N (to .forge/archive/pre-migration/)
201
+ ```
202
+ 4. The substitution plan:
203
+ ```
204
+ Files to write: N (new .forge/personas/, .forge/skills/, .forge/workflows/, .forge/templates/)
205
+ ```
206
+
207
+ Prompt for explicit confirmation:
208
+ ```
209
+ Migration plan ready.
210
+ String fields populated: N / 19
211
+ Items needing review: K (see MIGRATION_NOTES.md)
212
+ Files to archive: N
213
+ Files to write: N
214
+
215
+ Proceed with migration? [Y/n]
216
+ ```
217
+
218
+ **If user declines:**
219
+ ```sh
220
+ rm .forge/archive/pre-migration/.migration-in-progress
221
+ # Remove sentinel dir only if it is now empty
222
+ rmdir .forge/archive/pre-migration/ 2>/dev/null || true
223
+ ```
224
+ Exit cleanly with the message: "Migration cancelled. No changes made."
225
+
226
+ **If user accepts:** proceed to Phase 3.
227
+
228
+ ---
229
+
230
+ ### Phase 3 — Write (archive → substitute → register)
231
+
232
+ #### Step 3a — Archive
233
+
234
+ Note: `.forge/archive/pre-migration/` was already created in Phase 0 (sentinel
235
+ setup). The `mkdir -p` below is idempotent.
236
+
237
+ ```sh
238
+ mkdir -p .forge/archive/pre-migration/
239
+ ```
240
+
241
+ Copy every file from `.forge/` (excluding `.forge/store/` and `.forge/archive/`
242
+ themselves) to `.forge/archive/pre-migration/`. Preserve directory structure.
243
+ Example:
244
+ ```sh
245
+ # List files to archive (excluding store/ and archive/ subtrees)
246
+ find .forge/ -not -path '.forge/store/*' -not -path '.forge/archive/*' -type f
247
+ ```
248
+
249
+ For each file found, copy it to `.forge/archive/pre-migration/<relative-path>`,
250
+ creating intermediate directories as needed.
251
+
252
+ Write an md5 manifest:
253
+ ```sh
254
+ find .forge/archive/pre-migration/ -not -name 'MANIFEST.md5' -not -name '.migration-in-progress' -type f \
255
+ | sort | xargs md5sum > .forge/archive/pre-migration/MANIFEST.md5
256
+ ```
257
+
258
+ Verify manifest completeness: re-read the directory list and confirm every
259
+ archived file (excluding `MANIFEST.md5` itself and `.migration-in-progress`)
260
+ has an entry in `MANIFEST.md5`. If any file is missing, add it and report the
261
+ discrepancy to the user.
262
+
263
+ #### Step 3b — Write `project-context.json`
264
+
265
+ Write `.forge/project-context.json` with the synthesised content.
266
+
267
+ Validate via the store tool:
268
+ ```sh
269
+ export FORGE_ROOT
270
+ node "$FORGE_ROOT/tools/validate-store.cjs" --dry-run
271
+ ```
272
+
273
+ If this exits non-zero, report the validation errors to the user and HALT. Do
274
+ NOT remove the sentinel — the user can fix the issue and re-run.
275
+
276
+ #### Step 3c — Substitute (T03)
277
+
278
+ ```sh
279
+ export FORGE_ROOT
280
+ node "$FORGE_ROOT/tools/substitute-placeholders.cjs" \
281
+ --forge-root "$FORGE_ROOT" \
282
+ --base-pack "$FORGE_ROOT/init/base-pack" \
283
+ --config ".forge/config.json" \
284
+ --context ".forge/project-context.json" \
285
+ --out "."
286
+ ```
287
+
288
+ This overwrites `.forge/personas/`, `.forge/skills/`, `.forge/workflows/`,
289
+ `.forge/templates/`, and `.claude/commands/forge/` with the freshly substituted
290
+ base-pack.
291
+
292
+ If `substitute-placeholders.cjs` exits non-zero: halt, report the error to the
293
+ user. Do NOT remove the sentinel (preserves ability to re-run after fixing).
294
+
295
+ #### Step 3d — Register snapshot (T05)
296
+
297
+ ```sh
298
+ export FORGE_ROOT
299
+ node "$FORGE_ROOT/tools/manage-versions.cjs" init
300
+ ```
301
+
302
+ `manage-versions init` is idempotent. Since `.forge/structure-versions.json`
303
+ does not exist yet, this writes snapshot 0 with `source: "base-pack"` and
304
+ `createdAt` set to the current time.
305
+
306
+ After `init` completes, read the written file and patch snapshot 0:
307
+
308
+ 1. Set `source` → `"migration-from-v{old}"` where `{old}` is the old plugin
309
+ version determined in Phase 1 (defaults to `"unknown-pre-v0.40"`).
310
+ The `source` field is `type: string` with no enum constraint — this free-form
311
+ value is valid per schema.
312
+ 2. Set `createdAt` of snapshot 0 → `$MIGRATION_START` (the timestamp recorded in
313
+ Phase 0d). This ensures snapshot 0 reflects the conceptual moment of
314
+ migration, not the `manage-versions init` run time.
315
+
316
+ Example patch (using Node.js):
317
+ ```sh
318
+ node -e "
319
+ const fs = require('fs');
320
+ const sv = JSON.parse(fs.readFileSync('.forge/structure-versions.json','utf8'));
321
+ if (sv.snapshots && sv.snapshots.length > 0) {
322
+ sv.snapshots[0].source = 'migration-from-v{old}';
323
+ sv.snapshots[0].createdAt = process.env.MIGRATION_START;
324
+ }
325
+ fs.writeFileSync('.forge/structure-versions.json', JSON.stringify(sv, null, 2) + '\n');
326
+ console.log('Patched snapshot 0');
327
+ " MIGRATION_START="$MIGRATION_START"
328
+ ```
329
+
330
+ #### Step 3e — Cleanup sentinel
331
+
332
+ ```sh
333
+ rm .forge/archive/pre-migration/.migration-in-progress
334
+ ```
335
+
336
+ ---
337
+
338
+ ### Phase 4 — Verify and Emit
339
+
340
+ **Verification (CLI-accessible only — do NOT invoke `/forge:health` here):**
341
+
342
+ ```sh
343
+ export FORGE_ROOT
344
+ # 1. Validate the store
345
+ node "$FORGE_ROOT/tools/validate-store.cjs" --dry-run
346
+
347
+ # 2. Verify substitution outputs are non-empty
348
+ ls .forge/personas/*.md .forge/skills/*.md .forge/workflows/*.md .forge/templates/*.md
349
+
350
+ # 3. Verify project-context.json exists and is valid JSON
351
+ node -e "JSON.parse(require('fs').readFileSync('.forge/project-context.json','utf8')); console.log('project-context.json OK');"
352
+ ```
353
+
354
+ Report findings to the user.
355
+
356
+ Tell the user: "Run `/forge:health` after migration completes to check overall
357
+ knowledge base status."
358
+
359
+ **Event emission — canonical schema compliant:**
360
+
361
+ Determine the sprint ID for the event. Look up the first sprint record in the
362
+ store:
363
+ ```sh
364
+ ls .forge/store/sprints/*.json 2>/dev/null | sort | head -n1
365
+ ```
366
+
367
+ Read that file and extract the `sprintId` field. If no sprint files exist, use
368
+ `"migration"` as the `sprintId` placeholder.
369
+
370
+ ```sh
371
+ export FORGE_ROOT
372
+ MIGRATION_END=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
373
+ node "$FORGE_ROOT/tools/store-cli.cjs" emit "{projectSprintId}" '{
374
+ "eventId": "migration-'"$(date -u +%Y%m%dT%H%M%SZ)"'",
375
+ "taskId": "migration",
376
+ "sprintId": "{projectSprintId}",
377
+ "role": "migration-agent",
378
+ "action": "migration-completed",
379
+ "phase": "write",
380
+ "iteration": 1,
381
+ "startTimestamp": "'"$MIGRATION_START"'",
382
+ "endTimestamp": "'"$MIGRATION_END"'",
383
+ "durationMinutes": {elapsed},
384
+ "model": "{current-model}",
385
+ "notes": "{\"source\":\"migration-from-v{old}\",\"archivePath\":\".forge/archive/pre-migration/\",\"projectContextPath\":\".forge/project-context.json\"}"
386
+ }'
387
+ ```
388
+
389
+ If `store-cli.cjs emit` exits non-zero, report the error but do NOT block
390
+ migration completion — the event is diagnostic metadata, not a prerequisite for
391
+ a working `.forge/` install.
392
+
393
+ **Report completion summary:**
394
+
395
+ ```
396
+ Structural migration complete.
397
+
398
+ project-context.json: .forge/project-context.json (N / 19 string fields populated)
399
+ Archive: .forge/archive/pre-migration/ (N files, MANIFEST.md5 included)
400
+ Structure snapshot: .forge/structure-versions.json (source: migration-from-v{old})
401
+ Review items: K items in .forge/archive/pre-migration/MIGRATION_NOTES.md
402
+
403
+ Next steps:
404
+ 1. Run /forge:health to verify the knowledge base.
405
+ 2. Review MIGRATION_NOTES.md for any extractions requiring manual attention.
406
+ 3. If something looks wrong, use the rollback procedure below.
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Rollback Procedure
412
+
413
+ The archive at `.forge/archive/pre-migration/` contains the complete pre-migration
414
+ state. To restore:
415
+
416
+ ```sh
417
+ # Step 1 — Remove the migrated outputs
418
+ rm -rf .forge/personas .forge/skills .forge/workflows .forge/templates
419
+ rm -f .forge/project-context.json .forge/structure-versions.json
420
+
421
+ # Step 2 — Restore from archive
422
+ cp -r .forge/archive/pre-migration/personas .forge/personas 2>/dev/null || true
423
+ cp -r .forge/archive/pre-migration/skills .forge/skills 2>/dev/null || true
424
+ cp -r .forge/archive/pre-migration/workflows .forge/workflows 2>/dev/null || true
425
+ cp -r .forge/archive/pre-migration/templates .forge/templates 2>/dev/null || true
426
+ cp .forge/archive/pre-migration/project-context.json .forge/project-context.json 2>/dev/null || true
427
+
428
+ # Step 3 — Verify restoration
429
+ ls .forge/personas/*.md .forge/skills/*.md .forge/workflows/*.md .forge/templates/*.md
430
+
431
+ # Step 4 (optional) — Keep archive for audit, or remove it
432
+ # rm -rf .forge/archive/pre-migration/
433
+ ```
434
+
435
+ To verify the restored files match the originals, compare against `MANIFEST.md5`:
436
+ ```sh
437
+ cd .forge && md5sum -c archive/pre-migration/MANIFEST.md5 2>/dev/null | grep -v OK || echo "All files match"
438
+ ```
439
+
440
+ ---
441
+
442
+ ## Error Handling
443
+
444
+ | Situation | Action |
445
+ |---|---|
446
+ | `.forge/config.json` missing | Stop. Tell user to run `/forge:init` first. |
447
+ | `structure-versions.json` already exists | Stop. Structural migration not needed for post-T05 installs. |
448
+ | Sentinel found + valid draft exists | Offer resume from Phase 2 or fresh restart. |
449
+ | Sentinel found + no valid draft | Offer fresh restart (remove sentinel and continue). |
450
+ | User declines confirmation | Remove sentinel, exit cleanly. No writes made. |
451
+ | `validate-store.cjs --dry-run` fails after writing `project-context.json` | Halt. Report errors. Do NOT remove sentinel. User fixes and re-runs. |
452
+ | `substitute-placeholders.cjs` exits non-zero | Halt. Report error. Do NOT remove sentinel. |
453
+ | `manage-versions.cjs init` exits non-zero | Halt. Report error. Archive is complete — rollback is available. |
454
+ | `store-cli.cjs emit` exits non-zero | Report error. Continue — event is diagnostic only. |
455
+ | Any unexpected error | Describe the error, point user to rollback procedure, suggest `/forge:report-bug`. |