agentic-forge 0.0.0 → 0.7.1

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 (212) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +64 -24
  3. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/SKILL.md +2 -2
  4. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/references/REFERENCE.md +9 -3
  5. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/references/workflow-example.yaml +15 -8
  6. package/dist/checkpoints/manager.d.ts +5 -0
  7. package/dist/checkpoints/manager.js +87 -0
  8. package/dist/checkpoints/manager.js.map +1 -0
  9. package/{src → dist}/claude/.claude/skills/analyze/SKILL.md +1 -1
  10. package/{src → dist}/claude/.claude/skills/create-checkpoint/SKILL.md +1 -1
  11. package/{src → dist}/claude/.claude/skills/create-log/SKILL.md +1 -1
  12. package/{src → dist}/claude/.claude/skills/fix-analyze/SKILL.md +1 -1
  13. package/{src → dist}/claude/.claude/skills/git-branch/SKILL.md +1 -1
  14. package/{src → dist}/claude/.claude/skills/git-commit/SKILL.md +1 -1
  15. package/{src → dist}/claude/.claude/skills/git-pr/SKILL.md +1 -1
  16. package/{src → dist}/claude/.claude/skills/sdlc-plan/SKILL.md +1 -1
  17. package/{src → dist}/claude/.claude/skills/sdlc-review/SKILL.md +1 -1
  18. package/dist/cli.d.ts +3 -0
  19. package/dist/cli.js +173 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/commands/authoring-dir.d.ts +2 -0
  22. package/dist/commands/authoring-dir.js +9 -0
  23. package/dist/commands/authoring-dir.js.map +1 -0
  24. package/dist/commands/config-cmd.d.ts +2 -0
  25. package/dist/commands/config-cmd.js +30 -0
  26. package/dist/commands/config-cmd.js.map +1 -0
  27. package/{src/commands/index.ts → dist/commands/index.d.ts} +2 -10
  28. package/dist/commands/index.js +14 -0
  29. package/dist/commands/index.js.map +1 -0
  30. package/dist/commands/init.d.ts +6 -0
  31. package/dist/commands/init.js +83 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/release-notes.d.ts +5 -0
  34. package/dist/commands/release-notes.js +68 -0
  35. package/dist/commands/release-notes.js.map +1 -0
  36. package/dist/commands/resume.d.ts +5 -0
  37. package/dist/commands/resume.js +79 -0
  38. package/dist/commands/resume.js.map +1 -0
  39. package/dist/commands/run.d.ts +27 -0
  40. package/dist/commands/run.js +243 -0
  41. package/dist/commands/run.js.map +1 -0
  42. package/dist/commands/shortcuts.d.ts +2 -0
  43. package/dist/commands/shortcuts.js +11 -0
  44. package/dist/commands/shortcuts.js.map +1 -0
  45. package/dist/commands/skills-dir.d.ts +2 -0
  46. package/dist/commands/skills-dir.js +9 -0
  47. package/dist/commands/skills-dir.js.map +1 -0
  48. package/dist/commands/status.d.ts +4 -0
  49. package/dist/commands/status.js +99 -0
  50. package/dist/commands/status.js.map +1 -0
  51. package/dist/commands/update.d.ts +4 -0
  52. package/dist/commands/update.js +65 -0
  53. package/dist/commands/update.js.map +1 -0
  54. package/dist/commands/version.d.ts +3 -0
  55. package/dist/commands/version.js +26 -0
  56. package/dist/commands/version.js.map +1 -0
  57. package/dist/commands/workflows.d.ts +4 -0
  58. package/dist/commands/workflows.js +111 -0
  59. package/dist/commands/workflows.js.map +1 -0
  60. package/dist/config.d.ts +8 -0
  61. package/dist/config.js +110 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/console.d.ts +103 -0
  64. package/dist/console.js +670 -0
  65. package/dist/console.js.map +1 -0
  66. package/dist/executor.d.ts +27 -0
  67. package/dist/executor.js +236 -0
  68. package/dist/executor.js.map +1 -0
  69. package/dist/git/worktree.d.ts +23 -0
  70. package/dist/git/worktree.js +170 -0
  71. package/dist/git/worktree.js.map +1 -0
  72. package/dist/logging/logger.d.ts +27 -0
  73. package/dist/logging/logger.js +69 -0
  74. package/dist/logging/logger.js.map +1 -0
  75. package/dist/orchestrator.d.ts +44 -0
  76. package/dist/orchestrator.js +587 -0
  77. package/dist/orchestrator.js.map +1 -0
  78. package/dist/parser.d.ts +17 -0
  79. package/dist/parser.js +184 -0
  80. package/dist/parser.js.map +1 -0
  81. package/dist/progress.d.ts +29 -0
  82. package/dist/progress.js +275 -0
  83. package/dist/progress.js.map +1 -0
  84. package/dist/ralph-loop.d.ts +26 -0
  85. package/dist/ralph-loop.js +194 -0
  86. package/dist/ralph-loop.js.map +1 -0
  87. package/dist/renderer.d.ts +15 -0
  88. package/dist/renderer.js +123 -0
  89. package/dist/renderer.js.map +1 -0
  90. package/dist/runner.d.ts +84 -0
  91. package/dist/runner.js +529 -0
  92. package/dist/runner.js.map +1 -0
  93. package/dist/signal-manager.d.ts +16 -0
  94. package/dist/signal-manager.js +50 -0
  95. package/dist/signal-manager.js.map +1 -0
  96. package/dist/steps/base.d.ts +28 -0
  97. package/dist/steps/base.js +23 -0
  98. package/dist/steps/base.js.map +1 -0
  99. package/dist/steps/conditional-step.d.ts +12 -0
  100. package/dist/steps/conditional-step.js +106 -0
  101. package/dist/steps/conditional-step.js.map +1 -0
  102. package/{src/steps/index.ts → dist/steps/index.d.ts} +1 -9
  103. package/dist/steps/index.js +8 -0
  104. package/dist/steps/index.js.map +1 -0
  105. package/dist/steps/parallel-step.d.ts +11 -0
  106. package/dist/steps/parallel-step.js +166 -0
  107. package/dist/steps/parallel-step.js.map +1 -0
  108. package/dist/steps/prompt-step.d.ts +8 -0
  109. package/dist/steps/prompt-step.js +94 -0
  110. package/dist/steps/prompt-step.js.map +1 -0
  111. package/dist/steps/ralph-loop-step.d.ts +8 -0
  112. package/dist/steps/ralph-loop-step.js +132 -0
  113. package/dist/steps/ralph-loop-step.js.map +1 -0
  114. package/dist/steps/serial-step.d.ts +10 -0
  115. package/dist/steps/serial-step.js +57 -0
  116. package/dist/steps/serial-step.js.map +1 -0
  117. package/dist/types.d.ts +118 -0
  118. package/dist/types.js +10 -0
  119. package/dist/types.js.map +1 -0
  120. package/package.json +59 -2
  121. package/.gitattributes +0 -24
  122. package/.github/workflows/ci.yml +0 -70
  123. package/.markdownlint-cli2.jsonc +0 -16
  124. package/.prettierignore +0 -3
  125. package/.prettierrc +0 -6
  126. package/.vscode/agentic-forge.code-workspace +0 -26
  127. package/CHANGELOG.md +0 -100
  128. package/CLAUDE.md +0 -158
  129. package/CONTRIBUTING.md +0 -152
  130. package/biome.json +0 -21
  131. package/scripts/copy-assets.js +0 -21
  132. package/src/checkpoints/manager.ts +0 -119
  133. package/src/cli.ts +0 -182
  134. package/src/commands/config-cmd.ts +0 -28
  135. package/src/commands/init.ts +0 -96
  136. package/src/commands/release-notes.ts +0 -85
  137. package/src/commands/resume.ts +0 -103
  138. package/src/commands/run.ts +0 -234
  139. package/src/commands/shortcuts.ts +0 -11
  140. package/src/commands/skills-dir.ts +0 -11
  141. package/src/commands/status.ts +0 -112
  142. package/src/commands/update.ts +0 -64
  143. package/src/commands/version.ts +0 -27
  144. package/src/commands/workflows.ts +0 -129
  145. package/src/config.ts +0 -129
  146. package/src/console.ts +0 -790
  147. package/src/executor.ts +0 -354
  148. package/src/git/worktree.ts +0 -236
  149. package/src/logging/logger.ts +0 -95
  150. package/src/orchestrator.ts +0 -815
  151. package/src/parser.ts +0 -225
  152. package/src/progress.ts +0 -306
  153. package/src/ralph-loop.ts +0 -260
  154. package/src/renderer.ts +0 -164
  155. package/src/runner.ts +0 -634
  156. package/src/signal-manager.ts +0 -55
  157. package/src/steps/base.ts +0 -71
  158. package/src/steps/conditional-step.ts +0 -144
  159. package/src/steps/parallel-step.ts +0 -213
  160. package/src/steps/prompt-step.ts +0 -121
  161. package/src/steps/ralph-loop-step.ts +0 -186
  162. package/src/steps/serial-step.ts +0 -84
  163. package/src/types.ts +0 -141
  164. package/tests/config.test.ts +0 -219
  165. package/tests/console.test.ts +0 -506
  166. package/tests/executor.test.ts +0 -339
  167. package/tests/init.test.ts +0 -86
  168. package/tests/logger.test.ts +0 -110
  169. package/tests/parser.test.ts +0 -290
  170. package/tests/progress.test.ts +0 -345
  171. package/tests/ralph-loop.test.ts +0 -418
  172. package/tests/renderer.test.ts +0 -350
  173. package/tests/runner.test.ts +0 -497
  174. package/tests/setup.test.ts +0 -7
  175. package/tests/signal-manager.test.ts +0 -26
  176. package/tests/steps.test.ts +0 -412
  177. package/tests/worktree.test.ts +0 -411
  178. package/tsconfig.json +0 -18
  179. package/vitest.config.ts +0 -8
  180. /package/{src → dist}/agents/explorer.md +0 -0
  181. /package/{src → dist}/agents/reviewer.md +0 -0
  182. /package/{src → dist}/claude/.claude/skills/analyze/references/bug.md +0 -0
  183. /package/{src → dist}/claude/.claude/skills/analyze/references/debt.md +0 -0
  184. /package/{src → dist}/claude/.claude/skills/analyze/references/doc.md +0 -0
  185. /package/{src → dist}/claude/.claude/skills/analyze/references/security.md +0 -0
  186. /package/{src → dist}/claude/.claude/skills/analyze/references/style.md +0 -0
  187. /package/{src → dist}/claude/.claude/skills/orchestrate/SKILL.md +0 -0
  188. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/bug.md +0 -0
  189. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/chore.md +0 -0
  190. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/feature.md +0 -0
  191. /package/{src → dist}/prompts/agentic-system.md +0 -0
  192. /package/{src → dist}/templates/analysis/bug.md.j2 +0 -0
  193. /package/{src → dist}/templates/analysis/debt.md.j2 +0 -0
  194. /package/{src → dist}/templates/analysis/doc.md.j2 +0 -0
  195. /package/{src → dist}/templates/analysis/security.md.j2 +0 -0
  196. /package/{src → dist}/templates/analysis/style.md.j2 +0 -0
  197. /package/{src → dist}/templates/analysis-summary.md.j2 +0 -0
  198. /package/{src → dist}/templates/checkpoint.md.j2 +0 -0
  199. /package/{src → dist}/templates/implementation-report.md.j2 +0 -0
  200. /package/{src → dist}/templates/memory.md.j2 +0 -0
  201. /package/{src → dist}/templates/plan-bug.md.j2 +0 -0
  202. /package/{src → dist}/templates/plan-chore.md.j2 +0 -0
  203. /package/{src → dist}/templates/plan-feature.md.j2 +0 -0
  204. /package/{src → dist}/templates/progress.json.j2 +0 -0
  205. /package/{src → dist}/templates/ralph-report.md.j2 +0 -0
  206. /package/{src → dist}/workflows/analyze-codebase-merge.yaml +0 -0
  207. /package/{src → dist}/workflows/analyze-codebase.yaml +0 -0
  208. /package/{src → dist}/workflows/analyze-single.yaml +0 -0
  209. /package/{src → dist}/workflows/demo.yaml +0 -0
  210. /package/{src → dist}/workflows/one-shot.yaml +0 -0
  211. /package/{src → dist}/workflows/plan-build-review.yaml +0 -0
  212. /package/{src → dist}/workflows/ralph-loop.yaml +0 -0
package/src/ralph-loop.ts DELETED
@@ -1,260 +0,0 @@
1
- /** Ralph Wiggum loop state management and completion detection. */
2
-
3
- import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
4
- import path from "node:path";
5
- import yaml from "js-yaml";
6
-
7
- // --- Types ---
8
-
9
- export interface RalphLoopState {
10
- active: boolean;
11
- iteration: number;
12
- maxIterations: number;
13
- completionPromise: string;
14
- startedAt: string;
15
- prompt: string;
16
- }
17
-
18
- export interface CompletionResult {
19
- isComplete: boolean;
20
- promiseMatched: boolean;
21
- promiseValue: string | null;
22
- output: string;
23
- isFailed: boolean;
24
- failureReason: string | null;
25
- }
26
-
27
- // --- State path ---
28
-
29
- export function getRalphStatePath(workflowId: string, stepName: string, repoRoot: string): string {
30
- const safeName = stepName.replace(/[^\w-]/g, "_");
31
- return path.join(repoRoot, "agentic", "outputs", workflowId, `ralph-${safeName}.md`);
32
- }
33
-
34
- // --- State management ---
35
-
36
- export function createRalphState(
37
- workflowId: string,
38
- stepName: string,
39
- prompt: string,
40
- maxIterations: number,
41
- completionPromise: string,
42
- repoRoot: string,
43
- ): RalphLoopState {
44
- const state: RalphLoopState = {
45
- active: true,
46
- iteration: 1,
47
- maxIterations,
48
- completionPromise,
49
- startedAt: new Date().toISOString(),
50
- prompt,
51
- };
52
-
53
- saveRalphState(workflowId, stepName, state, repoRoot);
54
- return state;
55
- }
56
-
57
- export function loadRalphState(
58
- workflowId: string,
59
- stepName: string,
60
- repoRoot: string,
61
- ): RalphLoopState | null {
62
- const statePath = getRalphStatePath(workflowId, stepName, repoRoot);
63
- if (!existsSync(statePath)) return null;
64
-
65
- const content = readFileSync(statePath, "utf-8");
66
- return parseRalphState(content);
67
- }
68
-
69
- export function updateRalphIteration(
70
- workflowId: string,
71
- stepName: string,
72
- repoRoot: string,
73
- ): RalphLoopState | null {
74
- const state = loadRalphState(workflowId, stepName, repoRoot);
75
- if (!state) return null;
76
-
77
- state.iteration += 1;
78
- saveRalphState(workflowId, stepName, state, repoRoot);
79
- return state;
80
- }
81
-
82
- export function deactivateRalphState(workflowId: string, stepName: string, repoRoot: string): void {
83
- const state = loadRalphState(workflowId, stepName, repoRoot);
84
- if (state) {
85
- state.active = false;
86
- saveRalphState(workflowId, stepName, state, repoRoot);
87
- }
88
- }
89
-
90
- export function deleteRalphState(workflowId: string, stepName: string, repoRoot: string): void {
91
- const statePath = getRalphStatePath(workflowId, stepName, repoRoot);
92
- if (existsSync(statePath)) {
93
- unlinkSync(statePath);
94
- }
95
- }
96
-
97
- // --- Internal helpers ---
98
-
99
- function saveRalphState(
100
- workflowId: string,
101
- stepName: string,
102
- state: RalphLoopState,
103
- repoRoot: string,
104
- ): void {
105
- const statePath = getRalphStatePath(workflowId, stepName, repoRoot);
106
- const dir = path.dirname(statePath);
107
- mkdirSync(dir, { recursive: true });
108
-
109
- const frontmatter = {
110
- active: state.active,
111
- iteration: state.iteration,
112
- max_iterations: state.maxIterations,
113
- completion_promise: state.completionPromise,
114
- started_at: state.startedAt,
115
- };
116
-
117
- const yamlStr = yaml.dump(frontmatter, { flowLevel: -1 }).trim();
118
- const content = `---
119
- ${yamlStr}
120
- ---
121
-
122
- # Ralph Loop Prompt
123
-
124
- ${state.prompt}
125
- `;
126
-
127
- writeFileSync(statePath, content, "utf-8");
128
- }
129
-
130
- export function parseRalphState(content: string): RalphLoopState | null {
131
- if (!content.startsWith("---")) return null;
132
-
133
- const parts = content.split("---");
134
- if (parts.length < 3) return null;
135
-
136
- let frontmatter: Record<string, unknown>;
137
- try {
138
- frontmatter = yaml.load(parts[1]) as Record<string, unknown>;
139
- } catch {
140
- return null;
141
- }
142
-
143
- const promptSection = parts.slice(2).join("---").trim();
144
- let prompt: string;
145
- if (promptSection.includes("# Ralph Loop Prompt")) {
146
- prompt = promptSection.split("# Ralph Loop Prompt")[1].trim();
147
- } else {
148
- prompt = promptSection;
149
- }
150
-
151
- return {
152
- active: (frontmatter.active as boolean) ?? false,
153
- iteration: (frontmatter.iteration as number) ?? 1,
154
- maxIterations: (frontmatter.max_iterations as number) ?? 5,
155
- completionPromise: (frontmatter.completion_promise as string) ?? "COMPLETE",
156
- startedAt: (frontmatter.started_at as string) ?? "",
157
- prompt,
158
- };
159
- }
160
-
161
- // --- Completion detection ---
162
-
163
- export function detectCompletionPromise(output: string, expectedPromise: string): CompletionResult {
164
- const jsonPatterns = [
165
- /```json\s*\n?(.*?)\n?```/gis,
166
- /```\s*\n?(\{.*?\})\n?```/gis,
167
- /(\{[^{}]*"ralph_complete"[^{}]*\})/gi,
168
- /(\{[^{}]*"ralph_failed"[^{}]*\})/gi,
169
- ];
170
-
171
- for (const pattern of jsonPatterns) {
172
- pattern.lastIndex = 0;
173
- const matches = [...output.matchAll(pattern)];
174
- for (const match of matches) {
175
- try {
176
- const data = JSON.parse(match[1].trim());
177
- if (typeof data !== "object" || data === null) continue;
178
-
179
- // Check for completion signal
180
- if (data.ralph_complete) {
181
- const promiseValue = String(data.promise ?? "");
182
- const promiseMatched =
183
- promiseValue.trim().toUpperCase() === expectedPromise.trim().toUpperCase();
184
- return {
185
- isComplete: true,
186
- promiseMatched,
187
- promiseValue,
188
- output,
189
- isFailed: false,
190
- failureReason: null,
191
- };
192
- }
193
-
194
- // Check for failure signal
195
- if (data.ralph_failed) {
196
- const failureReason = String(data.reason ?? "Unknown error");
197
- return {
198
- isComplete: true,
199
- promiseMatched: false,
200
- promiseValue: null,
201
- output,
202
- isFailed: true,
203
- failureReason,
204
- };
205
- }
206
- } catch {
207
- // Invalid JSON, skip
208
- }
209
- }
210
- }
211
-
212
- return {
213
- isComplete: false,
214
- promiseMatched: false,
215
- promiseValue: null,
216
- output,
217
- isFailed: false,
218
- failureReason: null,
219
- };
220
- }
221
-
222
- // --- System message builder ---
223
-
224
- export function buildRalphSystemMessage(
225
- iteration: number,
226
- maxIterations: number,
227
- completionPromise: string,
228
- ): string {
229
- return `## Ralph Wiggum Loop - Iteration ${iteration}/${maxIterations}
230
-
231
- You are in a Ralph Wiggum iterative loop. Each iteration starts a fresh session.
232
-
233
- **Completion Signal:**
234
- When your task is FULLY complete, output a JSON block:
235
- \`\`\`json
236
- {
237
- "ralph_complete": true,
238
- "promise": "${completionPromise}"
239
- }
240
- \`\`\`
241
-
242
- **Failure Signal:**
243
- If you encounter a BLOCKING error that prevents completion (e.g., missing permissions, cannot write files, access denied), output a failure JSON block:
244
- \`\`\`json
245
- {
246
- "ralph_failed": true,
247
- "reason": "<brief description of the blocking error>"
248
- }
249
- \`\`\`
250
-
251
- **IMPORTANT:**
252
- - Only output the completion JSON when the task is genuinely finished
253
- - Do not output false promises to exit early
254
- - Output the FAILURE JSON immediately if you encounter permission errors or other unrecoverable blocking issues - do NOT continue iterating
255
- - If the task is incomplete but can still progress, continue working - you have ${maxIterations - iteration} iterations remaining
256
-
257
- ---
258
-
259
- `;
260
- }
package/src/renderer.ts DELETED
@@ -1,164 +0,0 @@
1
- /** Nunjucks template rendering for workflows. */
2
-
3
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
- import path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import nunjucks from "nunjucks";
7
-
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
-
10
- /** Set of variable names already warned about (reset per render). */
11
- const warnedVars = new Set<string>();
12
-
13
- /**
14
- * Custom nunjucks loader that warns on undefined variables instead of failing.
15
- * Returns the original `{{ variable_name }}` syntax for undefined variables.
16
- */
17
- function createLenientEnvironment(templateDirs: string[]): nunjucks.Environment {
18
- const loader = new nunjucks.FileSystemLoader(templateDirs, { noCache: true });
19
- const env = new nunjucks.Environment(loader, { autoescape: false });
20
-
21
- // Install a global that intercepts missing variables
22
- // Nunjucks doesn't have a direct WarnOnUndefined equivalent,
23
- // so we use a custom extension approach
24
- return env;
25
- }
26
-
27
- function createStrictEnvironment(templateDirs: string[]): nunjucks.Environment {
28
- const loader = new nunjucks.FileSystemLoader(templateDirs, { noCache: true });
29
- return new nunjucks.Environment(loader, {
30
- autoescape: false,
31
- throwOnUndefined: true,
32
- });
33
- }
34
-
35
- export class TemplateRenderer {
36
- templateDirs: string[];
37
- strictMode: boolean;
38
- private env: nunjucks.Environment;
39
-
40
- constructor(templateDirs?: string[], strictMode = false) {
41
- const dirs = templateDirs ?? [path.join(__dirname, "templates")];
42
-
43
- this.templateDirs = dirs;
44
- this.strictMode = strictMode;
45
-
46
- const existingDirs = dirs.filter((d) => existsSync(d));
47
- this.env = strictMode
48
- ? createStrictEnvironment(existingDirs)
49
- : createLenientEnvironment(existingDirs);
50
- }
51
-
52
- render(templateName: string, context: Record<string, unknown>): string {
53
- if (!this.strictMode) {
54
- warnedVars.clear();
55
- }
56
- return this.env.render(templateName, context);
57
- }
58
-
59
- renderString(templateStr: string, context: Record<string, unknown>): string {
60
- if (!this.strictMode) {
61
- warnedVars.clear();
62
- }
63
- return this.env.renderString(templateStr, context);
64
- }
65
-
66
- hasVariables(text: string): boolean {
67
- return text.includes("{{") || text.includes("{%");
68
- }
69
-
70
- addTemplateDir(dirPath: string): void {
71
- if (existsSync(dirPath) && !this.templateDirs.includes(dirPath)) {
72
- this.templateDirs.push(dirPath);
73
- const existingDirs = this.templateDirs.filter((d) => existsSync(d));
74
- this.env = this.strictMode
75
- ? createStrictEnvironment(existingDirs)
76
- : createLenientEnvironment(existingDirs);
77
- }
78
- }
79
- }
80
-
81
- // --- Helper functions ---
82
-
83
- const ANALYSIS_TYPES = ["bug", "debt", "doc", "security", "style"];
84
-
85
- export function extractAnalysisSteps(
86
- stepOutputs: Record<string, Record<string, unknown>>,
87
- ): Record<string, Record<string, unknown>> {
88
- const result: Record<string, Record<string, unknown>> = {};
89
- for (const [name, data] of Object.entries(stepOutputs)) {
90
- if (name.startsWith("analyze-")) {
91
- const analysisType = name.slice("analyze-".length);
92
- if (ANALYSIS_TYPES.includes(analysisType)) {
93
- result[name] = data;
94
- }
95
- }
96
- }
97
- return result;
98
- }
99
-
100
- export function extractFixSteps(
101
- stepOutputs: Record<string, Record<string, unknown>>,
102
- ): Record<string, Record<string, unknown>> {
103
- const result: Record<string, Record<string, unknown>> = {};
104
- for (const [name, data] of Object.entries(stepOutputs)) {
105
- if (name.startsWith("fix-") || name.startsWith("apply-")) {
106
- result[name] = data;
107
- }
108
- }
109
- return result;
110
- }
111
-
112
- export function buildTemplateContext(
113
- workflowName: string,
114
- workflowId: string,
115
- startedAt: string,
116
- completedAt: string | null,
117
- stepOutputs: Record<string, Record<string, unknown>>,
118
- filesChanged: string[],
119
- branches: string[],
120
- pullRequests: Record<string, unknown>[],
121
- inputs: Record<string, unknown>,
122
- ): Record<string, unknown> {
123
- const analysisSteps = extractAnalysisSteps(stepOutputs);
124
- const fixSteps = extractFixSteps(stepOutputs);
125
-
126
- return {
127
- workflow: {
128
- name: workflowName,
129
- id: workflowId,
130
- started_at: startedAt,
131
- completed_at: completedAt,
132
- },
133
- workflow_id: workflowId,
134
- steps: stepOutputs,
135
- analysis_steps: analysisSteps,
136
- fix_steps: fixSteps,
137
- files_changed: filesChanged,
138
- branches,
139
- pull_requests: pullRequests,
140
- inputs,
141
- };
142
- }
143
-
144
- export function renderWorkflowOutput(
145
- templatePath: string,
146
- outputPath: string,
147
- context: Record<string, unknown>,
148
- templateDirs?: string[],
149
- strictMode = false,
150
- ): void {
151
- const renderer = new TemplateRenderer(templateDirs, strictMode);
152
-
153
- let rendered: string;
154
- if (path.isAbsolute(templatePath)) {
155
- const content = readFileSync(templatePath, "utf-8");
156
- rendered = renderer.renderString(content, context);
157
- } else {
158
- rendered = renderer.render(templatePath, context);
159
- }
160
-
161
- const dir = path.dirname(outputPath);
162
- mkdirSync(dir, { recursive: true });
163
- writeFileSync(outputPath, rendered, "utf-8");
164
- }