issue-flow 0.5.2 → 0.6.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-QVQ4CTCU.js → analyze-VVG7UABS.js} +15 -5
- package/dist/analyze-VVG7UABS.js.map +1 -0
- package/dist/{chunk-3ULIAC2J.js → chunk-2CSHLHYP.js} +2 -2
- package/dist/{chunk-PA3GI7LR.js → chunk-4HT4EVYV.js} +78 -32
- package/dist/chunk-4HT4EVYV.js.map +1 -0
- package/dist/{chunk-DLWRUTRL.js → chunk-7W5VGYXW.js} +11 -11
- package/dist/{chunk-JMSRJ43G.js → chunk-EHX4J5G5.js} +15 -8
- package/dist/chunk-EHX4J5G5.js.map +1 -0
- package/dist/{chunk-KMX3DUJN.js → chunk-FPGHTTVV.js} +15 -8
- package/dist/chunk-FPGHTTVV.js.map +1 -0
- package/dist/{chunk-OEJSMZMO.js → chunk-JTSAL3TI.js} +12 -5
- package/dist/chunk-JTSAL3TI.js.map +1 -0
- package/dist/{chunk-LJI45O5B.js → chunk-KWGRBNUG.js} +22 -8
- package/dist/chunk-KWGRBNUG.js.map +1 -0
- package/dist/chunk-SVOWWZQJ.js +982 -0
- package/dist/chunk-SVOWWZQJ.js.map +1 -0
- package/dist/{chunk-O5XI2CFF.js → chunk-WZDCTAWZ.js} +55 -20
- package/dist/chunk-WZDCTAWZ.js.map +1 -0
- package/dist/{chunk-VM7C7L3A.js → chunk-YM3G5BLR.js} +21 -9
- package/dist/chunk-YM3G5BLR.js.map +1 -0
- package/dist/cli.js +130 -29
- package/dist/cli.js.map +1 -1
- package/dist/config-B564P45C.js +29 -0
- package/dist/execute-PNOFNLZG.js +12 -0
- package/dist/generate-IN62ARBS.js +143 -0
- package/dist/generate-IN62ARBS.js.map +1 -0
- package/dist/init-5242XSYC.js +9 -0
- package/dist/plan-6KLONWPR.js +14 -0
- package/dist/pr-JLJLMFN3.js +14 -0
- package/dist/prd-TVJDYZXH.js +14 -0
- package/dist/review-FRV4ZMS2.js +12 -0
- package/dist/review-FRV4ZMS2.js.map +1 -0
- package/dist/{run-3GJC54DB.js → run-GPBICAD6.js} +45 -26
- package/dist/run-GPBICAD6.js.map +1 -0
- package/package.json +2 -1
- package/prompts/analyze.md +18 -5
- package/prompts/generate.md +27 -6
- package/prompts/plan.md +19 -2
- package/prompts/pr.md +23 -6
- package/prompts/prd.md +18 -5
- package/prompts/review.md +18 -6
- package/dist/analyze-QVQ4CTCU.js.map +0 -1
- package/dist/chunk-JMSRJ43G.js.map +0 -1
- package/dist/chunk-KLBAHTXX.js +0 -283
- package/dist/chunk-KLBAHTXX.js.map +0 -1
- package/dist/chunk-KMX3DUJN.js.map +0 -1
- package/dist/chunk-LJI45O5B.js.map +0 -1
- package/dist/chunk-O5XI2CFF.js.map +0 -1
- package/dist/chunk-OEJSMZMO.js.map +0 -1
- package/dist/chunk-PA3GI7LR.js.map +0 -1
- package/dist/chunk-VM7C7L3A.js.map +0 -1
- package/dist/execute-TEJ26L4O.js +0 -12
- package/dist/generate-KBQ4KW4T.js +0 -48
- package/dist/generate-KBQ4KW4T.js.map +0 -1
- package/dist/init-4VMPBRMA.js +0 -9
- package/dist/plan-PWYZP5AN.js +0 -13
- package/dist/pr-CJQWZUDR.js +0 -13
- package/dist/prd-4KLQY7BC.js +0 -13
- package/dist/review-YFCWBBKY.js +0 -11
- package/dist/run-3GJC54DB.js.map +0 -1
- /package/dist/{chunk-3ULIAC2J.js.map → chunk-2CSHLHYP.js.map} +0 -0
- /package/dist/{chunk-DLWRUTRL.js.map → chunk-7W5VGYXW.js.map} +0 -0
- /package/dist/{execute-TEJ26L4O.js.map → config-B564P45C.js.map} +0 -0
- /package/dist/{init-4VMPBRMA.js.map → execute-PNOFNLZG.js.map} +0 -0
- /package/dist/{plan-PWYZP5AN.js.map → init-5242XSYC.js.map} +0 -0
- /package/dist/{pr-CJQWZUDR.js.map → plan-6KLONWPR.js.map} +0 -0
- /package/dist/{prd-4KLQY7BC.js.map → pr-JLJLMFN3.js.map} +0 -0
- /package/dist/{review-YFCWBBKY.js.map → prd-TVJDYZXH.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,76 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
setIssuesCliOverrides,
|
|
3
4
|
setWebCliOverrides
|
|
4
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4HT4EVYV.js";
|
|
5
6
|
import {
|
|
6
7
|
printError,
|
|
7
8
|
setGlobalTimeout,
|
|
8
9
|
setVerbose
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WZDCTAWZ.js";
|
|
10
11
|
|
|
11
12
|
// src/cli.ts
|
|
12
13
|
import { createRequire } from "module";
|
|
13
14
|
import { Command, InvalidArgumentError } from "commander";
|
|
15
|
+
|
|
16
|
+
// src/cli-options.ts
|
|
17
|
+
function resolveNoBranch(options) {
|
|
18
|
+
return options.branch === false ? true : void 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/issues/cli-flags.ts
|
|
22
|
+
var IssueFlagError = class extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "IssueFlagError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function resolveIssuesOverrides(opts) {
|
|
29
|
+
const overrides = {};
|
|
30
|
+
if (opts.local === true && opts.github === true) {
|
|
31
|
+
throw new IssueFlagError("--local and --github are mutually exclusive; pass only one.");
|
|
32
|
+
}
|
|
33
|
+
if (opts.local === true) {
|
|
34
|
+
overrides.preferredProvider = "local";
|
|
35
|
+
}
|
|
36
|
+
if (opts.github === true) {
|
|
37
|
+
overrides.preferredProvider = "github";
|
|
38
|
+
}
|
|
39
|
+
const conflictFlags = [
|
|
40
|
+
opts.preferLocal === true ? "--prefer-local" : null,
|
|
41
|
+
opts.preferGithub === true ? "--prefer-github" : null,
|
|
42
|
+
opts.ask === true ? "--ask" : null
|
|
43
|
+
].filter((flag) => flag !== null);
|
|
44
|
+
if (conflictFlags.length > 1) {
|
|
45
|
+
throw new IssueFlagError(
|
|
46
|
+
`${conflictFlags.join(", ")} are mutually exclusive; pass only one conflict policy.`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
if (opts.preferLocal === true) {
|
|
50
|
+
overrides.conflictPolicy = "prefer-local";
|
|
51
|
+
}
|
|
52
|
+
if (opts.preferGithub === true) {
|
|
53
|
+
overrides.conflictPolicy = "prefer-github";
|
|
54
|
+
}
|
|
55
|
+
if (opts.ask === true) {
|
|
56
|
+
overrides.conflictPolicy = "ask";
|
|
57
|
+
}
|
|
58
|
+
return overrides;
|
|
59
|
+
}
|
|
60
|
+
function resolveGenerateTarget(opts) {
|
|
61
|
+
const selected = [];
|
|
62
|
+
if (opts.github === true) selected.push("github");
|
|
63
|
+
if (opts.local === true) selected.push("local");
|
|
64
|
+
if (opts.both === true) selected.push("both");
|
|
65
|
+
if (selected.length > 1) {
|
|
66
|
+
throw new IssueFlagError(
|
|
67
|
+
`${selected.map((target) => `--${target}`).join(", ")} are mutually exclusive; pass only one destination.`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
return selected[0];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/cli.ts
|
|
14
74
|
var require2 = createRequire(import.meta.url);
|
|
15
75
|
var { version } = require2("../package.json");
|
|
16
76
|
function parseInteger(value) {
|
|
@@ -30,6 +90,9 @@ function withGlobalOptions(cmd) {
|
|
|
30
90
|
function withWebOptions(cmd) {
|
|
31
91
|
return cmd.option("--web", "Enable the web monitoring server").option("--serve", "Alias for --web").option("--port <n>", "Web server port (default: 3737)", parseInteger).option("--host <h>", "Web server host (default: 0.0.0.0)").option("--refresh <s>", "Suggested UI polling interval in seconds", parseInteger).option("--web-log-limit <n>", "Max log entries kept in the snapshot", parseInteger).option("--web-no-logs", "Exclude logs from the published snapshot");
|
|
32
92
|
}
|
|
93
|
+
function withIssueOptions(cmd) {
|
|
94
|
+
return cmd.option("--local", "Prefer the local file Issue provider").option("--github", "Prefer the GitHub Issue provider").option("--prefer-local", "On divergence, use the local version without asking").option("--prefer-github", "On divergence, use the GitHub version without asking").option("--ask", "On divergence, ask which version to use (interactive only)");
|
|
95
|
+
}
|
|
33
96
|
function resolveWebOverrides(opts) {
|
|
34
97
|
const overrides = {};
|
|
35
98
|
if (opts.web === true || opts.serve === true) {
|
|
@@ -65,48 +128,82 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
|
65
128
|
setGlobalTimeout(opts.timeout * 1e3);
|
|
66
129
|
}
|
|
67
130
|
setWebCliOverrides(resolveWebOverrides(opts));
|
|
131
|
+
try {
|
|
132
|
+
setIssuesCliOverrides(resolveIssuesOverrides(opts));
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error instanceof IssueFlagError) {
|
|
135
|
+
printError(error.message);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
68
140
|
});
|
|
69
|
-
|
|
70
|
-
|
|
141
|
+
withIssueOptions(
|
|
142
|
+
withGlobalOptions(
|
|
143
|
+
program.command("init").description("Verify that all prerequisites (claude, gh, git) are met")
|
|
144
|
+
)
|
|
71
145
|
).action(async () => {
|
|
72
|
-
const {
|
|
73
|
-
const
|
|
146
|
+
const { loadIssuesConfig } = await import("./config-B564P45C.js");
|
|
147
|
+
const { runInit } = await import("./init-5242XSYC.js");
|
|
148
|
+
const { preferredProvider } = await loadIssuesConfig();
|
|
149
|
+
const code = await runInit(preferredProvider);
|
|
74
150
|
process.exit(code);
|
|
75
151
|
});
|
|
76
152
|
withGlobalOptions(
|
|
77
|
-
program.command("generate").description("
|
|
153
|
+
program.command("generate").description("Draft an issue via Claude Code Headless and create it").requiredOption("--prompt <text>", "Issue description text").option("--github", "Create the issue on GitHub").option("--local", "Create the issue under issues/<n>/ only").option("--both", "Create the issue on GitHub and mirror it locally")
|
|
78
154
|
).action(async (options) => {
|
|
79
|
-
|
|
80
|
-
|
|
155
|
+
let target;
|
|
156
|
+
try {
|
|
157
|
+
target = resolveGenerateTarget(options);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (error instanceof IssueFlagError) {
|
|
160
|
+
printError(error.message);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
const { runGenerate } = await import("./generate-IN62ARBS.js");
|
|
166
|
+
const code = await runGenerate(options.prompt, target);
|
|
81
167
|
process.exit(code);
|
|
82
168
|
});
|
|
83
169
|
withWebOptions(
|
|
84
|
-
|
|
85
|
-
|
|
170
|
+
withIssueOptions(
|
|
171
|
+
withGlobalOptions(
|
|
172
|
+
program.command("run").description("Execute the full pipeline: prd \u2192 plan \u2192 execute \u2192 review \u2192 pr").argument("<issue>", "Issue number").option("--mode <mode>", "Execution mode: auto | manual", "auto").option("--from <phase>", "Resume from a specific phase").option(
|
|
173
|
+
"--no-branch",
|
|
174
|
+
"Run pipeline on current branch without creating a new branch or PR"
|
|
175
|
+
)
|
|
176
|
+
)
|
|
86
177
|
)
|
|
87
178
|
).action(async (issue, options) => {
|
|
88
|
-
const { runPipeline } = await import("./run-
|
|
89
|
-
const code = await runPipeline(issue, options.mode, options.from, options
|
|
179
|
+
const { runPipeline } = await import("./run-GPBICAD6.js");
|
|
180
|
+
const code = await runPipeline(issue, options.mode, options.from, resolveNoBranch(options));
|
|
90
181
|
process.exit(code);
|
|
91
182
|
});
|
|
92
|
-
|
|
93
|
-
|
|
183
|
+
withIssueOptions(
|
|
184
|
+
withGlobalOptions(
|
|
185
|
+
program.command("analyze").description("Analyze an issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
186
|
+
)
|
|
94
187
|
).action(async (issue) => {
|
|
95
|
-
const { runAnalyze } = await import("./analyze-
|
|
188
|
+
const { runAnalyze } = await import("./analyze-VVG7UABS.js");
|
|
96
189
|
const code = await runAnalyze(issue);
|
|
97
190
|
process.exit(code);
|
|
98
191
|
});
|
|
99
|
-
|
|
100
|
-
|
|
192
|
+
withIssueOptions(
|
|
193
|
+
withGlobalOptions(
|
|
194
|
+
program.command("prd").description("Generate a PRD from an analyzed issue via Claude Code Headless").argument("<issue>", "Issue number")
|
|
195
|
+
)
|
|
101
196
|
).action(async (issue) => {
|
|
102
|
-
const { runPrd } = await import("./prd-
|
|
197
|
+
const { runPrd } = await import("./prd-TVJDYZXH.js");
|
|
103
198
|
const code = await runPrd(issue);
|
|
104
199
|
process.exit(code);
|
|
105
200
|
});
|
|
106
|
-
|
|
107
|
-
|
|
201
|
+
withIssueOptions(
|
|
202
|
+
withGlobalOptions(
|
|
203
|
+
program.command("plan").description("Convert a PRD to a tasks.json task plan via Claude Code Headless").argument("<issue>", "Issue number")
|
|
204
|
+
)
|
|
108
205
|
).action(async (issue) => {
|
|
109
|
-
const { runPlan } = await import("./plan-
|
|
206
|
+
const { runPlan } = await import("./plan-6KLONWPR.js");
|
|
110
207
|
const code = await runPlan(issue);
|
|
111
208
|
process.exit(code);
|
|
112
209
|
});
|
|
@@ -125,7 +222,7 @@ withWebOptions(
|
|
|
125
222
|
).action(
|
|
126
223
|
async (positionalMaxIter, options) => {
|
|
127
224
|
try {
|
|
128
|
-
const { runExecute } = await import("./execute-
|
|
225
|
+
const { runExecute } = await import("./execute-PNOFNLZG.js");
|
|
129
226
|
const code = await runExecute(positionalMaxIter, options);
|
|
130
227
|
process.exit(code);
|
|
131
228
|
} catch (error) {
|
|
@@ -134,17 +231,21 @@ withWebOptions(
|
|
|
134
231
|
}
|
|
135
232
|
}
|
|
136
233
|
);
|
|
137
|
-
|
|
138
|
-
|
|
234
|
+
withIssueOptions(
|
|
235
|
+
withGlobalOptions(
|
|
236
|
+
program.command("review").description("Validate an issue resolution via Claude Code Headless").argument("<issue>", "Issue number")
|
|
237
|
+
)
|
|
139
238
|
).action(async (issue) => {
|
|
140
|
-
const { runReview } = await import("./review-
|
|
239
|
+
const { runReview } = await import("./review-FRV4ZMS2.js");
|
|
141
240
|
const code = await runReview(issue);
|
|
142
241
|
process.exit(code);
|
|
143
242
|
});
|
|
144
|
-
|
|
145
|
-
|
|
243
|
+
withIssueOptions(
|
|
244
|
+
withGlobalOptions(
|
|
245
|
+
program.command("pr").description("Create a pull request via Claude Code Headless").argument("<issue>", "Issue number")
|
|
246
|
+
)
|
|
146
247
|
).action(async (issue) => {
|
|
147
|
-
const { runPr } = await import("./pr-
|
|
248
|
+
const { runPr } = await import("./pr-JLJLMFN3.js");
|
|
148
249
|
const code = await runPr(issue);
|
|
149
250
|
process.exit(code);
|
|
150
251
|
});
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { Command, InvalidArgumentError } from 'commander';\nimport { setWebCliOverrides } from './config.js';\nimport { setGlobalTimeout, setVerbose } from './core/verbose.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 * 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});\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 ─────────────────────────────────────────────────────────────────────\nwithWebOptions(\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('--no-branch', 'Run pipeline on current branch without creating a new branch or PR'),\n ),\n).action(async (issue: string, options: { mode: string; from?: string; noBranch?: boolean }) => {\n const { runPipeline } = await import('./commands/run.js');\n const code = await runPipeline(issue, options.mode, options.from, options.noBranch);\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 ─────────────────────────────────────────────────────────────────\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 ──────────────────────────────────────────────────────────────────\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":["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 { 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"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULTS,
|
|
4
|
+
PROJECT_CONFIG_FILENAME,
|
|
5
|
+
WEB_CONFIG_FILENAME,
|
|
6
|
+
createConfig,
|
|
7
|
+
getInstallHint,
|
|
8
|
+
loadIssuesConfig,
|
|
9
|
+
loadWebConfig,
|
|
10
|
+
resolvePaths,
|
|
11
|
+
setIssuesCliOverrides,
|
|
12
|
+
setWebCliOverrides,
|
|
13
|
+
validateDependencies
|
|
14
|
+
} from "./chunk-4HT4EVYV.js";
|
|
15
|
+
import "./chunk-WZDCTAWZ.js";
|
|
16
|
+
export {
|
|
17
|
+
DEFAULTS,
|
|
18
|
+
PROJECT_CONFIG_FILENAME,
|
|
19
|
+
WEB_CONFIG_FILENAME,
|
|
20
|
+
createConfig,
|
|
21
|
+
getInstallHint,
|
|
22
|
+
loadIssuesConfig,
|
|
23
|
+
loadWebConfig,
|
|
24
|
+
resolvePaths,
|
|
25
|
+
setIssuesCliOverrides,
|
|
26
|
+
setWebCliOverrides,
|
|
27
|
+
validateDependencies
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=config-B564P45C.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runExecute
|
|
4
|
+
} from "./chunk-7W5VGYXW.js";
|
|
5
|
+
import "./chunk-HDV3YDTG.js";
|
|
6
|
+
import "./chunk-SLHZPB3C.js";
|
|
7
|
+
import "./chunk-4HT4EVYV.js";
|
|
8
|
+
import "./chunk-WZDCTAWZ.js";
|
|
9
|
+
export {
|
|
10
|
+
runExecute
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=execute-PNOFNLZG.js.map
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ensureProvidersRegistered,
|
|
4
|
+
getProvider,
|
|
5
|
+
localIssueRef,
|
|
6
|
+
runHeadless
|
|
7
|
+
} from "./chunk-SVOWWZQJ.js";
|
|
8
|
+
import {
|
|
9
|
+
applyPlaceholders,
|
|
10
|
+
loadPrompt
|
|
11
|
+
} from "./chunk-SLHZPB3C.js";
|
|
12
|
+
import {
|
|
13
|
+
loadIssuesConfig
|
|
14
|
+
} from "./chunk-4HT4EVYV.js";
|
|
15
|
+
import {
|
|
16
|
+
getGlobalTimeout,
|
|
17
|
+
isoNow,
|
|
18
|
+
printError,
|
|
19
|
+
printSuccess
|
|
20
|
+
} from "./chunk-WZDCTAWZ.js";
|
|
21
|
+
|
|
22
|
+
// src/issues/draft.ts
|
|
23
|
+
var DRAFT_TAG = "issue-draft";
|
|
24
|
+
var IssueDraftParseError = class extends Error {
|
|
25
|
+
constructor(message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "IssueDraftParseError";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
function extractTag(source, tag) {
|
|
31
|
+
const open = `<${tag}>`;
|
|
32
|
+
const close = `</${tag}>`;
|
|
33
|
+
const start = source.lastIndexOf(open);
|
|
34
|
+
if (start === -1) return null;
|
|
35
|
+
const end = source.lastIndexOf(close);
|
|
36
|
+
if (end === -1 || end < start) return null;
|
|
37
|
+
return source.slice(start + open.length, end);
|
|
38
|
+
}
|
|
39
|
+
function parseLabels(raw) {
|
|
40
|
+
if (raw === null) return [];
|
|
41
|
+
return raw.split(",").map((label) => label.trim()).filter((label) => label.length > 0 && label.toLowerCase() !== "(none)");
|
|
42
|
+
}
|
|
43
|
+
function parseIssueDraft(output) {
|
|
44
|
+
const normalized = output.replace(/\r\n?/g, "\n");
|
|
45
|
+
const block = extractTag(normalized, DRAFT_TAG);
|
|
46
|
+
if (block === null) {
|
|
47
|
+
throw new IssueDraftParseError(
|
|
48
|
+
`The agent did not emit an <${DRAFT_TAG}> block, so there is no Issue to create. Output was: ${normalized.trim().slice(0, 300) || "(empty)"}`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const title = (extractTag(block, "title") ?? "").trim();
|
|
52
|
+
const body = (extractTag(block, "body") ?? "").trim();
|
|
53
|
+
if (title.length === 0) {
|
|
54
|
+
throw new IssueDraftParseError(`The <${DRAFT_TAG}> block has no <title>.`);
|
|
55
|
+
}
|
|
56
|
+
if (body.length === 0) {
|
|
57
|
+
throw new IssueDraftParseError(`The <${DRAFT_TAG}> block has no <body>.`);
|
|
58
|
+
}
|
|
59
|
+
return { title, body, labels: parseLabels(extractTag(block, "labels")) };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/commands/generate.ts
|
|
63
|
+
function issueLocation(issue) {
|
|
64
|
+
return issue.remoteRef ?? localIssueRef(issue.id);
|
|
65
|
+
}
|
|
66
|
+
async function draftIssue(promptText) {
|
|
67
|
+
const template = await loadPrompt("generate");
|
|
68
|
+
const prompt = applyPlaceholders(template, {
|
|
69
|
+
__USER_PROMPT__: promptText
|
|
70
|
+
});
|
|
71
|
+
const result = await runHeadless({
|
|
72
|
+
prompt,
|
|
73
|
+
maxTurns: 15,
|
|
74
|
+
timeout: getGlobalTimeout() ?? 3e5,
|
|
75
|
+
outputFormat: "text",
|
|
76
|
+
allowedTools: ["Bash", "Read", "Glob", "Grep"],
|
|
77
|
+
statusMessage: "Drafting issue..."
|
|
78
|
+
});
|
|
79
|
+
if (!result.success) {
|
|
80
|
+
throw new Error(`Issue creation failed: ${result.error}`);
|
|
81
|
+
}
|
|
82
|
+
return parseIssueDraft(result.result);
|
|
83
|
+
}
|
|
84
|
+
async function createBoth(draft) {
|
|
85
|
+
const remote = await getProvider("github").create(draft);
|
|
86
|
+
try {
|
|
87
|
+
const mirror = await getProvider("local").create({
|
|
88
|
+
...draft,
|
|
89
|
+
id: remote.id,
|
|
90
|
+
...remote.remoteRef ? {
|
|
91
|
+
remote: {
|
|
92
|
+
provider: "github",
|
|
93
|
+
ref: remote.remoteRef,
|
|
94
|
+
syncedAt: isoNow(),
|
|
95
|
+
syncedContentHash: remote.contentHash
|
|
96
|
+
}
|
|
97
|
+
} : {}
|
|
98
|
+
});
|
|
99
|
+
return [remote, mirror];
|
|
100
|
+
} catch (err) {
|
|
101
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
102
|
+
throw new Error(
|
|
103
|
+
`GitHub issue created at ${issueLocation(remote)}, but the local mirror was not written: ${message}. Nothing else was persisted; re-run with --local to create the mirror.`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function createIssues(target, draft) {
|
|
108
|
+
if (target === "both") {
|
|
109
|
+
return createBoth(draft);
|
|
110
|
+
}
|
|
111
|
+
return [await getProvider(target).create(draft)];
|
|
112
|
+
}
|
|
113
|
+
async function runGenerate(promptText, target) {
|
|
114
|
+
const config = await loadIssuesConfig();
|
|
115
|
+
const destination = target ?? config.defaultGenerateTarget;
|
|
116
|
+
ensureProvidersRegistered();
|
|
117
|
+
let draft;
|
|
118
|
+
try {
|
|
119
|
+
draft = await draftIssue(promptText);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
if (err instanceof IssueDraftParseError) {
|
|
122
|
+
printError(`Could not read the generated Issue draft: ${err.message}`);
|
|
123
|
+
} else {
|
|
124
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
125
|
+
}
|
|
126
|
+
return 1;
|
|
127
|
+
}
|
|
128
|
+
let created;
|
|
129
|
+
try {
|
|
130
|
+
created = await createIssues(destination, draft);
|
|
131
|
+
} catch (err) {
|
|
132
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
for (const issue of created) {
|
|
136
|
+
printSuccess(`Issue created (${issue.source}): ${issueLocation(issue)}`);
|
|
137
|
+
}
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
export {
|
|
141
|
+
runGenerate
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=generate-IN62ARBS.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 { 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 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: '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":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runPlan
|
|
4
|
+
} from "./chunk-FPGHTTVV.js";
|
|
5
|
+
import "./chunk-2CSHLHYP.js";
|
|
6
|
+
import "./chunk-SVOWWZQJ.js";
|
|
7
|
+
import "./chunk-HDV3YDTG.js";
|
|
8
|
+
import "./chunk-SLHZPB3C.js";
|
|
9
|
+
import "./chunk-4HT4EVYV.js";
|
|
10
|
+
import "./chunk-WZDCTAWZ.js";
|
|
11
|
+
export {
|
|
12
|
+
runPlan
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=plan-6KLONWPR.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runPr
|
|
4
|
+
} from "./chunk-KWGRBNUG.js";
|
|
5
|
+
import "./chunk-2CSHLHYP.js";
|
|
6
|
+
import "./chunk-SVOWWZQJ.js";
|
|
7
|
+
import "./chunk-HDV3YDTG.js";
|
|
8
|
+
import "./chunk-SLHZPB3C.js";
|
|
9
|
+
import "./chunk-4HT4EVYV.js";
|
|
10
|
+
import "./chunk-WZDCTAWZ.js";
|
|
11
|
+
export {
|
|
12
|
+
runPr
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=pr-JLJLMFN3.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runPrd
|
|
4
|
+
} from "./chunk-EHX4J5G5.js";
|
|
5
|
+
import "./chunk-2CSHLHYP.js";
|
|
6
|
+
import "./chunk-SVOWWZQJ.js";
|
|
7
|
+
import "./chunk-HDV3YDTG.js";
|
|
8
|
+
import "./chunk-SLHZPB3C.js";
|
|
9
|
+
import "./chunk-4HT4EVYV.js";
|
|
10
|
+
import "./chunk-WZDCTAWZ.js";
|
|
11
|
+
export {
|
|
12
|
+
runPrd
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=prd-TVJDYZXH.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
runReview
|
|
4
|
+
} from "./chunk-JTSAL3TI.js";
|
|
5
|
+
import "./chunk-SVOWWZQJ.js";
|
|
6
|
+
import "./chunk-SLHZPB3C.js";
|
|
7
|
+
import "./chunk-4HT4EVYV.js";
|
|
8
|
+
import "./chunk-WZDCTAWZ.js";
|
|
9
|
+
export {
|
|
10
|
+
runReview
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=review-FRV4ZMS2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|