@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,195 @@
1
+ // materialize.ts — native handler for /forge:materialize (FORGE-S23-T09)
2
+ //
3
+ // Ports the deterministic subset of the plugin's /forge:materialize:
4
+ // - Full warm-up (no args or --all): runs substitute-placeholders.cjs,
5
+ // build-persona-pack.cjs, and build-context-pack.cjs from the bundled payload.
6
+ // - Single-workflow mode: deferred — notify + return (follow-up task).
7
+ //
8
+ // Mode-neutral invariant: never writes .forge/config.json mode field.
9
+ // Uses spawn("node", [toolPath, ...argv]) — argv-array, no shell (IL6).
10
+ //
11
+ // References: regenerate.ts (substitute-placeholders.cjs argv),
12
+ // forge-init.ts (build-persona-pack / build-context-pack argv).
13
+ import { spawn } from "node:child_process";
14
+ import * as fs from "node:fs";
15
+ import * as path from "node:path";
16
+ import { getBundledPayloadRoot, getBundledToolsRoot } from "./forge-init.js";
17
+ // ── Argument parser ─────────────────────────────────────────────────────────
18
+ /**
19
+ * Parse /forge:materialize arguments.
20
+ *
21
+ * Recognised forms:
22
+ * (empty) → { mode: "all" }
23
+ * --all → { mode: "all" }
24
+ * workflows <id> → { mode: "single-workflow", workflowId: "<id>" }
25
+ * workflows:<id> → { mode: "single-workflow", workflowId: "<id>" }
26
+ */
27
+ export function parseMaterializeArgs(args) {
28
+ const trimmed = args.trim();
29
+ if (!trimmed || trimmed === "--all") {
30
+ return { mode: "all" };
31
+ }
32
+ // "workflows plan_task" or "workflows:plan_task"
33
+ const workflowsMatch = trimmed.match(/^workflows[: ](.+)$/);
34
+ if (workflowsMatch) {
35
+ return { mode: "single-workflow", workflowId: workflowsMatch[1].trim() };
36
+ }
37
+ // Unrecognised flags/forms: treat as full warm-up (fail-open)
38
+ return { mode: "all" };
39
+ }
40
+ // ── Tool runner ─────────────────────────────────────────────────────────────
41
+ /**
42
+ * Spawn `node <toolPath> [...argv]` and await completion.
43
+ * Returns `{ ok: boolean, stderr: string }`.
44
+ *
45
+ * Non-zero exit is FATAL when `fatal === true` (default), ADVISORY otherwise.
46
+ */
47
+ async function runTool(toolPath, argv, cwd, label, timeoutMs = 60_000) {
48
+ return new Promise((resolve) => {
49
+ const child = spawn("node", [toolPath, ...argv], {
50
+ cwd,
51
+ stdio: ["ignore", "pipe", "pipe"],
52
+ });
53
+ let stderrBuf = "";
54
+ const timer = setTimeout(() => {
55
+ child.kill("SIGKILL");
56
+ resolve({ ok: false, stderr: `${label} timed out after ${timeoutMs}ms` });
57
+ }, timeoutMs);
58
+ child.stderr?.on("data", (d) => {
59
+ stderrBuf += d.toString();
60
+ });
61
+ child.on("close", (code) => {
62
+ clearTimeout(timer);
63
+ resolve({ ok: code === 0, stderr: stderrBuf });
64
+ });
65
+ child.on("error", (err) => {
66
+ clearTimeout(timer);
67
+ resolve({ ok: false, stderr: err.message });
68
+ });
69
+ });
70
+ }
71
+ // ── Register ────────────────────────────────────────────────────────────────
72
+ export function registerMaterialize(pi) {
73
+ pi.registerCommand("forge:materialize", {
74
+ description: "Fill missing or stubbed Forge scaffolding without overwriting pristine files. " +
75
+ "Deterministic complement to /forge:init --fast. Mode-neutral: never writes config mode.",
76
+ async handler(args, ctx) {
77
+ const cwd = process.cwd();
78
+ const parsed = parseMaterializeArgs(args);
79
+ // Single-workflow mode: deferred in forge-cli — notify and return
80
+ if (parsed.mode === "single-workflow") {
81
+ ctx.ui.notify(`〇 forge:materialize — single-workflow mode ('${parsed.workflowId ?? "?"}') is not yet supported in forge-cli. ` +
82
+ "Use the Forge plugin directly or run /forge:materialize --all for a full warm-up.", "info");
83
+ return;
84
+ }
85
+ // Config guard
86
+ const configPath = path.join(cwd, ".forge", "config.json");
87
+ if (!fs.existsSync(configPath)) {
88
+ ctx.ui.notify("× forge:materialize — no .forge/config.json found. Run /forge:init first.", "error");
89
+ return;
90
+ }
91
+ // Resolve tool paths
92
+ let bundleRoot;
93
+ let toolsRoot;
94
+ try {
95
+ bundleRoot = getBundledPayloadRoot();
96
+ toolsRoot = getBundledToolsRoot();
97
+ }
98
+ catch (err) {
99
+ const msg = err instanceof Error ? err.message : String(err);
100
+ ctx.ui.notify(`× forge:materialize — could not resolve bundle paths: ${msg}`, "error");
101
+ return;
102
+ }
103
+ const substituteTool = path.join(toolsRoot, "substitute-placeholders.cjs");
104
+ const basePackDir = path.join(bundleRoot, ".base-pack");
105
+ const configJsonPath = path.join(cwd, ".forge", "config.json");
106
+ // Guard: tools must exist
107
+ if (!fs.existsSync(substituteTool)) {
108
+ ctx.ui.notify(`× forge:materialize — substitute-placeholders.cjs not found at ${substituteTool}`, "error");
109
+ return;
110
+ }
111
+ if (!fs.existsSync(basePackDir)) {
112
+ ctx.ui.notify(`× forge:materialize — .base-pack not found at ${basePackDir}`, "error");
113
+ return;
114
+ }
115
+ ctx.ui.setStatus?.("forge:materialize", "Materializing .forge/ artifacts…");
116
+ // Step 1: substitute-placeholders.cjs (fatal on failure)
117
+ // argv shape mirrors regenerate.ts usage
118
+ const initContextJson = path.join(cwd, ".forge", "init-context.json");
119
+ const subArgv = [
120
+ "--forge-root",
121
+ bundleRoot,
122
+ "--base-pack",
123
+ basePackDir,
124
+ "--config",
125
+ configJsonPath,
126
+ "--out",
127
+ cwd,
128
+ ];
129
+ if (fs.existsSync(initContextJson)) {
130
+ subArgv.push("--context", initContextJson);
131
+ }
132
+ const subResult = await runTool(substituteTool, subArgv, cwd, "substitute-placeholders", 60_000);
133
+ if (!subResult.ok) {
134
+ const errMsg = subResult.stderr.trim().split("\n").slice(-3).join(" | ") || "unknown error";
135
+ ctx.ui.notify(`× forge:materialize — substitute-placeholders.cjs failed: ${errMsg}`, "error");
136
+ ctx.ui.setStatus?.("forge:materialize", undefined);
137
+ return;
138
+ }
139
+ ctx.ui.notify("〇 forge:materialize — scaffold filled", "info");
140
+ // Step 2: build-persona-pack.cjs (advisory — non-fatal)
141
+ const buildPersonaPackTool = path.join(toolsRoot, "build-persona-pack.cjs");
142
+ if (fs.existsSync(buildPersonaPackTool)) {
143
+ fs.mkdirSync(path.join(cwd, ".forge", "cache"), { recursive: true });
144
+ const personaResult = await runTool(buildPersonaPackTool, ["--out", path.join(cwd, ".forge", "cache", "persona-pack.json")], cwd, "build-persona-pack", 30_000);
145
+ if (!personaResult.ok) {
146
+ const msg = personaResult.stderr.trim().split("\n").at(-1) ?? "unknown";
147
+ ctx.ui.notify(`△ forge:materialize — build-persona-pack.cjs failed (non-fatal): ${msg}`, "warning");
148
+ }
149
+ }
150
+ // Step 3: build-context-pack.cjs (advisory — non-fatal)
151
+ const buildContextPackTool = path.join(toolsRoot, "build-context-pack.cjs");
152
+ if (fs.existsSync(buildContextPackTool)) {
153
+ // Read engineering path from config
154
+ let kbPath = "engineering";
155
+ try {
156
+ const raw = fs.readFileSync(configPath, "utf8");
157
+ const cfg = JSON.parse(raw);
158
+ const p = cfg.paths;
159
+ if (p && typeof p.engineering === "string")
160
+ kbPath = p.engineering;
161
+ }
162
+ catch {
163
+ // use default
164
+ }
165
+ const ctxResult = await runTool(buildContextPackTool, [
166
+ "--arch-dir",
167
+ path.join(cwd, kbPath, "architecture"),
168
+ "--out-md",
169
+ path.join(cwd, ".forge", "cache", "context-pack.md"),
170
+ "--out-json",
171
+ path.join(cwd, ".forge", "cache", "context-pack.json"),
172
+ ], cwd, "build-context-pack", 30_000);
173
+ if (!ctxResult.ok) {
174
+ const msg = ctxResult.stderr.trim().split("\n").at(-1) ?? "unknown";
175
+ ctx.ui.notify(`△ forge:materialize — build-context-pack.cjs failed (non-fatal): ${msg}`, "warning");
176
+ }
177
+ }
178
+ // Complete
179
+ ctx.ui.setStatus?.("forge:materialize", undefined);
180
+ ctx.ui.notify("〇 forge:materialize complete — gaps filled (mode unchanged)", "info");
181
+ // Promotion hint (mode-neutral: only read, never write)
182
+ try {
183
+ const raw = fs.readFileSync(configPath, "utf8");
184
+ const cfg = JSON.parse(raw);
185
+ if (cfg.mode === "fast") {
186
+ ctx.ui.notify("〇 To declare the project fully generated: /forge:config mode full", "info");
187
+ }
188
+ }
189
+ catch {
190
+ // non-fatal — promotion hint is cosmetic
191
+ }
192
+ },
193
+ });
194
+ }
195
+ //# sourceMappingURL=materialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/materialize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ export interface ParsedMigrateArgs {
3
+ /** True when --structural flag present OR .forge/structure-versions.json absent. */
4
+ structural: boolean;
5
+ /** True when --dry-run flag present (schema branch only). */
6
+ dryRun: boolean;
7
+ }
8
+ /**
9
+ * Parse /forge:migrate arguments.
10
+ *
11
+ * Also checks filesystem for .forge/structure-versions.json to determine
12
+ * structural vs schema branch (absence → structural).
13
+ */
14
+ export declare function parseMigrateArgs(args: string, cwd: string): ParsedMigrateArgs;
15
+ export interface RegisterMigrateOptions {
16
+ /** Override bundleRoot — for testing only. Production: always undefined (resolved via getBundledPayloadRoot). */
17
+ _testBundleRoot?: string;
18
+ }
19
+ export declare function registerMigrate(pi: ExtensionAPI, opts?: RegisterMigrateOptions): void;
@@ -0,0 +1,258 @@
1
+ // migrate.ts — native handler for /forge:migrate (FORGE-S23-T09)
2
+ //
3
+ // Two-branch handler:
4
+ // Structural branch: --structural flag OR .forge/structure-versions.json absent
5
+ // → runForgeSubagent(architect persona + migrate_structural.md workflow)
6
+ // Schema branch: deterministic store migration
7
+ // → runMigrations() from migration-engine.ts (T01)
8
+ //
9
+ // Post-migration health check runs in both branches via runHealthCheck().
10
+ //
11
+ // Iron Laws:
12
+ // IL6 — no shell-string interpolation (argv-array throughout)
13
+ // IL10 — structural branch uses runForgeSubagent (in-process pi SDK), not sendKickoff
14
+ // FORGE-BUG-001 — ctx.modelRegistry passed to runForgeSubagent
15
+ import * as fs from "node:fs";
16
+ import * as path from "node:path";
17
+ import { getBundledPayloadRoot } from "./forge-init.js";
18
+ import { runHealthCheck } from "./health-check.js";
19
+ import { loadForgePersona, runForgeSubagent } from "./forge-subagent.js";
20
+ import { runMigrations } from "./migration-engine.js";
21
+ // ── Argument parser ─────────────────────────────────────────────────────────
22
+ /**
23
+ * Parse /forge:migrate arguments.
24
+ *
25
+ * Also checks filesystem for .forge/structure-versions.json to determine
26
+ * structural vs schema branch (absence → structural).
27
+ */
28
+ export function parseMigrateArgs(args, cwd) {
29
+ const parts = args.trim().split(/\s+/).filter(Boolean);
30
+ const hasStructuralFlag = parts.includes("--structural");
31
+ const hasDryRun = parts.includes("--dry-run");
32
+ // Structural if --structural flag OR structure-versions.json absent
33
+ const structureVersionsPath = path.join(cwd, ".forge", "structure-versions.json");
34
+ const structural = hasStructuralFlag || !fs.existsSync(structureVersionsPath);
35
+ return { structural, dryRun: hasDryRun };
36
+ }
37
+ // ── Ledger reader ───────────────────────────────────────────────────────────
38
+ function readAppliedMigrationsFromVersion(cwd) {
39
+ const ledgerPath = path.join(cwd, ".forge", "applied-migrations.json");
40
+ try {
41
+ const raw = fs.readFileSync(ledgerPath, "utf8");
42
+ const ledger = JSON.parse(raw);
43
+ const versions = ledger.appliedVersions ?? [];
44
+ return versions.at(-1) ?? "0.0.0";
45
+ }
46
+ catch {
47
+ return "0.0.0";
48
+ }
49
+ }
50
+ // ── Bundle version reader ───────────────────────────────────────────────────
51
+ function readBundledForgeVersion(bundleRoot) {
52
+ try {
53
+ const pluginJson = path.join(bundleRoot, ".claude-plugin", "plugin.json");
54
+ const raw = fs.readFileSync(pluginJson, "utf8");
55
+ const parsed = JSON.parse(raw);
56
+ if (typeof parsed.version === "string" && parsed.version)
57
+ return parsed.version;
58
+ }
59
+ catch {
60
+ // fall through
61
+ }
62
+ return "0.0.0";
63
+ }
64
+ export function registerMigrate(pi, opts = {}) {
65
+ pi.registerCommand("forge:migrate", {
66
+ description: "Migrate an existing project store to Forge format. " +
67
+ "Structural branch (--structural or pre-T05 install): delegates to architect persona. " +
68
+ "Schema branch: applies deterministic store migrations from bundled migrations.json.",
69
+ async handler(args, ctx) {
70
+ const cwd = process.cwd();
71
+ const parsed = parseMigrateArgs(args, cwd);
72
+ // Config guard (Step 1 from plugin source)
73
+ const configPath = path.join(cwd, ".forge", "config.json");
74
+ if (!fs.existsSync(configPath)) {
75
+ ctx.ui.notify("× forge:migrate — no .forge/config.json found. " +
76
+ "Run /forge:init first, then come back to /forge:migrate.", "error");
77
+ return;
78
+ }
79
+ // Resolve forge root (for subagent and health check)
80
+ let forgeRoot;
81
+ let bundleRoot;
82
+ if (opts._testBundleRoot) {
83
+ bundleRoot = opts._testBundleRoot;
84
+ }
85
+ else {
86
+ try {
87
+ bundleRoot = getBundledPayloadRoot();
88
+ }
89
+ catch (err) {
90
+ const msg = err instanceof Error ? err.message : String(err);
91
+ ctx.ui.notify(`× forge:migrate — could not resolve bundle root: ${msg}`, "error");
92
+ return;
93
+ }
94
+ }
95
+ try {
96
+ const cfg = JSON.parse(fs.readFileSync(configPath, "utf8"));
97
+ const paths = cfg.paths;
98
+ if (paths && typeof paths.forgeRoot === "string")
99
+ forgeRoot = paths.forgeRoot;
100
+ }
101
+ catch {
102
+ // non-fatal — forgeRoot remains undefined; health check degrades gracefully
103
+ }
104
+ if (parsed.structural) {
105
+ // ── Structural branch ────────────────────────────────────────────────
106
+ await runStructuralMigration(cwd, forgeRoot, bundleRoot, ctx);
107
+ }
108
+ else {
109
+ // ── Schema branch ────────────────────────────────────────────────────
110
+ await runSchemaMigration(cwd, forgeRoot, bundleRoot, parsed.dryRun, ctx);
111
+ }
112
+ },
113
+ });
114
+ }
115
+ // ── Structural branch ────────────────────────────────────────────────────────
116
+ /**
117
+ * Structural migration: load migrate_structural.md (materialized workflow),
118
+ * run marker check, spawn architect subagent, then health check.
119
+ *
120
+ * Marker check rationale: migrate_structural.md does NOT contain
121
+ * Store-Write Verification or forge_store markers (it is a prose-heavy
122
+ * migration guide, not a store-writing kickoff). The handler checks only
123
+ * for `Iron Laws` as the minimum safeguard. This is a documented deviation
124
+ * from the full pack-06 marker set (pack-06 markers are designed for
125
+ * store-writing kickoff shims; structural migration is a different workflow
126
+ * class). Filed for follow-up: add Store-Write Verification to meta-migrate.md.
127
+ */
128
+ async function runStructuralMigration(cwd, forgeRoot, bundleRoot, ctx) {
129
+ ctx.ui.setStatus?.("forge:migrate", "Structural migration — loading workflow…");
130
+ // Read the materialized structural migration workflow
131
+ const workflowPath = path.join(cwd, ".forge", "workflows", "migrate_structural.md");
132
+ let workflowContent;
133
+ try {
134
+ workflowContent = fs.readFileSync(workflowPath, "utf8");
135
+ }
136
+ catch {
137
+ ctx.ui.notify(`× forge:migrate — migrate_structural.md not found at ${workflowPath}. ` +
138
+ "Run /forge:materialize first to fill missing workflows.", "error");
139
+ ctx.ui.setStatus?.("forge:migrate", undefined);
140
+ return;
141
+ }
142
+ // Materialization marker check (partial — Iron Laws only for structural workflow class)
143
+ if (!workflowContent.includes("Iron Laws")) {
144
+ ctx.ui.notify(`× forge:migrate — workflow regression: 'Iron Laws' not found in ${workflowPath}. ` +
145
+ "Run /forge:materialize to refresh.", "error");
146
+ ctx.ui.setStatus?.("forge:migrate", undefined);
147
+ return;
148
+ }
149
+ // Load architect persona
150
+ let persona;
151
+ try {
152
+ persona = loadForgePersona("architect", cwd);
153
+ }
154
+ catch (err) {
155
+ const msg = err instanceof Error ? err.message : String(err);
156
+ ctx.ui.notify(`× forge:migrate — could not load architect persona: ${msg}`, "error");
157
+ ctx.ui.setStatus?.("forge:migrate", undefined);
158
+ return;
159
+ }
160
+ ctx.ui.setStatus?.("forge:migrate", "Structural migration — architect running…");
161
+ // Spawn isolated subagent (IL10)
162
+ const result = await runForgeSubagent({
163
+ persona,
164
+ task: workflowContent,
165
+ cwd,
166
+ signal: ctx.signal,
167
+ forgeRoot,
168
+ modelRegistry: ctx.modelRegistry, // FORGE-BUG-001 followup
169
+ });
170
+ if (result.exitCode !== 0) {
171
+ ctx.ui.notify(`× forge:migrate — structural migration subagent failed (exit ${result.exitCode})`, "error");
172
+ ctx.ui.setStatus?.("forge:migrate", undefined);
173
+ return;
174
+ }
175
+ ctx.ui.notify("〇 forge:migrate — structural migration complete", "info");
176
+ await runPostMigrationHealthCheck(cwd, bundleRoot, forgeRoot, ctx);
177
+ ctx.ui.setStatus?.("forge:migrate", undefined);
178
+ }
179
+ // ── Schema branch ─────────────────────────────────────────────────────────────
180
+ async function runSchemaMigration(cwd, forgeRoot, bundleRoot, dryRun, ctx) {
181
+ ctx.ui.setStatus?.("forge:migrate", "Schema migration — detecting versions…");
182
+ const fromVersion = readAppliedMigrationsFromVersion(cwd);
183
+ const toVersion = readBundledForgeVersion(bundleRoot);
184
+ if (!toVersion || toVersion === "0.0.0") {
185
+ ctx.ui.notify("× forge:migrate — could not determine bundled forge version. " +
186
+ "The bundle may be incomplete. Try reinstalling forge-cli.", "error");
187
+ ctx.ui.setStatus?.("forge:migrate", undefined);
188
+ return;
189
+ }
190
+ if (fromVersion === toVersion) {
191
+ ctx.ui.notify(`〇 forge:migrate — store is already at v${toVersion}; no schema migration needed. ` +
192
+ 'Run `node "$FORGE_ROOT/tools/validate-store.cjs"` to confirm.', "info");
193
+ await runPostMigrationHealthCheck(cwd, bundleRoot, forgeRoot, ctx);
194
+ ctx.ui.setStatus?.("forge:migrate", undefined);
195
+ return;
196
+ }
197
+ ctx.ui.notify(`forge:migrate — applying migrations from v${fromVersion} → v${toVersion}${dryRun ? " (dry-run)" : ""}`, "info");
198
+ ctx.ui.setStatus?.("forge:migrate", `Applying migrations v${fromVersion} → v${toVersion}…`);
199
+ let migResult;
200
+ try {
201
+ migResult = await runMigrations({
202
+ bundleRoot,
203
+ projectRoot: cwd,
204
+ fromVersion,
205
+ toVersion,
206
+ dryRun,
207
+ });
208
+ }
209
+ catch (err) {
210
+ const msg = err instanceof Error ? err.message : String(err);
211
+ ctx.ui.notify(`× forge:migrate — migration engine error: ${msg}`, "error");
212
+ ctx.ui.setStatus?.("forge:migrate", undefined);
213
+ return;
214
+ }
215
+ // Surface results
216
+ if (migResult.applied.length > 0) {
217
+ const versions = migResult.applied.map((a) => `v${a.toVersion}`).join(", ");
218
+ ctx.ui.notify(`〇 forge:migrate — applied ${migResult.applied.length} migration(s): ${versions}`, "info");
219
+ }
220
+ else {
221
+ ctx.ui.notify(`〇 forge:migrate — no new migrations to apply from v${fromVersion} to v${toVersion}`, "info");
222
+ }
223
+ if (migResult.skippedBreaking.length > 0) {
224
+ for (const skipped of migResult.skippedBreaking) {
225
+ ctx.ui.notify(`△ forge:migrate — skipped breaking migration to v${skipped.toVersion}: ${skipped.reason}`, "warning");
226
+ }
227
+ }
228
+ if (migResult.manualSteps.length > 0) {
229
+ ctx.ui.notify("△ forge:migrate — manual steps required after migration:", "warning");
230
+ for (const ms of migResult.manualSteps) {
231
+ for (const step of ms.steps) {
232
+ ctx.ui.notify(` · v${ms.toVersion}: ${step}`, "info");
233
+ }
234
+ }
235
+ }
236
+ await runPostMigrationHealthCheck(cwd, bundleRoot, forgeRoot, ctx);
237
+ ctx.ui.setStatus?.("forge:migrate", undefined);
238
+ }
239
+ // ── Shared post-migration health check ─────────────────────────────────────────
240
+ async function runPostMigrationHealthCheck(cwd, bundleRoot, forgeRoot, ctx) {
241
+ try {
242
+ const healthResult = await runHealthCheck(cwd, bundleRoot, forgeRoot);
243
+ if (healthResult.clean) {
244
+ ctx.ui.notify("〇 /forge:health: clean.", "info");
245
+ }
246
+ else {
247
+ ctx.ui.notify(`△ /forge:health: ${healthResult.gaps.length} gap(s) detected after migration`, "warning");
248
+ for (const gap of healthResult.gaps) {
249
+ ctx.ui.notify(` · ${gap.check}: ${gap.message}`, "info");
250
+ }
251
+ }
252
+ }
253
+ catch (err) {
254
+ const msg = err instanceof Error ? err.message : String(err);
255
+ ctx.ui.notify(`△ forge:migrate — health check failed (non-fatal): ${msg}`, "warning");
256
+ }
257
+ }
258
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ export interface MigrationEntry {
2
+ version: string;
3
+ date: string;
4
+ notes: string;
5
+ regenerate?: string[];
6
+ fileOps?: FileOp[];
7
+ breaking?: boolean;
8
+ manual?: string[];
9
+ }
10
+ export interface FileOp {
11
+ op: "mkdir" | "copy" | "delete" | "substitute-placeholder";
12
+ path: string;
13
+ src?: string;
14
+ }
15
+ export interface MigrationsJson {
16
+ [key: string]: MigrationEntry;
17
+ }
18
+ export interface MigrationResult {
19
+ applied: Array<{
20
+ fromVersion: string;
21
+ toVersion: string;
22
+ categories: string[];
23
+ }>;
24
+ skippedBreaking: Array<{
25
+ fromVersion: string;
26
+ toVersion: string;
27
+ reason: string;
28
+ }>;
29
+ manualSteps: Array<{
30
+ fromVersion: string;
31
+ toVersion: string;
32
+ steps: string[];
33
+ }>;
34
+ dryRun: boolean;
35
+ schemasRefreshed: string[];
36
+ forgeRootUpdated: boolean;
37
+ }
38
+ export interface RunMigrationsOptions {
39
+ /** Absolute path to the dist/forge-payload/ bundle root */
40
+ bundleRoot: string;
41
+ /** Absolute path to the project root (contains .forge/) */
42
+ projectRoot: string;
43
+ /** Version the user was running before the upgrade */
44
+ fromVersion: string;
45
+ /** Version the user just upgraded to */
46
+ toVersion: string;
47
+ /** When true, log actions without writing any files */
48
+ dryRun?: boolean;
49
+ }
50
+ interface EntryWithKey {
51
+ key: string;
52
+ entry: MigrationEntry;
53
+ }
54
+ /** Write-descriptor: source path + destination path for a file copy/write operation */
55
+ interface WriteDescriptor {
56
+ src: string;
57
+ dest: string;
58
+ content?: string;
59
+ }
60
+ /**
61
+ * Compare two version strings using semver integer-component comparison.
62
+ * Returns: negative if a < b, 0 if a === b, positive if a > b.
63
+ *
64
+ * Unlike string comparison, this correctly handles 0.9.x vs 0.10.x boundaries.
65
+ * Strips leading "v" prefix (matches parseTriple() behavior in forge-update-command.ts:118).
66
+ * Falls back to localeCompare for invalid/non-semver inputs.
67
+ */
68
+ export declare function semverCompare(a: string, b: string): number;
69
+ /**
70
+ * Filter migrations.json entries using [fromVersion, toVersion) semantics on keys.
71
+ *
72
+ * - fromVersion entry IS included: it represents the transition AWAY from that version.
73
+ * - toVersion entry is EXCLUDED: it would be a further transition past the target.
74
+ * - Results are sorted ascending by semver (oldest first).
75
+ *
76
+ * No first-run special case — this same filter applies for both first-run
77
+ * (empty ledger) and subsequent runs. The idempotency ledger handles re-run protection.
78
+ */
79
+ export declare function filterMigrationEntries(migrations: MigrationsJson, fromVersion: string, toVersion: string): EntryWithKey[];
80
+ /**
81
+ * Resolve a migration category string to one or more WriteDescriptors.
82
+ * Pure function — does not write files; appends to the provided writes array.
83
+ *
84
+ * ENOENT trap rule: if source doesn't exist, skip silently (never throw on ENOENT).
85
+ * Non-ENOENT IO errors propagate.
86
+ *
87
+ * Path-traversal defense: all output paths are validated against
88
+ * path.join(projectRoot, '.forge') before being added to writes.
89
+ */
90
+ export declare function resolveCategory(category: string, bundleRoot: string, projectRoot: string, writes: WriteDescriptor[]): void;
91
+ /**
92
+ * Execute all migration entries between [fromVersion, toVersion) from the
93
+ * bundled migrations.json against the project's .forge/ directory.
94
+ *
95
+ * Design constraints:
96
+ * - No UI context (no ctx.ui calls).
97
+ * - No event emission (caller is responsible).
98
+ * - Pure deterministic engine: reads from bundleRoot, writes to projectRoot/.forge/.
99
+ * - Idempotent: already-applied versions (from .forge/applied-migrations.json) are skipped.
100
+ *
101
+ * Forward-compat: entries with non-empty fileOps[] use fileOps; otherwise regenerate.
102
+ * NOTE: 0 of 158 current entries use fileOps — the executor is dead code on day 1.
103
+ * Once a real fileOps entry lands, an integration test against that entry MUST be added.
104
+ */
105
+ export declare function runMigrations(opts: RunMigrationsOptions): Promise<MigrationResult>;
106
+ export declare const __test__: {
107
+ semverCompare: typeof semverCompare;
108
+ filterMigrationEntries: typeof filterMigrationEntries;
109
+ resolveCategory: typeof resolveCategory;
110
+ };
111
+ export {};