@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.
- package/CHANGELOG.md +95 -0
- package/README.md +21 -3
- package/dist/CHANGELOG-forge-plugin.md +90 -0
- package/dist/bin/config.js +6 -0
- package/dist/bin/config.js.map +1 -1
- package/dist/extensions/forgecli/add-pipeline.d.ts +19 -0
- package/dist/extensions/forgecli/add-pipeline.js +143 -0
- package/dist/extensions/forgecli/add-pipeline.js.map +1 -0
- package/dist/extensions/forgecli/add-task.d.ts +20 -0
- package/dist/extensions/forgecli/add-task.js +154 -0
- package/dist/extensions/forgecli/add-task.js.map +1 -0
- package/dist/extensions/forgecli/calibrate.d.ts +61 -0
- package/dist/extensions/forgecli/calibrate.js +488 -0
- package/dist/extensions/forgecli/calibrate.js.map +1 -0
- package/dist/extensions/forgecli/fix-bug.d.ts +9 -1
- package/dist/extensions/forgecli/fix-bug.js +155 -45
- package/dist/extensions/forgecli/fix-bug.js.map +1 -1
- package/dist/extensions/forgecli/forge-commands.js +15 -22
- package/dist/extensions/forgecli/forge-commands.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.d.ts +16 -1
- package/dist/extensions/forgecli/forge-subagent.js +45 -8
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/forge-update-command.d.ts +9 -0
- package/dist/extensions/forgecli/forge-update-command.js +106 -7
- package/dist/extensions/forgecli/forge-update-command.js.map +1 -1
- package/dist/extensions/forgecli/health-check.d.ts +22 -1
- package/dist/extensions/forgecli/health-check.js +177 -4
- package/dist/extensions/forgecli/health-check.js.map +1 -1
- package/dist/extensions/forgecli/hook-dispatcher.d.ts +25 -1
- package/dist/extensions/forgecli/hook-dispatcher.js +104 -9
- package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
- package/dist/extensions/forgecli/hooks/check-update.d.ts +81 -0
- package/dist/extensions/forgecli/hooks/check-update.js +308 -0
- package/dist/extensions/forgecli/hooks/check-update.js.map +1 -0
- package/dist/extensions/forgecli/hooks/forge-permissions.d.ts +32 -0
- package/dist/extensions/forgecli/hooks/forge-permissions.js +119 -0
- package/dist/extensions/forgecli/hooks/forge-permissions.js.map +1 -0
- package/dist/extensions/forgecli/hooks/triage-error.d.ts +23 -0
- package/dist/extensions/forgecli/hooks/triage-error.js +62 -0
- package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -0
- package/dist/extensions/forgecli/hooks/write-guard.d.ts +28 -0
- package/dist/extensions/forgecli/hooks/write-guard.js +225 -0
- package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -0
- package/dist/extensions/forgecli/index.js +60 -0
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/init-context.d.ts +1 -1
- package/dist/extensions/forgecli/init-context.js +21 -6
- package/dist/extensions/forgecli/init-context.js.map +1 -1
- package/dist/extensions/forgecli/materialize.d.ts +16 -0
- package/dist/extensions/forgecli/materialize.js +195 -0
- package/dist/extensions/forgecli/materialize.js.map +1 -0
- package/dist/extensions/forgecli/migrate.d.ts +19 -0
- package/dist/extensions/forgecli/migrate.js +258 -0
- package/dist/extensions/forgecli/migrate.js.map +1 -0
- package/dist/extensions/forgecli/migration-engine.d.ts +111 -0
- package/dist/extensions/forgecli/migration-engine.js +533 -0
- package/dist/extensions/forgecli/migration-engine.js.map +1 -0
- package/dist/extensions/forgecli/quiz-agent.d.ts +17 -0
- package/dist/extensions/forgecli/quiz-agent.js +98 -0
- package/dist/extensions/forgecli/quiz-agent.js.map +1 -0
- package/dist/extensions/forgecli/remove-command.d.ts +17 -0
- package/dist/extensions/forgecli/remove-command.js +124 -0
- package/dist/extensions/forgecli/remove-command.js.map +1 -0
- package/dist/extensions/forgecli/report-bug.d.ts +25 -0
- package/dist/extensions/forgecli/report-bug.js +159 -0
- package/dist/extensions/forgecli/report-bug.js.map +1 -0
- package/dist/extensions/forgecli/retrospective.d.ts +19 -0
- package/dist/extensions/forgecli/retrospective.js +156 -0
- package/dist/extensions/forgecli/retrospective.js.map +1 -0
- package/dist/extensions/forgecli/run-sprint.js +36 -3
- package/dist/extensions/forgecli/run-sprint.js.map +1 -1
- package/dist/extensions/forgecli/run-task.d.ts +9 -1
- package/dist/extensions/forgecli/run-task.js +66 -13
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/session-registry.d.ts +40 -2
- package/dist/extensions/forgecli/session-registry.js +71 -1
- package/dist/extensions/forgecli/session-registry.js.map +1 -1
- package/dist/extensions/forgecli/status-command.d.ts +19 -0
- package/dist/extensions/forgecli/status-command.js +140 -0
- package/dist/extensions/forgecli/status-command.js.map +1 -0
- package/dist/extensions/forgecli/store-query.d.ts +22 -0
- package/dist/extensions/forgecli/store-query.js +107 -0
- package/dist/extensions/forgecli/store-query.js.map +1 -0
- package/dist/extensions/forgecli/store-repair.d.ts +17 -0
- package/dist/extensions/forgecli/store-repair.js +123 -0
- package/dist/extensions/forgecli/store-repair.js.map +1 -0
- package/dist/extensions/forgecli/test-orchestrate.js +1 -0
- package/dist/extensions/forgecli/test-orchestrate.js.map +1 -1
- package/dist/extensions/forgecli/thread-switcher.js +286 -41
- package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
- package/dist/extensions/forgecli/transition-guard.js +7 -2
- package/dist/extensions/forgecli/transition-guard.js.map +1 -1
- package/dist/extensions/forgecli/update-tools.d.ts +23 -0
- package/dist/extensions/forgecli/update-tools.js +136 -0
- package/dist/extensions/forgecli/update-tools.js.map +1 -0
- package/dist/extensions/forgecli/viewport-events.js +10 -0
- package/dist/extensions/forgecli/viewport-events.js.map +1 -1
- package/dist/extensions/forgecli/viewport-renderer.d.ts +18 -0
- package/dist/extensions/forgecli/viewport-renderer.js +27 -0
- package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
- package/dist/extensions/forgecli/viewport-theme.js +4 -0
- package/dist/extensions/forgecli/viewport-theme.js.map +1 -1
- package/dist/extensions/forgecli/whats-new-widget.d.ts +13 -8
- package/dist/extensions/forgecli/whats-new-widget.js +111 -42
- package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
- package/dist/forge-payload/.base-pack/workflows/architect_approve.md +29 -3
- package/dist/forge-payload/.base-pack/workflows/commit_task.md +15 -8
- package/dist/forge-payload/.base-pack/workflows/fix_bug.md +327 -185
- package/dist/forge-payload/.base-pack/workflows/implement_plan.md +18 -10
- package/dist/forge-payload/.base-pack/workflows/plan_task.md +15 -9
- package/dist/forge-payload/.base-pack/workflows/review_code.md +14 -6
- package/dist/forge-payload/.base-pack/workflows/review_plan.md +18 -10
- package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
- package/dist/forge-payload/.schemas/bug.schema.json +3 -2
- package/dist/forge-payload/.schemas/config.schema.json +83 -0
- package/dist/forge-payload/.schemas/migrations.json +2049 -0
- package/dist/forge-payload/commands/regenerate.md +17 -1
- package/dist/forge-payload/meta/personas/README.md +16 -0
- package/dist/forge-payload/meta/personas/meta-architect.md +70 -0
- package/dist/forge-payload/meta/personas/meta-bug-fixer.md +73 -0
- package/dist/forge-payload/meta/personas/meta-collator.md +72 -0
- package/dist/forge-payload/meta/personas/meta-engineer.md +70 -0
- package/dist/forge-payload/meta/personas/meta-orchestrator.md +71 -0
- package/dist/forge-payload/meta/personas/meta-product-manager.md +82 -0
- package/dist/forge-payload/meta/personas/meta-qa-engineer.md +91 -0
- package/dist/forge-payload/meta/personas/meta-supervisor.md +92 -0
- package/dist/forge-payload/meta/skill-recommendations.md +154 -0
- package/dist/forge-payload/meta/skills/meta-architect-skills.md +43 -0
- package/dist/forge-payload/meta/skills/meta-bug-fixer-skills.md +43 -0
- package/dist/forge-payload/meta/skills/meta-collator-skills.md +41 -0
- package/dist/forge-payload/meta/skills/meta-engineer-skills.md +43 -0
- package/dist/forge-payload/meta/skills/meta-generic-skills.md +58 -0
- package/dist/forge-payload/meta/skills/meta-qa-engineer-skills.md +46 -0
- package/dist/forge-payload/meta/skills/meta-supervisor-skills.md +43 -0
- package/dist/forge-payload/meta/store-schema/bug.schema.md +71 -0
- package/dist/forge-payload/meta/store-schema/event.schema.md +76 -0
- package/dist/forge-payload/meta/store-schema/feature.schema.md +65 -0
- package/dist/forge-payload/meta/store-schema/sprint.schema.md +64 -0
- package/dist/forge-payload/meta/store-schema/task.schema.md +78 -0
- package/dist/forge-payload/meta/templates/meta-code-review.md +26 -0
- package/dist/forge-payload/meta/templates/meta-plan-review.md +28 -0
- package/dist/forge-payload/meta/templates/meta-plan.md +28 -0
- package/dist/forge-payload/meta/templates/meta-progress.md +25 -0
- package/dist/forge-payload/meta/templates/meta-retrospective.md +28 -0
- package/dist/forge-payload/meta/templates/meta-sprint-manifest.md +26 -0
- package/dist/forge-payload/meta/templates/meta-sprint-requirements.md +91 -0
- package/dist/forge-payload/meta/templates/meta-task-prompt.md +26 -0
- package/dist/forge-payload/meta/tool-specs/collate.spec.md +88 -0
- package/dist/forge-payload/meta/tool-specs/generation-manifest.spec.md +139 -0
- package/dist/forge-payload/meta/tool-specs/manage-config.spec.md +143 -0
- package/dist/forge-payload/meta/tool-specs/seed-store.spec.md +91 -0
- package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +328 -0
- package/dist/forge-payload/meta/tool-specs/validate-store.spec.md +191 -0
- package/dist/forge-payload/meta/workflows/_fragments/context-injection.md +75 -0
- package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +73 -0
- package/dist/forge-payload/meta/workflows/_fragments/finalize.md +13 -0
- package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +73 -0
- package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +38 -0
- package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +39 -0
- package/dist/forge-payload/meta/workflows/meta-approve.md +119 -0
- package/dist/forge-payload/meta/workflows/meta-collate.md +89 -0
- package/dist/forge-payload/meta/workflows/meta-commit.md +93 -0
- package/dist/forge-payload/meta/workflows/meta-enhance.md +286 -0
- package/dist/forge-payload/meta/workflows/meta-fix-bug.md +501 -0
- package/dist/forge-payload/meta/workflows/meta-implement.md +132 -0
- package/dist/forge-payload/meta/workflows/meta-migrate.md +455 -0
- package/dist/forge-payload/meta/workflows/meta-orchestrate.md +993 -0
- package/dist/forge-payload/meta/workflows/meta-plan-task.md +133 -0
- package/dist/forge-payload/meta/workflows/meta-quiz-agent.md +135 -0
- package/dist/forge-payload/meta/workflows/meta-retrospective.md +65 -0
- package/dist/forge-payload/meta/workflows/meta-review-implementation.md +119 -0
- package/dist/forge-payload/meta/workflows/meta-review-plan.md +108 -0
- package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +65 -0
- package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +76 -0
- package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +147 -0
- package/dist/forge-payload/meta/workflows/meta-update-implementation.md +76 -0
- package/dist/forge-payload/meta/workflows/meta-update-plan.md +76 -0
- package/dist/forge-payload/meta/workflows/meta-validate.md +111 -0
- package/dist/forge-payload/tools/check-structure.cjs +344 -0
- package/dist/forge-payload/tools/collate.cjs +34 -9
- package/dist/forge-payload/tools/list-skills.js +76 -0
- package/dist/forge-payload/tools/parse-gates.cjs +8 -2
- package/dist/forge-payload/tools/store-cli.cjs +56 -11
- package/dist/forge-payload/tools/store.cjs +61 -0
- package/dist/forge-payload/tools/substitute-placeholders.cjs +60 -8
- package/dist/forge-payload/tools/validate-store.cjs +6 -2
- package/dist/forge-payload/tools/verify-integrity.cjs +86 -0
- 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 {};
|