issue-flow 0.13.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 (162) hide show
  1. package/dist/agent-OX3KPHE4.js +30 -0
  2. package/dist/{analyze-WS47UYGN.js → analyze-WIND2SEB.js} +21 -18
  3. package/dist/{analyze-WS47UYGN.js.map → analyze-WIND2SEB.js.map} +1 -1
  4. package/dist/{apply-OS62UWRN.js → apply-JNOI2LR4.js} +14 -11
  5. package/dist/{apply-OS62UWRN.js.map → apply-JNOI2LR4.js.map} +1 -1
  6. package/dist/{bench-SA3BOME5.js → bench-B4VZON7E.js} +30 -26
  7. package/dist/{bench-SA3BOME5.js.map → bench-B4VZON7E.js.map} +1 -1
  8. package/dist/{chunk-PIVGJM6K.js → chunk-2IQ6M4ZE.js} +11 -11
  9. package/dist/{chunk-QCXPNSEL.js → chunk-3BWZO4YI.js} +2 -2
  10. package/dist/chunk-3WFZETIM.js +163 -0
  11. package/dist/chunk-3WFZETIM.js.map +1 -0
  12. package/dist/{chunk-6FDFRNXZ.js → chunk-67YIU2VB.js} +25 -20
  13. package/dist/chunk-67YIU2VB.js.map +1 -0
  14. package/dist/{chunk-TM67EHSV.js → chunk-6BENHR2I.js} +19 -19
  15. package/dist/chunk-6BENHR2I.js.map +1 -0
  16. package/dist/{chunk-IYV6KNVF.js → chunk-6QYMSNVA.js} +66 -240
  17. package/dist/chunk-6QYMSNVA.js.map +1 -0
  18. package/dist/{chunk-IV5SS4JN.js → chunk-76MMPJ53.js} +9 -7
  19. package/dist/{chunk-IV5SS4JN.js.map → chunk-76MMPJ53.js.map} +1 -1
  20. package/dist/{chunk-LZ6GFQAG.js → chunk-B72RQZBV.js} +35 -25
  21. package/dist/chunk-B72RQZBV.js.map +1 -0
  22. package/dist/{chunk-KQHB7ZT3.js → chunk-BEZ5BA5U.js} +82 -16
  23. package/dist/chunk-BEZ5BA5U.js.map +1 -0
  24. package/dist/{chunk-BQDQTIM7.js → chunk-BRCNQXYQ.js} +4 -4
  25. package/dist/{chunk-ARFVHC2F.js → chunk-CGKLE6WR.js} +115 -23
  26. package/dist/chunk-CGKLE6WR.js.map +1 -0
  27. package/dist/{chunk-BHJCGWQX.js → chunk-F6TOYSYY.js} +9 -9
  28. package/dist/chunk-G5EK2XRN.js +25 -0
  29. package/dist/chunk-G5EK2XRN.js.map +1 -0
  30. package/dist/{chunk-TX5WIVYP.js → chunk-HAKDLR6N.js} +6 -1
  31. package/dist/chunk-HAKDLR6N.js.map +1 -0
  32. package/dist/{chunk-DIG5XKQQ.js → chunk-J3SOTUVI.js} +2 -2
  33. package/dist/{chunk-SNTTOQAD.js → chunk-JN6D3MY6.js} +2 -2
  34. package/dist/{chunk-MIVHK5YI.js → chunk-KMRFRXIT.js} +3 -3
  35. package/dist/{chunk-5TB6KLC2.js → chunk-KT7JKOXB.js} +8 -8
  36. package/dist/{chunk-NEZZ6KDR.js → chunk-LBGHI4S2.js} +49 -2
  37. package/dist/chunk-LBGHI4S2.js.map +1 -0
  38. package/dist/{chunk-3XLCNVMD.js → chunk-LEW4QM74.js} +2 -2
  39. package/dist/{chunk-IHIEXUTC.js → chunk-LFEQIZLB.js} +85 -10
  40. package/dist/chunk-LFEQIZLB.js.map +1 -0
  41. package/dist/{chunk-TVN2JVOF.js → chunk-OOVG2KBY.js} +3 -3
  42. package/dist/{chunk-7KD66LIM.js → chunk-OR43364P.js} +3 -3
  43. package/dist/{chunk-J62QSVP6.js → chunk-PBTA3QQX.js} +8 -7
  44. package/dist/{chunk-J62QSVP6.js.map → chunk-PBTA3QQX.js.map} +1 -1
  45. package/dist/{chunk-664Y3NDX.js → chunk-PHW2YV6N.js} +8 -8
  46. package/dist/{chunk-PV4OX5TC.js → chunk-PZTWU277.js} +11 -11
  47. package/dist/{chunk-HJGGNLWI.js → chunk-QD4VOILZ.js} +9 -9
  48. package/dist/{chunk-CNBYCMSU.js → chunk-QJ5UZAH5.js} +27 -18
  49. package/dist/{chunk-CNBYCMSU.js.map → chunk-QJ5UZAH5.js.map} +1 -1
  50. package/dist/{chunk-HQAHNIAR.js → chunk-QK7WUO7A.js} +14 -14
  51. package/dist/{chunk-UJ7XWK7J.js → chunk-QZVKRDJY.js} +16 -14
  52. package/dist/{chunk-UJ7XWK7J.js.map → chunk-QZVKRDJY.js.map} +1 -1
  53. package/dist/{chunk-FZDR7CGH.js → chunk-REO3PXXO.js} +3 -3
  54. package/dist/{chunk-UOCPC2Y2.js → chunk-RVO7L4FX.js} +4 -4
  55. package/dist/{chunk-QXDNBYQF.js → chunk-SZMHCEYV.js} +21 -10
  56. package/dist/chunk-SZMHCEYV.js.map +1 -0
  57. package/dist/chunk-TYRNTSPJ.js +243 -0
  58. package/dist/chunk-TYRNTSPJ.js.map +1 -0
  59. package/dist/{agent-BXRIEKVM.js → chunk-UJ3L2MS7.js} +22 -22
  60. package/dist/chunk-UJ3L2MS7.js.map +1 -0
  61. package/dist/{chunk-37N2RJW2.js → chunk-V7MO5EDS.js} +3 -3
  62. package/dist/{chunk-HEF2RMKN.js → chunk-WB2X37MO.js} +18 -16
  63. package/dist/{chunk-HEF2RMKN.js.map → chunk-WB2X37MO.js.map} +1 -1
  64. package/dist/{chunk-OPNGPUKJ.js → chunk-X44FKNKP.js} +133 -42
  65. package/dist/chunk-X44FKNKP.js.map +1 -0
  66. package/dist/cli.js +43 -40
  67. package/dist/cli.js.map +1 -1
  68. package/dist/{config-MEM2IWWN.js → config-HMFMCY2M.js} +12 -9
  69. package/dist/{conventions-WV4NDXGH.js → conventions-NJF2OPVQ.js} +14 -11
  70. package/dist/{conventions-WV4NDXGH.js.map → conventions-NJF2OPVQ.js.map} +1 -1
  71. package/dist/diagnostics-THH42ZMP.js +23 -0
  72. package/dist/execute-KFNNZZHI.js +35 -0
  73. package/dist/{generate-MVQI7A45.js → generate-FW5C6NP7.js} +23 -20
  74. package/dist/{generate-MVQI7A45.js.map → generate-FW5C6NP7.js.map} +1 -1
  75. package/dist/{git-YRVRUN3C.js → git-W72QQ6GT.js} +4 -2
  76. package/dist/init-HTN4V67Q.js +24 -0
  77. package/dist/{operations-LU6JA3BX.js → operations-BCFOBH42.js} +17 -14
  78. package/dist/{operations-LU6JA3BX.js.map → operations-BCFOBH42.js.map} +1 -1
  79. package/dist/{permissions-7NMDFU27.js → permissions-4AKNQZHK.js} +4 -4
  80. package/dist/plan-SIZLGA4V.js +34 -0
  81. package/dist/{policy-JSYEK5B2.js → policy-DT6Q6ZVM.js} +13 -10
  82. package/dist/{policy-JSYEK5B2.js.map → policy-DT6Q6ZVM.js.map} +1 -1
  83. package/dist/pr-OMWCGUOW.js +39 -0
  84. package/dist/pr-review-N24CZPKR.js +32 -0
  85. package/dist/prd-5OFTZAHJ.js +33 -0
  86. package/dist/{ps-TNE44R5V.js → ps-RFORTCUD.js} +11 -8
  87. package/dist/{ps-TNE44R5V.js.map → ps-RFORTCUD.js.map} +1 -1
  88. package/dist/{recorder-XGF55WXI.js → recorder-KCCPMKQG.js} +5 -4
  89. package/dist/registry-GLPXOMFG.js +15 -0
  90. package/dist/{resume-QMEPMSZW.js → resume-M5RLKP4I.js} +44 -40
  91. package/dist/{resume-QMEPMSZW.js.map → resume-M5RLKP4I.js.map} +1 -1
  92. package/dist/review-YM4JAABY.js +35 -0
  93. package/dist/{routing-2ZUMZPJB.js → routing-NNT5WKGX.js} +13 -10
  94. package/dist/{routing-2ZUMZPJB.js.map → routing-NNT5WKGX.js.map} +1 -1
  95. package/dist/run-PZUKHPQK.js +54 -0
  96. package/dist/run-PZUKHPQK.js.map +1 -0
  97. package/dist/session-publisher-T7EI3CIP.js +11 -0
  98. package/dist/session-publisher-T7EI3CIP.js.map +1 -0
  99. package/dist/{state-manager-X3PT3FGT.js → state-manager-GQH32C44.js} +3 -3
  100. package/dist/state-manager-GQH32C44.js.map +1 -0
  101. package/dist/{usage-VCFLDA5Y.js → usage-V2CHE5PY.js} +13 -10
  102. package/dist/{usage-VCFLDA5Y.js.map → usage-V2CHE5PY.js.map} +1 -1
  103. package/dist/{web-XVHLX62B.js → web-EA3KGNFN.js} +18 -14
  104. package/dist/{web-XVHLX62B.js.map → web-EA3KGNFN.js.map} +1 -1
  105. package/package.json +1 -1
  106. package/web/AGENTS.md +150 -11
  107. package/web/public/app.css +343 -110
  108. package/web/public/app.js +408 -18
  109. package/web/public/index.html +44 -1
  110. package/dist/agent-BXRIEKVM.js.map +0 -1
  111. package/dist/chunk-6FDFRNXZ.js.map +0 -1
  112. package/dist/chunk-ARFVHC2F.js.map +0 -1
  113. package/dist/chunk-IHIEXUTC.js.map +0 -1
  114. package/dist/chunk-IYV6KNVF.js.map +0 -1
  115. package/dist/chunk-KQHB7ZT3.js.map +0 -1
  116. package/dist/chunk-LZ6GFQAG.js.map +0 -1
  117. package/dist/chunk-NEZZ6KDR.js.map +0 -1
  118. package/dist/chunk-OPNGPUKJ.js.map +0 -1
  119. package/dist/chunk-QXDNBYQF.js.map +0 -1
  120. package/dist/chunk-TM67EHSV.js.map +0 -1
  121. package/dist/chunk-TX5WIVYP.js.map +0 -1
  122. package/dist/execute-NITIHHCK.js +0 -31
  123. package/dist/init-OKWEC3EV.js +0 -21
  124. package/dist/plan-LEJJF3DE.js +0 -31
  125. package/dist/pr-HPVUZ7S3.js +0 -36
  126. package/dist/pr-review-R2QZBT3F.js +0 -29
  127. package/dist/prd-5O6GYCC6.js +0 -30
  128. package/dist/registry-LGPE53QD.js +0 -15
  129. package/dist/review-YKWD6SNN.js +0 -32
  130. package/dist/run-YU4TR62R.js +0 -50
  131. /package/dist/{config-MEM2IWWN.js.map → agent-OX3KPHE4.js.map} +0 -0
  132. /package/dist/{chunk-PIVGJM6K.js.map → chunk-2IQ6M4ZE.js.map} +0 -0
  133. /package/dist/{chunk-QCXPNSEL.js.map → chunk-3BWZO4YI.js.map} +0 -0
  134. /package/dist/{chunk-BQDQTIM7.js.map → chunk-BRCNQXYQ.js.map} +0 -0
  135. /package/dist/{chunk-BHJCGWQX.js.map → chunk-F6TOYSYY.js.map} +0 -0
  136. /package/dist/{chunk-DIG5XKQQ.js.map → chunk-J3SOTUVI.js.map} +0 -0
  137. /package/dist/{chunk-SNTTOQAD.js.map → chunk-JN6D3MY6.js.map} +0 -0
  138. /package/dist/{chunk-MIVHK5YI.js.map → chunk-KMRFRXIT.js.map} +0 -0
  139. /package/dist/{chunk-5TB6KLC2.js.map → chunk-KT7JKOXB.js.map} +0 -0
  140. /package/dist/{chunk-3XLCNVMD.js.map → chunk-LEW4QM74.js.map} +0 -0
  141. /package/dist/{chunk-TVN2JVOF.js.map → chunk-OOVG2KBY.js.map} +0 -0
  142. /package/dist/{chunk-7KD66LIM.js.map → chunk-OR43364P.js.map} +0 -0
  143. /package/dist/{chunk-664Y3NDX.js.map → chunk-PHW2YV6N.js.map} +0 -0
  144. /package/dist/{chunk-PV4OX5TC.js.map → chunk-PZTWU277.js.map} +0 -0
  145. /package/dist/{chunk-HJGGNLWI.js.map → chunk-QD4VOILZ.js.map} +0 -0
  146. /package/dist/{chunk-HQAHNIAR.js.map → chunk-QK7WUO7A.js.map} +0 -0
  147. /package/dist/{chunk-FZDR7CGH.js.map → chunk-REO3PXXO.js.map} +0 -0
  148. /package/dist/{chunk-UOCPC2Y2.js.map → chunk-RVO7L4FX.js.map} +0 -0
  149. /package/dist/{chunk-37N2RJW2.js.map → chunk-V7MO5EDS.js.map} +0 -0
  150. /package/dist/{execute-NITIHHCK.js.map → config-HMFMCY2M.js.map} +0 -0
  151. /package/dist/{git-YRVRUN3C.js.map → diagnostics-THH42ZMP.js.map} +0 -0
  152. /package/dist/{init-OKWEC3EV.js.map → execute-KFNNZZHI.js.map} +0 -0
  153. /package/dist/{permissions-7NMDFU27.js.map → git-W72QQ6GT.js.map} +0 -0
  154. /package/dist/{plan-LEJJF3DE.js.map → init-HTN4V67Q.js.map} +0 -0
  155. /package/dist/{pr-HPVUZ7S3.js.map → permissions-4AKNQZHK.js.map} +0 -0
  156. /package/dist/{pr-review-R2QZBT3F.js.map → plan-SIZLGA4V.js.map} +0 -0
  157. /package/dist/{prd-5O6GYCC6.js.map → pr-OMWCGUOW.js.map} +0 -0
  158. /package/dist/{recorder-XGF55WXI.js.map → pr-review-N24CZPKR.js.map} +0 -0
  159. /package/dist/{registry-LGPE53QD.js.map → prd-5OFTZAHJ.js.map} +0 -0
  160. /package/dist/{review-YKWD6SNN.js.map → recorder-KCCPMKQG.js.map} +0 -0
  161. /package/dist/{run-YU4TR62R.js.map → registry-GLPXOMFG.js.map} +0 -0
  162. /package/dist/{state-manager-X3PT3FGT.js.map → review-YM4JAABY.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/ps.ts"],"sourcesContent":["import { z } from 'zod';\nimport { type LiveRun, listLiveRuns } from '../execution/registry.js';\nimport { formatDuration, printInfo } from '../ui/logger.js';\n\nexport const liveRunJsonSchema = z.object({\n schemaVersion: z.literal(1),\n runs: z.array(\n z.object({\n projectId: z.string(),\n target: z.string(),\n pid: z.number(),\n host: z.string(),\n detached: z.boolean(),\n status: z.enum(['running', 'unsignaled', 'orphan']),\n startedAt: z.string(),\n lastHeartbeatAt: z.string(),\n issue: z.number().nullable(),\n phase: z.string().nullable(),\n storiesCompleted: z.number().nullable(),\n storiesTotal: z.number().nullable(),\n elapsedSeconds: z.number().nullable(),\n }),\n ),\n});\n\nexport interface PsOptions {\n json?: boolean;\n watch?: boolean;\n}\n\nexport function formatPsTable(runs: readonly LiveRun[]): string[] {\n if (runs.length === 0) return ['No issue-flow run is active on this machine.'];\n\n const header = pad(['STATUS', 'ISSUE', 'PHASE', 'PROGRESS', 'ELAPSED', 'PID', 'PROJECT']);\n const rows = runs.map((run) =>\n pad([\n run.status,\n run.issue !== null ? `#${run.issue}` : run.target,\n run.phase ?? '—',\n run.storiesTotal !== null ? `${run.storiesCompleted ?? 0}/${run.storiesTotal}` : '—',\n run.elapsedSeconds !== null ? formatDuration(run.elapsedSeconds) : '—',\n String(run.pid),\n `${run.projectId}${run.detached ? ' (bg)' : ''}`,\n ]),\n );\n return [header, ...rows];\n}\n\nfunction pad(cells: string[]): string {\n const widths = [12, 10, 12, 10, 10, 8, 24];\n return cells.map((cell, i) => cell.padEnd(widths[i] ?? 12)).join(' ');\n}\n\nexport async function runPs(options: PsOptions = {}): Promise<number> {\n const render = async () => {\n const runs = await listLiveRuns();\n if (options.json === true) {\n const payload = liveRunJsonSchema.parse({\n schemaVersion: 1,\n runs: runs.map(({ lockFile: _lockFile, ...rest }) => rest),\n });\n printInfo(JSON.stringify(payload, null, 2));\n return runs.length;\n }\n for (const line of formatPsTable(runs)) {\n printInfo(line);\n }\n return runs.length;\n };\n\n if (options.watch === true) {\n for (;;) {\n await render();\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n\n await render();\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS;AAIX,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,eAAe,EAAE,QAAQ,CAAC;AAAA,EAC1B,MAAM,EAAE;AAAA,IACN,EAAE,OAAO;AAAA,MACP,WAAW,EAAE,OAAO;AAAA,MACpB,QAAQ,EAAE,OAAO;AAAA,MACjB,KAAK,EAAE,OAAO;AAAA,MACd,MAAM,EAAE,OAAO;AAAA,MACf,UAAU,EAAE,QAAQ;AAAA,MACpB,QAAQ,EAAE,KAAK,CAAC,WAAW,cAAc,QAAQ,CAAC;AAAA,MAClD,WAAW,EAAE,OAAO;AAAA,MACpB,iBAAiB,EAAE,OAAO;AAAA,MAC1B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,MACtC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,MAClC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,IACtC,CAAC;AAAA,EACH;AACF,CAAC;AAOM,SAAS,cAAc,MAAoC;AAChE,MAAI,KAAK,WAAW,EAAG,QAAO,CAAC,8CAA8C;AAE7E,QAAM,SAAS,IAAI,CAAC,UAAU,SAAS,SAAS,YAAY,WAAW,OAAO,SAAS,CAAC;AACxF,QAAM,OAAO,KAAK;AAAA,IAAI,CAAC,QACrB,IAAI;AAAA,MACF,IAAI;AAAA,MACJ,IAAI,UAAU,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI;AAAA,MAC3C,IAAI,SAAS;AAAA,MACb,IAAI,iBAAiB,OAAO,GAAG,IAAI,oBAAoB,CAAC,IAAI,IAAI,YAAY,KAAK;AAAA,MACjF,IAAI,mBAAmB,OAAO,eAAe,IAAI,cAAc,IAAI;AAAA,MACnE,OAAO,IAAI,GAAG;AAAA,MACd,GAAG,IAAI,SAAS,GAAG,IAAI,WAAW,UAAU,EAAE;AAAA,IAChD,CAAC;AAAA,EACH;AACA,SAAO,CAAC,QAAQ,GAAG,IAAI;AACzB;AAEA,SAAS,IAAI,OAAyB;AACpC,QAAM,SAAS,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE;AACzC,SAAO,MAAM,IAAI,CAAC,MAAM,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG;AACtE;AAEA,eAAsB,MAAM,UAAqB,CAAC,GAAoB;AACpE,QAAM,SAAS,YAAY;AACzB,UAAM,OAAO,MAAM,aAAa;AAChC,QAAI,QAAQ,SAAS,MAAM;AACzB,YAAM,UAAU,kBAAkB,MAAM;AAAA,QACtC,eAAe;AAAA,QACf,MAAM,KAAK,IAAI,CAAC,EAAE,UAAU,WAAW,GAAG,KAAK,MAAM,IAAI;AAAA,MAC3D,CAAC;AACD,gBAAU,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC1C,aAAO,KAAK;AAAA,IACd;AACA,eAAW,QAAQ,cAAc,IAAI,GAAG;AACtC,gBAAU,IAAI;AAAA,IAChB;AACA,WAAO,KAAK;AAAA,EACd;AAEA,MAAI,QAAQ,UAAU,MAAM;AAC1B,eAAS;AACP,YAAM,OAAO;AACb,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,OAAO;AACb,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/commands/ps.ts"],"sourcesContent":["import { z } from 'zod';\nimport { type LiveRun, listLiveRuns } from '../execution/registry.js';\nimport { formatDuration, printInfo } from '../ui/logger.js';\n\nexport const liveRunJsonSchema = z.object({\n schemaVersion: z.literal(1),\n runs: z.array(\n z.object({\n projectId: z.string(),\n target: z.string(),\n pid: z.number(),\n host: z.string(),\n detached: z.boolean(),\n status: z.enum(['running', 'unsignaled', 'orphan']),\n startedAt: z.string(),\n lastHeartbeatAt: z.string(),\n issue: z.number().nullable(),\n phase: z.string().nullable(),\n storiesCompleted: z.number().nullable(),\n storiesTotal: z.number().nullable(),\n elapsedSeconds: z.number().nullable(),\n }),\n ),\n});\n\nexport interface PsOptions {\n json?: boolean;\n watch?: boolean;\n}\n\nexport function formatPsTable(runs: readonly LiveRun[]): string[] {\n if (runs.length === 0) return ['No issue-flow run is active on this machine.'];\n\n const header = pad(['STATUS', 'ISSUE', 'PHASE', 'PROGRESS', 'ELAPSED', 'PID', 'PROJECT']);\n const rows = runs.map((run) =>\n pad([\n run.status,\n run.issue !== null ? `#${run.issue}` : run.target,\n run.phase ?? '—',\n run.storiesTotal !== null ? `${run.storiesCompleted ?? 0}/${run.storiesTotal}` : '—',\n run.elapsedSeconds !== null ? formatDuration(run.elapsedSeconds) : '—',\n String(run.pid),\n `${run.projectId}${run.detached ? ' (bg)' : ''}`,\n ]),\n );\n return [header, ...rows];\n}\n\nfunction pad(cells: string[]): string {\n const widths = [12, 10, 12, 10, 10, 8, 24];\n return cells.map((cell, i) => cell.padEnd(widths[i] ?? 12)).join(' ');\n}\n\nexport async function runPs(options: PsOptions = {}): Promise<number> {\n const render = async () => {\n const runs = await listLiveRuns();\n if (options.json === true) {\n const payload = liveRunJsonSchema.parse({\n schemaVersion: 1,\n runs: runs.map(({ lockFile: _lockFile, ...rest }) => rest),\n });\n printInfo(JSON.stringify(payload, null, 2));\n return runs.length;\n }\n for (const line of formatPsTable(runs)) {\n printInfo(line);\n }\n return runs.length;\n };\n\n if (options.watch === true) {\n for (;;) {\n await render();\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n\n await render();\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,SAAS;AAIX,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,eAAe,EAAE,QAAQ,CAAC;AAAA,EAC1B,MAAM,EAAE;AAAA,IACN,EAAE,OAAO;AAAA,MACP,WAAW,EAAE,OAAO;AAAA,MACpB,QAAQ,EAAE,OAAO;AAAA,MACjB,KAAK,EAAE,OAAO;AAAA,MACd,MAAM,EAAE,OAAO;AAAA,MACf,UAAU,EAAE,QAAQ;AAAA,MACpB,QAAQ,EAAE,KAAK,CAAC,WAAW,cAAc,QAAQ,CAAC;AAAA,MAClD,WAAW,EAAE,OAAO;AAAA,MACpB,iBAAiB,EAAE,OAAO;AAAA,MAC1B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,MAC3B,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,MACtC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,MAClC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,IACtC,CAAC;AAAA,EACH;AACF,CAAC;AAOM,SAAS,cAAc,MAAoC;AAChE,MAAI,KAAK,WAAW,EAAG,QAAO,CAAC,8CAA8C;AAE7E,QAAM,SAAS,IAAI,CAAC,UAAU,SAAS,SAAS,YAAY,WAAW,OAAO,SAAS,CAAC;AACxF,QAAM,OAAO,KAAK;AAAA,IAAI,CAAC,QACrB,IAAI;AAAA,MACF,IAAI;AAAA,MACJ,IAAI,UAAU,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI;AAAA,MAC3C,IAAI,SAAS;AAAA,MACb,IAAI,iBAAiB,OAAO,GAAG,IAAI,oBAAoB,CAAC,IAAI,IAAI,YAAY,KAAK;AAAA,MACjF,IAAI,mBAAmB,OAAO,eAAe,IAAI,cAAc,IAAI;AAAA,MACnE,OAAO,IAAI,GAAG;AAAA,MACd,GAAG,IAAI,SAAS,GAAG,IAAI,WAAW,UAAU,EAAE;AAAA,IAChD,CAAC;AAAA,EACH;AACA,SAAO,CAAC,QAAQ,GAAG,IAAI;AACzB;AAEA,SAAS,IAAI,OAAyB;AACpC,QAAM,SAAS,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,EAAE;AACzC,SAAO,MAAM,IAAI,CAAC,MAAM,MAAM,KAAK,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG;AACtE;AAEA,eAAsB,MAAM,UAAqB,CAAC,GAAoB;AACpE,QAAM,SAAS,YAAY;AACzB,UAAM,OAAO,MAAM,aAAa;AAChC,QAAI,QAAQ,SAAS,MAAM;AACzB,YAAM,UAAU,kBAAkB,MAAM;AAAA,QACtC,eAAe;AAAA,QACf,MAAM,KAAK,IAAI,CAAC,EAAE,UAAU,WAAW,GAAG,KAAK,MAAM,IAAI;AAAA,MAC3D,CAAC;AACD,gBAAU,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC1C,aAAO,KAAK;AAAA,IACd;AACA,eAAW,QAAQ,cAAc,IAAI,GAAG;AACtC,gBAAU,IAAI;AAAA,IAChB;AACA,WAAO,KAAK;AAAA,EACd;AAEA,MAAI,QAAQ,UAAU,MAAM;AAC1B,eAAS;AACP,YAAM,OAAO;AACb,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,OAAO;AACb,SAAO;AACT;","names":[]}
@@ -10,10 +10,11 @@ import {
10
10
  resetTelemetryState,
11
11
  timingFromUsage,
12
12
  usageFromClaude
13
- } from "./chunk-6FDFRNXZ.js";
13
+ } from "./chunk-67YIU2VB.js";
14
14
  import "./chunk-P3LRUNC6.js";
15
- import "./chunk-DIG5XKQQ.js";
16
- import "./chunk-NEZZ6KDR.js";
15
+ import "./chunk-G5EK2XRN.js";
16
+ import "./chunk-J3SOTUVI.js";
17
+ import "./chunk-LBGHI4S2.js";
17
18
  import "./chunk-7Z4Y3VKM.js";
18
19
  import "./chunk-XEYH6ZZI.js";
19
20
  export {
@@ -28,4 +29,4 @@ export {
28
29
  timingFromUsage,
29
30
  usageFromClaude
30
31
  };
31
- //# sourceMappingURL=recorder-XGF55WXI.js.map
32
+ //# sourceMappingURL=recorder-KCCPMKQG.js.map
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ classifyRunLock,
4
+ listLiveRuns
5
+ } from "./chunk-KT7JKOXB.js";
6
+ import "./chunk-JN6D3MY6.js";
7
+ import "./chunk-HAKDLR6N.js";
8
+ import "./chunk-BEZ5BA5U.js";
9
+ import "./chunk-LBGHI4S2.js";
10
+ import "./chunk-XEYH6ZZI.js";
11
+ export {
12
+ classifyRunLock,
13
+ listLiveRuns
14
+ };
15
+ //# sourceMappingURL=registry-GLPXOMFG.js.map
@@ -1,67 +1,71 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runPipeline
4
- } from "./chunk-OPNGPUKJ.js";
5
- import "./chunk-37N2RJW2.js";
6
- import "./chunk-QXDNBYQF.js";
4
+ } from "./chunk-X44FKNKP.js";
5
+ import "./chunk-V7MO5EDS.js";
6
+ import "./chunk-QZVKRDJY.js";
7
+ import "./chunk-QD4VOILZ.js";
8
+ import "./chunk-SZMHCEYV.js";
7
9
  import {
8
10
  PIPELINE_PHASES,
9
11
  PipelineManager,
10
12
  loadExecutionPlan,
11
13
  nextQueueIssue
12
- } from "./chunk-7KD66LIM.js";
13
- import "./chunk-BHJCGWQX.js";
14
- import "./chunk-LZ6GFQAG.js";
15
- import "./chunk-IHIEXUTC.js";
16
- import "./chunk-BQDQTIM7.js";
17
- import "./chunk-HEF2RMKN.js";
14
+ } from "./chunk-OR43364P.js";
15
+ import "./chunk-F6TOYSYY.js";
16
+ import "./chunk-B72RQZBV.js";
17
+ import "./chunk-LFEQIZLB.js";
18
+ import "./chunk-BRCNQXYQ.js";
19
+ import "./chunk-WB2X37MO.js";
18
20
  import "./chunk-CRGIQFUQ.js";
19
- import "./chunk-TM67EHSV.js";
20
- import "./chunk-PIVGJM6K.js";
21
- import "./chunk-UJ7XWK7J.js";
22
- import "./chunk-J62QSVP6.js";
23
- import "./chunk-HJGGNLWI.js";
24
- import "./chunk-IV5SS4JN.js";
25
- import "./chunk-FZDR7CGH.js";
26
- import "./chunk-PV4OX5TC.js";
21
+ import "./chunk-L6HSKTQE.js";
22
+ import "./chunk-UJ3L2MS7.js";
23
+ import "./chunk-6BENHR2I.js";
24
+ import "./chunk-2IQ6M4ZE.js";
25
+ import "./chunk-PBTA3QQX.js";
26
+ import "./chunk-76MMPJ53.js";
27
+ import "./chunk-REO3PXXO.js";
28
+ import "./chunk-PZTWU277.js";
27
29
  import "./chunk-KMMASOA6.js";
28
- import "./chunk-664Y3NDX.js";
29
- import "./chunk-MIVHK5YI.js";
30
- import "./chunk-ARFVHC2F.js";
31
- import "./chunk-3XLCNVMD.js";
30
+ import "./chunk-PHW2YV6N.js";
31
+ import "./chunk-KMRFRXIT.js";
32
+ import "./chunk-CGKLE6WR.js";
33
+ import "./chunk-LEW4QM74.js";
32
34
  import {
33
35
  parseJournal
34
- } from "./chunk-QCXPNSEL.js";
36
+ } from "./chunk-3BWZO4YI.js";
37
+ import "./chunk-OOVG2KBY.js";
35
38
  import "./chunk-3D4A4B46.js";
36
- import "./chunk-UOCPC2Y2.js";
37
- import "./chunk-CNBYCMSU.js";
39
+ import "./chunk-RVO7L4FX.js";
40
+ import "./chunk-QJ5UZAH5.js";
38
41
  import {
39
42
  resolveProjectPaths
40
- } from "./chunk-HQAHNIAR.js";
43
+ } from "./chunk-QK7WUO7A.js";
41
44
  import {
42
45
  printError,
43
46
  printInfo,
44
47
  printWarning
45
- } from "./chunk-IYV6KNVF.js";
46
- import "./chunk-6FDFRNXZ.js";
47
- import "./chunk-P3LRUNC6.js";
48
- import {
49
- loadTaskPlan
50
- } from "./chunk-DIG5XKQQ.js";
51
- import {
52
- acquireRunLock,
53
- describeRunLockOwner
54
- } from "./chunk-NEZZ6KDR.js";
55
- import "./chunk-L6HSKTQE.js";
56
- import "./chunk-TVN2JVOF.js";
48
+ } from "./chunk-TYRNTSPJ.js";
49
+ import "./chunk-6QYMSNVA.js";
50
+ import "./chunk-3WFZETIM.js";
57
51
  import {
58
52
  QUEUES_DIR_NAME,
59
53
  getIssuePaths
60
- } from "./chunk-TX5WIVYP.js";
54
+ } from "./chunk-HAKDLR6N.js";
61
55
  import {
62
56
  describePreflight,
63
57
  preflightRepository
64
- } from "./chunk-KQHB7ZT3.js";
58
+ } from "./chunk-BEZ5BA5U.js";
59
+ import "./chunk-67YIU2VB.js";
60
+ import "./chunk-P3LRUNC6.js";
61
+ import "./chunk-G5EK2XRN.js";
62
+ import {
63
+ loadTaskPlan
64
+ } from "./chunk-J3SOTUVI.js";
65
+ import {
66
+ acquireRunLock,
67
+ describeRunLockOwner
68
+ } from "./chunk-LBGHI4S2.js";
65
69
  import "./chunk-7Z4Y3VKM.js";
66
70
  import "./chunk-XEYH6ZZI.js";
67
71
 
@@ -235,4 +239,4 @@ async function loadTarget(projectId, issue) {
235
239
  export {
236
240
  runResume
237
241
  };
238
- //# sourceMappingURL=resume-QMEPMSZW.js.map
242
+ //# sourceMappingURL=resume-M5RLKP4I.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/resume.ts"],"sourcesContent":["import { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parseJournal } from '../core/journal.js';\nimport { PIPELINE_PHASES, PipelineManager, type PipelinePhase } from '../core/pipeline.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { loadExecutionPlan, nextQueueIssue } from '../execution/plan.js';\nimport { acquireRunLock, describeRunLockOwner, type RunLockHandle } from '../storage/lock.js';\nimport { getIssuePaths, QUEUES_DIR_NAME } from '../storage/paths.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport type { TaskPlan } from '../types.js';\nimport { printError, printInfo, printWarning } from '../ui/logger.js';\nimport { describePreflight, preflightRepository } from '../utils/git.js';\nimport { runPipeline } from './run.js';\n\n/**\n * `issue-flow resume` — explicit recovery.\n *\n * Resumption already worked before this command existed, but only *implicitly*:\n * the user re-ran the same `run` and the pipeline happened to pick up where it\n * left off, because `PipelineManager` skips the phases already marked complete\n * and `nextQueueIssue()` treats a stale `in_progress` as \"do this one first\".\n * That is a coincidence of two mechanisms, not a contract — nothing said what\n * had been interrupted, nothing checked whether the repository was still in a\n * state to continue, and nothing distinguished \"carry on\" from \"start over\".\n *\n * This command makes each of those steps explicit, in this order:\n *\n * 1. **ownership** — a live owner refuses, a dead one is taken over;\n * 2. **plans** — `execution-plan.json` for a queue, `tasks.json` for an issue;\n * 3. **the journal** — the last `phase:start` with no `phase:end` is what was\n * running when the process died, which is the one fact no snapshot keeps;\n * 4. **the preflight** — the repository is described, and a state a human has to\n * settle stops the resume instead of being repaired;\n * 5. **the phase** — `PipelineManager.getNextPhase()`, the same answer `run`\n * has always used, now stated out loud before anything runs.\n *\n * `run` is untouched: its auto-resume still works exactly as it did.\n */\n\nexport interface ResumeOptions {\n /** Resume every unfinished issue of the project, not just one. */\n all?: boolean;\n /** Execution mode handed to the pipeline. Same values as `run`. */\n mode?: string;\n}\n\ninterface ResumeTarget {\n issue: string;\n plan: TaskPlan;\n tasksFile: string;\n eventsFile: string;\n rotatedEventsFile: string;\n}\n\nexport async function runResume(issue?: string, options: ResumeOptions = {}): Promise<number> {\n const mode = options.mode ?? 'auto';\n\n let project: Awaited<ReturnType<typeof resolveProjectPaths>>;\n try {\n project = await resolveProjectPaths();\n } catch (err) {\n printError(`Cannot resume: ${err instanceof Error ? err.message : String(err)}`);\n return 1;\n }\n\n // 1. Ownership, before reading anything else: a resume that runs beside a\n // live owner is the collision this whole layer exists to prevent.\n const acquisition = await acquireRunLock(project.runLockFile, { target: issue ?? 'resume' });\n if (!acquisition.ok) {\n printError(\n `Another issue-flow run owns this project: ${describeRunLockOwner(acquisition.owner)}.`,\n );\n printInfo('Wait for it to finish, or stop that process before resuming.');\n return 1;\n }\n const handle: RunLockHandle = acquisition.handle;\n if (handle.reclaimedFrom !== null) {\n printWarning(\n `Taking over an interrupted run: ${describeRunLockOwner(handle.reclaimedFrom)}. Its lock was stale.`,\n );\n }\n\n try {\n // 2. What is there to resume.\n const targets = await findTargets(project, issue, options.all === true);\n if (targets.length === 0) {\n printInfo(\n issue === undefined\n ? 'Nothing to resume: no issue in this project has an unfinished pipeline.'\n : `Nothing to resume: issue #${issue} has no task plan in this project.`,\n );\n return 0;\n }\n\n for (const target of targets) {\n const code = await resumeOne(target, mode);\n if (code !== 0) return code;\n }\n return 0;\n } finally {\n await handle.release();\n }\n}\n\nasync function resumeOne(target: ResumeTarget, mode: string): Promise<number> {\n const phases = activePhases(target.plan);\n const manager = new PipelineManager(target.plan, target.tasksFile, phases);\n const next = manager.getNextPhase();\n\n if (next === null) {\n printInfo(`Issue #${target.issue} has every phase complete; nothing to resume.`);\n return 0;\n }\n\n // 3. What was running when the process died. The snapshot cannot answer this\n // — it only knows the phase failed or never ended — so the journal does.\n const interrupted = await lastUnfinishedPhase(target);\n if (interrupted !== null) {\n printInfo(`Issue #${target.issue} was interrupted during the '${interrupted}' phase.`);\n }\n\n // 4. The repository, described and never repaired. Continuing the very phase\n // that was interrupted is the one case where uncommitted work is expected;\n // anything else would be carrying changes into work they do not belong to.\n const sameWork = interrupted === next;\n const preflight = await preflightRepository({\n expectedBranch: target.plan.noBranch === true ? null : target.plan.branchName,\n intent: sameWork ? 'resume-same-phase' : 'new-phase',\n });\n if (!preflight.ok) {\n printError(`Cannot resume issue #${target.issue}: the repository needs attention first.`);\n for (const line of describePreflight(preflight)) {\n printError(line);\n }\n return 1;\n }\n\n // 5. The phase, stated before anything runs.\n printInfo(`Resuming issue #${target.issue} from the '${next}' phase.`);\n return runPipeline(target.issue, mode, next, undefined, undefined, { only: true });\n}\n\n/** The phase set this plan's pipeline actually has, so `pr-review` is honoured. */\nfunction activePhases(plan: TaskPlan): readonly PipelinePhase[] {\n const base =\n plan.noBranch === true\n ? PIPELINE_PHASES.filter((phase) => phase !== 'pr')\n : [...PIPELINE_PHASES];\n return plan.prReview?.enabled === true ? [...base, 'pr-review'] : base;\n}\n\n/**\n * The phase the journal shows as started and never ended.\n *\n * Both generations are read, oldest first, because a run long enough to rotate\n * its journal is exactly the kind that gets interrupted. A missing or\n * unreadable journal answers `null`: the resume continues from the plan, which\n * is what it did before a journal existed.\n */\nasync function lastUnfinishedPhase(target: ResumeTarget): Promise<string | null> {\n const content = `${await readIfPresent(target.rotatedEventsFile)}${await readIfPresent(target.eventsFile)}`;\n if (content === '') return null;\n\n const open: string[] = [];\n for (const entry of parseJournal(content)) {\n const event = entry.event;\n if (event.type === 'phase:start') {\n open.push(event.phase);\n } else if (event.type === 'phase:end') {\n const index = open.lastIndexOf(event.phase);\n if (index >= 0) open.splice(index, 1);\n }\n }\n return open.at(-1) ?? null;\n}\n\nasync function readIfPresent(path: string): Promise<string> {\n try {\n return await readFile(path, 'utf-8');\n } catch {\n return '';\n }\n}\n\n/**\n * Which issues to resume.\n *\n * A named issue is taken at its word. Without one, the queue decides when there\n * is a queue — `nextQueueIssue()` is already the project's answer to \"which one\n * first\" — and otherwise the unfinished issues are ordered by when they were\n * last attempted, so `resume` alone picks up the most recent work.\n */\nasync function findTargets(\n project: Awaited<ReturnType<typeof resolveProjectPaths>>,\n issue: string | undefined,\n all: boolean,\n): Promise<ResumeTarget[]> {\n if (issue !== undefined) {\n const target = await loadTarget(project.projectId, issue);\n return target === null ? [] : [target];\n }\n\n const queued = await queueTarget(project);\n if (queued !== null && !all) return [queued];\n\n const unfinished = await unfinishedTargets(project);\n if (all) return unfinished;\n return unfinished.slice(0, 1);\n}\n\n/** The issue a queue would hand out next, when this project has a queue. */\nasync function queueTarget(\n project: Awaited<ReturnType<typeof resolveProjectPaths>>,\n): Promise<ResumeTarget | null> {\n const queuesDir = join(project.projectDir, QUEUES_DIR_NAME);\n let entries: string[];\n try {\n entries = await readdir(queuesDir);\n } catch {\n return null;\n }\n\n for (const entry of entries) {\n const plan = await loadExecutionPlan(join(queuesDir, entry, 'execution-plan.json'));\n if (plan === null) continue;\n const next = nextQueueIssue(plan);\n if (next === null) continue;\n const target = await loadTarget(project.projectId, next.id);\n if (target !== null) return target;\n }\n return null;\n}\n\n/** Every issue whose plan is not finished, most recently attempted first. */\nasync function unfinishedTargets(\n project: Awaited<ReturnType<typeof resolveProjectPaths>>,\n): Promise<ResumeTarget[]> {\n let ids: string[];\n try {\n ids = await readdir(project.issuesDir);\n } catch {\n return [];\n }\n\n const targets: ResumeTarget[] = [];\n for (const id of ids) {\n const target = await loadTarget(project.projectId, id);\n if (target === null) continue;\n if (target.plan.issueStatus === 'completed') continue;\n const manager = new PipelineManager(target.plan, target.tasksFile, activePhases(target.plan));\n if (manager.getNextPhase() === null) continue;\n targets.push(target);\n }\n\n return targets.sort((a, b) => attemptedAt(b.plan) - attemptedAt(a.plan));\n}\n\nfunction attemptedAt(plan: TaskPlan): number {\n const at = Date.parse(plan.lastAttemptAt ?? '');\n return Number.isNaN(at) ? 0 : at;\n}\n\nasync function loadTarget(projectId: string, issue: string): Promise<ResumeTarget | null> {\n let paths: ReturnType<typeof getIssuePaths>;\n try {\n paths = getIssuePaths(projectId, issue);\n } catch {\n // Not a usable issue identifier — a stray file in `issues/`, for instance.\n return null;\n }\n\n try {\n const plan = await loadTaskPlan(paths.tasksFile);\n return {\n issue,\n plan,\n tasksFile: paths.tasksFile,\n eventsFile: paths.eventsFile,\n rotatedEventsFile: paths.rotatedEventsFile,\n };\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/resume.ts"],"sourcesContent":["import { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { parseJournal } from '../core/journal.js';\nimport { PIPELINE_PHASES, PipelineManager, type PipelinePhase } from '../core/pipeline.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { loadExecutionPlan, nextQueueIssue } from '../execution/plan.js';\nimport { acquireRunLock, describeRunLockOwner, type RunLockHandle } from '../storage/lock.js';\nimport { getIssuePaths, QUEUES_DIR_NAME } from '../storage/paths.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport type { TaskPlan } from '../types.js';\nimport { printError, printInfo, printWarning } from '../ui/logger.js';\nimport { describePreflight, preflightRepository } from '../utils/git.js';\nimport { runPipeline } from './run.js';\n\n/**\n * `issue-flow resume` — explicit recovery.\n *\n * Resumption already worked before this command existed, but only *implicitly*:\n * the user re-ran the same `run` and the pipeline happened to pick up where it\n * left off, because `PipelineManager` skips the phases already marked complete\n * and `nextQueueIssue()` treats a stale `in_progress` as \"do this one first\".\n * That is a coincidence of two mechanisms, not a contract — nothing said what\n * had been interrupted, nothing checked whether the repository was still in a\n * state to continue, and nothing distinguished \"carry on\" from \"start over\".\n *\n * This command makes each of those steps explicit, in this order:\n *\n * 1. **ownership** — a live owner refuses, a dead one is taken over;\n * 2. **plans** — `execution-plan.json` for a queue, `tasks.json` for an issue;\n * 3. **the journal** — the last `phase:start` with no `phase:end` is what was\n * running when the process died, which is the one fact no snapshot keeps;\n * 4. **the preflight** — the repository is described, and a state a human has to\n * settle stops the resume instead of being repaired;\n * 5. **the phase** — `PipelineManager.getNextPhase()`, the same answer `run`\n * has always used, now stated out loud before anything runs.\n *\n * `run` is untouched: its auto-resume still works exactly as it did.\n */\n\nexport interface ResumeOptions {\n /** Resume every unfinished issue of the project, not just one. */\n all?: boolean;\n /** Execution mode handed to the pipeline. Same values as `run`. */\n mode?: string;\n}\n\ninterface ResumeTarget {\n issue: string;\n plan: TaskPlan;\n tasksFile: string;\n eventsFile: string;\n rotatedEventsFile: string;\n}\n\nexport async function runResume(issue?: string, options: ResumeOptions = {}): Promise<number> {\n const mode = options.mode ?? 'auto';\n\n let project: Awaited<ReturnType<typeof resolveProjectPaths>>;\n try {\n project = await resolveProjectPaths();\n } catch (err) {\n printError(`Cannot resume: ${err instanceof Error ? err.message : String(err)}`);\n return 1;\n }\n\n // 1. Ownership, before reading anything else: a resume that runs beside a\n // live owner is the collision this whole layer exists to prevent.\n const acquisition = await acquireRunLock(project.runLockFile, { target: issue ?? 'resume' });\n if (!acquisition.ok) {\n printError(\n `Another issue-flow run owns this project: ${describeRunLockOwner(acquisition.owner)}.`,\n );\n printInfo('Wait for it to finish, or stop that process before resuming.');\n return 1;\n }\n const handle: RunLockHandle = acquisition.handle;\n if (handle.reclaimedFrom !== null) {\n printWarning(\n `Taking over an interrupted run: ${describeRunLockOwner(handle.reclaimedFrom)}. Its lock was stale.`,\n );\n }\n\n try {\n // 2. What is there to resume.\n const targets = await findTargets(project, issue, options.all === true);\n if (targets.length === 0) {\n printInfo(\n issue === undefined\n ? 'Nothing to resume: no issue in this project has an unfinished pipeline.'\n : `Nothing to resume: issue #${issue} has no task plan in this project.`,\n );\n return 0;\n }\n\n for (const target of targets) {\n const code = await resumeOne(target, mode);\n if (code !== 0) return code;\n }\n return 0;\n } finally {\n await handle.release();\n }\n}\n\nasync function resumeOne(target: ResumeTarget, mode: string): Promise<number> {\n const phases = activePhases(target.plan);\n const manager = new PipelineManager(target.plan, target.tasksFile, phases);\n const next = manager.getNextPhase();\n\n if (next === null) {\n printInfo(`Issue #${target.issue} has every phase complete; nothing to resume.`);\n return 0;\n }\n\n // 3. What was running when the process died. The snapshot cannot answer this\n // — it only knows the phase failed or never ended — so the journal does.\n const interrupted = await lastUnfinishedPhase(target);\n if (interrupted !== null) {\n printInfo(`Issue #${target.issue} was interrupted during the '${interrupted}' phase.`);\n }\n\n // 4. The repository, described and never repaired. Continuing the very phase\n // that was interrupted is the one case where uncommitted work is expected;\n // anything else would be carrying changes into work they do not belong to.\n const sameWork = interrupted === next;\n const preflight = await preflightRepository({\n expectedBranch: target.plan.noBranch === true ? null : target.plan.branchName,\n intent: sameWork ? 'resume-same-phase' : 'new-phase',\n });\n if (!preflight.ok) {\n printError(`Cannot resume issue #${target.issue}: the repository needs attention first.`);\n for (const line of describePreflight(preflight)) {\n printError(line);\n }\n return 1;\n }\n\n // 5. The phase, stated before anything runs.\n printInfo(`Resuming issue #${target.issue} from the '${next}' phase.`);\n return runPipeline(target.issue, mode, next, undefined, undefined, { only: true });\n}\n\n/** The phase set this plan's pipeline actually has, so `pr-review` is honoured. */\nfunction activePhases(plan: TaskPlan): readonly PipelinePhase[] {\n const base =\n plan.noBranch === true\n ? PIPELINE_PHASES.filter((phase) => phase !== 'pr')\n : [...PIPELINE_PHASES];\n return plan.prReview?.enabled === true ? [...base, 'pr-review'] : base;\n}\n\n/**\n * The phase the journal shows as started and never ended.\n *\n * Both generations are read, oldest first, because a run long enough to rotate\n * its journal is exactly the kind that gets interrupted. A missing or\n * unreadable journal answers `null`: the resume continues from the plan, which\n * is what it did before a journal existed.\n */\nasync function lastUnfinishedPhase(target: ResumeTarget): Promise<string | null> {\n const content = `${await readIfPresent(target.rotatedEventsFile)}${await readIfPresent(target.eventsFile)}`;\n if (content === '') return null;\n\n const open: string[] = [];\n for (const entry of parseJournal(content)) {\n const event = entry.event;\n if (event.type === 'phase:start') {\n open.push(event.phase);\n } else if (event.type === 'phase:end') {\n const index = open.lastIndexOf(event.phase);\n if (index >= 0) open.splice(index, 1);\n }\n }\n return open.at(-1) ?? null;\n}\n\nasync function readIfPresent(path: string): Promise<string> {\n try {\n return await readFile(path, 'utf-8');\n } catch {\n return '';\n }\n}\n\n/**\n * Which issues to resume.\n *\n * A named issue is taken at its word. Without one, the queue decides when there\n * is a queue — `nextQueueIssue()` is already the project's answer to \"which one\n * first\" — and otherwise the unfinished issues are ordered by when they were\n * last attempted, so `resume` alone picks up the most recent work.\n */\nasync function findTargets(\n project: Awaited<ReturnType<typeof resolveProjectPaths>>,\n issue: string | undefined,\n all: boolean,\n): Promise<ResumeTarget[]> {\n if (issue !== undefined) {\n const target = await loadTarget(project.projectId, issue);\n return target === null ? [] : [target];\n }\n\n const queued = await queueTarget(project);\n if (queued !== null && !all) return [queued];\n\n const unfinished = await unfinishedTargets(project);\n if (all) return unfinished;\n return unfinished.slice(0, 1);\n}\n\n/** The issue a queue would hand out next, when this project has a queue. */\nasync function queueTarget(\n project: Awaited<ReturnType<typeof resolveProjectPaths>>,\n): Promise<ResumeTarget | null> {\n const queuesDir = join(project.projectDir, QUEUES_DIR_NAME);\n let entries: string[];\n try {\n entries = await readdir(queuesDir);\n } catch {\n return null;\n }\n\n for (const entry of entries) {\n const plan = await loadExecutionPlan(join(queuesDir, entry, 'execution-plan.json'));\n if (plan === null) continue;\n const next = nextQueueIssue(plan);\n if (next === null) continue;\n const target = await loadTarget(project.projectId, next.id);\n if (target !== null) return target;\n }\n return null;\n}\n\n/** Every issue whose plan is not finished, most recently attempted first. */\nasync function unfinishedTargets(\n project: Awaited<ReturnType<typeof resolveProjectPaths>>,\n): Promise<ResumeTarget[]> {\n let ids: string[];\n try {\n ids = await readdir(project.issuesDir);\n } catch {\n return [];\n }\n\n const targets: ResumeTarget[] = [];\n for (const id of ids) {\n const target = await loadTarget(project.projectId, id);\n if (target === null) continue;\n if (target.plan.issueStatus === 'completed') continue;\n const manager = new PipelineManager(target.plan, target.tasksFile, activePhases(target.plan));\n if (manager.getNextPhase() === null) continue;\n targets.push(target);\n }\n\n return targets.sort((a, b) => attemptedAt(b.plan) - attemptedAt(a.plan));\n}\n\nfunction attemptedAt(plan: TaskPlan): number {\n const at = Date.parse(plan.lastAttemptAt ?? '');\n return Number.isNaN(at) ? 0 : at;\n}\n\nasync function loadTarget(projectId: string, issue: string): Promise<ResumeTarget | null> {\n let paths: ReturnType<typeof getIssuePaths>;\n try {\n paths = getIssuePaths(projectId, issue);\n } catch {\n // Not a usable issue identifier — a stray file in `issues/`, for instance.\n return null;\n }\n\n try {\n const plan = await loadTaskPlan(paths.tasksFile);\n return {\n issue,\n plan,\n tasksFile: paths.tasksFile,\n eventsFile: paths.eventsFile,\n rotatedEventsFile: paths.rotatedEventsFile,\n };\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runReview
4
+ } from "./chunk-SZMHCEYV.js";
5
+ import "./chunk-BRCNQXYQ.js";
6
+ import "./chunk-WB2X37MO.js";
7
+ import "./chunk-L6HSKTQE.js";
8
+ import "./chunk-REO3PXXO.js";
9
+ import "./chunk-PZTWU277.js";
10
+ import "./chunk-KMMASOA6.js";
11
+ import "./chunk-PHW2YV6N.js";
12
+ import "./chunk-KMRFRXIT.js";
13
+ import "./chunk-CGKLE6WR.js";
14
+ import "./chunk-LEW4QM74.js";
15
+ import "./chunk-3BWZO4YI.js";
16
+ import "./chunk-OOVG2KBY.js";
17
+ import "./chunk-RVO7L4FX.js";
18
+ import "./chunk-QJ5UZAH5.js";
19
+ import "./chunk-QK7WUO7A.js";
20
+ import "./chunk-TYRNTSPJ.js";
21
+ import "./chunk-6QYMSNVA.js";
22
+ import "./chunk-3WFZETIM.js";
23
+ import "./chunk-HAKDLR6N.js";
24
+ import "./chunk-BEZ5BA5U.js";
25
+ import "./chunk-67YIU2VB.js";
26
+ import "./chunk-P3LRUNC6.js";
27
+ import "./chunk-G5EK2XRN.js";
28
+ import "./chunk-J3SOTUVI.js";
29
+ import "./chunk-LBGHI4S2.js";
30
+ import "./chunk-7Z4Y3VKM.js";
31
+ import "./chunk-XEYH6ZZI.js";
32
+ export {
33
+ runReview
34
+ };
35
+ //# sourceMappingURL=review-YM4JAABY.js.map
@@ -2,24 +2,27 @@
2
2
  import {
3
3
  PRIORS_VERSION,
4
4
  decideRouting
5
- } from "./chunk-3XLCNVMD.js";
5
+ } from "./chunk-LEW4QM74.js";
6
6
  import {
7
7
  loadRoutingConfig
8
- } from "./chunk-CNBYCMSU.js";
8
+ } from "./chunk-QJ5UZAH5.js";
9
9
  import {
10
10
  resolveIssuePaths
11
- } from "./chunk-HQAHNIAR.js";
11
+ } from "./chunk-QK7WUO7A.js";
12
12
  import {
13
13
  printInfo
14
- } from "./chunk-IYV6KNVF.js";
15
- import "./chunk-6FDFRNXZ.js";
14
+ } from "./chunk-TYRNTSPJ.js";
15
+ import "./chunk-6QYMSNVA.js";
16
+ import "./chunk-3WFZETIM.js";
17
+ import "./chunk-HAKDLR6N.js";
18
+ import "./chunk-BEZ5BA5U.js";
19
+ import "./chunk-67YIU2VB.js";
16
20
  import "./chunk-P3LRUNC6.js";
21
+ import "./chunk-G5EK2XRN.js";
17
22
  import {
18
23
  loadTaskPlan
19
- } from "./chunk-DIG5XKQQ.js";
20
- import "./chunk-NEZZ6KDR.js";
21
- import "./chunk-TX5WIVYP.js";
22
- import "./chunk-KQHB7ZT3.js";
24
+ } from "./chunk-J3SOTUVI.js";
25
+ import "./chunk-LBGHI4S2.js";
23
26
  import "./chunk-7Z4Y3VKM.js";
24
27
  import "./chunk-XEYH6ZZI.js";
25
28
 
@@ -88,4 +91,4 @@ export {
88
91
  runRoutingInspect,
89
92
  runRoutingReport
90
93
  };
91
- //# sourceMappingURL=routing-2ZUMZPJB.js.map
94
+ //# sourceMappingURL=routing-NNT5WKGX.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/routing.ts"],"sourcesContent":["import { loadRoutingConfig } from '../config.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { decideRouting } from '../routing/decide.js';\nimport { PRIORS_VERSION } from '../routing/priors.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printInfo } from '../ui/logger.js';\n\nexport const ROUTING_COMMAND_SCHEMA_VERSION = 1;\n\nexport async function runRoutingInspect(options: { json?: boolean }): Promise<number> {\n const config = await loadRoutingConfig();\n const sample = decideRouting({\n phase: 'execute',\n actualHarness: 'claude-code',\n mode: config.mode,\n profile: config.profile,\n });\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n schemaVersion: ROUTING_COMMAND_SCHEMA_VERSION,\n priorsVersion: PRIORS_VERSION,\n config,\n sample,\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n printInfo(`routing.mode: ${config.mode} (default shadow — records, does not act)`);\n printInfo(`routing.profile: ${config.profile}`);\n if (sample) {\n printInfo(\n `sample selected=${sample.selected} actual=${sample.actual} class=${sample.taskClass}`,\n );\n }\n return 0;\n}\n\nexport async function runRoutingReport(options: {\n issue?: string;\n json?: boolean;\n}): Promise<number> {\n if (options.issue === undefined) {\n printInfo('Pass --issue N to compare selected vs actual on that plan.');\n return 0;\n }\n const paths = await resolveIssuePaths(options.issue);\n const plan = await loadTaskPlan(paths.tasksFile);\n const records = plan.executions ?? [];\n let agree = 0;\n let total = 0;\n for (const record of records) {\n const decision = record.routingDecision;\n if (decision === undefined || decision === null) continue;\n total += 1;\n if (decision.selected === decision.actual) agree += 1;\n }\n const rate = total === 0 ? 0 : agree / total;\n if (options.json === true) {\n console.log(\n JSON.stringify({ schemaVersion: ROUTING_COMMAND_SCHEMA_VERSION, total, agree, rate }),\n );\n return 0;\n }\n printInfo(`shadow agreement: ${agree}/${total} (${(rate * 100).toFixed(0)}%)`);\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAOO,IAAM,iCAAiC;AAE9C,eAAsB,kBAAkB,SAA8C;AACpF,QAAM,SAAS,MAAM,kBAAkB;AACvC,QAAM,SAAS,cAAc;AAAA,IAC3B,OAAO;AAAA,IACP,eAAe;AAAA,IACf,MAAM,OAAO;AAAA,IACb,SAAS,OAAO;AAAA,EAClB,CAAC;AACD,MAAI,QAAQ,SAAS,MAAM;AACzB,YAAQ;AAAA,MACN,KAAK;AAAA,QACH;AAAA,UACE,eAAe;AAAA,UACf,eAAe;AAAA,UACf;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,YAAU,iBAAiB,OAAO,IAAI,gDAA2C;AACjF,YAAU,oBAAoB,OAAO,OAAO,EAAE;AAC9C,MAAI,QAAQ;AACV;AAAA,MACE,mBAAmB,OAAO,QAAQ,WAAW,OAAO,MAAM,UAAU,OAAO,SAAS;AAAA,IACtF;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,iBAAiB,SAGnB;AAClB,MAAI,QAAQ,UAAU,QAAW;AAC/B,cAAU,4DAA4D;AACtE,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,MAAM,kBAAkB,QAAQ,KAAK;AACnD,QAAM,OAAO,MAAM,aAAa,MAAM,SAAS;AAC/C,QAAM,UAAU,KAAK,cAAc,CAAC;AACpC,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,aAAW,UAAU,SAAS;AAC5B,UAAM,WAAW,OAAO;AACxB,QAAI,aAAa,UAAa,aAAa,KAAM;AACjD,aAAS;AACT,QAAI,SAAS,aAAa,SAAS,OAAQ,UAAS;AAAA,EACtD;AACA,QAAM,OAAO,UAAU,IAAI,IAAI,QAAQ;AACvC,MAAI,QAAQ,SAAS,MAAM;AACzB,YAAQ;AAAA,MACN,KAAK,UAAU,EAAE,eAAe,gCAAgC,OAAO,OAAO,KAAK,CAAC;AAAA,IACtF;AACA,WAAO;AAAA,EACT;AACA,YAAU,qBAAqB,KAAK,IAAI,KAAK,MAAM,OAAO,KAAK,QAAQ,CAAC,CAAC,IAAI;AAC7E,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/commands/routing.ts"],"sourcesContent":["import { loadRoutingConfig } from '../config.js';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { decideRouting } from '../routing/decide.js';\nimport { PRIORS_VERSION } from '../routing/priors.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printInfo } from '../ui/logger.js';\n\nexport const ROUTING_COMMAND_SCHEMA_VERSION = 1;\n\nexport async function runRoutingInspect(options: { json?: boolean }): Promise<number> {\n const config = await loadRoutingConfig();\n const sample = decideRouting({\n phase: 'execute',\n actualHarness: 'claude-code',\n mode: config.mode,\n profile: config.profile,\n });\n if (options.json === true) {\n console.log(\n JSON.stringify(\n {\n schemaVersion: ROUTING_COMMAND_SCHEMA_VERSION,\n priorsVersion: PRIORS_VERSION,\n config,\n sample,\n },\n null,\n 2,\n ),\n );\n return 0;\n }\n printInfo(`routing.mode: ${config.mode} (default shadow — records, does not act)`);\n printInfo(`routing.profile: ${config.profile}`);\n if (sample) {\n printInfo(\n `sample selected=${sample.selected} actual=${sample.actual} class=${sample.taskClass}`,\n );\n }\n return 0;\n}\n\nexport async function runRoutingReport(options: {\n issue?: string;\n json?: boolean;\n}): Promise<number> {\n if (options.issue === undefined) {\n printInfo('Pass --issue N to compare selected vs actual on that plan.');\n return 0;\n }\n const paths = await resolveIssuePaths(options.issue);\n const plan = await loadTaskPlan(paths.tasksFile);\n const records = plan.executions ?? [];\n let agree = 0;\n let total = 0;\n for (const record of records) {\n const decision = record.routingDecision;\n if (decision === undefined || decision === null) continue;\n total += 1;\n if (decision.selected === decision.actual) agree += 1;\n }\n const rate = total === 0 ? 0 : agree / total;\n if (options.json === true) {\n console.log(\n JSON.stringify({ schemaVersion: ROUTING_COMMAND_SCHEMA_VERSION, total, agree, rate }),\n );\n return 0;\n }\n printInfo(`shadow agreement: ${agree}/${total} (${(rate * 100).toFixed(0)}%)`);\n return 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOO,IAAM,iCAAiC;AAE9C,eAAsB,kBAAkB,SAA8C;AACpF,QAAM,SAAS,MAAM,kBAAkB;AACvC,QAAM,SAAS,cAAc;AAAA,IAC3B,OAAO;AAAA,IACP,eAAe;AAAA,IACf,MAAM,OAAO;AAAA,IACb,SAAS,OAAO;AAAA,EAClB,CAAC;AACD,MAAI,QAAQ,SAAS,MAAM;AACzB,YAAQ;AAAA,MACN,KAAK;AAAA,QACH;AAAA,UACE,eAAe;AAAA,UACf,eAAe;AAAA,UACf;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,YAAU,iBAAiB,OAAO,IAAI,gDAA2C;AACjF,YAAU,oBAAoB,OAAO,OAAO,EAAE;AAC9C,MAAI,QAAQ;AACV;AAAA,MACE,mBAAmB,OAAO,QAAQ,WAAW,OAAO,MAAM,UAAU,OAAO,SAAS;AAAA,IACtF;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,iBAAiB,SAGnB;AAClB,MAAI,QAAQ,UAAU,QAAW;AAC/B,cAAU,4DAA4D;AACtE,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,MAAM,kBAAkB,QAAQ,KAAK;AACnD,QAAM,OAAO,MAAM,aAAa,MAAM,SAAS;AAC/C,QAAM,UAAU,KAAK,cAAc,CAAC;AACpC,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,aAAW,UAAU,SAAS;AAC5B,UAAM,WAAW,OAAO;AACxB,QAAI,aAAa,UAAa,aAAa,KAAM;AACjD,aAAS;AACT,QAAI,SAAS,aAAa,SAAS,OAAQ,UAAS;AAAA,EACtD;AACA,QAAM,OAAO,UAAU,IAAI,IAAI,QAAQ;AACvC,MAAI,QAAQ,SAAS,MAAM;AACzB,YAAQ;AAAA,MACN,KAAK,UAAU,EAAE,eAAe,gCAAgC,OAAO,OAAO,KAAK,CAAC;AAAA,IACtF;AACA,WAAO;AAAA,EACT;AACA,YAAU,qBAAqB,KAAK,IAAI,KAAK,MAAM,OAAO,KAAK,QAAQ,CAAC,CAAC,IAAI;AAC7E,SAAO;AACT;","names":[]}
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ publishIssueDetails,
4
+ publishStorySeed,
5
+ runPipeline
6
+ } from "./chunk-X44FKNKP.js";
7
+ import "./chunk-V7MO5EDS.js";
8
+ import "./chunk-QZVKRDJY.js";
9
+ import "./chunk-QD4VOILZ.js";
10
+ import "./chunk-SZMHCEYV.js";
11
+ import "./chunk-OR43364P.js";
12
+ import "./chunk-F6TOYSYY.js";
13
+ import "./chunk-B72RQZBV.js";
14
+ import "./chunk-LFEQIZLB.js";
15
+ import "./chunk-BRCNQXYQ.js";
16
+ import "./chunk-WB2X37MO.js";
17
+ import "./chunk-CRGIQFUQ.js";
18
+ import "./chunk-L6HSKTQE.js";
19
+ import "./chunk-UJ3L2MS7.js";
20
+ import "./chunk-6BENHR2I.js";
21
+ import "./chunk-2IQ6M4ZE.js";
22
+ import "./chunk-PBTA3QQX.js";
23
+ import "./chunk-76MMPJ53.js";
24
+ import "./chunk-REO3PXXO.js";
25
+ import "./chunk-PZTWU277.js";
26
+ import "./chunk-KMMASOA6.js";
27
+ import "./chunk-PHW2YV6N.js";
28
+ import "./chunk-KMRFRXIT.js";
29
+ import "./chunk-CGKLE6WR.js";
30
+ import "./chunk-LEW4QM74.js";
31
+ import "./chunk-3BWZO4YI.js";
32
+ import "./chunk-OOVG2KBY.js";
33
+ import "./chunk-3D4A4B46.js";
34
+ import "./chunk-RVO7L4FX.js";
35
+ import "./chunk-QJ5UZAH5.js";
36
+ import "./chunk-QK7WUO7A.js";
37
+ import "./chunk-TYRNTSPJ.js";
38
+ import "./chunk-6QYMSNVA.js";
39
+ import "./chunk-3WFZETIM.js";
40
+ import "./chunk-HAKDLR6N.js";
41
+ import "./chunk-BEZ5BA5U.js";
42
+ import "./chunk-67YIU2VB.js";
43
+ import "./chunk-P3LRUNC6.js";
44
+ import "./chunk-G5EK2XRN.js";
45
+ import "./chunk-J3SOTUVI.js";
46
+ import "./chunk-LBGHI4S2.js";
47
+ import "./chunk-7Z4Y3VKM.js";
48
+ import "./chunk-XEYH6ZZI.js";
49
+ export {
50
+ publishIssueDetails,
51
+ publishStorySeed,
52
+ runPipeline
53
+ };
54
+ //# sourceMappingURL=run-PZUKHPQK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getSessionPublisher,
4
+ setSessionPublisher
5
+ } from "./chunk-6QYMSNVA.js";
6
+ import "./chunk-P3LRUNC6.js";
7
+ export {
8
+ getSessionPublisher,
9
+ setSessionPublisher
10
+ };
11
+ //# sourceMappingURL=session-publisher-T7EI3CIP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -14,8 +14,8 @@ import {
14
14
  selectActiveStory,
15
15
  setLastError,
16
16
  trimErrorMessage
17
- } from "./chunk-DIG5XKQQ.js";
18
- import "./chunk-NEZZ6KDR.js";
17
+ } from "./chunk-J3SOTUVI.js";
18
+ import "./chunk-LBGHI4S2.js";
19
19
  import "./chunk-7Z4Y3VKM.js";
20
20
  export {
21
21
  allStoriesPass,
@@ -33,4 +33,4 @@ export {
33
33
  setLastError,
34
34
  trimErrorMessage
35
35
  };
36
- //# sourceMappingURL=state-manager-X3PT3FGT.js.map
36
+ //# sourceMappingURL=state-manager-GQH32C44.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -5,23 +5,26 @@ import {
5
5
  } from "./chunk-CRGIQFUQ.js";
6
6
  import {
7
7
  resolveProjectPaths
8
- } from "./chunk-HQAHNIAR.js";
8
+ } from "./chunk-QK7WUO7A.js";
9
9
  import {
10
10
  printError,
11
11
  printInfo
12
- } from "./chunk-IYV6KNVF.js";
12
+ } from "./chunk-TYRNTSPJ.js";
13
+ import "./chunk-6QYMSNVA.js";
14
+ import "./chunk-3WFZETIM.js";
15
+ import {
16
+ getIssuePaths
17
+ } from "./chunk-HAKDLR6N.js";
18
+ import "./chunk-BEZ5BA5U.js";
13
19
  import {
14
20
  discardedExecutionCount
15
- } from "./chunk-6FDFRNXZ.js";
21
+ } from "./chunk-67YIU2VB.js";
16
22
  import "./chunk-P3LRUNC6.js";
23
+ import "./chunk-G5EK2XRN.js";
17
24
  import {
18
25
  loadTaskPlan
19
- } from "./chunk-DIG5XKQQ.js";
20
- import "./chunk-NEZZ6KDR.js";
21
- import {
22
- getIssuePaths
23
- } from "./chunk-TX5WIVYP.js";
24
- import "./chunk-KQHB7ZT3.js";
26
+ } from "./chunk-J3SOTUVI.js";
27
+ import "./chunk-LBGHI4S2.js";
25
28
  import "./chunk-7Z4Y3VKM.js";
26
29
  import "./chunk-XEYH6ZZI.js";
27
30
 
@@ -171,4 +174,4 @@ export {
171
174
  formatUsageReport,
172
175
  runUsage
173
176
  };
174
- //# sourceMappingURL=usage-VCFLDA5Y.js.map
177
+ //# sourceMappingURL=usage-V2CHE5PY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/usage.ts"],"sourcesContent":["import { readdir } from 'node:fs/promises';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { getIssuePaths } from '../storage/paths.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport { type GroupKey, groupBy, summarize } from '../telemetry/aggregate.js';\nimport { discardedExecutionCount } from '../telemetry/recorder.js';\nimport type { ExecutionRecord, ExecutionSummary } from '../telemetry/types.js';\nimport type { TaskPlan } from '../types.js';\nimport { printError, printInfo } from '../ui/logger.js';\n\nexport const USAGE_GROUP_KEYS = [\n 'harness',\n 'provider',\n 'model',\n 'purpose',\n 'status',\n] as const satisfies readonly GroupKey[];\n\nexport type UsageGroupKey = (typeof USAGE_GROUP_KEYS)[number];\n\nexport interface UsageOptions {\n issue?: string;\n since?: string;\n by?: UsageGroupKey;\n json?: boolean;\n}\n\nexport interface UsageReport {\n issue: string | null;\n since: string | null;\n by: UsageGroupKey | null;\n discarded: number;\n total: ExecutionSummary;\n groups: Array<{ key: string; summary: ExecutionSummary }>;\n}\n\nfunction sinceCutoff(since: string | undefined): number | null {\n if (since === undefined || since === '') return null;\n const parsed = Date.parse(since);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nfunction afterCutoff(\n records: readonly ExecutionRecord[],\n cutoff: number | null,\n): ExecutionRecord[] {\n if (cutoff === null) return [...records];\n return records.filter((record) => Date.parse(record.startedAt) >= cutoff);\n}\n\nfunction formatUsd(amount: number): string {\n return `$${amount.toFixed(2)}`;\n}\n\nfunction formatCost(summary: ExecutionSummary): string {\n const parts: string[] = [];\n if (summary.totalCost.reported > 0 || summary.totalCost.estimated === 0) {\n if (summary.count > 0 && summary.totalCost.unknownExecutions < summary.count) {\n parts.push(`${formatUsd(summary.totalCost.reported)} reportado`);\n }\n }\n if (summary.totalCost.estimated > 0) {\n parts.push(`${formatUsd(summary.totalCost.estimated)} estimado`);\n }\n if (summary.totalCost.unknownExecutions > 0) {\n parts.push(`— desconhecido (${summary.totalCost.unknownExecutions})`);\n }\n return parts.length === 0 ? '—' : parts.join(' · ');\n}\n\nfunction formatTokens(summary: ExecutionSummary): string {\n const total = summary.usage.inputTokens + summary.usage.outputTokens;\n if (total >= 1_000_000) return `${(total / 1_000_000).toFixed(1)}M`;\n if (total >= 1_000) return `${(total / 1_000).toFixed(1)}k`;\n return String(total);\n}\n\nfunction successRate(summary: ExecutionSummary): string {\n if (summary.count === 0) return '—';\n const ok = summary.byStatus.completed ?? 0;\n return `${((ok / summary.count) * 100).toFixed(1)}%`;\n}\n\nasync function loadPlans(\n issue: string | undefined,\n): Promise<{ id: string; plan: TaskPlan }[] | null> {\n let project: Awaited<ReturnType<typeof resolveProjectPaths>>;\n try {\n project = await resolveProjectPaths();\n } catch (err) {\n printError(`Not inside a usable project: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n\n if (issue !== undefined) {\n try {\n const paths = getIssuePaths(project.projectId, issue);\n return [{ id: issue, plan: await loadTaskPlan(paths.tasksFile) }];\n } catch (err) {\n printError(\n `No telemetry for issue ${issue}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n }\n\n let ids: string[];\n try {\n ids = await readdir(project.issuesDir);\n } catch {\n return [];\n }\n\n const loaded: { id: string; plan: TaskPlan }[] = [];\n for (const id of ids) {\n try {\n loaded.push({\n id,\n plan: await loadTaskPlan(getIssuePaths(project.projectId, id).tasksFile),\n });\n } catch {\n // An issue without a readable plan is not telemetry.\n }\n }\n return loaded;\n}\n\nexport function buildUsageReport(\n plans: { id: string; plan: TaskPlan }[],\n options: UsageOptions,\n discarded = 0,\n): UsageReport {\n const cutoff = sinceCutoff(options.since);\n const records = plans.flatMap(({ plan }) => afterCutoff(plan.executions ?? [], cutoff));\n const total = summarize(records, discarded);\n const groups =\n options.by === undefined\n ? []\n : [...groupBy(records, options.by)].map(([key, summary]) => ({ key, summary }));\n return {\n issue: options.issue ?? (plans.length === 1 ? (plans[0]?.id ?? null) : null),\n since: options.since ?? null,\n by: options.by ?? null,\n discarded,\n total,\n groups,\n };\n}\n\nexport function formatUsageReport(report: UsageReport): string {\n if (report.total.count === 0) {\n return 'No execution telemetry recorded yet.';\n }\n\n const header = [\n report.issue === null ? 'project' : `issue #${report.issue}`,\n `${report.total.count} execução${report.total.count === 1 ? '' : 'ões'}`,\n formatCost(report.total),\n ].join(' · ');\n\n if (report.by === null || report.groups.length === 0) {\n return header;\n }\n\n const rows = report.groups.map((group) => {\n const name = group.key.padEnd(14);\n const count = String(group.summary.count).padStart(10);\n const success = successRate(group.summary).padStart(8);\n const tokens = formatTokens(group.summary).padStart(8);\n return `${name}${count}${success}${tokens.padStart(10)} ${formatCost(group.summary)}`;\n });\n const columns = `${report.by.padEnd(14)}${'execuções'.padStart(10)}${'sucesso'.padStart(8)}${'tokens'.padStart(10)} custo`;\n return [`${header}`, columns, ...rows].join('\\n');\n}\n\nexport async function runUsage(\n issue: string | undefined,\n options: UsageOptions = {},\n): Promise<number> {\n const plans = await loadPlans(issue ?? options.issue);\n if (plans === null) return 1;\n\n if (options.since !== undefined && sinceCutoff(options.since) === null) {\n printError(`Invalid --since date: ${options.since}`);\n return 1;\n }\n\n const report = buildUsageReport(plans, { ...options, issue: issue ?? options.issue });\n if (plans.length === 0 || (report.total.count === 0 && (issue ?? options.issue) !== undefined)) {\n printInfo('No execution telemetry recorded yet.');\n return 0;\n }\n\n if (options.json === true) {\n printInfo(JSON.stringify(report, null, 2));\n return 0;\n }\n\n printInfo(formatUsageReport(report));\n return 0;\n}\n\nexport { discardedExecutionCount };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/usage.ts"],"sourcesContent":["import { readdir } from 'node:fs/promises';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { getIssuePaths } from '../storage/paths.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport { type GroupKey, groupBy, summarize } from '../telemetry/aggregate.js';\nimport { discardedExecutionCount } from '../telemetry/recorder.js';\nimport type { ExecutionRecord, ExecutionSummary } from '../telemetry/types.js';\nimport type { TaskPlan } from '../types.js';\nimport { printError, printInfo } from '../ui/logger.js';\n\nexport const USAGE_GROUP_KEYS = [\n 'harness',\n 'provider',\n 'model',\n 'purpose',\n 'status',\n] as const satisfies readonly GroupKey[];\n\nexport type UsageGroupKey = (typeof USAGE_GROUP_KEYS)[number];\n\nexport interface UsageOptions {\n issue?: string;\n since?: string;\n by?: UsageGroupKey;\n json?: boolean;\n}\n\nexport interface UsageReport {\n issue: string | null;\n since: string | null;\n by: UsageGroupKey | null;\n discarded: number;\n total: ExecutionSummary;\n groups: Array<{ key: string; summary: ExecutionSummary }>;\n}\n\nfunction sinceCutoff(since: string | undefined): number | null {\n if (since === undefined || since === '') return null;\n const parsed = Date.parse(since);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nfunction afterCutoff(\n records: readonly ExecutionRecord[],\n cutoff: number | null,\n): ExecutionRecord[] {\n if (cutoff === null) return [...records];\n return records.filter((record) => Date.parse(record.startedAt) >= cutoff);\n}\n\nfunction formatUsd(amount: number): string {\n return `$${amount.toFixed(2)}`;\n}\n\nfunction formatCost(summary: ExecutionSummary): string {\n const parts: string[] = [];\n if (summary.totalCost.reported > 0 || summary.totalCost.estimated === 0) {\n if (summary.count > 0 && summary.totalCost.unknownExecutions < summary.count) {\n parts.push(`${formatUsd(summary.totalCost.reported)} reportado`);\n }\n }\n if (summary.totalCost.estimated > 0) {\n parts.push(`${formatUsd(summary.totalCost.estimated)} estimado`);\n }\n if (summary.totalCost.unknownExecutions > 0) {\n parts.push(`— desconhecido (${summary.totalCost.unknownExecutions})`);\n }\n return parts.length === 0 ? '—' : parts.join(' · ');\n}\n\nfunction formatTokens(summary: ExecutionSummary): string {\n const total = summary.usage.inputTokens + summary.usage.outputTokens;\n if (total >= 1_000_000) return `${(total / 1_000_000).toFixed(1)}M`;\n if (total >= 1_000) return `${(total / 1_000).toFixed(1)}k`;\n return String(total);\n}\n\nfunction successRate(summary: ExecutionSummary): string {\n if (summary.count === 0) return '—';\n const ok = summary.byStatus.completed ?? 0;\n return `${((ok / summary.count) * 100).toFixed(1)}%`;\n}\n\nasync function loadPlans(\n issue: string | undefined,\n): Promise<{ id: string; plan: TaskPlan }[] | null> {\n let project: Awaited<ReturnType<typeof resolveProjectPaths>>;\n try {\n project = await resolveProjectPaths();\n } catch (err) {\n printError(`Not inside a usable project: ${err instanceof Error ? err.message : String(err)}`);\n return null;\n }\n\n if (issue !== undefined) {\n try {\n const paths = getIssuePaths(project.projectId, issue);\n return [{ id: issue, plan: await loadTaskPlan(paths.tasksFile) }];\n } catch (err) {\n printError(\n `No telemetry for issue ${issue}: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n }\n\n let ids: string[];\n try {\n ids = await readdir(project.issuesDir);\n } catch {\n return [];\n }\n\n const loaded: { id: string; plan: TaskPlan }[] = [];\n for (const id of ids) {\n try {\n loaded.push({\n id,\n plan: await loadTaskPlan(getIssuePaths(project.projectId, id).tasksFile),\n });\n } catch {\n // An issue without a readable plan is not telemetry.\n }\n }\n return loaded;\n}\n\nexport function buildUsageReport(\n plans: { id: string; plan: TaskPlan }[],\n options: UsageOptions,\n discarded = 0,\n): UsageReport {\n const cutoff = sinceCutoff(options.since);\n const records = plans.flatMap(({ plan }) => afterCutoff(plan.executions ?? [], cutoff));\n const total = summarize(records, discarded);\n const groups =\n options.by === undefined\n ? []\n : [...groupBy(records, options.by)].map(([key, summary]) => ({ key, summary }));\n return {\n issue: options.issue ?? (plans.length === 1 ? (plans[0]?.id ?? null) : null),\n since: options.since ?? null,\n by: options.by ?? null,\n discarded,\n total,\n groups,\n };\n}\n\nexport function formatUsageReport(report: UsageReport): string {\n if (report.total.count === 0) {\n return 'No execution telemetry recorded yet.';\n }\n\n const header = [\n report.issue === null ? 'project' : `issue #${report.issue}`,\n `${report.total.count} execução${report.total.count === 1 ? '' : 'ões'}`,\n formatCost(report.total),\n ].join(' · ');\n\n if (report.by === null || report.groups.length === 0) {\n return header;\n }\n\n const rows = report.groups.map((group) => {\n const name = group.key.padEnd(14);\n const count = String(group.summary.count).padStart(10);\n const success = successRate(group.summary).padStart(8);\n const tokens = formatTokens(group.summary).padStart(8);\n return `${name}${count}${success}${tokens.padStart(10)} ${formatCost(group.summary)}`;\n });\n const columns = `${report.by.padEnd(14)}${'execuções'.padStart(10)}${'sucesso'.padStart(8)}${'tokens'.padStart(10)} custo`;\n return [`${header}`, columns, ...rows].join('\\n');\n}\n\nexport async function runUsage(\n issue: string | undefined,\n options: UsageOptions = {},\n): Promise<number> {\n const plans = await loadPlans(issue ?? options.issue);\n if (plans === null) return 1;\n\n if (options.since !== undefined && sinceCutoff(options.since) === null) {\n printError(`Invalid --since date: ${options.since}`);\n return 1;\n }\n\n const report = buildUsageReport(plans, { ...options, issue: issue ?? options.issue });\n if (plans.length === 0 || (report.total.count === 0 && (issue ?? options.issue) !== undefined)) {\n printInfo('No execution telemetry recorded yet.');\n return 0;\n }\n\n if (options.json === true) {\n printInfo(JSON.stringify(report, null, 2));\n return 0;\n }\n\n printInfo(formatUsageReport(report));\n return 0;\n}\n\nexport { discardedExecutionCount };\n"],"mappings":"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","names":[]}
@@ -1,30 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readSessionFile
4
- } from "./chunk-SNTTOQAD.js";
4
+ } from "./chunk-JN6D3MY6.js";
5
5
  import {
6
6
  ensureSingleWebServer,
7
7
  getWebLockFile,
8
8
  readWebLock,
9
9
  removeWebLock
10
- } from "./chunk-IHIEXUTC.js";
11
- import "./chunk-MIVHK5YI.js";
10
+ } from "./chunk-LFEQIZLB.js";
11
+ import "./chunk-UJ3L2MS7.js";
12
+ import "./chunk-KMRFRXIT.js";
12
13
  import {
13
14
  parseJournal
14
- } from "./chunk-QCXPNSEL.js";
15
+ } from "./chunk-3BWZO4YI.js";
15
16
  import {
16
17
  loadWebConfig
17
- } from "./chunk-CNBYCMSU.js";
18
- import "./chunk-HQAHNIAR.js";
18
+ } from "./chunk-QJ5UZAH5.js";
19
+ import "./chunk-QK7WUO7A.js";
19
20
  import {
20
21
  printError,
21
22
  printInfo,
22
23
  printWarning
23
- } from "./chunk-IYV6KNVF.js";
24
- import "./chunk-6FDFRNXZ.js";
25
- import "./chunk-P3LRUNC6.js";
26
- import "./chunk-DIG5XKQQ.js";
27
- import "./chunk-NEZZ6KDR.js";
24
+ } from "./chunk-TYRNTSPJ.js";
25
+ import "./chunk-6QYMSNVA.js";
26
+ import "./chunk-3WFZETIM.js";
28
27
  import {
29
28
  EVENTS_FILENAME,
30
29
  ISSUES_DIR_NAME,
@@ -32,8 +31,13 @@ import {
32
31
  ROTATED_EVENTS_FILENAME,
33
32
  SESSION_FILENAME,
34
33
  getGlobalRoot
35
- } from "./chunk-TX5WIVYP.js";
36
- import "./chunk-KQHB7ZT3.js";
34
+ } from "./chunk-HAKDLR6N.js";
35
+ import "./chunk-BEZ5BA5U.js";
36
+ import "./chunk-67YIU2VB.js";
37
+ import "./chunk-P3LRUNC6.js";
38
+ import "./chunk-G5EK2XRN.js";
39
+ import "./chunk-J3SOTUVI.js";
40
+ import "./chunk-LBGHI4S2.js";
37
41
  import "./chunk-7Z4Y3VKM.js";
38
42
  import "./chunk-XEYH6ZZI.js";
39
43
 
@@ -201,4 +205,4 @@ export {
201
205
  runWebServe,
202
206
  runWebStop
203
207
  };
204
- //# sourceMappingURL=web-XVHLX62B.js.map
208
+ //# sourceMappingURL=web-EA3KGNFN.js.map