issue-flow 0.3.1 → 0.4.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-3SN7ZAZU.js +12 -0
- package/dist/{chunk-FPX32B2W.js → chunk-2JZCWJEQ.js} +4 -6
- package/dist/{chunk-FPX32B2W.js.map → chunk-2JZCWJEQ.js.map} +1 -1
- package/dist/{chunk-3M7FPMO7.js → chunk-4OQ2ARLP.js} +28 -22
- package/dist/chunk-4OQ2ARLP.js.map +1 -0
- package/dist/{chunk-K22WFAWY.js → chunk-4PZXIOXD.js} +4 -6
- package/dist/{chunk-K22WFAWY.js.map → chunk-4PZXIOXD.js.map} +1 -1
- package/dist/{chunk-7A6NLYQE.js → chunk-CSSXTPWE.js} +2 -2
- package/dist/{chunk-ZR5KSQWZ.js → chunk-CYWHYPTU.js} +4 -6
- package/dist/{chunk-ZR5KSQWZ.js.map → chunk-CYWHYPTU.js.map} +1 -1
- package/dist/{chunk-R7HJYTQU.js → chunk-MEB3B2FI.js} +4 -6
- package/dist/{chunk-R7HJYTQU.js.map → chunk-MEB3B2FI.js.map} +1 -1
- package/dist/{chunk-2DR5PWPR.js → chunk-MWUIIUAS.js} +4 -6
- package/dist/{chunk-2DR5PWPR.js.map → chunk-MWUIIUAS.js.map} +1 -1
- package/dist/{chunk-KTJI7WMC.js → chunk-WM6AYRHQ.js} +42 -173
- package/dist/chunk-WM6AYRHQ.js.map +1 -0
- package/dist/{chunk-SB52G2M2.js → chunk-YAFHVFV5.js} +58 -11
- package/dist/chunk-YAFHVFV5.js.map +1 -0
- package/dist/cli.js +12 -14
- package/dist/cli.js.map +1 -1
- package/dist/{execute-H3COM62D.js → execute-6AAKNSLM.js} +3 -3
- package/dist/{generate-KRVWNLQU.js → generate-HP4CPMJG.js} +4 -6
- package/dist/{generate-KRVWNLQU.js.map → generate-HP4CPMJG.js.map} +1 -1
- package/dist/init-SXFGOCML.js +9 -0
- package/dist/plan-HWZRG5GP.js +12 -0
- package/dist/pr-TTOFYUCV.js +12 -0
- package/dist/prd-ET2QN7GB.js +12 -0
- package/dist/review-3QDZCOMT.js +12 -0
- package/dist/run-6CR5FDYH.js +451 -0
- package/dist/run-6CR5FDYH.js.map +1 -0
- package/package.json +2 -1
- package/dist/analyze-YSKLI2YL.js +0 -13
- package/dist/chunk-3M7FPMO7.js.map +0 -1
- package/dist/chunk-KMZHFUOY.js +0 -25
- package/dist/chunk-KMZHFUOY.js.map +0 -1
- package/dist/chunk-KTJI7WMC.js.map +0 -1
- package/dist/chunk-SB52G2M2.js.map +0 -1
- package/dist/init-AA453TQF.js +0 -9
- package/dist/plan-GGF7FMOV.js +0 -13
- package/dist/pr-OF25YHPZ.js +0 -13
- package/dist/prd-MEYPY6XI.js +0 -13
- package/dist/review-7DQIPFTD.js +0 -13
- package/dist/run-JZAL7XB2.js +0 -302
- package/dist/run-JZAL7XB2.js.map +0 -1
- /package/dist/{analyze-YSKLI2YL.js.map → analyze-3SN7ZAZU.js.map} +0 -0
- /package/dist/{chunk-7A6NLYQE.js.map → chunk-CSSXTPWE.js.map} +0 -0
- /package/dist/{execute-H3COM62D.js.map → execute-6AAKNSLM.js.map} +0 -0
- /package/dist/{init-AA453TQF.js.map → init-SXFGOCML.js.map} +0 -0
- /package/dist/{plan-GGF7FMOV.js.map → plan-HWZRG5GP.js.map} +0 -0
- /package/dist/{pr-OF25YHPZ.js.map → pr-TTOFYUCV.js.map} +0 -0
- /package/dist/{prd-MEYPY6XI.js.map → prd-ET2QN7GB.js.map} +0 -0
- /package/dist/{review-7DQIPFTD.js.map → review-3QDZCOMT.js.map} +0 -0
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from 'commander';\nimport { setGlobalTimeout, setVerbose } from './core/verbose.js';\nimport { printError } from './ui/logger.js';\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\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('0.3.
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from 'commander';\nimport { setGlobalTimeout, setVerbose } from './core/verbose.js';\nimport { printError } from './ui/logger.js';\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\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('0.3.0');\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});\n\n// ── init ────────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program.command('init').description('Verify that all prerequisites (claude, gh, git) are met'),\n).action(async () => {\n const { runInit } = await import('./commands/init.js');\n const code = await runInit();\n process.exit(code);\n});\n\n// ── generate ────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('generate')\n .description('Create a GitHub issue via Claude Code Headless')\n .requiredOption('--prompt <text>', 'Issue description text'),\n).action(async (options: { prompt: string }) => {\n const { runGenerate } = await import('./commands/generate.js');\n const code = await runGenerate(options.prompt);\n process.exit(code);\n});\n\n// ── run ─────────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('run')\n .description('Execute the full pipeline: analyze → 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).action(async (issue: string, options: { mode: string; from?: string }) => {\n const { runPipeline } = await import('./commands/run.js');\n const code = await runPipeline(issue, options.mode, options.from);\n process.exit(code);\n});\n\n// ── analyze ─────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('analyze')\n .description('Analyze a GitHub issue via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\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 ─────────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('prd')\n .description('Generate a PRD from an analyzed issue via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\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 ────────────────────────────────────────────────────────────────────\nwithGlobalOptions(\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).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 ─────────────────────────────────────────────────────────────────\nwithGlobalOptions(\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('[max-iterations]', 'Backward-compatible alias for --max-iterations N', parseInteger),\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 ──────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('review')\n .description('Validate an issue resolution via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\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 ──────────────────────────────────────────────────────────────────────\nwithGlobalOptions(\n program\n .command('pr')\n .description('Create a pull request via Claude Code Headless')\n .argument('<issue>', 'Issue number'),\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"],"mappings":"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","names":[]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runExecute
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WM6AYRHQ.js";
|
|
5
5
|
import "./chunk-64FU2L2T.js";
|
|
6
6
|
import "./chunk-OZVHOVDT.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-YAFHVFV5.js";
|
|
8
8
|
export {
|
|
9
9
|
runExecute
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=execute-
|
|
11
|
+
//# sourceMappingURL=execute-6AAKNSLM.js.map
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runHeadless
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import {
|
|
6
|
-
getGlobalTimeout
|
|
7
|
-
} from "./chunk-KMZHFUOY.js";
|
|
4
|
+
} from "./chunk-4OQ2ARLP.js";
|
|
8
5
|
import {
|
|
9
6
|
applyPlaceholders,
|
|
10
7
|
loadPrompt
|
|
11
8
|
} from "./chunk-OZVHOVDT.js";
|
|
12
9
|
import {
|
|
10
|
+
getGlobalTimeout,
|
|
13
11
|
printError,
|
|
14
12
|
printSuccess
|
|
15
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-YAFHVFV5.js";
|
|
16
14
|
|
|
17
15
|
// src/commands/generate.ts
|
|
18
16
|
function parseIssueUrl(output) {
|
|
@@ -47,4 +45,4 @@ async function runGenerate(promptText) {
|
|
|
47
45
|
export {
|
|
48
46
|
runGenerate
|
|
49
47
|
};
|
|
50
|
-
//# sourceMappingURL=generate-
|
|
48
|
+
//# sourceMappingURL=generate-HP4CPMJG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/generate.ts"],"sourcesContent":["import { runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { printError, printSuccess } from '../ui/logger.js';\n\n/**\n * Extract an issue URL from headless output.\n */\nfunction parseIssueUrl(output: string): string | null {\n const match = output.match(/(https:\\/\\/github\\.com\\/[^\\s]+\\/issues\\/\\d+)/);\n return match?.[1] ?? null;\n}\n\nexport async function runGenerate(promptText: string): Promise<number> {\n const template = await loadPrompt('generate');\n const prompt = applyPlaceholders(template, {\n __USER_PROMPT__: promptText,\n });\n\n const result = await runHeadless({\n prompt,\n maxTurns: 15,\n timeout: getGlobalTimeout() ?? 300_000,\n outputFormat: 'text',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n statusMessage: 'Creating GitHub issue...',\n });\n\n if (!result.success) {\n printError(`Issue creation failed: ${result.error}`);\n return 1;\n }\n\n const issueUrl = parseIssueUrl(result.result);\n\n if (issueUrl) {\n printSuccess(`Issue created: ${issueUrl}`);\n } else {\n printSuccess('Issue creation completed');\n }\n return 0;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/commands/generate.ts"],"sourcesContent":["import { runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { printError, printSuccess } from '../ui/logger.js';\n\n/**\n * Extract an issue URL from headless output.\n */\nfunction parseIssueUrl(output: string): string | null {\n const match = output.match(/(https:\\/\\/github\\.com\\/[^\\s]+\\/issues\\/\\d+)/);\n return match?.[1] ?? null;\n}\n\nexport async function runGenerate(promptText: string): Promise<number> {\n const template = await loadPrompt('generate');\n const prompt = applyPlaceholders(template, {\n __USER_PROMPT__: promptText,\n });\n\n const result = await runHeadless({\n prompt,\n maxTurns: 15,\n timeout: getGlobalTimeout() ?? 300_000,\n outputFormat: 'text',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n statusMessage: 'Creating GitHub issue...',\n });\n\n if (!result.success) {\n printError(`Issue creation failed: ${result.error}`);\n return 1;\n }\n\n const issueUrl = parseIssueUrl(result.result);\n\n if (issueUrl) {\n printSuccess(`Issue created: ${issueUrl}`);\n } else {\n printSuccess('Issue creation completed');\n }\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAQA,SAAS,cAAc,QAA+B;AACpD,QAAM,QAAQ,OAAO,MAAM,8CAA8C;AACzE,SAAO,QAAQ,CAAC,KAAK;AACvB;AAEA,eAAsB,YAAY,YAAqC;AACrE,QAAM,WAAW,MAAM,WAAW,UAAU;AAC5C,QAAM,SAAS,kBAAkB,UAAU;AAAA,IACzC,iBAAiB;AAAA,EACnB,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;AAAA,EACjB,CAAC;AAED,MAAI,CAAC,OAAO,SAAS;AACnB,eAAW,0BAA0B,OAAO,KAAK,EAAE;AACnD,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,cAAc,OAAO,MAAM;AAE5C,MAAI,UAAU;AACZ,iBAAa,kBAAkB,QAAQ,EAAE;AAAA,EAC3C,OAAO;AACL,iBAAa,0BAA0B;AAAA,EACzC;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runPlan
|
|
4
|
+
} from "./chunk-MWUIIUAS.js";
|
|
5
|
+
import "./chunk-4OQ2ARLP.js";
|
|
6
|
+
import "./chunk-64FU2L2T.js";
|
|
7
|
+
import "./chunk-OZVHOVDT.js";
|
|
8
|
+
import "./chunk-YAFHVFV5.js";
|
|
9
|
+
export {
|
|
10
|
+
runPlan
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=plan-HWZRG5GP.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runPr
|
|
4
|
+
} from "./chunk-CYWHYPTU.js";
|
|
5
|
+
import "./chunk-4OQ2ARLP.js";
|
|
6
|
+
import "./chunk-64FU2L2T.js";
|
|
7
|
+
import "./chunk-OZVHOVDT.js";
|
|
8
|
+
import "./chunk-YAFHVFV5.js";
|
|
9
|
+
export {
|
|
10
|
+
runPr
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=pr-TTOFYUCV.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runPrd
|
|
4
|
+
} from "./chunk-2JZCWJEQ.js";
|
|
5
|
+
import "./chunk-4OQ2ARLP.js";
|
|
6
|
+
import "./chunk-64FU2L2T.js";
|
|
7
|
+
import "./chunk-OZVHOVDT.js";
|
|
8
|
+
import "./chunk-YAFHVFV5.js";
|
|
9
|
+
export {
|
|
10
|
+
runPrd
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=prd-ET2QN7GB.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runReview
|
|
4
|
+
} from "./chunk-4PZXIOXD.js";
|
|
5
|
+
import "./chunk-4OQ2ARLP.js";
|
|
6
|
+
import "./chunk-64FU2L2T.js";
|
|
7
|
+
import "./chunk-OZVHOVDT.js";
|
|
8
|
+
import "./chunk-YAFHVFV5.js";
|
|
9
|
+
export {
|
|
10
|
+
runReview
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=review-3QDZCOMT.js.map
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runReview
|
|
4
|
+
} from "./chunk-4PZXIOXD.js";
|
|
5
|
+
import {
|
|
6
|
+
runInit
|
|
7
|
+
} from "./chunk-CSSXTPWE.js";
|
|
8
|
+
import {
|
|
9
|
+
runAnalyze
|
|
10
|
+
} from "./chunk-MEB3B2FI.js";
|
|
11
|
+
import {
|
|
12
|
+
runExecute
|
|
13
|
+
} from "./chunk-WM6AYRHQ.js";
|
|
14
|
+
import {
|
|
15
|
+
runPlan
|
|
16
|
+
} from "./chunk-MWUIIUAS.js";
|
|
17
|
+
import {
|
|
18
|
+
runPr
|
|
19
|
+
} from "./chunk-CYWHYPTU.js";
|
|
20
|
+
import {
|
|
21
|
+
runPrd
|
|
22
|
+
} from "./chunk-2JZCWJEQ.js";
|
|
23
|
+
import "./chunk-4OQ2ARLP.js";
|
|
24
|
+
import {
|
|
25
|
+
isoNow,
|
|
26
|
+
loadTaskPlan,
|
|
27
|
+
saveTaskPlan
|
|
28
|
+
} from "./chunk-64FU2L2T.js";
|
|
29
|
+
import "./chunk-OZVHOVDT.js";
|
|
30
|
+
import {
|
|
31
|
+
formatDuration,
|
|
32
|
+
isVerbose,
|
|
33
|
+
printError,
|
|
34
|
+
printInfo,
|
|
35
|
+
printSuccess,
|
|
36
|
+
printWarning,
|
|
37
|
+
setOutputCallback,
|
|
38
|
+
setStoryUpdateCallback
|
|
39
|
+
} from "./chunk-YAFHVFV5.js";
|
|
40
|
+
|
|
41
|
+
// src/commands/run.ts
|
|
42
|
+
import { join } from "path";
|
|
43
|
+
import { execa } from "execa";
|
|
44
|
+
|
|
45
|
+
// src/core/pipeline.ts
|
|
46
|
+
var PIPELINE_PHASES = [
|
|
47
|
+
"init",
|
|
48
|
+
"analyze",
|
|
49
|
+
"prd",
|
|
50
|
+
"plan",
|
|
51
|
+
"execute",
|
|
52
|
+
"review",
|
|
53
|
+
"pr"
|
|
54
|
+
];
|
|
55
|
+
var PHASE_TO_FIELD = {
|
|
56
|
+
init: null,
|
|
57
|
+
analyze: "analyzeCompleted",
|
|
58
|
+
prd: "prdCompleted",
|
|
59
|
+
plan: "jsonCompleted",
|
|
60
|
+
execute: "executionCompleted",
|
|
61
|
+
review: "reviewCompleted",
|
|
62
|
+
pr: "prCreated"
|
|
63
|
+
};
|
|
64
|
+
var PipelineManager = class {
|
|
65
|
+
tasksJsonPath;
|
|
66
|
+
plan;
|
|
67
|
+
constructor(plan, tasksJsonPath) {
|
|
68
|
+
this.plan = plan;
|
|
69
|
+
this.tasksJsonPath = tasksJsonPath;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Reload state from disk.
|
|
73
|
+
*/
|
|
74
|
+
async reload() {
|
|
75
|
+
this.plan = await loadTaskPlan(this.tasksJsonPath);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check if a phase is complete.
|
|
79
|
+
*/
|
|
80
|
+
isPhaseComplete(phase) {
|
|
81
|
+
const field = PHASE_TO_FIELD[phase];
|
|
82
|
+
if (field === null) return true;
|
|
83
|
+
return this.plan.pipeline?.[field] ?? false;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get the first incomplete phase in the pipeline.
|
|
87
|
+
* Returns null if all phases are complete.
|
|
88
|
+
*/
|
|
89
|
+
getNextPhase() {
|
|
90
|
+
for (const phase of PIPELINE_PHASES) {
|
|
91
|
+
if (!this.isPhaseComplete(phase)) {
|
|
92
|
+
return phase;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the current phase (alias for getNextPhase).
|
|
99
|
+
*/
|
|
100
|
+
getCurrentPhase() {
|
|
101
|
+
return this.getNextPhase();
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check whether we can resume from a specific phase.
|
|
105
|
+
* All prerequisite phases must be complete.
|
|
106
|
+
*/
|
|
107
|
+
canResume(fromPhase) {
|
|
108
|
+
const idx = PIPELINE_PHASES.indexOf(fromPhase);
|
|
109
|
+
if (idx < 0) return false;
|
|
110
|
+
for (let i = 0; i < idx; i++) {
|
|
111
|
+
if (!this.isPhaseComplete(PIPELINE_PHASES[i])) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Mark a phase as complete and persist to disk.
|
|
119
|
+
*/
|
|
120
|
+
async markPhaseComplete(phase) {
|
|
121
|
+
const field = PHASE_TO_FIELD[phase];
|
|
122
|
+
if (field === null) return;
|
|
123
|
+
this.plan = {
|
|
124
|
+
...this.plan,
|
|
125
|
+
pipeline: {
|
|
126
|
+
...this.plan.pipeline ?? {
|
|
127
|
+
analyzeCompleted: false,
|
|
128
|
+
prdCompleted: false,
|
|
129
|
+
jsonCompleted: false,
|
|
130
|
+
executionCompleted: false,
|
|
131
|
+
reviewCompleted: false,
|
|
132
|
+
prCreated: false
|
|
133
|
+
},
|
|
134
|
+
[field]: true
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
await saveTaskPlan(this.tasksJsonPath, this.plan);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/ui/pipeline-renderer.ts
|
|
142
|
+
import { Listr, PRESET_TIMER, PRESET_TIMESTAMP } from "listr2";
|
|
143
|
+
var PHASE_LABELS = {
|
|
144
|
+
analyze: "Analyze",
|
|
145
|
+
prd: "PRD",
|
|
146
|
+
plan: "Plan",
|
|
147
|
+
execute: "Execute",
|
|
148
|
+
review: "Review",
|
|
149
|
+
pr: "PR"
|
|
150
|
+
};
|
|
151
|
+
function selectRenderer(verbose) {
|
|
152
|
+
const isTTY = !!process.stdout.isTTY;
|
|
153
|
+
const isCI = !!process.env.CI;
|
|
154
|
+
if (!isTTY || isCI) {
|
|
155
|
+
return "simple";
|
|
156
|
+
}
|
|
157
|
+
return verbose ? "verbose" : "default";
|
|
158
|
+
}
|
|
159
|
+
function buildExecutePhaseTask(runner, tasksPath, verbose) {
|
|
160
|
+
return async (_ctx, task) => {
|
|
161
|
+
let stories;
|
|
162
|
+
try {
|
|
163
|
+
const plan = await loadTaskPlan(tasksPath);
|
|
164
|
+
stories = [...plan.userStories].sort((a, b) => a.priority - b.priority);
|
|
165
|
+
} catch {
|
|
166
|
+
setOutputCallback((line) => {
|
|
167
|
+
task.output = line;
|
|
168
|
+
});
|
|
169
|
+
try {
|
|
170
|
+
await runner();
|
|
171
|
+
} finally {
|
|
172
|
+
setOutputCallback(void 0);
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const totalStories = stories.length;
|
|
177
|
+
const initialPassed = stories.filter((s) => s.passes).length;
|
|
178
|
+
task.title = `Execute (${initialPassed}/${totalStories} stories passing)`;
|
|
179
|
+
const resolvers = /* @__PURE__ */ new Map();
|
|
180
|
+
setStoryUpdateCallback((updatedStories) => {
|
|
181
|
+
const passed = updatedStories.filter((s) => s.passes).length;
|
|
182
|
+
task.title = `Execute (${passed}/${totalStories} stories passing)`;
|
|
183
|
+
for (const s of updatedStories) {
|
|
184
|
+
if (s.passes && resolvers.has(s.id)) {
|
|
185
|
+
resolvers.get(s.id).resolve();
|
|
186
|
+
resolvers.delete(s.id);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
const subtaskDefs = stories.map((story) => ({
|
|
191
|
+
title: `${story.id}: ${story.title}`,
|
|
192
|
+
skip: story.passes ? "already passing" : false,
|
|
193
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
194
|
+
task: async () => {
|
|
195
|
+
await new Promise((resolve, reject) => {
|
|
196
|
+
resolvers.set(story.id, { resolve, reject });
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
rendererOptions: {
|
|
200
|
+
timer: PRESET_TIMER
|
|
201
|
+
}
|
|
202
|
+
}));
|
|
203
|
+
const engineSubtask = {
|
|
204
|
+
title: "Running engine",
|
|
205
|
+
task: async (_c, engineTask) => {
|
|
206
|
+
setOutputCallback((line) => {
|
|
207
|
+
engineTask.output = line;
|
|
208
|
+
});
|
|
209
|
+
try {
|
|
210
|
+
await runner();
|
|
211
|
+
} finally {
|
|
212
|
+
setOutputCallback(void 0);
|
|
213
|
+
setStoryUpdateCallback(void 0);
|
|
214
|
+
for (const [, { resolve }] of resolvers) {
|
|
215
|
+
resolve();
|
|
216
|
+
}
|
|
217
|
+
resolvers.clear();
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
rendererOptions: {
|
|
221
|
+
timer: PRESET_TIMER,
|
|
222
|
+
outputBar: verbose ? Infinity : false,
|
|
223
|
+
persistentOutput: false,
|
|
224
|
+
bottomBar: verbose ? Infinity : 5
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
return task.newListr([engineSubtask, ...subtaskDefs], {
|
|
228
|
+
concurrent: true,
|
|
229
|
+
exitOnError: false,
|
|
230
|
+
rendererOptions: {
|
|
231
|
+
timer: PRESET_TIMER,
|
|
232
|
+
collapseSkips: false
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
async function runPipelineWithRenderer(options) {
|
|
238
|
+
const { phases, startIndex, verbose, runners, tasksPath } = options;
|
|
239
|
+
const overallStart = Date.now();
|
|
240
|
+
let currentPhase;
|
|
241
|
+
const renderer = selectRenderer(verbose);
|
|
242
|
+
const isSimple = renderer === "simple";
|
|
243
|
+
const tasks = new Listr(
|
|
244
|
+
phases.map((phase, index) => {
|
|
245
|
+
const label = PHASE_LABELS[phase] ?? phase.charAt(0).toUpperCase() + phase.slice(1);
|
|
246
|
+
const isExecutePhase = phase === "execute" && tasksPath;
|
|
247
|
+
return {
|
|
248
|
+
title: label,
|
|
249
|
+
skip: index < startIndex ? "skipped" : false,
|
|
250
|
+
task: isExecutePhase ? async (_ctx, task) => {
|
|
251
|
+
currentPhase = phase;
|
|
252
|
+
const runner = runners[phase];
|
|
253
|
+
if (!runner) {
|
|
254
|
+
throw new Error(`No runner defined for phase: ${phase}`);
|
|
255
|
+
}
|
|
256
|
+
return buildExecutePhaseTask(runner, tasksPath, verbose)(_ctx, task);
|
|
257
|
+
} : async (_ctx, task) => {
|
|
258
|
+
currentPhase = phase;
|
|
259
|
+
const runner = runners[phase];
|
|
260
|
+
if (!runner) {
|
|
261
|
+
throw new Error(`No runner defined for phase: ${phase}`);
|
|
262
|
+
}
|
|
263
|
+
setOutputCallback((line) => {
|
|
264
|
+
task.output = line;
|
|
265
|
+
});
|
|
266
|
+
try {
|
|
267
|
+
await runner();
|
|
268
|
+
} finally {
|
|
269
|
+
setOutputCallback(void 0);
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
rendererOptions: {
|
|
273
|
+
timer: PRESET_TIMER,
|
|
274
|
+
outputBar: verbose ? Infinity : false,
|
|
275
|
+
persistentOutput: false
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}),
|
|
279
|
+
{
|
|
280
|
+
renderer,
|
|
281
|
+
rendererOptions: {
|
|
282
|
+
timer: PRESET_TIMER,
|
|
283
|
+
collapseSkips: false,
|
|
284
|
+
...isSimple ? { timestamp: PRESET_TIMESTAMP } : {}
|
|
285
|
+
},
|
|
286
|
+
exitOnError: true
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
let failedPhase;
|
|
290
|
+
try {
|
|
291
|
+
await tasks.run();
|
|
292
|
+
} catch {
|
|
293
|
+
failedPhase = currentPhase ?? phases[startIndex];
|
|
294
|
+
} finally {
|
|
295
|
+
setOutputCallback(void 0);
|
|
296
|
+
setStoryUpdateCallback(void 0);
|
|
297
|
+
}
|
|
298
|
+
const overallElapsedSeconds = Math.floor((Date.now() - overallStart) / 1e3);
|
|
299
|
+
return {
|
|
300
|
+
success: !failedPhase,
|
|
301
|
+
failedPhase,
|
|
302
|
+
overallElapsedSeconds
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/commands/run.ts
|
|
307
|
+
async function runPipeline(issue, mode, from) {
|
|
308
|
+
const issueNumber = issue.replace(/^#/, "");
|
|
309
|
+
const issueDir = join("issues", issueNumber);
|
|
310
|
+
const tasksPath = join(issueDir, "tasks.json");
|
|
311
|
+
printInfo(`Starting pipeline for issue #${issueNumber} (mode: ${mode})`);
|
|
312
|
+
printInfo("Running prerequisite checks...");
|
|
313
|
+
const initCode = await runInit();
|
|
314
|
+
if (initCode !== 0) {
|
|
315
|
+
printError("Prerequisites not met. Fix the issues above and try again.");
|
|
316
|
+
return 1;
|
|
317
|
+
}
|
|
318
|
+
let startPhase = "analyze";
|
|
319
|
+
if (from) {
|
|
320
|
+
if (!PIPELINE_PHASES.includes(from)) {
|
|
321
|
+
printError(`Invalid phase: ${from}. Valid phases: ${PIPELINE_PHASES.join(", ")}`);
|
|
322
|
+
return 1;
|
|
323
|
+
}
|
|
324
|
+
startPhase = from;
|
|
325
|
+
} else {
|
|
326
|
+
try {
|
|
327
|
+
const plan = await loadTaskPlan(tasksPath);
|
|
328
|
+
const mgr = new PipelineManager(plan, tasksPath);
|
|
329
|
+
const nextPhase = mgr.getNextPhase();
|
|
330
|
+
if (nextPhase && nextPhase !== "init") {
|
|
331
|
+
startPhase = nextPhase;
|
|
332
|
+
printInfo(`Resuming from phase: ${startPhase}`);
|
|
333
|
+
}
|
|
334
|
+
} catch {
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (from) {
|
|
338
|
+
try {
|
|
339
|
+
const plan = await loadTaskPlan(tasksPath);
|
|
340
|
+
const mgr = new PipelineManager(plan, tasksPath);
|
|
341
|
+
if (!mgr.canResume(startPhase)) {
|
|
342
|
+
printError(`Cannot resume from ${startPhase}: prerequisite phases not complete`);
|
|
343
|
+
return 1;
|
|
344
|
+
}
|
|
345
|
+
} catch {
|
|
346
|
+
if (startPhase !== "analyze") {
|
|
347
|
+
printError(`Cannot resume from ${startPhase}: no pipeline state found`);
|
|
348
|
+
return 1;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
const phaseOrder = ["analyze", "prd", "plan", "execute", "review", "pr"];
|
|
353
|
+
const startIdx = phaseOrder.indexOf(startPhase);
|
|
354
|
+
const makeRunner = (fn, phase) => async () => {
|
|
355
|
+
const code = await fn();
|
|
356
|
+
if (code !== 0) {
|
|
357
|
+
throw new Error(`Phase ${phase} failed with exit code ${code}`);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
const runners = {
|
|
361
|
+
analyze: makeRunner(() => runAnalyze(issueNumber), "analyze"),
|
|
362
|
+
prd: makeRunner(() => runPrd(issueNumber), "prd"),
|
|
363
|
+
plan: makeRunner(() => runPlan(issueNumber), "plan"),
|
|
364
|
+
execute: makeRunner(() => runExecute(void 0, { issue: issueNumber }), "execute"),
|
|
365
|
+
review: async () => {
|
|
366
|
+
let maxCycles = 3;
|
|
367
|
+
try {
|
|
368
|
+
const plan = await loadTaskPlan(tasksPath);
|
|
369
|
+
maxCycles = plan.maxCorrectionCycles;
|
|
370
|
+
} catch {
|
|
371
|
+
}
|
|
372
|
+
let code = await runReview(issueNumber);
|
|
373
|
+
let cycle = 0;
|
|
374
|
+
while (code !== 0 && cycle < maxCycles) {
|
|
375
|
+
cycle++;
|
|
376
|
+
printWarning(`Review failed. Starting correction cycle ${cycle}/${maxCycles}...`);
|
|
377
|
+
try {
|
|
378
|
+
const plan = await loadTaskPlan(tasksPath);
|
|
379
|
+
plan.correctionCycle = cycle;
|
|
380
|
+
await saveTaskPlan(tasksPath, plan);
|
|
381
|
+
} catch {
|
|
382
|
+
}
|
|
383
|
+
const execCode = await runExecute(void 0, { issue: issueNumber });
|
|
384
|
+
if (execCode !== 0) {
|
|
385
|
+
throw new Error("Correction execution failed");
|
|
386
|
+
}
|
|
387
|
+
code = await runReview(issueNumber);
|
|
388
|
+
}
|
|
389
|
+
if (code !== 0) {
|
|
390
|
+
throw new Error(`Review failed after ${maxCycles} correction cycles`);
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
pr: makeRunner(() => runPr(issueNumber), "pr")
|
|
394
|
+
};
|
|
395
|
+
const result = await runPipelineWithRenderer({
|
|
396
|
+
phases: phaseOrder,
|
|
397
|
+
startIndex: startIdx,
|
|
398
|
+
verbose: isVerbose(),
|
|
399
|
+
runners,
|
|
400
|
+
tasksPath
|
|
401
|
+
});
|
|
402
|
+
if (!result.success) {
|
|
403
|
+
printError(`Phase ${result.failedPhase} failed`);
|
|
404
|
+
return 1;
|
|
405
|
+
}
|
|
406
|
+
printInfo("Closing issue...");
|
|
407
|
+
try {
|
|
408
|
+
await execa("gh", ["issue", "close", issueNumber], { reject: false });
|
|
409
|
+
} catch {
|
|
410
|
+
printWarning("Failed to close issue automatically");
|
|
411
|
+
}
|
|
412
|
+
let prUrl = "unknown";
|
|
413
|
+
try {
|
|
414
|
+
const proc = await execa("gh", ["pr", "list", "--head", "", "--json", "url", "--limit", "1"], {
|
|
415
|
+
reject: false
|
|
416
|
+
});
|
|
417
|
+
const parsed = JSON.parse(proc.stdout?.toString() ?? "[]");
|
|
418
|
+
if (parsed[0]?.url) {
|
|
419
|
+
prUrl = parsed[0].url;
|
|
420
|
+
}
|
|
421
|
+
} catch {
|
|
422
|
+
}
|
|
423
|
+
let branchName = "unknown";
|
|
424
|
+
try {
|
|
425
|
+
const proc = await execa("git", ["branch", "--show-current"], { reject: false });
|
|
426
|
+
branchName = proc.stdout?.toString().trim() ?? "unknown";
|
|
427
|
+
} catch {
|
|
428
|
+
}
|
|
429
|
+
let storyCount = 0;
|
|
430
|
+
try {
|
|
431
|
+
const plan = await loadTaskPlan(tasksPath);
|
|
432
|
+
storyCount = plan.userStories.length;
|
|
433
|
+
plan.issueStatus = "completed";
|
|
434
|
+
plan.completedAt = isoNow();
|
|
435
|
+
plan.lastAttemptAt = isoNow();
|
|
436
|
+
await saveTaskPlan(tasksPath, plan);
|
|
437
|
+
} catch {
|
|
438
|
+
}
|
|
439
|
+
const totalDuration = formatDuration(result.overallElapsedSeconds);
|
|
440
|
+
console.log("");
|
|
441
|
+
printSuccess(`Pipeline complete for issue #${issueNumber}!`);
|
|
442
|
+
console.log(` Branch: ${branchName}`);
|
|
443
|
+
console.log(` Stories: ${storyCount}`);
|
|
444
|
+
console.log(` Duration: ${totalDuration}`);
|
|
445
|
+
console.log(` PR: ${prUrl}`);
|
|
446
|
+
return 0;
|
|
447
|
+
}
|
|
448
|
+
export {
|
|
449
|
+
runPipeline
|
|
450
|
+
};
|
|
451
|
+
//# sourceMappingURL=run-6CR5FDYH.js.map
|