issue-flow 0.12.0 → 0.14.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.
Files changed (197) hide show
  1. package/README.md +79 -274
  2. package/dist/agent-OX3KPHE4.js +30 -0
  3. package/dist/{analyze-OEET7KGE.js → analyze-WIND2SEB.js} +31 -16
  4. package/dist/analyze-WIND2SEB.js.map +1 -0
  5. package/dist/{apply-ZIA3C52S.js → apply-JNOI2LR4.js} +18 -7
  6. package/dist/{apply-ZIA3C52S.js.map → apply-JNOI2LR4.js.map} +1 -1
  7. package/dist/bench-B4VZON7E.js +910 -0
  8. package/dist/bench-B4VZON7E.js.map +1 -0
  9. package/dist/{chunk-FADTCQGM.js → chunk-2IQ6M4ZE.js} +94 -32
  10. package/dist/chunk-2IQ6M4ZE.js.map +1 -0
  11. package/dist/chunk-3BWZO4YI.js +141 -0
  12. package/dist/chunk-3BWZO4YI.js.map +1 -0
  13. package/dist/chunk-3WFZETIM.js +163 -0
  14. package/dist/chunk-3WFZETIM.js.map +1 -0
  15. package/dist/chunk-67YIU2VB.js +362 -0
  16. package/dist/chunk-67YIU2VB.js.map +1 -0
  17. package/dist/{chunk-QCPGHBSZ.js → chunk-6BENHR2I.js} +63 -21
  18. package/dist/chunk-6BENHR2I.js.map +1 -0
  19. package/dist/{chunk-BYZDPR7N.js → chunk-6QYMSNVA.js} +194 -235
  20. package/dist/chunk-6QYMSNVA.js.map +1 -0
  21. package/dist/{chunk-Y5ZDJ4PJ.js → chunk-76MMPJ53.js} +20 -10
  22. package/dist/chunk-76MMPJ53.js.map +1 -0
  23. package/dist/chunk-7Z4Y3VKM.js +26 -0
  24. package/dist/chunk-7Z4Y3VKM.js.map +1 -0
  25. package/dist/{chunk-3QHK4YQA.js → chunk-B72RQZBV.js} +346 -119
  26. package/dist/chunk-B72RQZBV.js.map +1 -0
  27. package/dist/chunk-BEZ5BA5U.js +625 -0
  28. package/dist/chunk-BEZ5BA5U.js.map +1 -0
  29. package/dist/chunk-BRCNQXYQ.js +74 -0
  30. package/dist/chunk-BRCNQXYQ.js.map +1 -0
  31. package/dist/chunk-CGKLE6WR.js +1203 -0
  32. package/dist/chunk-CGKLE6WR.js.map +1 -0
  33. package/dist/chunk-CRGIQFUQ.js +83 -0
  34. package/dist/chunk-CRGIQFUQ.js.map +1 -0
  35. package/dist/{chunk-NS6R37II.js → chunk-F6TOYSYY.js} +141 -12
  36. package/dist/chunk-F6TOYSYY.js.map +1 -0
  37. package/dist/chunk-G5EK2XRN.js +25 -0
  38. package/dist/chunk-G5EK2XRN.js.map +1 -0
  39. package/dist/chunk-HAKDLR6N.js +134 -0
  40. package/dist/chunk-HAKDLR6N.js.map +1 -0
  41. package/dist/chunk-J3SOTUVI.js +298 -0
  42. package/dist/chunk-J3SOTUVI.js.map +1 -0
  43. package/dist/chunk-JN6D3MY6.js +30 -0
  44. package/dist/chunk-JN6D3MY6.js.map +1 -0
  45. package/dist/{chunk-LAFNLLQP.js → chunk-KMRFRXIT.js} +5 -5
  46. package/dist/chunk-KT7JKOXB.js +72 -0
  47. package/dist/chunk-KT7JKOXB.js.map +1 -0
  48. package/dist/chunk-L6HSKTQE.js +77 -0
  49. package/dist/chunk-L6HSKTQE.js.map +1 -0
  50. package/dist/chunk-LBGHI4S2.js +1264 -0
  51. package/dist/chunk-LBGHI4S2.js.map +1 -0
  52. package/dist/chunk-LEW4QM74.js +180 -0
  53. package/dist/chunk-LEW4QM74.js.map +1 -0
  54. package/dist/{chunk-FJP3UQGD.js → chunk-LFEQIZLB.js} +115 -20
  55. package/dist/chunk-LFEQIZLB.js.map +1 -0
  56. package/dist/chunk-OOVG2KBY.js +77 -0
  57. package/dist/chunk-OOVG2KBY.js.map +1 -0
  58. package/dist/{chunk-56KS3TFQ.js → chunk-OR43364P.js} +115 -160
  59. package/dist/chunk-OR43364P.js.map +1 -0
  60. package/dist/chunk-P3LRUNC6.js +16 -0
  61. package/dist/chunk-P3LRUNC6.js.map +1 -0
  62. package/dist/{chunk-TSOLWK7Y.js → chunk-PBTA3QQX.js} +8 -7
  63. package/dist/{chunk-TSOLWK7Y.js.map → chunk-PBTA3QQX.js.map} +1 -1
  64. package/dist/{chunk-MJULIKQU.js → chunk-PHW2YV6N.js} +23 -47
  65. package/dist/chunk-PHW2YV6N.js.map +1 -0
  66. package/dist/{chunk-73ATPIYX.js → chunk-PZTWU277.js} +36 -71
  67. package/dist/chunk-PZTWU277.js.map +1 -0
  68. package/dist/{chunk-M5UCXTIT.js → chunk-QD4VOILZ.js} +22 -18
  69. package/dist/chunk-QD4VOILZ.js.map +1 -0
  70. package/dist/chunk-QJ5UZAH5.js +2718 -0
  71. package/dist/chunk-QJ5UZAH5.js.map +1 -0
  72. package/dist/chunk-QK7WUO7A.js +283 -0
  73. package/dist/chunk-QK7WUO7A.js.map +1 -0
  74. package/dist/{chunk-A4SLHOW7.js → chunk-QZVKRDJY.js} +27 -19
  75. package/dist/chunk-QZVKRDJY.js.map +1 -0
  76. package/dist/chunk-REO3PXXO.js +71 -0
  77. package/dist/chunk-REO3PXXO.js.map +1 -0
  78. package/dist/{chunk-EZATO3DW.js → chunk-RVO7L4FX.js} +594 -17
  79. package/dist/chunk-RVO7L4FX.js.map +1 -0
  80. package/dist/{chunk-XQUSIEKA.js → chunk-SZMHCEYV.js} +63 -14
  81. package/dist/chunk-SZMHCEYV.js.map +1 -0
  82. package/dist/chunk-TYRNTSPJ.js +243 -0
  83. package/dist/chunk-TYRNTSPJ.js.map +1 -0
  84. package/dist/chunk-UJ3L2MS7.js +238 -0
  85. package/dist/chunk-UJ3L2MS7.js.map +1 -0
  86. package/dist/chunk-V7MO5EDS.js +120 -0
  87. package/dist/chunk-V7MO5EDS.js.map +1 -0
  88. package/dist/chunk-WB2X37MO.js +415 -0
  89. package/dist/chunk-WB2X37MO.js.map +1 -0
  90. package/dist/{chunk-NTMMF5UD.js → chunk-X44FKNKP.js} +525 -252
  91. package/dist/chunk-X44FKNKP.js.map +1 -0
  92. package/dist/chunk-XEYH6ZZI.js +289 -0
  93. package/dist/chunk-XEYH6ZZI.js.map +1 -0
  94. package/dist/cli.js +267 -44
  95. package/dist/cli.js.map +1 -1
  96. package/dist/{config-PRJGWW7J.js → config-HMFMCY2M.js} +31 -5
  97. package/dist/contract-JH2WBIO6.js +8 -0
  98. package/dist/conventions-NJF2OPVQ.js +146 -0
  99. package/dist/conventions-NJF2OPVQ.js.map +1 -0
  100. package/dist/diagnostics-THH42ZMP.js +23 -0
  101. package/dist/execute-KFNNZZHI.js +35 -0
  102. package/dist/{generate-EGB4KV2B.js → generate-FW5C6NP7.js} +37 -20
  103. package/dist/{generate-EGB4KV2B.js.map → generate-FW5C6NP7.js.map} +1 -1
  104. package/dist/git-W72QQ6GT.js +33 -0
  105. package/dist/init-HTN4V67Q.js +24 -0
  106. package/dist/{operations-BYT626KQ.js → operations-BCFOBH42.js} +27 -15
  107. package/dist/{operations-BYT626KQ.js.map → operations-BCFOBH42.js.map} +1 -1
  108. package/dist/permissions-4AKNQZHK.js +18 -0
  109. package/dist/plan-SIZLGA4V.js +34 -0
  110. package/dist/{policy-6S4GFC76.js → policy-DT6Q6ZVM.js} +20 -6
  111. package/dist/policy-DT6Q6ZVM.js.map +1 -0
  112. package/dist/pr-OMWCGUOW.js +39 -0
  113. package/dist/pr-review-N24CZPKR.js +32 -0
  114. package/dist/pr-review-N24CZPKR.js.map +1 -0
  115. package/dist/prd-5OFTZAHJ.js +33 -0
  116. package/dist/prd-5OFTZAHJ.js.map +1 -0
  117. package/dist/ps-RFORTCUD.js +93 -0
  118. package/dist/ps-RFORTCUD.js.map +1 -0
  119. package/dist/recorder-KCCPMKQG.js +32 -0
  120. package/dist/recorder-KCCPMKQG.js.map +1 -0
  121. package/dist/registry-GLPXOMFG.js +15 -0
  122. package/dist/registry-GLPXOMFG.js.map +1 -0
  123. package/dist/{resume-PPCNQVVV.js → resume-M5RLKP4I.js} +55 -34
  124. package/dist/{resume-PPCNQVVV.js.map → resume-M5RLKP4I.js.map} +1 -1
  125. package/dist/review-YM4JAABY.js +35 -0
  126. package/dist/review-YM4JAABY.js.map +1 -0
  127. package/dist/routing-NNT5WKGX.js +94 -0
  128. package/dist/routing-NNT5WKGX.js.map +1 -0
  129. package/dist/run-PZUKHPQK.js +54 -0
  130. package/dist/run-PZUKHPQK.js.map +1 -0
  131. package/dist/session-publisher-T7EI3CIP.js +11 -0
  132. package/dist/session-publisher-T7EI3CIP.js.map +1 -0
  133. package/dist/{state-manager-2EDVDBAR.js → state-manager-GQH32C44.js} +4 -2
  134. package/dist/state-manager-GQH32C44.js.map +1 -0
  135. package/dist/usage-V2CHE5PY.js +177 -0
  136. package/dist/usage-V2CHE5PY.js.map +1 -0
  137. package/dist/{web-EF5WIIGG.js → web-EA3KGNFN.js} +45 -30
  138. package/dist/web-EA3KGNFN.js.map +1 -0
  139. package/package.json +6 -2
  140. package/prompts/execute.md +7 -8
  141. package/prompts/plan.md +4 -5
  142. package/prompts/pr.md +2 -2
  143. package/web/AGENTS.md +152 -13
  144. package/web/public/app.css +380 -109
  145. package/web/public/app.js +525 -25
  146. package/web/public/index.html +68 -1
  147. package/dist/analyze-OEET7KGE.js.map +0 -1
  148. package/dist/chunk-3QHK4YQA.js.map +0 -1
  149. package/dist/chunk-42PJFMAR.js +0 -605
  150. package/dist/chunk-42PJFMAR.js.map +0 -1
  151. package/dist/chunk-4JSOYE4G.js +0 -368
  152. package/dist/chunk-4JSOYE4G.js.map +0 -1
  153. package/dist/chunk-56KS3TFQ.js.map +0 -1
  154. package/dist/chunk-73ATPIYX.js.map +0 -1
  155. package/dist/chunk-A4SLHOW7.js.map +0 -1
  156. package/dist/chunk-BAUPQXPE.js +0 -173
  157. package/dist/chunk-BAUPQXPE.js.map +0 -1
  158. package/dist/chunk-BYZDPR7N.js.map +0 -1
  159. package/dist/chunk-CD5ULRVC.js +0 -615
  160. package/dist/chunk-CD5ULRVC.js.map +0 -1
  161. package/dist/chunk-DIDUVL6O.js +0 -1365
  162. package/dist/chunk-DIDUVL6O.js.map +0 -1
  163. package/dist/chunk-EZATO3DW.js.map +0 -1
  164. package/dist/chunk-FADTCQGM.js.map +0 -1
  165. package/dist/chunk-FJP3UQGD.js.map +0 -1
  166. package/dist/chunk-LWRSMTTZ.js +0 -18
  167. package/dist/chunk-LWRSMTTZ.js.map +0 -1
  168. package/dist/chunk-M5UCXTIT.js.map +0 -1
  169. package/dist/chunk-M66SJHQQ.js +0 -206
  170. package/dist/chunk-M66SJHQQ.js.map +0 -1
  171. package/dist/chunk-MJULIKQU.js.map +0 -1
  172. package/dist/chunk-NS6R37II.js.map +0 -1
  173. package/dist/chunk-NTMMF5UD.js.map +0 -1
  174. package/dist/chunk-QCPGHBSZ.js.map +0 -1
  175. package/dist/chunk-XQUSIEKA.js.map +0 -1
  176. package/dist/chunk-Y5ZDJ4PJ.js.map +0 -1
  177. package/dist/execute-XBNVL753.js +0 -18
  178. package/dist/init-AJHCXJBP.js +0 -10
  179. package/dist/plan-QOZ3RIO6.js +0 -21
  180. package/dist/policy-6S4GFC76.js.map +0 -1
  181. package/dist/pr-EBBHD2ZX.js +0 -26
  182. package/dist/pr-review-VVMW5PO4.js +0 -20
  183. package/dist/prd-JQSZF7PR.js +0 -21
  184. package/dist/review-3F6MARWH.js +0 -19
  185. package/dist/run-RXE5GDQO.js +0 -36
  186. package/dist/web-EF5WIIGG.js.map +0 -1
  187. /package/dist/{config-PRJGWW7J.js.map → agent-OX3KPHE4.js.map} +0 -0
  188. /package/dist/{chunk-LAFNLLQP.js.map → chunk-KMRFRXIT.js.map} +0 -0
  189. /package/dist/{execute-XBNVL753.js.map → config-HMFMCY2M.js.map} +0 -0
  190. /package/dist/{init-AJHCXJBP.js.map → contract-JH2WBIO6.js.map} +0 -0
  191. /package/dist/{plan-QOZ3RIO6.js.map → diagnostics-THH42ZMP.js.map} +0 -0
  192. /package/dist/{pr-EBBHD2ZX.js.map → execute-KFNNZZHI.js.map} +0 -0
  193. /package/dist/{pr-review-VVMW5PO4.js.map → git-W72QQ6GT.js.map} +0 -0
  194. /package/dist/{prd-JQSZF7PR.js.map → init-HTN4V67Q.js.map} +0 -0
  195. /package/dist/{review-3F6MARWH.js.map → permissions-4AKNQZHK.js.map} +0 -0
  196. /package/dist/{run-RXE5GDQO.js.map → plan-SIZLGA4V.js.map} +0 -0
  197. /package/dist/{state-manager-2EDVDBAR.js.map → pr-OMWCGUOW.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/run.ts","../src/execution/detach.ts","../src/storage/run-log.ts","../src/execution/confirm.ts","../src/execution/discovery.ts","../src/execution/queue.ts","../src/issues/args.ts","../src/ui/pipeline-renderer.ts","../src/ui/status-view.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { execa } from 'execa';\nimport { resetAgentInvocationState } from '../agents/invoke.js';\nimport { describeRunAgents } from '../agents/resolve.js';\nimport {\n getActiveResilienceConfig,\n initResilienceConfig,\n loadIssuesConfig,\n loadWebConfig,\n} from '../config.js';\nimport {\n assessDecomposition,\n buildDecompositionReport,\n proposeSubIssues,\n} from '../core/decompose.js';\nimport { JournalPublisher, MultiPublisher } from '../core/journal.js';\nimport {\n PIPELINE_PHASES,\n PIPELINE_PHASES_NO_BRANCH,\n PIPELINE_PHASES_WITH_PR_REVIEW,\n PipelineManager,\n type PipelinePhase,\n} from '../core/pipeline.js';\nimport { mostRecent } from '../core/pr-review/discovery.js';\nimport {\n type PrReviewRoundEntry,\n prReviewDir,\n readPrReviewIndex,\n} from '../core/pr-review/report.js';\nimport { listPullRequests, publishGitState } from '../core/session-git.js';\nimport { beginUsageScope, getRunUsageTotals } from '../core/session-metrics.js';\nimport { getSessionPublisher, setSessionPublisher } from '../core/session-publisher.js';\nimport {\n FilePublisher,\n MemoryPublisher,\n type SessionConfigurationSnapshot,\n type SessionPublisher,\n} from '../core/session-state.js';\nimport { onShutdown } from '../core/shutdown.js';\nimport { isoNow, loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getInactivityTimeout, isVerbose, setInactivityTimeout } from '../core/verbose.js';\nimport { backgroundRejection, spawnDetachedRun } from '../execution/detach.js';\nimport {\n markQueueIssueBlocked,\n markQueueIssueCompleted,\n markQueueIssueFailed,\n markQueueIssueInProgress,\n markQueueIssueSkipped,\n nextQueueIssue,\n saveExecutionPlan,\n setQueueBranch,\n setQueuePullRequest,\n} from '../execution/plan.js';\nimport { planQueue, type QueueDecision } from '../execution/queue.js';\nimport type { ExecutionPlan } from '../execution/types.js';\nimport { parseIssueArguments } from '../issues/args.js';\nimport { resolveCommandIssue } from '../issues/context.js';\nimport { getProvider } from '../issues/registry.js';\nimport type { Issue, IssueSource, ResolvedIssue } from '../issues/types.js';\nimport {\n bindDiagnosticContext,\n flushDiagnostics,\n writeDiagnostic,\n} from '../storage/diagnostics.js';\nimport { acquireRunLock, describeRunLockOwner } from '../storage/lock.js';\nimport type { IssuePaths } from '../storage/paths.js';\nimport { resolveIssuePaths, resolveProjectPaths, resolveQueuePaths } from '../storage/resolve.js';\nimport type { RunLock } from '../storage/schemas.js';\nimport { formatPhaseLine, loadPhaseTiming, snapshotTimingFields } from '../telemetry/timing.js';\nimport type { PullRequestRef, TaskPlan, UserStory } from '../types.js';\nimport { printError, printInfo, printSuccess, printWarning } from '../ui/logger.js';\nimport { runPipelineWithRenderer } from '../ui/pipeline-renderer.js';\nimport {\n printQueueSummary,\n printRunSummary,\n type QueueIssueSummary,\n type RunSummaryPrReview,\n} from '../ui/summary.js';\nimport {\n committedStoryIds,\n describePreflight,\n getBaseBranch,\n getCurrentBranch,\n getHeadCommit,\n getProjectRoot,\n localBranchExists,\n preflightRepository,\n} from '../utils/git.js';\nimport { run } from '../utils/shell.js';\nimport { ensureWebMonitor } from '../web/lock.js';\nimport { runExecute } from './execute.js';\nimport { runInit } from './init.js';\nimport { runPlan } from './plan.js';\nimport { type PrQueueContext, runPr } from './pr.js';\nimport { runPrReview } from './pr-review.js';\nimport { runPrd } from './prd.js';\nimport { runReview } from './review.js';\n\n/**\n * Numeric form of an identifier, or `null` when the origin uses a non-numeric\n * one. Published as-is in session.json: a local id like 'auth-refactor' has no\n * number, and reporting it as 0 would claim an Issue that does not exist.\n */\nfunction toIssueNumber(id: string): number | null {\n const parsed = Number.parseInt(id, 10);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nasync function publishInstrumentedPhaseEnd(\n publisher: SessionPublisher,\n phase: string,\n issueNumber: string,\n success: boolean,\n error?: string,\n): Promise<void> {\n const at = isoNow();\n const startedAt = publisher.snapshot().phases.find((entry) => entry.name === phase)?.startedAt;\n const wallMs =\n startedAt === null || startedAt === undefined\n ? null\n : Math.max(0, Date.parse(at) - Date.parse(startedAt));\n const timing = await loadPhaseTiming(phase, wallMs);\n publisher.publish({\n type: 'phase:end',\n at,\n phase,\n success,\n ...(error === undefined ? {} : { error }),\n ...snapshotTimingFields(timing),\n });\n if (isVerbose()) {\n printInfo(\n formatPhaseLine({\n issueNumber: toIssueNumber(issueNumber) ?? issueNumber,\n phase,\n iteration: timing.iteration,\n wallMs,\n cliDurationMs: timing.cliDurationMs,\n harnessStartupMs: timing.harnessStartupMs,\n ttftMs: timing.ttftMs,\n numTurns: timing.numTurns,\n outputTokens: timing.outputTokens,\n }),\n );\n }\n}\n\n/**\n * Seed the snapshot with the stories a `tasks.json` already holds on disk, so\n * the monitor shows the plan instead of \"no user story yet\" until the first\n * execute iteration republishes them.\n *\n * Must be called **after** `session:start`, which resets the snapshot through\n * `createInitialSnapshot()`. An empty plan publishes nothing: the event would\n * bump the publisher's version without adding any content.\n *\n * Returns whether anything was published.\n */\nexport function publishStorySeed(\n publisher: SessionPublisher,\n stories: readonly UserStory[],\n at: string,\n): boolean {\n if (stories.length === 0) return false;\n publisher.publish({ type: 'stories:update', at, stories: [...stories] });\n return true;\n}\n\n/**\n * Publish the Issue's structural data (title, description, labels, state) so\n * the panel shows what is being implemented without a detour through GitHub.\n *\n * Same window as the story seed: right after `session:start`, which resets the\n * snapshot. The data comes from the `ResolvedIssue` the run already holds — no\n * extra provider call — and the description goes out whole, untruncated.\n */\nexport function publishIssueDetails(publisher: SessionPublisher, issue: Issue, at: string): void {\n publisher.publish({\n type: 'issue:update',\n at,\n number: issue.number,\n // Left undefined (rather than null) when the origin has no remote, so the\n // reducer keeps whatever URL session:start already published.\n url: issue.remoteRef ?? undefined,\n title: issue.title,\n description: issue.body,\n labels: issue.labels,\n state: issue.state,\n });\n}\n\n/** Runnable phase lists (excluding 'init' which is handled separately). */\nconst RUNNABLE_PHASES: PipelinePhase[] = ['prd', 'plan', 'execute', 'review', 'pr'];\nconst RUNNABLE_PHASES_NO_BRANCH: PipelinePhase[] = ['prd', 'plan', 'execute', 'review'];\nconst RUNNABLE_PHASES_WITH_PR_REVIEW: PipelinePhase[] = [...RUNNABLE_PHASES, 'pr-review'];\n\n/**\n * Phases of a queue's closing pass: the work is already committed by the\n * per-issue runs, so all that is left is the single consolidated Pull Request.\n */\nconst QUEUE_PR_PHASES = ['init', 'pr'] as const satisfies readonly PipelinePhase[];\nconst QUEUE_PR_PHASES_WITH_REVIEW = [\n 'init',\n 'pr',\n 'pr-review',\n] as const satisfies readonly PipelinePhase[];\nconst RUNNABLE_QUEUE_PR_PHASES: PipelinePhase[] = ['pr'];\nconst RUNNABLE_QUEUE_PR_PHASES_WITH_REVIEW: PipelinePhase[] = ['pr', 'pr-review'];\n\n/**\n * What the `pr-review` phase left behind, for the steps that run after it: the\n * automatic issue close, the highlighted warning and the final summary.\n *\n * Same shape the summary consumes: `requestedChanges` drives the close\n * suppression and is true on exit code 2 even when the plan is gone.\n */\ntype PrReviewOutcome = RunSummaryPrReview;\n\nfunction verificationForSummary(\n value: {\n verdict: 'passed' | 'failed' | 'unverified' | null;\n level: string | null;\n } | null,\n): { verdict: 'passed' | 'failed' | 'unverified'; level: string | null } | null {\n if (value === null || value.verdict === null) return null;\n return { verdict: value.verdict, level: value.level };\n}\n\n/**\n * Recover the verdict and the report path the `pr-review` phase produced.\n *\n * Best-effort by design: the exit code already tells whether changes were\n * requested, so a missing plan or index costs the summary a detail, never the\n * decision to keep the issue open.\n */\nasync function readPrReviewOutcome(\n issue: string,\n tasksPath: string,\n requestedChanges: boolean,\n): Promise<PrReviewOutcome> {\n const outcome: PrReviewOutcome = { requestedChanges, recommendation: null, reportPath: null };\n try {\n const plan = await loadTaskPlan(tasksPath);\n outcome.recommendation = plan.prReview?.lastRecommendation ?? null;\n\n const pullRequest = plan.prReview?.pullRequestNumber;\n if (pullRequest !== undefined) {\n const dir = await prReviewDir({ issue, pullRequest });\n const index = await readPrReviewIndex(dir);\n const last = index?.rounds.reduce<PrReviewRoundEntry | null>(\n (latest, entry) => (latest === null || entry.round > latest.round ? entry : latest),\n null,\n );\n if (last) {\n outcome.reportPath = join(dir, last.reportPath);\n outcome.recommendation ??= last.recommendation;\n }\n }\n } catch {\n /* non-critical */\n }\n return outcome;\n}\n\n/** Options `run` accepts on top of the phase selection ones. */\nexport interface RunPipelineOptions {\n /** `--yes`: accept the discovered hierarchy without confirmation. */\n yes?: boolean;\n /** `--only`: run just the issues informed, skipping discovery. */\n only?: boolean;\n /** `--cascade`: hierarchy of a container, without implementing it. */\n cascade?: boolean;\n /** `--background`: parent process should detach after confirmation. */\n background?: boolean;\n /** Hidden: this process is the child of a `--background` spawn. */\n detachedChild?: boolean;\n /** `--continue`: name the (automatic) User Story numbering continuity. */\n continueNumbering?: boolean;\n /** `--start-us <n>`: force the first plan of this run to start at `n`. */\n startUs?: number;\n /**\n * `--retry-limit <n>`: consecutive retries the `execute` phase may spend on a\n * transient failure. Absent means the engine default (`DEFAULTS.retryLimit`),\n * which is what every release before this flag existed used.\n */\n retryLimit?: number;\n /** `--retry-forever`: lift the retry count of the `execute` phase. */\n retryForever?: boolean;\n /**\n * `--on-issue-failure <mode>`: what one failing Issue does to the rest of a\n * queue. `stop` is the default and the behaviour of every release before the\n * flag existed.\n */\n onIssueFailure?: QueueFailureMode;\n}\n\n/** What one failing Issue does to the rest of the queue. */\nexport type QueueFailureMode =\n | /** End the run where it failed. The behaviour that has always been. */ 'stop'\n | /** Set it aside, run the independent work, come back to it. */ 'skip'\n | /** Set it aside for a human, and never come back to it. */ 'block';\n\n/** Attempts an Issue gets before the queue stops handing it out. */\nconst DEFAULT_MAX_ISSUE_ATTEMPTS = 2;\n\n/**\n * Everything a queue hands to the run of one of its issues.\n *\n * Its presence is what tells `runPipelinePhases` it is a member of a queue\n * rather than a standalone pipeline: the Pull Request moves to the end of the\n * queue, the branch is shared, commits carry the issue scope, and the terminal\n * summary is the queue's, not the issue's.\n */\ninterface QueueRunContext {\n /** State of the queue, for the branch every issue of it shares. */\n plan: ExecutionPlan;\n /** True when `init` already ran in this process for the queue. */\n preChecked: boolean;\n /** Issue already resolved by the planner, if this is the primary one. */\n resolved?: ResolvedIssue;\n /**\n * Set on the final pass of a queue, which runs no implementation phase at\n * all: only `pr` (and the optional `pr-review`), for the single Pull Request\n * that consolidates every issue.\n */\n finalPr?: PrQueueContext;\n}\n\n/** What one issue's run reports back to the caller. */\ninterface IssueRunResult {\n code: number;\n /** Phase that failed, `null` on success. */\n failedPhase: string | null;\n /** `branchName` of the issue's plan once the `plan` phase produced one. */\n branchName: string | null;\n storyCount: number;\n elapsedSeconds: number;\n /** Verdict of the `pr-review` phase, when it ran. */\n review?: PrReviewOutcome | null;\n /** Set when the run stopped to hand control over to a queue. */\n queue?: { plan: ExecutionPlan; resumed: boolean; resolved: ResolvedIssue };\n}\n\n/**\n * Entry point of `issue-flow run`.\n *\n * Accepts one issue (the historical form, untouched) or several. The first\n * attempt runs as a plain single-issue pipeline; only if the planner decides\n * this invocation is really a queue does it hand control over to\n * {@link runQueue} — and that decision is taken before any session is\n * published, so nothing was written on the way.\n */\nexport async function runPipeline(\n issue: string | readonly string[],\n mode: string,\n from?: string,\n noBranch?: boolean,\n prReview?: boolean,\n options: RunPipelineOptions = {},\n): Promise<number> {\n let requested: string[];\n try {\n requested = parseIssueArguments(typeof issue === 'string' ? [issue] : issue);\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n return 1;\n }\n\n if (options.background === true && options.detachedChild !== true) {\n const reason = backgroundRejection(mode);\n if (reason !== null) {\n printError(reason);\n return 1;\n }\n return detachAfterConfirm(requested, noBranch, prReview, options);\n }\n\n // Ownership of the run, for the whole invocation — a queue is one run, not\n // one per issue. Two invocations in the same repository share a working tree\n // and a branch, so \"a different issue\" is not a different lock.\n const ownership = await claimRunOwnership(requested[0] as string, options.detachedChild === true);\n if (!ownership.ok) {\n printError(\n `Another issue-flow run owns this project: ${describeRunLockOwner(ownership.owner)}.`,\n );\n printInfo('Wait for it to finish, or stop that process before running again.');\n return 1;\n }\n\n try {\n const first = await runIssueSession(requested[0] as string, mode, {\n from,\n noBranch,\n prReview,\n requested,\n runOptions: options,\n ...(ownership.interruptedBy === null ? {} : { interruptedBy: ownership.interruptedBy }),\n });\n\n if (first.queue === undefined) {\n return first.code;\n }\n\n return runQueue(\n first.queue.plan,\n { mode, from, noBranch, prReview, runOptions: options },\n first.queue.resolved,\n );\n } finally {\n await ownership.release();\n }\n}\n\n/**\n * Phases that write to the repository — the working tree, the branch, or the\n * remote. The read-only ones (`init`, `prd`, `review`) produce artifacts under\n * the global storage and cannot be hurt by, nor hurt, a repository mid-rebase.\n */\nconst WRITING_PHASES: ReadonlySet<string> = new Set(['plan', 'execute', 'pr']);\n\n/**\n * Refuse to hand the repository to an agent while it is in a state a human has\n * to settle first.\n *\n * **Nothing is repaired here.** A rebase in progress, an unresolved conflict, a\n * detached HEAD or a branch that is not the plan's are reported with the\n * command that gets out of them, and the phase fails. That is the Epic's second\n * limit: no destructive operation is ever run automatically to fix state, and\n * \"the tool aborted my rebase overnight\" is exactly the outcome it forbids.\n *\n * Two of the checks are deliberately left to `resume` rather than run here:\n *\n * - a **dirty tree** does not block mid-pipeline, because the phases of one run\n * follow each other by design and uncommitted work between them is the\n * pipeline's own doing;\n * - the **branch** is not compared either, because within a run the `plan`\n * phase is what creates and checks it out, and a queue adopts a shared branch\n * after its own plan ran.\n *\n * `resume` reads both strictly, because there the repository may have been\n * touched by anything at all in between.\n */\nasync function ensureRepositoryWritable(phase: string): Promise<void> {\n if (!WRITING_PHASES.has(phase)) return;\n\n const preflight = await preflightRepository({ intent: 'resume-same-phase' });\n if (preflight.ok) return;\n\n for (const line of describePreflight(preflight)) {\n printError(line);\n }\n throw new Error(`The repository is not in a state the ${phase} phase can write to`);\n}\n\ntype RunOwnership =\n | { ok: true; interruptedBy: RunLock | null; release: () => Promise<void> }\n | { ok: false; owner: RunLock };\n\n/**\n * Take the project's run lock, or report who holds it.\n *\n * A project whose storage cannot be resolved at all (no git repository yet, no\n * home directory) runs **without** a lock rather than not running: the guard\n * exists to stop two runs from colliding, and it must never be the reason a\n * single run cannot start.\n */\nasync function claimRunOwnership(target: string, detached = false): Promise<RunOwnership> {\n let lockFile: string;\n try {\n lockFile = (await resolveProjectPaths()).runLockFile;\n } catch {\n return { ok: true, interruptedBy: null, release: async () => {} };\n }\n\n const result = await acquireRunLock(lockFile, { target, detached });\n if (!result.ok) return result;\n\n return {\n ok: true,\n interruptedBy: result.handle.reclaimedFrom,\n release: () => result.handle.release(),\n };\n}\n\ninterface IssueSessionInput {\n from?: string;\n noBranch?: boolean;\n prReview?: boolean;\n /** Identifiers the user asked for; only the standalone attempt needs them. */\n requested?: string[];\n runOptions?: RunPipelineOptions;\n queue?: QueueRunContext;\n /**\n * The dead owner whose lock this run took over. Recorded in the journal as\n * an interrupted run: something was executing here and never finished, and\n * that is the difference between a resume and a fresh start.\n */\n interruptedBy?: RunLock;\n}\n\n/**\n * Run one issue with its own session publisher and web monitor registration.\n *\n * This is the body `runPipeline` always had; a queue calls it once per issue,\n * which is what gives each of them its own `session.json` (and therefore its\n * own card in the monitor) inside a single process.\n */\nasync function runIssueSession(\n issueNumber: string,\n mode: string,\n input: IssueSessionInput,\n): Promise<IssueRunResult> {\n resetAgentInvocationState();\n // Resolved once, at the top: every phase that runs below shares the process\n // cache, so the git call and the legacy migration happen a single time for\n // the whole run instead of once per phase.\n const paths = await resolveIssuePaths(issueNumber);\n try {\n const project = await resolveProjectPaths();\n bindDiagnosticContext({\n project: project.projectId,\n projectRoot: await getProjectRoot(),\n issue: issueNumber,\n sessionId: null,\n executionId: null,\n phase: null,\n story: null,\n harness: null,\n model: null,\n });\n } catch {}\n\n // The `resilience` key, installed once for the whole run. Every `gh` call\n // below reads it synchronously (`getActiveResilienceConfig()`), so it has to\n // be in place before the first phase resolves the Issue — and the journal\n // decision below is the first thing that reads it. Absent configuration\n // leaves the base table, so this is a no-op for a project that configured\n // nothing.\n const resilience = await initResilienceConfig();\n\n // The watchdog budget, when the project configured one and the CLI did not\n // override it. A flag wins because it is the higher rung of the same ladder.\n const configuredInactivity = resilience.watchdog?.inactivityTimeoutMs;\n if (configuredInactivity !== undefined && getInactivityTimeout() === undefined) {\n setInactivityTimeout(configuredInactivity);\n }\n\n // Read per issue rather than cached for the process: the configuration is\n // per project and cheap to read, and a cached value would leak a `--web`\n // decision from one invocation into the next inside the same process.\n const webConfig = await loadWebConfig();\n\n // Two independent surfaces over one event stream: the snapshot the dashboard\n // reads, and the append-only journal an audit reads. Neither implies the\n // other — `--web` without a journal is the common case, and a journal\n // without `--web` is what an unattended run wants.\n const surfaces: SessionPublisher[] = [];\n const journalEnabled = resilience.journal?.enabled === true;\n const persistSnapshot = webConfig.enabled || input.runOptions?.detachedChild === true;\n if (persistSnapshot || journalEnabled) {\n // resolveIssuePaths never creates directories, and a run may well be the\n // first thing to touch this issue's global folder — so the writer creates\n // it. Only when a surface asked for it: with monitoring off and no journal\n // the pipeline still creates nothing at all (issue 25, US-009).\n await mkdir(paths.issueDir, { recursive: true });\n }\n if (persistSnapshot) {\n surfaces.push(\n new FilePublisher(paths.sessionFile, {\n logLimit: webConfig.logLimit,\n includeLogs: webConfig.includeLogs,\n }),\n );\n }\n if (journalEnabled) {\n surfaces.push(\n new JournalPublisher(paths.eventsFile, paths.rotatedEventsFile, {\n logLimit: webConfig.logLimit,\n includeLogs: webConfig.includeLogs,\n ...(resilience.journal?.maxFileBytes === undefined\n ? {}\n : { maxFileBytes: resilience.journal.maxFileBytes }),\n }),\n );\n }\n // The snapshot writer stays the primary surface, so `snapshot()` and\n // `version()` keep answering exactly what the dashboard answered before.\n // With no disk surface the reducer still runs in memory: the terminal\n // renders that snapshot, and US-009 is preserved because nothing is written.\n const publisher: SessionPublisher =\n surfaces.length === 0\n ? new MemoryPublisher()\n : surfaces.length === 1\n ? (surfaces[0] as SessionPublisher)\n : new MultiPublisher(surfaces);\n setSessionPublisher(publisher);\n\n // Recorded through the publisher rather than printed, so it lands in the\n // journal beside the events of the run that replaced it.\n if (input.interruptedBy !== undefined) {\n const previous = input.interruptedBy;\n publisher.publish({\n type: 'log',\n at: isoNow(),\n level: 'warn',\n message: `Previous run interrupted: ${describeRunLockOwner(previous)}. Its lock was stale and has been taken over.`,\n });\n }\n\n // A null handle (port in use, ...) means the pipeline runs without a server.\n // ensureWebMonitor reuses an already-running, healthy instance instead of\n // binding a second one (US-001), or spawns it detached when none exists\n // (US-002) — either way the returned handle never owns a local server that\n // this process would need to close.\n if (webConfig.enabled) {\n await ensureWebMonitor({\n publisher,\n port: webConfig.port,\n host: webConfig.host,\n refreshSeconds: webConfig.refreshSeconds,\n });\n }\n\n let result: IssueRunResult = {\n code: 1,\n failedPhase: null,\n branchName: null,\n storyCount: 0,\n elapsedSeconds: 0,\n };\n\n // What a `Ctrl+C` leaves behind. Registered for the duration of this issue\n // only — a queue runs several, and each must checkpoint its own plan — and\n // deliberately split across the two shutdown phases: the state is written\n // while the agent is still alive, and the surfaces are closed after it is\n // gone, so nothing the checkpoint published is lost on the way out.\n const releaseCheckpoint = onShutdown({\n phase: 'checkpoint',\n run: async () => {\n await pauseIssue(paths.tasksFile, issueNumber);\n publisher.publish({\n type: 'log',\n at: isoNow(),\n level: 'warn',\n message: `Interrupted during issue #${issueNumber}. A checkpoint was saved; resume with \\`issue-flow resume ${issueNumber}\\`.`,\n });\n publisher.publish({ type: 'session:end', at: isoNow(), status: 'failed' });\n },\n });\n const releaseClose = onShutdown({\n phase: 'close',\n run: async () => {\n await publisher.close();\n },\n });\n\n try {\n result = await runPipelinePhases(issueNumber, paths, mode, publisher, input);\n if (result.code !== 0) {\n await reportIfOversized(issueNumber, paths, result);\n }\n return result;\n } finally {\n releaseCheckpoint();\n releaseClose();\n // A run that only decided to become a queue published nothing: closing the\n // session here would write a `session.json` for a pipeline that never ran.\n if (result.queue === undefined) {\n publisher.publish({\n type: 'session:end',\n at: isoNow(),\n status: result.code === 0 ? 'completed' : 'failed',\n });\n }\n // The web monitor is no longer this process's to close (US-002): it is a\n // detached, single machine-wide instance meant to outlive the pipeline\n // and serve other invocations. Only this run's own publication ends here.\n await publisher.close();\n writeDiagnostic({\n level: result.code === 0 ? 'info' : 'error',\n message: `Issue Flow session ${result.code === 0 ? 'completed' : 'failed'}`,\n context: { code: result.code, failedPhase: result.failedPhase },\n });\n await flushDiagnostics();\n setSessionPublisher(undefined);\n }\n}\n\n/**\n * Write a decomposition report when the failure looks like \"too much work\",\n * and say nothing when it does not.\n *\n * The guard that matters is the one *before* the assessment: a run that died\n * because the network went down is not too large, and reacting to that with\n * \"have you considered splitting this issue?\" is worse than silence. Only a\n * failure the resilience layer could not absorb — and that carries at least two\n * independent size signals — gets a report.\n *\n * Nothing is split here. The report is written and the issue is marked\n * `blocked` with a pointer to it, because splitting an issue is a product\n * decision and the tool does not get to make it.\n */\nasync function reportIfOversized(\n issueNumber: string,\n paths: IssuePaths,\n result: IssueRunResult,\n): Promise<void> {\n try {\n const journal = `${await readFileIfPresent(paths.rotatedEventsFile)}${await readFileIfPresent(paths.eventsFile)}`;\n const plan = await loadTaskPlan(paths.tasksFile).catch(() => null);\n\n const assessment = assessDecomposition({\n journal,\n plan,\n filesTouched: await countChangedFiles(),\n hitMaxIterations: result.failedPhase === 'execute' && plan?.issueStatus !== 'completed',\n });\n if (!assessment.oversized) return;\n\n const report = buildDecompositionReport({\n issueNumber,\n assessment,\n plan,\n at: isoNow(),\n });\n const reportFile = paths.decompositionFile;\n await mkdir(paths.issueDir, { recursive: true });\n await writeFile(reportFile, report, 'utf-8');\n\n printWarning(`Issue #${issueNumber} looks larger than one run. Report: ${reportFile}`);\n for (const signal of assessment.signals) {\n printWarning(` ${signal.detail}`);\n }\n\n await maybeCreateSubIssues(issueNumber, plan, reportFile);\n\n if (plan !== null) {\n await saveTaskPlan(paths.tasksFile, {\n ...plan,\n runState: {\n currentPhase: plan.runState?.currentPhase ?? result.failedPhase,\n attempt: plan.runState?.attempt ?? 0,\n owner: null,\n status: 'blocked',\n blockedReason: `Looks larger than one run; see ${reportFile}`,\n lastHeartbeatAt: isoNow(),\n },\n });\n }\n } catch {\n // A report is a courtesy. Failing to write one must not change the exit\n // code of a run that already failed for its own reasons.\n }\n}\n\n/**\n * Create the proposed sub-issues, but only when asked and only when it is safe.\n *\n * Two conditions, and the second is the one that matters: `--auto-decompose`\n * has to be on, **and** the branch must carry no committed story yet. Splitting\n * an issue whose work is half done leaves commits that belong to no issue and\n * sub-issues that describe work already merged — a mess nobody asked for, made\n * automatically at 3am. With commits present the report still stands; only the\n * acting stops.\n */\nasync function maybeCreateSubIssues(\n issueNumber: string,\n plan: TaskPlan | null,\n reportFile: string,\n): Promise<void> {\n if (getActiveResilienceConfig().decompose?.auto !== true) {\n printInfo(`Nothing was split. Read ${reportFile} and decide.`);\n return;\n }\n\n const committed = await committedStoryIds(await getBaseBranch()).catch(() => new Set<string>());\n if (committed.size > 0) {\n printWarning(\n `--auto-decompose did not run: ${committed.size} story(ies) are already committed on this branch. ` +\n 'Splitting on top of committed work needs a person.',\n );\n return;\n }\n\n const proposals = proposeSubIssues(plan);\n if (proposals.length === 0) {\n printInfo('Nothing left to split: no pending story.');\n return;\n }\n\n const { runGenerate } = await import('./generate.js');\n for (const proposal of proposals) {\n const instruction = [\n `Create a sub-issue of #${issueNumber}: ${proposal.title}.`,\n proposal.dependsOn.length === 0 ? '' : `It depends on: ${proposal.dependsOn.join(', ')}.`,\n 'It covers exactly these user stories, and nothing else:',\n ...proposal.stories.map((story) => `- ${story.id} ${story.title}: ${story.description}`),\n ]\n .filter((line) => line !== '')\n .join('\\n');\n\n const code = await runGenerate(instruction);\n if (code !== 0) {\n printWarning(\n `Could not create \"${proposal.title}\". The report at ${reportFile} still stands.`,\n );\n return;\n }\n }\n}\n\n/** Files changed on this branch, or `0` when git cannot say. */\nasync function countChangedFiles(): Promise<number> {\n try {\n const base = await getBaseBranch();\n const result = await run('git', ['diff', '--name-only', `${base}...HEAD`]);\n if (result.exitCode !== 0) return 0;\n return result.stdout.split('\\n').filter((line) => line.trim() !== '').length;\n } catch {\n return 0;\n }\n}\n\nasync function readFileIfPresent(path: string): Promise<string> {\n try {\n return await readFile(path, 'utf-8');\n } catch {\n return '';\n }\n}\n\n/**\n * Mark an interrupted issue as paused, in the one place resumption reads.\n *\n * `pipeline` still says which phases finished — that is what `resume` continues\n * from — and `runState` is what says *why* the run is not running: paused by a\n * person, not failed, not still going. Before this field, a `Ctrl+C` left\n * `issueStatus: 'in_progress'` and nothing else, and the difference between\n * \"someone stopped it\" and \"it died\" was unrecoverable.\n *\n * Never throws: a checkpoint that cannot be written must not stop the rest of\n * the shutdown, and the phases already marked complete are still on disk.\n */\nasync function pauseIssue(tasksFile: string, issueNumber: string): Promise<void> {\n try {\n const plan = await loadTaskPlan(tasksFile);\n await saveTaskPlan(tasksFile, {\n ...plan,\n runState: {\n ...(plan.runState ?? {\n currentPhase: null,\n attempt: 0,\n lastHeartbeatAt: null,\n blockedReason: null,\n owner: null,\n }),\n status: 'paused',\n lastHeartbeatAt: isoNow(),\n },\n });\n } catch {\n // No plan yet (interrupted before the `plan` phase), or an unreadable one.\n printWarning(`Could not write a checkpoint for issue #${issueNumber}.`);\n }\n}\n\nasync function runPipelinePhases(\n issueNumber: string,\n paths: IssuePaths,\n mode: string,\n publisher: SessionPublisher,\n input: IssueSessionInput,\n): Promise<IssueRunResult> {\n const { from, noBranch, prReview, queue } = input;\n // User Story numbering flags (issue #36). `--start-us` names a starting\n // point, so the queue only ever hands it to the first issue it runs —\n // applying it to each one would give them all the same ids, the very\n // collision #36 set out to remove. Every later issue continues from history,\n // which by then already includes the plans written earlier in this run.\n const continueNumbering = input.runOptions?.continueNumbering;\n const startUs = input.runOptions?.startUs;\n // Retry budget of the `execute` phase (`--retry-limit`, `--retry-forever`).\n // Left `undefined` when the flags are absent so `createConfig()` applies the\n // engine defaults — passing a number here would make `run` diverge from\n // `execute` the moment one of those defaults changes.\n const executeRetry = {\n retryLimit: input.runOptions?.retryLimit,\n retryForever: input.runOptions?.retryForever,\n };\n const tasksPath = paths.tasksFile;\n const sessionId = randomUUID();\n bindDiagnosticContext({\n sessionId,\n issue: issueNumber,\n executionId: null,\n phase: null,\n story: null,\n harness: null,\n model: null,\n });\n const [initialBranch, initialCommit] = await Promise.all([\n getCurrentBranch().catch(() => ''),\n getHeadCommit(),\n ]);\n\n // Refined with the provider's own number once the Issue is resolved.\n let publishedIssueNumber = toIssueNumber(issueNumber);\n\n const publishSessionStart = (\n phases: readonly string[],\n at: string,\n info?: {\n issueUrl?: string;\n branch?: string;\n branchCreated?: boolean | null;\n startCommit?: string | null;\n },\n ): void => {\n publisher.publish({\n type: 'session:start',\n at,\n sessionId,\n issueNumber: publishedIssueNumber,\n issueUrl: info?.issueUrl,\n branch: info?.branch,\n branchCreated: info?.branchCreated,\n startCommit: info?.startCommit,\n phases: [...phases],\n configuration: configurationSnapshot,\n environment: {\n node: process.version,\n platform: process.platform,\n agent: agentSummary.defaultProvider,\n model: agentSummary.defaultModel,\n },\n });\n };\n\n const agentSummary = await describeRunAgents(\n prReview\n ? ['prd', 'plan', 'execute', 'review', 'pr', 'pr-review']\n : ['prd', 'plan', 'execute', 'review', 'pr'],\n );\n const fallbacks = getActiveResilienceConfig().providers?.chain ?? [];\n const configurationSnapshot: SessionConfigurationSnapshot = {\n precedence: ['default', 'global', 'project', 'env', 'cli', 'step override'],\n defaultProvider: {\n value: agentSummary.defaultProvider,\n source: agentSummary.defaultOrigin.provider,\n },\n defaultModel: {\n value: agentSummary.defaultModel,\n source: agentSummary.defaultOrigin.model,\n },\n phases: Object.entries(agentSummary.byPhase).map(([phase, resolved]) => ({\n phase,\n provider: { value: resolved.provider, source: resolved.origin.provider },\n model: { value: resolved.model, source: resolved.origin.model },\n })),\n fallbacks,\n overrides: Object.entries(agentSummary.byPhase)\n .filter(\n ([, resolved]) =>\n resolved.provider !== agentSummary.defaultProvider ||\n resolved.model !== agentSummary.defaultModel,\n )\n .map(\n ([phase, resolved]) =>\n `${phase}: ${resolved.provider}${resolved.model ? ` · ${resolved.model}` : ''}`,\n ),\n };\n printInfo(\n `Starting pipeline for issue #${issueNumber} (mode: ${mode}, agent: ${agentSummary.label})`,\n );\n\n // Loaded before the checks so init knows which origin the user is heading\n // for: with a local one, a missing gh must not fail the environment.\n const issuesConfig = await loadIssuesConfig();\n\n // Phase 1: Init check. Inside a queue it already ran for the whole run, so\n // the environment is not probed once per issue — the phase is still\n // published, keeping every issue's session shape identical.\n const sessionStartedAt = isoNow();\n if (queue?.preChecked !== true) {\n if (isVerbose()) {\n printInfo('Running prerequisite checks...');\n }\n const initCode = await runInit(issuesConfig.preferredProvider, { compact: !isVerbose() });\n if (initCode !== 0) {\n publishSessionStart(PIPELINE_PHASES, sessionStartedAt);\n publisher.publish({ type: 'phase:start', at: sessionStartedAt, phase: 'init' });\n publisher.publish({\n type: 'phase:end',\n at: isoNow(),\n phase: 'init',\n success: false,\n error: 'Prerequisites not met',\n });\n printError('Prerequisites not met. Fix the issues above and try again.');\n return failure(1);\n }\n }\n\n // The origin is settled once, here, and the decision travels to every phase.\n // Resolving per phase would query the providers five times and could ask the\n // user about the same divergence five times.\n const resolution = await resolveCommandIssue(issueNumber, queue?.resolved, {\n config: issuesConfig,\n });\n if (!resolution.ok) {\n return failure(resolution.code);\n }\n const resolvedIssue = resolution.resolved;\n publishedIssueNumber = resolvedIssue.issue.number;\n\n // Everything above is what a queue needs to exist: prerequisites checked and\n // the primary Issue resolved, but not a single phase run and not a single\n // event published. This is where a run learns it is really a queue.\n if (queue === undefined) {\n const decision = await decideQueue({\n requested: input.requested ?? [issueNumber],\n resolved: resolvedIssue,\n noBranch: noBranch ?? false,\n prReview: prReview ?? false,\n runOptions: input.runOptions ?? {},\n });\n if (decision.kind === 'stop') {\n return failure(decision.code);\n }\n if (decision.kind === 'queue') {\n return {\n ...failure(0),\n queue: { plan: decision.plan, resumed: decision.resumed, resolved: resolvedIssue },\n };\n }\n }\n\n // Resolve noBranch mode: persisted value takes precedence on resume\n let effectiveNoBranch = noBranch ?? false;\n // Resolve pr-review mode: flag > persisted value > default (off). Unlike\n // --no-branch, the flag wins: the phase adds a step at the end instead of\n // changing what the earlier phases did, so opting in on resume is safe.\n let effectivePrReview = prReview ?? false;\n let planIssueUrl: string | undefined;\n let planBranch: string | undefined;\n // Kept from the same read as planIssueUrl/planBranch — seeding the snapshot\n // must not cost a second trip to disk.\n let planStories: UserStory[] = [];\n try {\n const existingPlan = await loadTaskPlan(tasksPath);\n const persistedNoBranch = existingPlan.noBranch ?? false;\n planIssueUrl = existingPlan.issueUrl || undefined;\n planBranch = existingPlan.branchName || undefined;\n planStories = existingPlan.userStories;\n effectivePrReview = prReview ?? existingPlan.prReview?.enabled ?? false;\n\n // Only warn when the user explicitly passed a flag that conflicts with the persisted value\n if (noBranch !== undefined && noBranch !== persistedNoBranch) {\n if (persistedNoBranch) {\n printWarning(\n 'This pipeline was started with --no-branch. Ignoring current flag; using persisted mode.',\n );\n } else {\n printWarning(\n 'This pipeline was started without --no-branch. Ignoring current flag; using persisted mode.',\n );\n }\n }\n\n // Persisted mode wins on resume\n effectiveNoBranch = persistedNoBranch;\n } catch {\n // No tasks.json yet — use the CLI flag as-is\n }\n\n // The CLI rejects --pr-review with --no-branch, but the persisted no-branch\n // mode can only be known here. Without a pr phase there is no Pull Request\n // to review, so the opt-in is dropped instead of failing a resumed run.\n if (effectiveNoBranch && effectivePrReview) {\n printWarning(\n 'This pipeline runs with --no-branch and opens no PR. Skipping the pr-review phase.',\n );\n effectivePrReview = false;\n }\n\n // Persist the opt-in as soon as we know it, not only after the `plan` phase.\n // A mid-pipeline `--pr-review` (e.g. `--from pr --pr-review`) never re-enters\n // the plan runner, and without `enabled: true` a later resume without the flag\n // would drop the phase even when `prReviewCompleted` is still false.\n if (effectivePrReview) {\n try {\n const plan = await loadTaskPlan(tasksPath);\n if (plan.prReview?.enabled !== true) {\n plan.prReview = { ...plan.prReview, enabled: true, rounds: plan.prReview?.rounds ?? 0 };\n await saveTaskPlan(tasksPath, plan);\n }\n } catch {\n // No tasks.json yet — the plan runner persists it after creating the file.\n }\n }\n\n // Inside a queue the Pull Request is opened once, after the last issue, so\n // `pr` (and with it `pr-review`) leaves the per-issue phase list. The list is\n // the same one `--no-branch` uses, but the branch is still created: what\n // changes is who opens the Pull Request, not whether there is a branch.\n const inQueue = queue !== undefined;\n // The queue's last pass implements nothing: it only opens the single Pull\n // Request that covers every issue already committed to the shared branch.\n const finalPr = queue?.finalPr;\n const activePhases = finalPr\n ? effectivePrReview\n ? QUEUE_PR_PHASES_WITH_REVIEW\n : QUEUE_PR_PHASES\n : inQueue\n ? PIPELINE_PHASES_NO_BRANCH\n : effectiveNoBranch\n ? PIPELINE_PHASES_NO_BRANCH\n : effectivePrReview\n ? PIPELINE_PHASES_WITH_PR_REVIEW\n : PIPELINE_PHASES;\n const phaseOrder = finalPr\n ? effectivePrReview\n ? RUNNABLE_QUEUE_PR_PHASES_WITH_REVIEW\n : RUNNABLE_QUEUE_PR_PHASES\n : inQueue\n ? RUNNABLE_PHASES_NO_BRANCH\n : effectiveNoBranch\n ? RUNNABLE_PHASES_NO_BRANCH\n : effectivePrReview\n ? RUNNABLE_PHASES_WITH_PR_REVIEW\n : RUNNABLE_PHASES;\n\n // Commit scope for this issue's stories: only a queue needs one, because\n // only there do several issues share a branch (and therefore a `git log`).\n const queueCommitScope = queue === undefined ? undefined : `issue-${issueNumber}`;\n // Branch this issue will work on, reported back so the queue can adopt the\n // first issue's choice for every later one.\n let producedBranch: string | null = null;\n let plannedExecutionBranch: string | null = planBranch ?? null;\n let branchExistedBeforeExecution =\n effectiveNoBranch || planBranch === undefined || planBranch === null\n ? null\n : await localBranchExists(planBranch).catch(() => null);\n\n // Adopted **before** the phases run, not only after `plan`: an issue whose\n // plan phase is already complete (it was run standalone before joining the\n // queue, or the queue is being resumed) never re-enters the plan runner, and\n // would otherwise send `execute` at a branch of its own.\n if (queue !== undefined && finalPr === undefined && !effectiveNoBranch) {\n producedBranch = await adoptQueueBranch(tasksPath, queue.plan.branchName);\n if (producedBranch !== null) {\n planBranch = producedBranch;\n }\n }\n\n // The phase list is only known after resolving --no-branch, so the init\n // phase (which already ran) is published retroactively with real timestamps.\n publishSessionStart(activePhases, sessionStartedAt, {\n issueUrl: planIssueUrl ?? resolvedIssue.issue.remoteRef ?? undefined,\n branch: effectiveNoBranch ? initialBranch : planBranch,\n branchCreated: effectiveNoBranch ? false : branchExistedBeforeExecution === true ? false : null,\n startCommit: initialCommit,\n });\n // Right after session:start (which resets the snapshot) and before any phase\n // event, so the first /api/status poll already answers with the Issue and\n // the plan.\n publishIssueDetails(publisher, resolvedIssue.issue, sessionStartedAt);\n publishStorySeed(publisher, planStories, sessionStartedAt);\n publisher.publish({ type: 'phase:start', at: sessionStartedAt, phase: 'init' });\n publisher.publish({ type: 'phase:end', at: isoNow(), phase: 'init', success: true });\n await publishGitState(publisher);\n\n // Determine starting phase\n let startPhase: PipelinePhase = 'prd';\n if (from) {\n if (!(activePhases as readonly string[]).includes(from)) {\n const validPhases = activePhases.filter((p) => p !== 'init').join(', ');\n // Check if the phase exists in the full set but is excluded by --no-branch\n if (effectiveNoBranch && (PIPELINE_PHASES as readonly string[]).includes(from)) {\n printError(\n `The '${from}' phase is not available in --no-branch mode. Valid phases: ${validPhases}`,\n );\n } else {\n printError(`Invalid phase: ${from}. Valid phases: ${validPhases}`);\n }\n return failure(1);\n }\n startPhase = from as PipelinePhase;\n } else {\n // Try to auto-resume from pipeline state\n try {\n const plan = await loadTaskPlan(tasksPath);\n const mgr = new PipelineManager(plan, tasksPath, activePhases);\n const nextPhase = mgr.getNextPhase();\n if (nextPhase && nextPhase !== 'init') {\n startPhase = nextPhase;\n printInfo(`Resuming from phase: ${startPhase}`);\n }\n } catch {\n // No tasks.json yet — start from beginning\n }\n }\n\n // Validate resume prerequisites if starting from a later phase\n if (from) {\n try {\n const plan = await loadTaskPlan(tasksPath);\n const mgr = new PipelineManager(plan, tasksPath, activePhases);\n if (!mgr.canResume(startPhase)) {\n printError(`Cannot resume from ${startPhase}: prerequisite phases not complete`);\n return failure(1);\n }\n } catch {\n if (startPhase !== 'prd') {\n printError(`Cannot resume from ${startPhase}: no pipeline state found`);\n return failure(1);\n }\n }\n }\n\n // A phase that is not part of this run's list (the closing pass of a queue\n // runs only `pr`) starts the renderer at the beginning rather than at -1.\n const startIdx = Math.max(phaseOrder.indexOf(startPhase), 0);\n\n // Build phase runner functions that throw on failure\n const makeRunner = (fn: () => Promise<number>, phase: string) => async () => {\n await ensureRepositoryWritable(phase);\n const code = await fn();\n if (code !== 0) {\n throw new Error(`Phase ${phase} failed with exit code ${code}`);\n }\n };\n\n const runners: Record<string, () => Promise<void>> = {\n prd: makeRunner(() => runPrd(issueNumber, resolvedIssue), 'prd'),\n plan: async () => {\n await makeRunner(\n () =>\n runPlan(issueNumber, resolvedIssue, {\n continueFlag: continueNumbering,\n startUs,\n ...(effectiveNoBranch && initialBranch ? { branchName: initialBranch } : {}),\n }),\n 'plan',\n )();\n // Read the newly-created plan once: publish its stories immediately so\n // the first execute iteration never points at a story absent from the\n // snapshot, and persist phase-selection modes from the same object.\n try {\n const plan = await loadTaskPlan(tasksPath);\n if (!effectiveNoBranch) {\n plannedExecutionBranch = plan.branchName;\n branchExistedBeforeExecution = await localBranchExists(plan.branchName).catch(() => null);\n publisher.publish({\n type: 'git:update',\n at: isoNow(),\n branchCreated: branchExistedBeforeExecution === true ? false : null,\n });\n }\n publishStorySeed(publisher, plan.userStories, isoNow());\n if (effectiveNoBranch || effectivePrReview) {\n if (effectiveNoBranch) plan.noBranch = true;\n if (effectivePrReview) {\n plan.prReview = { ...plan.prReview, enabled: true, rounds: plan.prReview?.rounds ?? 0 };\n }\n await saveTaskPlan(tasksPath, plan);\n }\n } catch {\n /* non-critical: tasks.json may not exist yet if plan phase didn't create it */\n }\n // A queue shares one branch: the first issue's plan decides it, every\n // later issue has it written over whatever slug the agent derived from\n // its own title. The `execute` prompt then finds the branch already\n // checked out instead of creating a second one — the creation logic\n // itself is untouched.\n if (queue !== undefined && !effectiveNoBranch) {\n producedBranch = await adoptQueueBranch(tasksPath, queue.plan.branchName);\n }\n },\n execute: makeRunner(\n () =>\n runExecute(undefined, {\n issue: issueNumber,\n commitScope: queueCommitScope,\n ...executeRetry,\n }),\n 'execute',\n ),\n review: async () => {\n // Read maxCorrectionCycles\n let maxCycles = 3;\n try {\n const plan = await loadTaskPlan(tasksPath);\n maxCycles = plan.maxCorrectionCycles;\n } catch {\n /* use default */\n }\n\n let code = await runReview(issueNumber, resolvedIssue);\n\n // Auto-correction loop on failure\n let cycle = 0;\n while (code !== 0 && cycle < maxCycles) {\n cycle++;\n printWarning(`Review failed. Starting correction cycle ${cycle}/${maxCycles}...`);\n publisher.publish({ type: 'correction:cycle', at: isoNow(), cycle, maxCycles });\n\n // Update correction cycle in tasks.json\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.correctionCycle = cycle;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n /* non-critical */\n }\n\n // Re-execute\n const execCode = await runExecute(undefined, {\n issue: issueNumber,\n commitScope: queueCommitScope,\n ...executeRetry,\n });\n if (execCode !== 0) {\n throw new Error('Correction execution failed');\n }\n\n // Re-review\n code = await runReview(issueNumber, resolvedIssue);\n }\n\n if (code !== 0) {\n throw new Error(`Review failed after ${maxCycles} correction cycles`);\n }\n },\n pr: makeRunner(\n // The options argument is omitted outside a queue so a standalone run\n // calls `runPr` exactly as it always did.\n () =>\n finalPr === undefined\n ? runPr(issueNumber, resolvedIssue)\n : runPr(issueNumber, resolvedIssue, { queue: finalPr }),\n 'pr',\n ),\n };\n\n // Filled by the pr-review runner; read after the pipeline finishes. Held in a\n // box because a `let` written only inside a closure keeps its initial `null`\n // narrowing at the read site.\n const reviewBox: { outcome: PrReviewOutcome | null } = { outcome: null };\n if (effectivePrReview) {\n runners['pr-review'] = async () => {\n // `yes` because the run is autonomous: the phase must never stop to ask\n // which Pull Request it is reviewing.\n const code = await runPrReview(undefined, { issue: issueNumber, yes: true });\n if (code === 1) {\n throw new Error('Phase pr-review failed with exit code 1');\n }\n // Exit code 2 is a verdict, not a failure: the review ran, the report is\n // on disk and the pipeline keeps going.\n reviewBox.outcome = await readPrReviewOutcome(issueNumber, tasksPath, code === 2);\n };\n }\n\n // Publish phase:start/phase:end around every runner without touching the\n // listr2 renderer (pipeline-renderer.ts stays publication-free). Commit/PR\n // enrichment happens only at these boundaries (and at iteration end, in\n // engine.ts) — never per HTTP request.\n const instrumentedRunners = Object.fromEntries(\n Object.entries(runners).map(([phase, fn]) => [\n phase,\n async () => {\n publisher.publish({ type: 'phase:start', at: isoNow(), phase });\n try {\n await fn();\n if (\n phase === 'execute' &&\n branchExistedBeforeExecution === false &&\n plannedExecutionBranch !== null &&\n (await getCurrentBranch().catch(() => '')) === plannedExecutionBranch\n ) {\n publisher.publish({ type: 'git:update', at: isoNow(), branchCreated: true });\n }\n await publishGitState(publisher);\n await publishInstrumentedPhaseEnd(publisher, phase, issueNumber, true);\n } catch (err) {\n await publishGitState(publisher);\n await publishInstrumentedPhaseEnd(\n publisher,\n phase,\n issueNumber,\n false,\n err instanceof Error ? err.message : String(err),\n );\n throw err;\n }\n },\n ]),\n );\n\n // Run pipeline with listr2 renderer — startup header printed above, summary below\n const phaseSuffixes: Record<string, string> = {};\n for (const [phase, resolved] of Object.entries(agentSummary.byPhase)) {\n if (resolved.provider !== agentSummary.defaultProvider) {\n phaseSuffixes[phase] = resolved.model\n ? `${resolved.provider} · ${resolved.model}`\n : resolved.provider;\n }\n }\n\n const result = await runPipelineWithRenderer({\n phases: phaseOrder,\n startIndex: startIdx,\n verbose: isVerbose(),\n runners: instrumentedRunners,\n tasksPath,\n phaseSuffixes,\n });\n\n if (!result.success) {\n printError(`Phase ${result.failedPhase} failed`);\n return {\n ...failure(1),\n failedPhase: result.failedPhase ?? null,\n branchName: producedBranch,\n elapsedSeconds: result.overallElapsedSeconds,\n };\n }\n\n // A PR review asking for changes is not a pipeline failure, but the work is\n // not done either: the warning is highlighted and the issue stays open.\n const review = reviewBox.outcome;\n if (review?.requestedChanges) {\n console.log('');\n printWarning('PR review requested changes — the Pull Request is not ready to merge.');\n if (review.reportPath !== null) {\n console.log(` Report: ${review.reportPath}`);\n }\n }\n\n // Close the issue through whoever owns it. A provider without close() (a\n // read-only origin) has nothing to do here, so the step is simply skipped.\n // REQUEST_CHANGES also leaves the local plan unfinished: marking\n // `issueStatus: completed` while `prReviewCompleted` is false would lie to\n // every tool that keys off the local status.\n // Inside a queue the issues are closed once, after the consolidated Pull\n // Request: closing one here would announce it as done while the branch that\n // carries its work has not even been proposed yet.\n if (review?.requestedChanges) {\n printInfo('Issue left open until the review blockers are addressed.');\n } else if (!inQueue) {\n await closeIssue(issueNumber, resolvedIssue.source);\n }\n\n // Get branch and story count\n let branchName = 'unknown';\n try {\n const proc = await execa('git', ['branch', '--show-current'], { reject: false });\n branchName = proc.stdout?.toString().trim() ?? 'unknown';\n } catch {\n /* non-critical */\n }\n\n let storyCount = 0;\n let planPrUrl: string | null = null;\n try {\n const plan = await loadTaskPlan(tasksPath);\n storyCount = plan.userStories.length;\n // The `pr` phase records the Pull Request it opened; trusting it spares a\n // round-trip to the GitHub CLI below.\n planPrUrl = plan.pullRequest?.url ?? null;\n\n plan.lastAttemptAt = isoNow();\n if (!review?.requestedChanges) {\n plan.issueStatus = 'completed';\n plan.completedAt = isoNow();\n }\n await saveTaskPlan(tasksPath, plan);\n } catch {\n /* non-critical */\n }\n\n // Inside a queue the run is not over: the summary, the Pull Request and the\n // totals belong to the queue, which prints them once at the end.\n if (inQueue) {\n if (finalPr === undefined) {\n printSuccess(`Issue #${issueNumber} completed (${storyCount} stories).`);\n }\n return {\n code: 0,\n failedPhase: null,\n branchName: producedBranch ?? (branchName === 'unknown' ? null : branchName),\n storyCount,\n elapsedSeconds: result.overallElapsedSeconds,\n review,\n };\n }\n\n // Get PR URL for summary. Only GitHub-hosted Issues have a pull request to\n // look up, and --no-branch never opens one. Falling back to the GitHub CLI\n // uses the branch actually checked out: a query without a head branch would\n // return an unrelated Pull Request.\n let prUrl = 'unknown';\n if (!effectiveNoBranch && resolvedIssue.source === 'github') {\n if (planPrUrl !== null) {\n prUrl = planPrUrl;\n } else if (branchName !== 'unknown' && branchName !== '') {\n try {\n const latest = mostRecent(await listPullRequests(branchName));\n if (latest !== null) {\n prUrl = latest.url;\n }\n } catch {\n /* non-critical */\n }\n }\n }\n\n printRunSummary({\n issueNumber,\n branchName,\n noBranch: effectiveNoBranch,\n storyCount,\n elapsedSeconds: result.overallElapsedSeconds,\n prUrl,\n prReview: review,\n // Process-owned counters: the session snapshot is empty whenever web\n // monitoring is off, so it cannot be the source of these totals.\n usage: getRunUsageTotals(),\n verification: verificationForSummary(getSessionPublisher().snapshot().verification),\n });\n\n return {\n code: 0,\n failedPhase: null,\n branchName: branchName === 'unknown' ? null : branchName,\n storyCount,\n elapsedSeconds: result.overallElapsedSeconds,\n };\n}\n\ninterface DecideQueueInput {\n requested: string[];\n resolved: ResolvedIssue;\n noBranch: boolean;\n prReview: boolean;\n runOptions: RunPipelineOptions;\n}\n\n/**\n * Ask the planner whether this invocation is a queue, resolving the storage\n * paths it needs.\n *\n * A failure here degrades to a single-issue run when only one issue was asked\n * for — discovery is an enrichment, and losing it must never cost the user the\n * pipeline. With several issues informed there is nothing to degrade to: the\n * user asked for a queue, so the error is reported and the run stops.\n */\n/**\n * Confirm the queue (if needed) and spawn the same command without `--background`.\n * The child acquires the lock with `detached: true` and writes `run.log`.\n */\nasync function detachAfterConfirm(\n requested: string[],\n noBranch: boolean | undefined,\n prReview: boolean | undefined,\n options: RunPipelineOptions,\n): Promise<number> {\n const childFlags = [...process.argv.slice(2)];\n if (options.yes !== true && options.only !== true) {\n try {\n const issuesConfig = await loadIssuesConfig();\n const resolution = await resolveCommandIssue(requested[0] as string, undefined, {\n config: issuesConfig,\n });\n if (resolution.ok) {\n const decision = await decideQueue({\n requested,\n resolved: resolution.resolved,\n noBranch: noBranch ?? false,\n prReview: prReview ?? false,\n runOptions: options,\n });\n if (decision.kind === 'stop') return decision.code;\n if (decision.kind === 'queue' && !childFlags.includes('--yes')) childFlags.push('--yes');\n if (decision.kind === 'single' && !childFlags.includes('--only')) childFlags.push('--only');\n }\n } catch {\n // Discovery is an enrichment; a detach still starts the run that was asked for.\n }\n }\n\n const paths = await resolveIssuePaths(requested[0] as string);\n const { pid, logFile } = await spawnDetachedRun({ paths, argv: childFlags });\n printSuccess(`Detached run started (pid ${pid}).`);\n printInfo(`Log: ${logFile}`);\n printInfo('Follow with: issue-flow ps');\n printInfo(`Stop with: kill ${pid}`);\n return 0;\n}\n\nasync function decideQueue(input: DecideQueueInput): Promise<QueueDecision> {\n const primary = input.requested[0] as string;\n const single = input.requested.length === 1;\n\n if (single && input.runOptions.only === true) {\n return { kind: 'single' };\n }\n\n try {\n const [project, queuePaths] = await Promise.all([\n resolveProjectPaths(),\n resolveQueuePaths(primary),\n ]);\n\n return await planQueue({\n requested: input.requested,\n source: input.resolved.source,\n known: [input.resolved.issue],\n projectId: project.projectId,\n planFile: queuePaths.planFile,\n noBranch: input.noBranch,\n prReview: input.prReview,\n confirm: {\n yes: input.runOptions.yes,\n only: input.runOptions.only,\n cascade: input.runOptions.cascade,\n },\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (single) {\n printWarning(\n `Could not inspect related issues (${message}). Running issue #${primary} alone.`,\n );\n return { kind: 'single' };\n }\n printError(`Could not plan the execution of ${input.requested.length} issues: ${message}`);\n return { kind: 'stop', code: 1 };\n }\n}\n\n/**\n * Run a queue of issues: one shared branch, one process, one issue at a time.\n *\n * Each issue goes through the very same phases a single-issue run does\n * (`prd` → `plan` → `execute` → `review`), with its own `tasks.json`, its own\n * session and its own usage scope. The queue owns only what is shared: the\n * order, the branch, the Pull Request and the consolidated totals.\n *\n * A failure stops the queue where it happened, records the issue and the phase,\n * and leaves every commit and the branch exactly as they are — the next\n * invocation resumes from the failed issue without redoing the ones before it.\n */\nasync function runQueue(\n initialPlan: ExecutionPlan,\n options: {\n mode: string;\n from?: string;\n noBranch?: boolean;\n prReview?: boolean;\n runOptions?: RunPipelineOptions;\n },\n resolvedPrimary?: ResolvedIssue,\n): Promise<number> {\n const planFile = (await resolveQueuePaths(initialPlan.id)).planFile;\n let plan = initialPlan;\n\n const queueUsage = beginUsageScope();\n const startedAtMs = Date.now();\n const summaries: QueueIssueSummary[] = [];\n let firstOfThisRun = true;\n\n const resilience = getActiveResilienceConfig();\n const failureMode: QueueFailureMode =\n options.runOptions?.onIssueFailure ??\n (resilience.queue?.onIssueFailure as QueueFailureMode | undefined) ??\n 'stop';\n const maxIssueAttempts = resilience.queue?.maxIssueAttempts ?? DEFAULT_MAX_ISSUE_ATTEMPTS;\n\n // Ids this invocation is done with. Without it, an Issue that exhausted its\n // attempts would be handed back out on the very next lookup — `failed` comes\n // before `pending` in the resumption policy, which is right *across*\n // invocations and wrong inside one.\n const exhausted = new Set<string>();\n const failedIds = new Set<string>();\n\n try {\n while (true) {\n const entry = nextQueueIssue(plan, { exclude: exhausted });\n if (entry === null) break;\n\n plan = markQueueIssueInProgress(plan, entry.id);\n await saveExecutionPlan(planFile, plan);\n\n printInfo(\n `Queue ${entry.position}/${plan.issues.length}: issue #${entry.id}${entry.title === '' ? '' : ` — ${entry.title}`}`,\n );\n\n const issueUsage = beginUsageScope();\n let result: IssueRunResult;\n try {\n result = await runIssueSession(entry.id, options.mode, {\n // `--from` addresses the issue the queue is resuming, never the ones\n // that come after it — those start from their own beginning.\n from: firstOfThisRun ? options.from : undefined,\n noBranch: options.noBranch,\n // `--start-us` belongs to the first issue this invocation runs; the\n // ones after it continue from the history those plans just wrote.\n runOptions: {\n ...options.runOptions,\n startUs: firstOfThisRun ? options.runOptions?.startUs : undefined,\n },\n queue: {\n plan,\n preChecked: true,\n resolved: entry.id === initialPlan.id ? resolvedPrimary : undefined,\n },\n });\n } finally {\n firstOfThisRun = false;\n // Ending here (not only on the happy path) keeps a thrown error from\n // leaving an orphan accumulator on top of the scope stack, where it\n // would silently become \"the current scope\" for everything after it.\n issueUsage.end();\n }\n const usage = issueUsage.totals();\n\n if (result.code !== 0) {\n const failure = {\n phase: result.failedPhase,\n error: {\n category: 'queue_issue_failed',\n message: `Issue #${entry.id} failed${result.failedPhase === null ? '' : ` in phase ${result.failedPhase}`}`,\n at: isoNow(),\n },\n };\n const where = result.failedPhase === null ? '' : ` (phase ${result.failedPhase})`;\n\n if (failureMode === 'stop') {\n plan = markQueueIssueFailed(plan, entry.id, failure);\n await saveExecutionPlan(planFile, plan);\n printError(\n `Queue stopped at issue #${entry.id}${where}. ` +\n 'The branch and every commit made so far were kept.',\n );\n printInfo(`Resume with: issue-flow run ${plan.requested.join(',')}`);\n return result.code;\n }\n\n if (failureMode === 'block') {\n plan = markQueueIssueBlocked(\n plan,\n entry.id,\n `Failed${where} and --on-issue-failure block was in force`,\n failure,\n );\n await saveExecutionPlan(planFile, plan);\n exhausted.add(entry.id);\n failedIds.add(entry.id);\n printWarning(\n `Issue #${entry.id} failed${where} and is blocked for review. Continuing with the rest of the queue.`,\n );\n continue;\n }\n\n // `skip`: not a verdict on the eleven other Issues in the queue.\n const attempts = entry.attempts + 1;\n if (attempts >= maxIssueAttempts) {\n plan = markQueueIssueFailed(plan, entry.id, failure);\n exhausted.add(entry.id);\n failedIds.add(entry.id);\n printWarning(\n `Issue #${entry.id} failed${where} after ${attempts} attempt(s). Continuing with the rest of the queue.`,\n );\n } else {\n plan = markQueueIssueSkipped(plan, entry.id, failure);\n printWarning(\n `Issue #${entry.id} failed${where}. Skipping it for now and coming back at the end of the queue.`,\n );\n }\n await saveExecutionPlan(planFile, plan);\n continue;\n }\n\n // The first issue names the branch; every later one is made to adopt it.\n if (plan.branchName === null && result.branchName !== null) {\n plan = setQueueBranch(plan, result.branchName);\n }\n plan = markQueueIssueCompleted(plan, entry.id);\n await saveExecutionPlan(planFile, plan);\n\n summaries.push({\n id: entry.id,\n title: entry.title,\n storyCount: result.storyCount,\n elapsedSeconds: result.elapsedSeconds,\n usage,\n });\n }\n\n const code = await finishQueue(\n plan,\n planFile,\n summaries,\n startedAtMs,\n queueUsage,\n options,\n resolvedPrimary,\n );\n\n if (failedIds.size > 0) {\n // The queue went as far as it could, and that is worth reporting as a\n // failure even though the independent work landed.\n printError(\n `${failedIds.size} issue(s) did not finish: ${[...failedIds].map((id) => `#${id}`).join(', ')}.`,\n );\n printInfo(`Resume with: issue-flow run ${plan.requested.join(',')}`);\n return code === 0 ? 1 : code;\n }\n return code;\n } finally {\n queueUsage.end();\n }\n}\n\n/**\n * Everything that happens once every issue of the queue is done: the single\n * consolidated Pull Request, closing the issues and reporting. Split out so the\n * loop above stays about scheduling.\n */\nasync function finishQueue(\n plan: ExecutionPlan,\n planFile: string,\n summaries: QueueIssueSummary[],\n startedAtMs: number,\n /** Read only after the consolidated Pull Request ran, so its cost counts. */\n queueUsage: { totals: () => ReturnType<typeof getRunUsageTotals> },\n options: { mode: string; noBranch?: boolean; prReview?: boolean },\n resolvedPrimary?: ResolvedIssue,\n): Promise<number> {\n let current = plan;\n let review: PrReviewOutcome | null = null;\n\n // One Pull Request for the whole queue, and only when there is a branch to\n // propose and no Pull Request has been opened for this queue yet.\n const alreadyOpened = current.pullRequest !== undefined || (await primaryPrCreated(current));\n if (!current.noBranch && options.noBranch !== true && !alreadyOpened) {\n const outcome = await runIssueSession(current.id, options.mode, {\n prReview: options.prReview ?? current.prReview,\n queue: {\n plan: current,\n preChecked: true,\n resolved: resolvedPrimary,\n finalPr: await buildPrQueueContext(current),\n },\n });\n review = outcome.review ?? null;\n\n if (outcome.code !== 0) {\n printError('The consolidated Pull Request could not be created.');\n await saveExecutionPlan(planFile, current);\n return outcome.code;\n }\n\n const pullRequest = await propagatePullRequest(current);\n if (pullRequest !== null) {\n current = setQueuePullRequest(current, pullRequest);\n }\n }\n\n await saveExecutionPlan(planFile, current);\n\n // A review asking for changes leaves every issue open, exactly as it does for\n // a single-issue run: the work is proposed, not accepted.\n if (review?.requestedChanges === true) {\n printInfo('Issues left open until the review blockers are addressed.');\n } else {\n for (const entry of current.issues) {\n await closeIssue(entry.id, entry.source);\n }\n }\n\n printQueueSummary({\n queueId: current.id,\n branchName: current.branchName,\n issues: summaries,\n excluded: current.excluded.map((entry) => ({ id: entry.id, title: entry.title })),\n elapsedSeconds: Math.round((Date.now() - startedAtMs) / 1000),\n prUrl: current.pullRequest?.url ?? null,\n // Read here, after the consolidated Pull Request (and the optional\n // pr-review) already ran: reading it before would report a queue total\n // that leaves out the phase that just spent tokens.\n usage: queueUsage.totals(),\n prReview: review,\n });\n\n return 0;\n}\n\n/**\n * Whether the `pr` phase already ran for this queue, even if it could not\n * report a URL.\n *\n * `plan.pullRequest` on the queue is the happy path; this is the safety net for\n * the case where the phase succeeded but no URL could be parsed from its output\n * — re-running it on a resume would open a second Pull Request for the same\n * branch, which is exactly what the whole feature exists to avoid.\n */\nasync function primaryPrCreated(plan: ExecutionPlan): Promise<boolean> {\n try {\n const paths = await resolveIssuePaths(plan.id);\n return (await loadTaskPlan(paths.tasksFile)).pipeline.prCreated;\n } catch {\n return false;\n }\n}\n\n/**\n * The context the consolidated Pull Request needs: what was implemented, in\n * which order, and what is knowingly left pending.\n *\n * \"Pending\" is the honest half of the report — the issues the user chose not to\n * run, and any review findings still recorded on an issue's plan. Both would\n * otherwise be invisible to whoever reviews the Pull Request.\n */\nasync function buildPrQueueContext(plan: ExecutionPlan): Promise<PrQueueContext> {\n const pending: string[] = [];\n\n for (const entry of plan.issues) {\n try {\n const paths = await resolveIssuePaths(entry.id);\n const taskPlan = await loadTaskPlan(paths.tasksFile);\n if (taskPlan.lastReviewFindings !== null && taskPlan.lastReviewFindings !== '') {\n pending.push(`Issue #${entry.id} has unresolved review findings`);\n }\n } catch {\n // No plan on disk for this issue: nothing to report about it.\n }\n }\n\n return {\n issues: plan.issues.map((entry) => ({\n id: entry.id,\n number: entry.number,\n title: entry.title,\n url: entry.url,\n source: entry.source,\n parent: entry.parent,\n role: entry.role,\n complete: entry.status === 'completed',\n })),\n excluded: plan.excluded.map((entry) => ({\n id: entry.id,\n number: entry.number,\n title: entry.title,\n reason: entry.reason,\n })),\n pending,\n };\n}\n\n/**\n * Copy the Pull Request the `pr` phase recorded on the primary issue's plan\n * onto every other issue of the queue.\n *\n * The queue's `execution-plan.json` is the source of truth, but `pr-review`\n * discovers a Pull Request from `plan.pullRequest` in `tasks.json`\n * (`core/pr-review/discovery.ts`), so replicating it is what keeps\n * `pr-review --issue <any issue of the queue>` working without a special case.\n * A write that fails is reported and skipped: the Pull Request exists either\n * way, and the queue file already records it.\n */\nasync function propagatePullRequest(plan: ExecutionPlan): Promise<PullRequestRef | null> {\n let pullRequest: PullRequestRef | null = null;\n try {\n const primaryPaths = await resolveIssuePaths(plan.id);\n pullRequest = (await loadTaskPlan(primaryPaths.tasksFile)).pullRequest ?? null;\n } catch {\n return null;\n }\n if (pullRequest === null) return null;\n\n for (const entry of plan.issues) {\n if (entry.id === plan.id) continue;\n try {\n const paths = await resolveIssuePaths(entry.id);\n const taskPlan = await loadTaskPlan(paths.tasksFile);\n taskPlan.pullRequest = pullRequest;\n taskPlan.pipeline.prCreated = true;\n await saveTaskPlan(paths.tasksFile, taskPlan);\n } catch {\n printWarning(`Could not record the Pull Request on issue #${entry.id}'s task plan.`);\n }\n }\n\n return pullRequest;\n}\n\n/** An {@link IssueRunResult} carrying nothing but an exit code. */\nfunction failure(code: number): IssueRunResult {\n return { code, failedPhase: null, branchName: null, storyCount: 0, elapsedSeconds: 0 };\n}\n\n/**\n * Close an Issue through whoever owns it.\n *\n * A provider without `close()` (a read-only origin) has nothing to do here, so\n * the step is simply skipped, and a failure is a warning: the work is done\n * either way, and an Issue left open is a nuisance, not a broken pipeline.\n */\nasync function closeIssue(issueNumber: string, source: IssueSource): Promise<void> {\n try {\n const provider = getProvider(source);\n if (provider.close !== undefined) {\n printInfo('Closing issue...');\n await provider.close(issueNumber);\n }\n } catch {\n printWarning('Failed to close issue automatically');\n }\n}\n\n/**\n * Make an issue's task plan use the queue's branch.\n *\n * With no branch decided yet, whatever the `plan` phase produced becomes the\n * queue's branch (the first issue names it, from its own title). From then on\n * the value is written over every later issue's plan, so `execute.md`'s\n * \"check it out or create from main\" finds the branch already there.\n */\nasync function adoptQueueBranch(\n tasksPath: string,\n queueBranch: string | null,\n): Promise<string | null> {\n try {\n const plan = await loadTaskPlan(tasksPath);\n if (queueBranch === null || queueBranch === '') {\n return plan.branchName === '' ? null : plan.branchName;\n }\n if (plan.branchName !== queueBranch) {\n plan.branchName = queueBranch;\n await saveTaskPlan(tasksPath, plan);\n }\n return queueBranch;\n } catch {\n // No tasks.json (the plan phase failed to write one): the queue keeps the\n // branch it already had, and the phase failure is reported on its own.\n return queueBranch;\n }\n}\n","import { spawn } from 'node:child_process';\nimport { mkdir, open } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport type { IssuePaths } from '../storage/paths.js';\nimport { rotateRunLogIfNeeded } from '../storage/run-log.js';\n\nexport function backgroundRejection(mode: string, env = process.env): string | null {\n if (mode === 'manual') {\n return '--background cannot be used with --mode manual: a detached run cannot answer prompts.';\n }\n const ci = env.CI;\n const inCi = ci !== undefined && ci !== '' && ci !== '0' && ci.toLowerCase() !== 'false';\n if (inCi || !process.stdout.isTTY) {\n return '--background needs an interactive terminal. In CI, run in the foreground so the exit code is visible.';\n }\n return null;\n}\n\n/** Strip detach flags and mark the child so it does not detach again. */\nexport function childArgv(argv: readonly string[]): string[] {\n const next: string[] = [];\n for (const arg of argv) {\n if (arg === '--background' || arg === '-d') continue;\n next.push(arg);\n }\n next.push('--detached-child');\n return next;\n}\n\nexport interface SpawnDetachedRunInput {\n paths: IssuePaths;\n execPath?: string;\n entryScript?: string;\n argv?: readonly string[];\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n spawnFn?: typeof spawn;\n}\n\nexport async function spawnDetachedRun(\n input: SpawnDetachedRunInput,\n): Promise<{ pid: number; logFile: string }> {\n const entryScript = input.entryScript ?? process.argv[1];\n if (entryScript === undefined) {\n throw new Error('Could not determine the CLI entry point to spawn a detached run.');\n }\n\n await mkdir(dirname(input.paths.runLogFile), { recursive: true });\n await rotateRunLogIfNeeded(input.paths.runLogFile, input.paths.rotatedRunLogFile);\n\n const log = await open(input.paths.runLogFile, 'a');\n try {\n const args = [entryScript, ...childArgv((input.argv ?? process.argv.slice(2)).slice())];\n const spawnFn = input.spawnFn ?? spawn;\n const child = spawnFn(input.execPath ?? process.execPath, args, {\n detached: true,\n stdio: ['ignore', log.fd, log.fd],\n cwd: input.cwd ?? process.cwd(),\n env: input.env ?? process.env,\n });\n if (child.pid === undefined) {\n throw new Error('The detached run started but reported no pid.');\n }\n child.unref();\n return { pid: child.pid, logFile: input.paths.runLogFile };\n } finally {\n await log.close();\n }\n}\n","import { rename, stat } from 'node:fs/promises';\n\n/** Default ceiling before `run.log` rotates into `run.log.1`. */\nexport const DEFAULT_RUN_LOG_MAX_BYTES = 5 * 1024 * 1024;\n\n/**\n * If `run.log` is already at the ceiling, move it to the rotated name so the\n * next writer starts a fresh file. The current generation is never deleted.\n */\nexport async function rotateRunLogIfNeeded(\n filePath: string,\n rotatedPath: string,\n maxBytes = DEFAULT_RUN_LOG_MAX_BYTES,\n): Promise<void> {\n if (maxBytes <= 0) return;\n try {\n const size = (await stat(filePath)).size;\n if (size < maxBytes) return;\n } catch {\n return;\n }\n try {\n await rename(filePath, rotatedPath);\n } catch {\n // A concurrent rotator already moved it, or the disk is full — the\n // writer will append to whatever is there.\n }\n}\n","import { createInterface } from 'node:readline';\nimport { printInfo, printWarning } from '../ui/logger.js';\nimport type { ExecutionPlan, ExecutionPlanIssue } from './types.js';\n\n/**\n * The one place a multi-issue run stops and asks.\n *\n * Discovery may well turn `issue-flow run 50` into four Issues; implementing\n * them without saying so would be the worst possible outcome of this feature.\n * So the pipeline halts **before** any phase runs, prints what it found and\n * lets the user pick the scope.\n */\n\n/** What the user decided about the discovered hierarchy. */\nexport type QueueChoice = 'requested' | 'all' | 'cascade' | 'cancel';\n\n/** How many invalid answers are tolerated before the prompt gives up. */\nconst MAX_PROMPT_ATTEMPTS = 3;\n\n/** A confirmation that cannot be asked for and was not answered by a flag. */\nexport class QueueConfirmationError extends Error {\n readonly exitCode: number;\n\n constructor(message: string, exitCode = 1) {\n super(message);\n this.name = 'QueueConfirmationError';\n this.exitCode = exitCode;\n }\n}\n\nexport interface ConfirmQueueOptions {\n /** `--yes`: accept the suggested plan (the whole hierarchy) without asking. */\n yes?: boolean;\n /** `--only`: run just the requested Issues, without asking. */\n only?: boolean;\n /** `--cascade`: the hierarchy of a container, without implementing it. */\n cascade?: boolean;\n /**\n * Whether a prompt may be shown. Defaults to a real TTY on both ends outside\n * CI, mirroring `pr-review`'s discovery confirmation.\n */\n interactive?: boolean;\n /**\n * Whether the user asked for a single Issue. Only the hierarchy around it is\n * up for confirmation, so a non-interactive run falls back to that Issue\n * alone instead of failing: running exactly what was asked for can never\n * implement something nobody approved.\n */\n singleRequest?: boolean;\n stdin?: NodeJS.ReadableStream;\n stdout?: NodeJS.WritableStream;\n info?: (message: string) => void;\n warn?: (message: string) => void;\n}\n\nfunction isInteractiveByDefault(): boolean {\n const ci = process.env.CI;\n const inCi = ci !== undefined && ci !== '' && ci !== '0' && ci.toLowerCase() !== 'false';\n return Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY) && !inCi;\n}\n\n/** `#50` for a numeric identifier, `auth-refactor` for anything else. */\nexport function issueLabel(entry: { id: string; number: number | null }): string {\n return entry.number === null ? entry.id : `#${entry.number}`;\n}\n\n/** Why this Issue is in the queue, in a few words. */\nfunction reasonFor(entry: ExecutionPlanIssue): string {\n const parts: string[] = [];\n if (entry.origin === 'requested') {\n parts.push('requested');\n }\n if (entry.dependsOn.length > 0) {\n parts.push(`after ${entry.dependsOn.map((id) => `#${id}`).join(', ')}`);\n }\n if (entry.parent !== null) {\n parts.push(`sub-issue of #${entry.parent}`);\n }\n if (entry.priority !== null) {\n parts.push(entry.priority);\n }\n return parts.join(', ');\n}\n\n/**\n * The summary printed before the prompt.\n *\n * Returned as lines rather than printed so the shape is testable without\n * capturing stdout — the same split `buildRunSummaryLines` uses.\n */\nexport function buildQueueSummaryLines(plan: ExecutionPlan): string[] {\n const primary = plan.issues.find((entry) => entry.id === plan.id) ?? plan.issues[0];\n const lines: string[] = [];\n\n if (primary !== undefined) {\n const role = primary.role === 'container' ? ' (container)' : '';\n lines.push(\n ` Main issue: ${issueLabel(primary)}${primary.title ? ` ${primary.title}` : ''}${role}`,\n );\n }\n const executables = plan.issues.filter((entry) => entry.role !== 'container').length;\n const containers = plan.issues.length - executables;\n lines.push(\n containers > 0\n ? ` Total issues: ${executables} executable + ${containers} container`\n : ` Total issues: ${plan.issues.length}`,\n );\n lines.push(' Suggested order:');\n\n for (const entry of plan.issues) {\n const reason = reasonFor(entry);\n const flag = entry.heuristic ? ' ~' : '';\n const external =\n entry.externalDependencies.length > 0\n ? ` ⚠ depends on ${entry.externalDependencies.map((id) => `#${id}`).join(', ')} (outside this scope)`\n : '';\n const role = entry.role === 'container' ? ' (container)' : '';\n const title = entry.title === '' ? '' : ` ${entry.title}`;\n lines.push(\n ` ${entry.position}. ${issueLabel(entry)}${title}${role}${reason === '' ? '' : ` (${reason})`}${flag}${external}`,\n );\n }\n\n if (plan.issues.some((entry) => entry.heuristic)) {\n lines.push(' ~ relation found only in the issue text, which may be a false positive');\n }\n if (plan.truncated) {\n lines.push(' Note: discovery hit its limit — the hierarchy may be larger than shown');\n }\n\n return lines;\n}\n\n/** One-line recap after the user (or a flag) picks a scope. */\nexport function buildScopeSummaryLine(plan: ExecutionPlan, choice: QueueChoice): string | null {\n if (choice === 'cancel') return null;\n const primary = plan.requested[0] ?? plan.id;\n if (choice === 'requested') {\n return `Scope: ${plan.requested.length} requested issue(s).`;\n }\n if (choice === 'cascade') {\n const executables = plan.issues.filter((entry) => entry.role !== 'container').length;\n return `Scope: hierarchy of #${primary} (${executables} executable, container not implemented).`;\n }\n return `Scope: ${plan.issues.length} issues from the hierarchy of #${primary}.`;\n}\n\nfunction requestedIsContainer(plan: ExecutionPlan): boolean {\n return plan.issues.some(\n (entry) => plan.requested.includes(entry.id) && entry.role === 'container',\n );\n}\n\n/**\n * Ask, in an interactive terminal, which scope to run.\n *\n * Outside a TTY the answer must come from a flag: `--yes` for the whole\n * hierarchy, `--only` for just what was asked for. Neither is a *default* —\n * silently picking one would either implement Issues nobody approved or ignore\n * a dependency the user was never told about. The command fails instead, which\n * is what keeps an unattended CI run honest.\n */\nexport async function confirmQueue(\n plan: ExecutionPlan,\n requestedOnlyCount: number,\n options: ConfirmQueueOptions = {},\n): Promise<QueueChoice> {\n const info = options.info ?? printInfo;\n const warn = options.warn ?? printWarning;\n\n info(`Issue ${plan.requested.map((id) => `#${id}`).join(', ')} is part of a larger structure:`);\n for (const line of buildQueueSummaryLines(plan)) {\n (options.stdout ?? process.stdout).write(`${line}\\n`);\n }\n\n const container = requestedIsContainer(plan);\n\n if (options.only === true) {\n if (container) {\n warn(\n `${plan.requested.map((id) => `#${id}`).join(', ')} is a container. ` +\n '--only will run it as an executable issue.',\n );\n }\n info(`--only: running just the ${requestedOnlyCount} issue(s) you asked for.`);\n info(buildScopeSummaryLine(plan, 'requested') ?? '');\n return 'requested';\n }\n if (options.cascade === true || (options.yes === true && container)) {\n info(\n `${options.cascade === true ? '--cascade' : '--yes'}: running the hierarchy of the container, without implementing it.`,\n );\n info(buildScopeSummaryLine(plan, 'cascade') ?? '');\n return 'cascade';\n }\n if (options.yes === true) {\n info(`--yes: running the whole hierarchy (${plan.issues.length} issues).`);\n info(buildScopeSummaryLine(plan, 'all') ?? '');\n return 'all';\n }\n\n const interactive = options.interactive ?? isInteractiveByDefault();\n if (!interactive && container) {\n throw new QueueConfirmationError(\n `${plan.requested.map((id) => `#${id}`).join(', ')} is a container (umbrella) and the terminal is not interactive. ` +\n 'Re-run with --cascade to execute its children, or --only to execute just that issue.',\n );\n }\n if (!interactive && options.singleRequest === true) {\n warn(\n 'A larger structure was found, but the terminal is not interactive: running just ' +\n `issue ${plan.requested.map((id) => `#${id}`).join(', ')}. ` +\n 'Re-run with --yes to execute the whole hierarchy.',\n );\n const summary = buildScopeSummaryLine(plan, 'requested');\n if (summary) info(summary);\n return 'requested';\n }\n if (!interactive) {\n throw new QueueConfirmationError(\n 'This run involves more than one issue and the terminal is not interactive. ' +\n 'Re-run with --yes to execute the whole hierarchy, or --only to execute just the ' +\n 'issues you informed.',\n );\n }\n\n const query = container\n ? `Which scope should run? [1] The hierarchy of #${plan.id} ` +\n `(${plan.issues.filter((entry) => entry.role !== 'container').length} issues) ` +\n `[2] Include dependencies outside it [3] Just #${plan.id} itself [4] Cancel: `\n : `Which scope should run? [1] Only the issues informed (${requestedOnlyCount}) ` +\n `[2] The whole hierarchy (${plan.issues.length}) [3] Cancel: `;\n\n const choice = await ask(\n query,\n options.stdin ?? process.stdin,\n options.stdout ?? process.stdout,\n warn,\n container ? 'container' : 'plain',\n );\n const summary = buildScopeSummaryLine(plan, choice);\n if (summary) info(summary);\n return choice;\n}\n\n/**\n * Numbered prompt, sharing the queued-lines discipline of `issues/resolver.ts`:\n * `rl.question` drops input that arrives before the prompt is written, which\n * silently loses a piped answer. EOF answers `cancel` — never consent.\n */\nasync function ask(\n query: string,\n stdin: NodeJS.ReadableStream,\n stdout: NodeJS.WritableStream,\n warn: (message: string) => void,\n mode: 'plain' | 'container' = 'plain',\n): Promise<QueueChoice> {\n const rl = createInterface({ input: stdin, output: stdout });\n const queued: string[] = [];\n let pending: ((line: string | null) => void) | null = null;\n let closed = false;\n\n rl.on('line', (line: string) => {\n if (pending !== null) {\n const resolve = pending;\n pending = null;\n resolve(line);\n return;\n }\n queued.push(line);\n });\n rl.on('close', () => {\n closed = true;\n if (pending !== null) {\n const resolve = pending;\n pending = null;\n resolve(null);\n }\n });\n\n const read = (): Promise<string | null> =>\n new Promise<string | null>((resolve) => {\n const buffered = queued.shift();\n if (buffered !== undefined) {\n resolve(buffered);\n return;\n }\n if (closed) {\n resolve(null);\n return;\n }\n stdout.write(query);\n pending = resolve;\n });\n\n try {\n for (let attempt = 0; attempt < MAX_PROMPT_ATTEMPTS; attempt++) {\n const answer = await read();\n if (answer === null) {\n return 'cancel';\n }\n const choice = answer.trim();\n if (mode === 'container') {\n if (choice === '' || choice === '1') return 'cascade';\n if (choice === '2') return 'all';\n if (choice === '3') return 'requested';\n if (choice === '4') return 'cancel';\n warn(`Invalid choice: '${choice}'. Enter 1, 2, 3 or 4.`);\n continue;\n }\n if (choice === '1') return 'requested';\n // An empty answer accepts the suggestion, which is the whole point of\n // having computed an order: the same convention as `pr-review`'s (Y/n).\n if (choice === '' || choice === '2') return 'all';\n if (choice === '3') return 'cancel';\n warn(`Invalid choice: '${choice}'. Enter 1, 2 or 3.`);\n }\n return 'cancel';\n } finally {\n rl.close();\n }\n}\n","import {\n type BuildDependencyGraphOptions,\n buildDependencyGraph,\n type DependencyGraph,\n} from '../issues/graph.js';\nimport { getProvider } from '../issues/registry.js';\nimport type { Issue, IssueRelations, IssueSource } from '../issues/types.js';\n\n/**\n * Bridge between the Issue providers and the dependency graph.\n *\n * Discovery is a *best-effort enrichment* of a run, never a prerequisite: an\n * origin with no `fetchRelations`, an unregistered provider or a failing API all\n * degrade to \"this issue relates to nothing\", which is exactly the single-issue\n * pipeline that existed before. That is what makes the feature additive.\n */\n\nexport interface DiscoverGraphOptions extends BuildDependencyGraphOptions {\n /** Origin to ask about relations. Defaults to the first known Issue's source. */\n source?: IssueSource;\n}\n\n/** Whether an origin can answer questions about related Issues at all. */\nexport function supportsRelations(source: IssueSource): boolean {\n try {\n return typeof getProvider(source).fetchRelations === 'function';\n } catch {\n return false;\n }\n}\n\n/**\n * Walk the hierarchy of `roots` through the provider of `source`.\n *\n * Discovered Issues are read from the same origin: a queue is resolved against\n * one provider, so an id found in a GitHub hierarchy is a GitHub Issue. The\n * Issues the caller already resolved are passed through `known`, so the roots\n * never cost a second round-trip.\n */\nexport async function discoverIssueGraph(\n roots: readonly string[],\n options: DiscoverGraphOptions = {},\n): Promise<DependencyGraph> {\n const source = options.source ?? [...(options.known ?? [])][0]?.source ?? 'github';\n\n let fetchRelations: ((id: string) => Promise<IssueRelations | null>) | null = null;\n let fetchIssue: ((id: string) => Promise<Issue | null>) | null = null;\n try {\n const provider = getProvider(source);\n const relations = provider.fetchRelations?.bind(provider);\n if (relations !== undefined) {\n fetchRelations = (id) => relations(id);\n fetchIssue = (id) => provider.get(id);\n }\n } catch {\n // Unknown origin: nothing to discover, and the run continues single-issue.\n }\n\n if (fetchRelations === null) {\n return buildDependencyGraph(roots, async () => null, { ...options, fetchIssue: undefined });\n }\n\n return buildDependencyGraph(roots, fetchRelations, {\n ...options,\n fetchIssue: options.fetchIssue ?? fetchIssue ?? undefined,\n });\n}\n","import type { Issue, IssueSource } from '../issues/types.js';\nimport { printInfo, printWarning } from '../ui/logger.js';\nimport { type ConfirmQueueOptions, confirmQueue, QueueConfirmationError } from './confirm.js';\nimport { collectCascadeIds } from './containers.js';\nimport { discoverIssueGraph, supportsRelations } from './discovery.js';\nimport { computeExecutionOrder, describeCycles } from './order.js';\nimport {\n buildExecutionPlan,\n isQueueComplete,\n loadExecutionPlan,\n saveExecutionPlan,\n} from './plan.js';\nimport type { ExecutionPlan } from './types.js';\n\n/**\n * Deciding, before any phase runs, whether this invocation is a single-issue\n * pipeline or a queue — and, when it is a queue, what exactly it will run.\n *\n * Everything here happens *before* the session starts, so a run that turns out\n * to be a plain single-issue pipeline is indistinguishable from what the CLI\n * did before this feature existed: no prompt, no artifact, no extra output.\n */\n\nexport type QueueDecision =\n /** Nothing to coordinate: run the single issue exactly as before. */\n | { kind: 'single' }\n | { kind: 'queue'; plan: ExecutionPlan; resumed: boolean }\n /** The run must stop; `code` is what the CLI returns. */\n | { kind: 'stop'; code: number };\n\nexport interface PlanQueueInput {\n /** Identifiers the user asked for, in order. */\n requested: string[];\n /** Origin the run resolved, used to ask the right provider about relations. */\n source: IssueSource;\n /** Issues already resolved by the caller, so the roots are not re-read. */\n known: Issue[];\n projectId: string;\n /** Where the queue's `execution-plan.json` lives. */\n planFile: string;\n noBranch: boolean;\n prReview: boolean;\n /** `--yes` / `--only`, forwarded to the confirmation. */\n confirm?: ConfirmQueueOptions;\n info?: (message: string) => void;\n warn?: (message: string) => void;\n}\n\n/** `--only` / \"just this issue\" implements a requested container on purpose. */\nfunction forceRequestedExecutable(plan: ExecutionPlan): ExecutionPlan {\n return {\n ...plan,\n issues: plan.issues.map((entry) =>\n plan.requested.includes(entry.id) ? { ...entry, role: 'executable' as const } : entry,\n ),\n };\n}\n\n/** A persisted queue that matches this invocation, or `null`. */\nasync function loadResumableQueue(\n planFile: string,\n requested: readonly string[],\n): Promise<ExecutionPlan | null> {\n let plan: ExecutionPlan;\n try {\n plan = await loadExecutionPlan(planFile);\n } catch {\n // Absent (the common case) or unreadable: plan the queue from scratch. A\n // corrupted file must not strand the user — the plan is derived state.\n return null;\n }\n\n // The stored queue answers a different question than the one being asked.\n const sameRequest =\n plan.requested.length === requested.length &&\n plan.requested.every((id, index) => id === requested[index]);\n\n return sameRequest ? plan : null;\n}\n\n/**\n * Work out what this invocation runs.\n *\n * The order of the checks is what keeps the feature additive:\n *\n * 1. an unfinished queue for the very same request is resumed, never\n * re-confirmed — the user already answered that question;\n * 2. `--only` with a single issue skips discovery altogether, so an automation\n * that knows what it wants pays nothing for the feature;\n * 3. discovery runs; if it finds nothing beyond the requested issue, the run\n * stays single-issue and no artifact is created;\n * 4. only a genuinely larger structure reaches the confirmation.\n */\nexport async function planQueue(input: PlanQueueInput): Promise<QueueDecision> {\n const info = input.info ?? printInfo;\n const warn = input.warn ?? printWarning;\n const single = input.requested.length === 1;\n\n const resumable = await loadResumableQueue(input.planFile, input.requested);\n // A queue that already finished has nothing left to run, and re-planning it\n // would overwrite its `execution-plan.json` — losing the Pull Request and\n // the record of what ran. Report it and stop successfully instead.\n if (resumable !== null && isQueueComplete(resumable)) {\n const pr = resumable.pullRequest?.url;\n info(\n `The execution queue of issue #${resumable.id} is already complete ` +\n `(${resumable.issues.length} issues)${pr === undefined ? '' : ` — ${pr}`}. Nothing to run.`,\n );\n return { kind: 'stop', code: 0 };\n }\n if (resumable !== null) {\n const done = resumable.issues.filter((entry) => entry.status === 'completed').length;\n info(\n `Resuming the execution queue of issue #${resumable.id}: ` +\n `${done}/${resumable.issues.length} issues already completed.`,\n );\n return { kind: 'queue', plan: resumable, resumed: true };\n }\n\n // `--only` on a single issue is the explicit \"do not look around\" answer.\n if (single && input.confirm?.only === true) {\n return { kind: 'single' };\n }\n\n if (single && !supportsRelations(input.source)) {\n // An origin with no notion of related Issues (the local provider) can only\n // ever produce a single-issue run.\n return { kind: 'single' };\n }\n\n const graph = await discoverIssueGraph(input.requested, {\n source: input.source,\n known: input.known,\n warn,\n });\n\n if (single && graph.nodes.size <= 1) {\n return { kind: 'single' };\n }\n\n const suggested = computeExecutionOrder(graph);\n if (!suggested.ok) {\n // A cycle anywhere in the discovered hierarchy must not take down a run\n // the user asked for on a single issue: they never opted into the\n // hierarchy, so degrade to the pipeline that has always worked and say\n // why. Only an explicitly multi-issue request is refused outright.\n if (single) {\n warn(\n `Dependency cycle between issues: ${describeCycles(suggested.cycles)}. ` +\n 'Running just the issue you informed; fix the dependencies on GitHub to run the hierarchy.',\n );\n return { kind: 'single' };\n }\n warn(\n `Dependency cycle between issues: ${describeCycles(suggested.cycles)}. ` +\n 'Fix the dependencies on GitHub, or re-run with --only to execute just the issues you informed.',\n );\n return { kind: 'stop', code: 1 };\n }\n\n const requestedOrder = computeExecutionOrder(graph, { include: input.requested });\n const requestedCount = requestedOrder.ok ? requestedOrder.order.length : input.requested.length;\n\n const suggestedPlan = buildExecutionPlan({\n projectId: input.projectId,\n requested: input.requested,\n graph,\n order: suggested.order,\n noBranch: input.noBranch,\n prReview: input.prReview,\n });\n\n let choice: 'all' | 'requested' | 'cascade' | 'cancel';\n try {\n choice = await confirmQueue(suggestedPlan, requestedCount, {\n ...(input.confirm ?? {}),\n singleRequest: single,\n });\n } catch (err) {\n if (err instanceof QueueConfirmationError) {\n warn(err.message);\n return { kind: 'stop', code: err.exitCode };\n }\n throw err;\n }\n\n if (choice === 'cancel') {\n info('Cancelled: nothing was executed.');\n return { kind: 'stop', code: 1 };\n }\n\n let plan = suggestedPlan;\n if (choice === 'cascade') {\n const include = collectCascadeIds(graph, input.requested);\n const cascadeOrder = computeExecutionOrder(graph, { include });\n if (!cascadeOrder.ok) {\n warn(`Dependency cycle between issues: ${describeCycles(cascadeOrder.cycles)}.`);\n return { kind: 'stop', code: 1 };\n }\n if (\n cascadeOrder.order.filter(\n (id) => suggestedPlan.issues.find((entry) => entry.id === id)?.role !== 'container',\n ).length === 0\n ) {\n warn(\n `Issue #${input.requested[0]} is a container with no executable children in scope. ` +\n 'Re-run with --only if you really want to implement it.',\n );\n return { kind: 'stop', code: 1 };\n }\n plan = buildExecutionPlan({\n projectId: input.projectId,\n requested: input.requested,\n graph,\n order: cascadeOrder.order,\n noBranch: input.noBranch,\n prReview: input.prReview,\n });\n } else if (choice === 'requested') {\n if (!requestedOrder.ok) {\n warn(\n `Dependency cycle between the issues you informed: ${describeCycles(requestedOrder.cycles)}.`,\n );\n return { kind: 'stop', code: 1 };\n }\n // A single issue after trimming is not a queue at all: fall back to the\n // untouched single-issue pipeline instead of creating an artifact for it.\n // But that fallback only makes sense when one issue was requested — with\n // several, trimming to one means the others never made it into the graph\n // (unreadable issue, node limit), and silently running a subset of what\n // the user asked for is worse than stopping.\n if (requestedOrder.order.length <= 1) {\n if (input.requested.length > 1) {\n const missing = input.requested.filter((id) => !requestedOrder.order.includes(id));\n warn(\n `Only issue #${requestedOrder.order[0] ?? '—'} of the ones you informed could be read; ` +\n `${missing.map((id) => `#${id}`).join(', ')} did not make it into the dependency graph. ` +\n 'Nothing was executed — check the identifiers and try again.',\n );\n return { kind: 'stop', code: 1 };\n }\n return { kind: 'single' };\n }\n plan = forceRequestedExecutable(\n buildExecutionPlan({\n projectId: input.projectId,\n requested: input.requested,\n graph,\n order: requestedOrder.order,\n noBranch: input.noBranch,\n prReview: input.prReview,\n }),\n );\n }\n\n await saveExecutionPlan(input.planFile, plan);\n return { kind: 'queue', plan, resumed: false };\n}\n","/**\n * Parsing of the issue identifiers a command receives on the command line.\n *\n * `run` accepts both spellings of the same list — `42,43,50` and `42 43 50` —\n * because both are what a user naturally types, and commander gives them to us\n * as different shapes (one argument with commas, or several arguments). Normal-\n * izing here keeps every downstream layer working on a plain `string[]`.\n */\n\n/** Malformed issue arguments, reported as a CLI error. */\nexport class IssueArgumentError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'IssueArgumentError';\n }\n}\n\n/**\n * Rejected before an identifier ever becomes a path segment or an API call.\n * Mirrors `normalizeIssueNumber` in `storage/paths.ts`: the storage layer would\n * refuse these anyway, and failing here names the offending argument instead.\n */\nconst INVALID_ID = /[/\\\\\\s]/;\n\n/**\n * Normalize the positional arguments of `run` into a list of issue identifiers.\n *\n * - splits on commas, so `42,43` and `42 43` produce the same list;\n * - strips a leading `#` and surrounding whitespace;\n * - preserves the order the user typed, which is what a tie-break falls back to;\n * - drops exact duplicates silently (`42 42` is a typo with an obvious intent),\n * but rejects an empty or malformed identifier, which is not.\n *\n * @throws IssueArgumentError when no identifier survives or one is malformed.\n */\nexport function parseIssueArguments(values: readonly string[]): string[] {\n const ids: string[] = [];\n const seen = new Set<string>();\n\n for (const value of values) {\n for (const raw of value.split(',')) {\n const id = raw.trim().replace(/^#/, '').trim();\n if (id === '') {\n // An empty slot is always a typo: `42,,43` or a stray comma.\n if (raw.trim() !== '' || value.includes(',')) {\n throw new IssueArgumentError(\n `Invalid issue list '${value}': it has an empty entry. Use '42,43' or '42 43'.`,\n );\n }\n continue;\n }\n if (INVALID_ID.test(id) || id === '.' || id === '..') {\n throw new IssueArgumentError(`Invalid issue identifier '${raw.trim()}'.`);\n }\n if (seen.has(id)) continue;\n seen.add(id);\n ids.push(id);\n }\n }\n\n if (ids.length === 0) {\n throw new IssueArgumentError('No issue was informed. Pass at least one issue number.');\n }\n\n return ids;\n}\n","import { Listr, type ListrTask, PRESET_TIMER, PRESET_TIMESTAMP } from 'listr2';\nimport type { PipelinePhase } from '../core/pipeline.js';\nimport { getSessionPublisher } from '../core/session-publisher.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport {\n setActivityCallback,\n setOutputCallback,\n setStoryStageCallback,\n setStoryUpdateCallback,\n} from '../core/verbose.js';\nimport type { UserStory } from '../types.js';\nimport { renderExecuteFocus } from './status-view.js';\n\n/** Minimal interface for the listr2 task wrapper properties we use. */\ninterface TaskContext {\n title: string;\n output: string;\n newListr(tasks: ListrTask[], options?: Record<string, unknown>): Listr;\n}\n\n/**\n * Result returned after the pipeline renderer finishes.\n */\nexport interface PipelineResult {\n success: boolean;\n failedPhase?: string;\n overallElapsedSeconds: number;\n}\n\n/**\n * Options for runPipelineWithRenderer.\n */\nexport interface PipelineRendererOptions {\n /** All pipeline phases in order */\n phases: PipelinePhase[];\n /** Index of the first phase to run (phases before this are skipped) */\n startIndex: number;\n /** Whether verbose mode is enabled */\n verbose: boolean;\n /** Map of phase name to its async runner function */\n runners: Record<string, () => Promise<void>>;\n /** Path to tasks.json — enables execute-phase subtask progress when set */\n tasksPath?: string;\n /** Suffix per phase when its agent differs from the run default (e.g. `codex`). */\n phaseSuffixes?: Record<string, string>;\n}\n\n/**\n * Phase labels for display.\n *\n * Typed as `Record<string, string>` on purpose (phases arrive as plain strings\n * here), which also means adding a phase to `PipelinePhase` does *not* break\n * the build when its label is missing — it silently falls back to the\n * capitalized phase name. Hence `phaseLabel()` below being covered by a test.\n */\nconst PHASE_LABELS: Record<string, string> = {\n prd: 'PRD',\n plan: 'Plan',\n execute: 'Execute',\n review: 'Review',\n pr: 'PR',\n 'pr-review': 'PR Review',\n};\n\n/**\n * Display label for a pipeline phase, falling back to the capitalized phase\n * name for anything not in the table.\n */\nexport function phaseLabel(phase: string): string {\n return PHASE_LABELS[phase] ?? phase.charAt(0).toUpperCase() + phase.slice(1);\n}\n\n/**\n * Select the appropriate listr2 renderer based on environment.\n *\n * - TTY + not verbose -> 'default' (animated spinners)\n * - TTY + verbose -> 'verbose' (sequential lines)\n * - Non-TTY / CI -> 'simple' (plain timestamped output)\n *\n * NO_COLOR is handled by listr2's own color support and the useColor() utility,\n * not by switching renderers — a TTY with NO_COLOR still benefits from the\n * default renderer's layout and spinners.\n */\nfunction selectRenderer(verbose: boolean): 'default' | 'verbose' | 'simple' {\n const isTTY = !!process.stdout.isTTY;\n const isCI = !!process.env.CI;\n\n if (!isTTY || isCI) {\n return 'simple';\n }\n\n return verbose ? 'verbose' : 'default';\n}\n\n/**\n * Plain subtask title for a story, optionally suffixed to show it is the one\n * `execute` is currently working on. Exported standalone for testing without\n * spinning up a `listr2` renderer.\n */\nexport function storySubtaskTitle(\n story: Pick<UserStory, 'id' | 'title'>,\n executing: boolean,\n): string {\n const base = `${story.id}: ${story.title}`;\n return executing ? `${base} → Executando...` : base;\n}\n\n/** Minimal view of a listr2 task the tracker needs: a writable title. */\ninterface TitledTask {\n title: string;\n}\n\nexport interface ActiveStoryTracker {\n /** The story `execute` is now working on, or `undefined` for none. */\n setActive(storyId: string | undefined): void;\n /** Nothing is executing any more — drop the suffix from whoever holds it. */\n clear(): void;\n}\n\n/**\n * Keeps the \"executing\" suffix on exactly one story subtask at a time.\n *\n * `clear()` matters as much as `setActive()`: the engine leaves its loop the\n * moment the last story passes, so no further `iteration:start` ever arrives\n * to move the suffix off the story that just finished. Without an explicit\n * clear at the end of the phase, the terminal would keep showing a completed\n * story as executing while the web panel already shows it awaiting review.\n */\nexport function createActiveStoryTracker(\n stories: ReadonlyArray<Pick<UserStory, 'id' | 'title'>>,\n storyTasks: ReadonlyMap<string, TitledTask>,\n): ActiveStoryTracker {\n let activeStoryId: string | undefined;\n\n const retitle = (storyId: string, executing: boolean): void => {\n const task = storyTasks.get(storyId);\n if (!task) return;\n task.title = storySubtaskTitle(\n stories.find((s) => s.id === storyId) ?? { id: storyId, title: '' },\n executing,\n );\n };\n\n return {\n setActive(storyId: string | undefined): void {\n if (activeStoryId !== undefined && activeStoryId !== storyId) {\n retitle(activeStoryId, false);\n }\n activeStoryId = storyId;\n if (storyId !== undefined) retitle(storyId, true);\n },\n clear(): void {\n if (activeStoryId === undefined) return;\n retitle(activeStoryId, false);\n activeStoryId = undefined;\n },\n };\n}\n\n/**\n * Clean mode never expands one line per story. The phase title carries\n * `N/M` and the output bar carries the active story plus the current tool,\n * both read from the same snapshot the dashboard uses.\n */\nexport function executeExpandsStories(verbose: boolean): boolean {\n return verbose;\n}\n\nfunction paintExecuteFocus(task: TaskContext): void {\n const lines = renderExecuteFocus(getSessionPublisher().snapshot());\n if (lines.length > 0) task.output = lines.join('\\n');\n}\n\n/**\n * Build the execute phase task with dynamic subtasks for each user story.\n *\n * Stories that already pass are displayed as skipped. Pending stories wait for\n * the engine to complete them via the story update callback. The parent task\n * title is updated with aggregate progress (e.g., \"Execute (3/5 stories passing)\").\n */\nfunction buildExecutePhaseTask(runner: () => Promise<void>, tasksPath: string, verbose: boolean) {\n return async (_ctx: unknown, task: TaskContext) => {\n let stories: UserStory[];\n try {\n const plan = await loadTaskPlan(tasksPath);\n stories = [...plan.userStories].sort((a, b) => a.priority - b.priority);\n } catch {\n // If we can't read the plan, fall back to running without subtasks\n setOutputCallback((line: string) => {\n task.output = line;\n });\n try {\n await runner();\n } finally {\n setOutputCallback(undefined);\n }\n return;\n }\n\n const totalStories = stories.length;\n const initialPassed = stories.filter((s) => s.passes).length;\n task.title = `Execute (${initialPassed}/${totalStories} stories passing)`;\n\n if (!executeExpandsStories(verbose)) {\n setStoryUpdateCallback((updatedStories: UserStory[]) => {\n const passed = updatedStories.filter((s) => s.passes).length;\n task.title = `Execute (${passed}/${totalStories} stories passing)`;\n paintExecuteFocus(task);\n });\n setStoryStageCallback(() => {\n paintExecuteFocus(task);\n });\n setActivityCallback(() => {\n paintExecuteFocus(task);\n });\n setOutputCallback((line: string) => {\n task.output = line;\n });\n try {\n await runner();\n } finally {\n setOutputCallback(undefined);\n setStoryUpdateCallback(undefined);\n setStoryStageCallback(undefined);\n setActivityCallback(undefined);\n }\n return;\n }\n\n // Create promise resolvers for pending stories\n const resolvers = new Map<string, { resolve: () => void; reject: (err: Error) => void }>();\n\n // Set up story update callback — engine calls this after each iteration\n setStoryUpdateCallback((updatedStories: UserStory[]) => {\n const passed = updatedStories.filter((s) => s.passes).length;\n task.title = `Execute (${passed}/${totalStories} stories passing)`;\n\n for (const s of updatedStories) {\n if (s.passes && resolvers.has(s.id)) {\n resolvers.get(s.id)!.resolve();\n resolvers.delete(s.id);\n }\n }\n });\n\n // Own listr2 task handle per story subtask, so the story-stage callback\n // below can update a title after the subtask has already started — the\n // resolvers map alone has no reference back into the renderer.\n const storyTasks = new Map<string, TaskContext>();\n const tracker = createActiveStoryTracker(stories, storyTasks);\n\n // Engine calls this alongside every iteration:start, with the same\n // storyId the published event and the session snapshot carry — never a\n // second, independently computed \"who is active\" heuristic. Only ever\n // meaningful for a story still pending (an already-passing one has no\n // subtask left to update: it already resolved and disappeared from view).\n setStoryStageCallback((storyId: string | undefined) => {\n tracker.setActive(storyId);\n });\n\n // Build subtask definitions for each story\n const subtaskDefs = stories.map((story) => ({\n title: storySubtaskTitle(story, false),\n skip: story.passes ? 'already passing' : false,\n task: async (_c: unknown, subTask: TaskContext) => {\n storyTasks.set(story.id, subTask);\n await new Promise<void>((resolve, reject) => {\n resolvers.set(story.id, { resolve, reject });\n });\n },\n rendererOptions: {\n timer: PRESET_TIMER,\n },\n }));\n\n // Engine runner subtask — drives the execution loop\n const engineSubtask = {\n title: 'Running engine',\n task: async (_c: unknown, engineTask: TaskContext) => {\n setOutputCallback((line: string) => {\n engineTask.output = line;\n });\n try {\n await runner();\n } finally {\n setOutputCallback(undefined);\n setStoryUpdateCallback(undefined);\n setStoryStageCallback(undefined);\n // The engine is done — nothing is executing any more, whether it\n // finished the plan or failed mid-story.\n tracker.clear();\n // Resolve any remaining pending stories (engine finished successfully)\n for (const [, { resolve }] of resolvers) {\n resolve();\n }\n resolvers.clear();\n }\n },\n rendererOptions: {\n timer: PRESET_TIMER,\n outputBar: verbose ? Infinity : false,\n persistentOutput: false,\n bottomBar: verbose ? Infinity : 3,\n },\n };\n\n // Run engine + story subtasks concurrently:\n // - Engine subtask runs the actual execution loop\n // - Story subtasks resolve as the engine completes each story\n // Cleanup of setStoryUpdateCallback is handled in engineSubtask's finally block\n //\n // exitOnError must stay true: the per-story subtasks never reject (they\n // only ever get resolve()d, either by the story-update callback or by\n // engineSubtask's finally block once the engine is done), so the only way\n // this nested Listr can fail is engineSubtask itself throwing. With\n // exitOnError: false that failure was swallowed here — the outer \"execute\"\n // phase task then resolved successfully even though the engine failed,\n // and the pipeline moved on to `review` with 0 stories passing instead of\n // stopping. exitOnError: true lets the failure propagate out of\n // task.newListr(...) so the outer phase list (which does have\n // exitOnError: true) aborts before ever starting `review`.\n return task.newListr([engineSubtask, ...subtaskDefs], {\n concurrent: true,\n exitOnError: true,\n rendererOptions: {\n timer: PRESET_TIMER,\n collapseSkips: false,\n },\n });\n };\n}\n\n/**\n * Run the pipeline phases through listr2 for single-writer terminal output.\n *\n * Phases before startIndex are displayed as \"skipped\".\n * Each running phase shows an animated spinner with elapsed time.\n * Completed phases show a checkmark with final duration.\n * The execute phase shows per-story subtask progress when tasksPath is provided.\n */\nexport async function runPipelineWithRenderer(\n options: PipelineRendererOptions,\n): Promise<PipelineResult> {\n const { phases, startIndex, verbose, runners, tasksPath, phaseSuffixes } = options;\n const overallStart = Date.now();\n let currentPhase: string | undefined;\n const renderer = selectRenderer(verbose);\n const isSimple = renderer === 'simple';\n\n const tasks = new Listr(\n phases.map((phase, index) => {\n const label = phaseSuffixes?.[phase]\n ? `${phaseLabel(phase)} (${phaseSuffixes[phase]})`\n : phaseLabel(phase);\n const isExecutePhase = phase === 'execute' && tasksPath;\n\n return {\n title: label,\n skip: index < startIndex ? 'skipped' : false,\n task: isExecutePhase\n ? async (_ctx: unknown, task: TaskContext) => {\n currentPhase = phase;\n const runner = runners[phase];\n if (!runner) {\n throw new Error(`No runner defined for phase: ${phase}`);\n }\n return buildExecutePhaseTask(runner, tasksPath, verbose)(_ctx, task);\n }\n : async (_ctx: unknown, task: TaskContext) => {\n currentPhase = phase;\n const runner = runners[phase];\n if (!runner) {\n throw new Error(`No runner defined for phase: ${phase}`);\n }\n // Route all output through task.output so listr2 controls rendering\n setOutputCallback((line: string) => {\n task.output = line;\n });\n try {\n await runner();\n } finally {\n setOutputCallback(undefined);\n }\n },\n rendererOptions: {\n timer: PRESET_TIMER,\n outputBar: verbose ? Infinity : false,\n persistentOutput: false,\n },\n };\n }),\n {\n renderer,\n rendererOptions: {\n timer: PRESET_TIMER,\n collapseSkips: false,\n ...(isSimple ? { timestamp: PRESET_TIMESTAMP } : {}),\n },\n exitOnError: true,\n },\n );\n\n let failedPhase: string | undefined;\n\n try {\n await tasks.run();\n } catch {\n failedPhase = currentPhase ?? phases[startIndex];\n } finally {\n // Ensure global callbacks are always cleaned up, even on unexpected errors\n setOutputCallback(undefined);\n setStoryUpdateCallback(undefined);\n setStoryStageCallback(undefined);\n setActivityCallback(undefined);\n }\n\n const overallElapsedSeconds = Math.floor((Date.now() - overallStart) / 1000);\n\n return {\n success: !failedPhase,\n failedPhase,\n overallElapsedSeconds,\n };\n}\n","import type {\n SessionPhaseSnapshot,\n SessionSnapshot,\n SessionStorySnapshot,\n} from '../core/session-state.js';\nimport { formatDuration, getIcons, type Icons } from './logger.js';\nimport { stripMarkdown } from './text.js';\n\nexport interface StatusViewOptions {\n /** Override icons (tests, or a caller that already resolved them). */\n icons?: Icons;\n /** Monitor URL, shown only when a web surface is actually up. */\n monitorUrl?: string | null;\n}\n\n/**\n * Pure projection of a `SessionSnapshot` into the clean terminal view.\n *\n * No I/O: the same function is what the renderer paints and what the tests\n * assert. The terminal does not compute a second, parallel view of the run.\n */\nexport function renderStatusView(\n snapshot: SessionSnapshot,\n options: StatusViewOptions = {},\n): string[] {\n const icons = options.icons ?? getIcons();\n const lines: string[] = [];\n\n const issue = formatIssueHeadline(snapshot);\n lines.push(issue);\n\n const location = formatLocationLine(snapshot, options.monitorUrl);\n if (location !== null) lines.push(location);\n\n lines.push('');\n\n for (const phase of snapshot.phases) {\n lines.push(formatPhaseLine(phase, snapshot, icons));\n }\n\n const focus = renderExecuteFocus(snapshot, { icons });\n if (focus.length > 0) {\n lines.push('');\n lines.push(...focus);\n }\n\n const footer = formatFooter(snapshot);\n if (footer !== null) {\n lines.push('');\n lines.push(` ${footer}`);\n }\n\n return lines;\n}\n\n/**\n * The live execute focus: active story plus current tool activity.\n *\n * Clean mode shows these two lines instead of one subtask per story.\n */\nexport function renderExecuteFocus(\n snapshot: SessionSnapshot,\n options: StatusViewOptions = {},\n): string[] {\n const icons = options.icons ?? getIcons();\n const story = activeStory(snapshot);\n if (story === undefined && snapshot.currentActivity === null) return [];\n\n const lines: string[] = [];\n if (story !== undefined) {\n const duration =\n story.durationSeconds !== null && story.durationSeconds !== undefined\n ? ` ${formatDuration(story.durationSeconds)}`\n : '';\n lines.push(` ${icons.pending} ${story.id} ${stripMarkdown(story.title)}${duration}`);\n }\n\n const activity = snapshot.currentActivity;\n if (activity?.tool) {\n const detail = activity.detail ? ` ${stripMarkdown(activity.detail)}` : '';\n lines.push(` ${activity.tool}${detail}`);\n }\n return lines;\n}\n\nexport function formatIssueHeadline(snapshot: SessionSnapshot): string {\n const number = snapshot.issue.number !== null ? `#${snapshot.issue.number}` : null;\n const title = snapshot.issue.title ? stripMarkdown(snapshot.issue.title) : null;\n const bits = ['Issue Flow', number, title].filter((bit): bit is string => bit !== null);\n return bits.join(' · ');\n}\n\nfunction formatLocationLine(\n snapshot: SessionSnapshot,\n monitorUrl: string | null | undefined,\n): string | null {\n const bits: string[] = [];\n if (snapshot.git.branch) bits.push(snapshot.git.branch);\n if (monitorUrl) bits.push(`monitor ${monitorUrl}`);\n return bits.length > 0 ? bits.join(' · ') : null;\n}\n\nfunction formatPhaseLine(\n phase: SessionPhaseSnapshot,\n snapshot: SessionSnapshot,\n icons: Icons,\n): string {\n const icon = phaseIcon(phase.status, icons);\n const label = phaseLabel(phase.name);\n const detail = phaseDetail(phase, snapshot);\n const duration =\n phase.durationSeconds !== null && phase.durationSeconds !== undefined\n ? formatDuration(phase.durationSeconds)\n : '';\n const body = detail === '' ? label : `${label} ${detail}`;\n return duration === '' ? ` ${icon} ${body}` : ` ${icon} ${body} ${duration}`;\n}\n\nfunction phaseIcon(status: SessionPhaseSnapshot['status'], icons: Icons): string {\n switch (status) {\n case 'completed':\n return icons.success;\n case 'failed':\n return icons.fail;\n case 'running':\n return icons.pending;\n default:\n return icons.notReached;\n }\n}\n\nfunction phaseLabel(name: string): string {\n if (name === 'prd') return 'PRD';\n if (name === 'pr-review') return 'PR Review';\n if (name === 'init') return 'Preflight';\n return name.charAt(0).toUpperCase() + name.slice(1);\n}\n\nfunction phaseDetail(phase: SessionPhaseSnapshot, snapshot: SessionSnapshot): string {\n if (phase.name !== 'execute') {\n if (phase.status === 'failed' && phase.error) return stripMarkdown(phase.error);\n return '';\n }\n const bits: string[] = [];\n const { storiesCompleted, storiesTotal } = snapshot.progress;\n if (storiesTotal > 0) bits.push(`${storiesCompleted}/${storiesTotal} stories`);\n if (snapshot.execution.iteration > 0) bits.push(`iteration ${snapshot.execution.iteration}`);\n if (snapshot.execution.retries > 0) bits.push(`${snapshot.execution.retries} retries`);\n return bits.join(' · ');\n}\n\nfunction formatFooter(snapshot: SessionSnapshot): string | null {\n const bits: string[] = [];\n if (snapshot.elapsedSeconds !== null) {\n bits.push(`elapsed ${formatDuration(snapshot.elapsedSeconds)}`);\n }\n if (snapshot.estimatedRemainingSeconds !== null) {\n bits.push(`remaining ~${formatDuration(snapshot.estimatedRemainingSeconds)}`);\n }\n if (snapshot.metrics.totalCostUsd !== null) {\n bits.push(`$${snapshot.metrics.totalCostUsd.toFixed(2)}`);\n }\n if (snapshot.execution.retries > 0) {\n bits.push(`${snapshot.execution.retries} retries`);\n }\n if (snapshot.verification?.verdict === 'unverified') {\n bits.push('unverified');\n } else if (snapshot.verification?.verdict === 'failed') {\n bits.push('contract failed');\n }\n return bits.length > 0 ? bits.join(' · ') : null;\n}\n\nfunction activeStory(snapshot: SessionSnapshot): SessionStorySnapshot | undefined {\n const fromActivity = snapshot.currentActivity?.story;\n if (fromActivity) {\n const match = snapshot.stories.find((story) => story.id === fromActivity);\n if (match) return match;\n }\n return snapshot.stories.find((story) => story.stage === 'executing');\n}\n"],"mappings":"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","names":["mkdir","summary","mkdir","failure"]}