issue-flow 0.6.0 → 0.7.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.
- package/dist/{analyze-VVG7UABS.js → analyze-WRFFG2R5.js} +10 -6
- package/dist/analyze-WRFFG2R5.js.map +1 -0
- package/dist/{chunk-WZDCTAWZ.js → chunk-2Y3UO7H2.js} +27 -2
- package/dist/chunk-2Y3UO7H2.js.map +1 -0
- package/dist/{chunk-FPGHTTVV.js → chunk-75K5IKAC.js} +12 -7
- package/dist/chunk-75K5IKAC.js.map +1 -0
- package/dist/{chunk-EHX4J5G5.js → chunk-BTBSVBE3.js} +12 -7
- package/dist/chunk-BTBSVBE3.js.map +1 -0
- package/dist/chunk-CW6UE3NW.js +72 -0
- package/dist/chunk-CW6UE3NW.js.map +1 -0
- package/dist/chunk-EWMSQQL2.js +725 -0
- package/dist/chunk-EWMSQQL2.js.map +1 -0
- package/dist/{chunk-SVOWWZQJ.js → chunk-HS4QWZAO.js} +5 -280
- package/dist/chunk-HS4QWZAO.js.map +1 -0
- package/dist/{chunk-2CSHLHYP.js → chunk-JV7P6UGG.js} +2 -2
- package/dist/chunk-KUDAY57D.js +283 -0
- package/dist/chunk-KUDAY57D.js.map +1 -0
- package/dist/{chunk-4HT4EVYV.js → chunk-OVFYJLOH.js} +56 -13
- package/dist/chunk-OVFYJLOH.js.map +1 -0
- package/dist/{chunk-KWGRBNUG.js → chunk-UX6YAVLT.js} +26 -7
- package/dist/chunk-UX6YAVLT.js.map +1 -0
- package/dist/{chunk-YM3G5BLR.js → chunk-VLSZFMLZ.js} +2 -2
- package/dist/{chunk-7W5VGYXW.js → chunk-YXJPKBPV.js} +39 -64
- package/dist/chunk-YXJPKBPV.js.map +1 -0
- package/dist/{chunk-JTSAL3TI.js → chunk-Z3UIGLZG.js} +10 -5
- package/dist/chunk-Z3UIGLZG.js.map +1 -0
- package/dist/cli.js +65 -20
- package/dist/cli.js.map +1 -1
- package/dist/{config-B564P45C.js → config-UHQ6XXX2.js} +5 -3
- package/dist/execute-K5B4UMUT.js +13 -0
- package/dist/{generate-IN62ARBS.js → generate-DUKQCADD.js} +7 -5
- package/dist/{generate-IN62ARBS.js.map → generate-DUKQCADD.js.map} +1 -1
- package/dist/init-W4HBLW7R.js +9 -0
- package/dist/plan-NKPU45NP.js +15 -0
- package/dist/pr-JYGLLIEF.js +15 -0
- package/dist/pr-review-6H6F4XUY.js +15 -0
- package/dist/prd-FC2ZCEOX.js +15 -0
- package/dist/review-X4NGDZZI.js +13 -0
- package/dist/review-X4NGDZZI.js.map +1 -0
- package/dist/{run-GPBICAD6.js → run-VC647DQI.js} +150 -55
- package/dist/run-VC647DQI.js.map +1 -0
- package/package.json +1 -1
- package/prompts/pr-review.md +144 -0
- package/dist/analyze-VVG7UABS.js.map +0 -1
- package/dist/chunk-4HT4EVYV.js.map +0 -1
- package/dist/chunk-7W5VGYXW.js.map +0 -1
- package/dist/chunk-EHX4J5G5.js.map +0 -1
- package/dist/chunk-FPGHTTVV.js.map +0 -1
- package/dist/chunk-JTSAL3TI.js.map +0 -1
- package/dist/chunk-KWGRBNUG.js.map +0 -1
- package/dist/chunk-SVOWWZQJ.js.map +0 -1
- package/dist/chunk-WZDCTAWZ.js.map +0 -1
- package/dist/execute-PNOFNLZG.js +0 -12
- package/dist/init-5242XSYC.js +0 -9
- package/dist/plan-6KLONWPR.js +0 -14
- package/dist/pr-JLJLMFN3.js +0 -14
- package/dist/prd-TVJDYZXH.js +0 -14
- package/dist/review-FRV4ZMS2.js +0 -12
- package/dist/run-GPBICAD6.js.map +0 -1
- /package/dist/{chunk-2CSHLHYP.js.map → chunk-JV7P6UGG.js.map} +0 -0
- /package/dist/{chunk-YM3G5BLR.js.map → chunk-VLSZFMLZ.js.map} +0 -0
- /package/dist/{config-B564P45C.js.map → config-UHQ6XXX2.js.map} +0 -0
- /package/dist/{execute-PNOFNLZG.js.map → execute-K5B4UMUT.js.map} +0 -0
- /package/dist/{init-5242XSYC.js.map → init-W4HBLW7R.js.map} +0 -0
- /package/dist/{plan-6KLONWPR.js.map → plan-NKPU45NP.js.map} +0 -0
- /package/dist/{pr-JLJLMFN3.js.map → pr-JYGLLIEF.js.map} +0 -0
- /package/dist/{prd-TVJDYZXH.js.map → pr-review-6H6F4XUY.js.map} +0 -0
- /package/dist/{review-FRV4ZMS2.js.map → prd-FC2ZCEOX.js.map} +0 -0
|
@@ -4,21 +4,19 @@ import {
|
|
|
4
4
|
retryDelaySeconds,
|
|
5
5
|
sleep
|
|
6
6
|
} from "./chunk-HDV3YDTG.js";
|
|
7
|
+
import {
|
|
8
|
+
publishGitState
|
|
9
|
+
} from "./chunk-CW6UE3NW.js";
|
|
7
10
|
import {
|
|
8
11
|
applyPlaceholders,
|
|
9
12
|
loadPrompt
|
|
10
13
|
} from "./chunk-SLHZPB3C.js";
|
|
11
14
|
import {
|
|
12
15
|
createConfig,
|
|
13
|
-
getBaseBranch,
|
|
14
|
-
getCommitsSince,
|
|
15
|
-
getCurrentBranch,
|
|
16
16
|
resolvePaths,
|
|
17
|
-
run,
|
|
18
17
|
validateDependencies
|
|
19
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-OVFYJLOH.js";
|
|
20
19
|
import {
|
|
21
|
-
NullPublisher,
|
|
22
20
|
allStoriesPass,
|
|
23
21
|
clearLastError,
|
|
24
22
|
formatDuration,
|
|
@@ -43,7 +41,7 @@ import {
|
|
|
43
41
|
trimErrorMessage,
|
|
44
42
|
useColor,
|
|
45
43
|
useUnicode
|
|
46
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-2Y3UO7H2.js";
|
|
47
45
|
|
|
48
46
|
// src/core/engine.ts
|
|
49
47
|
import { existsSync } from "fs";
|
|
@@ -214,6 +212,38 @@ function printSummaryBox(status, iterations, totalRetries, elapsedSeconds, plan,
|
|
|
214
212
|
console.log("");
|
|
215
213
|
printBox(boxLines);
|
|
216
214
|
}
|
|
215
|
+
function buildRunSummaryLines(info) {
|
|
216
|
+
const lines = [
|
|
217
|
+
` Branch: ${info.branchName}${info.noBranch ? " (current)" : ""}`,
|
|
218
|
+
` Stories: ${info.storyCount}`,
|
|
219
|
+
` Duration: ${formatDuration(info.elapsedSeconds)}`
|
|
220
|
+
];
|
|
221
|
+
if (!info.noBranch) {
|
|
222
|
+
lines.push(` PR: ${info.prUrl}`);
|
|
223
|
+
}
|
|
224
|
+
const review = info.prReview;
|
|
225
|
+
if (review) {
|
|
226
|
+
const verdict = review.recommendation ?? (review.requestedChanges ? "REQUEST_CHANGES" : "unknown");
|
|
227
|
+
lines.push(` Review: ${verdict}`);
|
|
228
|
+
if (review.reportPath !== null) {
|
|
229
|
+
lines.push(` Report: ${review.reportPath}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return lines;
|
|
233
|
+
}
|
|
234
|
+
function printRunSummary(info) {
|
|
235
|
+
console.log("");
|
|
236
|
+
if (info.prReview?.requestedChanges) {
|
|
237
|
+
printWarning(
|
|
238
|
+
`Pipeline finished for issue #${info.issueNumber}, but the PR review requested changes.`
|
|
239
|
+
);
|
|
240
|
+
} else {
|
|
241
|
+
printSuccess(`Pipeline complete for issue #${info.issueNumber}!`);
|
|
242
|
+
}
|
|
243
|
+
for (const line of buildRunSummaryLines(info)) {
|
|
244
|
+
console.log(line);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
217
247
|
|
|
218
248
|
// src/core/executor.ts
|
|
219
249
|
import { execa } from "execa";
|
|
@@ -242,61 +272,6 @@ ${stderr}` : "");
|
|
|
242
272
|
};
|
|
243
273
|
}
|
|
244
274
|
|
|
245
|
-
// src/core/session-git.ts
|
|
246
|
-
async function listPullRequests(branch) {
|
|
247
|
-
if (!branch) return [];
|
|
248
|
-
const result = await run("gh", [
|
|
249
|
-
"pr",
|
|
250
|
-
"list",
|
|
251
|
-
"--head",
|
|
252
|
-
branch,
|
|
253
|
-
"--state",
|
|
254
|
-
"all",
|
|
255
|
-
"--json",
|
|
256
|
-
"number,url,title",
|
|
257
|
-
"--limit",
|
|
258
|
-
"10"
|
|
259
|
-
]);
|
|
260
|
-
if (result.exitCode !== 0) return [];
|
|
261
|
-
try {
|
|
262
|
-
const parsed = JSON.parse(result.stdout || "[]");
|
|
263
|
-
if (!Array.isArray(parsed)) return [];
|
|
264
|
-
return parsed.filter(
|
|
265
|
-
(pr) => typeof pr === "object" && pr !== null && typeof pr.number === "number" && typeof pr.url === "string" && typeof pr.title === "string"
|
|
266
|
-
).map((pr) => ({ number: pr.number, url: pr.url, title: pr.title }));
|
|
267
|
-
} catch {
|
|
268
|
-
return [];
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
var defaultSources = {
|
|
272
|
-
currentBranch: getCurrentBranch,
|
|
273
|
-
baseBranch: getBaseBranch,
|
|
274
|
-
commitsSince: getCommitsSince,
|
|
275
|
-
pullRequests: listPullRequests,
|
|
276
|
-
now: isoNow
|
|
277
|
-
};
|
|
278
|
-
async function publishGitState(publisher, sources = {}) {
|
|
279
|
-
if (publisher instanceof NullPublisher) return;
|
|
280
|
-
const src = { ...defaultSources, ...sources };
|
|
281
|
-
try {
|
|
282
|
-
const branch = await src.currentBranch();
|
|
283
|
-
const baseBranch = await src.baseBranch();
|
|
284
|
-
const [commits, pullRequests] = await Promise.all([
|
|
285
|
-
src.commitsSince(baseBranch),
|
|
286
|
-
src.pullRequests(branch)
|
|
287
|
-
]);
|
|
288
|
-
publisher.publish({
|
|
289
|
-
type: "git:update",
|
|
290
|
-
at: src.now(),
|
|
291
|
-
branch,
|
|
292
|
-
baseBranch,
|
|
293
|
-
commits,
|
|
294
|
-
pullRequests
|
|
295
|
-
});
|
|
296
|
-
} catch {
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
275
|
// src/core/engine.ts
|
|
301
276
|
function emitLog(message) {
|
|
302
277
|
const cb = getOutputCallback();
|
|
@@ -562,7 +537,7 @@ async function runExecute(positionalMaxIter, options) {
|
|
|
562
537
|
}
|
|
563
538
|
|
|
564
539
|
export {
|
|
565
|
-
|
|
540
|
+
printRunSummary,
|
|
566
541
|
runExecute
|
|
567
542
|
};
|
|
568
|
-
//# sourceMappingURL=chunk-
|
|
543
|
+
//# sourceMappingURL=chunk-YXJPKBPV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/engine.ts","../src/ui/progress.ts","../src/ui/summary.ts","../src/core/executor.ts","../src/commands/execute.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { cp, mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { EngineConfig, ResolvedPaths, TaskPlan } from '../types.js';\nimport { printError, printInfo, printRetry, printSuccess, printWarning } from '../ui/logger.js';\nimport { printIterationHeader } from '../ui/progress.js';\nimport { printStartupHeader, printSummaryBox } from '../ui/summary.js';\nimport { isTransientFailure, retryDelaySeconds, sleep } from '../utils/retry.js';\nimport { executeClaude } from './executor.js';\nimport { applyPlaceholders, loadPrompt } from './prompt-resolver.js';\nimport { publishGitState } from './session-git.js';\nimport { getSessionPublisher } from './session-publisher.js';\nimport {\n allStoriesPass,\n clearLastError,\n initializeState,\n isoNow,\n loadTaskPlan,\n markIssueCompleted,\n markIssueInProgress,\n saveTaskPlan,\n setLastError,\n trimErrorMessage,\n} from './state-manager.js';\nimport { getOutputCallback, getStoryUpdateCallback, isVerbose } from './verbose.js';\n\n/**\n * Emit a message through the output callback if available, otherwise console.log.\n * Used for bare console.log calls in engine functions so they route through listr2.\n */\nfunction emitLog(message: string): void {\n const cb = getOutputCallback();\n if (cb) {\n // Skip empty lines in listr2 context — they don't render meaningfully\n if (message) {\n cb(message);\n }\n } else {\n console.log(message);\n }\n}\n\n/**\n * Initialize the progress file if it doesn't exist.\n */\nasync function ensureProgressFile(progressFile: string): Promise<void> {\n if (!existsSync(progressFile)) {\n const content = `# Issue Flow Progress Log\\nStarted: ${new Date().toString()}\\n---\\n`;\n await writeFile(progressFile, content, 'utf-8');\n }\n}\n\n/**\n * Archive previous run artifacts if the branch has changed.\n */\nasync function archiveIfBranchChanged(plan: TaskPlan, paths: ResolvedPaths): Promise<void> {\n const { lastBranchFile, archiveDir, prdFile, progressFile } = paths;\n\n if (!existsSync(lastBranchFile)) {\n return;\n }\n\n const currentBranch = plan.branchName ?? '';\n let lastBranch = '';\n\n try {\n lastBranch = (await readFile(lastBranchFile, 'utf-8')).trim();\n } catch {\n return;\n }\n\n if (currentBranch && lastBranch && currentBranch !== lastBranch) {\n const dateStr = new Date().toISOString().split('T')[0];\n const folderName = lastBranch.replace(/^issue\\//, '').replace(/[<>:\"|?*\\\\]/g, '_');\n const archiveFolder = join(archiveDir, `${dateStr}-${folderName}`);\n\n printInfo(`Archiving previous run: ${lastBranch}`);\n await mkdir(archiveFolder, { recursive: true });\n\n if (existsSync(prdFile)) {\n await cp(prdFile, join(archiveFolder, 'tasks.json'));\n }\n if (existsSync(progressFile)) {\n await cp(progressFile, join(archiveFolder, 'progress.txt'));\n }\n\n printInfo(` Archived to: ${archiveFolder}`);\n\n // Reset progress file for new run\n await writeFile(\n progressFile,\n `# Issue Flow Progress Log\\nStarted: ${new Date().toString()}\\n---\\n`,\n 'utf-8',\n );\n }\n}\n\n/**\n * Write the current branch to the last-branch tracking file.\n */\nasync function trackBranch(plan: TaskPlan, lastBranchFile: string): Promise<void> {\n const branch = plan.branchName ?? '';\n if (branch) {\n await writeFile(lastBranchFile, `${branch}\\n`, 'utf-8');\n }\n}\n\n/**\n * Run the issue-flow engine loop.\n *\n * This replicates the full execution flow:\n * 1. Load and initialize task plan state\n * 2. Check for early exit (already complete)\n * 3. Archive previous run if branch changed\n * 4. Resolve prompt\n * 5. Main loop: iterate, execute Claude, handle results\n * 6. Print summary\n */\nexport async function runEngine(config: EngineConfig, paths: ResolvedPaths): Promise<number> {\n // Load task plan\n if (!existsSync(paths.prdFile)) {\n printError(`PRD file not found at ${paths.prdFile}`);\n if (config.issueNumber) {\n emitLog(`Have you run the resolve-issue skill for issue #${config.issueNumber} first?`);\n }\n return 1;\n }\n\n let plan = await loadTaskPlan(paths.prdFile);\n plan = initializeState(plan);\n await saveTaskPlan(paths.prdFile, plan);\n\n // Check if already completed\n if (plan.issueStatus === 'completed' && allStoriesPass(plan)) {\n emitLog(`Issue already marked complete in ${paths.prdFile}`);\n return 0;\n }\n\n // Warn if marked complete but stories still pending\n if (plan.issueStatus === 'completed' && !allStoriesPass(plan)) {\n printWarning(\n 'Issue marked completed but some stories are still pending. Resetting to in_progress.',\n );\n plan = markIssueInProgress(plan);\n plan = setLastError(\n plan,\n 'invalid_completion_state',\n 'tasks.json claimed the issue was completed before every story had passes=true.',\n );\n await saveTaskPlan(paths.prdFile, plan);\n }\n\n // Check if all stories already pass\n if (allStoriesPass(plan)) {\n emitLog('All user stories already pass. Marking issue as completed.');\n plan = markIssueCompleted(plan);\n await saveTaskPlan(paths.prdFile, plan);\n return 0;\n }\n\n // Archive previous run if branch changed\n await archiveIfBranchChanged(plan, paths);\n\n // Track current branch\n await trackBranch(plan, paths.lastBranchFile);\n\n // Initialize progress file\n await ensureProgressFile(paths.progressFile);\n\n // Load prompt template\n const promptTemplate = await loadPrompt('execute');\n\n // Print startup header\n printStartupHeader(config, plan);\n\n const startTime = Date.now();\n let i = 0;\n let retryCount = 0;\n let totalRetryCount = 0;\n\n // Main loop\n while (true) {\n // Check iteration limit\n if (config.maxIterations !== undefined && i >= config.maxIterations) {\n break;\n }\n\n i++;\n getSessionPublisher().publish({ type: 'iteration:start', at: isoNow(), iteration: i });\n\n // Re-read plan to get latest state\n plan = await loadTaskPlan(paths.prdFile);\n\n if (isVerbose()) {\n printIterationHeader(i, config.maxIterations, plan.userStories);\n }\n\n // Apply placeholders to prompt\n const prompt = applyPlaceholders(promptTemplate, {\n __PRD_FILE__: paths.prdFile,\n __PROGRESS_FILE__: paths.progressFile,\n });\n\n const iterationStartedAt = isoNow();\n plan = markIssueInProgress(plan, iterationStartedAt);\n await saveTaskPlan(paths.prdFile, plan);\n\n // Execute Claude\n const result = await executeClaude(prompt);\n\n if (result.exitCode !== 0) {\n const errorMessage = trimErrorMessage(result.output);\n\n if (isTransientFailure(result.exitCode, result.output)) {\n retryCount++;\n totalRetryCount++;\n plan = await loadTaskPlan(paths.prdFile);\n plan = setLastError(plan, 'transient_claude_failure', errorMessage);\n await saveTaskPlan(paths.prdFile, plan);\n\n if (!config.retryForever && retryCount > config.retryLimit) {\n const elapsed = Math.floor((Date.now() - startTime) / 1000);\n plan = await loadTaskPlan(paths.prdFile);\n printSummaryBox(\n 'failed',\n i,\n totalRetryCount,\n elapsed,\n plan,\n `Exceeded retry limit (${config.retryLimit}) on transient errors`,\n );\n return result.exitCode;\n }\n\n const delaySeconds = retryDelaySeconds(\n retryCount,\n config.backoffBaseSeconds,\n config.backoffMaxSeconds,\n );\n getSessionPublisher().publish({\n type: 'retry',\n at: isoNow(),\n attempt: retryCount,\n delaySeconds,\n reason: 'transient_claude_failure',\n });\n\n if (isVerbose()) {\n emitLog('');\n }\n printRetry(\n `Transient Claude failure on iteration ${i} (attempt ${retryCount}). Retrying in ${delaySeconds}s.`,\n );\n\n // Stay within current iteration budget\n i--;\n await sleep(delaySeconds);\n continue;\n }\n\n // Fatal failure\n plan = await loadTaskPlan(paths.prdFile);\n plan = setLastError(plan, 'fatal_claude_failure', errorMessage);\n await saveTaskPlan(paths.prdFile, plan);\n\n const elapsed = Math.floor((Date.now() - startTime) / 1000);\n printSummaryBox(\n 'failed',\n i,\n totalRetryCount,\n elapsed,\n plan,\n `Claude CLI failed with exit code ${result.exitCode}`,\n );\n return result.exitCode;\n }\n\n // Success — reset retry counter\n retryCount = 0;\n plan = await loadTaskPlan(paths.prdFile);\n plan = clearLastError(plan, iterationStartedAt);\n await saveTaskPlan(paths.prdFile, plan);\n\n // Notify story progress listeners (e.g., listr2 subtasks)\n const storyUpdateCb = getStoryUpdateCallback();\n if (storyUpdateCb) {\n storyUpdateCb(plan.userStories);\n }\n getSessionPublisher().publish({\n type: 'stories:update',\n at: isoNow(),\n stories: plan.userStories,\n });\n getSessionPublisher().publish({ type: 'iteration:end', at: isoNow(), iteration: i });\n // Low-frequency commit/PR enrichment: iteration end is one of the only\n // two sanctioned points (the other is phase boundaries in run.ts).\n await publishGitState(getSessionPublisher());\n\n // Check for completion signal\n if (result.output.includes('<promise>COMPLETE</promise>')) {\n plan = await loadTaskPlan(paths.prdFile);\n if (allStoriesPass(plan)) {\n plan = markIssueCompleted(plan);\n await saveTaskPlan(paths.prdFile, plan);\n\n const elapsed = Math.floor((Date.now() - startTime) / 1000);\n printSummaryBox('success', i, totalRetryCount, elapsed, plan);\n return 0;\n }\n\n plan = setLastError(\n plan,\n 'invalid_completion_signal',\n 'Claude returned <promise>COMPLETE</promise> before every story had passes=true.',\n );\n await saveTaskPlan(paths.prdFile, plan);\n\n emitLog('');\n printWarning(\n 'Claude returned a completion signal, but tasks.json still has pending stories. Ignoring completion and continuing.',\n );\n }\n\n if (isVerbose()) {\n printSuccess(`Iteration ${i} complete. Continuing...`);\n }\n await sleep(2);\n }\n\n // Reached max iterations\n const elapsed = Math.floor((Date.now() - startTime) / 1000);\n plan = await loadTaskPlan(paths.prdFile);\n printSummaryBox(\n 'incomplete',\n config.maxIterations ?? i,\n totalRetryCount,\n elapsed,\n plan,\n 'Reached max iterations without completing all tasks.',\n );\n return 1;\n}\n","import chalk from 'chalk';\nimport { getOutputCallback } from '../core/verbose.js';\nimport type { UserStory } from '../types.js';\nimport { getIcons, useColor, useUnicode } from './logger.js';\n\n/**\n * Print a visual progress bar showing passed/total stories.\n */\nexport function printProgressBar(passed: number, total: number): string {\n const barWidth = 20;\n let pct = 0;\n let filled = 0;\n\n if (total > 0) {\n pct = Math.floor((passed * 100) / total);\n filled = Math.floor((passed * barWidth) / total);\n }\n\n const empty = barWidth - filled;\n const fillChar = useUnicode() ? '\\u2588' : '#';\n const emptyChar = useUnicode() ? '\\u2591' : '-';\n\n const bar = fillChar.repeat(filled) + emptyChar.repeat(empty);\n const text = `${passed}/${total} (${pct}%)`;\n\n if (useColor()) {\n return `${chalk.green(bar)} ${text}`;\n }\n return `${bar} ${text}`;\n}\n\n/**\n * Print the iteration header showing story statuses and progress bar.\n *\n * When a global output callback is set (e.g., inside a listr2 task),\n * output is routed through it instead of console.log.\n */\nexport function printIterationHeader(\n iteration: number,\n maxIter: number | undefined,\n stories: UserStory[],\n): void {\n const icons = getIcons();\n const colored = useColor();\n const cb = getOutputCallback();\n\n const iterLabel = maxIter ? `Iteration ${iteration} of ${maxIter}` : `Iteration ${iteration}`;\n\n const total = stories.length;\n const passed = stories.filter((s) => s.passes).length;\n\n const lines: string[] = [];\n\n if (colored) {\n lines.push(chalk.blue(`\\u2501\\u2501\\u2501 ${icons.start} ${iterLabel} \\u2501\\u2501\\u2501`));\n } else {\n lines.push(`--- ${icons.start} ${iterLabel} ---`);\n }\n\n // Display each story status\n let foundFirstPending = false;\n for (const story of stories) {\n let icon: string;\n let colorFn: (s: string) => string;\n\n if (story.passes) {\n icon = icons.success;\n colorFn = colored ? chalk.green : (s: string) => s;\n } else if (!foundFirstPending) {\n // First non-passing story = current in-progress\n icon = icons.pending;\n colorFn = colored ? chalk.yellow : (s: string) => s;\n foundFirstPending = true;\n } else {\n // Not yet reached\n icon = icons.notReached;\n colorFn = colored ? chalk.gray : (s: string) => s;\n }\n\n lines.push(colorFn(` ${icon} ${story.id}: ${story.title}`));\n }\n\n lines.push(` ${printProgressBar(passed, total)}`);\n\n if (cb) {\n // Send as single output to listr2 task context\n cb(lines.join('\\n'));\n } else {\n console.log('');\n for (const line of lines) {\n console.log(line);\n }\n console.log('');\n }\n}\n","import chalk from 'chalk';\nimport type { EngineConfig, PrReviewRecommendation, TaskPlan } from '../types.js';\nimport {\n formatDuration,\n getIcons,\n getTermWidth,\n printSuccess,\n printWarning,\n useColor,\n useUnicode,\n} from './logger.js';\n\n/**\n * Truncate or pad a string to fit within a given width.\n */\nfunction fitLine(text: string, width: number): string {\n if (text.length > width) {\n return text.substring(0, width);\n }\n return text.padEnd(width);\n}\n\n/**\n * Print a box with border characters around content lines.\n * Lines equal to \"---\" render as separator rows.\n */\nexport function printBox(lines: string[]): void {\n const colored = useColor();\n const unicode = useUnicode();\n const termWidth = getTermWidth();\n\n // Find max content width\n let maxContentWidth = 0;\n for (const line of lines) {\n if (line !== '---' && line.length > maxContentWidth) {\n maxContentWidth = line.length;\n }\n }\n\n // Cap to terminal width (border + padding = 4 chars)\n const available = termWidth - 4;\n if (maxContentWidth > available) {\n maxContentWidth = available;\n }\n if (maxContentWidth < 20) {\n maxContentWidth = 20;\n }\n\n // Box drawing characters\n const tl = unicode ? '\\u256D' : '+';\n const tr = unicode ? '\\u256E' : '+';\n const bl = unicode ? '\\u2570' : '+';\n const br = unicode ? '\\u256F' : '+';\n const h = unicode ? '\\u2500' : '-';\n const v = unicode ? '\\u2502' : '|';\n const sepL = unicode ? '\\u251C' : '+';\n const sepR = unicode ? '\\u2524' : '+';\n\n const hrule = h.repeat(maxContentWidth + 2);\n\n const blue = colored ? chalk.blue : (s: string) => s;\n const _reset = (s: string) => s;\n\n // Top border\n console.log(blue(`${tl}${hrule}${tr}`));\n\n // Content lines\n for (const line of lines) {\n if (line === '---') {\n console.log(blue(`${sepL}${hrule}${sepR}`));\n } else {\n const fitted = fitLine(line, maxContentWidth);\n console.log(`${blue(v)} ${fitted} ${blue(v)}`);\n }\n }\n\n // Bottom border\n console.log(blue(`${bl}${hrule}${br}`));\n}\n\n/**\n * Print the startup header box showing engine configuration.\n */\nexport function printStartupHeader(config: EngineConfig, plan: TaskPlan): void {\n const icons = getIcons();\n\n const storiesTotal = plan.userStories.length;\n const storiesPassing = plan.userStories.filter((s) => s.passes).length;\n const branchName = plan.branchName ?? 'N/A';\n\n const issueLabel = config.issueNumber ? `Issue #${config.issueNumber}` : 'Standalone mode';\n\n const maxIterLabel =\n config.maxIterations !== undefined ? String(config.maxIterations) : 'unlimited';\n\n const retryLabel = config.retryForever\n ? 'unlimited retries'\n : `${config.retryLimit} consecutive retries`;\n\n printBox([\n `${icons.start} Issue Flow`,\n '---',\n `Issue: ${issueLabel}`,\n `Branch: ${branchName}`,\n `Stories: ${storiesPassing}/${storiesTotal} passing`,\n `Iterations: ${maxIterLabel}`,\n `Retries: ${retryLabel}`,\n ]);\n}\n\n// Re-export formatDuration from logger to maintain backwards compatibility\nexport { formatDuration } from './logger.js';\n\n/**\n * Print the final summary box.\n */\nexport function printSummaryBox(\n status: 'success' | 'incomplete' | 'failed',\n iterations: number,\n totalRetries: number,\n elapsedSeconds: number,\n plan: TaskPlan,\n extraInfo?: string,\n): void {\n const icons = getIcons();\n\n const storiesTotal = plan.userStories.length;\n const storiesPassing = plan.userStories.filter((s) => s.passes).length;\n const duration = formatDuration(elapsedSeconds);\n\n let statusIcon: string;\n let statusLabel: string;\n\n switch (status) {\n case 'success':\n statusIcon = icons.success;\n statusLabel = 'Completed';\n break;\n case 'incomplete':\n statusIcon = icons.warn;\n statusLabel = 'Incomplete';\n break;\n case 'failed':\n statusIcon = icons.fail;\n statusLabel = 'Failed';\n break;\n }\n\n const boxLines = [\n `${icons.end} Issue Flow Summary`,\n '---',\n `Status: ${statusIcon} ${statusLabel}`,\n `Stories: ${storiesPassing}/${storiesTotal} passing`,\n `Iterations: ${iterations}`,\n `Duration: ${duration}`,\n `Retries: ${totalRetries}`,\n ];\n\n if (extraInfo) {\n boxLines.push('---');\n boxLines.push(extraInfo);\n }\n\n console.log('');\n printBox(boxLines);\n}\n\n/**\n * What the optional `pr-review` phase produced, as far as the summary cares.\n * `null` in `recommendation` means the verdict could not be recovered from\n * disk — the exit code still told us whether changes were requested.\n */\nexport interface RunSummaryPrReview {\n requestedChanges: boolean;\n recommendation: PrReviewRecommendation | null;\n reportPath: string | null;\n}\n\n/**\n * Everything the final `run` summary prints, already resolved by the caller.\n */\nexport interface RunSummaryInfo {\n issueNumber: string;\n /** 'unknown' when the branch could not be detected. */\n branchName: string;\n /** Pipelines run with --no-branch open no Pull Request. */\n noBranch: boolean;\n storyCount: number;\n elapsedSeconds: number;\n /** 'unknown' when no Pull Request could be resolved. */\n prUrl: string;\n /** Only set when the pr-review phase actually ran. */\n prReview?: RunSummaryPrReview | null;\n}\n\n/**\n * Detail lines of the final `run` summary (everything below the headline).\n *\n * Kept separate from the printing so the shape is testable without capturing\n * stdout. Without `prReview` the lines are exactly the ones the pipeline has\n * always printed.\n */\nexport function buildRunSummaryLines(info: RunSummaryInfo): string[] {\n const lines = [\n ` Branch: ${info.branchName}${info.noBranch ? ' (current)' : ''}`,\n ` Stories: ${info.storyCount}`,\n ` Duration: ${formatDuration(info.elapsedSeconds)}`,\n ];\n\n if (!info.noBranch) {\n lines.push(` PR: ${info.prUrl}`);\n }\n\n const review = info.prReview;\n if (review) {\n // The exit code is the source of truth for the verdict, so a report whose\n // recommendation could not be read still reports REQUEST_CHANGES.\n const verdict =\n review.recommendation ?? (review.requestedChanges ? 'REQUEST_CHANGES' : 'unknown');\n lines.push(` Review: ${verdict}`);\n if (review.reportPath !== null) {\n lines.push(` Report: ${review.reportPath}`);\n }\n }\n\n return lines;\n}\n\n/**\n * Print the final summary of a `run` (the flat listing, not the box used by\n * the execute engine).\n */\nexport function printRunSummary(info: RunSummaryInfo): void {\n console.log('');\n if (info.prReview?.requestedChanges) {\n printWarning(\n `Pipeline finished for issue #${info.issueNumber}, but the PR review requested changes.`,\n );\n } else {\n printSuccess(`Pipeline complete for issue #${info.issueNumber}!`);\n }\n for (const line of buildRunSummaryLines(info)) {\n console.log(line);\n }\n}\n","import { execa } from 'execa';\nimport type { ClaudeResult } from '../types.js';\nimport { getOutputCallback } from './verbose.js';\n\n/**\n * Execute Claude CLI with a prompt piped to stdin.\n *\n * Runs: echo $PROMPT | claude --dangerously-skip-permissions --print\n *\n * Captures combined stdout+stderr output. Does not throw on non-zero exit codes.\n * Output is returned via ClaudeResult and routed through the output callback infrastructure.\n */\nexport async function executeClaude(prompt: string): Promise<ClaudeResult> {\n const result = await execa('claude', ['--dangerously-skip-permissions', '--print'], {\n input: prompt,\n reject: false,\n timeout: 0, // No timeout — let the engine handle iteration limits\n stripFinalNewline: false,\n });\n\n // Combine stdout and stderr to match Bash's 2>&1 behavior\n const stdout = result.stdout?.toString() ?? '';\n const stderr = result.stderr?.toString() ?? '';\n const output = stdout + (stderr ? `\\n${stderr}` : '');\n\n // Forward output through the global callback (listr2 renderer) when active\n const onOutput = getOutputCallback();\n if (onOutput) {\n const trimmed = output.trim();\n if (trimmed) {\n onOutput(trimmed);\n }\n }\n\n return {\n exitCode: result.exitCode ?? 1,\n output,\n };\n}\n","import { createConfig, resolvePaths, validateDependencies } from '../config.js';\nimport { runEngine } from '../core/engine.js';\nimport { allStoriesPass, loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { printError } from '../ui/logger.js';\n\nexport interface ExecuteOptions {\n issue?: string;\n maxIterations?: number;\n retryLimit?: number;\n retryForever?: boolean;\n}\n\nexport async function runExecute(\n positionalMaxIter: number | undefined,\n options: ExecuteOptions,\n): Promise<number> {\n const errors = await validateDependencies();\n if (errors.length > 0) {\n printError('The following required tools are not installed:');\n for (const err of errors) {\n console.log(err);\n }\n return 1;\n }\n\n const maxIterations = options.maxIterations ?? positionalMaxIter;\n\n const config = createConfig({\n issueNumber: options.issue,\n maxIterations,\n retryLimit: options.retryLimit,\n retryForever: options.retryForever,\n });\n\n const paths = await resolvePaths(config);\n const exitCode = await runEngine(config, paths);\n\n // Update pipeline state if all stories pass\n if (exitCode === 0 && config.issueNumber) {\n try {\n const plan = await loadTaskPlan(paths.prdFile);\n if (allStoriesPass(plan)) {\n plan.pipeline.executionCompleted = true;\n await saveTaskPlan(paths.prdFile, plan);\n }\n } catch {\n // Non-critical — engine already handled state\n }\n }\n\n return exitCode;\n}\n"],"mappings":"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","names":["chalk","chalk","elapsed"]}
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
issuePlaceholders,
|
|
4
|
-
resolveCommandIssue
|
|
4
|
+
resolveCommandIssue
|
|
5
|
+
} from "./chunk-HS4QWZAO.js";
|
|
6
|
+
import {
|
|
5
7
|
runHeadless
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KUDAY57D.js";
|
|
7
9
|
import {
|
|
8
10
|
applyPlaceholders,
|
|
9
11
|
loadPrompt
|
|
10
12
|
} from "./chunk-SLHZPB3C.js";
|
|
13
|
+
import {
|
|
14
|
+
getIssueDir
|
|
15
|
+
} from "./chunk-OVFYJLOH.js";
|
|
11
16
|
import {
|
|
12
17
|
getGlobalTimeout,
|
|
13
18
|
loadTaskPlan,
|
|
14
19
|
printError,
|
|
15
20
|
printSuccess,
|
|
16
21
|
saveTaskPlan
|
|
17
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2Y3UO7H2.js";
|
|
18
23
|
|
|
19
24
|
// src/commands/review.ts
|
|
20
25
|
import { join } from "path";
|
|
@@ -42,7 +47,7 @@ function parseReviewResult(output) {
|
|
|
42
47
|
}
|
|
43
48
|
async function runReview(issue, resolvedIssue) {
|
|
44
49
|
const issueNumber = issue.replace(/^#/, "");
|
|
45
|
-
const issueDir =
|
|
50
|
+
const issueDir = await getIssueDir(issueNumber);
|
|
46
51
|
const tasksPath = join(issueDir, "tasks.json");
|
|
47
52
|
const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);
|
|
48
53
|
if (!resolution.ok) {
|
|
@@ -87,4 +92,4 @@ async function runReview(issue, resolvedIssue) {
|
|
|
87
92
|
export {
|
|
88
93
|
runReview
|
|
89
94
|
};
|
|
90
|
-
//# sourceMappingURL=chunk-
|
|
95
|
+
//# sourceMappingURL=chunk-Z3UIGLZG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/review.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { issuePlaceholders, resolveCommandIssue } from '../issues/context.js';\nimport type { ResolvedIssue } from '../issues/types.js';\nimport { printError, printSuccess } from '../ui/logger.js';\nimport { getIssueDir } from '../utils/git.js';\n\nexport interface ReviewResult {\n status: 'PASS' | 'FAIL';\n findings?: string;\n}\n\n/**\n * Parse the <review-result> block from headless output.\n */\nfunction parseReviewResult(output: string): ReviewResult {\n const match = output.match(/<review-result>([\\s\\S]*?)<\\/review-result>/);\n if (!match) {\n // Try to detect PASS/FAIL from the raw output\n if (/STATUS:\\s*PASS/i.test(output)) {\n return { status: 'PASS' };\n }\n if (/STATUS:\\s*FAIL/i.test(output)) {\n const findingsMatch = output.match(/FINDINGS:([\\s\\S]*?)(?:$|<\\/)/);\n return { status: 'FAIL', findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings' };\n }\n // Default to PASS if no explicit status found and no errors\n return { status: 'PASS' };\n }\n\n const block = match[1];\n if (/STATUS:\\s*PASS/i.test(block)) {\n return { status: 'PASS' };\n }\n\n const findingsMatch = block.match(/FINDINGS:([\\s\\S]*)/);\n return {\n status: 'FAIL',\n findings: findingsMatch?.[1]?.trim() ?? 'Unknown findings',\n };\n}\n\nexport async function runReview(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const issueDir = await getIssueDir(issueNumber);\n const tasksPath = join(issueDir, 'tasks.json');\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n const template = await loadPrompt('review');\n const prompt = applyPlaceholders(template, {\n __ISSUE_NUMBER__: issueNumber,\n __TASKS_PATH__: tasksPath,\n ...issuePlaceholders(resolution.resolved),\n });\n\n const result = await runHeadless({\n prompt,\n maxTurns: 25,\n timeout: getGlobalTimeout() ?? 300_000,\n outputFormat: 'text',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n statusMessage: `Reviewing issue #${issueNumber} resolution...`,\n });\n\n if (!result.success) {\n printError(`Review failed: ${result.error}`);\n return 1;\n }\n\n const review = parseReviewResult(result.result);\n\n if (review.status === 'PASS') {\n // Update pipeline state\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = true;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n printSuccess('Review PASSED — implementation meets acceptance criteria');\n return 0;\n }\n\n printError('Review FAILED — issues found:');\n if (review.findings) {\n console.log(review.findings);\n }\n return 1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY;AAkBrB,SAAS,kBAAkB,QAA8B;AACvD,QAAM,QAAQ,OAAO,MAAM,4CAA4C;AACvE,MAAI,CAAC,OAAO;AAEV,QAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,aAAO,EAAE,QAAQ,OAAO;AAAA,IAC1B;AACA,QAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,YAAMA,iBAAgB,OAAO,MAAM,8BAA8B;AACjE,aAAO,EAAE,QAAQ,QAAQ,UAAUA,iBAAgB,CAAC,GAAG,KAAK,KAAK,mBAAmB;AAAA,IACtF;AAEA,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAEA,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,kBAAkB,KAAK,KAAK,GAAG;AACjC,WAAO,EAAE,QAAQ,OAAO;AAAA,EAC1B;AAEA,QAAM,gBAAgB,MAAM,MAAM,oBAAoB;AACtD,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,UAAU,gBAAgB,CAAC,GAAG,KAAK,KAAK;AAAA,EAC1C;AACF;AAEA,eAAsB,UAAU,OAAe,eAAgD;AAC7F,QAAM,cAAc,MAAM,QAAQ,MAAM,EAAE;AAC1C,QAAM,WAAW,MAAM,YAAY,WAAW;AAC9C,QAAM,YAAY,KAAK,UAAU,YAAY;AAE7C,QAAM,aAAa,MAAM,oBAAoB,aAAa,aAAa;AACvE,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM,WAAW,MAAM,WAAW,QAAQ;AAC1C,QAAM,SAAS,kBAAkB,UAAU;AAAA,IACzC,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,GAAG,kBAAkB,WAAW,QAAQ;AAAA,EAC1C,CAAC;AAED,QAAM,SAAS,MAAM,YAAY;AAAA,IAC/B;AAAA,IACA,UAAU;AAAA,IACV,SAAS,iBAAiB,KAAK;AAAA,IAC/B,cAAc;AAAA,IACd,cAAc,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAAA,IAC7C,eAAe,oBAAoB,WAAW;AAAA,EAChD,CAAC;AAED,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,kBAAkB,OAAO,KAAK,EAAE;AAC3C,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,kBAAkB,OAAO,MAAM;AAE9C,MAAI,OAAO,WAAW,QAAQ;AAE5B,QAAI;AACF,YAAM,OAAO,MAAM,aAAa,SAAS;AACzC,WAAK,SAAS,kBAAkB;AAChC,YAAM,aAAa,WAAW,IAAI;AAAA,IACpC,QAAQ;AAAA,IAER;AAEA,iBAAa,+DAA0D;AACvE,WAAO;AAAA,EACT;AAEA,aAAW,oCAA+B;AAC1C,MAAI,OAAO,UAAU;AACnB,YAAQ,IAAI,OAAO,QAAQ;AAAA,EAC7B;AACA,SAAO;AACT;","names":["findingsMatch"]}
|
package/dist/cli.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
setIssuesCliOverrides,
|
|
4
4
|
setWebCliOverrides
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-OVFYJLOH.js";
|
|
6
6
|
import {
|
|
7
7
|
printError,
|
|
8
8
|
setGlobalTimeout,
|
|
9
9
|
setVerbose
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-2Y3UO7H2.js";
|
|
11
11
|
|
|
12
12
|
// src/cli.ts
|
|
13
13
|
import { createRequire } from "module";
|
|
@@ -17,6 +17,22 @@ import { Command, InvalidArgumentError } from "commander";
|
|
|
17
17
|
function resolveNoBranch(options) {
|
|
18
18
|
return options.branch === false ? true : void 0;
|
|
19
19
|
}
|
|
20
|
+
var CliFlagError = class extends Error {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = "CliFlagError";
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
function resolveRunPhaseFlags(options) {
|
|
27
|
+
const noBranch = resolveNoBranch(options);
|
|
28
|
+
const prReview = options.prReview === true ? true : void 0;
|
|
29
|
+
if (prReview === true && noBranch === true) {
|
|
30
|
+
throw new CliFlagError(
|
|
31
|
+
"--pr-review cannot be combined with --no-branch: --no-branch skips the pr phase, so there is no Pull Request to review."
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return { noBranch, prReview };
|
|
35
|
+
}
|
|
20
36
|
|
|
21
37
|
// src/issues/cli-flags.ts
|
|
22
38
|
var IssueFlagError = class extends Error {
|
|
@@ -143,8 +159,8 @@ withIssueOptions(
|
|
|
143
159
|
program.command("init").description("Verify that all prerequisites (claude, gh, git) are met")
|
|
144
160
|
)
|
|
145
161
|
).action(async () => {
|
|
146
|
-
const { loadIssuesConfig } = await import("./config-
|
|
147
|
-
const { runInit } = await import("./init-
|
|
162
|
+
const { loadIssuesConfig } = await import("./config-UHQ6XXX2.js");
|
|
163
|
+
const { runInit } = await import("./init-W4HBLW7R.js");
|
|
148
164
|
const { preferredProvider } = await loadIssuesConfig();
|
|
149
165
|
const code = await runInit(preferredProvider);
|
|
150
166
|
process.exit(code);
|
|
@@ -162,30 +178,47 @@ withGlobalOptions(
|
|
|
162
178
|
}
|
|
163
179
|
throw error;
|
|
164
180
|
}
|
|
165
|
-
const { runGenerate } = await import("./generate-
|
|
181
|
+
const { runGenerate } = await import("./generate-DUKQCADD.js");
|
|
166
182
|
const code = await runGenerate(options.prompt, target);
|
|
167
183
|
process.exit(code);
|
|
168
184
|
});
|
|
169
185
|
withWebOptions(
|
|
170
186
|
withIssueOptions(
|
|
171
187
|
withGlobalOptions(
|
|
172
|
-
program.command("run").description(
|
|
173
|
-
"
|
|
174
|
-
|
|
175
|
-
)
|
|
188
|
+
program.command("run").description(
|
|
189
|
+
"Execute the full pipeline: prd \u2192 plan \u2192 execute \u2192 review \u2192 pr (\u2192 pr-review, optional)"
|
|
190
|
+
).argument("<issue>", "Issue number").option("--mode <mode>", "Execution mode: auto | manual", "auto").option("--from <phase>", "Resume from a specific phase").option("--no-branch", "Run pipeline on current branch without creating a new branch or PR").option("--pr-review", "Review the created Pull Request after the pr phase")
|
|
176
191
|
)
|
|
177
192
|
)
|
|
178
|
-
).action(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
193
|
+
).action(
|
|
194
|
+
async (issue, options) => {
|
|
195
|
+
let phases;
|
|
196
|
+
try {
|
|
197
|
+
phases = resolveRunPhaseFlags(options);
|
|
198
|
+
} catch (error) {
|
|
199
|
+
if (error instanceof CliFlagError) {
|
|
200
|
+
printError(error.message);
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
const { runPipeline } = await import("./run-VC647DQI.js");
|
|
206
|
+
const code = await runPipeline(
|
|
207
|
+
issue,
|
|
208
|
+
options.mode,
|
|
209
|
+
options.from,
|
|
210
|
+
phases.noBranch,
|
|
211
|
+
phases.prReview
|
|
212
|
+
);
|
|
213
|
+
process.exit(code);
|
|
214
|
+
}
|
|
215
|
+
);
|
|
183
216
|
withIssueOptions(
|
|
184
217
|
withGlobalOptions(
|
|
185
218
|
program.command("analyze").description("Analyze an issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
186
219
|
)
|
|
187
220
|
).action(async (issue) => {
|
|
188
|
-
const { runAnalyze } = await import("./analyze-
|
|
221
|
+
const { runAnalyze } = await import("./analyze-WRFFG2R5.js");
|
|
189
222
|
const code = await runAnalyze(issue);
|
|
190
223
|
process.exit(code);
|
|
191
224
|
});
|
|
@@ -194,7 +227,7 @@ withIssueOptions(
|
|
|
194
227
|
program.command("prd").description("Generate a PRD from an analyzed issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
195
228
|
)
|
|
196
229
|
).action(async (issue) => {
|
|
197
|
-
const { runPrd } = await import("./prd-
|
|
230
|
+
const { runPrd } = await import("./prd-FC2ZCEOX.js");
|
|
198
231
|
const code = await runPrd(issue);
|
|
199
232
|
process.exit(code);
|
|
200
233
|
});
|
|
@@ -203,7 +236,7 @@ withIssueOptions(
|
|
|
203
236
|
program.command("plan").description("Convert a PRD to a tasks.json task plan via Claude Code Headless").argument("<issue>", "Issue number")
|
|
204
237
|
)
|
|
205
238
|
).action(async (issue) => {
|
|
206
|
-
const { runPlan } = await import("./plan-
|
|
239
|
+
const { runPlan } = await import("./plan-NKPU45NP.js");
|
|
207
240
|
const code = await runPlan(issue);
|
|
208
241
|
process.exit(code);
|
|
209
242
|
});
|
|
@@ -222,7 +255,7 @@ withWebOptions(
|
|
|
222
255
|
).action(
|
|
223
256
|
async (positionalMaxIter, options) => {
|
|
224
257
|
try {
|
|
225
|
-
const { runExecute } = await import("./execute-
|
|
258
|
+
const { runExecute } = await import("./execute-K5B4UMUT.js");
|
|
226
259
|
const code = await runExecute(positionalMaxIter, options);
|
|
227
260
|
process.exit(code);
|
|
228
261
|
} catch (error) {
|
|
@@ -236,7 +269,7 @@ withIssueOptions(
|
|
|
236
269
|
program.command("review").description("Validate an issue resolution via Claude Code Headless").argument("<issue>", "Issue number")
|
|
237
270
|
)
|
|
238
271
|
).action(async (issue) => {
|
|
239
|
-
const { runReview } = await import("./review-
|
|
272
|
+
const { runReview } = await import("./review-X4NGDZZI.js");
|
|
240
273
|
const code = await runReview(issue);
|
|
241
274
|
process.exit(code);
|
|
242
275
|
});
|
|
@@ -245,9 +278,21 @@ withIssueOptions(
|
|
|
245
278
|
program.command("pr").description("Create a pull request via Claude Code Headless").argument("<issue>", "Issue number")
|
|
246
279
|
)
|
|
247
280
|
).action(async (issue) => {
|
|
248
|
-
const { runPr } = await import("./pr-
|
|
281
|
+
const { runPr } = await import("./pr-JYGLLIEF.js");
|
|
249
282
|
const code = await runPr(issue);
|
|
250
283
|
process.exit(code);
|
|
251
284
|
});
|
|
285
|
+
withGlobalOptions(
|
|
286
|
+
program.command("pr-review").description("Review a Pull Request as a whole via Claude Code Headless").argument("[pr]", "Pull Request number (discovered from the session when omitted)").option("--issue <n>", "Issue the Pull Request belongs to").option("--round <n>", "Rewrite a specific review round instead of appending a new one").option("--yes", "Skip the confirmation of the discovered Pull Request").option(
|
|
287
|
+
"--fail-on <level>",
|
|
288
|
+
"Verdict that fails the command: request-changes | suggestions | none"
|
|
289
|
+
)
|
|
290
|
+
).action(
|
|
291
|
+
async (pr, options) => {
|
|
292
|
+
const { runPrReview } = await import("./pr-review-6H6F4XUY.js");
|
|
293
|
+
const code = await runPrReview(pr, options);
|
|
294
|
+
process.exit(code);
|
|
295
|
+
}
|
|
296
|
+
);
|
|
252
297
|
program.parse();
|
|
253
298
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/cli-options.ts","../src/issues/cli-flags.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { Command, InvalidArgumentError } from 'commander';\nimport { resolveNoBranch } from './cli-options.js';\nimport { setIssuesCliOverrides, setWebCliOverrides } from './config.js';\nimport { setGlobalTimeout, setVerbose } from './core/verbose.js';\nimport {\n IssueFlagError,\n resolveGenerateTarget,\n resolveIssuesOverrides,\n} from './issues/cli-flags.js';\nimport type { IssueGenerateTarget } from './issues/types.js';\nimport type { WebConfig } from './schemas.js';\nimport { printError } from './ui/logger.js';\n\nconst require = createRequire(import.meta.url);\nconst { version } = require('../package.json') as { version: string };\n\n/**\n * Parse a numeric string, throwing InvalidArgumentError if not a valid number.\n */\nfunction parseInteger(value: string): number {\n const parsed = parseInt(value, 10);\n if (Number.isNaN(parsed) || parsed < 0) {\n throw new InvalidArgumentError('Must be a non-negative integer.');\n }\n return parsed;\n}\n\n/**\n * Add shared options (--verbose) to a subcommand.\n */\nfunction withGlobalOptions(cmd: Command): Command {\n return cmd\n .option('-v, --verbose', 'Show Claude progress output in real time')\n .option(\n '-t, --timeout <seconds>',\n 'Override headless timeout in seconds (0 = no limit)',\n parseInteger,\n );\n}\n\n/**\n * Add web monitoring options to a subcommand (run and execute only).\n * The values are resolved into CLI overrides by the preAction hook below;\n * loadWebConfig() applies the flag > env > file > defaults precedence.\n */\nfunction withWebOptions(cmd: Command): Command {\n return cmd\n .option('--web', 'Enable the web monitoring server')\n .option('--serve', 'Alias for --web')\n .option('--port <n>', 'Web server port (default: 3737)', parseInteger)\n .option('--host <h>', 'Web server host (default: 0.0.0.0)')\n .option('--refresh <s>', 'Suggested UI polling interval in seconds', parseInteger)\n .option('--web-log-limit <n>', 'Max log entries kept in the snapshot', parseInteger)\n .option('--web-no-logs', 'Exclude logs from the published snapshot');\n}\n\n/**\n * Add the Issue provider options to a subcommand.\n *\n * Declared once here (like withWebOptions) so no command repeats the flag\n * list; the preAction hook below turns them into config overrides, and\n * loadIssuesConfig() applies the flag > .issue-flow.json > defaults precedence.\n */\nfunction withIssueOptions(cmd: Command): Command {\n return cmd\n .option('--local', 'Prefer the local file Issue provider')\n .option('--github', 'Prefer the GitHub Issue provider')\n .option('--prefer-local', 'On divergence, use the local version without asking')\n .option('--prefer-github', 'On divergence, use the GitHub version without asking')\n .option('--ask', 'On divergence, ask which version to use (interactive only)');\n}\n\n/**\n * Extract the web-related CLI flags from a command's options, keeping only\n * the ones the user actually set.\n */\nfunction resolveWebOverrides(opts: Record<string, unknown>): Partial<WebConfig> {\n const overrides: Partial<WebConfig> = {};\n if (opts.web === true || opts.serve === true) {\n overrides.enabled = true;\n }\n if (opts.port !== undefined) {\n overrides.port = opts.port as number;\n }\n if (opts.host !== undefined) {\n overrides.host = opts.host as string;\n }\n if (opts.refresh !== undefined) {\n overrides.refreshSeconds = opts.refresh as number;\n }\n if (opts.webLogLimit !== undefined) {\n overrides.logLimit = opts.webLogLimit as number;\n }\n if (opts.webNoLogs === true) {\n overrides.includeLogs = false;\n }\n return overrides;\n}\n\nconst program = new Command();\n\nprogram\n .name('issue-flow')\n .description(\n 'Unified CLI for orchestrating the full issue-flow pipeline via Claude Code Headless.',\n )\n .version(version);\n\nprogram.hook('preAction', (_thisCommand, actionCommand) => {\n const opts = actionCommand.opts();\n if (opts.verbose) {\n setVerbose(true);\n }\n if (opts.timeout !== undefined) {\n setGlobalTimeout(opts.timeout * 1000);\n }\n setWebCliOverrides(resolveWebOverrides(opts));\n try {\n setIssuesCliOverrides(resolveIssuesOverrides(opts));\n } catch (error) {\n if (error instanceof IssueFlagError) {\n printError(error.message);\n process.exit(1);\n }\n throw error;\n }\n});\n\n// ── init ────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program.command('init').description('Verify that all prerequisites (claude, gh, git) are met'),\n ),\n).action(async () => {\n const { loadIssuesConfig } = await import('./config.js');\n const { runInit } = await import('./commands/init.js');\n const { preferredProvider } = await loadIssuesConfig();\n const code = await runInit(preferredProvider);\n process.exit(code);\n});\n\n// ── generate ────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('generate')\n .description('Draft an issue via Claude Code Headless and create it')\n .requiredOption('--prompt <text>', 'Issue description text')\n .option('--github', 'Create the issue on GitHub')\n .option('--local', 'Create the issue under issues/<n>/ only')\n .option('--both', 'Create the issue on GitHub and mirror it locally'),\n).action(async (options: { prompt: string; github?: boolean; local?: boolean; both?: boolean }) => {\n let target: IssueGenerateTarget | undefined;\n try {\n target = resolveGenerateTarget(options);\n } catch (error) {\n if (error instanceof IssueFlagError) {\n printError(error.message);\n process.exit(1);\n }\n throw error;\n }\n\n const { runGenerate } = await import('./commands/generate.js');\n const code = await runGenerate(options.prompt, target);\n process.exit(code);\n});\n\n// ── run ─────────────────────────────────────────────────────────────────────\nwithWebOptions(\n withIssueOptions(\n withGlobalOptions(\n program\n .command('run')\n .description('Execute the full pipeline: prd → plan → execute → review → pr')\n .argument('<issue>', 'Issue number')\n .option('--mode <mode>', 'Execution mode: auto | manual', 'auto')\n .option('--from <phase>', 'Resume from a specific phase')\n .option(\n '--no-branch',\n 'Run pipeline on current branch without creating a new branch or PR',\n ),\n ),\n ),\n).action(async (issue: string, options: { mode: string; from?: string; branch?: boolean }) => {\n const { runPipeline } = await import('./commands/run.js');\n const code = await runPipeline(issue, options.mode, options.from, resolveNoBranch(options));\n process.exit(code);\n});\n\n// ── analyze ─────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('analyze')\n .description('Analyze an issue via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runAnalyze } = await import('./commands/analyze.js');\n const code = await runAnalyze(issue);\n process.exit(code);\n});\n\n// ── prd ─────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('prd')\n .description('Generate a PRD from an analyzed issue via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runPrd } = await import('./commands/prd.js');\n const code = await runPrd(issue);\n process.exit(code);\n});\n\n// ── plan ────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('plan')\n .description('Convert a PRD to a tasks.json task plan via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runPlan } = await import('./commands/plan.js');\n const code = await runPlan(issue);\n process.exit(code);\n});\n\n// ── execute ─────────────────────────────────────────────────────────────────\nwithWebOptions(\n withGlobalOptions(\n program\n .command('execute')\n .description('Run the iterative story execution loop (issue-flow engine)')\n .option('--issue <number>', 'Issue number — reads artifacts from issues/N/')\n .option('--max-iterations <number>', 'Stop after N iterations', parseInteger)\n .option(\n '--retry-limit <number>',\n 'Retry transient Claude failures up to N consecutive times',\n parseInteger,\n )\n .option('--retry-forever', 'Retry transient Claude failures indefinitely')\n .argument(\n '[max-iterations]',\n 'Backward-compatible alias for --max-iterations N',\n parseInteger,\n ),\n ),\n).action(\n async (\n positionalMaxIter: number | undefined,\n options: {\n issue?: string;\n maxIterations?: number;\n retryLimit?: number;\n retryForever?: boolean;\n },\n ) => {\n try {\n const { runExecute } = await import('./commands/execute.js');\n const code = await runExecute(positionalMaxIter, options);\n process.exit(code);\n } catch (error) {\n printError(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n },\n);\n\n// ── review ──────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('review')\n .description('Validate an issue resolution via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runReview } = await import('./commands/review.js');\n const code = await runReview(issue);\n process.exit(code);\n});\n\n// ── pr ──────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('pr')\n .description('Create a pull request via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runPr } = await import('./commands/pr.js');\n const code = await runPr(issue);\n process.exit(code);\n});\n\nprogram.parse();\n","/**\n * Pure mappings from parsed CLI options to command arguments.\n *\n * They live outside cli.ts because that module runs `program.parse()` on\n * import, so anything defined there is untestable.\n */\n\n/** Shape commander produces for a negated boolean option (`--no-branch`). */\nexport interface BranchFlagOptions {\n branch?: boolean;\n}\n\n/**\n * Translate commander's `--no-branch` into the tri-state `runPipeline` expects.\n *\n * Commander stores a negated option under its positive name: `--no-branch`\n * yields `{ branch: false }` and never a `noBranch` key. Reading `noBranch`\n * silently dropped the flag, so the pipeline always created a branch and opened\n * a PR.\n *\n * `undefined` (flag absent) is preserved on purpose: `runPipeline` uses it to\n * tell \"the user said nothing, keep the mode persisted in tasks.json\" apart\n * from an explicit choice.\n */\nexport function resolveNoBranch(options: BranchFlagOptions): boolean | undefined {\n return options.branch === false ? true : undefined;\n}\n","import type { IssueGenerateTarget, IssuesConfig } from './types.js';\n\n/**\n * Mapping from the Issue provider CLI flags to configuration overrides.\n *\n * Kept out of cli.ts (which runs `program.parse()` on import) so the\n * precedence rules stay unit-testable. Only the keys the user actually passed\n * are returned: a key present with `undefined` would override .issue-flow.json\n * when the layers are merged.\n */\n\nexport interface IssueCliFlags {\n local?: boolean;\n github?: boolean;\n preferLocal?: boolean;\n preferGithub?: boolean;\n ask?: boolean;\n}\n\n/** Invalid flag combination, reported to the user as a CLI error. */\nexport class IssueFlagError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'IssueFlagError';\n }\n}\n\n/**\n * Translate the parsed options of a command into `IssuesConfig` overrides.\n *\n * @throws IssueFlagError when mutually exclusive flags are combined.\n */\nexport function resolveIssuesOverrides(opts: IssueCliFlags): Partial<IssuesConfig> {\n const overrides: Partial<IssuesConfig> = {};\n\n if (opts.local === true && opts.github === true) {\n throw new IssueFlagError('--local and --github are mutually exclusive; pass only one.');\n }\n if (opts.local === true) {\n overrides.preferredProvider = 'local';\n }\n if (opts.github === true) {\n overrides.preferredProvider = 'github';\n }\n\n const conflictFlags = [\n opts.preferLocal === true ? '--prefer-local' : null,\n opts.preferGithub === true ? '--prefer-github' : null,\n opts.ask === true ? '--ask' : null,\n ].filter((flag): flag is string => flag !== null);\n\n if (conflictFlags.length > 1) {\n throw new IssueFlagError(\n `${conflictFlags.join(', ')} are mutually exclusive; pass only one conflict policy.`,\n );\n }\n if (opts.preferLocal === true) {\n overrides.conflictPolicy = 'prefer-local';\n }\n if (opts.preferGithub === true) {\n overrides.conflictPolicy = 'prefer-github';\n }\n if (opts.ask === true) {\n overrides.conflictPolicy = 'ask';\n }\n\n return overrides;\n}\n\n/** Destination flags accepted by `generate`. */\nexport interface GenerateTargetFlags {\n github?: boolean;\n local?: boolean;\n both?: boolean;\n}\n\n/**\n * Destination the generated Issue is created in, or `undefined` when the user\n * passed no flag (the caller then falls back to `defaultGenerateTarget`).\n *\n * @throws IssueFlagError when more than one destination is requested.\n */\nexport function resolveGenerateTarget(opts: GenerateTargetFlags): IssueGenerateTarget | undefined {\n const selected: IssueGenerateTarget[] = [];\n if (opts.github === true) selected.push('github');\n if (opts.local === true) selected.push('local');\n if (opts.both === true) selected.push('both');\n\n if (selected.length > 1) {\n throw new IssueFlagError(\n `${selected.map((target) => `--${target}`).join(', ')} are mutually exclusive; ` +\n 'pass only one destination.',\n );\n }\n\n return selected[0];\n}\n"],"mappings":"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","names":["require"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/cli-options.ts","../src/issues/cli-flags.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { Command, InvalidArgumentError } from 'commander';\nimport { CliFlagError, resolveRunPhaseFlags } from './cli-options.js';\nimport { setIssuesCliOverrides, setWebCliOverrides } from './config.js';\nimport { setGlobalTimeout, setVerbose } from './core/verbose.js';\nimport {\n IssueFlagError,\n resolveGenerateTarget,\n resolveIssuesOverrides,\n} from './issues/cli-flags.js';\nimport type { IssueGenerateTarget } from './issues/types.js';\nimport type { WebConfig } from './schemas.js';\nimport { printError } from './ui/logger.js';\n\nconst require = createRequire(import.meta.url);\nconst { version } = require('../package.json') as { version: string };\n\n/**\n * Parse a numeric string, throwing InvalidArgumentError if not a valid number.\n */\nfunction parseInteger(value: string): number {\n const parsed = parseInt(value, 10);\n if (Number.isNaN(parsed) || parsed < 0) {\n throw new InvalidArgumentError('Must be a non-negative integer.');\n }\n return parsed;\n}\n\n/**\n * Add shared options (--verbose) to a subcommand.\n */\nfunction withGlobalOptions(cmd: Command): Command {\n return cmd\n .option('-v, --verbose', 'Show Claude progress output in real time')\n .option(\n '-t, --timeout <seconds>',\n 'Override headless timeout in seconds (0 = no limit)',\n parseInteger,\n );\n}\n\n/**\n * Add web monitoring options to a subcommand (run and execute only).\n * The values are resolved into CLI overrides by the preAction hook below;\n * loadWebConfig() applies the flag > env > file > defaults precedence.\n */\nfunction withWebOptions(cmd: Command): Command {\n return cmd\n .option('--web', 'Enable the web monitoring server')\n .option('--serve', 'Alias for --web')\n .option('--port <n>', 'Web server port (default: 3737)', parseInteger)\n .option('--host <h>', 'Web server host (default: 0.0.0.0)')\n .option('--refresh <s>', 'Suggested UI polling interval in seconds', parseInteger)\n .option('--web-log-limit <n>', 'Max log entries kept in the snapshot', parseInteger)\n .option('--web-no-logs', 'Exclude logs from the published snapshot');\n}\n\n/**\n * Add the Issue provider options to a subcommand.\n *\n * Declared once here (like withWebOptions) so no command repeats the flag\n * list; the preAction hook below turns them into config overrides, and\n * loadIssuesConfig() applies the flag > .issue-flow.json > defaults precedence.\n */\nfunction withIssueOptions(cmd: Command): Command {\n return cmd\n .option('--local', 'Prefer the local file Issue provider')\n .option('--github', 'Prefer the GitHub Issue provider')\n .option('--prefer-local', 'On divergence, use the local version without asking')\n .option('--prefer-github', 'On divergence, use the GitHub version without asking')\n .option('--ask', 'On divergence, ask which version to use (interactive only)');\n}\n\n/**\n * Extract the web-related CLI flags from a command's options, keeping only\n * the ones the user actually set.\n */\nfunction resolveWebOverrides(opts: Record<string, unknown>): Partial<WebConfig> {\n const overrides: Partial<WebConfig> = {};\n if (opts.web === true || opts.serve === true) {\n overrides.enabled = true;\n }\n if (opts.port !== undefined) {\n overrides.port = opts.port as number;\n }\n if (opts.host !== undefined) {\n overrides.host = opts.host as string;\n }\n if (opts.refresh !== undefined) {\n overrides.refreshSeconds = opts.refresh as number;\n }\n if (opts.webLogLimit !== undefined) {\n overrides.logLimit = opts.webLogLimit as number;\n }\n if (opts.webNoLogs === true) {\n overrides.includeLogs = false;\n }\n return overrides;\n}\n\nconst program = new Command();\n\nprogram\n .name('issue-flow')\n .description(\n 'Unified CLI for orchestrating the full issue-flow pipeline via Claude Code Headless.',\n )\n .version(version);\n\nprogram.hook('preAction', (_thisCommand, actionCommand) => {\n const opts = actionCommand.opts();\n if (opts.verbose) {\n setVerbose(true);\n }\n if (opts.timeout !== undefined) {\n setGlobalTimeout(opts.timeout * 1000);\n }\n setWebCliOverrides(resolveWebOverrides(opts));\n try {\n setIssuesCliOverrides(resolveIssuesOverrides(opts));\n } catch (error) {\n if (error instanceof IssueFlagError) {\n printError(error.message);\n process.exit(1);\n }\n throw error;\n }\n});\n\n// ── init ────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program.command('init').description('Verify that all prerequisites (claude, gh, git) are met'),\n ),\n).action(async () => {\n const { loadIssuesConfig } = await import('./config.js');\n const { runInit } = await import('./commands/init.js');\n const { preferredProvider } = await loadIssuesConfig();\n const code = await runInit(preferredProvider);\n process.exit(code);\n});\n\n// ── generate ────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('generate')\n .description('Draft an issue via Claude Code Headless and create it')\n .requiredOption('--prompt <text>', 'Issue description text')\n .option('--github', 'Create the issue on GitHub')\n .option('--local', 'Create the issue under issues/<n>/ only')\n .option('--both', 'Create the issue on GitHub and mirror it locally'),\n).action(async (options: { prompt: string; github?: boolean; local?: boolean; both?: boolean }) => {\n let target: IssueGenerateTarget | undefined;\n try {\n target = resolveGenerateTarget(options);\n } catch (error) {\n if (error instanceof IssueFlagError) {\n printError(error.message);\n process.exit(1);\n }\n throw error;\n }\n\n const { runGenerate } = await import('./commands/generate.js');\n const code = await runGenerate(options.prompt, target);\n process.exit(code);\n});\n\n// ── run ─────────────────────────────────────────────────────────────────────\nwithWebOptions(\n withIssueOptions(\n withGlobalOptions(\n program\n .command('run')\n .description(\n 'Execute the full pipeline: prd → plan → execute → review → pr (→ pr-review, optional)',\n )\n .argument('<issue>', 'Issue number')\n .option('--mode <mode>', 'Execution mode: auto | manual', 'auto')\n .option('--from <phase>', 'Resume from a specific phase')\n .option('--no-branch', 'Run pipeline on current branch without creating a new branch or PR')\n .option('--pr-review', 'Review the created Pull Request after the pr phase'),\n ),\n ),\n).action(\n async (\n issue: string,\n options: { mode: string; from?: string; branch?: boolean; prReview?: boolean },\n ) => {\n let phases: ReturnType<typeof resolveRunPhaseFlags>;\n try {\n phases = resolveRunPhaseFlags(options);\n } catch (error) {\n if (error instanceof CliFlagError) {\n printError(error.message);\n process.exit(1);\n }\n throw error;\n }\n\n const { runPipeline } = await import('./commands/run.js');\n const code = await runPipeline(\n issue,\n options.mode,\n options.from,\n phases.noBranch,\n phases.prReview,\n );\n process.exit(code);\n },\n);\n\n// ── analyze ─────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('analyze')\n .description('Analyze an issue via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runAnalyze } = await import('./commands/analyze.js');\n const code = await runAnalyze(issue);\n process.exit(code);\n});\n\n// ── prd ─────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('prd')\n .description('Generate a PRD from an analyzed issue via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runPrd } = await import('./commands/prd.js');\n const code = await runPrd(issue);\n process.exit(code);\n});\n\n// ── plan ────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('plan')\n .description('Convert a PRD to a tasks.json task plan via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runPlan } = await import('./commands/plan.js');\n const code = await runPlan(issue);\n process.exit(code);\n});\n\n// ── execute ─────────────────────────────────────────────────────────────────\nwithWebOptions(\n withGlobalOptions(\n program\n .command('execute')\n .description('Run the iterative story execution loop (issue-flow engine)')\n .option('--issue <number>', 'Issue number — reads artifacts from issues/N/')\n .option('--max-iterations <number>', 'Stop after N iterations', parseInteger)\n .option(\n '--retry-limit <number>',\n 'Retry transient Claude failures up to N consecutive times',\n parseInteger,\n )\n .option('--retry-forever', 'Retry transient Claude failures indefinitely')\n .argument(\n '[max-iterations]',\n 'Backward-compatible alias for --max-iterations N',\n parseInteger,\n ),\n ),\n).action(\n async (\n positionalMaxIter: number | undefined,\n options: {\n issue?: string;\n maxIterations?: number;\n retryLimit?: number;\n retryForever?: boolean;\n },\n ) => {\n try {\n const { runExecute } = await import('./commands/execute.js');\n const code = await runExecute(positionalMaxIter, options);\n process.exit(code);\n } catch (error) {\n printError(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n },\n);\n\n// ── review ──────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('review')\n .description('Validate an issue resolution via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runReview } = await import('./commands/review.js');\n const code = await runReview(issue);\n process.exit(code);\n});\n\n// ── pr ──────────────────────────────────────────────────────────────────────\nwithIssueOptions(\n withGlobalOptions(\n program\n .command('pr')\n .description('Create a pull request via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\n ),\n).action(async (issue: string) => {\n const { runPr } = await import('./commands/pr.js');\n const code = await runPr(issue);\n process.exit(code);\n});\n\n// ── pr-review ───────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('pr-review')\n .description('Review a Pull Request as a whole via Claude Code Headless')\n .argument('[pr]', 'Pull Request number (discovered from the session when omitted)')\n .option('--issue <n>', 'Issue the Pull Request belongs to')\n .option('--round <n>', 'Rewrite a specific review round instead of appending a new one')\n .option('--yes', 'Skip the confirmation of the discovered Pull Request')\n .option(\n '--fail-on <level>',\n 'Verdict that fails the command: request-changes | suggestions | none',\n ),\n).action(\n async (\n pr: string | undefined,\n options: { issue?: string; round?: string; yes?: boolean; failOn?: string },\n ) => {\n const { runPrReview } = await import('./commands/pr-review.js');\n const code = await runPrReview(pr, options);\n process.exit(code);\n },\n);\n\nprogram.parse();\n","/**\n * Pure mappings from parsed CLI options to command arguments.\n *\n * They live outside cli.ts because that module runs `program.parse()` on\n * import, so anything defined there is untestable.\n */\n\n/** Shape commander produces for a negated boolean option (`--no-branch`). */\nexport interface BranchFlagOptions {\n branch?: boolean;\n}\n\n/**\n * Translate commander's `--no-branch` into the tri-state `runPipeline` expects.\n *\n * Commander stores a negated option under its positive name: `--no-branch`\n * yields `{ branch: false }` and never a `noBranch` key. Reading `noBranch`\n * silently dropped the flag, so the pipeline always created a branch and opened\n * a PR.\n *\n * `undefined` (flag absent) is preserved on purpose: `runPipeline` uses it to\n * tell \"the user said nothing, keep the mode persisted in tasks.json\" apart\n * from an explicit choice.\n */\nexport function resolveNoBranch(options: BranchFlagOptions): boolean | undefined {\n return options.branch === false ? true : undefined;\n}\n\n/** Invalid flag combination on a command, reported as a CLI error. */\nexport class CliFlagError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CliFlagError';\n }\n}\n\n/** Options `run` accepts that select which phases the pipeline executes. */\nexport interface RunPhaseFlagOptions extends BranchFlagOptions {\n prReview?: boolean;\n}\n\n/** Phase selection `runPipeline` expects, both entries tri-state. */\nexport interface RunPhaseFlags {\n noBranch: boolean | undefined;\n prReview: boolean | undefined;\n}\n\n/**\n * Resolve the phase-selection flags of `run`, rejecting the one combination\n * that cannot work.\n *\n * `--no-branch` skips the `pr` phase, so there is no Pull Request for\n * `--pr-review` to review. Failing here — before any phase runs — beats\n * discovering it at the end of a full pipeline.\n *\n * Both values stay `undefined` when the user passed nothing: `runPipeline`\n * uses that to tell \"no opinion, keep what tasks.json persisted\" apart from an\n * explicit choice.\n *\n * @throws CliFlagError when `--pr-review` is combined with `--no-branch`.\n */\nexport function resolveRunPhaseFlags(options: RunPhaseFlagOptions): RunPhaseFlags {\n const noBranch = resolveNoBranch(options);\n const prReview = options.prReview === true ? true : undefined;\n\n if (prReview === true && noBranch === true) {\n throw new CliFlagError(\n '--pr-review cannot be combined with --no-branch: --no-branch skips the pr phase, ' +\n 'so there is no Pull Request to review.',\n );\n }\n\n return { noBranch, prReview };\n}\n","import type { IssueGenerateTarget, IssuesConfig } from './types.js';\n\n/**\n * Mapping from the Issue provider CLI flags to configuration overrides.\n *\n * Kept out of cli.ts (which runs `program.parse()` on import) so the\n * precedence rules stay unit-testable. Only the keys the user actually passed\n * are returned: a key present with `undefined` would override .issue-flow.json\n * when the layers are merged.\n */\n\nexport interface IssueCliFlags {\n local?: boolean;\n github?: boolean;\n preferLocal?: boolean;\n preferGithub?: boolean;\n ask?: boolean;\n}\n\n/** Invalid flag combination, reported to the user as a CLI error. */\nexport class IssueFlagError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'IssueFlagError';\n }\n}\n\n/**\n * Translate the parsed options of a command into `IssuesConfig` overrides.\n *\n * @throws IssueFlagError when mutually exclusive flags are combined.\n */\nexport function resolveIssuesOverrides(opts: IssueCliFlags): Partial<IssuesConfig> {\n const overrides: Partial<IssuesConfig> = {};\n\n if (opts.local === true && opts.github === true) {\n throw new IssueFlagError('--local and --github are mutually exclusive; pass only one.');\n }\n if (opts.local === true) {\n overrides.preferredProvider = 'local';\n }\n if (opts.github === true) {\n overrides.preferredProvider = 'github';\n }\n\n const conflictFlags = [\n opts.preferLocal === true ? '--prefer-local' : null,\n opts.preferGithub === true ? '--prefer-github' : null,\n opts.ask === true ? '--ask' : null,\n ].filter((flag): flag is string => flag !== null);\n\n if (conflictFlags.length > 1) {\n throw new IssueFlagError(\n `${conflictFlags.join(', ')} are mutually exclusive; pass only one conflict policy.`,\n );\n }\n if (opts.preferLocal === true) {\n overrides.conflictPolicy = 'prefer-local';\n }\n if (opts.preferGithub === true) {\n overrides.conflictPolicy = 'prefer-github';\n }\n if (opts.ask === true) {\n overrides.conflictPolicy = 'ask';\n }\n\n return overrides;\n}\n\n/** Destination flags accepted by `generate`. */\nexport interface GenerateTargetFlags {\n github?: boolean;\n local?: boolean;\n both?: boolean;\n}\n\n/**\n * Destination the generated Issue is created in, or `undefined` when the user\n * passed no flag (the caller then falls back to `defaultGenerateTarget`).\n *\n * @throws IssueFlagError when more than one destination is requested.\n */\nexport function resolveGenerateTarget(opts: GenerateTargetFlags): IssueGenerateTarget | undefined {\n const selected: IssueGenerateTarget[] = [];\n if (opts.github === true) selected.push('github');\n if (opts.local === true) selected.push('local');\n if (opts.both === true) selected.push('both');\n\n if (selected.length > 1) {\n throw new IssueFlagError(\n `${selected.map((target) => `--${target}`).join(', ')} are mutually exclusive; ` +\n 'pass only one destination.',\n );\n }\n\n return selected[0];\n}\n"],"mappings":"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","names":["require"]}
|
|
@@ -6,13 +6,14 @@ import {
|
|
|
6
6
|
createConfig,
|
|
7
7
|
getInstallHint,
|
|
8
8
|
loadIssuesConfig,
|
|
9
|
+
loadPrReviewConfig,
|
|
9
10
|
loadWebConfig,
|
|
10
11
|
resolvePaths,
|
|
11
12
|
setIssuesCliOverrides,
|
|
12
13
|
setWebCliOverrides,
|
|
13
14
|
validateDependencies
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-OVFYJLOH.js";
|
|
16
|
+
import "./chunk-2Y3UO7H2.js";
|
|
16
17
|
export {
|
|
17
18
|
DEFAULTS,
|
|
18
19
|
PROJECT_CONFIG_FILENAME,
|
|
@@ -20,10 +21,11 @@ export {
|
|
|
20
21
|
createConfig,
|
|
21
22
|
getInstallHint,
|
|
22
23
|
loadIssuesConfig,
|
|
24
|
+
loadPrReviewConfig,
|
|
23
25
|
loadWebConfig,
|
|
24
26
|
resolvePaths,
|
|
25
27
|
setIssuesCliOverrides,
|
|
26
28
|
setWebCliOverrides,
|
|
27
29
|
validateDependencies
|
|
28
30
|
};
|
|
29
|
-
//# sourceMappingURL=config-
|
|
31
|
+
//# sourceMappingURL=config-UHQ6XXX2.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runExecute
|
|
4
|
+
} from "./chunk-YXJPKBPV.js";
|
|
5
|
+
import "./chunk-HDV3YDTG.js";
|
|
6
|
+
import "./chunk-CW6UE3NW.js";
|
|
7
|
+
import "./chunk-SLHZPB3C.js";
|
|
8
|
+
import "./chunk-OVFYJLOH.js";
|
|
9
|
+
import "./chunk-2Y3UO7H2.js";
|
|
10
|
+
export {
|
|
11
|
+
runExecute
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=execute-K5B4UMUT.js.map
|
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
import {
|
|
3
3
|
ensureProvidersRegistered,
|
|
4
4
|
getProvider,
|
|
5
|
-
localIssueRef
|
|
5
|
+
localIssueRef
|
|
6
|
+
} from "./chunk-HS4QWZAO.js";
|
|
7
|
+
import {
|
|
6
8
|
runHeadless
|
|
7
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KUDAY57D.js";
|
|
8
10
|
import {
|
|
9
11
|
applyPlaceholders,
|
|
10
12
|
loadPrompt
|
|
11
13
|
} from "./chunk-SLHZPB3C.js";
|
|
12
14
|
import {
|
|
13
15
|
loadIssuesConfig
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-OVFYJLOH.js";
|
|
15
17
|
import {
|
|
16
18
|
getGlobalTimeout,
|
|
17
19
|
isoNow,
|
|
18
20
|
printError,
|
|
19
21
|
printSuccess
|
|
20
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2Y3UO7H2.js";
|
|
21
23
|
|
|
22
24
|
// src/issues/draft.ts
|
|
23
25
|
var DRAFT_TAG = "issue-draft";
|
|
@@ -140,4 +142,4 @@ async function runGenerate(promptText, target) {
|
|
|
140
142
|
export {
|
|
141
143
|
runGenerate
|
|
142
144
|
};
|
|
143
|
-
//# sourceMappingURL=generate-
|
|
145
|
+
//# sourceMappingURL=generate-DUKQCADD.js.map
|