@bradtaylorsf/alpha-loop 1.0.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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +294 -0
  3. package/agents/implementer.md +30 -0
  4. package/agents/reviewer.md +29 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +57 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/auth.d.ts +1 -0
  9. package/dist/commands/auth.js +89 -0
  10. package/dist/commands/auth.js.map +1 -0
  11. package/dist/commands/history.d.ts +8 -0
  12. package/dist/commands/history.js +185 -0
  13. package/dist/commands/history.js.map +1 -0
  14. package/dist/commands/init.d.ts +1 -0
  15. package/dist/commands/init.js +241 -0
  16. package/dist/commands/init.js.map +1 -0
  17. package/dist/commands/run.d.ts +15 -0
  18. package/dist/commands/run.js +321 -0
  19. package/dist/commands/run.js.map +1 -0
  20. package/dist/commands/scan.d.ts +1 -0
  21. package/dist/commands/scan.js +50 -0
  22. package/dist/commands/scan.js.map +1 -0
  23. package/dist/commands/sync.d.ts +20 -0
  24. package/dist/commands/sync.js +149 -0
  25. package/dist/commands/sync.js.map +1 -0
  26. package/dist/commands/vision.d.ts +1 -0
  27. package/dist/commands/vision.js +194 -0
  28. package/dist/commands/vision.js.map +1 -0
  29. package/dist/engine/agents.d.ts +41 -0
  30. package/dist/engine/agents.js +90 -0
  31. package/dist/engine/agents.js.map +1 -0
  32. package/dist/engine/config.d.ts +71 -0
  33. package/dist/engine/config.js +73 -0
  34. package/dist/engine/config.js.map +1 -0
  35. package/dist/engine/prerequisites.d.ts +34 -0
  36. package/dist/engine/prerequisites.js +90 -0
  37. package/dist/engine/prerequisites.js.map +1 -0
  38. package/dist/lib/agent.d.ts +25 -0
  39. package/dist/lib/agent.js +97 -0
  40. package/dist/lib/agent.js.map +1 -0
  41. package/dist/lib/config.d.ts +35 -0
  42. package/dist/lib/config.js +179 -0
  43. package/dist/lib/config.js.map +1 -0
  44. package/dist/lib/context.d.ts +17 -0
  45. package/dist/lib/context.js +96 -0
  46. package/dist/lib/context.js.map +1 -0
  47. package/dist/lib/github.d.ts +61 -0
  48. package/dist/lib/github.js +313 -0
  49. package/dist/lib/github.js.map +1 -0
  50. package/dist/lib/learning.d.ts +43 -0
  51. package/dist/lib/learning.js +207 -0
  52. package/dist/lib/learning.js.map +1 -0
  53. package/dist/lib/logger.d.ts +9 -0
  54. package/dist/lib/logger.js +28 -0
  55. package/dist/lib/logger.js.map +1 -0
  56. package/dist/lib/pipeline.d.ts +18 -0
  57. package/dist/lib/pipeline.js +456 -0
  58. package/dist/lib/pipeline.js.map +1 -0
  59. package/dist/lib/preflight.d.ts +33 -0
  60. package/dist/lib/preflight.js +123 -0
  61. package/dist/lib/preflight.js.map +1 -0
  62. package/dist/lib/prerequisites.d.ts +12 -0
  63. package/dist/lib/prerequisites.js +54 -0
  64. package/dist/lib/prerequisites.js.map +1 -0
  65. package/dist/lib/prompts.d.ts +44 -0
  66. package/dist/lib/prompts.js +102 -0
  67. package/dist/lib/prompts.js.map +1 -0
  68. package/dist/lib/session.d.ts +28 -0
  69. package/dist/lib/session.js +173 -0
  70. package/dist/lib/session.js.map +1 -0
  71. package/dist/lib/shell.d.ts +32 -0
  72. package/dist/lib/shell.js +95 -0
  73. package/dist/lib/shell.js.map +1 -0
  74. package/dist/lib/testing.d.ts +10 -0
  75. package/dist/lib/testing.js +51 -0
  76. package/dist/lib/testing.js.map +1 -0
  77. package/dist/lib/verify.d.ts +18 -0
  78. package/dist/lib/verify.js +235 -0
  79. package/dist/lib/verify.js.map +1 -0
  80. package/dist/lib/vision.d.ts +9 -0
  81. package/dist/lib/vision.js +21 -0
  82. package/dist/lib/vision.js.map +1 -0
  83. package/dist/lib/worktree.d.ts +29 -0
  84. package/dist/lib/worktree.js +153 -0
  85. package/dist/lib/worktree.js.map +1 -0
  86. package/package.json +63 -0
  87. package/templates/agents/implementer.md +34 -0
  88. package/templates/agents/reviewer.md +48 -0
  89. package/templates/skills/code-review/SKILL.md +58 -0
  90. package/templates/skills/git-workflow/SKILL.md +53 -0
  91. package/templates/skills/implementation-planning/SKILL.md +64 -0
  92. package/templates/skills/security-analysis/SKILL.md +560 -0
  93. package/templates/skills/security-analysis/scripts/security-scanner.sh +227 -0
  94. package/templates/skills/test-robustness/SKILL.md +897 -0
  95. package/templates/skills/testing-patterns/SKILL.md +75 -0
@@ -0,0 +1,313 @@
1
+ /**
2
+ * GitHub Helpers — interact with GitHub via the `gh` CLI.
3
+ */
4
+ import { writeFileSync, unlinkSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { tmpdir } from 'node:os';
7
+ import { exec } from './shell.js';
8
+ import { log } from './logger.js';
9
+ /** Max PR body length. GitHub supports 65536 but we leave room for metadata. */
10
+ const MAX_PR_BODY_CHARS = 60_000;
11
+ /**
12
+ * List open milestones for a repository.
13
+ */
14
+ export function listMilestones(repo) {
15
+ const result = exec(`gh api "repos/${repo}/milestones?state=open&sort=due_on&direction=asc" --jq '[.[] | {number, title, description, openIssues: .open_issues, closedIssues: .closed_issues, dueOn: .due_on, state}]'`);
16
+ if (result.exitCode !== 0) {
17
+ log.warn(`Failed to list milestones: ${result.stderr}`);
18
+ return [];
19
+ }
20
+ try {
21
+ return JSON.parse(result.stdout);
22
+ }
23
+ catch {
24
+ log.warn('Failed to parse milestones JSON');
25
+ return [];
26
+ }
27
+ }
28
+ /**
29
+ * Fetch issues to process. When a project board is configured, reads from
30
+ * the board in display order (the order you set by dragging), filtered to
31
+ * "Todo" status. Falls back to label-based polling when no project is set.
32
+ *
33
+ * When a milestone is specified, only issues in that milestone are returned.
34
+ */
35
+ export function pollIssues(repo, label, limit = 10, options) {
36
+ const project = options?.project;
37
+ const repoOwner = options?.repoOwner ?? repo.split('/')[0];
38
+ const milestone = options?.milestone;
39
+ // If project board is configured, use it for ordering
40
+ if (project && project > 0) {
41
+ return pollIssuesByProject(repoOwner, project, limit, { repo, milestone });
42
+ }
43
+ // Fallback: poll by label
44
+ return pollIssuesByLabel(repo, label, limit, milestone);
45
+ }
46
+ /**
47
+ * Poll from GitHub Project board — items come in the board's display order.
48
+ * Filters to "Todo" status only. When a milestone is specified, cross-references
49
+ * with the GitHub API to only include issues in that milestone.
50
+ */
51
+ function pollIssuesByProject(owner, project, limit, options) {
52
+ const result = exec(`gh project item-list ${project} --owner "${owner}" --format json --limit 100`);
53
+ if (result.exitCode !== 0) {
54
+ log.warn(`Failed to poll project board: ${result.stderr}`);
55
+ return [];
56
+ }
57
+ try {
58
+ const data = JSON.parse(result.stdout);
59
+ let items = data.items
60
+ .filter((item) => item.status === 'Todo' && item.content?.type === 'Issue');
61
+ // Filter by milestone if specified
62
+ if (options?.milestone && options?.repo) {
63
+ const milestoneIssues = getMilestoneIssueNumbers(options.repo, options.milestone);
64
+ if (milestoneIssues) {
65
+ items = items.filter((item) => milestoneIssues.has(item.content.number));
66
+ }
67
+ }
68
+ return items
69
+ .slice(0, limit)
70
+ .map((item) => ({
71
+ number: item.content.number,
72
+ title: item.content.title,
73
+ body: item.content.body ?? '',
74
+ labels: (item.labels ?? []).map((l) => l.name),
75
+ }));
76
+ }
77
+ catch {
78
+ log.warn('Failed to parse project board JSON');
79
+ return [];
80
+ }
81
+ }
82
+ /**
83
+ * Get the set of open issue numbers belonging to a milestone.
84
+ */
85
+ function getMilestoneIssueNumbers(repo, milestone) {
86
+ const result = exec(`gh issue list --repo "${repo}" --milestone "${milestone}" --state open --json number --limit 100`);
87
+ if (result.exitCode !== 0)
88
+ return null;
89
+ try {
90
+ const issues = JSON.parse(result.stdout);
91
+ return new Set(issues.map((i) => i.number));
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }
97
+ /**
98
+ * Fallback: poll issues by label when no project board is configured.
99
+ * Optionally filters by milestone.
100
+ */
101
+ function pollIssuesByLabel(repo, label, limit, milestone) {
102
+ const milestoneFlag = milestone ? ` --milestone "${milestone}"` : '';
103
+ const result = exec(`gh issue list --repo "${repo}" --label "${label}" --state open${milestoneFlag} --json number,title,body,labels --limit ${limit}`);
104
+ if (result.exitCode !== 0) {
105
+ log.warn(`Failed to poll issues: ${result.stderr}`);
106
+ return [];
107
+ }
108
+ try {
109
+ const raw = JSON.parse(result.stdout);
110
+ return raw
111
+ .map((issue) => ({
112
+ number: issue.number,
113
+ title: issue.title,
114
+ body: issue.body ?? '',
115
+ labels: (issue.labels ?? []).map((l) => l.name),
116
+ }))
117
+ .sort((a, b) => a.number - b.number)
118
+ .slice(0, limit);
119
+ }
120
+ catch {
121
+ log.warn('Failed to parse issues JSON');
122
+ return [];
123
+ }
124
+ }
125
+ /**
126
+ * Add/remove labels on an issue.
127
+ */
128
+ export function labelIssue(repo, issueNum, addLabel, removeLabel) {
129
+ const args = [`gh issue edit ${issueNum} --repo "${repo}" --add-label "${addLabel}"`];
130
+ if (removeLabel) {
131
+ args[0] += ` --remove-label "${removeLabel}"`;
132
+ }
133
+ const result = exec(args[0]);
134
+ if (result.exitCode !== 0) {
135
+ log.warn(`Failed to update labels on issue #${issueNum}: ${result.stderr}`);
136
+ }
137
+ }
138
+ /**
139
+ * Comment on an issue.
140
+ */
141
+ export function commentIssue(repo, issueNum, body) {
142
+ const result = exec(`gh issue comment ${issueNum} --repo "${repo}" --body ${JSON.stringify(body)}`);
143
+ if (result.exitCode !== 0) {
144
+ log.warn(`Failed to comment on issue #${issueNum}: ${result.stderr}`);
145
+ }
146
+ }
147
+ /**
148
+ * Create a PR, or update an existing one if a PR already exists for the branch.
149
+ * Returns the PR URL.
150
+ */
151
+ export function createPR(options) {
152
+ const { repo, base, head, title, body, cwd } = options;
153
+ // Push the branch first
154
+ const pushResult = exec(`git push -u origin "${head}"`, { cwd });
155
+ if (pushResult.exitCode !== 0) {
156
+ // Try force push if branch exists from previous attempt
157
+ log.warn('Push failed, trying force push...');
158
+ const forceResult = exec(`git push -u origin "${head}" --force`, { cwd });
159
+ if (forceResult.exitCode !== 0) {
160
+ throw new Error(`Failed to push branch ${head}: ${forceResult.stderr}`);
161
+ }
162
+ }
163
+ // Write body to a temp file to avoid shell argument length/escaping issues
164
+ const truncatedBody = truncateBody(body);
165
+ const bodyFile = join(tmpdir(), `alpha-loop-pr-body-${Date.now()}`);
166
+ writeFileSync(bodyFile, truncatedBody, 'utf-8');
167
+ try {
168
+ // Check if PR already exists for this branch
169
+ const existingResult = exec(`gh pr list --repo "${repo}" --head "${head}" --json number,url --limit 1`);
170
+ if (existingResult.exitCode === 0 && existingResult.stdout) {
171
+ try {
172
+ const existing = JSON.parse(existingResult.stdout);
173
+ if (existing.length > 0) {
174
+ const prUrl = existing[0].url;
175
+ log.info(`PR already exists: ${prUrl}, updating...`);
176
+ exec(`gh pr edit ${existing[0].number} --repo "${repo}" --body-file "${bodyFile}"`);
177
+ return prUrl;
178
+ }
179
+ }
180
+ catch {
181
+ // Fall through to create
182
+ }
183
+ }
184
+ // Create new PR using --body-file to avoid shell escaping issues
185
+ const createResult = exec(`gh pr create --repo "${repo}" --base "${base}" --head "${head}" --title ${JSON.stringify(title)} --body-file "${bodyFile}"`);
186
+ if (createResult.exitCode !== 0) {
187
+ throw new Error(`Failed to create PR: ${createResult.stderr}`);
188
+ }
189
+ return createResult.stdout.trim();
190
+ }
191
+ finally {
192
+ try {
193
+ unlinkSync(bodyFile);
194
+ }
195
+ catch { /* cleanup best-effort */ }
196
+ }
197
+ }
198
+ /**
199
+ * Merge a PR by branch name.
200
+ */
201
+ export function mergePR(repo, head, method = 'squash') {
202
+ // Find the PR number by branch
203
+ const listResult = exec(`gh pr list --repo "${repo}" --head "${head}" --json number --limit 1`);
204
+ if (listResult.exitCode !== 0 || !listResult.stdout) {
205
+ log.warn(`No PR found to merge for branch ${head}`);
206
+ return;
207
+ }
208
+ let prNum;
209
+ try {
210
+ const prs = JSON.parse(listResult.stdout);
211
+ if (prs.length === 0) {
212
+ log.warn(`No PR found to merge for branch ${head}`);
213
+ return;
214
+ }
215
+ prNum = prs[0].number;
216
+ }
217
+ catch {
218
+ log.warn('Failed to parse PR list');
219
+ return;
220
+ }
221
+ const mergeFlag = method === 'squash' ? '--squash' : '--merge';
222
+ const result = exec(`gh pr merge ${prNum} --repo "${repo}" ${mergeFlag} --delete-branch`);
223
+ if (result.exitCode !== 0) {
224
+ throw new Error(`Failed to merge PR #${prNum}: ${result.stderr}`);
225
+ }
226
+ log.info(`PR #${prNum} merged`);
227
+ }
228
+ /**
229
+ * Update project board status for an issue.
230
+ * This is a multi-step operation using gh project commands.
231
+ */
232
+ export function updateProjectStatus(repo, projectNum, owner, issueNum, status) {
233
+ // Find the item ID for this issue in the project
234
+ const itemResult = exec(`gh project item-list ${projectNum} --owner "${owner}" --format json --limit 100`);
235
+ if (itemResult.exitCode !== 0) {
236
+ log.warn(`Could not list project items: ${itemResult.stderr}`);
237
+ return;
238
+ }
239
+ let itemId;
240
+ try {
241
+ const data = JSON.parse(itemResult.stdout);
242
+ const item = data.items.find((i) => i.content?.number === issueNum);
243
+ itemId = item?.id;
244
+ }
245
+ catch {
246
+ log.warn('Failed to parse project items');
247
+ return;
248
+ }
249
+ if (!itemId) {
250
+ log.warn(`Could not find project item for issue #${issueNum}`);
251
+ return;
252
+ }
253
+ // Get the Status field ID and option ID
254
+ const fieldResult = exec(`gh project field-list ${projectNum} --owner "${owner}" --format json`);
255
+ if (fieldResult.exitCode !== 0) {
256
+ log.warn(`Could not list project fields: ${fieldResult.stderr}`);
257
+ return;
258
+ }
259
+ let fieldId;
260
+ let optionId;
261
+ try {
262
+ const data = JSON.parse(fieldResult.stdout);
263
+ const statusField = data.fields.find((f) => f.name === 'Status');
264
+ if (statusField) {
265
+ fieldId = statusField.id;
266
+ const option = statusField.options?.find((o) => o.name === status);
267
+ optionId = option?.id;
268
+ }
269
+ }
270
+ catch {
271
+ log.warn('Failed to parse project fields');
272
+ return;
273
+ }
274
+ if (!fieldId || !optionId) {
275
+ log.warn(`Could not resolve project field/option for status '${status}'`);
276
+ return;
277
+ }
278
+ // Get project ID
279
+ const projectResult = exec(`gh project view ${projectNum} --owner "${owner}" --format json`);
280
+ if (projectResult.exitCode !== 0) {
281
+ log.warn(`Could not view project: ${projectResult.stderr}`);
282
+ return;
283
+ }
284
+ let projectId;
285
+ try {
286
+ const data = JSON.parse(projectResult.stdout);
287
+ projectId = data.id;
288
+ }
289
+ catch {
290
+ log.warn('Failed to parse project data');
291
+ return;
292
+ }
293
+ if (!projectId) {
294
+ log.warn('Could not get project ID');
295
+ return;
296
+ }
297
+ // Update the item
298
+ const editResult = exec(`gh project item-edit --project-id "${projectId}" --id "${itemId}" --field-id "${fieldId}" --single-select-option-id "${optionId}"`);
299
+ if (editResult.exitCode !== 0) {
300
+ log.warn(`Failed to update project status for #${issueNum}: ${editResult.stderr}`);
301
+ return;
302
+ }
303
+ log.info(`Project board: #${issueNum} -> ${status}`);
304
+ }
305
+ /**
306
+ * Truncate PR body at 30k chars to stay within GitHub limits.
307
+ */
308
+ function truncateBody(body) {
309
+ if (body.length <= MAX_PR_BODY_CHARS)
310
+ return body;
311
+ return body.slice(0, MAX_PR_BODY_CHARS) + '\n\n... (body truncated, see full log)';
312
+ }
313
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/lib/github.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { Config } from './config.js';
2
+ export type ExtractLearningsOptions = {
3
+ issueNum: number;
4
+ title: string;
5
+ status: string;
6
+ retries: number;
7
+ duration: number;
8
+ diff: string;
9
+ testOutput: string;
10
+ reviewOutput: string;
11
+ verifyOutput: string;
12
+ body: string;
13
+ config: Config;
14
+ };
15
+ /**
16
+ * Extract learnings from a completed run.
17
+ * Invokes an agent with the learn prompt and saves the output.
18
+ */
19
+ export declare function extractLearnings(options: ExtractLearningsOptions): Promise<void>;
20
+ /**
21
+ * Count learning files in the learnings directory.
22
+ */
23
+ export declare function countLearnings(learningsDir: string): number;
24
+ /**
25
+ * Get learning context for injection into implementation prompts.
26
+ * Reads the last N learning files and extracts key sections.
27
+ */
28
+ export declare function getLearningContext(learningsDir: string): string;
29
+ /**
30
+ * Generate a session summary that aggregates learnings across all processed issues.
31
+ * Produces a markdown summary with patterns, anti-patterns, and recommendations.
32
+ */
33
+ export declare function generateSessionSummary(options: {
34
+ sessionName: string;
35
+ results: Array<{
36
+ issueNum: number;
37
+ title: string;
38
+ status: string;
39
+ duration: number;
40
+ }>;
41
+ learningsDir: string;
42
+ config: Config;
43
+ }): Promise<string | null>;
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Learning Extractor — extract and aggregate learnings from completed runs.
3
+ */
4
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { log } from './logger.js';
7
+ import { formatTimestamp } from './shell.js';
8
+ import { spawnAgent } from './agent.js';
9
+ import { buildLearnPrompt } from './prompts.js';
10
+ /**
11
+ * Extract learnings from a completed run.
12
+ * Invokes an agent with the learn prompt and saves the output.
13
+ */
14
+ export async function extractLearnings(options) {
15
+ const { config } = options;
16
+ if (config.skipLearn) {
17
+ log.info('Skipping learning extraction (skipLearn=true)');
18
+ return;
19
+ }
20
+ log.step('Extracting learnings from run...');
21
+ const learningsDir = join(process.cwd(), '.alpha-loop', 'learnings');
22
+ mkdirSync(learningsDir, { recursive: true });
23
+ const timestamp = formatTimestamp(new Date());
24
+ const learningFile = join(learningsDir, `issue-${options.issueNum}-${timestamp}.md`);
25
+ const prompt = buildLearnPrompt({
26
+ issueNum: options.issueNum,
27
+ title: options.title,
28
+ status: options.status,
29
+ retries: options.retries,
30
+ duration: options.duration,
31
+ diff: options.diff,
32
+ testOutput: options.testOutput,
33
+ reviewOutput: options.reviewOutput,
34
+ verifyOutput: options.verifyOutput,
35
+ body: options.body,
36
+ });
37
+ if (config.dryRun) {
38
+ log.dry(`Would extract learnings to ${learningFile}`);
39
+ return;
40
+ }
41
+ const result = await spawnAgent({
42
+ agent: 'claude',
43
+ model: config.reviewModel,
44
+ prompt,
45
+ cwd: process.cwd(),
46
+ logFile: undefined,
47
+ });
48
+ if (result.exitCode !== 0 || !result.output.trim()) {
49
+ log.warn(`Learning extraction failed (exit ${result.exitCode}, output ${result.output.length} chars), skipping`);
50
+ return;
51
+ }
52
+ const output = result.output.trim();
53
+ // Validate output has frontmatter, wrap if not
54
+ if (output.startsWith('---')) {
55
+ writeFileSync(learningFile, output + '\n');
56
+ log.success(`Learning saved to ${learningFile}`);
57
+ }
58
+ else {
59
+ const today = new Date().toISOString().split('T')[0];
60
+ const wrapped = `---
61
+ issue: ${options.issueNum}
62
+ status: ${options.status}
63
+ retries: ${options.retries}
64
+ duration: ${options.duration}
65
+ date: ${today}
66
+ ---
67
+ ${output}`;
68
+ writeFileSync(learningFile, wrapped + '\n');
69
+ log.success(`Learning saved to ${learningFile} (added frontmatter)`);
70
+ }
71
+ }
72
+ /**
73
+ * Count learning files in the learnings directory.
74
+ */
75
+ export function countLearnings(learningsDir) {
76
+ if (!existsSync(learningsDir))
77
+ return 0;
78
+ return readdirSync(learningsDir)
79
+ .filter((f) => f.startsWith('issue-') && f.endsWith('.md'))
80
+ .length;
81
+ }
82
+ /**
83
+ * Get learning context for injection into implementation prompts.
84
+ * Reads the last N learning files and extracts key sections.
85
+ */
86
+ export function getLearningContext(learningsDir) {
87
+ if (!existsSync(learningsDir))
88
+ return '';
89
+ const files = readdirSync(learningsDir)
90
+ .filter((f) => f.startsWith('issue-') && f.endsWith('.md'))
91
+ .sort()
92
+ .reverse()
93
+ .slice(0, 5);
94
+ if (files.length === 0)
95
+ return '';
96
+ const sections = ['## Learnings from Previous Runs', ''];
97
+ for (const file of files) {
98
+ const content = readFileSync(join(learningsDir, file), 'utf-8');
99
+ // Extract issue number and status from frontmatter
100
+ const issueMatch = content.match(/^issue:\s*(.+)$/m);
101
+ const statusMatch = content.match(/^status:\s*(.+)$/m);
102
+ const issue = issueMatch?.[1] ?? 'unknown';
103
+ const status = statusMatch?.[1] ?? 'unknown';
104
+ sections.push(`### Run #${issue} (${status})`);
105
+ // Extract What Worked section
106
+ const workedMatch = content.match(/## What Worked\n([\s\S]*?)(?=\n## |$)/);
107
+ if (workedMatch)
108
+ sections.push(workedMatch[1].trim());
109
+ // Extract What Failed section
110
+ const failedMatch = content.match(/## What Failed\n([\s\S]*?)(?=\n## |$)/);
111
+ if (failedMatch)
112
+ sections.push(failedMatch[1].trim());
113
+ sections.push('');
114
+ }
115
+ // Extract anti-patterns from recent learnings
116
+ const antiPatterns = [];
117
+ const recentFiles = readdirSync(learningsDir)
118
+ .filter((f) => f.startsWith('issue-') && f.endsWith('.md'))
119
+ .sort()
120
+ .reverse()
121
+ .slice(0, 10);
122
+ for (const file of recentFiles) {
123
+ const content = readFileSync(join(learningsDir, file), 'utf-8');
124
+ const apMatch = content.match(/## Anti-Patterns\n([\s\S]*?)(?=\n## |$)/);
125
+ if (apMatch)
126
+ antiPatterns.push(apMatch[1].trim());
127
+ }
128
+ if (antiPatterns.length > 0) {
129
+ sections.push('', '## Known Anti-Patterns to Avoid');
130
+ sections.push(antiPatterns.join('\n'));
131
+ }
132
+ return sections.join('\n');
133
+ }
134
+ /**
135
+ * Generate a session summary that aggregates learnings across all processed issues.
136
+ * Produces a markdown summary with patterns, anti-patterns, and recommendations.
137
+ */
138
+ export async function generateSessionSummary(options) {
139
+ const { sessionName, results, learningsDir, config } = options;
140
+ if (config.skipLearn || config.dryRun || results.length === 0)
141
+ return null;
142
+ log.step('Generating session summary...');
143
+ // Collect all learnings from this session
144
+ const learningContents = [];
145
+ for (const result of results) {
146
+ const files = readdirSync(learningsDir)
147
+ .filter((f) => f.startsWith(`issue-${result.issueNum}-`) && f.endsWith('.md'));
148
+ for (const file of files) {
149
+ learningContents.push(readFileSync(join(learningsDir, file), 'utf-8'));
150
+ }
151
+ }
152
+ if (learningContents.length === 0)
153
+ return null;
154
+ const successCount = results.filter((r) => r.status === 'success').length;
155
+ const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
156
+ const prompt = `Analyze these learnings from a development session and produce a concise session summary with actionable recommendations.
157
+
158
+ ## Session: ${sessionName}
159
+ - Issues processed: ${results.length} (${successCount} succeeded, ${results.length - successCount} failed)
160
+ - Total duration: ${Math.round(totalDuration / 60)} minutes
161
+
162
+ ## Individual Learnings
163
+
164
+ ${learningContents.join('\n\n---\n\n')}
165
+
166
+ Output ONLY this markdown structure:
167
+
168
+ # Session Summary: ${sessionName}
169
+
170
+ ## Overview
171
+ - (2-3 sentences summarizing the session)
172
+
173
+ ## Recurring Patterns
174
+ - (patterns that appeared across multiple issues — these should be reinforced)
175
+
176
+ ## Recurring Anti-Patterns
177
+ - (problems that kept happening — these need fixing)
178
+
179
+ ## Recommendations
180
+ - (specific, actionable improvements for the agent prompts, project config, or workflow)
181
+ - (e.g., "Update the implement prompt to always check for X before Y")
182
+ - (e.g., "Add a pre-check for port conflicts before starting verification")
183
+
184
+ ## Metrics
185
+ | Metric | Value |
186
+ |--------|-------|
187
+ | Issues processed | ${results.length} |
188
+ | Success rate | ${Math.round((successCount / results.length) * 100)}% |
189
+ | Avg duration | ${Math.round(totalDuration / results.length)}s |
190
+ | Total duration | ${Math.round(totalDuration / 60)} min |`;
191
+ const agentResult = await spawnAgent({
192
+ agent: 'claude',
193
+ model: config.reviewModel,
194
+ prompt,
195
+ cwd: process.cwd(),
196
+ logFile: undefined,
197
+ });
198
+ if (agentResult.exitCode !== 0 || !agentResult.output.trim()) {
199
+ log.warn('Session summary generation failed');
200
+ return null;
201
+ }
202
+ const summaryFile = join(learningsDir, `session-summary-${sessionName.replace(/\//g, '-')}.md`);
203
+ writeFileSync(summaryFile, agentResult.output.trim() + '\n');
204
+ log.success(`Session summary saved: ${summaryFile}`);
205
+ return agentResult.output.trim();
206
+ }
207
+ //# sourceMappingURL=learning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning.js","sourceRoot":"","sources":["../../src/lib/learning.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare const log: {
2
+ info: (msg: string) => void;
3
+ success: (msg: string) => void;
4
+ warn: (msg: string) => void;
5
+ error: (msg: string) => void;
6
+ step: (msg: string) => void;
7
+ dry: (msg: string) => void;
8
+ debug: (msg: string) => void;
9
+ };
@@ -0,0 +1,28 @@
1
+ const RED = '\x1b[0;31m';
2
+ const GREEN = '\x1b[0;32m';
3
+ const YELLOW = '\x1b[1;33m';
4
+ const BLUE = '\x1b[0;34m';
5
+ const CYAN = '\x1b[0;36m';
6
+ const GRAY = '\x1b[0;90m';
7
+ const BOLD = '\x1b[1m';
8
+ const NC = '\x1b[0m';
9
+ function timestamp() {
10
+ const now = new Date();
11
+ const h = String(now.getHours()).padStart(2, '0');
12
+ const m = String(now.getMinutes()).padStart(2, '0');
13
+ const s = String(now.getSeconds()).padStart(2, '0');
14
+ return `${h}:${m}:${s}`;
15
+ }
16
+ function fmt(label, color, msg) {
17
+ console.error(`${color}[${label}]${NC} ${timestamp()} ${msg}`);
18
+ }
19
+ export const log = {
20
+ info: (msg) => fmt('INFO', BLUE, msg),
21
+ success: (msg) => fmt('OK', GREEN, msg),
22
+ warn: (msg) => fmt('WARN', YELLOW, msg),
23
+ error: (msg) => fmt('ERROR', RED, msg),
24
+ step: (msg) => fmt('STEP', CYAN, msg),
25
+ dry: (msg) => fmt('DRY', YELLOW, msg),
26
+ debug: (msg) => fmt('DEBUG', GRAY, msg),
27
+ };
28
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"AAAA,MAAM,GAAG,GAAG,YAAY,CAAC;AACzB,MAAM,KAAK,GAAG,YAAY,CAAC;AAC3B,MAAM,MAAM,GAAG,YAAY,CAAC;AAC5B,MAAM,IAAI,GAAG,YAAY,CAAC;AAC1B,MAAM,IAAI,GAAG,YAAY,CAAC;AAC1B,MAAM,IAAI,GAAG,YAAY,CAAC;AAC1B,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,EAAE,GAAG,SAAS,CAAC;AAErB,SAAS,SAAS;IAChB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,GAAW;IACpD,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,IAAI,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC;IACnD,OAAO,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC;IACrD,IAAI,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC;IACrD,KAAK,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC;IACpD,IAAI,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC;IACnD,GAAG,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC;IACnD,KAAK,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC;CACtD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Config } from './config.js';
2
+ import type { SessionContext } from './session.js';
3
+ export type PipelineResult = {
4
+ issueNum: number;
5
+ title: string;
6
+ status: 'success' | 'failure';
7
+ prUrl?: string;
8
+ testsPassing: boolean;
9
+ verifyPassing: boolean;
10
+ duration: number;
11
+ filesChanged: number;
12
+ };
13
+ /**
14
+ * Process a single issue through the full pipeline.
15
+ * Steps: status → worktree → plan → implement → test+retry → verify+retry →
16
+ * review → PR → learnings → update → auto-merge → cleanup
17
+ */
18
+ export declare function processIssue(issueNum: number, title: string, body: string, config: Config, session: SessionContext): Promise<PipelineResult>;