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,200 @@
1
+ /**
2
+ * Final Milestone Detection and PR Creation
3
+ *
4
+ * Handles the transition from "last milestone complete" to "PR ready for review".
5
+ * Uses `gh pr create` to open a pull request with a forge verification report
6
+ * in the body. Designed to be called by the execution engine after the final
7
+ * milestone passes verification.
8
+ */
9
+ import { execSync } from "node:child_process";
10
+ // ---------------------------------------------------------------------------
11
+ // buildPRTitle
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Generate a PR title summarizing all completed milestones.
15
+ *
16
+ * Examples:
17
+ * - `feat: my-project — Milestone 1 complete`
18
+ * - `feat: my-project — Milestones 1-5 complete`
19
+ */
20
+ export function buildPRTitle(project, milestoneCount) {
21
+ if (milestoneCount <= 0) {
22
+ return `feat: ${project} — implementation complete`;
23
+ }
24
+ if (milestoneCount === 1) {
25
+ return `feat: ${project} — Milestone 1 complete`;
26
+ }
27
+ return `feat: ${project} — Milestones 1-${milestoneCount} complete`;
28
+ }
29
+ // ---------------------------------------------------------------------------
30
+ // buildVerificationSection
31
+ // ---------------------------------------------------------------------------
32
+ /**
33
+ * Format a PipelineResult into a PR-ready verification section.
34
+ *
35
+ * Includes gate-level pass/fail status with error counts and
36
+ * duration information. Designed to be embedded in a PR body.
37
+ */
38
+ export function buildVerificationSection(result) {
39
+ const lines = [];
40
+ const status = result.passed ? "PASSED" : "FAILED";
41
+ lines.push(`**Status:** ${status}`);
42
+ lines.push(`**Iterations:** ${result.iteration}/${result.maxIterations}`);
43
+ lines.push("");
44
+ // Gate results table
45
+ lines.push("| Gate | Status | Duration | Details |");
46
+ lines.push("|------|--------|----------|---------|");
47
+ for (const gate of result.gates) {
48
+ const statusIcon = gate.passed ? "Pass" : "Fail";
49
+ const duration = `${(gate.duration_ms / 1000).toFixed(1)}s`;
50
+ let details = "";
51
+ if (!gate.passed && gate.errors.length > 0) {
52
+ details = `${gate.errors.length} error${gate.errors.length === 1 ? "" : "s"}`;
53
+ }
54
+ else if (gate.passed && gate.warnings.length > 0) {
55
+ details = `${gate.warnings.length} warning${gate.warnings.length === 1 ? "" : "s"}`;
56
+ }
57
+ else if (gate.passed) {
58
+ details = "Clean";
59
+ }
60
+ lines.push(`| ${gate.gate} | ${statusIcon} | ${duration} | ${details} |`);
61
+ }
62
+ lines.push("");
63
+ // Error details (collapsed for readability)
64
+ const failedGates = result.gates.filter((g) => !g.passed && g.errors.length > 0);
65
+ if (failedGates.length > 0) {
66
+ lines.push("<details>");
67
+ lines.push("<summary>Error Details</summary>");
68
+ lines.push("");
69
+ for (const gate of failedGates) {
70
+ lines.push(`**${gate.gate}:**`);
71
+ for (const err of gate.errors) {
72
+ const loc = err.file
73
+ ? `${err.file}${err.line ? `:${err.line}` : ""}`
74
+ : "";
75
+ const prefix = loc ? `\`${loc}\`: ` : "";
76
+ lines.push(`- ${prefix}${err.message}`);
77
+ }
78
+ lines.push("");
79
+ }
80
+ lines.push("</details>");
81
+ lines.push("");
82
+ }
83
+ return lines.join("\n");
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // buildPRBody
87
+ // ---------------------------------------------------------------------------
88
+ /**
89
+ * Assemble the complete PR body from milestones, verification, and metadata.
90
+ */
91
+ function buildPRBody(options) {
92
+ const lines = [];
93
+ // Summary section — milestone checklist
94
+ lines.push("## Summary");
95
+ lines.push("");
96
+ for (const m of options.milestones) {
97
+ const checkbox = m.success ? "[x]" : "[ ]";
98
+ lines.push(`- ${checkbox} M${m.number}: ${m.name}`);
99
+ }
100
+ lines.push("");
101
+ // Verification report section
102
+ lines.push("## Verification Report");
103
+ lines.push("");
104
+ if (options.verificationReport) {
105
+ lines.push(options.verificationReport);
106
+ }
107
+ else {
108
+ lines.push("_No verification report available._");
109
+ }
110
+ lines.push("");
111
+ // Details section
112
+ lines.push("## Details");
113
+ lines.push(`- **Branch:** ${options.branch}`);
114
+ if (options.commitSha) {
115
+ lines.push(`- **Commit:** ${options.commitSha.slice(0, 8)}`);
116
+ }
117
+ lines.push("");
118
+ // Footer
119
+ lines.push("---");
120
+ lines.push("Generated with [forge-cc](https://github.com/troyhoffman/forge-cc)");
121
+ return lines.join("\n");
122
+ }
123
+ // ---------------------------------------------------------------------------
124
+ // createPullRequest
125
+ // ---------------------------------------------------------------------------
126
+ /**
127
+ * Create a GitHub pull request using the `gh` CLI.
128
+ *
129
+ * Builds a structured PR body with milestone status, verification report,
130
+ * and metadata, then calls `gh pr create`. If `gh` is not installed or the
131
+ * command fails, returns a descriptive error result instead of throwing.
132
+ */
133
+ export function createPullRequest(options) {
134
+ const baseBranch = options.baseBranch ?? "main";
135
+ const body = buildPRBody(options);
136
+ // Check that gh CLI is available
137
+ try {
138
+ execSync("gh --version", { cwd: options.projectDir, stdio: "pipe" });
139
+ }
140
+ catch {
141
+ return {
142
+ url: "",
143
+ number: 0,
144
+ title: options.title,
145
+ created: false,
146
+ error: "GitHub CLI (gh) is not installed or not in PATH. " +
147
+ "Install it from https://cli.github.com/ and run `gh auth login`.",
148
+ };
149
+ }
150
+ // Create the PR
151
+ try {
152
+ // Write body to a temp approach using stdin to avoid shell escaping issues
153
+ const output = execSync(`gh pr create --title ${JSON.stringify(options.title)} --base ${JSON.stringify(baseBranch)} --body ${JSON.stringify(body)}`, {
154
+ cwd: options.projectDir,
155
+ encoding: "utf-8",
156
+ stdio: ["pipe", "pipe", "pipe"],
157
+ }).trim();
158
+ // gh pr create outputs the PR URL on success
159
+ const url = output.trim();
160
+ const prNumberMatch = url.match(/\/pull\/(\d+)/);
161
+ const prNumber = prNumberMatch ? parseInt(prNumberMatch[1], 10) : 0;
162
+ return {
163
+ url,
164
+ number: prNumber,
165
+ title: options.title,
166
+ created: true,
167
+ };
168
+ }
169
+ catch (err) {
170
+ const message = err instanceof Error ? err.message : String(err);
171
+ // Check for common failure modes
172
+ if (message.includes("already exists")) {
173
+ return {
174
+ url: "",
175
+ number: 0,
176
+ title: options.title,
177
+ created: false,
178
+ error: `A pull request already exists for branch '${options.branch}'. Close or merge the existing PR first.`,
179
+ };
180
+ }
181
+ if (message.includes("not authenticated") ||
182
+ message.includes("auth login")) {
183
+ return {
184
+ url: "",
185
+ number: 0,
186
+ title: options.title,
187
+ created: false,
188
+ error: "GitHub CLI is not authenticated. Run `gh auth login` to authenticate.",
189
+ };
190
+ }
191
+ return {
192
+ url: "",
193
+ number: 0,
194
+ title: options.title,
195
+ created: false,
196
+ error: `Failed to create PR: ${message}`,
197
+ };
198
+ }
199
+ }
200
+ //# sourceMappingURL=finalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finalize.js","sourceRoot":"","sources":["../../src/go/finalize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Linear Status Sync for Execution Engine
3
+ *
4
+ * Bridges the milestone executor with the Linear project management client.
5
+ * Manages issue and project state transitions during the go execution flow:
6
+ *
7
+ * - Milestone start: issues -> In Progress, project -> In Progress
8
+ * - Mid-execution: progress comments on milestone issues
9
+ * - Milestone complete: issues -> In Review (last milestone) or progress comment
10
+ *
11
+ * All operations degrade gracefully — the execution engine must never fail
12
+ * because Linear is unavailable or misconfigured.
13
+ */
14
+ export interface LinearSyncOptions {
15
+ projectId: string;
16
+ milestoneNumber: number;
17
+ milestoneName: string;
18
+ apiKey?: string;
19
+ }
20
+ export interface MilestoneStartSync {
21
+ linearMilestoneId: string | null;
22
+ issuesUpdated: number;
23
+ projectUpdated: boolean;
24
+ }
25
+ export interface MilestoneCompleteOptions extends LinearSyncOptions {
26
+ isLastMilestone: boolean;
27
+ prUrl?: string;
28
+ }
29
+ export interface MilestoneCompleteSync {
30
+ issuesUpdated: number;
31
+ projectUpdated: boolean;
32
+ finalState: string;
33
+ }
34
+ export interface ProgressCommentOptions {
35
+ projectId: string;
36
+ milestoneNumber: number;
37
+ milestoneName: string;
38
+ message: string;
39
+ apiKey?: string;
40
+ }
41
+ /**
42
+ * Execute a Linear operation safely — catches LinearClientError and logs
43
+ * a warning instead of crashing. The execution engine should never fail
44
+ * because Linear is unavailable.
45
+ *
46
+ * Returns the function's result on success, or null on failure.
47
+ */
48
+ export declare function syncLinearSafe<T>(fn: () => Promise<T>): Promise<T | null>;
49
+ /**
50
+ * Sync Linear state when a milestone starts execution.
51
+ *
52
+ * - Finds the Linear milestone by name
53
+ * - Transitions all milestone issues to "In Progress"
54
+ * - Transitions the project to "In Progress" (if not already)
55
+ *
56
+ * Degrades gracefully if Linear is unavailable or the milestone is not found.
57
+ */
58
+ export declare function syncMilestoneStart(options: LinearSyncOptions): Promise<MilestoneStartSync>;
59
+ /**
60
+ * Sync Linear state when a milestone completes.
61
+ *
62
+ * - If NOT the last milestone: adds a progress comment to each issue
63
+ * - If IS the last milestone: transitions all project issues to "In Review",
64
+ * transitions the project to "In Review"
65
+ *
66
+ * Degrades gracefully if Linear is unavailable.
67
+ */
68
+ export declare function syncMilestoneComplete(options: MilestoneCompleteOptions): Promise<MilestoneCompleteSync>;
69
+ /**
70
+ * Add a progress comment to all issues in a milestone.
71
+ * Used during execution to keep Linear updated with wave progress.
72
+ *
73
+ * Degrades gracefully if Linear is unavailable or the milestone is not found.
74
+ */
75
+ export declare function addMilestoneProgressComment(options: ProgressCommentOptions): Promise<void>;
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Linear Status Sync for Execution Engine
3
+ *
4
+ * Bridges the milestone executor with the Linear project management client.
5
+ * Manages issue and project state transitions during the go execution flow:
6
+ *
7
+ * - Milestone start: issues -> In Progress, project -> In Progress
8
+ * - Mid-execution: progress comments on milestone issues
9
+ * - Milestone complete: issues -> In Review (last milestone) or progress comment
10
+ *
11
+ * All operations degrade gracefully — the execution engine must never fail
12
+ * because Linear is unavailable or misconfigured.
13
+ */
14
+ import { LinearClient, LinearClientError } from "../linear/client.js";
15
+ import { transitionProject } from "../linear/projects.js";
16
+ import { transitionMilestoneIssues } from "../linear/issues.js";
17
+ import { findMilestoneByName } from "../linear/milestones.js";
18
+ // ---------------------------------------------------------------------------
19
+ // Safe Wrapper
20
+ // ---------------------------------------------------------------------------
21
+ /**
22
+ * Execute a Linear operation safely — catches LinearClientError and logs
23
+ * a warning instead of crashing. The execution engine should never fail
24
+ * because Linear is unavailable.
25
+ *
26
+ * Returns the function's result on success, or null on failure.
27
+ */
28
+ export async function syncLinearSafe(fn) {
29
+ try {
30
+ return await fn();
31
+ }
32
+ catch (error) {
33
+ if (error instanceof LinearClientError) {
34
+ console.warn(`[linear-sync] Linear operation failed: ${error.message}`);
35
+ return null;
36
+ }
37
+ // Re-throw unexpected errors — they indicate bugs, not Linear issues
38
+ throw error;
39
+ }
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Client Creation
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Attempt to create a LinearClient. Returns null and logs a warning
46
+ * if no API key is available (graceful degradation).
47
+ */
48
+ function createClientSafe(apiKey) {
49
+ try {
50
+ return new LinearClient(apiKey);
51
+ }
52
+ catch (error) {
53
+ if (error instanceof LinearClientError) {
54
+ console.warn(`[linear-sync] Linear client unavailable: ${error.message}`);
55
+ return null;
56
+ }
57
+ throw error;
58
+ }
59
+ }
60
+ // ---------------------------------------------------------------------------
61
+ // Milestone Start
62
+ // ---------------------------------------------------------------------------
63
+ /**
64
+ * Sync Linear state when a milestone starts execution.
65
+ *
66
+ * - Finds the Linear milestone by name
67
+ * - Transitions all milestone issues to "In Progress"
68
+ * - Transitions the project to "In Progress" (if not already)
69
+ *
70
+ * Degrades gracefully if Linear is unavailable or the milestone is not found.
71
+ */
72
+ export async function syncMilestoneStart(options) {
73
+ const noopResult = {
74
+ linearMilestoneId: null,
75
+ issuesUpdated: 0,
76
+ projectUpdated: false,
77
+ };
78
+ const client = createClientSafe(options.apiKey);
79
+ if (!client)
80
+ return noopResult;
81
+ const result = await syncLinearSafe(async () => {
82
+ // Find the milestone in Linear
83
+ const milestone = await findMilestoneByName(client, options.projectId, options.milestoneName);
84
+ if (!milestone) {
85
+ console.warn(`[linear-sync] Milestone "${options.milestoneName}" not found in project ${options.projectId}. Skipping issue transitions.`);
86
+ // Still try to transition the project
87
+ let projectUpdated = false;
88
+ try {
89
+ await transitionProject(client, options.projectId, "In Progress");
90
+ projectUpdated = true;
91
+ }
92
+ catch {
93
+ // Project may already be In Progress or beyond — that's fine
94
+ }
95
+ return {
96
+ linearMilestoneId: null,
97
+ issuesUpdated: 0,
98
+ projectUpdated,
99
+ };
100
+ }
101
+ // Transition milestone issues to In Progress
102
+ const { updated } = await transitionMilestoneIssues(client, options.projectId, milestone.id, "In Progress");
103
+ // Transition project to In Progress
104
+ let projectUpdated = false;
105
+ try {
106
+ await transitionProject(client, options.projectId, "In Progress");
107
+ projectUpdated = true;
108
+ }
109
+ catch {
110
+ // Project may already be In Progress or beyond — that's fine
111
+ }
112
+ return {
113
+ linearMilestoneId: milestone.id,
114
+ issuesUpdated: updated,
115
+ projectUpdated,
116
+ };
117
+ });
118
+ return result ?? noopResult;
119
+ }
120
+ // ---------------------------------------------------------------------------
121
+ // Milestone Complete
122
+ // ---------------------------------------------------------------------------
123
+ /**
124
+ * Sync Linear state when a milestone completes.
125
+ *
126
+ * - If NOT the last milestone: adds a progress comment to each issue
127
+ * - If IS the last milestone: transitions all project issues to "In Review",
128
+ * transitions the project to "In Review"
129
+ *
130
+ * Degrades gracefully if Linear is unavailable.
131
+ */
132
+ export async function syncMilestoneComplete(options) {
133
+ const noopResult = {
134
+ issuesUpdated: 0,
135
+ projectUpdated: false,
136
+ finalState: "unknown",
137
+ };
138
+ const client = createClientSafe(options.apiKey);
139
+ if (!client)
140
+ return noopResult;
141
+ const result = await syncLinearSafe(async () => {
142
+ if (!options.isLastMilestone) {
143
+ // Mid-project milestone — add progress comments
144
+ const milestone = await findMilestoneByName(client, options.projectId, options.milestoneName);
145
+ if (milestone) {
146
+ const issues = await client.listIssues({
147
+ projectId: options.projectId,
148
+ milestoneId: milestone.id,
149
+ });
150
+ const commentBody = `Milestone ${options.milestoneNumber} complete. Moving to next milestone.`;
151
+ for (const issue of issues) {
152
+ await client.createComment(issue.id, commentBody);
153
+ }
154
+ return {
155
+ issuesUpdated: issues.length,
156
+ projectUpdated: false,
157
+ finalState: "In Progress",
158
+ };
159
+ }
160
+ return {
161
+ issuesUpdated: 0,
162
+ projectUpdated: false,
163
+ finalState: "In Progress",
164
+ };
165
+ }
166
+ // Last milestone — move everything to In Review
167
+ // Get ALL project issues (not just this milestone's)
168
+ const allIssues = await client.listIssues({
169
+ projectId: options.projectId,
170
+ });
171
+ let updatedCount = 0;
172
+ for (const issue of allIssues) {
173
+ if (issue.state !== "In Review" && issue.state !== "Done") {
174
+ try {
175
+ await client.updateIssue(issue.id, { state: "In Review" });
176
+ updatedCount++;
177
+ }
178
+ catch {
179
+ // Some issues may not support this transition — skip them
180
+ }
181
+ }
182
+ }
183
+ // Add PR link comment if available
184
+ if (options.prUrl) {
185
+ for (const issue of allIssues) {
186
+ try {
187
+ await client.createComment(issue.id, `PR created: ${options.prUrl}`);
188
+ }
189
+ catch {
190
+ // Comment failures are non-critical
191
+ }
192
+ }
193
+ }
194
+ // Transition project to In Review
195
+ let projectUpdated = false;
196
+ try {
197
+ await transitionProject(client, options.projectId, "In Review");
198
+ projectUpdated = true;
199
+ }
200
+ catch {
201
+ // Project may already be In Review or beyond — that's fine
202
+ }
203
+ return {
204
+ issuesUpdated: updatedCount,
205
+ projectUpdated,
206
+ finalState: "In Review",
207
+ };
208
+ });
209
+ return result ?? noopResult;
210
+ }
211
+ // ---------------------------------------------------------------------------
212
+ // Progress Comments
213
+ // ---------------------------------------------------------------------------
214
+ /**
215
+ * Add a progress comment to all issues in a milestone.
216
+ * Used during execution to keep Linear updated with wave progress.
217
+ *
218
+ * Degrades gracefully if Linear is unavailable or the milestone is not found.
219
+ */
220
+ export async function addMilestoneProgressComment(options) {
221
+ const client = createClientSafe(options.apiKey);
222
+ if (!client)
223
+ return;
224
+ await syncLinearSafe(async () => {
225
+ const milestone = await findMilestoneByName(client, options.projectId, options.milestoneName);
226
+ if (!milestone) {
227
+ console.warn(`[linear-sync] Milestone "${options.milestoneName}" not found. Skipping progress comment.`);
228
+ return;
229
+ }
230
+ const issues = await client.listIssues({
231
+ projectId: options.projectId,
232
+ milestoneId: milestone.id,
233
+ });
234
+ for (const issue of issues) {
235
+ await client.createComment(issue.id, options.message);
236
+ }
237
+ });
238
+ }
239
+ //# sourceMappingURL=linear-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-sync.js","sourceRoot":"","sources":["../../src/go/linear-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { ForgeConfig, GateError, PipelineResult } from "../types.js";
2
+ /** Options for the self-healing verification loop */
3
+ export interface VerifyLoopOptions {
4
+ projectDir: string;
5
+ config: ForgeConfig;
6
+ /** Override config.maxIterations */
7
+ maxIterations?: number;
8
+ /** Called after each pipeline run with the iteration number and result */
9
+ onIteration?: (iteration: number, result: PipelineResult) => void;
10
+ /**
11
+ * Called when verification fails, giving the caller a chance to fix errors.
12
+ * Returns true if a fix was attempted (loop will re-verify).
13
+ * Returns false or is absent to re-run verification without external fix.
14
+ */
15
+ onFixAttempt?: (iteration: number, errors: GateError[]) => Promise<boolean>;
16
+ }
17
+ /** Result from the complete verification loop */
18
+ export interface VerifyLoopResult {
19
+ passed: boolean;
20
+ iterations: number;
21
+ maxIterations: number;
22
+ /** All pipeline results across every iteration */
23
+ results: PipelineResult[];
24
+ /** The last pipeline result */
25
+ finalResult: PipelineResult;
26
+ /** Gate names that still fail after all iterations */
27
+ failedGates: string[];
28
+ /** Human-readable summary of remaining errors */
29
+ errorSummary: string;
30
+ }
31
+ /**
32
+ * Self-healing verification loop.
33
+ *
34
+ * Runs the forge verification pipeline, and on failure either invokes the
35
+ * `onFixAttempt` callback (so the caller can spawn a fix agent) or simply
36
+ * re-runs verification. Loops until the pipeline passes or max iterations
37
+ * are exhausted.
38
+ */
39
+ export declare function runVerifyLoop(options: VerifyLoopOptions): Promise<VerifyLoopResult>;
40
+ /**
41
+ * Format gate errors into a structured prompt for a fix agent.
42
+ *
43
+ * The output is designed to be directly usable in an AI agent prompt:
44
+ * it includes file paths, line numbers, error messages, and remediation
45
+ * hints so the agent can locate and fix issues without extra searching.
46
+ */
47
+ export declare function formatErrorsForAgent(result: PipelineResult): string;