issue-flow 0.7.2 → 0.7.3

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.
Files changed (75) hide show
  1. package/dist/{analyze-XMEULTT2.js → analyze-PJBY346H.js} +13 -8
  2. package/dist/analyze-PJBY346H.js.map +1 -0
  3. package/dist/{chunk-MWUF4LMF.js → chunk-3ISZ7T5M.js} +13 -8
  4. package/dist/chunk-3ISZ7T5M.js.map +1 -0
  5. package/dist/{chunk-EHVKXFFN.js → chunk-4M4EWFZZ.js} +2 -2
  6. package/dist/{chunk-JNEHVQH5.js → chunk-6HGZYTAT.js} +223 -11
  7. package/dist/chunk-6HGZYTAT.js.map +1 -0
  8. package/dist/chunk-7HX2RPFY.js +123 -0
  9. package/dist/chunk-7HX2RPFY.js.map +1 -0
  10. package/dist/{chunk-DKMBLNGO.js → chunk-7YS3J4A2.js} +3 -3
  11. package/dist/{chunk-WQ4SUZ4P.js → chunk-EBJM6G2D.js} +90 -23
  12. package/dist/chunk-EBJM6G2D.js.map +1 -0
  13. package/dist/{chunk-GOZT2YP5.js → chunk-IWBHBDRU.js} +5 -9
  14. package/dist/chunk-IWBHBDRU.js.map +1 -0
  15. package/dist/{chunk-6UBA7CSJ.js → chunk-NVSJYJ72.js} +14 -8
  16. package/dist/chunk-NVSJYJ72.js.map +1 -0
  17. package/dist/{chunk-G3TJHMAS.js → chunk-OCXHO7YP.js} +2 -2
  18. package/dist/{chunk-RGCU2KE6.js → chunk-R7X26MWK.js} +14 -9
  19. package/dist/chunk-R7X26MWK.js.map +1 -0
  20. package/dist/{chunk-YLXPLHEL.js → chunk-RKASM5FF.js} +2 -2
  21. package/dist/{chunk-WUITOU5B.js → chunk-SHG2PPN7.js} +14 -9
  22. package/dist/chunk-SHG2PPN7.js.map +1 -0
  23. package/dist/{chunk-CYU6RSDJ.js → chunk-WEXU4R3H.js} +14 -9
  24. package/dist/chunk-WEXU4R3H.js.map +1 -0
  25. package/dist/{chunk-PRVWJZV4.js → chunk-YPIIIDTT.js} +3 -3
  26. package/dist/cli.js +13 -13
  27. package/dist/{config-2NDV7Y72.js → config-7N7UJP32.js} +3 -3
  28. package/dist/execute-EZKQKKLO.js +13 -0
  29. package/dist/{generate-YEQRH36H.js → generate-KUQNDMMR.js} +13 -8
  30. package/dist/generate-KUQNDMMR.js.map +1 -0
  31. package/dist/init-GL6US653.js +9 -0
  32. package/dist/plan-XNXGWNGY.js +15 -0
  33. package/dist/pr-XILDNJLM.js +15 -0
  34. package/dist/pr-review-4WG2RPRP.js +15 -0
  35. package/dist/prd-BLJ2XBPL.js +15 -0
  36. package/dist/review-MRA7ZQQG.js +13 -0
  37. package/dist/{run-EFXDXSB4.js → run-X62QZCXN.js} +20 -16
  38. package/dist/run-X62QZCXN.js.map +1 -0
  39. package/package.json +2 -2
  40. package/web/CLAUDE.md +35 -0
  41. package/web/public/app.css +5 -0
  42. package/web/public/app.js +80 -7
  43. package/dist/analyze-XMEULTT2.js.map +0 -1
  44. package/dist/chunk-6UBA7CSJ.js.map +0 -1
  45. package/dist/chunk-CYU6RSDJ.js.map +0 -1
  46. package/dist/chunk-GOZT2YP5.js.map +0 -1
  47. package/dist/chunk-JNEHVQH5.js.map +0 -1
  48. package/dist/chunk-MWUF4LMF.js.map +0 -1
  49. package/dist/chunk-RGCU2KE6.js.map +0 -1
  50. package/dist/chunk-SLHZPB3C.js +0 -50
  51. package/dist/chunk-SLHZPB3C.js.map +0 -1
  52. package/dist/chunk-WQ4SUZ4P.js.map +0 -1
  53. package/dist/chunk-WUITOU5B.js.map +0 -1
  54. package/dist/execute-BOQPTRH4.js +0 -13
  55. package/dist/generate-YEQRH36H.js.map +0 -1
  56. package/dist/init-5KXCG36P.js +0 -9
  57. package/dist/plan-4I47CQM5.js +0 -15
  58. package/dist/pr-F672VPMM.js +0 -15
  59. package/dist/pr-review-GKP4TJRJ.js +0 -15
  60. package/dist/prd-3QME4DYX.js +0 -15
  61. package/dist/review-RG2UIPOB.js +0 -13
  62. package/dist/run-EFXDXSB4.js.map +0 -1
  63. /package/dist/{chunk-EHVKXFFN.js.map → chunk-4M4EWFZZ.js.map} +0 -0
  64. /package/dist/{chunk-DKMBLNGO.js.map → chunk-7YS3J4A2.js.map} +0 -0
  65. /package/dist/{chunk-G3TJHMAS.js.map → chunk-OCXHO7YP.js.map} +0 -0
  66. /package/dist/{chunk-YLXPLHEL.js.map → chunk-RKASM5FF.js.map} +0 -0
  67. /package/dist/{chunk-PRVWJZV4.js.map → chunk-YPIIIDTT.js.map} +0 -0
  68. /package/dist/{config-2NDV7Y72.js.map → config-7N7UJP32.js.map} +0 -0
  69. /package/dist/{execute-BOQPTRH4.js.map → execute-EZKQKKLO.js.map} +0 -0
  70. /package/dist/{init-5KXCG36P.js.map → init-GL6US653.js.map} +0 -0
  71. /package/dist/{plan-4I47CQM5.js.map → plan-XNXGWNGY.js.map} +0 -0
  72. /package/dist/{pr-F672VPMM.js.map → pr-XILDNJLM.js.map} +0 -0
  73. /package/dist/{pr-review-GKP4TJRJ.js.map → pr-review-4WG2RPRP.js.map} +0 -0
  74. /package/dist/{prd-3QME4DYX.js.map → prd-BLJ2XBPL.js.map} +0 -0
  75. /package/dist/{review-RG2UIPOB.js.map → review-MRA7ZQQG.js.map} +0 -0
@@ -2,31 +2,32 @@
2
2
  import {
3
3
  readFileWithGrace,
4
4
  runPhaseWithRetry
5
- } from "./chunk-EHVKXFFN.js";
5
+ } from "./chunk-4M4EWFZZ.js";
6
6
  import {
7
7
  issuePlaceholders,
8
8
  resolveCommandIssue
9
- } from "./chunk-DKMBLNGO.js";
9
+ } from "./chunk-7YS3J4A2.js";
10
10
  import {
11
11
  isTransientFailure
12
12
  } from "./chunk-HDV3YDTG.js";
13
13
  import {
14
14
  runHeadless
15
- } from "./chunk-GOZT2YP5.js";
15
+ } from "./chunk-IWBHBDRU.js";
16
16
  import {
17
17
  applyPlaceholders,
18
- loadPrompt
19
- } from "./chunk-SLHZPB3C.js";
18
+ loadPrompt,
19
+ publishPhaseMetrics
20
+ } from "./chunk-7HX2RPFY.js";
20
21
  import {
21
22
  resolveIssuePaths
22
- } from "./chunk-G3TJHMAS.js";
23
+ } from "./chunk-OCXHO7YP.js";
23
24
  import {
24
25
  getGlobalTimeout,
25
26
  loadTaskPlan,
26
27
  printError,
27
28
  printSuccess,
28
29
  saveTaskPlan
29
- } from "./chunk-JNEHVQH5.js";
30
+ } from "./chunk-6HGZYTAT.js";
30
31
 
31
32
  // src/commands/prd.ts
32
33
  import { mkdir } from "fs/promises";
@@ -51,15 +52,19 @@ async function runPrd(issue, resolvedIssue) {
51
52
  const outcome = await runPhaseWithRetry({
52
53
  phase: "prd",
53
54
  attempt: async () => {
55
+ const startedAtMs = Date.now();
54
56
  const result = await runHeadless({
55
57
  prompt,
56
58
  maxTurns: 25,
57
59
  timeout: getGlobalTimeout() ?? 3e5,
58
- outputFormat: "text",
60
+ // json (not text) so the CLI reports usage: the envelope's `result`
61
+ // field carries the same assistant text this phase already consumed.
62
+ outputFormat: "json",
59
63
  allowedTools: ["Bash", "Read", "Glob", "Grep", "Write"],
60
64
  addDirs: [paths.issueDir],
61
65
  statusMessage: `Generating PRD for issue #${issueNumber}...`
62
66
  });
67
+ publishPhaseMetrics("prd", result.cost, startedAtMs);
63
68
  if (!result.success) {
64
69
  return {
65
70
  ok: false,
@@ -96,4 +101,4 @@ async function runPrd(issue, resolvedIssue) {
96
101
  export {
97
102
  runPrd
98
103
  };
99
- //# sourceMappingURL=chunk-CYU6RSDJ.js.map
104
+ //# sourceMappingURL=chunk-WEXU4R3H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/prd.ts"],"sourcesContent":["import { mkdir } 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 { publishPhaseMetrics } from '../core/session-metrics.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';\nimport { isTransientFailure } from '../utils/retry.js';\n\nexport async function runPrd(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n const prdPath = paths.prdFile;\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n await mkdir(paths.issueDir, { recursive: true });\n\n const template = await loadPrompt('prd');\n const prompt = applyPlaceholders(template, {\n __ISSUE_NUMBER__: issueNumber,\n __PRD_PATH__: prdPath,\n // Absolute: the analysis lives in the global storage, outside the working\n // directory the agent is started in.\n __ANALYSIS_PATH__: paths.analysisFile,\n ...issuePlaceholders(resolution.resolved),\n });\n\n const outcome = await runPhaseWithRetry({\n phase: 'prd',\n attempt: async () => {\n const startedAtMs = Date.now();\n const result = await runHeadless({\n prompt,\n maxTurns: 25,\n timeout: getGlobalTimeout() ?? 300_000,\n // json (not text) so the CLI reports usage: the envelope's `result`\n // field carries the same assistant text this phase already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep', 'Write'],\n addDirs: [paths.issueDir],\n statusMessage: `Generating PRD for issue #${issueNumber}...`,\n });\n // One event per attempt; the reducer sums them into the phase total.\n publishPhaseMetrics('prd', result.cost, startedAtMs);\n\n if (!result.success) {\n return {\n ok: false,\n transient: isTransientFailure(1, result.error ?? ''),\n error: `PRD generation failed: ${result.error}`,\n };\n }\n\n // Verify the file was created. A brief grace period absorbs a lag\n // between the Write tool completing and this process seeing it; if it\n // still isn't there, treat it as recoverable and let the phase retry.\n try {\n const content = await readFileWithGrace(prdPath);\n if (content.length < 10) {\n return { ok: false, transient: true, error: 'PRD file was created but appears empty' };\n }\n } catch {\n return { ok: false, transient: true, error: `PRD file was not created at ${prdPath}` };\n }\n\n return { ok: true };\n },\n });\n\n if (!outcome.ok) {\n printError(outcome.error ?? `PRD generation failed for issue #${issueNumber}`);\n return 1;\n }\n\n // Update pipeline state\n const tasksPath = paths.tasksFile;\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.prdCompleted = true;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist yet\n }\n\n printSuccess(`PRD saved to ${prdPath}`);\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AAatB,eAAsB,OAAO,OAAe,eAAgD;AAC1F,QAAM,cAAc,MAAM,QAAQ,MAAM,EAAE;AAC1C,QAAM,QAAQ,MAAM,kBAAkB,WAAW;AACjD,QAAM,UAAU,MAAM;AAEtB,QAAM,aAAa,MAAM,oBAAoB,aAAa,aAAa;AACvE,MAAI,CAAC,WAAW,IAAI;AAClB,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM,MAAM,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAE/C,QAAM,WAAW,MAAM,WAAW,KAAK;AACvC,QAAM,SAAS,kBAAkB,UAAU;AAAA,IACzC,kBAAkB;AAAA,IAClB,cAAc;AAAA;AAAA;AAAA,IAGd,mBAAmB,MAAM;AAAA,IACzB,GAAG,kBAAkB,WAAW,QAAQ;AAAA,EAC1C,CAAC;AAED,QAAM,UAAU,MAAM,kBAAkB;AAAA,IACtC,OAAO;AAAA,IACP,SAAS,YAAY;AACnB,YAAM,cAAc,KAAK,IAAI;AAC7B,YAAM,SAAS,MAAM,YAAY;AAAA,QAC/B;AAAA,QACA,UAAU;AAAA,QACV,SAAS,iBAAiB,KAAK;AAAA;AAAA;AAAA,QAG/B,cAAc;AAAA,QACd,cAAc,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,OAAO;AAAA,QACtD,SAAS,CAAC,MAAM,QAAQ;AAAA,QACxB,eAAe,6BAA6B,WAAW;AAAA,MACzD,CAAC;AAED,0BAAoB,OAAO,OAAO,MAAM,WAAW;AAEnD,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,WAAW,mBAAmB,GAAG,OAAO,SAAS,EAAE;AAAA,UACnD,OAAO,0BAA0B,OAAO,KAAK;AAAA,QAC/C;AAAA,MACF;AAKA,UAAI;AACF,cAAM,UAAU,MAAM,kBAAkB,OAAO;AAC/C,YAAI,QAAQ,SAAS,IAAI;AACvB,iBAAO,EAAE,IAAI,OAAO,WAAW,MAAM,OAAO,yCAAyC;AAAA,QACvF;AAAA,MACF,QAAQ;AACN,eAAO,EAAE,IAAI,OAAO,WAAW,MAAM,OAAO,+BAA+B,OAAO,GAAG;AAAA,MACvF;AAEA,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,QAAQ,IAAI;AACf,eAAW,QAAQ,SAAS,oCAAoC,WAAW,EAAE;AAC7E,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,MAAM;AACxB,MAAI;AACF,UAAM,OAAO,MAAM,aAAa,SAAS;AACzC,SAAK,SAAS,eAAe;AAC7B,UAAM,aAAa,WAAW,IAAI;AAAA,EACpC,QAAQ;AAAA,EAER;AAEA,eAAa,gBAAgB,OAAO,EAAE;AACtC,SAAO;AACT;","names":[]}
@@ -4,11 +4,11 @@ import {
4
4
  getCommitsSince,
5
5
  getCurrentBranch,
6
6
  run
7
- } from "./chunk-G3TJHMAS.js";
7
+ } from "./chunk-OCXHO7YP.js";
8
8
  import {
9
9
  NullPublisher,
10
10
  isoNow
11
- } from "./chunk-JNEHVQH5.js";
11
+ } from "./chunk-6HGZYTAT.js";
12
12
 
13
13
  // src/core/session-git.ts
14
14
  async function listPullRequests(branch) {
@@ -69,4 +69,4 @@ export {
69
69
  listPullRequests,
70
70
  publishGitState
71
71
  };
72
- //# sourceMappingURL=chunk-PRVWJZV4.js.map
72
+ //# sourceMappingURL=chunk-YPIIIDTT.js.map
package/dist/cli.js CHANGED
@@ -2,12 +2,12 @@
2
2
  import {
3
3
  setIssuesCliOverrides,
4
4
  setWebCliOverrides
5
- } from "./chunk-G3TJHMAS.js";
5
+ } from "./chunk-OCXHO7YP.js";
6
6
  import {
7
7
  printError,
8
8
  setGlobalTimeout,
9
9
  setVerbose
10
- } from "./chunk-JNEHVQH5.js";
10
+ } from "./chunk-6HGZYTAT.js";
11
11
 
12
12
  // src/cli.ts
13
13
  import { createRequire } from "module";
@@ -159,8 +159,8 @@ 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-2NDV7Y72.js");
163
- const { runInit } = await import("./init-5KXCG36P.js");
162
+ const { loadIssuesConfig } = await import("./config-7N7UJP32.js");
163
+ const { runInit } = await import("./init-GL6US653.js");
164
164
  const { preferredProvider } = await loadIssuesConfig();
165
165
  const code = await runInit(preferredProvider);
166
166
  process.exit(code);
@@ -178,7 +178,7 @@ withGlobalOptions(
178
178
  }
179
179
  throw error;
180
180
  }
181
- const { runGenerate } = await import("./generate-YEQRH36H.js");
181
+ const { runGenerate } = await import("./generate-KUQNDMMR.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-EFXDXSB4.js");
205
+ const { runPipeline } = await import("./run-X62QZCXN.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-XMEULTT2.js");
221
+ const { runAnalyze } = await import("./analyze-PJBY346H.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-3QME4DYX.js");
230
+ const { runPrd } = await import("./prd-BLJ2XBPL.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-4I47CQM5.js");
239
+ const { runPlan } = await import("./plan-XNXGWNGY.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-BOQPTRH4.js");
258
+ const { runExecute } = await import("./execute-EZKQKKLO.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-RG2UIPOB.js");
272
+ const { runReview } = await import("./review-MRA7ZQQG.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-F672VPMM.js");
281
+ const { runPr } = await import("./pr-XILDNJLM.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-GKP4TJRJ.js");
292
+ const { runPrReview } = await import("./pr-review-4WG2RPRP.js");
293
293
  const code = await runPrReview(pr, options);
294
294
  process.exit(code);
295
295
  }
@@ -15,8 +15,8 @@ import {
15
15
  setIssuesCliOverrides,
16
16
  setWebCliOverrides,
17
17
  validateDependencies
18
- } from "./chunk-G3TJHMAS.js";
19
- import "./chunk-JNEHVQH5.js";
18
+ } from "./chunk-OCXHO7YP.js";
19
+ import "./chunk-6HGZYTAT.js";
20
20
  export {
21
21
  DEFAULTS,
22
22
  GLOBAL_CONFIG_FILENAME,
@@ -34,4 +34,4 @@ export {
34
34
  setWebCliOverrides,
35
35
  validateDependencies
36
36
  };
37
- //# sourceMappingURL=config-2NDV7Y72.js.map
37
+ //# sourceMappingURL=config-7N7UJP32.js.map
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runExecute
4
+ } from "./chunk-EBJM6G2D.js";
5
+ import "./chunk-HDV3YDTG.js";
6
+ import "./chunk-YPIIIDTT.js";
7
+ import "./chunk-7HX2RPFY.js";
8
+ import "./chunk-OCXHO7YP.js";
9
+ import "./chunk-6HGZYTAT.js";
10
+ export {
11
+ runExecute
12
+ };
13
+ //# sourceMappingURL=execute-EZKQKKLO.js.map
@@ -3,24 +3,25 @@ import {
3
3
  ensureProvidersRegistered,
4
4
  getProvider,
5
5
  localIssueRef
6
- } from "./chunk-DKMBLNGO.js";
6
+ } from "./chunk-7YS3J4A2.js";
7
7
  import {
8
8
  runHeadless
9
- } from "./chunk-GOZT2YP5.js";
9
+ } from "./chunk-IWBHBDRU.js";
10
10
  import {
11
11
  applyPlaceholders,
12
- loadPrompt
13
- } from "./chunk-SLHZPB3C.js";
12
+ loadPrompt,
13
+ publishPhaseMetrics
14
+ } from "./chunk-7HX2RPFY.js";
14
15
  import {
15
16
  loadIssuesConfig,
16
17
  resolveProjectPaths
17
- } from "./chunk-G3TJHMAS.js";
18
+ } from "./chunk-OCXHO7YP.js";
18
19
  import {
19
20
  getGlobalTimeout,
20
21
  isoNow,
21
22
  printError,
22
23
  printSuccess
23
- } from "./chunk-JNEHVQH5.js";
24
+ } from "./chunk-6HGZYTAT.js";
24
25
 
25
26
  // src/issues/draft.ts
26
27
  var DRAFT_TAG = "issue-draft";
@@ -73,15 +74,19 @@ async function draftIssue(promptText) {
73
74
  __USER_PROMPT__: promptText,
74
75
  __LOCAL_ISSUES_DIR__: issuesDir
75
76
  });
77
+ const startedAtMs = Date.now();
76
78
  const result = await runHeadless({
77
79
  prompt,
78
80
  maxTurns: 15,
79
81
  timeout: getGlobalTimeout() ?? 3e5,
80
- outputFormat: "text",
82
+ // json (not text) so the CLI reports usage: the envelope's `result` field
83
+ // carries the same assistant text parseIssueDraft() already consumed.
84
+ outputFormat: "json",
81
85
  allowedTools: ["Bash", "Read", "Glob", "Grep"],
82
86
  addDirs: [issuesDir],
83
87
  statusMessage: "Drafting issue..."
84
88
  });
89
+ publishPhaseMetrics("generate", result.cost, startedAtMs);
85
90
  if (!result.success) {
86
91
  throw new Error(`Issue creation failed: ${result.error}`);
87
92
  }
@@ -146,4 +151,4 @@ async function runGenerate(promptText, target) {
146
151
  export {
147
152
  runGenerate
148
153
  };
149
- //# sourceMappingURL=generate-YEQRH36H.js.map
154
+ //# sourceMappingURL=generate-KUQNDMMR.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 { publishPhaseMetrics } from '../core/session-metrics.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 startedAtMs = Date.now();\n const result = await runHeadless({\n prompt,\n maxTurns: 15,\n timeout: getGlobalTimeout() ?? 300_000,\n // json (not text) so the CLI reports usage: the envelope's `result` field\n // carries the same assistant text parseIssueDraft() already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n addDirs: [issuesDir],\n statusMessage: 'Drafting issue...',\n });\n // Before the success check: the tokens were spent either way.\n publishPhaseMetrics('generate', result.cost, startedAtMs);\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":";;;;;;;;;;;;;;;;;;;;;;;;;;AAgBO,IAAM,YAAY;AAGlB,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAUA,SAAS,WAAW,QAAgB,KAA4B;AAC9D,QAAM,OAAO,IAAI,GAAG;AACpB,QAAM,QAAQ,KAAK,GAAG;AAEtB,QAAM,QAAQ,OAAO,YAAY,IAAI;AACrC,MAAI,UAAU,GAAI,QAAO;AAEzB,QAAM,MAAM,OAAO,YAAY,KAAK;AACpC,MAAI,QAAQ,MAAM,MAAM,MAAO,QAAO;AAEtC,SAAO,OAAO,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9C;AAEA,SAAS,YAAY,KAA8B;AACjD,MAAI,QAAQ,KAAM,QAAO,CAAC;AAC1B,SAAO,IACJ,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAC3B,OAAO,CAAC,UAAU,MAAM,SAAS,KAAK,MAAM,YAAY,MAAM,QAAQ;AAC3E;AASO,SAAS,gBAAgB,QAA4B;AAC1D,QAAM,aAAa,OAAO,QAAQ,UAAU,IAAI;AAChD,QAAM,QAAQ,WAAW,YAAY,SAAS;AAE9C,MAAI,UAAU,MAAM;AAClB,UAAM,IAAI;AAAA,MACR,8BAA8B,SAAS,wDACtB,WAAW,KAAK,EAAE,MAAM,GAAG,GAAG,KAAK,SAAS;AAAA,IAC/D;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,OAAO,OAAO,KAAK,IAAI,KAAK;AACtD,QAAM,QAAQ,WAAW,OAAO,MAAM,KAAK,IAAI,KAAK;AAEpD,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI,qBAAqB,QAAQ,SAAS,yBAAyB;AAAA,EAC3E;AACA,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,qBAAqB,QAAQ,SAAS,wBAAwB;AAAA,EAC1E;AAEA,SAAO,EAAE,OAAO,MAAM,QAAQ,YAAY,WAAW,OAAO,QAAQ,CAAC,EAAE;AACzE;;;ACrEA,SAAS,cAAc,OAAsB;AAC3C,SAAO,MAAM,aAAa,cAAc,MAAM,EAAE;AAClD;AAQA,eAAe,WAAW,YAAyC;AAIjE,QAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAEhD,QAAM,WAAW,MAAM,WAAW,UAAU;AAC5C,QAAM,SAAS,kBAAkB,UAAU;AAAA,IACzC,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,EACxB,CAAC;AAED,QAAM,cAAc,KAAK,IAAI;AAC7B,QAAM,SAAS,MAAM,YAAY;AAAA,IAC/B;AAAA,IACA,UAAU;AAAA,IACV,SAAS,iBAAiB,KAAK;AAAA;AAAA;AAAA,IAG/B,cAAc;AAAA,IACd,cAAc,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAAA,IAC7C,SAAS,CAAC,SAAS;AAAA,IACnB,eAAe;AAAA,EACjB,CAAC;AAED,sBAAoB,YAAY,OAAO,MAAM,WAAW;AAExD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI,MAAM,0BAA0B,OAAO,KAAK,EAAE;AAAA,EAC1D;AAEA,SAAO,gBAAgB,OAAO,MAAM;AACtC;AAUA,eAAe,WAAW,OAAqC;AAC7D,QAAM,SAAS,MAAM,YAAY,QAAQ,EAAE,OAAO,KAAK;AAEvD,MAAI;AACF,UAAM,SAAS,MAAM,YAAY,OAAO,EAAE,OAAO;AAAA,MAC/C,GAAG;AAAA,MACH,IAAI,OAAO;AAAA,MACX,GAAI,OAAO,YACP;AAAA,QACE,QAAQ;AAAA,UACN,UAAU;AAAA,UACV,KAAK,OAAO;AAAA,UACZ,UAAU,OAAO;AAAA,UACjB,mBAAmB,OAAO;AAAA,QAC5B;AAAA,MACF,IACA,CAAC;AAAA,IACP,CAAC;AACD,WAAO,CAAC,QAAQ,MAAM;AAAA,EACxB,SAAS,KAAK;AACZ,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAM,IAAI;AAAA,MACR,2BAA2B,cAAc,MAAM,CAAC,2CAC3C,OAAO;AAAA,IACd;AAAA,EACF;AACF;AAEA,eAAe,aAAa,QAA6B,OAAqC;AAC5F,MAAI,WAAW,QAAQ;AACrB,WAAO,WAAW,KAAK;AAAA,EACzB;AACA,SAAO,CAAC,MAAM,YAAY,MAAM,EAAE,OAAO,KAAK,CAAC;AACjD;AAEA,eAAsB,YACpB,YACA,QACiB;AACjB,QAAM,SAAS,MAAM,iBAAiB;AACtC,QAAM,cAAc,UAAU,OAAO;AAErC,4BAA0B;AAE1B,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,WAAW,UAAU;AAAA,EACrC,SAAS,KAAK;AACZ,QAAI,eAAe,sBAAsB;AACvC,iBAAW,6CAA6C,IAAI,OAAO,EAAE;AAAA,IACvE,OAAO;AACL,iBAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,aAAa,aAAa,KAAK;AAAA,EACjD,SAAS,KAAK;AACZ,eAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC3D,WAAO;AAAA,EACT;AAEA,aAAW,SAAS,SAAS;AAC3B,iBAAa,kBAAkB,MAAM,MAAM,MAAM,cAAc,KAAK,CAAC,EAAE;AAAA,EACzE;AACA,SAAO;AACT;","names":[]}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runInit
4
+ } from "./chunk-RKASM5FF.js";
5
+ import "./chunk-6HGZYTAT.js";
6
+ export {
7
+ runInit
8
+ };
9
+ //# sourceMappingURL=init-GL6US653.js.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runPlan
4
+ } from "./chunk-SHG2PPN7.js";
5
+ import "./chunk-4M4EWFZZ.js";
6
+ import "./chunk-7YS3J4A2.js";
7
+ import "./chunk-HDV3YDTG.js";
8
+ import "./chunk-IWBHBDRU.js";
9
+ import "./chunk-7HX2RPFY.js";
10
+ import "./chunk-OCXHO7YP.js";
11
+ import "./chunk-6HGZYTAT.js";
12
+ export {
13
+ runPlan
14
+ };
15
+ //# sourceMappingURL=plan-XNXGWNGY.js.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runPr
4
+ } from "./chunk-R7X26MWK.js";
5
+ import "./chunk-4M4EWFZZ.js";
6
+ import "./chunk-7YS3J4A2.js";
7
+ import "./chunk-HDV3YDTG.js";
8
+ import "./chunk-IWBHBDRU.js";
9
+ import "./chunk-7HX2RPFY.js";
10
+ import "./chunk-OCXHO7YP.js";
11
+ import "./chunk-6HGZYTAT.js";
12
+ export {
13
+ runPr
14
+ };
15
+ //# sourceMappingURL=pr-XILDNJLM.js.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ exitCodeFor,
4
+ runPrReview
5
+ } from "./chunk-NVSJYJ72.js";
6
+ import "./chunk-YPIIIDTT.js";
7
+ import "./chunk-IWBHBDRU.js";
8
+ import "./chunk-7HX2RPFY.js";
9
+ import "./chunk-OCXHO7YP.js";
10
+ import "./chunk-6HGZYTAT.js";
11
+ export {
12
+ exitCodeFor,
13
+ runPrReview
14
+ };
15
+ //# sourceMappingURL=pr-review-4WG2RPRP.js.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runPrd
4
+ } from "./chunk-WEXU4R3H.js";
5
+ import "./chunk-4M4EWFZZ.js";
6
+ import "./chunk-7YS3J4A2.js";
7
+ import "./chunk-HDV3YDTG.js";
8
+ import "./chunk-IWBHBDRU.js";
9
+ import "./chunk-7HX2RPFY.js";
10
+ import "./chunk-OCXHO7YP.js";
11
+ import "./chunk-6HGZYTAT.js";
12
+ export {
13
+ runPrd
14
+ };
15
+ //# sourceMappingURL=prd-BLJ2XBPL.js.map
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runReview
4
+ } from "./chunk-3ISZ7T5M.js";
5
+ import "./chunk-7YS3J4A2.js";
6
+ import "./chunk-IWBHBDRU.js";
7
+ import "./chunk-7HX2RPFY.js";
8
+ import "./chunk-OCXHO7YP.js";
9
+ import "./chunk-6HGZYTAT.js";
10
+ export {
11
+ runReview
12
+ };
13
+ //# sourceMappingURL=review-MRA7ZQQG.js.map
@@ -1,48 +1,49 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runPrd
4
- } from "./chunk-CYU6RSDJ.js";
4
+ } from "./chunk-WEXU4R3H.js";
5
5
  import {
6
6
  runReview
7
- } from "./chunk-MWUF4LMF.js";
7
+ } from "./chunk-3ISZ7T5M.js";
8
8
  import {
9
9
  runInit
10
- } from "./chunk-YLXPLHEL.js";
10
+ } from "./chunk-RKASM5FF.js";
11
11
  import {
12
12
  printRunSummary,
13
13
  runExecute
14
- } from "./chunk-WQ4SUZ4P.js";
14
+ } from "./chunk-EBJM6G2D.js";
15
15
  import {
16
16
  runPlan
17
- } from "./chunk-WUITOU5B.js";
17
+ } from "./chunk-SHG2PPN7.js";
18
18
  import {
19
19
  runPr
20
- } from "./chunk-RGCU2KE6.js";
21
- import "./chunk-EHVKXFFN.js";
20
+ } from "./chunk-R7X26MWK.js";
21
+ import "./chunk-4M4EWFZZ.js";
22
22
  import {
23
23
  getProvider,
24
24
  resolveCommandIssue
25
- } from "./chunk-DKMBLNGO.js";
25
+ } from "./chunk-7YS3J4A2.js";
26
26
  import "./chunk-HDV3YDTG.js";
27
27
  import {
28
28
  mostRecent,
29
29
  prReviewDir,
30
30
  readPrReviewIndex,
31
31
  runPrReview
32
- } from "./chunk-6UBA7CSJ.js";
32
+ } from "./chunk-NVSJYJ72.js";
33
33
  import {
34
34
  listPullRequests,
35
35
  publishGitState
36
- } from "./chunk-PRVWJZV4.js";
37
- import "./chunk-GOZT2YP5.js";
36
+ } from "./chunk-YPIIIDTT.js";
37
+ import "./chunk-IWBHBDRU.js";
38
38
  import {
39
+ getRunUsageTotals,
39
40
  resolvePackageDir
40
- } from "./chunk-SLHZPB3C.js";
41
+ } from "./chunk-7HX2RPFY.js";
41
42
  import {
42
43
  loadIssuesConfig,
43
44
  loadWebConfig,
44
45
  resolveIssuePaths
45
- } from "./chunk-G3TJHMAS.js";
46
+ } from "./chunk-OCXHO7YP.js";
46
47
  import {
47
48
  FilePublisher,
48
49
  NullPublisher,
@@ -56,7 +57,7 @@ import {
56
57
  setOutputCallback,
57
58
  setSessionPublisher,
58
59
  setStoryUpdateCallback
59
- } from "./chunk-JNEHVQH5.js";
60
+ } from "./chunk-6HGZYTAT.js";
60
61
 
61
62
  // src/commands/run.ts
62
63
  import { randomUUID } from "crypto";
@@ -867,11 +868,14 @@ async function runPipelinePhases(issueNumber, paths, mode, publisher, from, noBr
867
868
  storyCount,
868
869
  elapsedSeconds: result.overallElapsedSeconds,
869
870
  prUrl,
870
- prReview: review
871
+ prReview: review,
872
+ // Process-owned counters: the session snapshot is empty whenever web
873
+ // monitoring is off, so it cannot be the source of these totals.
874
+ usage: getRunUsageTotals()
871
875
  });
872
876
  return 0;
873
877
  }
874
878
  export {
875
879
  runPipeline
876
880
  };
877
- //# sourceMappingURL=run-EFXDXSB4.js.map
881
+ //# sourceMappingURL=run-X62QZCXN.js.map