forge-cc 0.1.0

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 (105) hide show
  1. package/.forge.json +5 -0
  2. package/AGENTS.md +42 -0
  3. package/README.md +283 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +148 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config/loader.d.ts +2 -0
  8. package/dist/config/loader.js +44 -0
  9. package/dist/config/loader.js.map +1 -0
  10. package/dist/config/schema.d.ts +57 -0
  11. package/dist/config/schema.js +15 -0
  12. package/dist/config/schema.js.map +1 -0
  13. package/dist/gates/index.d.ts +11 -0
  14. package/dist/gates/index.js +106 -0
  15. package/dist/gates/index.js.map +1 -0
  16. package/dist/gates/lint-gate.d.ts +2 -0
  17. package/dist/gates/lint-gate.js +66 -0
  18. package/dist/gates/lint-gate.js.map +1 -0
  19. package/dist/gates/prd-gate.d.ts +7 -0
  20. package/dist/gates/prd-gate.js +193 -0
  21. package/dist/gates/prd-gate.js.map +1 -0
  22. package/dist/gates/runtime-gate.d.ts +5 -0
  23. package/dist/gates/runtime-gate.js +99 -0
  24. package/dist/gates/runtime-gate.js.map +1 -0
  25. package/dist/gates/tests-gate.d.ts +2 -0
  26. package/dist/gates/tests-gate.js +116 -0
  27. package/dist/gates/tests-gate.js.map +1 -0
  28. package/dist/gates/types-gate.d.ts +2 -0
  29. package/dist/gates/types-gate.js +59 -0
  30. package/dist/gates/types-gate.js.map +1 -0
  31. package/dist/gates/visual-gate.d.ts +6 -0
  32. package/dist/gates/visual-gate.js +118 -0
  33. package/dist/gates/visual-gate.js.map +1 -0
  34. package/dist/go/auto-chain.d.ts +107 -0
  35. package/dist/go/auto-chain.js +303 -0
  36. package/dist/go/auto-chain.js.map +1 -0
  37. package/dist/go/executor.d.ts +130 -0
  38. package/dist/go/executor.js +409 -0
  39. package/dist/go/executor.js.map +1 -0
  40. package/dist/go/finalize.d.ts +58 -0
  41. package/dist/go/finalize.js +200 -0
  42. package/dist/go/finalize.js.map +1 -0
  43. package/dist/go/linear-sync.d.ts +75 -0
  44. package/dist/go/linear-sync.js +239 -0
  45. package/dist/go/linear-sync.js.map +1 -0
  46. package/dist/go/verify-loop.d.ts +47 -0
  47. package/dist/go/verify-loop.js +172 -0
  48. package/dist/go/verify-loop.js.map +1 -0
  49. package/dist/hooks/pre-commit.d.ts +5 -0
  50. package/dist/hooks/pre-commit.js +69 -0
  51. package/dist/hooks/pre-commit.js.map +1 -0
  52. package/dist/linear/client.d.ts +108 -0
  53. package/dist/linear/client.js +388 -0
  54. package/dist/linear/client.js.map +1 -0
  55. package/dist/linear/issues.d.ts +20 -0
  56. package/dist/linear/issues.js +39 -0
  57. package/dist/linear/issues.js.map +1 -0
  58. package/dist/linear/milestones.d.ts +11 -0
  59. package/dist/linear/milestones.js +32 -0
  60. package/dist/linear/milestones.js.map +1 -0
  61. package/dist/linear/projects.d.ts +16 -0
  62. package/dist/linear/projects.js +50 -0
  63. package/dist/linear/projects.js.map +1 -0
  64. package/dist/reporter/human.d.ts +2 -0
  65. package/dist/reporter/human.js +63 -0
  66. package/dist/reporter/human.js.map +1 -0
  67. package/dist/reporter/json.d.ts +2 -0
  68. package/dist/reporter/json.js +4 -0
  69. package/dist/reporter/json.js.map +1 -0
  70. package/dist/server.d.ts +2 -0
  71. package/dist/server.js +109 -0
  72. package/dist/server.js.map +1 -0
  73. package/dist/spec/generator.d.ts +14 -0
  74. package/dist/spec/generator.js +206 -0
  75. package/dist/spec/generator.js.map +1 -0
  76. package/dist/spec/interview.d.ts +104 -0
  77. package/dist/spec/interview.js +342 -0
  78. package/dist/spec/interview.js.map +1 -0
  79. package/dist/spec/linear-sync.d.ts +48 -0
  80. package/dist/spec/linear-sync.js +125 -0
  81. package/dist/spec/linear-sync.js.map +1 -0
  82. package/dist/spec/scanner.d.ts +45 -0
  83. package/dist/spec/scanner.js +473 -0
  84. package/dist/spec/scanner.js.map +1 -0
  85. package/dist/spec/templates.d.ts +345 -0
  86. package/dist/spec/templates.js +86 -0
  87. package/dist/spec/templates.js.map +1 -0
  88. package/dist/state/reader.d.ts +29 -0
  89. package/dist/state/reader.js +116 -0
  90. package/dist/state/reader.js.map +1 -0
  91. package/dist/state/writer.d.ts +60 -0
  92. package/dist/state/writer.js +222 -0
  93. package/dist/state/writer.js.map +1 -0
  94. package/dist/types.d.ts +64 -0
  95. package/dist/types.js +2 -0
  96. package/dist/types.js.map +1 -0
  97. package/dist/utils/browser.d.ts +10 -0
  98. package/dist/utils/browser.js +89 -0
  99. package/dist/utils/browser.js.map +1 -0
  100. package/hooks/pre-commit-verify.js +103 -0
  101. package/package.json +68 -0
  102. package/skills/README.md +33 -0
  103. package/skills/forge-go.md +332 -0
  104. package/skills/forge-spec.md +251 -0
  105. package/skills/forge-triage.md +133 -0
@@ -0,0 +1,59 @@
1
+ import { execSync } from "node:child_process";
2
+ /** Regex to parse tsc error lines: src/foo.ts(10,5): error TS2322: ... */
3
+ const TSC_ERROR_RE = /^(.+?)\((\d+),\d+\):\s*(.+)$/;
4
+ export async function verifyTypes(projectDir) {
5
+ const start = Date.now();
6
+ const errors = [];
7
+ const warnings = [];
8
+ try {
9
+ execSync("npx tsc --noEmit", {
10
+ cwd: projectDir,
11
+ stdio: "pipe",
12
+ timeout: 120_000,
13
+ });
14
+ return {
15
+ gate: "types",
16
+ passed: true,
17
+ errors,
18
+ warnings,
19
+ duration_ms: Date.now() - start,
20
+ };
21
+ }
22
+ catch (err) {
23
+ const output = err instanceof Error && "stdout" in err
24
+ ? String(err.stdout)
25
+ : "";
26
+ for (const line of output.split("\n")) {
27
+ const trimmed = line.trim();
28
+ if (!trimmed)
29
+ continue;
30
+ if (trimmed.toLowerCase().includes("warning")) {
31
+ warnings.push(trimmed);
32
+ }
33
+ else if (trimmed.includes("error TS")) {
34
+ const match = TSC_ERROR_RE.exec(trimmed);
35
+ if (match) {
36
+ errors.push({
37
+ file: match[1],
38
+ line: Number.parseInt(match[2], 10),
39
+ message: match[3],
40
+ });
41
+ }
42
+ else {
43
+ errors.push({ message: trimmed });
44
+ }
45
+ }
46
+ }
47
+ if (errors.length === 0) {
48
+ errors.push({ message: "tsc exited with non-zero status but no TS errors were parsed" });
49
+ }
50
+ return {
51
+ gate: "types",
52
+ passed: false,
53
+ errors,
54
+ warnings,
55
+ duration_ms: Date.now() - start,
56
+ };
57
+ }
58
+ }
59
+ //# sourceMappingURL=types-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-gate.js","sourceRoot":"","sources":["../../src/gates/types-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,0EAA0E;AAC1E,MAAM,YAAY,GAAG,8BAA8B,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,CAAC;QACH,QAAQ,CAAC,kBAAkB,EAAE;YAC3B,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,OAAO;YACL,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,IAAI;YACZ,MAAM;YACN,QAAQ;YACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAChC,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,MAAM,GACV,GAAG,YAAY,KAAK,IAAI,QAAQ,IAAI,GAAG;YACrC,CAAC,CAAC,MAAM,CAAE,GAA0B,CAAC,MAAM,CAAC;YAC5C,CAAC,CAAC,EAAE,CAAC;QAET,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,SAAS;YAEvB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;iBAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzC,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;wBACd,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;wBACnC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;qBAClB,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,8DAA8D,EAAE,CAAC,CAAC;QAC3F,CAAC;QAED,OAAO;YACL,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,KAAK;YACb,MAAM;YACN,QAAQ;YACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAChC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { VisualResult } from "../types.js";
2
+ export declare function verifyVisual(projectDir: string, pages: string[], options?: {
3
+ devServerCommand?: string;
4
+ devServerPort?: number;
5
+ screenshotDir?: string;
6
+ }): Promise<VisualResult>;
@@ -0,0 +1,118 @@
1
+ import { getBrowser, startDevServer, stopDevServer, waitForServer, } from "../utils/browser.js";
2
+ import { mkdirSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ export async function verifyVisual(projectDir, pages, options) {
5
+ const start = Date.now();
6
+ const resolvedPages = pages.length > 0 ? pages : ["/"];
7
+ const port = options?.devServerPort ?? 3000;
8
+ const screenshotDir = options?.screenshotDir ?? join(projectDir, ".forge", "screenshots");
9
+ const consoleErrors = [];
10
+ const warnings = [];
11
+ const screenshots = [];
12
+ mkdirSync(screenshotDir, { recursive: true });
13
+ try {
14
+ // Start dev server
15
+ try {
16
+ await startDevServer(projectDir, options?.devServerCommand, port);
17
+ }
18
+ catch (err) {
19
+ const message = err instanceof Error ? err.message : "Unknown dev server error";
20
+ return {
21
+ gate: "visual",
22
+ passed: false,
23
+ errors: [{ message: `Dev server failed to start: ${message}` }],
24
+ warnings,
25
+ duration_ms: Date.now() - start,
26
+ screenshots,
27
+ consoleErrors,
28
+ };
29
+ }
30
+ // Ensure server is reachable
31
+ const ready = await waitForServer(port);
32
+ if (!ready) {
33
+ return {
34
+ gate: "visual",
35
+ passed: false,
36
+ errors: [{ message: `Dev server not reachable on port ${port}` }],
37
+ warnings,
38
+ duration_ms: Date.now() - start,
39
+ screenshots,
40
+ consoleErrors,
41
+ };
42
+ }
43
+ // Launch browser and create context
44
+ const browser = await getBrowser();
45
+ const context = await browser.newContext();
46
+ try {
47
+ for (const pagePath of resolvedPages) {
48
+ const page = await context.newPage();
49
+ // Collect console errors
50
+ page.on("console", (msg) => {
51
+ if (msg.type() === "error") {
52
+ consoleErrors.push(msg.text());
53
+ }
54
+ });
55
+ page.on("pageerror", (err) => {
56
+ consoleErrors.push(err.message);
57
+ });
58
+ // Navigate to the page
59
+ try {
60
+ await page.goto(`http://localhost:${port}${pagePath}`, {
61
+ waitUntil: "networkidle",
62
+ timeout: 30_000,
63
+ });
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : "Navigation failed";
67
+ consoleErrors.push(`Navigation error for ${pagePath}: ${message}`);
68
+ await page.close();
69
+ continue;
70
+ }
71
+ // Take screenshot
72
+ try {
73
+ const safeName = pagePath.replace(/\//g, "_").replace(/^_/, "") || "index";
74
+ const screenshotPath = join(screenshotDir, `${safeName}.png`);
75
+ await page.screenshot({ path: screenshotPath, fullPage: true });
76
+ screenshots.push({ page: pagePath, path: screenshotPath });
77
+ }
78
+ catch (err) {
79
+ const message = err instanceof Error ? err.message : "Screenshot failed";
80
+ warnings.push(`Screenshot failed for ${pagePath}: ${message}`);
81
+ }
82
+ await page.close();
83
+ }
84
+ }
85
+ finally {
86
+ await context.close();
87
+ }
88
+ // Convert console errors to GateError objects
89
+ const errors = consoleErrors.map((msg) => ({
90
+ message: msg,
91
+ }));
92
+ return {
93
+ gate: "visual",
94
+ passed: consoleErrors.length === 0,
95
+ errors,
96
+ warnings,
97
+ duration_ms: Date.now() - start,
98
+ screenshots,
99
+ consoleErrors,
100
+ };
101
+ }
102
+ catch (err) {
103
+ const message = err instanceof Error ? err.message : "Unknown error in verifyVisual";
104
+ return {
105
+ gate: "visual",
106
+ passed: false,
107
+ errors: [{ message }],
108
+ warnings,
109
+ duration_ms: Date.now() - start,
110
+ screenshots,
111
+ consoleErrors,
112
+ };
113
+ }
114
+ finally {
115
+ await stopDevServer();
116
+ }
117
+ }
118
+ //# sourceMappingURL=visual-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visual-gate.js","sourceRoot":"","sources":["../../src/gates/visual-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Auto-Chain — Multi-Milestone Execution Orchestrator
3
+ *
4
+ * After a milestone completes, spawns a fresh agent with clean context for the
5
+ * next milestone. Fresh agent reads CLAUDE.md + STATE.md + next milestone section
6
+ * only. Loops until all milestones done or a failure stops the chain.
7
+ *
8
+ * This module is the data/logic layer. It does NOT spawn agents — that is
9
+ * the skill file's job (via Claude Code's Task tool). Auto-chain prepares
10
+ * the context and tracks results across milestones.
11
+ */
12
+ import type { MilestoneProgress } from "../state/reader.js";
13
+ import type { CommitResult } from "../state/writer.js";
14
+ import type { ForgeConfig } from "../types.js";
15
+ export interface AutoChainOptions {
16
+ projectDir: string;
17
+ prdPath: string;
18
+ config: ForgeConfig;
19
+ branch: string;
20
+ /** Project name (e.g., "forge-cc") */
21
+ project: string;
22
+ /** Relative PRD path for state docs */
23
+ activePrd: string;
24
+ /** Developer name for session memory */
25
+ developer: string;
26
+ /** If not provided, detect from STATE.md */
27
+ startMilestone?: number;
28
+ /** Called when a milestone begins execution */
29
+ onMilestoneStart?: (milestoneNumber: number, name: string) => void;
30
+ /** Called when a milestone finishes (success or failure) */
31
+ onMilestoneComplete?: (milestoneNumber: number, result: MilestoneResult) => void;
32
+ /** Called when the entire chain finishes */
33
+ onChainComplete?: (results: MilestoneResult[]) => void;
34
+ }
35
+ export interface MilestoneResult {
36
+ milestoneNumber: number;
37
+ milestoneName: string;
38
+ success: boolean;
39
+ commitSha?: string;
40
+ isLast: boolean;
41
+ /** Fresh-context prompt for spawning this milestone's agent */
42
+ freshPrompt: string;
43
+ errors: string[];
44
+ }
45
+ export interface AutoChainResult {
46
+ completed: MilestoneResult[];
47
+ /** true if the chain stopped due to a milestone failure */
48
+ stopped: boolean;
49
+ /** Milestone number where the chain stopped (on failure) */
50
+ stoppedAt?: number;
51
+ /** true if every milestone in the roadmap is complete */
52
+ allComplete: boolean;
53
+ }
54
+ /**
55
+ * Build the fresh-context prompt for a milestone agent (Ralph Loop pattern).
56
+ *
57
+ * Reads CLAUDE.md (abbreviated to Quick Context), STATE.md content, and the
58
+ * current milestone section from the PRD. The total is kept as small as
59
+ * possible (~200-300 lines) while giving the agent enough context to work.
60
+ */
61
+ export declare function buildFreshSessionPrompt(projectDir: string, prdPath: string, milestoneNumber: number): Promise<string>;
62
+ /**
63
+ * Find the next pending milestone number from the roadmap.
64
+ *
65
+ * Scans ROADMAP.md for milestones whose status does NOT start with "Complete".
66
+ * Returns the lowest-numbered pending milestone, or null if all are done.
67
+ */
68
+ export declare function findNextPendingMilestone(projectDir: string): Promise<MilestoneProgress | null>;
69
+ /**
70
+ * Auto-chain orchestrator: manages multi-milestone execution with context resets.
71
+ *
72
+ * For each pending milestone:
73
+ * 1. Determines the starting milestone (from options or STATE.md/ROADMAP.md)
74
+ * 2. Builds a fresh-context prompt for the milestone agent
75
+ * 3. Calls the milestone context builder for structured data
76
+ * 4. Returns results so the calling skill can spawn agents and drive execution
77
+ *
78
+ * The chain stops on the first milestone failure, or when all milestones
79
+ * are complete. The caller is responsible for actually executing each
80
+ * milestone (spawning agents, running waves) — this function provides the
81
+ * orchestration loop and context management.
82
+ */
83
+ export declare function runAutoChain(options: AutoChainOptions): Promise<AutoChainResult>;
84
+ /**
85
+ * Called after a milestone's agent finishes execution.
86
+ *
87
+ * Handles:
88
+ * 1. Updating milestone progress in STATE.md and ROADMAP.md
89
+ * 2. Committing milestone work to git
90
+ * 3. Returning the commit SHA for the milestone result
91
+ *
92
+ * The caller should update the MilestoneResult with the returned commit info.
93
+ */
94
+ export declare function completeMilestone(options: {
95
+ projectDir: string;
96
+ project: string;
97
+ milestoneNumber: number;
98
+ milestoneName: string;
99
+ branch: string;
100
+ activePrd: string;
101
+ developer: string;
102
+ filesToStage: string[];
103
+ push?: boolean;
104
+ }): Promise<{
105
+ commitResult: CommitResult;
106
+ isLast: boolean;
107
+ }>;
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Auto-Chain — Multi-Milestone Execution Orchestrator
3
+ *
4
+ * After a milestone completes, spawns a fresh agent with clean context for the
5
+ * next milestone. Fresh agent reads CLAUDE.md + STATE.md + next milestone section
6
+ * only. Loops until all milestones done or a failure stops the chain.
7
+ *
8
+ * This module is the data/logic layer. It does NOT spawn agents — that is
9
+ * the skill file's job (via Claude Code's Task tool). Auto-chain prepares
10
+ * the context and tracks results across milestones.
11
+ */
12
+ import { readFile } from "node:fs/promises";
13
+ import { join } from "node:path";
14
+ import { readStateFile, readRoadmapProgress, readCurrentMilestone, } from "../state/reader.js";
15
+ import { isLastMilestone, updateMilestoneProgress, commitMilestoneWork, } from "../state/writer.js";
16
+ import { buildMilestoneContext } from "./executor.js";
17
+ // ---------------------------------------------------------------------------
18
+ // Helpers
19
+ // ---------------------------------------------------------------------------
20
+ async function safeRead(filePath) {
21
+ try {
22
+ return await readFile(filePath, "utf-8");
23
+ }
24
+ catch {
25
+ return "";
26
+ }
27
+ }
28
+ /**
29
+ * Extract the "Quick Context" section from CLAUDE.md.
30
+ *
31
+ * Returns just the abbreviated context block (from "## Quick Context" to the
32
+ * next `##` heading or end of file). Falls back to the first 30 lines of
33
+ * the file if the section header isn't found.
34
+ */
35
+ function extractQuickContext(claudeMd) {
36
+ if (!claudeMd)
37
+ return "";
38
+ const quickMatch = claudeMd.match(/##\s*Quick Context\s*\n([\s\S]*?)(?=\n##\s|$)/);
39
+ if (quickMatch) {
40
+ return `## Quick Context\n${quickMatch[1].trim()}`;
41
+ }
42
+ // Fallback: first 30 lines (enough context without bloating the prompt)
43
+ const lines = claudeMd.split("\n").slice(0, 30);
44
+ return lines.join("\n").trim();
45
+ }
46
+ // ---------------------------------------------------------------------------
47
+ // buildFreshSessionPrompt
48
+ // ---------------------------------------------------------------------------
49
+ /**
50
+ * Build the fresh-context prompt for a milestone agent (Ralph Loop pattern).
51
+ *
52
+ * Reads CLAUDE.md (abbreviated to Quick Context), STATE.md content, and the
53
+ * current milestone section from the PRD. The total is kept as small as
54
+ * possible (~200-300 lines) while giving the agent enough context to work.
55
+ */
56
+ export async function buildFreshSessionPrompt(projectDir, prdPath, milestoneNumber) {
57
+ const [claudeMd, stateInfo, milestoneSection] = await Promise.all([
58
+ safeRead(join(projectDir, "CLAUDE.md")),
59
+ readStateFile(projectDir),
60
+ readCurrentMilestone(prdPath, milestoneNumber),
61
+ ]);
62
+ const lines = [];
63
+ // 1. Abbreviated CLAUDE.md
64
+ const quickContext = extractQuickContext(claudeMd);
65
+ if (quickContext) {
66
+ lines.push("# Project Context");
67
+ lines.push("");
68
+ lines.push(quickContext);
69
+ lines.push("");
70
+ }
71
+ // 2. STATE.md — current position
72
+ if (stateInfo) {
73
+ lines.push("# Current State");
74
+ lines.push("");
75
+ lines.push(stateInfo.raw.trim());
76
+ lines.push("");
77
+ }
78
+ // 3. Current milestone section from PRD
79
+ if (milestoneSection) {
80
+ lines.push("# Current Milestone");
81
+ lines.push("");
82
+ lines.push(milestoneSection.trim());
83
+ lines.push("");
84
+ }
85
+ else {
86
+ lines.push(`# Current Milestone`);
87
+ lines.push("");
88
+ lines.push(`Milestone ${milestoneNumber} section not found in PRD at ${prdPath}.`);
89
+ lines.push("");
90
+ }
91
+ // 4. Session instructions (minimal)
92
+ lines.push("# Session Instructions");
93
+ lines.push("");
94
+ lines.push("You are executing the milestone described above. Follow the PRD precisely.");
95
+ lines.push("- Run `npx tsc --noEmit` after all changes to verify types.");
96
+ lines.push("- Stage only files you create/modify (never `git add .`).");
97
+ lines.push("- Do not commit — the orchestrator handles commits.");
98
+ lines.push("- On completion, update `.planning/STATE.md` and `.planning/ROADMAP.md`.");
99
+ lines.push("");
100
+ return lines.join("\n");
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // findNextPendingMilestone
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Find the next pending milestone number from the roadmap.
107
+ *
108
+ * Scans ROADMAP.md for milestones whose status does NOT start with "Complete".
109
+ * Returns the lowest-numbered pending milestone, or null if all are done.
110
+ */
111
+ export async function findNextPendingMilestone(projectDir) {
112
+ const roadmap = await readRoadmapProgress(projectDir);
113
+ if (!roadmap || roadmap.milestones.length === 0) {
114
+ return null;
115
+ }
116
+ // Sort by number ascending to get the lowest pending one
117
+ const sorted = [...roadmap.milestones].sort((a, b) => a.number - b.number);
118
+ for (const milestone of sorted) {
119
+ const statusLower = milestone.status.toLowerCase();
120
+ if (!statusLower.startsWith("complete") &&
121
+ !statusLower.startsWith("done")) {
122
+ return milestone;
123
+ }
124
+ }
125
+ return null; // All milestones are complete
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // runAutoChain
129
+ // ---------------------------------------------------------------------------
130
+ /**
131
+ * Auto-chain orchestrator: manages multi-milestone execution with context resets.
132
+ *
133
+ * For each pending milestone:
134
+ * 1. Determines the starting milestone (from options or STATE.md/ROADMAP.md)
135
+ * 2. Builds a fresh-context prompt for the milestone agent
136
+ * 3. Calls the milestone context builder for structured data
137
+ * 4. Returns results so the calling skill can spawn agents and drive execution
138
+ *
139
+ * The chain stops on the first milestone failure, or when all milestones
140
+ * are complete. The caller is responsible for actually executing each
141
+ * milestone (spawning agents, running waves) — this function provides the
142
+ * orchestration loop and context management.
143
+ */
144
+ export async function runAutoChain(options) {
145
+ const { projectDir, prdPath, config, branch, project, activePrd, developer, onMilestoneStart, onMilestoneComplete, onChainComplete, } = options;
146
+ const completed = [];
147
+ // Determine starting milestone
148
+ let currentMilestoneNumber;
149
+ if (options.startMilestone !== undefined) {
150
+ currentMilestoneNumber = options.startMilestone;
151
+ }
152
+ else {
153
+ // Auto-detect from STATE.md and ROADMAP.md
154
+ const nextPending = await findNextPendingMilestone(projectDir);
155
+ if (!nextPending) {
156
+ // All milestones are already complete
157
+ const result = {
158
+ completed: [],
159
+ stopped: false,
160
+ allComplete: true,
161
+ };
162
+ onChainComplete?.([]);
163
+ return result;
164
+ }
165
+ currentMilestoneNumber = nextPending.number;
166
+ }
167
+ // Loop through milestones until we run out or hit a failure
168
+ while (true) {
169
+ // Build fresh-context prompt for this milestone
170
+ const freshPrompt = await buildFreshSessionPrompt(projectDir, prdPath, currentMilestoneNumber);
171
+ // Build structured context (validates milestone exists in PRD)
172
+ let context;
173
+ try {
174
+ context = await buildMilestoneContext({
175
+ projectDir,
176
+ prdPath,
177
+ milestoneNumber: currentMilestoneNumber,
178
+ config,
179
+ });
180
+ }
181
+ catch (err) {
182
+ // Milestone not found in PRD — chain cannot continue
183
+ const errorMessage = err instanceof Error ? err.message : String(err);
184
+ const failResult = {
185
+ milestoneNumber: currentMilestoneNumber,
186
+ milestoneName: "Unknown",
187
+ success: false,
188
+ isLast: false,
189
+ freshPrompt,
190
+ errors: [errorMessage],
191
+ };
192
+ completed.push(failResult);
193
+ onMilestoneComplete?.(currentMilestoneNumber, failResult);
194
+ const chainResult = {
195
+ completed,
196
+ stopped: true,
197
+ stoppedAt: currentMilestoneNumber,
198
+ allComplete: false,
199
+ };
200
+ onChainComplete?.(completed);
201
+ return chainResult;
202
+ }
203
+ // Notify: milestone starting
204
+ onMilestoneStart?.(currentMilestoneNumber, context.milestoneName);
205
+ // Build the milestone result with the fresh prompt.
206
+ // The caller uses `freshPrompt` to spawn an agent, then calls
207
+ // `completeMilestone()` after the agent finishes.
208
+ const milestoneResult = {
209
+ milestoneNumber: currentMilestoneNumber,
210
+ milestoneName: context.milestoneName,
211
+ success: true, // Optimistic; caller updates via completeMilestone
212
+ isLast: await isLastMilestone(projectDir, currentMilestoneNumber),
213
+ freshPrompt,
214
+ errors: [],
215
+ };
216
+ completed.push(milestoneResult);
217
+ // Notify: milestone complete (caller will drive actual execution)
218
+ onMilestoneComplete?.(currentMilestoneNumber, milestoneResult);
219
+ // If this was the last milestone, we're done
220
+ if (milestoneResult.isLast) {
221
+ const chainResult = {
222
+ completed,
223
+ stopped: false,
224
+ allComplete: true,
225
+ };
226
+ onChainComplete?.(completed);
227
+ return chainResult;
228
+ }
229
+ // Find the next pending milestone
230
+ const nextPending = await findNextPendingMilestone(projectDir);
231
+ if (!nextPending) {
232
+ // All milestones are complete
233
+ const chainResult = {
234
+ completed,
235
+ stopped: false,
236
+ allComplete: true,
237
+ };
238
+ onChainComplete?.(completed);
239
+ return chainResult;
240
+ }
241
+ currentMilestoneNumber = nextPending.number;
242
+ }
243
+ }
244
+ // ---------------------------------------------------------------------------
245
+ // completeMilestone — post-execution bookkeeping
246
+ // ---------------------------------------------------------------------------
247
+ /**
248
+ * Called after a milestone's agent finishes execution.
249
+ *
250
+ * Handles:
251
+ * 1. Updating milestone progress in STATE.md and ROADMAP.md
252
+ * 2. Committing milestone work to git
253
+ * 3. Returning the commit SHA for the milestone result
254
+ *
255
+ * The caller should update the MilestoneResult with the returned commit info.
256
+ */
257
+ export async function completeMilestone(options) {
258
+ const { projectDir, project, milestoneNumber, milestoneName, branch, activePrd, developer, filesToStage, push, } = options;
259
+ // Check if this is the last milestone
260
+ const last = await isLastMilestone(projectDir, milestoneNumber);
261
+ // Find next milestone for state docs
262
+ const roadmap = await readRoadmapProgress(projectDir);
263
+ const milestoneTable = roadmap?.milestones.map((m) => ({
264
+ number: m.number,
265
+ name: m.name,
266
+ status: m.number === milestoneNumber
267
+ ? `Complete (${new Date().toISOString().slice(0, 10)})`
268
+ : m.status,
269
+ })) ?? [];
270
+ // Find the next milestone (if any)
271
+ const nextMilestone = last
272
+ ? undefined
273
+ : roadmap?.milestones
274
+ .filter((m) => m.number > milestoneNumber &&
275
+ !m.status.toLowerCase().startsWith("complete"))
276
+ .sort((a, b) => a.number - b.number)[0];
277
+ const nextMilestoneInfo = nextMilestone
278
+ ? { number: nextMilestone.number, name: nextMilestone.name }
279
+ : undefined;
280
+ // Update state docs (STATE.md, ROADMAP.md, session memory)
281
+ await updateMilestoneProgress({
282
+ projectDir,
283
+ project,
284
+ milestoneNumber,
285
+ milestoneName,
286
+ branch,
287
+ activePrd,
288
+ developer,
289
+ nextMilestone: nextMilestoneInfo,
290
+ milestoneTable,
291
+ });
292
+ // Commit milestone work
293
+ const commitResult = commitMilestoneWork({
294
+ projectDir,
295
+ milestoneNumber,
296
+ milestoneName,
297
+ filesToStage,
298
+ push,
299
+ branch,
300
+ });
301
+ return { commitResult, isLast: last };
302
+ }
303
+ //# sourceMappingURL=auto-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-chain.js","sourceRoot":"","sources":["../../src/go/auto-chain.ts"],"names":[],"mappings":"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"}