issue-flow 0.18.0 → 0.20.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 (235) hide show
  1. package/README.md +43 -97
  2. package/dist/agent-4DHRKZ2Z.js +32 -0
  3. package/dist/{analyze-Q4ONIWRZ.js → analyze-UEJ2R3H5.js} +42 -41
  4. package/dist/analyze-UEJ2R3H5.js.map +1 -0
  5. package/dist/{apply-EEFPY2W4.js → apply-QDYNQMUX.js} +22 -24
  6. package/dist/apply-QDYNQMUX.js.map +1 -0
  7. package/dist/artifacts-AMJQJFFV.js +82 -0
  8. package/dist/artifacts-AMJQJFFV.js.map +1 -0
  9. package/dist/{bench-WWWXLTFH.js → bench-RNRXVEFK.js} +42 -42
  10. package/dist/{chunk-RYOUZ6EK.js → chunk-23VHVVKW.js} +3 -3
  11. package/dist/chunk-2EYLOS5I.js +99 -0
  12. package/dist/chunk-2EYLOS5I.js.map +1 -0
  13. package/dist/{chunk-C5TL7T4V.js → chunk-2YM2VH6R.js} +2 -2
  14. package/dist/{chunk-XUEMATVY.js → chunk-37O2FMAN.js} +28 -25
  15. package/dist/chunk-37O2FMAN.js.map +1 -0
  16. package/dist/chunk-44RF3VFG.js +717 -0
  17. package/dist/chunk-44RF3VFG.js.map +1 -0
  18. package/dist/chunk-6AOZCWN2.js +21 -0
  19. package/dist/chunk-6AOZCWN2.js.map +1 -0
  20. package/dist/chunk-7MJGYPHF.js +1571 -0
  21. package/dist/chunk-7MJGYPHF.js.map +1 -0
  22. package/dist/{chunk-SA6HXL4Y.js → chunk-7WBUEBD5.js} +9 -9
  23. package/dist/chunk-7WBUEBD5.js.map +1 -0
  24. package/dist/chunk-7ZZUSMBJ.js +35 -0
  25. package/dist/chunk-7ZZUSMBJ.js.map +1 -0
  26. package/dist/{chunk-QJ44VG5G.js → chunk-ADH6RJNX.js} +3 -3
  27. package/dist/{chunk-34OCSKOB.js → chunk-AKL5UPR6.js} +159 -114
  28. package/dist/chunk-AKL5UPR6.js.map +1 -0
  29. package/dist/{chunk-7F7LGMVO.js → chunk-BTBJ5UOO.js} +12 -12
  30. package/dist/{chunk-7F7LGMVO.js.map → chunk-BTBJ5UOO.js.map} +1 -1
  31. package/dist/{chunk-HOAHMERN.js → chunk-CLZ6RRZL.js} +21 -21
  32. package/dist/chunk-DBLXLKGU.js +1201 -0
  33. package/dist/chunk-DBLXLKGU.js.map +1 -0
  34. package/dist/{chunk-DUS5ZNKL.js → chunk-DIMDAYZS.js} +7 -6
  35. package/dist/chunk-DZ3DZ3EN.js +278 -0
  36. package/dist/chunk-DZ3DZ3EN.js.map +1 -0
  37. package/dist/{chunk-CRGIQFUQ.js → chunk-E2H3JV2E.js} +3 -1
  38. package/dist/chunk-E2H3JV2E.js.map +1 -0
  39. package/dist/{chunk-45WZ6GMI.js → chunk-EORDSKWZ.js} +17 -17
  40. package/dist/chunk-EORDSKWZ.js.map +1 -0
  41. package/dist/{chunk-LTH6XYZ3.js → chunk-EYKPWHT7.js} +40 -30
  42. package/dist/chunk-EYKPWHT7.js.map +1 -0
  43. package/dist/{chunk-OODXFCQV.js → chunk-FU2FQ4JE.js} +14 -16
  44. package/dist/{chunk-OODXFCQV.js.map → chunk-FU2FQ4JE.js.map} +1 -1
  45. package/dist/{chunk-V7QOIQYC.js → chunk-G442RDFX.js} +9 -23
  46. package/dist/{chunk-V7QOIQYC.js.map → chunk-G442RDFX.js.map} +1 -1
  47. package/dist/{chunk-QPGEFLMY.js → chunk-I64N6RL6.js} +7 -7
  48. package/dist/{chunk-KRAGAUKD.js → chunk-JBYXJOJJ.js} +201 -64
  49. package/dist/chunk-JBYXJOJJ.js.map +1 -0
  50. package/dist/{chunk-SOM4QA6C.js → chunk-JCR5C5A7.js} +93 -18
  51. package/dist/chunk-JCR5C5A7.js.map +1 -0
  52. package/dist/{chunk-RNFUVKC3.js → chunk-K5NM26NV.js} +30 -13
  53. package/dist/chunk-K5NM26NV.js.map +1 -0
  54. package/dist/{chunk-YVPZUN6X.js → chunk-KUA6KBBD.js} +335 -38
  55. package/dist/chunk-KUA6KBBD.js.map +1 -0
  56. package/dist/{chunk-KMCS76ZW.js → chunk-KUL64XUF.js} +44 -12
  57. package/dist/chunk-KUL64XUF.js.map +1 -0
  58. package/dist/{chunk-HAKDLR6N.js → chunk-MAJ6QDRL.js} +65 -78
  59. package/dist/chunk-MAJ6QDRL.js.map +1 -0
  60. package/dist/{chunk-DGRTJD5R.js → chunk-MML2G7IC.js} +7 -7
  61. package/dist/chunk-NP47HRX2.js +136 -0
  62. package/dist/chunk-NP47HRX2.js.map +1 -0
  63. package/dist/{chunk-3R27MJ5R.js → chunk-PFWHHYEO.js} +3 -3
  64. package/dist/{chunk-ECU7YO7S.js → chunk-PM5YWJYO.js} +22 -6
  65. package/dist/chunk-PM5YWJYO.js.map +1 -0
  66. package/dist/{chunk-E4I6MMHD.js → chunk-PXPTIXJF.js} +154 -101
  67. package/dist/chunk-PXPTIXJF.js.map +1 -0
  68. package/dist/{chunk-CWSQVHVV.js → chunk-QJHZ3HYJ.js} +248 -102
  69. package/dist/chunk-QJHZ3HYJ.js.map +1 -0
  70. package/dist/{chunk-LI35PIIS.js → chunk-RDPK7LYK.js} +20 -117
  71. package/dist/chunk-RDPK7LYK.js.map +1 -0
  72. package/dist/{chunk-PMLE7KAQ.js → chunk-RMIBLFG3.js} +30 -14
  73. package/dist/chunk-RMIBLFG3.js.map +1 -0
  74. package/dist/{chunk-62GVVZQO.js → chunk-T736DSZI.js} +32 -316
  75. package/dist/chunk-T736DSZI.js.map +1 -0
  76. package/dist/{chunk-TZYINKCC.js → chunk-UDUUUFQF.js} +57 -29
  77. package/dist/chunk-UDUUUFQF.js.map +1 -0
  78. package/dist/{chunk-NEWNXZ65.js → chunk-V7GETODQ.js} +36 -28
  79. package/dist/{chunk-NEWNXZ65.js.map → chunk-V7GETODQ.js.map} +1 -1
  80. package/dist/{chunk-PPZ3K4YM.js → chunk-VHQMMY2D.js} +2 -2
  81. package/dist/{chunk-ZVZMWNCG.js → chunk-VJ3PF6B7.js} +50 -16
  82. package/dist/chunk-VJ3PF6B7.js.map +1 -0
  83. package/dist/{chunk-L6HSKTQE.js → chunk-W7LZLJAF.js} +4 -4
  84. package/dist/{chunk-6K2LCFG6.js → chunk-WB4FA2EH.js} +70 -81
  85. package/dist/chunk-WB4FA2EH.js.map +1 -0
  86. package/dist/{chunk-LGHND47K.js → chunk-WQSGL5LX.js} +22 -16
  87. package/dist/chunk-WQSGL5LX.js.map +1 -0
  88. package/dist/{chunk-ICM463EO.js → chunk-XNK5UN2D.js} +5 -649
  89. package/dist/chunk-XNK5UN2D.js.map +1 -0
  90. package/dist/{chunk-7UMMFOL2.js → chunk-Y2KOWABB.js} +39 -24
  91. package/dist/chunk-Y2KOWABB.js.map +1 -0
  92. package/dist/{chunk-QF7VEL3M.js → chunk-YC24E66P.js} +568 -158
  93. package/dist/chunk-YC24E66P.js.map +1 -0
  94. package/dist/{chunk-EG2MGDP5.js → chunk-Z6RCKCVB.js} +52 -46
  95. package/dist/chunk-Z6RCKCVB.js.map +1 -0
  96. package/dist/{chunk-YUNBOUQH.js → chunk-ZPGNVBWY.js} +8 -8
  97. package/dist/cli.js +132 -62
  98. package/dist/cli.js.map +1 -1
  99. package/dist/compat-OJG76J4I.js +24 -0
  100. package/dist/{config-LEBZZCJP.js → config-6YTWPDBK.js} +20 -17
  101. package/dist/{contract-JH2WBIO6.js → contract-HWLFFL3F.js} +2 -2
  102. package/dist/{conventions-XOT6YW5L.js → conventions-5UPOTU42.js} +20 -16
  103. package/dist/{conventions-XOT6YW5L.js.map → conventions-5UPOTU42.js.map} +1 -1
  104. package/dist/db-QAZG4LQD.js +264 -0
  105. package/dist/db-QAZG4LQD.js.map +1 -0
  106. package/dist/diagnostics-YEFB42E5.js +25 -0
  107. package/dist/execute-QCT64D37.js +38 -0
  108. package/dist/{generate-JGW5JSKB.js → generate-QATMDKOK.js} +46 -43
  109. package/dist/generate-QATMDKOK.js.map +1 -0
  110. package/dist/{git-A2IP32PQ.js → git-XGOECXWG.js} +2 -3
  111. package/dist/history-NBPUZVGQ.js +101 -0
  112. package/dist/history-NBPUZVGQ.js.map +1 -0
  113. package/dist/init-4LB2YKWP.js +28 -0
  114. package/dist/{operations-O4FORFIH.js → operations-RUQP2Y2F.js} +78 -52
  115. package/dist/operations-RUQP2Y2F.js.map +1 -0
  116. package/dist/{permissions-G4XCAESF.js → permissions-QZPUUBSO.js} +5 -6
  117. package/dist/plan-2NMSHTMD.js +38 -0
  118. package/dist/{policy-U5NBFAO5.js → policy-RKKFF5A2.js} +17 -15
  119. package/dist/{policy-U5NBFAO5.js.map → policy-RKKFF5A2.js.map} +1 -1
  120. package/dist/pr-QKFO5HI3.js +42 -0
  121. package/dist/pr-review-H2BFD6F2.js +33 -0
  122. package/dist/prd-ET6XKYRS.js +37 -0
  123. package/dist/{ps-76L6ZAZL.js → ps-UIKSOUAQ.js} +26 -15
  124. package/dist/ps-UIKSOUAQ.js.map +1 -0
  125. package/dist/{recorder-2BAKPBRA.js → recorder-LOU3PTIE.js} +11 -7
  126. package/dist/registry-HV7M6MAH.js +17 -0
  127. package/dist/repository-RCRR6RDE.js +80 -0
  128. package/dist/resume-BWJZGBLZ.js +278 -0
  129. package/dist/resume-BWJZGBLZ.js.map +1 -0
  130. package/dist/review-2MTZLNSS.js +38 -0
  131. package/dist/routing-RM5ABHHD.js +35 -0
  132. package/dist/run-XMACQBRJ.js +61 -0
  133. package/dist/{session-publisher-KAJQRHNZ.js → session-publisher-Q5TNEZPX.js} +3 -3
  134. package/dist/session-publisher-Q5TNEZPX.js.map +1 -0
  135. package/dist/{state-manager-UPHO2EA2.js → state-manager-SRN4VJSX.js} +9 -4
  136. package/dist/state-manager-SRN4VJSX.js.map +1 -0
  137. package/dist/{usage-KTMYXAPF.js → usage-JOODVE5O.js} +69 -63
  138. package/dist/usage-JOODVE5O.js.map +1 -0
  139. package/dist/web-TLMWJ2BM.js +205 -0
  140. package/dist/web-TLMWJ2BM.js.map +1 -0
  141. package/package.json +22 -8
  142. package/prompts/analyze.md +16 -19
  143. package/prompts/execute.md +73 -144
  144. package/prompts/generate.md +23 -10
  145. package/prompts/plan.md +32 -60
  146. package/prompts/pr-review.md +58 -40
  147. package/prompts/pr.md +50 -16
  148. package/prompts/prd.md +26 -19
  149. package/prompts/review.md +41 -18
  150. package/web/public/app.js +111 -112
  151. package/dist/agent-HMZTXCRT.js +0 -30
  152. package/dist/analyze-Q4ONIWRZ.js.map +0 -1
  153. package/dist/apply-EEFPY2W4.js.map +0 -1
  154. package/dist/chunk-34OCSKOB.js.map +0 -1
  155. package/dist/chunk-45WZ6GMI.js.map +0 -1
  156. package/dist/chunk-62GVVZQO.js.map +0 -1
  157. package/dist/chunk-6K2LCFG6.js.map +0 -1
  158. package/dist/chunk-7UMMFOL2.js.map +0 -1
  159. package/dist/chunk-CRGIQFUQ.js.map +0 -1
  160. package/dist/chunk-CWSQVHVV.js.map +0 -1
  161. package/dist/chunk-E4I6MMHD.js.map +0 -1
  162. package/dist/chunk-ECU7YO7S.js.map +0 -1
  163. package/dist/chunk-EG2MGDP5.js.map +0 -1
  164. package/dist/chunk-HAKDLR6N.js.map +0 -1
  165. package/dist/chunk-ICM463EO.js.map +0 -1
  166. package/dist/chunk-KMCS76ZW.js.map +0 -1
  167. package/dist/chunk-KRAGAUKD.js.map +0 -1
  168. package/dist/chunk-LGHND47K.js.map +0 -1
  169. package/dist/chunk-LI35PIIS.js.map +0 -1
  170. package/dist/chunk-LTH6XYZ3.js.map +0 -1
  171. package/dist/chunk-PMLE7KAQ.js.map +0 -1
  172. package/dist/chunk-QF7VEL3M.js.map +0 -1
  173. package/dist/chunk-RNFUVKC3.js.map +0 -1
  174. package/dist/chunk-SA6HXL4Y.js.map +0 -1
  175. package/dist/chunk-SOM4QA6C.js.map +0 -1
  176. package/dist/chunk-TZYINKCC.js.map +0 -1
  177. package/dist/chunk-WCCZJL7W.js +0 -141
  178. package/dist/chunk-WCCZJL7W.js.map +0 -1
  179. package/dist/chunk-XEYH6ZZI.js +0 -289
  180. package/dist/chunk-XEYH6ZZI.js.map +0 -1
  181. package/dist/chunk-XUEMATVY.js.map +0 -1
  182. package/dist/chunk-XZUEFTUP.js +0 -243
  183. package/dist/chunk-XZUEFTUP.js.map +0 -1
  184. package/dist/chunk-YVPZUN6X.js.map +0 -1
  185. package/dist/chunk-ZVZMWNCG.js.map +0 -1
  186. package/dist/diagnostics-HTCWF7F4.js +0 -23
  187. package/dist/execute-LELOSR5T.js +0 -37
  188. package/dist/generate-JGW5JSKB.js.map +0 -1
  189. package/dist/init-TO6MUXO4.js +0 -26
  190. package/dist/operations-O4FORFIH.js.map +0 -1
  191. package/dist/plan-OXAT344Q.js +0 -34
  192. package/dist/pr-UZHNKKZC.js +0 -39
  193. package/dist/pr-review-Q4ACAWDM.js +0 -32
  194. package/dist/prd-6CYEMLDY.js +0 -33
  195. package/dist/ps-76L6ZAZL.js.map +0 -1
  196. package/dist/registry-XLHHYLTR.js +0 -15
  197. package/dist/resume-URCU6CIJ.js +0 -244
  198. package/dist/resume-URCU6CIJ.js.map +0 -1
  199. package/dist/review-LVZT2TMW.js +0 -35
  200. package/dist/routing-EK6RBZM4.js +0 -33
  201. package/dist/run-2RXJCJKT.js +0 -56
  202. package/dist/usage-KTMYXAPF.js.map +0 -1
  203. package/dist/web-B5UPHHR5.js +0 -172
  204. package/dist/web-B5UPHHR5.js.map +0 -1
  205. /package/dist/{agent-HMZTXCRT.js.map → agent-4DHRKZ2Z.js.map} +0 -0
  206. /package/dist/{bench-WWWXLTFH.js.map → bench-RNRXVEFK.js.map} +0 -0
  207. /package/dist/{chunk-RYOUZ6EK.js.map → chunk-23VHVVKW.js.map} +0 -0
  208. /package/dist/{chunk-C5TL7T4V.js.map → chunk-2YM2VH6R.js.map} +0 -0
  209. /package/dist/{chunk-QJ44VG5G.js.map → chunk-ADH6RJNX.js.map} +0 -0
  210. /package/dist/{chunk-HOAHMERN.js.map → chunk-CLZ6RRZL.js.map} +0 -0
  211. /package/dist/{chunk-DUS5ZNKL.js.map → chunk-DIMDAYZS.js.map} +0 -0
  212. /package/dist/{chunk-QPGEFLMY.js.map → chunk-I64N6RL6.js.map} +0 -0
  213. /package/dist/{chunk-DGRTJD5R.js.map → chunk-MML2G7IC.js.map} +0 -0
  214. /package/dist/{chunk-3R27MJ5R.js.map → chunk-PFWHHYEO.js.map} +0 -0
  215. /package/dist/{chunk-PPZ3K4YM.js.map → chunk-VHQMMY2D.js.map} +0 -0
  216. /package/dist/{chunk-L6HSKTQE.js.map → chunk-W7LZLJAF.js.map} +0 -0
  217. /package/dist/{chunk-YUNBOUQH.js.map → chunk-ZPGNVBWY.js.map} +0 -0
  218. /package/dist/{config-LEBZZCJP.js.map → compat-OJG76J4I.js.map} +0 -0
  219. /package/dist/{contract-JH2WBIO6.js.map → config-6YTWPDBK.js.map} +0 -0
  220. /package/dist/{diagnostics-HTCWF7F4.js.map → contract-HWLFFL3F.js.map} +0 -0
  221. /package/dist/{execute-LELOSR5T.js.map → diagnostics-YEFB42E5.js.map} +0 -0
  222. /package/dist/{git-A2IP32PQ.js.map → execute-QCT64D37.js.map} +0 -0
  223. /package/dist/{init-TO6MUXO4.js.map → git-XGOECXWG.js.map} +0 -0
  224. /package/dist/{permissions-G4XCAESF.js.map → init-4LB2YKWP.js.map} +0 -0
  225. /package/dist/{plan-OXAT344Q.js.map → permissions-QZPUUBSO.js.map} +0 -0
  226. /package/dist/{pr-UZHNKKZC.js.map → plan-2NMSHTMD.js.map} +0 -0
  227. /package/dist/{pr-review-Q4ACAWDM.js.map → pr-QKFO5HI3.js.map} +0 -0
  228. /package/dist/{prd-6CYEMLDY.js.map → pr-review-H2BFD6F2.js.map} +0 -0
  229. /package/dist/{recorder-2BAKPBRA.js.map → prd-ET6XKYRS.js.map} +0 -0
  230. /package/dist/{registry-XLHHYLTR.js.map → recorder-LOU3PTIE.js.map} +0 -0
  231. /package/dist/{review-LVZT2TMW.js.map → registry-HV7M6MAH.js.map} +0 -0
  232. /package/dist/{routing-EK6RBZM4.js.map → repository-RCRR6RDE.js.map} +0 -0
  233. /package/dist/{run-2RXJCJKT.js.map → review-2MTZLNSS.js.map} +0 -0
  234. /package/dist/{session-publisher-KAJQRHNZ.js.map → routing-RM5ABHHD.js.map} +0 -0
  235. /package/dist/{state-manager-UPHO2EA2.js.map → run-XMACQBRJ.js.map} +0 -0
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ publishIssueDetails,
4
+ publishStorySeed,
5
+ runPipeline
6
+ } from "./chunk-QJHZ3HYJ.js";
7
+ import "./chunk-ADH6RJNX.js";
8
+ import "./chunk-Y2KOWABB.js";
9
+ import "./chunk-2EYLOS5I.js";
10
+ import "./chunk-JBYXJOJJ.js";
11
+ import "./chunk-V7GETODQ.js";
12
+ import "./chunk-E2H3JV2E.js";
13
+ import "./chunk-AKL5UPR6.js";
14
+ import "./chunk-FU2FQ4JE.js";
15
+ import "./chunk-EYKPWHT7.js";
16
+ import "./chunk-ZPGNVBWY.js";
17
+ import "./chunk-37O2FMAN.js";
18
+ import "./chunk-6AOZCWN2.js";
19
+ import "./chunk-G442RDFX.js";
20
+ import "./chunk-Z6RCKCVB.js";
21
+ import "./chunk-PM5YWJYO.js";
22
+ import "./chunk-PXPTIXJF.js";
23
+ import "./chunk-7WBUEBD5.js";
24
+ import "./chunk-DZ3DZ3EN.js";
25
+ import "./chunk-W7LZLJAF.js";
26
+ import "./chunk-EORDSKWZ.js";
27
+ import "./chunk-RMIBLFG3.js";
28
+ import "./chunk-T736DSZI.js";
29
+ import "./chunk-7ZZUSMBJ.js";
30
+ import "./chunk-KMMASOA6.js";
31
+ import "./chunk-KUL64XUF.js";
32
+ import "./chunk-BTBJ5UOO.js";
33
+ import "./chunk-UDUUUFQF.js";
34
+ import "./chunk-3D4A4B46.js";
35
+ import "./chunk-WQSGL5LX.js";
36
+ import "./chunk-MML2G7IC.js";
37
+ import "./chunk-CLZ6RRZL.js";
38
+ import "./chunk-VJ3PF6B7.js";
39
+ import "./chunk-2YM2VH6R.js";
40
+ import "./chunk-YC24E66P.js";
41
+ import "./chunk-DBLXLKGU.js";
42
+ import "./chunk-I64N6RL6.js";
43
+ import "./chunk-DIMDAYZS.js";
44
+ import "./chunk-WB4FA2EH.js";
45
+ import "./chunk-VHQMMY2D.js";
46
+ import "./chunk-P3LRUNC6.js";
47
+ import "./chunk-RDPK7LYK.js";
48
+ import "./chunk-JCR5C5A7.js";
49
+ import "./chunk-NP47HRX2.js";
50
+ import "./chunk-44RF3VFG.js";
51
+ import "./chunk-7MJGYPHF.js";
52
+ import "./chunk-XNK5UN2D.js";
53
+ import "./chunk-MAJ6QDRL.js";
54
+ import "./chunk-KUA6KBBD.js";
55
+ import "./chunk-PFWHHYEO.js";
56
+ export {
57
+ publishIssueDetails,
58
+ publishStorySeed,
59
+ runPipeline
60
+ };
61
+ //# sourceMappingURL=run-XMACQBRJ.js.map
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  getSessionPublisher,
4
4
  setSessionPublisher
5
- } from "./chunk-DUS5ZNKL.js";
5
+ } from "./chunk-DIMDAYZS.js";
6
6
  import "./chunk-P3LRUNC6.js";
7
- import "./chunk-3R27MJ5R.js";
7
+ import "./chunk-PFWHHYEO.js";
8
8
  export {
9
9
  getSessionPublisher,
10
10
  setSessionPublisher
11
11
  };
12
- //# sourceMappingURL=session-publisher-KAJQRHNZ.js.map
12
+ //# sourceMappingURL=session-publisher-Q5TNEZPX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -14,9 +14,14 @@ import {
14
14
  selectActiveStory,
15
15
  setLastError,
16
16
  trimErrorMessage
17
- } from "./chunk-SOM4QA6C.js";
18
- import "./chunk-ICM463EO.js";
19
- import "./chunk-3R27MJ5R.js";
17
+ } from "./chunk-JCR5C5A7.js";
18
+ import "./chunk-NP47HRX2.js";
19
+ import "./chunk-44RF3VFG.js";
20
+ import "./chunk-7MJGYPHF.js";
21
+ import "./chunk-XNK5UN2D.js";
22
+ import "./chunk-MAJ6QDRL.js";
23
+ import "./chunk-KUA6KBBD.js";
24
+ import "./chunk-PFWHHYEO.js";
20
25
  export {
21
26
  allStoriesPass,
22
27
  applyStoryMetrics,
@@ -33,4 +38,4 @@ export {
33
38
  setLastError,
34
39
  trimErrorMessage
35
40
  };
36
- //# sourceMappingURL=state-manager-UPHO2EA2.js.map
41
+ //# sourceMappingURL=state-manager-SRN4VJSX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -2,39 +2,42 @@
2
2
  import {
3
3
  groupBy,
4
4
  summarize
5
- } from "./chunk-CRGIQFUQ.js";
6
- import {
7
- resolveProjectPaths
8
- } from "./chunk-LI35PIIS.js";
5
+ } from "./chunk-E2H3JV2E.js";
9
6
  import {
10
7
  printError,
11
- printInfo
12
- } from "./chunk-XZUEFTUP.js";
13
- import "./chunk-QPGEFLMY.js";
14
- import {
15
- getIssuePaths
16
- } from "./chunk-HAKDLR6N.js";
17
- import "./chunk-YVPZUN6X.js";
18
- import "./chunk-DUS5ZNKL.js";
8
+ printInfo,
9
+ resolveIssuePaths,
10
+ resolveProjectPaths
11
+ } from "./chunk-DBLXLKGU.js";
12
+ import "./chunk-I64N6RL6.js";
13
+ import "./chunk-DIMDAYZS.js";
19
14
  import {
20
15
  discardedExecutionCount
21
- } from "./chunk-6K2LCFG6.js";
22
- import "./chunk-PPZ3K4YM.js";
16
+ } from "./chunk-WB4FA2EH.js";
17
+ import "./chunk-VHQMMY2D.js";
18
+ import "./chunk-P3LRUNC6.js";
19
+ import "./chunk-RDPK7LYK.js";
23
20
  import {
24
21
  loadTaskPlan
25
- } from "./chunk-SOM4QA6C.js";
26
- import "./chunk-ICM463EO.js";
27
- import "./chunk-XEYH6ZZI.js";
28
- import "./chunk-P3LRUNC6.js";
29
- import "./chunk-3R27MJ5R.js";
22
+ } from "./chunk-JCR5C5A7.js";
23
+ import "./chunk-NP47HRX2.js";
24
+ import "./chunk-44RF3VFG.js";
25
+ import {
26
+ listStoredExecutions
27
+ } from "./chunk-7MJGYPHF.js";
28
+ import "./chunk-XNK5UN2D.js";
29
+ import "./chunk-MAJ6QDRL.js";
30
+ import "./chunk-KUA6KBBD.js";
31
+ import "./chunk-PFWHHYEO.js";
30
32
 
31
33
  // src/commands/usage.ts
32
- import { readdir } from "fs/promises";
34
+ import { readdir } from "node:fs/promises";
33
35
  var USAGE_GROUP_KEYS = [
34
36
  "harness",
35
37
  "provider",
36
38
  "model",
37
39
  "purpose",
40
+ "trigger",
38
41
  "status"
39
42
  ];
40
43
  function sinceCutoff(since) {
@@ -75,50 +78,16 @@ function successRate(summary) {
75
78
  const ok = summary.byStatus.completed ?? 0;
76
79
  return `${(ok / summary.count * 100).toFixed(1)}%`;
77
80
  }
78
- async function loadPlans(issue) {
79
- let project;
80
- try {
81
- project = await resolveProjectPaths();
82
- } catch (err) {
83
- printError(`Not inside a usable project: ${err instanceof Error ? err.message : String(err)}`);
84
- return null;
85
- }
86
- if (issue !== void 0) {
87
- try {
88
- const paths = getIssuePaths(project.projectId, issue);
89
- return [{ id: issue, plan: await loadTaskPlan(paths.tasksFile) }];
90
- } catch (err) {
91
- printError(
92
- `No telemetry for issue ${issue}: ${err instanceof Error ? err.message : String(err)}`
93
- );
94
- return null;
95
- }
96
- }
97
- let ids;
98
- try {
99
- ids = await readdir(project.issuesDir);
100
- } catch {
101
- return [];
102
- }
103
- const loaded = [];
104
- for (const id of ids) {
105
- try {
106
- loaded.push({
107
- id,
108
- plan: await loadTaskPlan(getIssuePaths(project.projectId, id).tasksFile)
109
- });
110
- } catch {
111
- }
112
- }
113
- return loaded;
114
- }
115
81
  function buildUsageReport(plans, options, discarded = 0) {
116
82
  const cutoff = sinceCutoff(options.since);
117
83
  const records = plans.flatMap(({ plan }) => afterCutoff(plan.executions ?? [], cutoff));
84
+ return buildUsageReportFromRecords(records, options, discarded);
85
+ }
86
+ function buildUsageReportFromRecords(records, options, discarded = 0) {
118
87
  const total = summarize(records, discarded);
119
88
  const groups = options.by === void 0 ? [] : [...groupBy(records, options.by)].map(([key, summary]) => ({ key, summary }));
120
89
  return {
121
- issue: options.issue ?? (plans.length === 1 ? plans[0]?.id ?? null : null),
90
+ issue: options.issue ?? null,
122
91
  since: options.since ?? null,
123
92
  by: options.by ?? null,
124
93
  discarded,
@@ -149,14 +118,50 @@ function formatUsageReport(report) {
149
118
  return [`${header}`, columns, ...rows].join("\n");
150
119
  }
151
120
  async function runUsage(issue, options = {}) {
152
- const plans = await loadPlans(issue ?? options.issue);
153
- if (plans === null) return 1;
154
121
  if (options.since !== void 0 && sinceCutoff(options.since) === null) {
155
122
  printError(`Invalid --since date: ${options.since}`);
156
123
  return 1;
157
124
  }
158
- const report = buildUsageReport(plans, { ...options, issue: issue ?? options.issue });
159
- if (plans.length === 0 || report.total.count === 0 && (issue ?? options.issue) !== void 0) {
125
+ const requestedIssue = issue ?? options.issue;
126
+ let project;
127
+ try {
128
+ project = await resolveProjectPaths();
129
+ } catch (err) {
130
+ printError(`Not inside a usable project: ${err instanceof Error ? err.message : String(err)}`);
131
+ return 1;
132
+ }
133
+ let records;
134
+ try {
135
+ if (project.storageDriver === "sqlite") {
136
+ records = await listStoredExecutions({
137
+ projectId: project.projectId,
138
+ ...requestedIssue === void 0 ? {} : { issueId: requestedIssue },
139
+ ...options.since === void 0 ? {} : { since: options.since }
140
+ });
141
+ } else {
142
+ const ids = requestedIssue === void 0 ? await readdir(project.issuesDir) : [requestedIssue];
143
+ const plans = await Promise.all(
144
+ ids.map(async (id) => {
145
+ try {
146
+ const paths = await resolveIssuePaths(id);
147
+ return await loadTaskPlan(paths.tasksFile);
148
+ } catch {
149
+ return null;
150
+ }
151
+ })
152
+ );
153
+ records = plans.flatMap((plan) => plan?.executions ?? []);
154
+ const cutoff = sinceCutoff(options.since);
155
+ if (cutoff !== null) records = afterCutoff(records, cutoff);
156
+ }
157
+ } catch (err) {
158
+ printError(
159
+ `Could not query execution telemetry: ${err instanceof Error ? err.message : String(err)}`
160
+ );
161
+ return 1;
162
+ }
163
+ const report = buildUsageReportFromRecords(records, { ...options, issue: requestedIssue });
164
+ if (report.total.count === 0) {
160
165
  printInfo("No execution telemetry recorded yet.");
161
166
  return 0;
162
167
  }
@@ -170,8 +175,9 @@ async function runUsage(issue, options = {}) {
170
175
  export {
171
176
  USAGE_GROUP_KEYS,
172
177
  buildUsageReport,
178
+ buildUsageReportFromRecords,
173
179
  discardedExecutionCount,
174
180
  formatUsageReport,
175
181
  runUsage
176
182
  };
177
- //# sourceMappingURL=usage-KTMYXAPF.js.map
183
+ //# sourceMappingURL=usage-JOODVE5O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/usage.ts"],"sourcesContent":["import { readdir } from 'node:fs/promises';\nimport { loadTaskPlan } from '../core/state-manager.js';\nimport { listStoredExecutions } from '../storage/db/repository.js';\nimport { resolveIssuePaths, 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 'trigger',\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\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 return buildUsageReportFromRecords(records, options, discarded);\n}\n\n/** Build the same report from the canonical execution rows. */\nexport function buildUsageReportFromRecords(\n records: readonly ExecutionRecord[],\n options: UsageOptions,\n discarded = 0,\n): UsageReport {\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 ?? 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 if (options.since !== undefined && sinceCutoff(options.since) === null) {\n printError(`Invalid --since date: ${options.since}`);\n return 1;\n }\n\n const requestedIssue = issue ?? options.issue;\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 1;\n }\n\n let records: ExecutionRecord[];\n try {\n if (project.storageDriver === 'sqlite') {\n records = await listStoredExecutions({\n projectId: project.projectId,\n ...(requestedIssue === undefined ? {} : { issueId: requestedIssue }),\n ...(options.since === undefined ? {} : { since: options.since }),\n });\n } else {\n const ids =\n requestedIssue === undefined ? await readdir(project.issuesDir) : [requestedIssue];\n const plans = await Promise.all(\n ids.map(async (id) => {\n try {\n const paths = await resolveIssuePaths(id);\n return await loadTaskPlan(paths.tasksFile);\n } catch {\n return null;\n }\n }),\n );\n records = plans.flatMap((plan) => plan?.executions ?? []);\n const cutoff = sinceCutoff(options.since);\n if (cutoff !== null) records = afterCutoff(records, cutoff);\n }\n } catch (err) {\n printError(\n `Could not query execution telemetry: ${err instanceof Error ? err.message : String(err)}`,\n );\n return 1;\n }\n\n const report = buildUsageReportFromRecords(records, { ...options, issue: requestedIssue });\n if (report.total.count === 0) {\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":[]}
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ readSessionFile
4
+ } from "./chunk-23VHVVKW.js";
5
+ import {
6
+ ensureSingleWebServer,
7
+ stopWebMonitor
8
+ } from "./chunk-V7GETODQ.js";
9
+ import "./chunk-EORDSKWZ.js";
10
+ import "./chunk-BTBJ5UOO.js";
11
+ import "./chunk-CLZ6RRZL.js";
12
+ import "./chunk-VJ3PF6B7.js";
13
+ import "./chunk-2YM2VH6R.js";
14
+ import {
15
+ loadWebConfig
16
+ } from "./chunk-YC24E66P.js";
17
+ import {
18
+ loadGlobalConfig,
19
+ parseJournal,
20
+ resolveProjectPaths
21
+ } from "./chunk-DBLXLKGU.js";
22
+ import "./chunk-I64N6RL6.js";
23
+ import "./chunk-DIMDAYZS.js";
24
+ import "./chunk-WB4FA2EH.js";
25
+ import "./chunk-VHQMMY2D.js";
26
+ import "./chunk-P3LRUNC6.js";
27
+ import "./chunk-RDPK7LYK.js";
28
+ import "./chunk-JCR5C5A7.js";
29
+ import "./chunk-NP47HRX2.js";
30
+ import "./chunk-44RF3VFG.js";
31
+ import {
32
+ listStoredSessionEvents,
33
+ listStoredSessions
34
+ } from "./chunk-7MJGYPHF.js";
35
+ import {
36
+ sessionSnapshotSchema
37
+ } from "./chunk-XNK5UN2D.js";
38
+ import {
39
+ EVENTS_FILENAME,
40
+ ISSUES_DIR_NAME,
41
+ PROJECTS_DIR_NAME,
42
+ ROTATED_EVENTS_FILENAME,
43
+ SESSION_FILENAME,
44
+ getGlobalRoot
45
+ } from "./chunk-MAJ6QDRL.js";
46
+ import "./chunk-KUA6KBBD.js";
47
+ import "./chunk-PFWHHYEO.js";
48
+
49
+ // src/web/session-directory.ts
50
+ import { readdir, readFile } from "node:fs/promises";
51
+ import { join } from "node:path";
52
+ var DEFAULT_POLL_INTERVAL_MS = 3e3;
53
+ var DEFAULT_STALE_AFTER_MS = 9e4;
54
+ function watchSessionDirectory(options = {}) {
55
+ const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
56
+ const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
57
+ const warn = options.onWarn;
58
+ const storageDriver = options.storageDriver ?? "sqlite";
59
+ const root = getGlobalRoot(options);
60
+ let sessions = /* @__PURE__ */ new Map();
61
+ let warned = false;
62
+ async function scan() {
63
+ try {
64
+ if (storageDriver === "json") {
65
+ sessions = await scanJsonSessions(root, staleAfterMs);
66
+ return;
67
+ }
68
+ const since = new Date(Date.now() - staleAfterMs).toISOString();
69
+ const stored = await listStoredSessions({
70
+ activeSince: since,
71
+ ...options.env === void 0 ? {} : { databaseOptions: { env: options.env } }
72
+ });
73
+ sessions = toSessionMap(stored);
74
+ } catch (error) {
75
+ if (!warned) {
76
+ warned = true;
77
+ warn?.(
78
+ `issue-flow: web monitor could not query SQLite session state (will keep retrying silently): ${error instanceof Error ? error.message : String(error)}`
79
+ );
80
+ }
81
+ }
82
+ }
83
+ void scan();
84
+ const timer = setInterval(() => void scan(), pollIntervalMs);
85
+ timer.unref();
86
+ return {
87
+ sessions: () => [...sessions.values()],
88
+ getSession: (sessionId) => sessions.get(sessionId),
89
+ events: async (sessionId) => {
90
+ const session = sessions.get(sessionId);
91
+ if (session === void 0) return void 0;
92
+ if (storageDriver === "json") {
93
+ const issueDir = join(
94
+ root,
95
+ PROJECTS_DIR_NAME,
96
+ session.projectId,
97
+ ISSUES_DIR_NAME,
98
+ session.issueId
99
+ );
100
+ const [rotated, current] = await Promise.all([
101
+ readFile(join(issueDir, ROTATED_EVENTS_FILENAME), "utf-8").catch(() => ""),
102
+ readFile(join(issueDir, EVENTS_FILENAME), "utf-8").catch(() => "")
103
+ ]);
104
+ return parseJournal(`${rotated}${current}`);
105
+ }
106
+ return listStoredSessionEvents({
107
+ projectId: session.projectId,
108
+ sessionId,
109
+ ...options.env === void 0 ? {} : { databaseOptions: { env: options.env } }
110
+ });
111
+ },
112
+ refresh: scan,
113
+ close: () => clearInterval(timer)
114
+ };
115
+ }
116
+ async function directories(path) {
117
+ try {
118
+ return (await readdir(path, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
119
+ } catch {
120
+ return [];
121
+ }
122
+ }
123
+ async function scanJsonSessions(root, staleAfterMs) {
124
+ const found = /* @__PURE__ */ new Map();
125
+ for (const projectId of await directories(join(root, PROJECTS_DIR_NAME))) {
126
+ const issuesDir = join(root, PROJECTS_DIR_NAME, projectId, ISSUES_DIR_NAME);
127
+ for (const issueId of await directories(issuesDir)) {
128
+ const result = await readSessionFile(join(issuesDir, issueId, SESSION_FILENAME));
129
+ if (result === null || Date.now() - result.updatedAtMs > staleAfterMs) continue;
130
+ const sessionId = result.snapshot.sessionId;
131
+ if (sessionId === null) continue;
132
+ found.set(sessionId, {
133
+ projectId,
134
+ issueId,
135
+ snapshot: result.snapshot,
136
+ updatedAtMs: result.updatedAtMs
137
+ });
138
+ }
139
+ }
140
+ return found;
141
+ }
142
+ function toSessionMap(stored) {
143
+ const sessions = /* @__PURE__ */ new Map();
144
+ for (const entry of stored) {
145
+ const snapshot = sessionSnapshotSchema.safeParse(entry.snapshot);
146
+ if (!snapshot.success) continue;
147
+ sessions.set(entry.sessionId, {
148
+ projectId: entry.projectId,
149
+ issueId: entry.issueId,
150
+ snapshot: snapshot.data,
151
+ updatedAtMs: Date.parse(entry.updatedAt)
152
+ });
153
+ }
154
+ return sessions;
155
+ }
156
+
157
+ // src/commands/web.ts
158
+ async function runWebServe(options) {
159
+ const cli = {};
160
+ if (options.port !== void 0) cli.port = options.port;
161
+ if (options.host !== void 0) cli.host = options.host;
162
+ if (options.refresh !== void 0) cli.refreshSeconds = options.refresh;
163
+ const webConfig = await loadWebConfig({ cli });
164
+ let storageDriver = (await loadGlobalConfig()).storage?.driver ?? "sqlite";
165
+ try {
166
+ storageDriver = (await resolveProjectPaths()).storageDriver;
167
+ } catch {
168
+ }
169
+ const sessions = watchSessionDirectory({ storageDriver });
170
+ const noop = () => {
171
+ };
172
+ const handle = await ensureSingleWebServer({
173
+ sessions,
174
+ port: webConfig.port,
175
+ host: webConfig.host,
176
+ refreshSeconds: webConfig.refreshSeconds,
177
+ unref: false,
178
+ info: noop,
179
+ warn: noop
180
+ });
181
+ if (handle === null) {
182
+ sessions.close();
183
+ return 1;
184
+ }
185
+ if (handle.server === void 0) {
186
+ sessions.close();
187
+ return 0;
188
+ }
189
+ const originalClose = handle.close;
190
+ handle.close = async () => {
191
+ await originalClose();
192
+ sessions.close();
193
+ };
194
+ return 0;
195
+ }
196
+ async function runWebStop() {
197
+ const webConfig = await loadWebConfig();
198
+ const result = await stopWebMonitor({ port: webConfig.port, host: webConfig.host });
199
+ return result === "failed" || result === "unowned" ? 1 : 0;
200
+ }
201
+ export {
202
+ runWebServe,
203
+ runWebStop
204
+ };
205
+ //# sourceMappingURL=web-TLMWJ2BM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/web/session-directory.ts","../src/commands/web.ts"],"sourcesContent":["import { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { type JournalEntry, parseJournal } from '../core/journal.js';\nimport { sessionSnapshotSchema, type ValidatedSessionSnapshot } from '../schemas.js';\nimport {\n listStoredSessionEvents,\n listStoredSessions,\n type StoredSession,\n} from '../storage/db/repository.js';\nimport {\n EVENTS_FILENAME,\n type GetGlobalRootOptions,\n getGlobalRoot,\n ISSUES_DIR_NAME,\n PROJECTS_DIR_NAME,\n ROTATED_EVENTS_FILENAME,\n SESSION_FILENAME,\n} from '../storage/paths.js';\nimport { readSessionFile } from '../storage/session-file.js';\n\n/** How often the monitor refreshes indexed session state. */\nexport const DEFAULT_POLL_INTERVAL_MS = 3000;\n\n/** A run remains visible through three missed ten-second heartbeats. */\nexport const DEFAULT_STALE_AFTER_MS = 90_000;\n\nexport interface ActiveSession {\n /** SQLite project identity, used to retrieve this session's event stream. */\n projectId: string;\n issueId: string;\n snapshot: ValidatedSessionSnapshot;\n /** Latest database heartbeat in epoch milliseconds. */\n updatedAtMs: number;\n}\n\nexport interface SessionDirectoryOptions extends GetGlobalRootOptions {\n pollIntervalMs?: number;\n staleAfterMs?: number;\n onWarn?: (message: string) => void;\n storageDriver?: 'sqlite' | 'json';\n}\n\nexport interface SessionDirectoryHandle {\n sessions(): ActiveSession[];\n getSession(sessionId: string): ActiveSession | undefined;\n events(sessionId: string): Promise<JournalEntry[] | undefined>;\n refresh(): Promise<void>;\n close(): void;\n}\n\n/**\n * Poll the canonical SQLite session history for every project on this machine.\n *\n * `session.json` and JSONL journals remain compatibility projections for\n * agents and older tooling, but the detached monitor must not traverse them:\n * it is often a different process and SQLite gives it one indexed, atomic view\n * of sessions, heartbeats and event ordering.\n */\nexport function watchSessionDirectory(\n options: SessionDirectoryOptions = {},\n): SessionDirectoryHandle {\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;\n const warn = options.onWarn;\n const storageDriver = options.storageDriver ?? 'sqlite';\n const root = getGlobalRoot(options);\n let sessions = new Map<string, ActiveSession>();\n let warned = false;\n\n async function scan(): Promise<void> {\n try {\n if (storageDriver === 'json') {\n sessions = await scanJsonSessions(root, staleAfterMs);\n return;\n }\n const since = new Date(Date.now() - staleAfterMs).toISOString();\n const stored = await listStoredSessions({\n activeSince: since,\n ...(options.env === undefined ? {} : { databaseOptions: { env: options.env } }),\n });\n sessions = toSessionMap(stored);\n } catch (error) {\n if (!warned) {\n warned = true;\n warn?.(\n `issue-flow: web monitor could not query SQLite session state (will keep retrying silently): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n }\n\n void scan();\n const timer = setInterval(() => void scan(), pollIntervalMs);\n timer.unref();\n\n return {\n sessions: () => [...sessions.values()],\n getSession: (sessionId) => sessions.get(sessionId),\n events: async (sessionId) => {\n const session = sessions.get(sessionId);\n if (session === undefined) return undefined;\n if (storageDriver === 'json') {\n const issueDir = join(\n root,\n PROJECTS_DIR_NAME,\n session.projectId,\n ISSUES_DIR_NAME,\n session.issueId,\n );\n const [rotated, current] = await Promise.all([\n readFile(join(issueDir, ROTATED_EVENTS_FILENAME), 'utf-8').catch(() => ''),\n readFile(join(issueDir, EVENTS_FILENAME), 'utf-8').catch(() => ''),\n ]);\n return parseJournal(`${rotated}${current}`);\n }\n return listStoredSessionEvents({\n projectId: session.projectId,\n sessionId,\n ...(options.env === undefined ? {} : { databaseOptions: { env: options.env } }),\n });\n },\n refresh: scan,\n close: () => clearInterval(timer),\n };\n}\n\nasync function directories(path: string): Promise<string[]> {\n try {\n return (await readdir(path, { withFileTypes: true }))\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name);\n } catch {\n return [];\n }\n}\n\nasync function scanJsonSessions(\n root: string,\n staleAfterMs: number,\n): Promise<Map<string, ActiveSession>> {\n const found = new Map<string, ActiveSession>();\n for (const projectId of await directories(join(root, PROJECTS_DIR_NAME))) {\n const issuesDir = join(root, PROJECTS_DIR_NAME, projectId, ISSUES_DIR_NAME);\n for (const issueId of await directories(issuesDir)) {\n const result = await readSessionFile(join(issuesDir, issueId, SESSION_FILENAME));\n if (result === null || Date.now() - result.updatedAtMs > staleAfterMs) continue;\n const sessionId = result.snapshot.sessionId;\n if (sessionId === null) continue;\n found.set(sessionId, {\n projectId,\n issueId,\n snapshot: result.snapshot,\n updatedAtMs: result.updatedAtMs,\n });\n }\n }\n return found;\n}\n\nfunction toSessionMap(stored: StoredSession[]): Map<string, ActiveSession> {\n const sessions = new Map<string, ActiveSession>();\n for (const entry of stored) {\n const snapshot = sessionSnapshotSchema.safeParse(entry.snapshot);\n if (!snapshot.success) continue;\n sessions.set(entry.sessionId, {\n projectId: entry.projectId,\n issueId: entry.issueId,\n snapshot: snapshot.data,\n updatedAtMs: Date.parse(entry.updatedAt),\n });\n }\n return sessions;\n}\n","import { loadGlobalConfig } from '../config/sources.js';\nimport { loadWebConfig } from '../config.js';\nimport type { WebConfig } from '../schemas.js';\nimport { resolveProjectPaths } from '../storage/resolve.js';\nimport { ensureSingleWebServer, stopWebMonitor } from '../web/lock.js';\nimport { watchSessionDirectory } from '../web/session-directory.js';\n\n/**\n * `issue-flow web serve` / `issue-flow web stop` (US-002).\n *\n * `serve` is the process `ensureWebMonitor()` (`web/lock.ts`) spawns detached\n * — it is not meant to be run interactively, though nothing stops a user from\n * doing so to watch every session on the machine without going through a\n * pipeline command first. It never exits on its own: the server stays bound\n * (see `unref: false` in `web/server.ts`) until `stop` sends it `SIGTERM`, at\n * which point `startWebServer`'s own signal handler closes it (removing the\n * lock) and re-raises the signal for the default termination behavior.\n */\n\nexport interface RunWebServeOptions {\n port?: number;\n host?: string;\n refresh?: number;\n}\n\n/**\n * Bind (or defer to) the single web monitor instance and keep the process\n * alive for as long as it stays bound. Logging is intentionally silent on the\n * happy path: this process is spawned with `stdio: 'ignore'`, so anything\n * printed here goes nowhere — the caller (`ensureWebMonitor`) is the one that\n * tells the user the server is up.\n */\nexport async function runWebServe(options: RunWebServeOptions): Promise<number> {\n // Built conditionally, not `{ port: options.port, ... }`: loadWebConfig()\n // spreads this object directly over the lower-precedence layers, and an\n // explicit `undefined` value would overwrite an env/.issue-flow.json\n // setting instead of falling through to it (only an *absent* key does).\n const cli: Partial<WebConfig> = {};\n if (options.port !== undefined) cli.port = options.port;\n if (options.host !== undefined) cli.host = options.host;\n if (options.refresh !== undefined) cli.refreshSeconds = options.refresh;\n const webConfig = await loadWebConfig({ cli });\n\n let storageDriver = (await loadGlobalConfig()).storage?.driver ?? 'sqlite';\n try {\n storageDriver = (await resolveProjectPaths()).storageDriver;\n } catch {\n // The global monitor remains usable outside a repository.\n }\n const sessions = watchSessionDirectory({ storageDriver });\n\n const noop = (): void => {};\n const handle = await ensureSingleWebServer({\n sessions,\n port: webConfig.port,\n host: webConfig.host,\n refreshSeconds: webConfig.refreshSeconds,\n unref: false,\n info: noop,\n warn: noop,\n });\n\n if (handle === null) {\n sessions.close();\n return 1;\n }\n\n if (handle.server === undefined) {\n // Another instance already won the race (or was already running by the\n // time this process got here): nothing to serve, so it exits right away\n // instead of idling as a redundant detached process.\n sessions.close();\n return 0;\n }\n\n const originalClose = handle.close;\n handle.close = async () => {\n await originalClose();\n sessions.close();\n };\n\n return 0;\n}\n\n/** Stop the single running web monitor instance, if any. */\nexport async function runWebStop(): Promise<number> {\n const webConfig = await loadWebConfig();\n const result = await stopWebMonitor({ port: webConfig.port, host: webConfig.host });\n return result === 'failed' || result === 'unowned' ? 1 : 0;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "issue-flow",
3
- "version": "0.18.0",
4
- "description": "Unified CLI for orchestrating the full issue-flow pipeline via Claude Code, Codex CLI, Cursor CLI or Antigravity CLI",
3
+ "version": "0.20.0",
4
+ "description": "Unified CLI for orchestrating the full issue-flow pipeline via Claude Code, Codex CLI, Cursor CLI, Antigravity CLI or OpenCode CLI",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "issue-flow": "./dist/cli.js"
8
8
  },
9
9
  "scripts": {
10
- "build": "tsup",
10
+ "build": "npm run skills:sync && npm run build:cli",
11
11
  "dev": "tsup --watch",
12
12
  "typecheck": "tsc --noEmit",
13
13
  "test": "vitest run",
@@ -19,13 +19,22 @@
19
19
  "format": "biome format --write .",
20
20
  "check": "biome check . && tsc --noEmit",
21
21
  "fix": "biome check --write . && tsc --noEmit",
22
- "prepack": "npm run build",
23
- "prepublishOnly": "npm run lint && npm run typecheck && npm test",
22
+ "prepack": "npm run skills:check && npm run build",
23
+ "prepublishOnly": "npm run skills:check && npm run skills:test && npm run lint && npm run typecheck && npm test",
24
24
  "preversion": "node scripts/git-version.mjs check",
25
- "postversion": "node scripts/git-version.mjs commit"
25
+ "postversion": "node scripts/git-version.mjs commit",
26
+ "skills:sync": "node scripts/skills-build.mjs",
27
+ "skills:check": "node scripts/skills-check.mjs",
28
+ "skills:test": "node --test scripts/skills.test.mjs",
29
+ "skills:install-test": "node scripts/skills-install-test.mjs",
30
+ "skills:eval": "node scripts/skills-eval.mjs",
31
+ "skills:benchmark": "node scripts/skills-benchmark.mjs",
32
+ "skills:cli-test": "node scripts/skills-cli-test.mjs",
33
+ "build:cli": "tsup",
34
+ "context:measure": "node scripts/architecture-benchmark.mjs"
26
35
  },
27
36
  "engines": {
28
- "node": ">=22.0.0"
37
+ "node": ">=22.13.0"
29
38
  },
30
39
  "files": [
31
40
  "dist",
@@ -39,6 +48,7 @@
39
48
  "codex",
40
49
  "cursor",
41
50
  "antigravity",
51
+ "opencode",
42
52
  "automation",
43
53
  "cli",
44
54
  "pipeline",
@@ -68,8 +78,12 @@
68
78
  "devDependencies": {
69
79
  "@biomejs/biome": "2.4.10",
70
80
  "@types/node": "^22.14.0",
81
+ "esbuild": "^0.28.2",
82
+ "mdast-util-from-markdown": "^2.0.3",
83
+ "skills": "1.5.23",
71
84
  "tsup": "^8.4.0",
72
85
  "typescript": "^5.8.3",
73
- "vitest": "^3.1.1"
86
+ "vitest": "^3.1.1",
87
+ "yaml": "^2.9.0"
74
88
  }
75
89
  }