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
@@ -3,60 +3,54 @@ import {
3
3
  applyAcceptanceToPlan,
4
4
  formatVerificationLine,
5
5
  runAcceptanceGate
6
- } from "./chunk-ECU7YO7S.js";
6
+ } from "./chunk-PM5YWJYO.js";
7
7
  import {
8
8
  issuePlaceholders,
9
9
  resolveCommandIssue
10
- } from "./chunk-SA6HXL4Y.js";
10
+ } from "./chunk-7WBUEBD5.js";
11
11
  import {
12
12
  publishPhaseMetrics,
13
13
  resolvePolicyPlaceholders
14
- } from "./chunk-KMCS76ZW.js";
14
+ } from "./chunk-KUL64XUF.js";
15
15
  import {
16
16
  applyPlaceholders,
17
17
  loadPrompt
18
- } from "./chunk-7F7LGMVO.js";
18
+ } from "./chunk-BTBJ5UOO.js";
19
19
  import {
20
20
  DEFAULT_HEADLESS_TIMEOUT_MS,
21
21
  runHeadless
22
- } from "./chunk-TZYINKCC.js";
23
- import {
24
- resolveIssuePaths
25
- } from "./chunk-LI35PIIS.js";
22
+ } from "./chunk-UDUUUFQF.js";
26
23
  import {
27
24
  getGlobalTimeout,
28
25
  printError,
29
26
  printSuccess,
30
- printWarning
31
- } from "./chunk-XZUEFTUP.js";
27
+ printWarning,
28
+ resolveIssuePaths
29
+ } from "./chunk-DBLXLKGU.js";
32
30
  import {
33
31
  loadTaskPlan,
34
32
  saveTaskPlan
35
- } from "./chunk-SOM4QA6C.js";
33
+ } from "./chunk-JCR5C5A7.js";
36
34
 
37
- // src/commands/review.ts
38
- function parseReviewResult(output) {
39
- const match = output.match(/<review-result>([\s\S]*?)<\/review-result>/);
40
- if (!match) {
41
- if (/STATUS:\s*PASS/i.test(output)) {
42
- return { status: "PASS" };
43
- }
44
- if (/STATUS:\s*FAIL/i.test(output)) {
45
- const findingsMatch2 = output.match(/FINDINGS:([\s\S]*?)(?:$|<\/)/);
46
- return { status: "FAIL", findings: findingsMatch2?.[1]?.trim() ?? "Unknown findings" };
47
- }
48
- return { status: "PASS" };
35
+ // src/verify/review-result.ts
36
+ function parseIssueReviewResult(output) {
37
+ const blocks = [...output.matchAll(/<review-result>([\s\S]*?)<\/review-result>/g)];
38
+ if (blocks.length !== 1 || (output.match(/<\/?review-result>/g)?.length ?? 0) !== 2 || !output.trimEnd().endsWith("</review-result>")) {
39
+ return { ok: false, error: "Expected exactly one final <review-result> block." };
49
40
  }
50
- const block = match[1];
51
- if (/STATUS:\s*PASS/i.test(block)) {
52
- return { status: "PASS" };
41
+ const body = blocks[0][1].trim();
42
+ if (body === "STATUS: PASS") return { ok: true, status: "PASS" };
43
+ const failure = body.match(/^STATUS: FAIL\s*\r?\nFINDINGS:\s*\r?\n([\s\S]+)$/);
44
+ if (failure && !/^STATUS:/m.test(failure[1])) {
45
+ const lines = failure[1].trim().split(/\r?\n/);
46
+ if (lines.every((line) => /^-\s+\S/.test(line))) {
47
+ return { ok: true, status: "FAIL", findings: lines.join("\n") };
48
+ }
53
49
  }
54
- const findingsMatch = block.match(/FINDINGS:([\s\S]*)/);
55
- return {
56
- status: "FAIL",
57
- findings: findingsMatch?.[1]?.trim() ?? "Unknown findings"
58
- };
50
+ return { ok: false, error: "Invalid review status or findings; no approval inferred." };
59
51
  }
52
+
53
+ // src/commands/review.ts
60
54
  async function runReview(issue, resolvedIssue) {
61
55
  const issueNumber = issue.replace(/^#/, "");
62
56
  const paths = await resolveIssuePaths(issueNumber);
@@ -84,25 +78,16 @@ async function runReview(issue, resolvedIssue) {
84
78
  } else {
85
79
  printSuccess(formatVerificationLine(acceptance.verdict, acceptance.level));
86
80
  }
87
- if (acceptance.review?.status === "failed") {
88
- printError("Independent review failed");
89
- try {
90
- const plan = await loadTaskPlan(tasksPath);
91
- plan.pipeline.reviewCompleted = false;
92
- plan.lastReviewFindings = acceptance.review.findings.map((finding) => finding.claim).join("\n");
93
- await saveTaskPlan(tasksPath, plan);
94
- } catch {
95
- }
96
- return 1;
97
- }
98
81
  const template = await loadPrompt("review");
99
82
  const prompt = applyPlaceholders(template, {
100
83
  // The repository's own conventions. Empty when it declares none, which is
101
84
  // what keeps the rendered prompt identical to the pre-policy one.
102
- ...await resolvePolicyPlaceholders(),
85
+ ...await resolvePolicyPlaceholders({ phase: "review" }),
103
86
  __ISSUE_NUMBER__: issueNumber,
104
87
  __TASKS_PATH__: tasksPath,
105
- ...issuePlaceholders(resolution.resolved)
88
+ __PROGRESS_FILE__: paths.progressFile,
89
+ __VERIFY_PATH__: paths.verifyFile,
90
+ ...issuePlaceholders(resolution.resolved, paths.issueFile)
106
91
  });
107
92
  const startedAtMs = Date.now();
108
93
  let reviewContext;
@@ -134,10 +119,28 @@ async function runReview(issue, resolvedIssue) {
134
119
  printError(`Review failed: ${result.error}`);
135
120
  return 1;
136
121
  }
137
- const review = parseReviewResult(result.result);
122
+ const review = parseIssueReviewResult(result.result);
123
+ if (!review.ok) {
124
+ printError(`Invalid review result: ${review.error}`);
125
+ try {
126
+ const plan = await loadTaskPlan(tasksPath);
127
+ plan.pipeline.reviewCompleted = false;
128
+ plan.issueStatus = "in_progress";
129
+ plan.completedAt = null;
130
+ plan.lastError = {
131
+ category: "review_protocol",
132
+ message: review.error,
133
+ at: (/* @__PURE__ */ new Date()).toISOString()
134
+ };
135
+ await saveTaskPlan(tasksPath, plan);
136
+ } catch {
137
+ }
138
+ return 1;
139
+ }
138
140
  if (review.status === "PASS") {
139
141
  try {
140
142
  const plan = await loadTaskPlan(tasksPath);
143
+ if (plan.lastError?.category === "review_protocol") plan.lastError = null;
141
144
  plan.pipeline.reviewCompleted = true;
142
145
  plan.lastReviewFindings = null;
143
146
  await saveTaskPlan(tasksPath, plan);
@@ -153,6 +156,9 @@ async function runReview(issue, resolvedIssue) {
153
156
  try {
154
157
  const plan = await loadTaskPlan(tasksPath);
155
158
  plan.pipeline.reviewCompleted = false;
159
+ if (plan.lastError?.category === "review_protocol") plan.lastError = null;
160
+ plan.issueStatus = "in_progress";
161
+ plan.completedAt = null;
156
162
  plan.lastReviewFindings = review.findings ?? "Unknown findings";
157
163
  await saveTaskPlan(tasksPath, plan);
158
164
  } catch {
@@ -163,4 +169,4 @@ async function runReview(issue, resolvedIssue) {
163
169
  export {
164
170
  runReview
165
171
  };
166
- //# sourceMappingURL=chunk-EG2MGDP5.js.map
172
+ //# sourceMappingURL=chunk-Z6RCKCVB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/verify/review-result.ts","../src/commands/review.ts"],"sourcesContent":["/** Portable issue-review protocol. No host, filesystem or orchestration dependencies. */\nexport type IssueReviewParse =\n | { ok: true; status: 'PASS' | 'FAIL'; findings?: string }\n | { ok: false; error: string };\n\nexport function parseIssueReviewResult(output: string): IssueReviewParse {\n const blocks = [...output.matchAll(/<review-result>([\\s\\S]*?)<\\/review-result>/g)];\n if (\n blocks.length !== 1 ||\n (output.match(/<\\/?review-result>/g)?.length ?? 0) !== 2 ||\n !output.trimEnd().endsWith('</review-result>')\n ) {\n return { ok: false, error: 'Expected exactly one final <review-result> block.' };\n }\n const body = blocks[0][1].trim();\n if (body === 'STATUS: PASS') return { ok: true, status: 'PASS' };\n const failure = body.match(/^STATUS: FAIL\\s*\\r?\\nFINDINGS:\\s*\\r?\\n([\\s\\S]+)$/);\n if (failure && !/^STATUS:/m.test(failure[1])) {\n const lines = failure[1].trim().split(/\\r?\\n/);\n if (lines.every((line) => /^-\\s+\\S/.test(line))) {\n return { ok: true, status: 'FAIL', findings: lines.join('\\n') };\n }\n }\n return { ok: false, error: 'Invalid review status or findings; no approval inferred.' };\n}\n","import { DEFAULT_HEADLESS_TIMEOUT_MS, runHeadless } from '../core/headless.js';\nimport { applyPlaceholders, loadPrompt } from '../core/prompt-resolver.js';\nimport { publishPhaseMetrics } from '../core/session-metrics.js';\nimport { loadTaskPlan, saveTaskPlan } from '../core/state-manager.js';\nimport { getGlobalTimeout } from '../core/verbose.js';\nimport { issuePlaceholders, resolveCommandIssue } from '../issues/context.js';\nimport type { ResolvedIssue } from '../issues/types.js';\nimport { resolvePolicyPlaceholders } from '../policy/placeholders.js';\nimport { resolveIssuePaths } from '../storage/resolve.js';\nimport { printError, printSuccess, printWarning } from '../ui/logger.js';\nimport { applyAcceptanceToPlan, runAcceptanceGate } from '../verify/gate.js';\nimport { formatVerificationLine } from '../verify/present.js';\nimport { parseIssueReviewResult } from '../verify/review-result.js';\n\nexport async function runReview(issue: string, resolvedIssue?: ResolvedIssue): Promise<number> {\n const issueNumber = issue.replace(/^#/, '');\n const paths = await resolveIssuePaths(issueNumber);\n const tasksPath = paths.tasksFile;\n\n const resolution = await resolveCommandIssue(issueNumber, resolvedIssue);\n if (!resolution.ok) {\n return resolution.code;\n }\n\n const acceptance = await runAcceptanceGate({\n issueDir: paths.issueDir,\n addDirs: [paths.issueDir],\n });\n if (acceptance.verdict === 'failed') {\n try {\n const plan = await loadTaskPlan(tasksPath);\n const applied = applyAcceptanceToPlan(plan, acceptance);\n await saveTaskPlan(tasksPath, applied.plan);\n } catch {\n printError(formatVerificationLine(acceptance.verdict, acceptance.level));\n }\n return 1;\n }\n if (acceptance.verdict === 'unverified') {\n printWarning(formatVerificationLine(acceptance.verdict, acceptance.level));\n } else {\n printSuccess(formatVerificationLine(acceptance.verdict, acceptance.level));\n }\n const template = await loadPrompt('review');\n const prompt = applyPlaceholders(template, {\n // The repository's own conventions. Empty when it declares none, which is\n // what keeps the rendered prompt identical to the pre-policy one.\n ...(await resolvePolicyPlaceholders({ phase: 'review' })),\n __ISSUE_NUMBER__: issueNumber,\n __TASKS_PATH__: tasksPath,\n __PROGRESS_FILE__: paths.progressFile,\n __VERIFY_PATH__: paths.verifyFile,\n ...issuePlaceholders(resolution.resolved, paths.issueFile),\n });\n\n const startedAtMs = Date.now();\n let reviewContext: { storyIds: string[]; correctionCycle: number } | undefined;\n try {\n const plan = await loadTaskPlan(tasksPath);\n reviewContext = {\n storyIds: plan.userStories.map((story) => story.id),\n correctionCycle: plan.correctionCycle,\n };\n } catch {\n reviewContext = undefined;\n }\n const result = await runHeadless({\n prompt,\n maxTurns: 25,\n timeout: getGlobalTimeout() ?? DEFAULT_HEADLESS_TIMEOUT_MS,\n // json (not text) so the CLI reports usage: the envelope's `result` field\n // carries the same assistant text parseReviewResult() already consumed.\n outputFormat: 'json',\n allowedTools: ['Bash', 'Read', 'Glob', 'Grep'],\n addDirs: [paths.issueDir],\n statusMessage: `Reviewing issue #${issueNumber} resolution...`,\n phase: 'review',\n permission: 'read-only',\n ...(reviewContext ?? {}),\n });\n // Before the success check: the tokens were spent either way. A correction\n // cycle calls runReview() again and the reducer sums both invocations.\n publishPhaseMetrics('review', result.cost, startedAtMs, result.agent?.provider);\n\n if (!result.success) {\n printError(`Review failed: ${result.error}`);\n return 1;\n }\n\n const review = parseIssueReviewResult(result.result);\n if (!review.ok) {\n printError(`Invalid review result: ${review.error}`);\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = false;\n plan.issueStatus = 'in_progress';\n plan.completedAt = null;\n plan.lastError = {\n category: 'review_protocol',\n message: review.error,\n at: new Date().toISOString(),\n };\n await saveTaskPlan(tasksPath, plan);\n } catch {\n /* Standalone review may have no task plan. */\n }\n return 1;\n }\n\n if (review.status === 'PASS') {\n // Update pipeline state\n try {\n const plan = await loadTaskPlan(tasksPath);\n if (plan.lastError?.category === 'review_protocol') plan.lastError = null;\n plan.pipeline.reviewCompleted = true;\n plan.lastReviewFindings = null;\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n printSuccess('Review PASSED — implementation meets acceptance criteria');\n return 0;\n }\n\n printError('Review FAILED — issues found:');\n if (review.findings) {\n console.log(review.findings);\n }\n\n // Persist the findings so a correction cycle can act on them: without this,\n // a re-run of execute sees every userStories[].passes already true and\n // exits immediately without attempting any fix (see engine.ts's\n // \"already complete\" guards).\n try {\n const plan = await loadTaskPlan(tasksPath);\n plan.pipeline.reviewCompleted = false;\n if (plan.lastError?.category === 'review_protocol') plan.lastError = null;\n plan.issueStatus = 'in_progress';\n plan.completedAt = null;\n plan.lastReviewFindings = review.findings ?? 'Unknown findings';\n await saveTaskPlan(tasksPath, plan);\n } catch {\n // tasks.json may not exist\n }\n\n return 1;\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ NullPublisher
4
+ } from "./chunk-DIMDAYZS.js";
5
+ import {
6
+ isoNow
7
+ } from "./chunk-JCR5C5A7.js";
2
8
  import {
3
9
  getBaseBranch,
4
10
  getCommitsSince,
@@ -9,13 +15,7 @@ import {
9
15
  normalizeRemoteUrl,
10
16
  run,
11
17
  stripRemoteUrlCredentials
12
- } from "./chunk-YVPZUN6X.js";
13
- import {
14
- NullPublisher
15
- } from "./chunk-DUS5ZNKL.js";
16
- import {
17
- isoNow
18
- } from "./chunk-SOM4QA6C.js";
18
+ } from "./chunk-KUA6KBBD.js";
19
19
 
20
20
  // src/core/session-git.ts
21
21
  async function listPullRequests(branch, options = {}) {
@@ -112,4 +112,4 @@ export {
112
112
  listPullRequests,
113
113
  publishGitState
114
114
  };
115
- //# sourceMappingURL=chunk-YUNBOUQH.js.map
115
+ //# sourceMappingURL=chunk-ZPGNVBWY.js.map