@bradtaylorsf/alpha-loop 1.13.1 → 1.14.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.
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Epic verification pass — runs after all sub-issues of an epic have shipped.
3
+ *
4
+ * The agent is given the epic body (with its acceptance criteria), each
5
+ * sub-issue body (with its own AC checklist), and the merged PR diffs.
6
+ * It emits a structured {@link EpicVerdict} JSON block rating each
7
+ * sub-issue's AC against what actually landed.
8
+ *
9
+ * Permissive `--verify-only` mode: sub-issues without a merged PR are reported
10
+ * as `skipped` in the comment; the overall verdict caps at `partial` in that
11
+ * case (we can't declare `pass` without full coverage).
12
+ */
13
+ import { spawnAgent } from './agent.js';
14
+ import { log } from './logger.js';
15
+ import { ghExec } from './rate-limit.js';
16
+ /** Max chars of a single PR diff to include in the prompt. Mirrors pipeline.ts. */
17
+ const MAX_DIFF_CHARS = 10_000;
18
+ const DEFAULT_VERDICT = {
19
+ verdict: 'partial',
20
+ summary: 'Verification output could not be parsed; defaulting to partial.',
21
+ findings: [],
22
+ };
23
+ /**
24
+ * Extract a pr number from a github PR URL like
25
+ * `https://github.com/owner/repo/pull/42`.
26
+ */
27
+ function prNumberFromUrl(url) {
28
+ const m = url.match(/\/pull\/(\d+)(?:\D|$)/);
29
+ return m ? parseInt(m[1], 10) : null;
30
+ }
31
+ function fetchPRDiff(repo, prUrl) {
32
+ const prNum = prNumberFromUrl(prUrl);
33
+ if (prNum === null)
34
+ return '';
35
+ const result = ghExec(`gh pr diff ${prNum} --repo "${repo}"`);
36
+ if (result.exitCode !== 0)
37
+ return '';
38
+ const diff = result.stdout;
39
+ return diff.length > MAX_DIFF_CHARS
40
+ ? diff.slice(0, MAX_DIFF_CHARS) + '\n\n... (diff truncated)'
41
+ : diff;
42
+ }
43
+ /** Extract the last fenced ```json block from agent output, or a trailing JSON object. */
44
+ function extractJsonBlock(output) {
45
+ const fence = /```json\s*([\s\S]*?)\s*```/gi;
46
+ let lastMatch = null;
47
+ let m;
48
+ while ((m = fence.exec(output)) !== null)
49
+ lastMatch = m;
50
+ if (lastMatch)
51
+ return lastMatch[1];
52
+ const trailing = output.match(/\{[\s\S]*\}\s*$/);
53
+ return trailing ? trailing[0] : null;
54
+ }
55
+ function parseVerdict(output) {
56
+ const block = extractJsonBlock(output);
57
+ if (!block)
58
+ return DEFAULT_VERDICT;
59
+ try {
60
+ const parsed = JSON.parse(block);
61
+ const rawVerdict = String(parsed.verdict ?? '').toLowerCase();
62
+ const verdict = ['pass', 'partial', 'fail'].includes(rawVerdict)
63
+ ? rawVerdict
64
+ : 'partial';
65
+ const findings = Array.isArray(parsed.findings)
66
+ ? parsed.findings.flatMap((f) => {
67
+ const issueNum = Number(f.issueNum ?? f.issue ?? 0);
68
+ if (!Number.isFinite(issueNum) || issueNum <= 0)
69
+ return [];
70
+ const rawFindingVerdict = String(f.verdict ?? '').toLowerCase();
71
+ const findingVerdict = ['met', 'partial', 'missing', 'unclear'].includes(rawFindingVerdict)
72
+ ? rawFindingVerdict
73
+ : 'unclear';
74
+ return [
75
+ {
76
+ issueNum,
77
+ criterion: String(f.criterion ?? ''),
78
+ verdict: findingVerdict,
79
+ notes: f.notes ? String(f.notes) : undefined,
80
+ },
81
+ ];
82
+ })
83
+ : [];
84
+ return {
85
+ verdict,
86
+ summary: String(parsed.summary ?? ''),
87
+ findings,
88
+ };
89
+ }
90
+ catch {
91
+ return DEFAULT_VERDICT;
92
+ }
93
+ }
94
+ function buildPrompt(input, diffs) {
95
+ const lines = [
96
+ `You are verifying that epic #${input.epic.number} ("${input.epic.title}") has been met by its merged sub-issue PRs.`,
97
+ '',
98
+ `For each sub-issue, evaluate each acceptance-criterion checklist item against the merged PR diff.`,
99
+ `Return ONLY a JSON object (wrapped in a \`\`\`json code fence) matching this shape:`,
100
+ '',
101
+ '```json',
102
+ '{',
103
+ ' "verdict": "pass" | "partial" | "fail",',
104
+ ' "summary": "one-paragraph overall assessment",',
105
+ ' "findings": [',
106
+ ' { "issueNum": 123, "criterion": "quoted AC text", "verdict": "met" | "partial" | "missing" | "unclear", "notes": "why" }',
107
+ ' ]',
108
+ '}',
109
+ '```',
110
+ '',
111
+ 'Rules:',
112
+ '- `pass` only if every criterion on every evaluated sub-issue is `met`.',
113
+ '- `partial` if some are met and some are `partial`/`missing`/`unclear`.',
114
+ '- `fail` if a majority are `missing` or `unclear`.',
115
+ '- Sub-issues marked as "not yet merged" in the input are out of scope — do not include findings for them.',
116
+ '',
117
+ '---',
118
+ '',
119
+ `## Epic #${input.epic.number}: ${input.epic.title}`,
120
+ '',
121
+ input.epic.body.slice(0, 4000),
122
+ '',
123
+ '## Sub-issues',
124
+ '',
125
+ ];
126
+ for (let i = 0; i < input.subIssues.length; i++) {
127
+ const sub = input.subIssues[i];
128
+ const prUrl = input.mergedPRUrls[i];
129
+ lines.push(`### #${sub.number}: ${sub.title}`);
130
+ if (!prUrl) {
131
+ lines.push('*Not yet merged — skipped in this pass.*', '');
132
+ continue;
133
+ }
134
+ lines.push(`Merged PR: ${prUrl}`, '');
135
+ lines.push('#### Issue body');
136
+ lines.push(sub.body.slice(0, 3000), '');
137
+ const diff = diffs.get(sub.number) ?? '';
138
+ if (diff) {
139
+ lines.push('#### Merged diff');
140
+ lines.push('```diff');
141
+ lines.push(diff);
142
+ lines.push('```', '');
143
+ }
144
+ else {
145
+ lines.push('*(diff unavailable)*', '');
146
+ }
147
+ }
148
+ return lines.join('\n');
149
+ }
150
+ function formatComment(input, parsed, capped) {
151
+ const lines = [
152
+ '## Epic Verification',
153
+ '',
154
+ `**Overall:** ${parsed.verdict.toUpperCase()}${capped ? ' (capped — some sub-issues not yet merged)' : ''}`,
155
+ '',
156
+ ];
157
+ if (parsed.summary) {
158
+ lines.push(parsed.summary, '');
159
+ }
160
+ lines.push('| Sub-issue | PR | Status |', '|---|---|---|');
161
+ for (let i = 0; i < input.subIssues.length; i++) {
162
+ const sub = input.subIssues[i];
163
+ const prUrl = input.mergedPRUrls[i];
164
+ if (!prUrl) {
165
+ lines.push(`| #${sub.number} ${sub.title} | — | not yet merged |`);
166
+ continue;
167
+ }
168
+ const subFindings = parsed.findings.filter((f) => f.issueNum === sub.number);
169
+ const met = subFindings.filter((f) => f.verdict === 'met').length;
170
+ const total = subFindings.length;
171
+ const status = total === 0
172
+ ? 'evaluated'
173
+ : met === total
174
+ ? `pass (${met}/${total})`
175
+ : `partial (${met}/${total})`;
176
+ lines.push(`| #${sub.number} ${sub.title} | [PR](${prUrl}) | ${status} |`);
177
+ }
178
+ lines.push('');
179
+ if (parsed.findings.length > 0) {
180
+ lines.push('<details>', `<summary>Per-criterion findings (${parsed.findings.length})</summary>`, '');
181
+ for (const f of parsed.findings) {
182
+ const notes = f.notes ? ` — ${f.notes}` : '';
183
+ lines.push(`- #${f.issueNum} • **${f.verdict}** — ${f.criterion}${notes}`);
184
+ }
185
+ lines.push('', '</details>', '');
186
+ }
187
+ lines.push('---', '*Verified by alpha-loop*');
188
+ return lines.join('\n');
189
+ }
190
+ /**
191
+ * Run the verification pass. If any sub-issue has no merged PR, the overall
192
+ * verdict is capped at `partial`.
193
+ */
194
+ export async function verifyEpic(input, config, logsDir) {
195
+ // Fetch diffs for every sub-issue that has a merged PR.
196
+ const diffs = new Map();
197
+ for (let i = 0; i < input.subIssues.length; i++) {
198
+ const sub = input.subIssues[i];
199
+ const url = input.mergedPRUrls[i];
200
+ if (!url)
201
+ continue;
202
+ try {
203
+ diffs.set(sub.number, fetchPRDiff(config.repo, url));
204
+ }
205
+ catch (err) {
206
+ log.warn(`Could not fetch diff for sub-issue #${sub.number}: ${err instanceof Error ? err.message : err}`);
207
+ }
208
+ }
209
+ const prompt = buildPrompt(input, diffs);
210
+ const model = config.reviewModel || config.model;
211
+ log.step(`Verifying epic #${input.epic.number} (${input.subIssues.filter((_, i) => input.mergedPRUrls[i]).length}/${input.subIssues.length} sub-issues merged)`);
212
+ let parsed;
213
+ try {
214
+ const result = await spawnAgent({
215
+ agent: config.agent,
216
+ model,
217
+ prompt,
218
+ cwd: process.cwd(),
219
+ logFile: `${logsDir}/epic-${input.epic.number}-verify.log`,
220
+ verbose: config.verbose,
221
+ timeout: config.agentTimeout * 1000,
222
+ });
223
+ parsed = parseVerdict(result.output);
224
+ }
225
+ catch (err) {
226
+ log.warn(`Epic verification agent call failed: ${err instanceof Error ? err.message : err}`);
227
+ parsed = DEFAULT_VERDICT;
228
+ }
229
+ const hasUnmerged = input.mergedPRUrls.some((u) => !u);
230
+ let verdict = parsed.verdict;
231
+ if (hasUnmerged && verdict === 'pass') {
232
+ verdict = 'partial';
233
+ }
234
+ const comment = formatComment(input, { ...parsed, verdict }, hasUnmerged && parsed.verdict === 'pass');
235
+ return { verdict, comment, parsed: { ...parsed, verdict } };
236
+ }
237
+ //# sourceMappingURL=verify-epic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-epic.js","sourceRoot":"","sources":["../../src/lib/verify-epic.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bradtaylorsf/alpha-loop",
3
- "version": "1.13.1",
3
+ "version": "1.14.0",
4
4
  "description": "Agent-agnostic automated development loop: Plan → Build → Test → Review → Ship",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@9.0.0",