issue-flow 0.7.1 → 0.7.2
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/README.md +11 -7
- package/dist/{analyze-R25HDGBJ.js → analyze-XMEULTT2.js} +10 -10
- package/dist/analyze-XMEULTT2.js.map +1 -0
- package/dist/{chunk-23WOEBGN.js → chunk-6UBA7CSJ.js} +21 -18
- package/dist/chunk-6UBA7CSJ.js.map +1 -0
- package/dist/{chunk-ZAEBDO3Q.js → chunk-CYU6RSDJ.js} +13 -10
- package/dist/chunk-CYU6RSDJ.js.map +1 -0
- package/dist/{chunk-RN2FAMUU.js → chunk-DKMBLNGO.js} +70 -21
- package/dist/chunk-DKMBLNGO.js.map +1 -0
- package/dist/{chunk-2AVZZAC6.js → chunk-G3TJHMAS.js} +331 -26
- package/dist/chunk-G3TJHMAS.js.map +1 -0
- package/dist/{chunk-TCOS2KFB.js → chunk-GOZT2YP5.js} +18 -15
- package/dist/chunk-GOZT2YP5.js.map +1 -0
- package/dist/{chunk-EM43T462.js → chunk-MWUF4LMF.js} +8 -8
- package/dist/chunk-MWUF4LMF.js.map +1 -0
- package/dist/{chunk-WHIBTNYI.js → chunk-PRVWJZV4.js} +2 -2
- package/dist/{chunk-HJ7JT777.js → chunk-RGCU2KE6.js} +8 -8
- package/dist/chunk-RGCU2KE6.js.map +1 -0
- package/dist/{chunk-YGEWIEAI.js → chunk-WQ4SUZ4P.js} +3 -3
- package/dist/{chunk-ASMCLXQ2.js → chunk-WUITOU5B.js} +10 -10
- package/dist/chunk-WUITOU5B.js.map +1 -0
- package/dist/cli.js +11 -11
- package/dist/{config-SJAQMFWB.js → config-2NDV7Y72.js} +2 -2
- package/dist/{execute-VZ7SHLP4.js → execute-BOQPTRH4.js} +4 -4
- package/dist/{generate-LUK3XTIP.js → generate-YEQRH36H.js} +10 -6
- package/dist/generate-YEQRH36H.js.map +1 -0
- package/dist/{plan-R34SAWRK.js → plan-4I47CQM5.js} +5 -5
- package/dist/{pr-P4BDQXUQ.js → pr-F672VPMM.js} +5 -5
- package/dist/pr-review-GKP4TJRJ.js +15 -0
- package/dist/{prd-RYLULM75.js → prd-3QME4DYX.js} +5 -5
- package/dist/review-RG2UIPOB.js +13 -0
- package/dist/{run-SDRQDMSZ.js → run-EFXDXSB4.js} +26 -21
- package/dist/run-EFXDXSB4.js.map +1 -0
- package/package.json +1 -1
- package/prompts/generate.md +1 -1
- package/prompts/prd.md +1 -1
- package/dist/analyze-R25HDGBJ.js.map +0 -1
- package/dist/chunk-23WOEBGN.js.map +0 -1
- package/dist/chunk-2AVZZAC6.js.map +0 -1
- package/dist/chunk-ASMCLXQ2.js.map +0 -1
- package/dist/chunk-EM43T462.js.map +0 -1
- package/dist/chunk-HJ7JT777.js.map +0 -1
- package/dist/chunk-RN2FAMUU.js.map +0 -1
- package/dist/chunk-TCOS2KFB.js.map +0 -1
- package/dist/chunk-ZAEBDO3Q.js.map +0 -1
- package/dist/generate-LUK3XTIP.js.map +0 -1
- package/dist/pr-review-TOSBE6ZS.js +0 -15
- package/dist/review-ZSC5ELQA.js +0 -13
- package/dist/run-SDRQDMSZ.js.map +0 -1
- /package/dist/{chunk-WHIBTNYI.js.map → chunk-PRVWJZV4.js.map} +0 -0
- /package/dist/{chunk-YGEWIEAI.js.map → chunk-WQ4SUZ4P.js.map} +0 -0
- /package/dist/{config-SJAQMFWB.js.map → config-2NDV7Y72.js.map} +0 -0
- /package/dist/{execute-VZ7SHLP4.js.map → execute-BOQPTRH4.js.map} +0 -0
- /package/dist/{plan-R34SAWRK.js.map → plan-4I47CQM5.js.map} +0 -0
- /package/dist/{pr-P4BDQXUQ.js.map → pr-F672VPMM.js.map} +0 -0
- /package/dist/{pr-review-TOSBE6ZS.js.map → pr-review-GKP4TJRJ.js.map} +0 -0
- /package/dist/{prd-RYLULM75.js.map → prd-3QME4DYX.js.map} +0 -0
- /package/dist/{review-ZSC5ELQA.js.map → review-RG2UIPOB.js.map} +0 -0
|
@@ -15,6 +15,12 @@ import {
|
|
|
15
15
|
import { createInterface } from "readline";
|
|
16
16
|
import chalk from "chalk";
|
|
17
17
|
import { execa } from "execa";
|
|
18
|
+
function pushRepeatedFlag(args, flag, values) {
|
|
19
|
+
if (!values || values.length === 0) return;
|
|
20
|
+
for (const value of values) {
|
|
21
|
+
args.push(flag, value);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
18
24
|
function getToolContext(name, input) {
|
|
19
25
|
switch (name) {
|
|
20
26
|
case "Read":
|
|
@@ -87,7 +93,8 @@ function printStreamEvent(line, state, onOutput) {
|
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
|
-
async function runHeadlessVerbose(
|
|
96
|
+
async function runHeadlessVerbose(options) {
|
|
97
|
+
const { prompt, maxTurns, timeout, allowedTools, addDirs, statusMessage, onOutput } = options;
|
|
91
98
|
const icons = getIcons();
|
|
92
99
|
const colored = useColor();
|
|
93
100
|
const emit = onOutput ?? ((msg) => process.stderr.write(`${msg}
|
|
@@ -108,11 +115,8 @@ async function runHeadlessVerbose(prompt, maxTurns, timeout, allowedTools, statu
|
|
|
108
115
|
"--max-turns",
|
|
109
116
|
String(maxTurns)
|
|
110
117
|
];
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
args.push("--allowedTools", tool);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
118
|
+
pushRepeatedFlag(args, "--allowedTools", allowedTools);
|
|
119
|
+
pushRepeatedFlag(args, "--add-dir", addDirs);
|
|
116
120
|
const subprocess = execa("claude", args, {
|
|
117
121
|
stdin: "ignore",
|
|
118
122
|
reject: false,
|
|
@@ -174,19 +178,21 @@ async function runHeadless(options) {
|
|
|
174
178
|
timeout = 3e5,
|
|
175
179
|
outputFormat = "json",
|
|
176
180
|
allowedTools,
|
|
181
|
+
addDirs,
|
|
177
182
|
statusMessage,
|
|
178
183
|
onOutput
|
|
179
184
|
} = options;
|
|
180
185
|
if (isVerbose()) {
|
|
181
186
|
const effectiveOnOutput = onOutput ?? getOutputCallback();
|
|
182
|
-
return runHeadlessVerbose(
|
|
187
|
+
return runHeadlessVerbose({
|
|
183
188
|
prompt,
|
|
184
189
|
maxTurns,
|
|
185
190
|
timeout,
|
|
186
191
|
allowedTools,
|
|
192
|
+
addDirs,
|
|
187
193
|
statusMessage,
|
|
188
|
-
effectiveOnOutput
|
|
189
|
-
);
|
|
194
|
+
onOutput: effectiveOnOutput
|
|
195
|
+
});
|
|
190
196
|
}
|
|
191
197
|
const spinner = statusMessage ? createSpinner(statusMessage).start() : null;
|
|
192
198
|
let timer = null;
|
|
@@ -203,11 +209,8 @@ async function runHeadless(options) {
|
|
|
203
209
|
"--max-turns",
|
|
204
210
|
String(maxTurns)
|
|
205
211
|
];
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
args.push("--allowedTools", tool);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
212
|
+
pushRepeatedFlag(args, "--allowedTools", allowedTools);
|
|
213
|
+
pushRepeatedFlag(args, "--add-dir", addDirs);
|
|
211
214
|
try {
|
|
212
215
|
const proc = await execa("claude", args, {
|
|
213
216
|
stdin: "ignore",
|
|
@@ -280,4 +283,4 @@ async function runHeadless(options) {
|
|
|
280
283
|
export {
|
|
281
284
|
runHeadless
|
|
282
285
|
};
|
|
283
|
-
//# sourceMappingURL=chunk-
|
|
286
|
+
//# sourceMappingURL=chunk-GOZT2YP5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/headless.ts"],"sourcesContent":["import { createInterface } from 'node:readline';\nimport chalk from 'chalk';\nimport { execa } from 'execa';\nimport { createSpinner, ElapsedTimer, formatDuration, getIcons, useColor } from '../ui/logger.js';\nimport { getSessionPublisher } from './session-publisher.js';\nimport { isoNow } from './state-manager.js';\nimport { getOutputCallback, isVerbose } from './verbose.js';\n\nexport interface HeadlessOptions {\n prompt: string;\n maxTurns?: number;\n timeout?: number;\n outputFormat?: 'json' | 'text' | 'stream-json';\n allowedTools?: string[];\n /**\n * Extra directories the headless session may read from and write to, passed\n * through as `--add-dir`. Required whenever a prompt points at a path outside\n * the working tree (e.g. the global issue storage under `~/.issue-flow`),\n * since `claude -p` otherwise refuses the access.\n */\n addDirs?: string[];\n /** Status message displayed as spinner (non-verbose) or header (verbose). */\n statusMessage?: string;\n /** Optional callback for routing verbose output (e.g., through listr2 task.output). When provided, verbose stream events are sent here instead of directly to stderr. */\n onOutput?: (line: string) => void;\n}\n\nexport interface HeadlessCost {\n inputTokens?: number;\n outputTokens?: number;\n}\n\nexport interface HeadlessResult {\n success: boolean;\n result: string;\n cost: HeadlessCost | null;\n error: string | null;\n}\n\n/* ── argument helpers ───────────────────────────────────────────────────── */\n\n/**\n * Append one `<flag> <value>` pair per value. An empty or absent list leaves\n * `args` untouched, so callers that pass nothing keep the exact same argv.\n */\nfunction pushRepeatedFlag(args: string[], flag: string, values: string[] | undefined): void {\n if (!values || values.length === 0) return;\n for (const value of values) {\n args.push(flag, value);\n }\n}\n\n/* ── verbose stream formatting ──────────────────────────────────────────── */\n\n/**\n * Extract a short context string from a tool_use input object.\n */\nfunction getToolContext(name: string, input: Record<string, unknown>): string {\n switch (name) {\n case 'Read':\n return shortPath(input.file_path as string);\n case 'Write':\n case 'Edit':\n return shortPath(input.file_path as string);\n case 'Glob':\n return (input.pattern as string) ?? '';\n case 'Grep':\n return (input.pattern as string) ?? '';\n case 'Bash': {\n const cmd = (input.command as string) ?? '';\n return cmd.length > 60 ? `${cmd.substring(0, 57)}...` : cmd;\n }\n default:\n return '';\n }\n}\n\n/**\n * Shorten a file path to be relative-friendly.\n */\nfunction shortPath(filePath: string | undefined): string {\n if (!filePath) return '';\n const cwd = process.cwd();\n if (filePath.startsWith(cwd)) {\n return filePath.substring(cwd.length + 1);\n }\n // Show last 2 segments for absolute paths\n const parts = filePath.split('/');\n if (parts.length > 2) {\n return `.../${parts.slice(-2).join('/')}`;\n }\n return filePath;\n}\n\n/**\n * Print a formatted stream event line to stderr.\n */\nfunction printStreamEvent(\n line: string,\n state: { turnCount: number },\n onOutput?: (line: string) => void,\n): void {\n let event: {\n type?: string;\n subtype?: string;\n message?: {\n content?: { type: string; text?: string; name?: string; input?: Record<string, unknown> }[];\n };\n };\n\n try {\n event = JSON.parse(line);\n } catch {\n return;\n }\n\n const icons = getIcons();\n const colored = useColor();\n const emit = onOutput ?? ((msg: string) => process.stderr.write(`${msg}\\n`));\n\n if (event.type === 'assistant' && event.message?.content) {\n state.turnCount++;\n\n for (const block of event.message.content) {\n if (block.type === 'text' && block.text) {\n // Wrap text with connector prefix\n const lines = block.text.split('\\n');\n for (const textLine of lines) {\n if (!textLine.trim()) continue;\n const prefix = colored ? chalk.dim(` ${icons.connector} `) : ` ${icons.connector} `;\n const text = colored ? chalk.dim(textLine) : textLine;\n emit(`${prefix}${text}`);\n }\n }\n\n if (block.type === 'tool_use' && block.name) {\n const context = block.input ? getToolContext(block.name, block.input) : '';\n getSessionPublisher().publish({\n type: 'activity',\n at: isoNow(),\n tool: block.name,\n detail: context || undefined,\n });\n const toolName = block.name.padEnd(12);\n\n const prefix = colored ? chalk.dim(` ${icons.connector} `) : ` ${icons.connector} `;\n const toolIcon = colored ? chalk.cyan(icons.tool) : icons.tool;\n const toolLabel = colored ? chalk.cyan(toolName) : toolName;\n const contextText = context ? (colored ? chalk.dim(context) : context) : '';\n\n emit(`${prefix}${toolIcon} ${toolLabel} ${contextText}`);\n }\n }\n }\n}\n\n/* ── verbose execution ──────────────────────────────────────────────────── */\n\n/**\n * Run headless in verbose mode using stream-json to display real-time progress.\n */\nasync function runHeadlessVerbose(options: {\n prompt: string;\n maxTurns: number;\n timeout: number;\n allowedTools?: string[];\n addDirs?: string[];\n statusMessage?: string;\n onOutput?: (line: string) => void;\n}): Promise<HeadlessResult> {\n const { prompt, maxTurns, timeout, allowedTools, addDirs, statusMessage, onOutput } = options;\n const icons = getIcons();\n const colored = useColor();\n const emit = onOutput ?? ((msg: string) => process.stderr.write(`${msg}\\n`));\n\n // Print header\n if (statusMessage) {\n const msg = colored\n ? chalk.blue(`${icons.start} ${statusMessage}`)\n : `${icons.start} ${statusMessage}`;\n emit(msg);\n }\n\n // Print opening connector\n const connectorLine = colored ? chalk.dim(` ${icons.connector}`) : ` ${icons.connector}`;\n emit(connectorLine);\n\n const startTime = Date.now();\n\n const args: string[] = [\n '-p',\n prompt,\n '--output-format',\n 'stream-json',\n '--verbose',\n '--max-turns',\n String(maxTurns),\n ];\n\n pushRepeatedFlag(args, '--allowedTools', allowedTools);\n pushRepeatedFlag(args, '--add-dir', addDirs);\n\n const subprocess = execa('claude', args, {\n stdin: 'ignore',\n reject: false,\n timeout,\n stripFinalNewline: false,\n });\n\n let resultText = '';\n let isError = false;\n let costData: HeadlessCost | null = null;\n const state = { turnCount: 0 };\n\n if (subprocess.stdout) {\n const rl = createInterface({ input: subprocess.stdout });\n for await (const line of rl) {\n printStreamEvent(line, state, onOutput);\n\n try {\n const event = JSON.parse(line);\n if (event.type === 'result') {\n resultText = event.result ?? '';\n isError = event.is_error === true;\n if (event.total_cost_usd != null && event.usage) {\n costData = {\n inputTokens: event.usage.input_tokens,\n outputTokens: event.usage.output_tokens,\n };\n }\n }\n } catch {\n // ignore malformed lines\n }\n }\n }\n\n // Wait for the process to finish\n const proc = await subprocess;\n\n // Close connector with elapsed time\n const elapsedSec = Math.floor((Date.now() - startTime) / 1000);\n const durationStr = formatDuration(elapsedSec);\n const doneLine = colored\n ? chalk.dim(` ${icons.connector} ${chalk.italic(`Done in ${durationStr}`)}`)\n : ` ${icons.connector} Done in ${durationStr}`;\n emit(doneLine);\n emit(connectorLine);\n\n if (proc.exitCode !== 0 && !resultText) {\n const stderr = proc.stderr?.toString() ?? '';\n const isTimeout =\n proc.exitCode === 143 || ('signalName' in proc && proc.signalName === 'SIGTERM');\n const errorMsg = isTimeout\n ? `Headless invocation timed out after ${timeout}ms`\n : stderr || `claude exited with code ${proc.exitCode}`;\n return {\n success: false,\n result: '',\n cost: null,\n error: errorMsg,\n };\n }\n\n return {\n success: !isError,\n result: resultText,\n cost: costData,\n error: isError ? resultText : null,\n };\n}\n\n/* ── standard execution ─────────────────────────────────────────────────── */\n\n/**\n * Invoke Claude Code in headless mode via `claude -p`.\n *\n * Each invocation is an isolated session — no context is shared between calls.\n * Output is parsed as JSON when outputFormat is 'json' (default).\n *\n * When verbose mode is active, uses stream-json to display real-time progress.\n * Otherwise, shows a spinner while waiting.\n */\nexport async function runHeadless(options: HeadlessOptions): Promise<HeadlessResult> {\n const {\n prompt,\n maxTurns = 10,\n timeout = 300_000,\n outputFormat = 'json',\n allowedTools,\n addDirs,\n statusMessage,\n onOutput,\n } = options;\n\n if (isVerbose()) {\n // Use explicit onOutput, fall back to global output callback, or default to stderr\n const effectiveOnOutput = onOutput ?? getOutputCallback();\n return runHeadlessVerbose({\n prompt,\n maxTurns,\n timeout,\n allowedTools,\n addDirs,\n statusMessage,\n onOutput: effectiveOnOutput,\n });\n }\n\n // Non-verbose: use spinner with elapsed timer\n const spinner = statusMessage ? createSpinner(statusMessage).start() : null;\n\n let timer: ElapsedTimer | null = null;\n if (spinner) {\n timer = new ElapsedTimer((elapsed) => {\n spinner.suffixText = useColor() ? chalk.dim(`(${elapsed})`) : `(${elapsed})`;\n }).start();\n }\n\n const args: string[] = [\n '-p',\n prompt,\n '--output-format',\n outputFormat,\n '--max-turns',\n String(maxTurns),\n ];\n\n pushRepeatedFlag(args, '--allowedTools', allowedTools);\n pushRepeatedFlag(args, '--add-dir', addDirs);\n\n try {\n const proc = await execa('claude', args, {\n stdin: 'ignore',\n reject: false,\n timeout,\n stripFinalNewline: false,\n });\n\n const stdout = proc.stdout?.toString() ?? '';\n const stderr = proc.stderr?.toString() ?? '';\n\n if (proc.exitCode !== 0) {\n const elapsed = timer?.stop() ?? 0;\n const dur = useColor()\n ? chalk.dim(` (${formatDuration(elapsed)})`)\n : ` (${formatDuration(elapsed)})`;\n spinner?.fail(`${statusMessage}${dur}`);\n return {\n success: false,\n result: '',\n cost: null,\n error: stderr || stdout || `claude exited with code ${proc.exitCode}`,\n };\n }\n\n const elapsed = timer?.stop() ?? 0;\n const dur = useColor()\n ? chalk.dim(` (${formatDuration(elapsed)})`)\n : ` (${formatDuration(elapsed)})`;\n spinner?.succeed(`${statusMessage}${dur}`);\n\n if (outputFormat === 'json') {\n try {\n const parsed = JSON.parse(stdout);\n return {\n success: true,\n result: parsed.result ?? stdout,\n cost:\n parsed.cost_usd != null\n ? { inputTokens: parsed.num_input_tokens, outputTokens: parsed.num_output_tokens }\n : null,\n error: null,\n };\n } catch {\n return {\n success: true,\n result: stdout,\n cost: null,\n error: null,\n };\n }\n }\n\n return {\n success: true,\n result: stdout,\n cost: null,\n error: null,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const catchElapsed = timer?.stop() ?? 0;\n const catchDur = useColor()\n ? chalk.dim(` (${formatDuration(catchElapsed)})`)\n : ` (${formatDuration(catchElapsed)})`;\n spinner?.fail(`${statusMessage}${catchDur}`);\n\n if (message.includes('timed out') || message.includes('ETIMEDOUT')) {\n return {\n success: false,\n result: '',\n cost: null,\n error: `Headless invocation timed out after ${timeout}ms`,\n };\n }\n\n return {\n success: false,\n result: '',\n cost: null,\n error: message,\n };\n }\n}\n"],"mappings":"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","names":["elapsed","dur"]}
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
import {
|
|
3
3
|
issuePlaceholders,
|
|
4
4
|
resolveCommandIssue
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DKMBLNGO.js";
|
|
6
6
|
import {
|
|
7
7
|
runHeadless
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GOZT2YP5.js";
|
|
9
9
|
import {
|
|
10
10
|
applyPlaceholders,
|
|
11
11
|
loadPrompt
|
|
12
12
|
} from "./chunk-SLHZPB3C.js";
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
} from "./chunk-
|
|
14
|
+
resolveIssuePaths
|
|
15
|
+
} from "./chunk-G3TJHMAS.js";
|
|
16
16
|
import {
|
|
17
17
|
getGlobalTimeout,
|
|
18
18
|
loadTaskPlan,
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
} from "./chunk-JNEHVQH5.js";
|
|
23
23
|
|
|
24
24
|
// src/commands/review.ts
|
|
25
|
-
import { join } from "path";
|
|
26
25
|
function parseReviewResult(output) {
|
|
27
26
|
const match = output.match(/<review-result>([\s\S]*?)<\/review-result>/);
|
|
28
27
|
if (!match) {
|
|
@@ -47,8 +46,8 @@ function parseReviewResult(output) {
|
|
|
47
46
|
}
|
|
48
47
|
async function runReview(issue, resolvedIssue) {
|
|
49
48
|
const issueNumber = issue.replace(/^#/, "");
|
|
50
|
-
const
|
|
51
|
-
const tasksPath =
|
|
49
|
+
const paths = await resolveIssuePaths(issueNumber);
|
|
50
|
+
const tasksPath = paths.tasksFile;
|
|
52
51
|
const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);
|
|
53
52
|
if (!resolution.ok) {
|
|
54
53
|
return resolution.code;
|
|
@@ -65,6 +64,7 @@ async function runReview(issue, resolvedIssue) {
|
|
|
65
64
|
timeout: getGlobalTimeout() ?? 3e5,
|
|
66
65
|
outputFormat: "text",
|
|
67
66
|
allowedTools: ["Bash", "Read", "Glob", "Grep"],
|
|
67
|
+
addDirs: [paths.issueDir],
|
|
68
68
|
statusMessage: `Reviewing issue #${issueNumber} resolution...`
|
|
69
69
|
});
|
|
70
70
|
if (!result.success) {
|
|
@@ -100,4 +100,4 @@ async function runReview(issue, resolvedIssue) {
|
|
|
100
100
|
export {
|
|
101
101
|
runReview
|
|
102
102
|
};
|
|
103
|
-
//# sourceMappingURL=chunk-
|
|
103
|
+
//# sourceMappingURL=chunk-MWUF4LMF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/review.ts"],"sourcesContent":["import { 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 { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printSuccess } from '../ui/logger.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 paths = await resolveIssuePaths(issueNumber);\n const tasksPath = paths.tasksFile;\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 addDirs: [paths.issueDir],\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 plan.lastReviewFindings = null;\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\n // Persist the findings so a correction cycle can act on them: without this,\n // a re-run of execute sees every userStories[].passes already true and\n // exits immediately without attempting any fix (see engine.ts's\n // \"already complete\" guards).\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = false;\n plan.lastReviewFindings = review.findings ?? 'Unknown findings';\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n return 1;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAiBA,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,QAAQ,MAAM,kBAAkB,WAAW;AACjD,QAAM,YAAY,MAAM;AAExB,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,SAAS,CAAC,MAAM,QAAQ;AAAA,IACxB,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,WAAK,qBAAqB;AAC1B,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;AAMA,MAAI;AACF,UAAM,OAAO,MAAM,aAAa,SAAS;AACzC,SAAK,SAAS,kBAAkB;AAChC,SAAK,qBAAqB,OAAO,YAAY;AAC7C,UAAM,aAAa,WAAW,IAAI;AAAA,EACpC,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;","names":["findingsMatch"]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getCommitsSince,
|
|
5
5
|
getCurrentBranch,
|
|
6
6
|
run
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-G3TJHMAS.js";
|
|
8
8
|
import {
|
|
9
9
|
NullPublisher,
|
|
10
10
|
isoNow
|
|
@@ -69,4 +69,4 @@ export {
|
|
|
69
69
|
listPullRequests,
|
|
70
70
|
publishGitState
|
|
71
71
|
};
|
|
72
|
-
//# sourceMappingURL=chunk-
|
|
72
|
+
//# sourceMappingURL=chunk-PRVWJZV4.js.map
|
|
@@ -5,20 +5,20 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
issuePlaceholders,
|
|
7
7
|
resolveCommandIssue
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DKMBLNGO.js";
|
|
9
9
|
import {
|
|
10
10
|
isTransientFailure
|
|
11
11
|
} from "./chunk-HDV3YDTG.js";
|
|
12
12
|
import {
|
|
13
13
|
runHeadless
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-GOZT2YP5.js";
|
|
15
15
|
import {
|
|
16
16
|
applyPlaceholders,
|
|
17
17
|
loadPrompt
|
|
18
18
|
} from "./chunk-SLHZPB3C.js";
|
|
19
19
|
import {
|
|
20
|
-
|
|
21
|
-
} from "./chunk-
|
|
20
|
+
resolveIssuePaths
|
|
21
|
+
} from "./chunk-G3TJHMAS.js";
|
|
22
22
|
import {
|
|
23
23
|
getGlobalTimeout,
|
|
24
24
|
isoNow,
|
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
} from "./chunk-JNEHVQH5.js";
|
|
30
30
|
|
|
31
31
|
// src/commands/pr.ts
|
|
32
|
-
import { join } from "path";
|
|
33
32
|
import { execa } from "execa";
|
|
34
33
|
function parsePrUrl(output) {
|
|
35
34
|
const match = output.match(/(https:\/\/github\.com\/[^\s]+\/pull\/\d+)/);
|
|
@@ -47,8 +46,8 @@ function issueClosesLine(issue, fallbackId) {
|
|
|
47
46
|
}
|
|
48
47
|
async function runPr(issue, resolvedIssue) {
|
|
49
48
|
const issueNumber = issue.replace(/^#/, "");
|
|
50
|
-
const
|
|
51
|
-
const tasksPath =
|
|
49
|
+
const paths = await resolveIssuePaths(issueNumber);
|
|
50
|
+
const tasksPath = paths.tasksFile;
|
|
52
51
|
const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);
|
|
53
52
|
if (!resolution.ok) {
|
|
54
53
|
return resolution.code;
|
|
@@ -83,6 +82,7 @@ async function runPr(issue, resolvedIssue) {
|
|
|
83
82
|
timeout: getGlobalTimeout() ?? 3e5,
|
|
84
83
|
outputFormat: "text",
|
|
85
84
|
allowedTools: ["Bash", "Read", "Glob", "Grep"],
|
|
85
|
+
addDirs: [paths.issueDir],
|
|
86
86
|
statusMessage: `Creating PR for issue #${issueNumber}...`
|
|
87
87
|
});
|
|
88
88
|
if (!result.success) {
|
|
@@ -127,4 +127,4 @@ async function runPr(issue, resolvedIssue) {
|
|
|
127
127
|
export {
|
|
128
128
|
runPr
|
|
129
129
|
};
|
|
130
|
-
//# sourceMappingURL=chunk-
|
|
130
|
+
//# sourceMappingURL=chunk-RGCU2KE6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/pr.ts"],"sourcesContent":["import { execa } from 'execa';\nimport { runHeadless } from '../core/headless.js';\nimport { runPhaseWithRetry } from '../core/phase-runner.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { isoNow, loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { issuePlaceholders, resolveCommandIssue } from '../issues/context.js';\nimport type { Issue, ResolvedIssue } from '../issues/types.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printSuccess } from '../ui/logger.js';\nimport { isTransientFailure } from '../utils/retry.js';\n\n/**\n * Extract a PR URL from headless output.\n */\nfunction parsePrUrl(output: string): string | null {\n const match = output.match(/(https:\\/\\/github\\.com\\/[^\\s]+\\/pull\\/\\d+)/);\n return match?.[1] ?? null;\n}\n\n/**\n * The numeric id inside a PR URL, so later phases (`pr-review`) address the\n * Pull Request without querying GitHub again.\n */\nfunction parsePrNumber(url: string): number | null {\n const match = url.match(/\\/pull\\/(\\d+)/);\n return match?.[1] === undefined ? null : Number(match[1]);\n}\n\n/**\n * The `Closes #N` line for the PR body, empty when the Issue has no remote\n * counterpart: GitHub only understands the reference for Issues it hosts, and\n * an invented `#N` would silently point at an unrelated Issue.\n */\nfunction issueClosesLine(issue: Issue, fallbackId: string): string {\n if (issue.remoteRef === null) {\n return '';\n }\n return `Closes #${issue.number ?? fallbackId}`;\n}\n\nexport async function runPr(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n const tasksPath = paths.tasksFile;\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n // Get current branch\n let branchName: string;\n try {\n const proc = await execa('git', ['branch', '--show-current'], { reject: false });\n branchName = proc.stdout?.toString().trim() ?? '';\n if (!branchName) {\n printError('Could not determine current branch');\n return 1;\n }\n } catch {\n printError('Failed to get current branch');\n return 1;\n }\n\n const template = await loadPrompt('pr');\n const prompt = applyPlaceholders(template, {\n __ISSUE_NUMBER__: issueNumber,\n __BRANCH_NAME__: branchName,\n __TASKS_PATH__: tasksPath,\n __ISSUE_CLOSES__: issueClosesLine(resolution.resolved.issue, issueNumber),\n ...issuePlaceholders(resolution.resolved),\n });\n\n let headlessOutput = '';\n\n const outcome = await runPhaseWithRetry({\n phase: 'pr',\n attempt: async () => {\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 addDirs: [paths.issueDir],\n statusMessage: `Creating PR for issue #${issueNumber}...`,\n });\n\n if (!result.success) {\n return {\n ok: false,\n transient: isTransientFailure(1, result.error ?? ''),\n error: `PR creation failed: ${result.error}`,\n };\n }\n\n headlessOutput = result.result;\n return { ok: true };\n },\n });\n\n if (!outcome.ok) {\n printError(outcome.error ?? `PR creation failed for issue #${issueNumber}`);\n return 1;\n }\n\n const prUrl = parsePrUrl(headlessOutput);\n\n // Update pipeline state\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.prCreated = true;\n const prNumber = prUrl === null ? null : parsePrNumber(prUrl);\n // Without a URL the PR is still assumed created (the phase succeeded), but\n // there is nothing trustworthy to record: an invented number would send\n // `pr-review` at an unrelated Pull Request.\n if (prUrl !== null && prNumber !== null) {\n plan.pullRequest = {\n number: prNumber,\n url: prUrl,\n headBranch: branchName,\n createdAt: isoNow(),\n };\n }\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n if (prUrl) {\n printSuccess(`PR created: ${prUrl}`);\n } else {\n printSuccess('PR creation completed');\n }\n return 0;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-HDV3YDTG.js";
|
|
7
7
|
import {
|
|
8
8
|
publishGitState
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PRVWJZV4.js";
|
|
10
10
|
import {
|
|
11
11
|
applyPlaceholders,
|
|
12
12
|
loadPrompt
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
createConfig,
|
|
16
16
|
resolvePaths,
|
|
17
17
|
validateDependencies
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-G3TJHMAS.js";
|
|
19
19
|
import {
|
|
20
20
|
allStoriesPass,
|
|
21
21
|
clearLastError,
|
|
@@ -541,4 +541,4 @@ export {
|
|
|
541
541
|
printRunSummary,
|
|
542
542
|
runExecute
|
|
543
543
|
};
|
|
544
|
-
//# sourceMappingURL=chunk-
|
|
544
|
+
//# sourceMappingURL=chunk-WQ4SUZ4P.js.map
|
|
@@ -6,20 +6,20 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
issuePlaceholders,
|
|
8
8
|
resolveCommandIssue
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DKMBLNGO.js";
|
|
10
10
|
import {
|
|
11
11
|
isTransientFailure
|
|
12
12
|
} from "./chunk-HDV3YDTG.js";
|
|
13
13
|
import {
|
|
14
14
|
runHeadless
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-GOZT2YP5.js";
|
|
16
16
|
import {
|
|
17
17
|
applyPlaceholders,
|
|
18
18
|
loadPrompt
|
|
19
19
|
} from "./chunk-SLHZPB3C.js";
|
|
20
20
|
import {
|
|
21
|
-
|
|
22
|
-
} from "./chunk-
|
|
21
|
+
resolveIssuePaths
|
|
22
|
+
} from "./chunk-G3TJHMAS.js";
|
|
23
23
|
import {
|
|
24
24
|
getGlobalTimeout,
|
|
25
25
|
loadTaskPlan,
|
|
@@ -31,15 +31,14 @@ import {
|
|
|
31
31
|
|
|
32
32
|
// src/commands/plan.ts
|
|
33
33
|
import { mkdir, readFile } from "fs/promises";
|
|
34
|
-
import { join } from "path";
|
|
35
34
|
async function runPlan(issue, resolvedIssue) {
|
|
36
35
|
const issueNumber = issue.replace(/^#/, "");
|
|
37
|
-
const
|
|
36
|
+
const paths = await resolveIssuePaths(issueNumber);
|
|
38
37
|
const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);
|
|
39
38
|
if (!resolution.ok) {
|
|
40
39
|
return resolution.code;
|
|
41
40
|
}
|
|
42
|
-
const prdPath =
|
|
41
|
+
const prdPath = paths.prdFile;
|
|
43
42
|
let prdContent;
|
|
44
43
|
try {
|
|
45
44
|
prdContent = await readFile(prdPath, "utf-8");
|
|
@@ -47,7 +46,7 @@ async function runPlan(issue, resolvedIssue) {
|
|
|
47
46
|
printError(`PRD not found at ${prdPath}. Run 'issue-flow prd ${issueNumber}' first.`);
|
|
48
47
|
return 1;
|
|
49
48
|
}
|
|
50
|
-
const tasksPath =
|
|
49
|
+
const tasksPath = paths.tasksFile;
|
|
51
50
|
const template = await loadPrompt("plan");
|
|
52
51
|
const prompt = applyPlaceholders(template, {
|
|
53
52
|
__ISSUE_NUMBER__: issueNumber,
|
|
@@ -55,7 +54,7 @@ async function runPlan(issue, resolvedIssue) {
|
|
|
55
54
|
__TASKS_PATH__: tasksPath,
|
|
56
55
|
...issuePlaceholders(resolution.resolved)
|
|
57
56
|
});
|
|
58
|
-
await mkdir(issueDir, { recursive: true });
|
|
57
|
+
await mkdir(paths.issueDir, { recursive: true });
|
|
59
58
|
const outcome = await runPhaseWithRetry({
|
|
60
59
|
phase: "plan",
|
|
61
60
|
attempt: async () => {
|
|
@@ -65,6 +64,7 @@ async function runPlan(issue, resolvedIssue) {
|
|
|
65
64
|
timeout: getGlobalTimeout() ?? 3e5,
|
|
66
65
|
outputFormat: "text",
|
|
67
66
|
allowedTools: ["Bash", "Read", "Glob", "Grep", "Write"],
|
|
67
|
+
addDirs: [paths.issueDir],
|
|
68
68
|
statusMessage: `Converting PRD to task plan for issue #${issueNumber}...`
|
|
69
69
|
});
|
|
70
70
|
if (!result.success) {
|
|
@@ -113,4 +113,4 @@ ${issues}`
|
|
|
113
113
|
export {
|
|
114
114
|
runPlan
|
|
115
115
|
};
|
|
116
|
-
//# sourceMappingURL=chunk-
|
|
116
|
+
//# sourceMappingURL=chunk-WUITOU5B.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/plan.ts"],"sourcesContent":["import { mkdir, readFile } from 'node:fs/promises';\nimport { runHeadless } from '../core/headless.js';\nimport { readFileWithGrace, runPhaseWithRetry } from '../core/phase-runner.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 { taskPlanSchema } from '../schemas.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printSuccess } from '../ui/logger.js';\nimport { isTransientFailure } from '../utils/retry.js';\n\nexport async function runPlan(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n // Read the PRD\n const prdPath = paths.prdFile;\n let prdContent: string;\n try {\n prdContent = await readFile(prdPath, 'utf-8');\n } catch {\n printError(`PRD not found at ${prdPath}. Run 'issue-flow prd ${issueNumber}' first.`);\n return 1;\n }\n\n const tasksPath = paths.tasksFile;\n\n const template = await loadPrompt('plan');\n const prompt = applyPlaceholders(template, {\n __ISSUE_NUMBER__: issueNumber,\n __PRD_CONTENT__: prdContent,\n __TASKS_PATH__: tasksPath,\n ...issuePlaceholders(resolution.resolved),\n });\n\n await mkdir(paths.issueDir, { recursive: true });\n\n const outcome = await runPhaseWithRetry({\n phase: 'plan',\n attempt: async () => {\n const result = await runHeadless({\n prompt,\n maxTurns: 25,\n timeout: getGlobalTimeout() ?? 300_000,\n outputFormat: 'text',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep', 'Write'],\n addDirs: [paths.issueDir],\n statusMessage: `Converting PRD to task plan for issue #${issueNumber}...`,\n });\n\n if (!result.success) {\n return {\n ok: false,\n transient: isTransientFailure(1, result.error ?? ''),\n error: `Task plan generation failed: ${result.error}`,\n };\n }\n\n // Verify the file was created, tolerating a brief FS-visibility lag.\n let rawContent: string;\n try {\n rawContent = await readFileWithGrace(tasksPath);\n } catch {\n return { ok: false, transient: true, error: `tasks.json was not created at ${tasksPath}` };\n }\n\n // Validate JSON structure — a content defect, not a timing issue, but\n // still worth a bounded retry since it's a fresh Claude invocation.\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawContent);\n } catch {\n return { ok: false, transient: true, error: 'tasks.json contains invalid JSON' };\n }\n\n // Validate with zod schema\n const validation = taskPlanSchema.safeParse(parsed);\n if (!validation.success) {\n const issues = validation.error.issues\n .map((i) => ` - ${i.path.join('.')}: ${i.message}`)\n .join('\\n');\n return {\n ok: false,\n transient: true,\n error: `tasks.json does not match expected schema:\\n${issues}`,\n };\n }\n\n return { ok: true };\n },\n });\n\n if (!outcome.ok) {\n printError(outcome.error ?? `Task plan generation failed for issue #${issueNumber}`);\n return 1;\n }\n\n // Ensure pipeline state reflects completion of this phase\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.jsonCompleted = true;\n await saveTaskPlan(tasksPath, plan);\n\n printSuccess(`Task plan saved to ${tasksPath} (${plan.userStories.length} stories)`);\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,OAAO,gBAAgB;AAahC,eAAsB,QAAQ,OAAe,eAAgD;AAC3F,QAAM,cAAc,MAAM,QAAQ,MAAM,EAAE;AAC1C,QAAM,QAAQ,MAAM,kBAAkB,WAAW;AAEjD,QAAM,aAAa,MAAM,oBAAoB,aAAa,aAAa;AACvE,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,WAAW;AAAA,EACpB;AAGA,QAAM,UAAU,MAAM;AACtB,MAAI;AACJ,MAAI;AACF,iBAAa,MAAM,SAAS,SAAS,OAAO;AAAA,EAC9C,QAAQ;AACN,eAAW,oBAAoB,OAAO,yBAAyB,WAAW,UAAU;AACpF,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM;AAExB,QAAM,WAAW,MAAM,WAAW,MAAM;AACxC,QAAM,SAAS,kBAAkB,UAAU;AAAA,IACzC,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,GAAG,kBAAkB,WAAW,QAAQ;AAAA,EAC1C,CAAC;AAED,QAAM,MAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAE/C,QAAM,UAAU,MAAM,kBAAkB;AAAA,IACtC,OAAO;AAAA,IACP,SAAS,YAAY;AACnB,YAAM,SAAS,MAAM,YAAY;AAAA,QAC/B;AAAA,QACA,UAAU;AAAA,QACV,SAAS,iBAAiB,KAAK;AAAA,QAC/B,cAAc;AAAA,QACd,cAAc,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,OAAO;AAAA,QACtD,SAAS,CAAC,MAAM,QAAQ;AAAA,QACxB,eAAe,0CAA0C,WAAW;AAAA,MACtE,CAAC;AAED,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,WAAW,mBAAmB,GAAG,OAAO,SAAS,EAAE;AAAA,UACnD,OAAO,gCAAgC,OAAO,KAAK;AAAA,QACrD;AAAA,MACF;AAGA,UAAI;AACJ,UAAI;AACF,qBAAa,MAAM,kBAAkB,SAAS;AAAA,MAChD,QAAQ;AACN,eAAO,EAAE,IAAI,OAAO,WAAW,MAAM,OAAO,iCAAiC,SAAS,GAAG;AAAA,MAC3F;AAIA,UAAI;AACJ,UAAI;AACF,iBAAS,KAAK,MAAM,UAAU;AAAA,MAChC,QAAQ;AACN,eAAO,EAAE,IAAI,OAAO,WAAW,MAAM,OAAO,mCAAmC;AAAA,MACjF;AAGA,YAAM,aAAa,eAAe,UAAU,MAAM;AAClD,UAAI,CAAC,WAAW,SAAS;AACvB,cAAM,SAAS,WAAW,MAAM,OAC7B,IAAI,CAAC,MAAM,OAAO,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAClD,KAAK,IAAI;AACZ,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,WAAW;AAAA,UACX,OAAO;AAAA,EAA+C,MAAM;AAAA,QAC9D;AAAA,MACF;AAEA,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,QAAQ,IAAI;AACf,eAAW,QAAQ,SAAS,0CAA0C,WAAW,EAAE;AACnF,WAAO;AAAA,EACT;AAGA,QAAM,OAAO,MAAM,aAAa,SAAS;AACzC,OAAK,SAAS,gBAAgB;AAC9B,QAAM,aAAa,WAAW,IAAI;AAElC,eAAa,sBAAsB,SAAS,KAAK,KAAK,YAAY,MAAM,WAAW;AACnF,SAAO;AACT;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
setIssuesCliOverrides,
|
|
4
4
|
setWebCliOverrides
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-G3TJHMAS.js";
|
|
6
6
|
import {
|
|
7
7
|
printError,
|
|
8
8
|
setGlobalTimeout,
|
|
@@ -159,7 +159,7 @@ withIssueOptions(
|
|
|
159
159
|
program.command("init").description("Verify that all prerequisites (claude, gh, git) are met")
|
|
160
160
|
)
|
|
161
161
|
).action(async () => {
|
|
162
|
-
const { loadIssuesConfig } = await import("./config-
|
|
162
|
+
const { loadIssuesConfig } = await import("./config-2NDV7Y72.js");
|
|
163
163
|
const { runInit } = await import("./init-5KXCG36P.js");
|
|
164
164
|
const { preferredProvider } = await loadIssuesConfig();
|
|
165
165
|
const code = await runInit(preferredProvider);
|
|
@@ -178,7 +178,7 @@ withGlobalOptions(
|
|
|
178
178
|
}
|
|
179
179
|
throw error;
|
|
180
180
|
}
|
|
181
|
-
const { runGenerate } = await import("./generate-
|
|
181
|
+
const { runGenerate } = await import("./generate-YEQRH36H.js");
|
|
182
182
|
const code = await runGenerate(options.prompt, target);
|
|
183
183
|
process.exit(code);
|
|
184
184
|
});
|
|
@@ -202,7 +202,7 @@ withWebOptions(
|
|
|
202
202
|
}
|
|
203
203
|
throw error;
|
|
204
204
|
}
|
|
205
|
-
const { runPipeline } = await import("./run-
|
|
205
|
+
const { runPipeline } = await import("./run-EFXDXSB4.js");
|
|
206
206
|
const code = await runPipeline(
|
|
207
207
|
issue,
|
|
208
208
|
options.mode,
|
|
@@ -218,7 +218,7 @@ withIssueOptions(
|
|
|
218
218
|
program.command("analyze").description("Analyze an issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
219
219
|
)
|
|
220
220
|
).action(async (issue) => {
|
|
221
|
-
const { runAnalyze } = await import("./analyze-
|
|
221
|
+
const { runAnalyze } = await import("./analyze-XMEULTT2.js");
|
|
222
222
|
const code = await runAnalyze(issue);
|
|
223
223
|
process.exit(code);
|
|
224
224
|
});
|
|
@@ -227,7 +227,7 @@ withIssueOptions(
|
|
|
227
227
|
program.command("prd").description("Generate a PRD from an analyzed issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
228
228
|
)
|
|
229
229
|
).action(async (issue) => {
|
|
230
|
-
const { runPrd } = await import("./prd-
|
|
230
|
+
const { runPrd } = await import("./prd-3QME4DYX.js");
|
|
231
231
|
const code = await runPrd(issue);
|
|
232
232
|
process.exit(code);
|
|
233
233
|
});
|
|
@@ -236,7 +236,7 @@ withIssueOptions(
|
|
|
236
236
|
program.command("plan").description("Convert a PRD to a tasks.json task plan via Claude Code Headless").argument("<issue>", "Issue number")
|
|
237
237
|
)
|
|
238
238
|
).action(async (issue) => {
|
|
239
|
-
const { runPlan } = await import("./plan-
|
|
239
|
+
const { runPlan } = await import("./plan-4I47CQM5.js");
|
|
240
240
|
const code = await runPlan(issue);
|
|
241
241
|
process.exit(code);
|
|
242
242
|
});
|
|
@@ -255,7 +255,7 @@ withWebOptions(
|
|
|
255
255
|
).action(
|
|
256
256
|
async (positionalMaxIter, options) => {
|
|
257
257
|
try {
|
|
258
|
-
const { runExecute } = await import("./execute-
|
|
258
|
+
const { runExecute } = await import("./execute-BOQPTRH4.js");
|
|
259
259
|
const code = await runExecute(positionalMaxIter, options);
|
|
260
260
|
process.exit(code);
|
|
261
261
|
} catch (error) {
|
|
@@ -269,7 +269,7 @@ withIssueOptions(
|
|
|
269
269
|
program.command("review").description("Validate an issue resolution via Claude Code Headless").argument("<issue>", "Issue number")
|
|
270
270
|
)
|
|
271
271
|
).action(async (issue) => {
|
|
272
|
-
const { runReview } = await import("./review-
|
|
272
|
+
const { runReview } = await import("./review-RG2UIPOB.js");
|
|
273
273
|
const code = await runReview(issue);
|
|
274
274
|
process.exit(code);
|
|
275
275
|
});
|
|
@@ -278,7 +278,7 @@ withIssueOptions(
|
|
|
278
278
|
program.command("pr").description("Create a pull request via Claude Code Headless").argument("<issue>", "Issue number")
|
|
279
279
|
)
|
|
280
280
|
).action(async (issue) => {
|
|
281
|
-
const { runPr } = await import("./pr-
|
|
281
|
+
const { runPr } = await import("./pr-F672VPMM.js");
|
|
282
282
|
const code = await runPr(issue);
|
|
283
283
|
process.exit(code);
|
|
284
284
|
});
|
|
@@ -289,7 +289,7 @@ withGlobalOptions(
|
|
|
289
289
|
)
|
|
290
290
|
).action(
|
|
291
291
|
async (pr, options) => {
|
|
292
|
-
const { runPrReview } = await import("./pr-review-
|
|
292
|
+
const { runPrReview } = await import("./pr-review-GKP4TJRJ.js");
|
|
293
293
|
const code = await runPrReview(pr, options);
|
|
294
294
|
process.exit(code);
|
|
295
295
|
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
setIssuesCliOverrides,
|
|
16
16
|
setWebCliOverrides,
|
|
17
17
|
validateDependencies
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-G3TJHMAS.js";
|
|
19
19
|
import "./chunk-JNEHVQH5.js";
|
|
20
20
|
export {
|
|
21
21
|
DEFAULTS,
|
|
@@ -34,4 +34,4 @@ export {
|
|
|
34
34
|
setWebCliOverrides,
|
|
35
35
|
validateDependencies
|
|
36
36
|
};
|
|
37
|
-
//# sourceMappingURL=config-
|
|
37
|
+
//# sourceMappingURL=config-2NDV7Y72.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runExecute
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WQ4SUZ4P.js";
|
|
5
5
|
import "./chunk-HDV3YDTG.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-PRVWJZV4.js";
|
|
7
7
|
import "./chunk-SLHZPB3C.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-G3TJHMAS.js";
|
|
9
9
|
import "./chunk-JNEHVQH5.js";
|
|
10
10
|
export {
|
|
11
11
|
runExecute
|
|
12
12
|
};
|
|
13
|
-
//# sourceMappingURL=execute-
|
|
13
|
+
//# sourceMappingURL=execute-BOQPTRH4.js.map
|
|
@@ -3,17 +3,18 @@ import {
|
|
|
3
3
|
ensureProvidersRegistered,
|
|
4
4
|
getProvider,
|
|
5
5
|
localIssueRef
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DKMBLNGO.js";
|
|
7
7
|
import {
|
|
8
8
|
runHeadless
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-GOZT2YP5.js";
|
|
10
10
|
import {
|
|
11
11
|
applyPlaceholders,
|
|
12
12
|
loadPrompt
|
|
13
13
|
} from "./chunk-SLHZPB3C.js";
|
|
14
14
|
import {
|
|
15
|
-
loadIssuesConfig
|
|
16
|
-
|
|
15
|
+
loadIssuesConfig,
|
|
16
|
+
resolveProjectPaths
|
|
17
|
+
} from "./chunk-G3TJHMAS.js";
|
|
17
18
|
import {
|
|
18
19
|
getGlobalTimeout,
|
|
19
20
|
isoNow,
|
|
@@ -66,9 +67,11 @@ function issueLocation(issue) {
|
|
|
66
67
|
return issue.remoteRef ?? localIssueRef(issue.id);
|
|
67
68
|
}
|
|
68
69
|
async function draftIssue(promptText) {
|
|
70
|
+
const { issuesDir } = await resolveProjectPaths();
|
|
69
71
|
const template = await loadPrompt("generate");
|
|
70
72
|
const prompt = applyPlaceholders(template, {
|
|
71
|
-
__USER_PROMPT__: promptText
|
|
73
|
+
__USER_PROMPT__: promptText,
|
|
74
|
+
__LOCAL_ISSUES_DIR__: issuesDir
|
|
72
75
|
});
|
|
73
76
|
const result = await runHeadless({
|
|
74
77
|
prompt,
|
|
@@ -76,6 +79,7 @@ async function draftIssue(promptText) {
|
|
|
76
79
|
timeout: getGlobalTimeout() ?? 3e5,
|
|
77
80
|
outputFormat: "text",
|
|
78
81
|
allowedTools: ["Bash", "Read", "Glob", "Grep"],
|
|
82
|
+
addDirs: [issuesDir],
|
|
79
83
|
statusMessage: "Drafting issue..."
|
|
80
84
|
});
|
|
81
85
|
if (!result.success) {
|
|
@@ -142,4 +146,4 @@ async function runGenerate(promptText, target) {
|
|
|
142
146
|
export {
|
|
143
147
|
runGenerate
|
|
144
148
|
};
|
|
145
|
-
//# sourceMappingURL=generate-
|
|
149
|
+
//# sourceMappingURL=generate-YEQRH36H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/issues/draft.ts","../src/commands/generate.ts"],"sourcesContent":["import type { IssueDraft } from './types.js';\n\n/**\n * Structured Issue draft emitted by the `generate` prompt.\n *\n * The agent no longer creates the Issue itself: it returns the content and the\n * providers persist it, so the same draft can reach GitHub, the local files, or\n * both. Capturing the result therefore has to be exact — the old approach of\n * fishing an issue URL out of free-form prose only ever worked for GitHub.\n *\n * The block mirrors the `<issue-body>` convention already used by the phase\n * templates, which keeps a multi-line markdown body readable and free of the\n * escaping a JSON payload would demand.\n */\n\n/** Wrapper the agent must emit around the draft. */\nexport const DRAFT_TAG = 'issue-draft';\n\n/** Failure to capture a draft from the agent output. */\nexport class IssueDraftParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'IssueDraftParseError';\n }\n}\n\n/**\n * Last occurrence of `<tag>...</tag>` in `source`, or `null`.\n *\n * The last one wins: an agent that shows the format before filling it in (or\n * restates the draft after a correction) would otherwise have its first,\n * throwaway attempt captured. The closing tag is searched from the end for the\n * same reason a body may legitimately quote one.\n */\nfunction extractTag(source: string, tag: string): string | null {\n const open = `<${tag}>`;\n const close = `</${tag}>`;\n\n const start = source.lastIndexOf(open);\n if (start === -1) return null;\n\n const end = source.lastIndexOf(close);\n if (end === -1 || end < start) return null;\n\n return source.slice(start + open.length, end);\n}\n\nfunction parseLabels(raw: string | null): string[] {\n if (raw === null) return [];\n return raw\n .split(',')\n .map((label) => label.trim())\n .filter((label) => label.length > 0 && label.toLowerCase() !== '(none)');\n}\n\n/**\n * Read the draft the agent produced.\n *\n * @throws IssueDraftParseError when the block is absent or has no usable\n * title/body, so a malformed answer fails loudly instead of creating an empty\n * Issue.\n */\nexport function parseIssueDraft(output: string): IssueDraft {\n const normalized = output.replace(/\\r\\n?/g, '\\n');\n const block = extractTag(normalized, DRAFT_TAG);\n\n if (block === null) {\n throw new IssueDraftParseError(\n `The agent did not emit an <${DRAFT_TAG}> block, so there is no Issue to create. ` +\n `Output was: ${normalized.trim().slice(0, 300) || '(empty)'}`,\n );\n }\n\n const title = (extractTag(block, 'title') ?? '').trim();\n const body = (extractTag(block, 'body') ?? '').trim();\n\n if (title.length === 0) {\n throw new IssueDraftParseError(`The <${DRAFT_TAG}> block has no <title>.`);\n }\n if (body.length === 0) {\n throw new IssueDraftParseError(`The <${DRAFT_TAG}> block has no <body>.`);\n }\n\n return { title, body, labels: parseLabels(extractTag(block, 'labels')) };\n}\n","import { loadIssuesConfig } from '../config.js';\nimport { runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { isoNow } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { ensureProvidersRegistered } from '../issues/bootstrap.js';\nimport { localIssueRef } from '../issues/context.js';\nimport { IssueDraftParseError, parseIssueDraft } from '../issues/draft.js';\nimport { getProvider } from '../issues/registry.js';\nimport type { Issue, IssueDraft, IssueGenerateTarget } from '../issues/types.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport { printError, printSuccess } from '../ui/logger.js';\n\n/** Human-readable pointer to a created Issue. */\nfunction issueLocation(issue: Issue): string {\n return issue.remoteRef ?? localIssueRef(issue.id);\n}\n\n/**\n * Ask the agent for the Issue content.\n *\n * The agent only drafts: creation belongs to the providers, so the same draft\n * can be persisted to GitHub, to the local files, or to both.\n */\nasync function draftIssue(promptText: string): Promise<IssueDraft> {\n // The duplicate check reads the local issues, which live in the global\n // storage: the path has to be handed over (and allowed) explicitly, since it\n // is outside the working directory the agent is started in.\n const { issuesDir } = await resolveProjectPaths();\n\n const template = await loadPrompt('generate');\n const prompt = applyPlaceholders(template, {\n __USER_PROMPT__: promptText,\n __LOCAL_ISSUES_DIR__: issuesDir,\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 addDirs: [issuesDir],\n statusMessage: 'Drafting issue...',\n });\n\n if (!result.success) {\n throw new Error(`Issue creation failed: ${result.error}`);\n }\n\n return parseIssueDraft(result.result);\n}\n\n/**\n * Create the GitHub Issue and mirror it locally.\n *\n * The remote comes first on purpose: it owns the identifier, and the mirror has\n * to reuse it so both copies describe one demand. A remote failure therefore\n * leaves nothing behind, and a mirror failure is reported with the remote\n * reference that already exists.\n */\nasync function createBoth(draft: IssueDraft): Promise<Issue[]> {\n const remote = await getProvider('github').create(draft);\n\n try {\n const mirror = await getProvider('local').create({\n ...draft,\n id: remote.id,\n ...(remote.remoteRef\n ? {\n remote: {\n provider: 'github' as const,\n ref: remote.remoteRef,\n syncedAt: isoNow(),\n syncedContentHash: remote.contentHash,\n },\n }\n : {}),\n });\n return [remote, mirror];\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(\n `GitHub issue created at ${issueLocation(remote)}, but the local mirror was not written: ` +\n `${message}. Nothing else was persisted; re-run with --local to create the mirror.`,\n );\n }\n}\n\nasync function createIssues(target: IssueGenerateTarget, draft: IssueDraft): Promise<Issue[]> {\n if (target === 'both') {\n return createBoth(draft);\n }\n return [await getProvider(target).create(draft)];\n}\n\nexport async function runGenerate(\n promptText: string,\n target?: IssueGenerateTarget,\n): Promise<number> {\n const config = await loadIssuesConfig();\n const destination = target ?? config.defaultGenerateTarget;\n\n ensureProvidersRegistered();\n\n let draft: IssueDraft;\n try {\n draft = await draftIssue(promptText);\n } catch (err) {\n if (err instanceof IssueDraftParseError) {\n printError(`Could not read the generated Issue draft: ${err.message}`);\n } else {\n printError(err instanceof Error ? err.message : String(err));\n }\n return 1;\n }\n\n let created: Issue[];\n try {\n created = await createIssues(destination, draft);\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n return 1;\n }\n\n for (const issue of created) {\n printSuccess(`Issue created (${issue.source}): ${issueLocation(issue)}`);\n }\n return 0;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runPlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WUITOU5B.js";
|
|
5
5
|
import "./chunk-EHVKXFFN.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-DKMBLNGO.js";
|
|
7
7
|
import "./chunk-HDV3YDTG.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-GOZT2YP5.js";
|
|
9
9
|
import "./chunk-SLHZPB3C.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-G3TJHMAS.js";
|
|
11
11
|
import "./chunk-JNEHVQH5.js";
|
|
12
12
|
export {
|
|
13
13
|
runPlan
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=plan-
|
|
15
|
+
//# sourceMappingURL=plan-4I47CQM5.js.map
|