@poetic-ai/poetic 1.42.1-bootstrap.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 (781) hide show
  1. package/.github/SECURITY.md +47 -0
  2. package/.nvmrc +1 -0
  3. package/.poetic/README.md +37 -0
  4. package/.poetic/providers/catalog.json +12051 -0
  5. package/.poetic/providers/pricing.json +1272 -0
  6. package/.poetic/providers/registry.json +3369 -0
  7. package/CHANGELOG.md +552 -0
  8. package/CODE_OF_CONDUCT.md +40 -0
  9. package/CONTRIBUTING.md +23 -0
  10. package/INSTALL.md +454 -0
  11. package/LICENSE +21 -0
  12. package/README.md +474 -0
  13. package/dist/BasicOptimizationCompetitionRunner-5H5TBYO4.js +153 -0
  14. package/dist/ExecutionTracker-UVONC4C6.js +16 -0
  15. package/dist/OptimizationConfig-7DFY2TST.js +17 -0
  16. package/dist/OptimizationEngine-MXTSOSST.js +1597 -0
  17. package/dist/PromptStore-U6ZD3ZMQ.js +18 -0
  18. package/dist/actions-M3AESHFF.js +322 -0
  19. package/dist/agent-ingest-HO77TH26.js +53 -0
  20. package/dist/aggregator-DNCBINFO.js +12 -0
  21. package/dist/ai-judge-LDWHURKK.js +156 -0
  22. package/dist/allowlist-grounding-RO6HKUFI.js +16 -0
  23. package/dist/allowlist-utils-23V7TJ3G.js +28 -0
  24. package/dist/anchored-turn-service-GFYU6GCQ.js +489 -0
  25. package/dist/api-transport-FS3CQRMN.js +1087 -0
  26. package/dist/apply-completion-mode-JBT2CTQO.js +89 -0
  27. package/dist/artifact-migrator-23L45ISD.js +267 -0
  28. package/dist/ask-UYVZY7JH.js +135 -0
  29. package/dist/auth-CSQP5RHJ.js +67 -0
  30. package/dist/auth-E6XUNZ5M.js +68 -0
  31. package/dist/auth-KQLJPZ2E.js +134 -0
  32. package/dist/auth-OC4E6633.js +71 -0
  33. package/dist/auth-R3NQ2ZF5.js +78 -0
  34. package/dist/auth-S4CTX4GQ.js +44 -0
  35. package/dist/auth-YLH3S7EY.js +69 -0
  36. package/dist/auth-liveness-TDDEZY3T.js +46 -0
  37. package/dist/auto-optimizer-HA3T23SF.js +80 -0
  38. package/dist/autoloop-cleanup-JOGKTLWA.js +109 -0
  39. package/dist/autoloop-evidence-gates-ACB5YW5G.js +36 -0
  40. package/dist/autoloop-gate-policy-XZA5EQFN.js +175 -0
  41. package/dist/autoloop-helpers-EFJLBQUP.js +22 -0
  42. package/dist/autoloop-ledger-W7QO62PX.js +96 -0
  43. package/dist/autoloop-ledger-subscriber-Z5RW5EIE.js +162 -0
  44. package/dist/autoloop-run-defaults-FERGRZGP.js +19 -0
  45. package/dist/autoloop-run-lock-CT2NWSV3.js +197 -0
  46. package/dist/autoloop-success-OPR74YEX.js +85 -0
  47. package/dist/autoloop-termination-summary-RN75F422.js +58 -0
  48. package/dist/autoloop-trajectory-K5I45UBR.js +282 -0
  49. package/dist/autoloop-wall-clock-T7ZVIQOC.js +12 -0
  50. package/dist/autonomous-loop-controller-4QJMOIIN.js +4120 -0
  51. package/dist/backend-P3DAYRP7.js +29 -0
  52. package/dist/background-executor-CBN552V4.js +257 -0
  53. package/dist/backlog-execution-intent-U4XYPTV6.js +15 -0
  54. package/dist/backup-active-store-5WXG6SXT.js +17 -0
  55. package/dist/backup-telemetry-db-XGLXAA3N.js +254 -0
  56. package/dist/basic-competition-master-WXZHUT42.js +344 -0
  57. package/dist/branch-archive-manager-RP6FP3ZC.js +254 -0
  58. package/dist/branch-cleanup-manager-RSHAI7YR.js +20 -0
  59. package/dist/build-gate-YFASRB5Z.js +71 -0
  60. package/dist/change-summary-WY7J5TOX.js +33 -0
  61. package/dist/chunk-25QL3M3L.js +899 -0
  62. package/dist/chunk-2ABC6SEC.js +2626 -0
  63. package/dist/chunk-2AICM4P3.js +1763 -0
  64. package/dist/chunk-2AQUWJPW.js +225 -0
  65. package/dist/chunk-2DY5KNVM.js +276 -0
  66. package/dist/chunk-2QJ3H3L7.js +42 -0
  67. package/dist/chunk-2UH6VQRZ.js +328 -0
  68. package/dist/chunk-2VSQMRCB.js +18 -0
  69. package/dist/chunk-2XQXYBM2.js +130 -0
  70. package/dist/chunk-2YFUIER7.js +426 -0
  71. package/dist/chunk-2YXZCZTX.js +1160 -0
  72. package/dist/chunk-32VLDFRT.js +797 -0
  73. package/dist/chunk-34CNP2HB.js +148 -0
  74. package/dist/chunk-35P3W3JX.js +456 -0
  75. package/dist/chunk-36PEBZAF.js +18 -0
  76. package/dist/chunk-3733QTI7.js +6818 -0
  77. package/dist/chunk-3A5PDH5L.js +12513 -0
  78. package/dist/chunk-3AOKYKA7.js +22 -0
  79. package/dist/chunk-3BCUNHKF.js +475 -0
  80. package/dist/chunk-3C26DPFK.js +566 -0
  81. package/dist/chunk-3FLXLLB7.js +26 -0
  82. package/dist/chunk-3FOZ2VHV.js +100 -0
  83. package/dist/chunk-3G6FZCRF.js +106 -0
  84. package/dist/chunk-3JWNRJSB.js +736 -0
  85. package/dist/chunk-3LUMR3D3.js +156 -0
  86. package/dist/chunk-3M57DADF.js +44 -0
  87. package/dist/chunk-3S62LLWJ.js +543 -0
  88. package/dist/chunk-3VABAKT2.js +1784 -0
  89. package/dist/chunk-44N5WZZH.js +45 -0
  90. package/dist/chunk-45FPSA3B.js +125 -0
  91. package/dist/chunk-4BIPZBT7.js +791 -0
  92. package/dist/chunk-4BJ3O4RQ.js +929 -0
  93. package/dist/chunk-4BTDUT2S.js +42 -0
  94. package/dist/chunk-4CSS7WVI.js +143 -0
  95. package/dist/chunk-4CUY7AFY.js +247 -0
  96. package/dist/chunk-4HN6DF7V.js +1027 -0
  97. package/dist/chunk-4HXKHDNH.js +1064 -0
  98. package/dist/chunk-4KKI477Q.js +44 -0
  99. package/dist/chunk-4NA7FSTV.js +595 -0
  100. package/dist/chunk-4NXPXE62.js +84 -0
  101. package/dist/chunk-4SALLK63.js +9831 -0
  102. package/dist/chunk-4SHKPCGK.js +110 -0
  103. package/dist/chunk-4VJITV4P.js +445 -0
  104. package/dist/chunk-4W2NRXQL.js +1205 -0
  105. package/dist/chunk-4XICK3HN.js +784 -0
  106. package/dist/chunk-55EJVV3C.js +385 -0
  107. package/dist/chunk-5DLKYTQX.js +4003 -0
  108. package/dist/chunk-5EERLVZB.js +139 -0
  109. package/dist/chunk-5HDP7XZG.js +91 -0
  110. package/dist/chunk-5LAMRH4X.js +969 -0
  111. package/dist/chunk-5REDMNLZ.js +310 -0
  112. package/dist/chunk-5UCJARII.js +1984 -0
  113. package/dist/chunk-5WCQRDRB.js +588 -0
  114. package/dist/chunk-5WRLK5KW.js +700 -0
  115. package/dist/chunk-66AGFTBQ.js +131 -0
  116. package/dist/chunk-66CIO2SV.js +48 -0
  117. package/dist/chunk-6BM72ZMG.js +31 -0
  118. package/dist/chunk-6BTFXYRO.js +276 -0
  119. package/dist/chunk-6EDAJH2I.js +68 -0
  120. package/dist/chunk-6EQKFDBH.js +457 -0
  121. package/dist/chunk-6KMJKHIQ.js +2193 -0
  122. package/dist/chunk-6MFRHTRI.js +115 -0
  123. package/dist/chunk-6QMUKUHH.js +632 -0
  124. package/dist/chunk-6TZJRKNW.js +321 -0
  125. package/dist/chunk-6V7HGQFZ.js +20 -0
  126. package/dist/chunk-6Y5TWI7H.js +146 -0
  127. package/dist/chunk-6Y5U7UFY.js +91 -0
  128. package/dist/chunk-6ZLAK3XG.js +14 -0
  129. package/dist/chunk-72XCRQED.js +34 -0
  130. package/dist/chunk-72YTZMAM.js +589 -0
  131. package/dist/chunk-73NCTWKL.js +188 -0
  132. package/dist/chunk-77I6G4CO.js +1 -0
  133. package/dist/chunk-7D7QT3BE.js +688 -0
  134. package/dist/chunk-7DNSNKJV.js +78 -0
  135. package/dist/chunk-7FMJVYBS.js +307 -0
  136. package/dist/chunk-7GDRQBQC.js +419 -0
  137. package/dist/chunk-7IL4A2PP.js +948 -0
  138. package/dist/chunk-7NPSXSHO.js +975 -0
  139. package/dist/chunk-7PS6INZP.js +302 -0
  140. package/dist/chunk-7QCZSLBH.js +1 -0
  141. package/dist/chunk-7R2WLDOS.js +62 -0
  142. package/dist/chunk-7XV3QXLT.js +878 -0
  143. package/dist/chunk-A2WKSVX7.js +43 -0
  144. package/dist/chunk-A3YGID55.js +133 -0
  145. package/dist/chunk-A5MRWHMI.js +1604 -0
  146. package/dist/chunk-A722DEVA.js +14 -0
  147. package/dist/chunk-AG2Z2SUZ.js +554 -0
  148. package/dist/chunk-AHWAZ2MU.js +137 -0
  149. package/dist/chunk-AIAQ3HS3.js +119 -0
  150. package/dist/chunk-ALAB3PBR.js +2206 -0
  151. package/dist/chunk-APPNGGN7.js +365 -0
  152. package/dist/chunk-APV6MK5E.js +137 -0
  153. package/dist/chunk-AQNPGRWS.js +395 -0
  154. package/dist/chunk-ASEP3M2W.js +968 -0
  155. package/dist/chunk-AT4TNPWW.js +2931 -0
  156. package/dist/chunk-ATVKCSGT.js +250 -0
  157. package/dist/chunk-AX6GWE7V.js +47 -0
  158. package/dist/chunk-AZQILSNQ.js +1376 -0
  159. package/dist/chunk-B76KHLX6.js +13 -0
  160. package/dist/chunk-BAV2HJXS.js +194 -0
  161. package/dist/chunk-BBHRN366.js +89 -0
  162. package/dist/chunk-BCZAENOH.js +448 -0
  163. package/dist/chunk-BIGSACCY.js +19527 -0
  164. package/dist/chunk-BPYMCIVD.js +9243 -0
  165. package/dist/chunk-BSE4R6XD.js +322 -0
  166. package/dist/chunk-BVPWRDCO.js +2321 -0
  167. package/dist/chunk-BXI4NXL3.js +507 -0
  168. package/dist/chunk-C3L6YQ7P.js +147 -0
  169. package/dist/chunk-C57KJOUQ.js +121 -0
  170. package/dist/chunk-CCV7BPSY.js +118 -0
  171. package/dist/chunk-CD7ISXA4.js +826 -0
  172. package/dist/chunk-CE5OZBYY.js +21 -0
  173. package/dist/chunk-CFBIG37O.js +154 -0
  174. package/dist/chunk-CHQV73H5.js +408 -0
  175. package/dist/chunk-CJC6GZ46.js +457 -0
  176. package/dist/chunk-CJHRFSNY.js +924 -0
  177. package/dist/chunk-CKP2Q3TP.js +1905 -0
  178. package/dist/chunk-CLKSETWE.js +10 -0
  179. package/dist/chunk-CQM3A35X.js +844 -0
  180. package/dist/chunk-CSLAS5GW.js +4007 -0
  181. package/dist/chunk-CTLUBNCW.js +622 -0
  182. package/dist/chunk-CVMVZWG4.js +3544 -0
  183. package/dist/chunk-CYB6QDCT.js +263 -0
  184. package/dist/chunk-D5EP5D2W.js +26 -0
  185. package/dist/chunk-DC4ZYMXJ.js +115 -0
  186. package/dist/chunk-DCAVAABI.js +348 -0
  187. package/dist/chunk-DCYF7EKG.js +26 -0
  188. package/dist/chunk-DF5SLDE4.js +966 -0
  189. package/dist/chunk-DN7UMLF7.js +5678 -0
  190. package/dist/chunk-DSFM56OA.js +1203 -0
  191. package/dist/chunk-DTY4APYV.js +218 -0
  192. package/dist/chunk-E3NTPHEO.js +194 -0
  193. package/dist/chunk-E74LUIID.js +302 -0
  194. package/dist/chunk-EJ42BNGY.js +2904 -0
  195. package/dist/chunk-EJ4ZAWLV.js +305 -0
  196. package/dist/chunk-EJGCZGUF.js +1483 -0
  197. package/dist/chunk-EK2U3YEG.js +486 -0
  198. package/dist/chunk-ELMFYNV7.js +109 -0
  199. package/dist/chunk-ENRGKNR5.js +25 -0
  200. package/dist/chunk-EQGIDAUF.js +62 -0
  201. package/dist/chunk-EX3OM35G.js +20414 -0
  202. package/dist/chunk-F5JO7HAS.js +94 -0
  203. package/dist/chunk-F7ER6ANO.js +174 -0
  204. package/dist/chunk-FATUVIIN.js +374 -0
  205. package/dist/chunk-FC23CTXV.js +322 -0
  206. package/dist/chunk-FCNAS3W2.js +1033 -0
  207. package/dist/chunk-FD4ERYEG.js +22 -0
  208. package/dist/chunk-FDVZLG6Z.js +3104 -0
  209. package/dist/chunk-FEPIFY7D.js +511 -0
  210. package/dist/chunk-FEQ4HXL7.js +412 -0
  211. package/dist/chunk-FFH5HHJU.js +5351 -0
  212. package/dist/chunk-FH7WOJAE.js +79 -0
  213. package/dist/chunk-FKAUPHMR.js +96 -0
  214. package/dist/chunk-FRG57FPM.js +240 -0
  215. package/dist/chunk-FUVP64ER.js +31 -0
  216. package/dist/chunk-G2PTLLEL.js +284 -0
  217. package/dist/chunk-G35UYQ6Z.js +69 -0
  218. package/dist/chunk-G36W2T2S.js +1143 -0
  219. package/dist/chunk-G4THLFV3.js +148 -0
  220. package/dist/chunk-GAFJEYLK.js +29 -0
  221. package/dist/chunk-GCCAPO3S.js +118 -0
  222. package/dist/chunk-GG6KJYW6.js +85 -0
  223. package/dist/chunk-GHHFDU2U.js +55 -0
  224. package/dist/chunk-GHTZSQB7.js +57 -0
  225. package/dist/chunk-GJTWJNLV.js +1374 -0
  226. package/dist/chunk-GKN3HMN4.js +2809 -0
  227. package/dist/chunk-GNH3QGTL.js +1342 -0
  228. package/dist/chunk-GOAQ2I7Y.js +7000 -0
  229. package/dist/chunk-GSGD5E4C.js +30 -0
  230. package/dist/chunk-GXWAJQOJ.js +5011 -0
  231. package/dist/chunk-H2AYQIHW.js +224 -0
  232. package/dist/chunk-H6G7QRMQ.js +35 -0
  233. package/dist/chunk-H7JAGHZT.js +59 -0
  234. package/dist/chunk-HAC6EHZZ.js +79 -0
  235. package/dist/chunk-HE2KH6EQ.js +161 -0
  236. package/dist/chunk-HIHENQDX.js +66 -0
  237. package/dist/chunk-HIO33P3G.js +19 -0
  238. package/dist/chunk-HK4AQZSR.js +438 -0
  239. package/dist/chunk-HMVQIPH3.js +547 -0
  240. package/dist/chunk-HOYBYAOA.js +257 -0
  241. package/dist/chunk-HQLGXODD.js +123 -0
  242. package/dist/chunk-HQXYYUNY.js +1231 -0
  243. package/dist/chunk-HY3ESWCA.js +708 -0
  244. package/dist/chunk-I46EG2XQ.js +65 -0
  245. package/dist/chunk-I4NPDSCB.js +279 -0
  246. package/dist/chunk-I5WRT7ZR.js +514 -0
  247. package/dist/chunk-I6BL3PDH.js +1024 -0
  248. package/dist/chunk-IATQ7NBI.js +679 -0
  249. package/dist/chunk-IC7I6YIJ.js +301 -0
  250. package/dist/chunk-IDCSOZVN.js +78 -0
  251. package/dist/chunk-IEXU4RR6.js +5742 -0
  252. package/dist/chunk-IFCBYECK.js +112 -0
  253. package/dist/chunk-IFZCPEY2.js +66 -0
  254. package/dist/chunk-IKFP2KUR.js +48 -0
  255. package/dist/chunk-IP7BYVUV.js +338 -0
  256. package/dist/chunk-IRJ2I6KH.js +166 -0
  257. package/dist/chunk-IUXNGKA6.js +152 -0
  258. package/dist/chunk-IZYIQQ7X.js +53 -0
  259. package/dist/chunk-IZZK3H6I.js +2175 -0
  260. package/dist/chunk-J3J4P7RW.js +353 -0
  261. package/dist/chunk-J62KPGII.js +464 -0
  262. package/dist/chunk-J6P3FWWW.js +130 -0
  263. package/dist/chunk-JD6SIZED.js +712 -0
  264. package/dist/chunk-JEV6UI7H.js +537 -0
  265. package/dist/chunk-JKBHJQMT.js +434 -0
  266. package/dist/chunk-JLS65NUQ.js +14 -0
  267. package/dist/chunk-JOSYEJKY.js +141 -0
  268. package/dist/chunk-JPKSXKNB.js +94 -0
  269. package/dist/chunk-JQD5VYKR.js +483 -0
  270. package/dist/chunk-JSOWEFEQ.js +351 -0
  271. package/dist/chunk-JSWMRQYG.js +28 -0
  272. package/dist/chunk-K4XK7SGB.js +6783 -0
  273. package/dist/chunk-K54Y7MLK.js +160 -0
  274. package/dist/chunk-KAT4RXUT.js +521 -0
  275. package/dist/chunk-KDMKKIRK.js +103 -0
  276. package/dist/chunk-KM3F7SYE.js +702 -0
  277. package/dist/chunk-KNDYMVWN.js +102 -0
  278. package/dist/chunk-KNT72VR6.js +132 -0
  279. package/dist/chunk-KQEBSK3T.js +274 -0
  280. package/dist/chunk-KT6VHSPF.js +84 -0
  281. package/dist/chunk-KTMW65UX.js +14 -0
  282. package/dist/chunk-L4427KOE.js +26 -0
  283. package/dist/chunk-L6OM4A22.js +189 -0
  284. package/dist/chunk-L7E6XCRA.js +1042 -0
  285. package/dist/chunk-L7JZLXQL.js +173 -0
  286. package/dist/chunk-LAMKBTXX.js +40 -0
  287. package/dist/chunk-LDCF2MKN.js +132 -0
  288. package/dist/chunk-LEIIWPWQ.js +78 -0
  289. package/dist/chunk-LFTQVYBB.js +31 -0
  290. package/dist/chunk-LGHII5ET.js +23 -0
  291. package/dist/chunk-LH34OGSB.js +265 -0
  292. package/dist/chunk-LO3X5NLS.js +326 -0
  293. package/dist/chunk-LPITVM7M.js +339 -0
  294. package/dist/chunk-LR5IJIGV.js +810 -0
  295. package/dist/chunk-LUVKFFWR.js +315 -0
  296. package/dist/chunk-LWCBNGH6.js +35 -0
  297. package/dist/chunk-LWTN3WRV.js +260 -0
  298. package/dist/chunk-LZBBXYWF.js +1004 -0
  299. package/dist/chunk-M34PS4NE.js +2213 -0
  300. package/dist/chunk-M3HQYKQX.js +308 -0
  301. package/dist/chunk-MCPQNJMK.js +482 -0
  302. package/dist/chunk-MF5HP6XV.js +221 -0
  303. package/dist/chunk-MFADRRTR.js +112 -0
  304. package/dist/chunk-MN6PL4AN.js +120 -0
  305. package/dist/chunk-MQ4WA34C.js +206 -0
  306. package/dist/chunk-MTVZITQ2.js +185 -0
  307. package/dist/chunk-MWHF5V7U.js +223 -0
  308. package/dist/chunk-MWHLBPNU.js +211 -0
  309. package/dist/chunk-MWK5UZQ3.js +1068 -0
  310. package/dist/chunk-MYLH2S4G.js +64 -0
  311. package/dist/chunk-MZ5WYKNA.js +28 -0
  312. package/dist/chunk-N5DX4JAK.js +12 -0
  313. package/dist/chunk-NEDCMN7E.js +415 -0
  314. package/dist/chunk-NEQUQHOX.js +223 -0
  315. package/dist/chunk-NGK6PEOG.js +25 -0
  316. package/dist/chunk-NM6PMYY4.js +768 -0
  317. package/dist/chunk-NOZGR2QO.js +2373 -0
  318. package/dist/chunk-NP2V3L7K.js +226 -0
  319. package/dist/chunk-NPZJMUZ4.js +194 -0
  320. package/dist/chunk-NRLY536M.js +260 -0
  321. package/dist/chunk-NS33V3IM.js +51 -0
  322. package/dist/chunk-NWOYOA6H.js +378 -0
  323. package/dist/chunk-NWRUSEXG.js +322 -0
  324. package/dist/chunk-O6V4PNLO.js +63 -0
  325. package/dist/chunk-OGMSYL6J.js +227 -0
  326. package/dist/chunk-OIS7J26S.js +319 -0
  327. package/dist/chunk-OKBTRSZI.js +205 -0
  328. package/dist/chunk-OMX5VL43.js +79 -0
  329. package/dist/chunk-ON3G73BU.js +264 -0
  330. package/dist/chunk-OPYFYTWQ.js +220 -0
  331. package/dist/chunk-OQ6K46CK.js +1734 -0
  332. package/dist/chunk-OSDYVKHW.js +2440 -0
  333. package/dist/chunk-OUM5S64R.js +3429 -0
  334. package/dist/chunk-OWB7JXUS.js +751 -0
  335. package/dist/chunk-OYZYO7TV.js +47 -0
  336. package/dist/chunk-P47VN5F4.js +282 -0
  337. package/dist/chunk-P6VQROCO.js +594 -0
  338. package/dist/chunk-P7CQGPLS.js +30 -0
  339. package/dist/chunk-PA6BCSOX.js +2872 -0
  340. package/dist/chunk-PGSPX4SU.js +15 -0
  341. package/dist/chunk-PIKLF7BM.js +432 -0
  342. package/dist/chunk-PJWJ3SAV.js +22 -0
  343. package/dist/chunk-PKIFMV72.js +100 -0
  344. package/dist/chunk-PTH5E5XO.js +195 -0
  345. package/dist/chunk-PYITM4N2.js +79 -0
  346. package/dist/chunk-PZ5AY32C.js +10 -0
  347. package/dist/chunk-Q3RO7N35.js +45 -0
  348. package/dist/chunk-Q3WIC6GQ.js +2670 -0
  349. package/dist/chunk-QGJDMEOV.js +34 -0
  350. package/dist/chunk-QJYIHVXT.js +100 -0
  351. package/dist/chunk-QNOB37UH.js +58 -0
  352. package/dist/chunk-QOCOVLUH.js +462 -0
  353. package/dist/chunk-QTCJ5CC5.js +172 -0
  354. package/dist/chunk-QU6JQJMH.js +3063 -0
  355. package/dist/chunk-QVFV5IP2.js +232 -0
  356. package/dist/chunk-QVZMFDYG.js +29 -0
  357. package/dist/chunk-R2ZYWNW3.js +1581 -0
  358. package/dist/chunk-R4UWBC35.js +200 -0
  359. package/dist/chunk-R6W23LKN.js +254 -0
  360. package/dist/chunk-RAK5HOIJ.js +459 -0
  361. package/dist/chunk-RDFRCT64.js +168 -0
  362. package/dist/chunk-RE5VZDFQ.js +58 -0
  363. package/dist/chunk-RGROYC2G.js +638 -0
  364. package/dist/chunk-RGWHUI5E.js +68 -0
  365. package/dist/chunk-RHVG6UNL.js +205 -0
  366. package/dist/chunk-RI4EX2QE.js +18 -0
  367. package/dist/chunk-RIKFAWZF.js +71 -0
  368. package/dist/chunk-RJAAKDRX.js +17 -0
  369. package/dist/chunk-RSXSD4MH.js +1016 -0
  370. package/dist/chunk-RW7RVSDV.js +79 -0
  371. package/dist/chunk-RWREC3KJ.js +517 -0
  372. package/dist/chunk-RZY7RKM5.js +500 -0
  373. package/dist/chunk-S2MNWFAG.js +52 -0
  374. package/dist/chunk-S2VQCZO4.js +22 -0
  375. package/dist/chunk-S54MKU6V.js +117 -0
  376. package/dist/chunk-S77XPALC.js +239 -0
  377. package/dist/chunk-SCW4ZF6R.js +150 -0
  378. package/dist/chunk-SKHGYQ7W.js +405 -0
  379. package/dist/chunk-SNLBO4BF.js +247 -0
  380. package/dist/chunk-SP3LFU6B.js +60 -0
  381. package/dist/chunk-SQZRPY23.js +5181 -0
  382. package/dist/chunk-SSB5UQHA.js +4128 -0
  383. package/dist/chunk-STJOHHSF.js +605 -0
  384. package/dist/chunk-STV6LYYE.js +45 -0
  385. package/dist/chunk-SUN4OFTW.js +740 -0
  386. package/dist/chunk-SURZ2WFE.js +326 -0
  387. package/dist/chunk-SUZ7UYZH.js +1972 -0
  388. package/dist/chunk-SZ7DL357.js +1047 -0
  389. package/dist/chunk-T2SZELJL.js +624 -0
  390. package/dist/chunk-T6VPI2XP.js +10338 -0
  391. package/dist/chunk-TAJPCXSB.js +13 -0
  392. package/dist/chunk-TAOOYK3P.js +358 -0
  393. package/dist/chunk-TDSEX5CF.js +24 -0
  394. package/dist/chunk-TFTGP7Z7.js +174 -0
  395. package/dist/chunk-TGON4N4O.js +197 -0
  396. package/dist/chunk-TIBZPAD2.js +9924 -0
  397. package/dist/chunk-TK644IOG.js +1813 -0
  398. package/dist/chunk-TRSVUPCX.js +25 -0
  399. package/dist/chunk-TSPQONRT.js +4533 -0
  400. package/dist/chunk-TSXGRLPR.js +107 -0
  401. package/dist/chunk-TWYLVAS2.js +152 -0
  402. package/dist/chunk-U2S3YEX3.js +224 -0
  403. package/dist/chunk-U32HWI76.js +437 -0
  404. package/dist/chunk-U45RTRGY.js +818 -0
  405. package/dist/chunk-U62VCQGR.js +49 -0
  406. package/dist/chunk-UDMS5AD3.js +307 -0
  407. package/dist/chunk-UGX7GI37.js +94 -0
  408. package/dist/chunk-UH3JJSHK.js +1 -0
  409. package/dist/chunk-UHRBTZYY.js +208 -0
  410. package/dist/chunk-UHT2KRG5.js +193 -0
  411. package/dist/chunk-UI2F6DJ5.js +118 -0
  412. package/dist/chunk-UKMAFG7A.js +189 -0
  413. package/dist/chunk-UUH2RVKS.js +585 -0
  414. package/dist/chunk-UVBBFDFQ.js +270 -0
  415. package/dist/chunk-UXZF3B7T.js +75 -0
  416. package/dist/chunk-V6YLL5WA.js +3746 -0
  417. package/dist/chunk-V72RMBM4.js +48 -0
  418. package/dist/chunk-VBNCKCCI.js +16 -0
  419. package/dist/chunk-VCAUV5XQ.js +3679 -0
  420. package/dist/chunk-VDSH7O4Y.js +152 -0
  421. package/dist/chunk-VNSYKC25.js +24 -0
  422. package/dist/chunk-VTLNJQ44.js +133 -0
  423. package/dist/chunk-VV6HOXRC.js +302 -0
  424. package/dist/chunk-VVGEPBPS.js +218 -0
  425. package/dist/chunk-VXF4Q3FW.js +20 -0
  426. package/dist/chunk-W3ZGW3C5.js +331 -0
  427. package/dist/chunk-W4OMESPG.js +271 -0
  428. package/dist/chunk-WDUORIHF.js +877 -0
  429. package/dist/chunk-WDVTY4U6.js +148 -0
  430. package/dist/chunk-WGXYDLMX.js +4386 -0
  431. package/dist/chunk-WMPU2UOV.js +82 -0
  432. package/dist/chunk-WOEVVPDP.js +1125 -0
  433. package/dist/chunk-WTLMSPBQ.js +256 -0
  434. package/dist/chunk-X43NMU4Z.js +1124 -0
  435. package/dist/chunk-X5NTI5U5.js +368 -0
  436. package/dist/chunk-X6UIEADS.js +949 -0
  437. package/dist/chunk-XAONGNST.js +57 -0
  438. package/dist/chunk-XB5YLCLB.js +13 -0
  439. package/dist/chunk-XGYF2QMZ.js +351 -0
  440. package/dist/chunk-XHEKQENB.js +255 -0
  441. package/dist/chunk-XPHKYHO4.js +878 -0
  442. package/dist/chunk-XQD2B6BB.js +507 -0
  443. package/dist/chunk-XT2ZQVTC.js +558 -0
  444. package/dist/chunk-XUSRFFA7.js +1859 -0
  445. package/dist/chunk-XUXVDPSZ.js +50 -0
  446. package/dist/chunk-XV7NZL4B.js +57 -0
  447. package/dist/chunk-XXCGJGSQ.js +121 -0
  448. package/dist/chunk-XYGDZCB5.js +659 -0
  449. package/dist/chunk-XZAMZUX5.js +992 -0
  450. package/dist/chunk-XZE4XARH.js +563 -0
  451. package/dist/chunk-Y34DUC4A.js +1356 -0
  452. package/dist/chunk-Y3J4JMTU.js +61 -0
  453. package/dist/chunk-Y4RC2YFX.js +1270 -0
  454. package/dist/chunk-Y55LZN5U.js +52 -0
  455. package/dist/chunk-Y5677NDO.js +183 -0
  456. package/dist/chunk-YESZJFK6.js +220 -0
  457. package/dist/chunk-YGXKOBQQ.js +292 -0
  458. package/dist/chunk-YMX76IOS.js +31 -0
  459. package/dist/chunk-YOTXESEH.js +257 -0
  460. package/dist/chunk-YQAAKTVH.js +712 -0
  461. package/dist/chunk-YVORHQ2S.js +579 -0
  462. package/dist/chunk-YWNAHW24.js +1552 -0
  463. package/dist/chunk-Z476RATD.js +1689 -0
  464. package/dist/chunk-ZDTGECTN.js +235 -0
  465. package/dist/chunk-ZDTMICNY.js +316 -0
  466. package/dist/chunk-ZIPWI2LY.js +151 -0
  467. package/dist/chunk-ZIVYXF7A.js +2344 -0
  468. package/dist/chunk-ZX65UI5W.js +78 -0
  469. package/dist/chunk-ZYG7GGKO.js +218 -0
  470. package/dist/chunk-ZZZUL4OF.js +38 -0
  471. package/dist/cli-utils-HUOTBRM3.js +40 -0
  472. package/dist/cli-validation-WLXWLUJL.js +111 -0
  473. package/dist/commit-utils-3QV2P6RA.js +202 -0
  474. package/dist/compete-config-resolver-SNH3TT2Q.js +76 -0
  475. package/dist/compete-request-XWNPOARL.js +364 -0
  476. package/dist/compete-results-PAP67LDR.js +208 -0
  477. package/dist/competition-outcome-tracker-GOZXNAQU.js +38 -0
  478. package/dist/config-HWHUNA72.js +166 -0
  479. package/dist/config-audit-EL3GHXS7.js +360 -0
  480. package/dist/config-explain-TNILDEVJ.js +12 -0
  481. package/dist/config-loader-VPFPFO4B.js +38 -0
  482. package/dist/config-manager-L3VRNTSG.js +67 -0
  483. package/dist/config-validator-SIIQEOFQ.js +72 -0
  484. package/dist/cost-7CX37DU3.js +53 -0
  485. package/dist/coverage-orchestrator-MNKHD6YC.js +772 -0
  486. package/dist/coverage-scanner-YVD62MLH.js +12 -0
  487. package/dist/createCompetitionRunner-LJG6ZQSO.js +46 -0
  488. package/dist/data-migration-state-VJK64DLT.js +31 -0
  489. package/dist/db-migrator-XSEIOGWY.js +34 -0
  490. package/dist/discovery-JGYGDD25.js +25 -0
  491. package/dist/doctor-CGBCD7IQ.js +186 -0
  492. package/dist/domain-analyzer-DL6BDR2N.js +29 -0
  493. package/dist/ensure-initialized-4BY73HLE.js +52 -0
  494. package/dist/entry.js +940 -0
  495. package/dist/environment-IGVH5X53.js +81 -0
  496. package/dist/error-parser-core-PPZ36A4S.js +50 -0
  497. package/dist/escalation-ladder-NWY5BJ57.js +130 -0
  498. package/dist/evaluation-context-KMWDSDYD.js +35 -0
  499. package/dist/evidence-plan-resolver-YIVH76PU.js +85 -0
  500. package/dist/execution-data-writer-OHAQ7G5H.js +53 -0
  501. package/dist/execution-policy-applier-ZHD3DCF3.js +31 -0
  502. package/dist/execution-preflight-Z4Y64V3I.js +209 -0
  503. package/dist/execution-roles-KBH2MC3M.js +66 -0
  504. package/dist/exit-code-error-Z4SW2DVK.js +14 -0
  505. package/dist/external-temp-cleanup-N2RZH4QP.js +311 -0
  506. package/dist/factory-IYBMCZG7.js +149 -0
  507. package/dist/file-utils-XIVR2ZMA.js +47 -0
  508. package/dist/flywheel-autoloop-executor-R3KD2G4D.js +249 -0
  509. package/dist/flywheel-competition-executor-XCFGVJSK.js +259 -0
  510. package/dist/flywheel-executor-LTSIZN2L.js +369 -0
  511. package/dist/flywheel-git-isolation-CZ5YVVZY.js +48 -0
  512. package/dist/flywheel-manifest-5UC4VBMA.js +108 -0
  513. package/dist/flywheel-model-defaults-7CVKP53V.js +27 -0
  514. package/dist/flywheel-preflight-6E33DJDK.js +104 -0
  515. package/dist/flywheel-resume-7HELH7QS.js +23 -0
  516. package/dist/flywheel-safety-7U7DPOAP.js +28 -0
  517. package/dist/flywheel-scope-decision-ZHKF6ZIN.js +11 -0
  518. package/dist/get-telemetry-logger-AZ46EPRP.js +73 -0
  519. package/dist/git-worktree-IY6V6DUO.js +18 -0
  520. package/dist/github-pr-manager-4XUO2YTM.js +211 -0
  521. package/dist/guidance-profile-config-E7XJL2VP.js +117 -0
  522. package/dist/guidance-profile-renderer-QK2YMAAP.js +21 -0
  523. package/dist/index-query-4JEUKA44.js +31 -0
  524. package/dist/index.js +108644 -0
  525. package/dist/instructions-CM6THDV7.js +64 -0
  526. package/dist/invoke-provider-auth-V5TC5UDS.js +223 -0
  527. package/dist/judge-scoring.json +80 -0
  528. package/dist/judge-test.js +555 -0
  529. package/dist/lab-mode-OTWVHN63.js +39 -0
  530. package/dist/lab-utils-VA6VXNOV.js +23 -0
  531. package/dist/linux-host-class-UY4KVLFD.js +29 -0
  532. package/dist/llm-judge-executor-34YPIRJ7.js +133 -0
  533. package/dist/local-executor-LJJSCWZX.js +223 -0
  534. package/dist/logger-6PRYM56M.js +72 -0
  535. package/dist/loop-spec-XTLQAVZ7.js +191 -0
  536. package/dist/manager-2HJG5CLT.js +25 -0
  537. package/dist/matrix-prompt-builder-LHDTJ4TY.js +497 -0
  538. package/dist/matrix-result-parser-7W35EUOV.js +15 -0
  539. package/dist/metadata-HQ43NDEK.js +22 -0
  540. package/dist/model-invocations-db-QBO4Y7WZ.js +38 -0
  541. package/dist/monitor-MCI3F4PX.js +72 -0
  542. package/dist/next-HQKDXIIR.js +90 -0
  543. package/dist/next-JC3V2UCS.js +69 -0
  544. package/dist/optimization-config-resolver-QPSFLCJU.js +75 -0
  545. package/dist/package-3YCWIQQ5.js +10 -0
  546. package/dist/parallel-orchestrator-NL7YJJU2.js +297 -0
  547. package/dist/parallel-worker.js +279 -0
  548. package/dist/parse-git-status-PIAF3OTP.js +10 -0
  549. package/dist/path-security-ETTH6TZL.js +39 -0
  550. package/dist/pattern-bank-UNJR5ADV.js +15 -0
  551. package/dist/plan-backlog-list-fast-DZK24LSZ.js +270 -0
  552. package/dist/plan-backlog-show-fast-63GBBH6Q.js +406 -0
  553. package/dist/plan-sprint-list-fast-TJ6ZUF5E.js +162 -0
  554. package/dist/plan-sprint-status-fast-YWE5X3NG.js +208 -0
  555. package/dist/plan-task-status-fast-K22BTTBW.js +349 -0
  556. package/dist/plan-to-flywheel-VFGCPINA.js +456 -0
  557. package/dist/planning-backlog-Y6TIJYWU.js +319 -0
  558. package/dist/poetic-root-V5DNXEAE.js +17 -0
  559. package/dist/preflight-OPANWMME.js +12 -0
  560. package/dist/process-registry-PDZJPTAS.js +27 -0
  561. package/dist/process-scanner-C22SYXYD.js +22 -0
  562. package/dist/processes-KMQUD7HY.js +29 -0
  563. package/dist/processes-json-fast-IBDXZ6WW.js +135 -0
  564. package/dist/profile-2XP3FWH2.js +149 -0
  565. package/dist/prompts-EPAAAMMF.js +168 -0
  566. package/dist/protected-branches-RNTEX7ET.js +57 -0
  567. package/dist/provider-aware-resource-manager-QBTZJMNP.js +18 -0
  568. package/dist/provider-matrix-KWTYA5QV.js +154 -0
  569. package/dist/provider-matrix-renderer-MZDWKKID.js +139 -0
  570. package/dist/provider-output-forwarding-DERID3TP.js +30 -0
  571. package/dist/provider-registry-J5NRBJKI.js +128 -0
  572. package/dist/provider-temp-cleanup-KYGLF6YU.js +14 -0
  573. package/dist/prune-engine-Q6E2DXBN.js +451 -0
  574. package/dist/quality-gate-33SHK43X.js +70 -0
  575. package/dist/quickstart-E32SODTA.js +62 -0
  576. package/dist/readiness-REWW7OSV.js +96 -0
  577. package/dist/registry-N6L36RE2.js +153 -0
  578. package/dist/repair-helpers-TTV5FEF4.js +117 -0
  579. package/dist/repo-root-2IGD4H7X.js +22 -0
  580. package/dist/resolution-engine-LXQYDSKS.js +127 -0
  581. package/dist/resolve-provider-cli-O2P6XZBZ.js +35 -0
  582. package/dist/restore-telemetry-db-BQL6DTQF.js +360 -0
  583. package/dist/result-streamer-WEHW476R.js +19 -0
  584. package/dist/routing-events-DHPUZDDF.js +27 -0
  585. package/dist/routing-history-store-UWCEXAP3.js +46 -0
  586. package/dist/routing-planner-VGQU35QM.js +160 -0
  587. package/dist/run-poetic-tui-ZZXFDOQ4.js +13517 -0
  588. package/dist/run-simulation.js +376 -0
  589. package/dist/runner-2YPKOJ6A.js +1092 -0
  590. package/dist/runner-HEJJ65AJ.js +1571 -0
  591. package/dist/safety-OCC4KJJR.js +64 -0
  592. package/dist/safety-stanza-BSVE6OJU.js +60 -0
  593. package/dist/sandbox-3AG2WJLM.js +94 -0
  594. package/dist/sandbox-5JOFBS75.js +81 -0
  595. package/dist/schema-extensions.sql +234 -0
  596. package/dist/security-2KI5XNDG.js +17 -0
  597. package/dist/setup-bb-plugin-QAQWZCV5.js +738 -0
  598. package/dist/setup-claude-code-P7BTTSPO.js +317 -0
  599. package/dist/setup-temp-cleanup-GASCWZ2I.js +20 -0
  600. package/dist/shared-utils-D6U6UREP.js +37 -0
  601. package/dist/simple-artifact-goal-OTXNGZY6.js +25 -0
  602. package/dist/sprint-QGXLN3SO.js +338 -0
  603. package/dist/sprint-bridge-FNKQCJGL.js +68 -0
  604. package/dist/sprint-execution-service-4ELKNJDS.js +311 -0
  605. package/dist/sprint-manager-7TNCXCIX.js +91 -0
  606. package/dist/sqlite-wrapper-UDWCTNLJ.js +17 -0
  607. package/dist/stale-cleanup-orchestrator-H5XKGZP2.js +62 -0
  608. package/dist/storage-access-F6ALDN4S.js +22 -0
  609. package/dist/synthesis-TGQUVAW3.js +185 -0
  610. package/dist/task-classifier-DZIRBSS2.js +494 -0
  611. package/dist/task-list-fast-PJ2EXVZE.js +147 -0
  612. package/dist/task-manager-5742GMJK.js +93 -0
  613. package/dist/task-splitter-6MBXSWF6.js +79 -0
  614. package/dist/task-type-detector-OLVOMXZO.js +21 -0
  615. package/dist/task-type-resolver-4HG6TXFV.js +42 -0
  616. package/dist/telemetry-JX7EMNOZ.js +131 -0
  617. package/dist/telemetry-health-tracker-DMSSGBZ2.js +11 -0
  618. package/dist/telemetry-path-resolver-7ICSG276.js +28 -0
  619. package/dist/telemetry-reliability-2MLJ4J6B.js +125 -0
  620. package/dist/token-estimator-PDU345YE.js +37 -0
  621. package/dist/transports-3UEO6C5Y.js +255 -0
  622. package/dist/unified-cost-tracker-F3W5NMPG.js +35 -0
  623. package/dist/unified-state-cleanup-LJPF2BOW.js +276 -0
  624. package/dist/universal-cost-calculator-BAJV35GA.js +42 -0
  625. package/dist/user-agents-GHUGCSKN.js +22 -0
  626. package/dist/variant-delivery-state-XCOYVCM4.js +33 -0
  627. package/dist/variant-state-cleanup-QIEKRULB.js +280 -0
  628. package/dist/variant-success-PJXWE3ZV.js +12 -0
  629. package/dist/variant-worker-HPTUA37Z.js +4196 -0
  630. package/dist/variant-worker.js +24 -0
  631. package/dist/variants-2HDYZOCG.js +233 -0
  632. package/dist/verification-toolchains-VVKT3GBF.js +28 -0
  633. package/dist/verify-commands-5F6CJV4B.js +37 -0
  634. package/dist/warning-EGQGUUIO.js +12 -0
  635. package/dist/work-edge-RWEDWJZF.js +49 -0
  636. package/dist/work-item-writer-WHAVZXAY.js +19 -0
  637. package/dist/worker-AGWHD4D2.js +1435 -0
  638. package/dist/worker.js +19 -0
  639. package/dist/worktree-metrics-3DFUYVYE.js +26 -0
  640. package/dist/writeback-VZKHYHSN.js +44 -0
  641. package/docs/CLI_REFERENCE.md +7040 -0
  642. package/docs/PROVIDER_SETUP.md +1570 -0
  643. package/docs/README.md +96 -0
  644. package/docs/TROUBLESHOOTING.md +2232 -0
  645. package/docs/getting-started/QUICK_START.md +294 -0
  646. package/docs/getting-started/README.md +188 -0
  647. package/docs/getting-started/SETUP.md +52 -0
  648. package/docs/reference/AGENT_CONTEXT.md +38 -0
  649. package/docs/reference/PROVIDER_RELEASE_TIERS.md +34 -0
  650. package/docs/reference/README.md +381 -0
  651. package/docs/reference/SECURITY.md +262 -0
  652. package/integrations/bb-plugin-poetic/README.md +362 -0
  653. package/integrations/bb-plugin-poetic/app.css +341 -0
  654. package/integrations/bb-plugin-poetic/app.tsx +5059 -0
  655. package/integrations/bb-plugin-poetic/package.json +45 -0
  656. package/integrations/bb-plugin-poetic/server.ts +444 -0
  657. package/integrations/bb-plugin-poetic/src/adapter.ts +3312 -0
  658. package/integrations/bb-plugin-poetic/src/backlog-authoring-model.ts +150 -0
  659. package/integrations/bb-plugin-poetic/src/backlog-authoring-schema.ts +355 -0
  660. package/integrations/bb-plugin-poetic/src/backlog-authoring-service.ts +419 -0
  661. package/integrations/bb-plugin-poetic/src/backlog-authoring-view.ts +1026 -0
  662. package/integrations/bb-plugin-poetic/src/competition-defaults-schema.ts +122 -0
  663. package/integrations/bb-plugin-poetic/src/competition-defaults-service.ts +105 -0
  664. package/integrations/bb-plugin-poetic/src/competition-defaults-view.ts +138 -0
  665. package/integrations/bb-plugin-poetic/src/contract.ts +615 -0
  666. package/integrations/bb-plugin-poetic/src/finalize-model.ts +205 -0
  667. package/integrations/bb-plugin-poetic/src/finalize-schema.ts +158 -0
  668. package/integrations/bb-plugin-poetic/src/finalize-service.ts +382 -0
  669. package/integrations/bb-plugin-poetic/src/finalize-view.ts +159 -0
  670. package/integrations/bb-plugin-poetic/src/judge-operations-readback.ts +303 -0
  671. package/integrations/bb-plugin-poetic/src/judge-operations-schema.ts +33 -0
  672. package/integrations/bb-plugin-poetic/src/judge-operations-view.ts +459 -0
  673. package/integrations/bb-plugin-poetic/src/model.ts +1302 -0
  674. package/integrations/bb-plugin-poetic/src/monitor-service.ts +233 -0
  675. package/integrations/bb-plugin-poetic/src/panel-read-ux.ts +97 -0
  676. package/integrations/bb-plugin-poetic/src/patch-preview-schema.ts +166 -0
  677. package/integrations/bb-plugin-poetic/src/patch-preview-service.ts +480 -0
  678. package/integrations/bb-plugin-poetic/src/patch-preview-view.ts +109 -0
  679. package/integrations/bb-plugin-poetic/src/planning-readback.ts +204 -0
  680. package/integrations/bb-plugin-poetic/src/planning-service.ts +594 -0
  681. package/integrations/bb-plugin-poetic/src/planning-workspace-schema.ts +95 -0
  682. package/integrations/bb-plugin-poetic/src/planning-workspace.ts +323 -0
  683. package/integrations/bb-plugin-poetic/src/poll-handoff.ts +136 -0
  684. package/integrations/bb-plugin-poetic/src/project-target-server.ts +21 -0
  685. package/integrations/bb-plugin-poetic/src/project-target.ts +45 -0
  686. package/integrations/bb-plugin-poetic/src/reference-index.ts +192 -0
  687. package/integrations/bb-plugin-poetic/src/repository-schema.ts +30 -0
  688. package/integrations/bb-plugin-poetic/src/result-explorer-view.ts +597 -0
  689. package/integrations/bb-plugin-poetic/src/result-readback-model.ts +163 -0
  690. package/integrations/bb-plugin-poetic/src/result-readback-schema.ts +319 -0
  691. package/integrations/bb-plugin-poetic/src/result-readback-service.ts +333 -0
  692. package/integrations/bb-plugin-poetic/src/run-page-view.ts +177 -0
  693. package/integrations/bb-plugin-poetic/src/setup-config-schema.ts +291 -0
  694. package/integrations/bb-plugin-poetic/src/setup-config-service.ts +590 -0
  695. package/integrations/bb-plugin-poetic/src/setup-config-view.ts +413 -0
  696. package/integrations/bb-plugin-poetic/src/sprint-close-model.ts +150 -0
  697. package/integrations/bb-plugin-poetic/src/sprint-close-schema.ts +136 -0
  698. package/integrations/bb-plugin-poetic/src/sprint-close-service.ts +341 -0
  699. package/integrations/bb-plugin-poetic/src/sprint-close-view.ts +116 -0
  700. package/integrations/bb-plugin-poetic/src/sprint-composition-model.ts +714 -0
  701. package/integrations/bb-plugin-poetic/src/sprint-composition-readback.ts +231 -0
  702. package/integrations/bb-plugin-poetic/src/sprint-composition-schema.ts +601 -0
  703. package/integrations/bb-plugin-poetic/src/sprint-composition-service.ts +775 -0
  704. package/integrations/bb-plugin-poetic/src/sprint-composition-view.ts +1221 -0
  705. package/integrations/bb-plugin-poetic/src/task-authoring-model.ts +567 -0
  706. package/integrations/bb-plugin-poetic/src/task-authoring-schema.ts +635 -0
  707. package/integrations/bb-plugin-poetic/src/task-authoring-service.ts +842 -0
  708. package/integrations/bb-plugin-poetic/src/task-authoring-view.ts +1227 -0
  709. package/integrations/bb-plugin-poetic/src/task-detail-readback.ts +56 -0
  710. package/integrations/bb-plugin-poetic/src/task-detail-schema.ts +144 -0
  711. package/integrations/bb-plugin-poetic/src/task-navigation.ts +446 -0
  712. package/integrations/bb-plugin-poetic/src/workbench-route.ts +74 -0
  713. package/integrations/bb-plugin-poetic/tests/host-contract.test.ts +773 -0
  714. package/integrations/bb-plugin-poetic/tsconfig.json +18 -0
  715. package/integrations/bb-plugin-poetic/types/PROVENANCE.json +52 -0
  716. package/integrations/bb-plugin-poetic/types/bb-plugin-sdk-app.d.ts +1444 -0
  717. package/integrations/bb-plugin-poetic/types/bb-plugin-sdk.d.ts +13030 -0
  718. package/integrations/bb-plugin-poetic/vitest.host.config.ts +71 -0
  719. package/package.json +331 -0
  720. package/schemas/README.md +80 -0
  721. package/schemas/config-v1.schema.json +136 -0
  722. package/schemas/execution-config.schema.json +47 -0
  723. package/schemas/judge-scoring.schema.json +370 -0
  724. package/schemas/poetic.config.schema.json +2214 -0
  725. package/schemas/provider-config.schema.json +203 -0
  726. package/schemas/telemetry-config.schema.json +79 -0
  727. package/schemas/user-preferences.schema.json +141 -0
  728. package/scripts/assert-node-runtime.mjs +140 -0
  729. package/scripts/preflight-native.mjs +49 -0
  730. package/scripts/preinstall-node-check.mjs +78 -0
  731. package/scripts/setup-git-hooks.mjs +24 -0
  732. package/scripts/sync.sh +2722 -0
  733. package/scripts/write-node-launcher.sh +108 -0
  734. package/src/resources/gemini/slash-packs/default/plan.toml +15 -0
  735. package/src/resources/gemini/slash-packs/default/summary.toml +16 -0
  736. package/src/resources/gemini/slash-packs/default/tests.toml +16 -0
  737. package/templates/.poetic/README.md +37 -0
  738. package/templates/.poetic/agents/README.md +296 -0
  739. package/templates/.poetic/agents/api-documenter.md +147 -0
  740. package/templates/.poetic/agents/backend-architect.md +31 -0
  741. package/templates/.poetic/agents/code-reviewer.md +157 -0
  742. package/templates/.poetic/agents/data-scientist.md +179 -0
  743. package/templates/.poetic/agents/database-optimizer.md +145 -0
  744. package/templates/.poetic/agents/debugger.md +31 -0
  745. package/templates/.poetic/agents/deployment-engineer.md +164 -0
  746. package/templates/.poetic/agents/devops-troubleshooter.md +139 -0
  747. package/templates/.poetic/agents/frontend-developer.md +150 -0
  748. package/templates/.poetic/agents/javascript-pro.md +36 -0
  749. package/templates/.poetic/agents/performance-engineer.md +151 -0
  750. package/templates/.poetic/agents/python-pro.md +137 -0
  751. package/templates/.poetic/agents/test-automator.md +147 -0
  752. package/templates/.poetic/agents/typescript-pro.md +34 -0
  753. package/templates/.poetic/config/poetic.config.jsonc +69 -0
  754. package/templates/.poetic/config/project-context.template.json +6 -0
  755. package/templates/.poetic/config/task-type-aliases.presets/kanban.yaml +14 -0
  756. package/templates/.poetic/config/task-type-aliases.presets/scrum.yaml +17 -0
  757. package/templates/.poetic/config/task-type-aliases.presets/xp.yaml +12 -0
  758. package/templates/.poetic/config/task-type-aliases.yaml +28 -0
  759. package/templates/.poetic/gitignore.template +55 -0
  760. package/templates/.poetic/task-types/analysis.yaml +40 -0
  761. package/templates/.poetic/task-types/architecture.yaml +38 -0
  762. package/templates/.poetic/task-types/doc.yaml +35 -0
  763. package/templates/.poetic/task-types/feature.yaml +23 -0
  764. package/templates/.poetic/task-types/general.yaml +6 -0
  765. package/templates/.poetic/task-types/security.yaml +39 -0
  766. package/templates/AGENTS.template.md +99 -0
  767. package/templates/CLAUDE.template.md +1 -0
  768. package/templates/GEMINI.template.md +1 -0
  769. package/templates/builtin-workflows/code-review.yaml +73 -0
  770. package/templates/builtin-workflows/compete-streak.yaml +78 -0
  771. package/templates/builtin-workflows/hello-verify.yaml +10 -0
  772. package/templates/builtin-workflows/judge-regression.yaml +114 -0
  773. package/templates/builtin-workflows/skills/code-review/SKILL.md +60 -0
  774. package/templates/builtin-workflows/skills/hello-verify/SKILL.md +6 -0
  775. package/templates/guard-kit/GUARD_SETUP.md.template +255 -0
  776. package/templates/guard-kit/check.mjs.template +777 -0
  777. package/templates/guard-kit/config.json.template +6 -0
  778. package/templates/guard-kit/poetic-guard.yml.template +189 -0
  779. package/templates/profiles/README.md +56 -0
  780. package/templates/profiles/frontier-claude.json +27 -0
  781. package/templates/profiles/frontier-codex.json +26 -0
@@ -0,0 +1,4386 @@
1
+ import {
2
+ ProcessLifecycleManager,
3
+ parseCitationTrace,
4
+ serializeCitationTrace
5
+ } from "./chunk-PA6BCSOX.js";
6
+ import {
7
+ AutomaticPromptOptimizer
8
+ } from "./chunk-VCAUV5XQ.js";
9
+ import {
10
+ detectHostConcurrencyBudget
11
+ } from "./chunk-PYITM4N2.js";
12
+ import {
13
+ LocalExecutor,
14
+ WorkspaceAgentRunner
15
+ } from "./chunk-BIGSACCY.js";
16
+ import {
17
+ GitHubPRManager
18
+ } from "./chunk-5UCJARII.js";
19
+ import {
20
+ enqueueRemoteBranchCleanup,
21
+ isRemoteBranchMissingError,
22
+ isRetryableRemoteDeleteError,
23
+ resolveExpectedRemoteShaForQueuedBranch
24
+ } from "./chunk-BXI4NXL3.js";
25
+ import {
26
+ UnifiedCostTracker
27
+ } from "./chunk-FCNAS3W2.js";
28
+ import {
29
+ WORKER_EXIT_DRAIN_MS,
30
+ applyComplementaryPatchToWinnerWorktree,
31
+ buildSynthesisTelemetrySnapshot,
32
+ countCompletedCompetitionObservations,
33
+ createLocalVariantResourceManager,
34
+ didSynthesisArtifactSucceed,
35
+ resolveLocalWorktreeConcurrency,
36
+ resolveSynthesisOutcomeStatusForArtifact,
37
+ resolveSynthesisSelectedVariants,
38
+ sealVariantResultSnapshot,
39
+ toConcurrencyProviderId
40
+ } from "./chunk-BPYMCIVD.js";
41
+ import {
42
+ createEvaluationHandleFinalState,
43
+ finalizeEvaluationHandle,
44
+ initEvaluationHandle,
45
+ isDurableHandleCompletion,
46
+ updateEvaluationHandleWithResult
47
+ } from "./chunk-4HXKHDNH.js";
48
+ import {
49
+ sanitizeSynthesisArtifactForPersistence
50
+ } from "./chunk-GG6KJYW6.js";
51
+ import {
52
+ ProviderAwareResourceManager
53
+ } from "./chunk-L7E6XCRA.js";
54
+ import {
55
+ UniversalOutputValidator,
56
+ VariantOrchestrator
57
+ } from "./chunk-3A5PDH5L.js";
58
+ import {
59
+ ConfigManager
60
+ } from "./chunk-GJTWJNLV.js";
61
+ import {
62
+ recordProviderRateLimit
63
+ } from "./chunk-GHTZSQB7.js";
64
+ import {
65
+ UniversalCostCalculator
66
+ } from "./chunk-ASEP3M2W.js";
67
+ import {
68
+ getEvaluationQualityScore,
69
+ getEvaluationRankingScore,
70
+ getEvaluationRankingScoreOrZero
71
+ } from "./chunk-4SALLK63.js";
72
+ import {
73
+ buildProjectVerificationGuidance
74
+ } from "./chunk-MCPQNJMK.js";
75
+ import {
76
+ resolveSynthesisModel
77
+ } from "./chunk-IZZK3H6I.js";
78
+ import {
79
+ getProcessLifecycleManager,
80
+ setProcessLifecycleManager
81
+ } from "./chunk-SQZRPY23.js";
82
+ import {
83
+ matchesErrorPattern
84
+ } from "./chunk-2YFUIER7.js";
85
+ import {
86
+ TelemetryLogger
87
+ } from "./chunk-T6VPI2XP.js";
88
+ import {
89
+ formatVariantIdentifier,
90
+ formatVariantIdentifierFromResult
91
+ } from "./chunk-YWNAHW24.js";
92
+ import {
93
+ parseJsonWithContext
94
+ } from "./chunk-QVZMFDYG.js";
95
+ import {
96
+ calculateRetryDelayMs,
97
+ retryOperation
98
+ } from "./chunk-C57KJOUQ.js";
99
+ import {
100
+ pruneGitWorktreeEntries
101
+ } from "./chunk-5EERLVZB.js";
102
+ import {
103
+ isProtectedPipelineBranch
104
+ } from "./chunk-XQD2B6BB.js";
105
+ import {
106
+ isPoeticOwnedBranch,
107
+ poeticVariantBranchName,
108
+ poeticVariantBranchPrefix
109
+ } from "./chunk-34CNP2HB.js";
110
+ import {
111
+ runVerifyCommands
112
+ } from "./chunk-QU6JQJMH.js";
113
+ import {
114
+ MAX_PER_VARIANT_TIMEOUT_MINUTES
115
+ } from "./chunk-LAMKBTXX.js";
116
+ import {
117
+ detectProjectCapabilities,
118
+ hasProjectLanguage
119
+ } from "./chunk-GNH3QGTL.js";
120
+ import {
121
+ isQuietOutputRequested,
122
+ isVerboseOutputRequested
123
+ } from "./chunk-FKAUPHMR.js";
124
+ import {
125
+ toVariantSlug
126
+ } from "./chunk-TSXGRLPR.js";
127
+ import {
128
+ CompetitionTimeoutError
129
+ } from "./chunk-LUVKFFWR.js";
130
+ import {
131
+ getRuntimeEnv
132
+ } from "./chunk-ENRGKNR5.js";
133
+ import {
134
+ LabPathResolver
135
+ } from "./chunk-7GDRQBQC.js";
136
+ import {
137
+ rethrowConfigValidityError
138
+ } from "./chunk-AT4TNPWW.js";
139
+ import {
140
+ resolvePoeticDirFromContext
141
+ } from "./chunk-UI2F6DJ5.js";
142
+ import {
143
+ findProjectRoot
144
+ } from "./chunk-L6OM4A22.js";
145
+ import {
146
+ debugLog,
147
+ emitWarning
148
+ } from "./chunk-EJGCZGUF.js";
149
+
150
+ // src/orchestrator/pr-workflow-coordinator-impl-core.ts
151
+ import fs from "fs/promises";
152
+ import chalk3 from "chalk";
153
+ import { execa } from "execa";
154
+
155
+ // src/config/validation-helpers.ts
156
+ function validateTimeout(value, unit, options = {}) {
157
+ const {
158
+ defaultMs = 3e5,
159
+ // 5 minutes default
160
+ minMs = 1e3,
161
+ // 1 second minimum
162
+ maxMs = 72e5,
163
+ // 2 hours maximum
164
+ fieldName = "timeout"
165
+ } = options;
166
+ if (value === void 0 || value === null) {
167
+ return defaultMs;
168
+ }
169
+ if (typeof value !== "number" || !Number.isFinite(value)) {
170
+ throw new Error(`${fieldName} must be a finite number, got: ${value}`);
171
+ }
172
+ let timeoutMs;
173
+ switch (unit) {
174
+ case "milliseconds":
175
+ timeoutMs = value;
176
+ break;
177
+ case "seconds":
178
+ timeoutMs = value * 1e3;
179
+ break;
180
+ case "minutes":
181
+ timeoutMs = value * 60 * 1e3;
182
+ break;
183
+ default:
184
+ throw new Error(`Invalid timeout unit: ${unit}`);
185
+ }
186
+ if (timeoutMs < 0) {
187
+ throw new Error(`${fieldName} must be non-negative, got: ${value} ${unit}`);
188
+ }
189
+ if (timeoutMs < minMs) {
190
+ throw new Error(
191
+ `${fieldName} (${timeoutMs}ms) is below minimum (${minMs}ms). Provide at least ${minMs / 1e3}s.`
192
+ );
193
+ }
194
+ if (timeoutMs > maxMs) {
195
+ throw new Error(
196
+ `${fieldName} (${timeoutMs}ms) exceeds maximum (${maxMs}ms). Provide at most ${maxMs / 6e4} minutes.`
197
+ );
198
+ }
199
+ return Math.round(timeoutMs);
200
+ }
201
+ function validateVerbosity(verboseBoolean, verbosityEnum) {
202
+ if (verbosityEnum !== void 0) {
203
+ const validLevels = ["silent", "minimal", "normal", "detailed", "debug"];
204
+ if (!validLevels.includes(verbosityEnum)) {
205
+ throw new Error(
206
+ `Invalid verbosity level: ${verbosityEnum}. Must be one of: ${validLevels.join(", ")}`
207
+ );
208
+ }
209
+ return verbosityEnum;
210
+ }
211
+ if (verboseBoolean === true) {
212
+ return "detailed";
213
+ }
214
+ if (verboseBoolean === false) {
215
+ return "normal";
216
+ }
217
+ return "normal";
218
+ }
219
+ function validatePercentage(value, fieldName, options = {}) {
220
+ const {
221
+ min = 0,
222
+ max = 100,
223
+ defaultValue = min,
224
+ fieldName: name = fieldName,
225
+ allowFractional = false
226
+ } = options;
227
+ if (value === void 0 || value === null) {
228
+ return defaultValue;
229
+ }
230
+ if (typeof value !== "number" || !Number.isFinite(value)) {
231
+ throw new Error(`${name} must be a finite number, got: ${value}`);
232
+ }
233
+ if (value < min || value > max) {
234
+ throw new Error(`${name} must be between ${min} and ${max}, got: ${value}`);
235
+ }
236
+ if (!allowFractional && !Number.isInteger(value)) {
237
+ throw new Error(`${name} must be an integer, got: ${value}`);
238
+ }
239
+ return value;
240
+ }
241
+ function validateConfidence(value, options = {}) {
242
+ if (value === void 0 || value === null) {
243
+ return options.defaultValue ?? 85;
244
+ }
245
+ const fieldName = options.fieldName ?? "confidence";
246
+ if (typeof value !== "number" || !Number.isFinite(value)) {
247
+ throw new Error(`${fieldName} must be a finite number, got: ${value}`);
248
+ }
249
+ if (value >= 0 && value <= 1) {
250
+ return Math.round(value * 100);
251
+ }
252
+ return validatePercentage(value, fieldName, {
253
+ min: 0,
254
+ max: 100,
255
+ allowFractional: false
256
+ });
257
+ }
258
+
259
+ // src/orchestrator/dependency-graph-resolver.ts
260
+ var DependencyGraphResolver = class {
261
+ /**
262
+ * Builds a dependency graph from task specifications
263
+ *
264
+ * Algorithm:
265
+ * 1. Create nodes with initial state (O(V))
266
+ * 2. Build adjacency list by reversing dependencies (O(E))
267
+ * 3. Compute topological levels via Kahn's algorithm (O(V+E))
268
+ *
269
+ * Complexity: O(V+E) where V = tasks, E = dependencies
270
+ *
271
+ * @param tasks - Array of task dependency specifications
272
+ * @returns Complete dependency graph with topological levels
273
+ *
274
+ * @example
275
+ * ```typescript
276
+ * const graph = resolver.buildGraph([
277
+ * { id: "task1", dependencies: [] },
278
+ * { id: "task2", dependencies: ["task1"] }
279
+ * ]);
280
+ * // graph.nodes.get("task1").topologicalLevel === 0
281
+ * // graph.nodes.get("task2").topologicalLevel === 1
282
+ * ```
283
+ */
284
+ buildGraph(tasks) {
285
+ const nodes = /* @__PURE__ */ new Map();
286
+ const adjacency = {};
287
+ for (const task of tasks) {
288
+ nodes.set(task.id, {
289
+ id: task.id,
290
+ state: task.dependencies.length === 0 ? "ready" : "pending",
291
+ dependencies: [...task.dependencies],
292
+ // Defensive copy
293
+ dependents: [],
294
+ // Will be populated below
295
+ topologicalLevel: -1,
296
+ // Will be computed below
297
+ metadata: task.metadata ? { ...task.metadata } : void 0
298
+ });
299
+ adjacency[task.id] = [];
300
+ }
301
+ for (const task of tasks) {
302
+ for (const depId of task.dependencies) {
303
+ const depNode = nodes.get(depId);
304
+ if (depNode) {
305
+ depNode.dependents.push(task.id);
306
+ if (!adjacency[depId]) {
307
+ adjacency[depId] = [];
308
+ }
309
+ const depAdjacency = adjacency[depId];
310
+ if (depAdjacency) {
311
+ depAdjacency.push(task.id);
312
+ }
313
+ }
314
+ }
315
+ }
316
+ this.computeTopologicalLevels(nodes, adjacency);
317
+ return { nodes, adjacency };
318
+ }
319
+ /**
320
+ * Computes topological levels using Kahn's algorithm
321
+ *
322
+ * Algorithm (modified Kahn's for level assignment):
323
+ * 1. Start with tasks that have no dependencies (level 0)
324
+ * 2. Process tasks level by level
325
+ * 3. When all dependencies of a task are processed, assign it to next level
326
+ * 4. Repeat until all tasks are assigned
327
+ *
328
+ * Complexity: O(V+E)
329
+ *
330
+ * Side effect: Updates topologicalLevel field in nodes
331
+ *
332
+ * @private
333
+ */
334
+ computeTopologicalLevels(nodes, adjacency) {
335
+ const inDegree = /* @__PURE__ */ new Map();
336
+ for (const [id, node] of nodes.entries()) {
337
+ inDegree.set(id, node.dependencies.length);
338
+ }
339
+ let currentLevel = [];
340
+ for (const [id, degree] of inDegree.entries()) {
341
+ if (degree === 0) {
342
+ currentLevel.push(id);
343
+ const node = nodes.get(id);
344
+ if (node) {
345
+ node.topologicalLevel = 0;
346
+ }
347
+ }
348
+ }
349
+ let level = 0;
350
+ while (currentLevel.length > 0) {
351
+ const nextLevel = [];
352
+ for (const taskId of currentLevel) {
353
+ const dependents = adjacency[taskId] || [];
354
+ for (const depId of dependents) {
355
+ const currentDegree = inDegree.get(depId) ?? 0;
356
+ const newDegree = currentDegree - 1;
357
+ inDegree.set(depId, newDegree);
358
+ if (newDegree === 0) {
359
+ nextLevel.push(depId);
360
+ const node = nodes.get(depId);
361
+ if (node) {
362
+ node.topologicalLevel = level + 1;
363
+ }
364
+ }
365
+ }
366
+ }
367
+ currentLevel = nextLevel;
368
+ level++;
369
+ }
370
+ }
371
+ /**
372
+ * Validates graph structure for safe execution
373
+ *
374
+ * Checks:
375
+ * 1. No cycles (circular dependencies)
376
+ * 2. No missing dependencies (broken references)
377
+ * 3. No self-loops (task depends on itself)
378
+ * 4. Warns about orphaned nodes (unreachable tasks)
379
+ *
380
+ * Complexity: O(V+E)
381
+ *
382
+ * @param graph - Graph to validate
383
+ * @returns Validation result with errors and warnings
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * const validation = resolver.validateGraph(graph);
388
+ * if (!validation.valid) {
389
+ * console.error("Invalid graph:", validation.errors);
390
+ * }
391
+ * if (validation.warnings?.length) {
392
+ * console.warn("Warnings:", validation.warnings);
393
+ * }
394
+ * ```
395
+ */
396
+ validateGraph(graph) {
397
+ const errors = [];
398
+ const warnings = [];
399
+ const cycleResult = this.detectCycles(graph);
400
+ if (cycleResult.hasCycle) {
401
+ const cyclePath = cycleResult.cyclePath?.join(" \u2192 ") || "unknown";
402
+ errors.push(`Circular dependency detected: ${cyclePath}`);
403
+ }
404
+ for (const [id, node] of graph.nodes.entries()) {
405
+ for (const depId of node.dependencies) {
406
+ if (!graph.nodes.has(depId)) {
407
+ errors.push(`Task "${id}" depends on non-existent task "${depId}"`);
408
+ }
409
+ }
410
+ }
411
+ for (const [id, node] of graph.nodes.entries()) {
412
+ if (node.dependencies.includes(id)) {
413
+ errors.push(`Task "${id}" has a self-loop (depends on itself)`);
414
+ }
415
+ }
416
+ const reachable = this.findReachableNodes(graph);
417
+ for (const id of graph.nodes.keys()) {
418
+ if (!reachable.has(id)) {
419
+ warnings.push(`Task "${id}" is orphaned (unreachable from entry points)`);
420
+ }
421
+ }
422
+ for (const [id, node] of graph.nodes.entries()) {
423
+ if (node.topologicalLevel === -1 && reachable.has(id)) {
424
+ warnings.push(`Task "${id}" has unassigned topological level (possible algorithm bug)`);
425
+ }
426
+ }
427
+ return {
428
+ valid: errors.length === 0,
429
+ errors,
430
+ warnings: warnings.length > 0 ? warnings : void 0
431
+ };
432
+ }
433
+ /**
434
+ * Detects cycles in the graph using DFS with colored nodes
435
+ *
436
+ * Algorithm:
437
+ * 1. Mark all nodes as WHITE (unvisited)
438
+ * 2. For each WHITE node, start DFS traversal
439
+ * 3. Mark nodes GRAY when entering, BLACK when leaving
440
+ * 4. If we encounter a GRAY node, we've found a cycle
441
+ *
442
+ * Complexity: O(V+E)
443
+ *
444
+ * @private
445
+ * @returns Cycle detection result with path if found
446
+ */
447
+ detectCycles(graph) {
448
+ const colors = /* @__PURE__ */ new Map();
449
+ const parent = /* @__PURE__ */ new Map();
450
+ for (const id of graph.nodes.keys()) {
451
+ colors.set(id, "WHITE");
452
+ }
453
+ for (const id of graph.nodes.keys()) {
454
+ if (colors.get(id) === "WHITE") {
455
+ const cyclePath = this.dfsVisit(id, graph, colors, parent, []);
456
+ if (cyclePath.length > 0) {
457
+ return { hasCycle: true, cyclePath };
458
+ }
459
+ }
460
+ }
461
+ return { hasCycle: false };
462
+ }
463
+ /**
464
+ * DFS visit helper for cycle detection
465
+ *
466
+ * @private
467
+ * @returns Cycle path if found, empty array otherwise
468
+ */
469
+ dfsVisit(nodeId, graph, colors, parent, path3) {
470
+ colors.set(nodeId, "GRAY");
471
+ path3.push(nodeId);
472
+ const adjacentNodes = graph.adjacency[nodeId] || [];
473
+ for (const adjId of adjacentNodes) {
474
+ const color = colors.get(adjId);
475
+ if (color === "GRAY") {
476
+ const cycleStart = path3.indexOf(adjId);
477
+ return [...path3.slice(cycleStart), adjId];
478
+ }
479
+ if (color === "WHITE") {
480
+ parent.set(adjId, nodeId);
481
+ const cyclePath = this.dfsVisit(adjId, graph, colors, parent, path3);
482
+ if (cyclePath.length > 0) {
483
+ return cyclePath;
484
+ }
485
+ }
486
+ }
487
+ path3.pop();
488
+ colors.set(nodeId, "BLACK");
489
+ return [];
490
+ }
491
+ /**
492
+ * Finds all reachable nodes from entry points (tasks with no dependencies)
493
+ *
494
+ * Uses Tarjan's algorithm to detect strongly connected components (cycles),
495
+ * then performs reachability analysis that properly handles cycles.
496
+ *
497
+ * Algorithm:
498
+ * 1. Find all SCCs (strongly connected components) using Tarjan's algorithm
499
+ * 2. Build condensed graph where each SCC is a single node
500
+ * 3. Perform BFS from entry point SCCs
501
+ * 4. A node is reachable if its SCC is reachable
502
+ *
503
+ * This ensures nodes in cycles are marked reachable if any node in the cycle
504
+ * is reachable from an entry point.
505
+ *
506
+ * Complexity: O(V+E)
507
+ *
508
+ * @private
509
+ * @returns Set of reachable task IDs
510
+ */
511
+ findReachableNodes(graph) {
512
+ const sccs = this.findStronglyConnectedComponents(graph);
513
+ const nodeToScc = /* @__PURE__ */ new Map();
514
+ for (let i = 0; i < sccs.length; i++) {
515
+ const scc = sccs[i];
516
+ if (!scc) continue;
517
+ for (const nodeId of scc) {
518
+ nodeToScc.set(nodeId, i);
519
+ }
520
+ }
521
+ const sccDeps = Array.from({ length: sccs.length }, () => /* @__PURE__ */ new Set());
522
+ for (const [id, node] of graph.nodes.entries()) {
523
+ const sccIdx = nodeToScc.get(id);
524
+ if (sccIdx === void 0) continue;
525
+ for (const depId of node.dependencies) {
526
+ const depSccIdx = nodeToScc.get(depId);
527
+ if (depSccIdx !== void 0 && depSccIdx !== sccIdx) {
528
+ sccDeps[depSccIdx]?.add(sccIdx);
529
+ }
530
+ }
531
+ }
532
+ const entrySCCs = /* @__PURE__ */ new Set();
533
+ for (let i = 0; i < sccs.length; i++) {
534
+ const scc = sccs[i];
535
+ if (!scc) continue;
536
+ for (const nodeId of scc) {
537
+ const node = graph.nodes.get(nodeId);
538
+ if (!node) continue;
539
+ if (node.dependencies.length === 0) {
540
+ entrySCCs.add(i);
541
+ break;
542
+ }
543
+ const hasOnlyInternalDeps = node.dependencies.every((depId) => {
544
+ const depSccIdx = nodeToScc.get(depId);
545
+ return depSccIdx === i;
546
+ });
547
+ if (hasOnlyInternalDeps && scc.length === 1) {
548
+ entrySCCs.add(i);
549
+ break;
550
+ }
551
+ }
552
+ }
553
+ const reachableSCCs = /* @__PURE__ */ new Set();
554
+ const queue = Array.from(entrySCCs);
555
+ for (const sccIdx of queue) {
556
+ reachableSCCs.add(sccIdx);
557
+ }
558
+ while (queue.length > 0) {
559
+ const current = queue.shift();
560
+ const deps = sccDeps[current];
561
+ if (!deps) continue;
562
+ for (const depIdx of deps) {
563
+ if (!reachableSCCs.has(depIdx)) {
564
+ reachableSCCs.add(depIdx);
565
+ queue.push(depIdx);
566
+ }
567
+ }
568
+ }
569
+ const reachable = /* @__PURE__ */ new Set();
570
+ for (const sccIdx of reachableSCCs) {
571
+ const scc = sccs[sccIdx];
572
+ if (!scc) continue;
573
+ for (const nodeId of scc) {
574
+ reachable.add(nodeId);
575
+ }
576
+ }
577
+ return reachable;
578
+ }
579
+ /**
580
+ * Finds strongly connected components using Tarjan's algorithm
581
+ *
582
+ * A strongly connected component is a maximal set of nodes where every node
583
+ * is reachable from every other node. Cycles form SCCs.
584
+ *
585
+ * Complexity: O(V+E)
586
+ *
587
+ * @private
588
+ * @returns Array of SCCs, where each SCC is an array of node IDs
589
+ */
590
+ findStronglyConnectedComponents(graph) {
591
+ const sccs = [];
592
+ const index = /* @__PURE__ */ new Map();
593
+ const lowlink = /* @__PURE__ */ new Map();
594
+ const onStack = /* @__PURE__ */ new Set();
595
+ const stack = [];
596
+ let currentIndex = 0;
597
+ const strongConnect = (nodeId) => {
598
+ index.set(nodeId, currentIndex);
599
+ lowlink.set(nodeId, currentIndex);
600
+ currentIndex++;
601
+ stack.push(nodeId);
602
+ onStack.add(nodeId);
603
+ const dependents = graph.adjacency[nodeId] || [];
604
+ for (const depId of dependents) {
605
+ if (!index.has(depId)) {
606
+ strongConnect(depId);
607
+ lowlink.set(nodeId, Math.min(lowlink.get(nodeId), lowlink.get(depId)));
608
+ } else if (onStack.has(depId)) {
609
+ lowlink.set(nodeId, Math.min(lowlink.get(nodeId), index.get(depId)));
610
+ }
611
+ }
612
+ if (lowlink.get(nodeId) === index.get(nodeId)) {
613
+ const scc = [];
614
+ let w;
615
+ do {
616
+ w = stack.pop();
617
+ onStack.delete(w);
618
+ scc.push(w);
619
+ } while (w !== nodeId);
620
+ sccs.push(scc);
621
+ }
622
+ };
623
+ for (const nodeId of graph.nodes.keys()) {
624
+ if (!index.has(nodeId)) {
625
+ strongConnect(nodeId);
626
+ }
627
+ }
628
+ return sccs;
629
+ }
630
+ /**
631
+ * Gets all tasks that are ready to execute
632
+ *
633
+ * A task is ready if:
634
+ * - All dependencies are completed
635
+ * - Current state is "ready"
636
+ *
637
+ * Complexity: O(V) - scans all nodes
638
+ *
639
+ * @param graph - Current graph state
640
+ * @returns Array of task IDs ready to execute, sorted by topological level
641
+ *
642
+ * @example
643
+ * ```typescript
644
+ * const readyTasks = resolver.getReadyTasks(graph);
645
+ * // Execute ready tasks in parallel
646
+ * await Promise.all(readyTasks.map(id => executeTask(id)));
647
+ * ```
648
+ */
649
+ getReadyTasks(graph) {
650
+ const ready = [];
651
+ for (const [id, node] of graph.nodes.entries()) {
652
+ if (node.state === "ready") {
653
+ ready.push({ id, level: node.topologicalLevel });
654
+ }
655
+ }
656
+ ready.sort((a, b) => a.level - b.level);
657
+ return ready.map((r) => r.id);
658
+ }
659
+ /**
660
+ * Marks a task as running
661
+ *
662
+ * Complexity: O(1)
663
+ *
664
+ * @param graph - Graph to update
665
+ * @param taskId - Task to mark as running
666
+ * @throws Error if task is not in "ready" state
667
+ */
668
+ markRunning(graph, taskId) {
669
+ const node = graph.nodes.get(taskId);
670
+ if (!node) {
671
+ throw new Error(`Task "${taskId}" not found in graph`);
672
+ }
673
+ if (node.state !== "ready") {
674
+ throw new Error(`Task "${taskId}" is not ready (current state: ${node.state})`);
675
+ }
676
+ node.state = "running";
677
+ }
678
+ /**
679
+ * Marks a task as completed and updates dependent tasks
680
+ *
681
+ * Algorithm:
682
+ * 1. Set task state to "completed"
683
+ * 2. For each dependent task:
684
+ * - Check if all dependencies are completed
685
+ * - If yes, mark as "ready"
686
+ *
687
+ * Complexity: O(D) where D = number of dependents
688
+ *
689
+ * @param graph - Graph to update
690
+ * @param taskId - Task to mark as completed
691
+ * @returns Array of newly ready task IDs
692
+ *
693
+ * @example
694
+ * ```typescript
695
+ * const newlyReady = resolver.markCompleted(graph, "compile");
696
+ * // Execute newly ready tasks
697
+ * for (const id of newlyReady) {
698
+ * await executeTask(id);
699
+ * }
700
+ * ```
701
+ */
702
+ markCompleted(graph, taskId) {
703
+ const node = graph.nodes.get(taskId);
704
+ if (!node) {
705
+ throw new Error(`Task "${taskId}" not found in graph`);
706
+ }
707
+ if (node.state !== "running") {
708
+ throw new Error(`Task "${taskId}" cannot be completed from state "${node.state}"`);
709
+ }
710
+ node.state = "completed";
711
+ const newlyReady = [];
712
+ for (const depId of node.dependents) {
713
+ const depNode = graph.nodes.get(depId);
714
+ if (!depNode) continue;
715
+ if (depNode.state !== "pending" && depNode.state !== "blocked") {
716
+ continue;
717
+ }
718
+ const allDepsCompleted = depNode.dependencies.every((d) => {
719
+ const dNode = graph.nodes.get(d);
720
+ return dNode?.state === "completed";
721
+ });
722
+ if (allDepsCompleted) {
723
+ depNode.state = "ready";
724
+ newlyReady.push(depId);
725
+ }
726
+ }
727
+ return newlyReady;
728
+ }
729
+ /**
730
+ * Marks a task as failed and optionally blocks or resets dependent tasks
731
+ *
732
+ * Algorithm:
733
+ * 1. Set task state to "failed"
734
+ * 2. If blockDependents=true: Recursively mark all transitive dependents as "blocked"
735
+ * 3. If blockDependents=false: Reset dependents to "pending" for retry workflows
736
+ *
737
+ * Complexity: O(V) worst case (if failure cascades through entire graph)
738
+ *
739
+ * @param graph - Graph to update
740
+ * @param taskId - Task to mark as failed
741
+ * @param error - Optional error message
742
+ * @param blockDependents - If true, blocks dependents; if false, resets to pending (default: true)
743
+ * @returns Array of affected task IDs (blocked or reset)
744
+ *
745
+ * @example
746
+ * ```typescript
747
+ * // Block dependents (default behavior)
748
+ * const blocked = resolver.markFailed(graph, "compile", "Type errors");
749
+ * console.log(`Blocked ${blocked.length} dependent tasks`);
750
+ *
751
+ * // Allow retry by resetting dependents to pending
752
+ * const reset = resolver.markFailed(graph, "compile", "Type errors", false);
753
+ * console.log(`Reset ${reset.length} dependents for retry`);
754
+ * ```
755
+ */
756
+ markFailed(graph, taskId, error, blockDependents = true) {
757
+ const node = graph.nodes.get(taskId);
758
+ if (!node) {
759
+ throw new Error(`Task "${taskId}" not found in graph`);
760
+ }
761
+ node.state = "failed";
762
+ if (error && node.metadata) {
763
+ node.metadata.error = error;
764
+ } else if (error) {
765
+ node.metadata = { error };
766
+ }
767
+ const affected = [];
768
+ const queue = [...node.dependents];
769
+ const visited = /* @__PURE__ */ new Set();
770
+ while (queue.length > 0) {
771
+ const depId = queue.shift();
772
+ if (visited.has(depId)) continue;
773
+ visited.add(depId);
774
+ const depNode = graph.nodes.get(depId);
775
+ if (!depNode) continue;
776
+ if (depNode.state === "completed" || depNode.state === "failed") {
777
+ continue;
778
+ }
779
+ if (blockDependents) {
780
+ depNode.state = "blocked";
781
+ affected.push(depId);
782
+ queue.push(...depNode.dependents);
783
+ } else {
784
+ const hasFailedDependency = depNode.dependencies.some(
785
+ (dependencyId) => dependencyId !== taskId && graph.nodes.get(dependencyId)?.state === "failed"
786
+ );
787
+ depNode.state = hasFailedDependency ? "blocked" : "pending";
788
+ affected.push(depId);
789
+ queue.push(...depNode.dependents);
790
+ }
791
+ }
792
+ return affected;
793
+ }
794
+ /**
795
+ * Checks if all tasks are in a terminal state
796
+ *
797
+ * Terminal states: completed, failed, blocked
798
+ *
799
+ * Complexity: O(V)
800
+ *
801
+ * @param graph - Graph to check
802
+ * @returns True if all tasks are completed, failed, or blocked
803
+ */
804
+ isComplete(graph) {
805
+ for (const node of graph.nodes.values()) {
806
+ if (node.state !== "completed" && node.state !== "failed" && node.state !== "blocked") {
807
+ return false;
808
+ }
809
+ }
810
+ return true;
811
+ }
812
+ /**
813
+ * Gets tasks at a specific topological level
814
+ *
815
+ * Useful for level-by-level execution strategies.
816
+ *
817
+ * Complexity: O(V)
818
+ *
819
+ * @param graph - Graph to query
820
+ * @param level - Topological level
821
+ * @returns Array of task IDs at the specified level
822
+ *
823
+ * @example
824
+ * ```typescript
825
+ * // Execute all level 0 tasks first
826
+ * const level0 = resolver.getTasksByLevel(graph, 0);
827
+ * await Promise.all(level0.map(id => executeTask(id)));
828
+ * ```
829
+ */
830
+ getTasksByLevel(graph, level) {
831
+ const tasks = [];
832
+ for (const [id, node] of graph.nodes.entries()) {
833
+ if (node.topologicalLevel === level) {
834
+ tasks.push(id);
835
+ }
836
+ }
837
+ return tasks;
838
+ }
839
+ /**
840
+ * Gets the maximum topological level in the graph
841
+ *
842
+ * Complexity: O(V)
843
+ *
844
+ * @param graph - Graph to analyze
845
+ * @returns Maximum level, or -1 if graph is empty
846
+ */
847
+ getMaxLevel(graph) {
848
+ let maxLevel = -1;
849
+ for (const node of graph.nodes.values()) {
850
+ if (node.topologicalLevel > maxLevel) {
851
+ maxLevel = node.topologicalLevel;
852
+ }
853
+ }
854
+ return maxLevel;
855
+ }
856
+ /**
857
+ * Computes comprehensive statistics about the graph
858
+ *
859
+ * Useful for monitoring, debugging, and optimization.
860
+ *
861
+ * Complexity: O(V)
862
+ *
863
+ * @param graph - Graph to analyze
864
+ * @returns Detailed statistics
865
+ *
866
+ * @example
867
+ * ```typescript
868
+ * const stats = resolver.getStatistics(graph);
869
+ * console.log(`Progress: ${stats.completedTasks}/${stats.totalTasks}`);
870
+ * console.log(`Graph depth: ${stats.maxLevel + 1} levels`);
871
+ * ```
872
+ */
873
+ getStatistics(graph) {
874
+ let readyCount = 0;
875
+ let runningCount = 0;
876
+ let completedCount = 0;
877
+ let failedCount = 0;
878
+ let blockedCount = 0;
879
+ let maxLevel = -1;
880
+ let totalDeps = 0;
881
+ let entryPoints = 0;
882
+ let terminalNodes = 0;
883
+ for (const node of graph.nodes.values()) {
884
+ switch (node.state) {
885
+ case "ready":
886
+ readyCount++;
887
+ break;
888
+ case "running":
889
+ runningCount++;
890
+ break;
891
+ case "completed":
892
+ completedCount++;
893
+ break;
894
+ case "failed":
895
+ failedCount++;
896
+ break;
897
+ case "blocked":
898
+ blockedCount++;
899
+ break;
900
+ }
901
+ if (node.topologicalLevel > maxLevel) {
902
+ maxLevel = node.topologicalLevel;
903
+ }
904
+ totalDeps += node.dependencies.length;
905
+ if (node.dependencies.length === 0) {
906
+ entryPoints++;
907
+ }
908
+ if (node.dependents.length === 0) {
909
+ terminalNodes++;
910
+ }
911
+ }
912
+ const totalTasks = graph.nodes.size;
913
+ return {
914
+ totalTasks,
915
+ readyTasks: readyCount,
916
+ runningTasks: runningCount,
917
+ completedTasks: completedCount,
918
+ failedTasks: failedCount,
919
+ blockedTasks: blockedCount,
920
+ maxLevel,
921
+ averageDependencies: totalTasks > 0 ? totalDeps / totalTasks : 0,
922
+ entryPoints,
923
+ terminalNodes
924
+ };
925
+ }
926
+ /**
927
+ * Resets all task states to initial values
928
+ *
929
+ * Useful for re-executing the graph or recovering from failures.
930
+ *
931
+ * Complexity: O(V)
932
+ *
933
+ * @param graph - Graph to reset
934
+ *
935
+ * @example
936
+ * ```typescript
937
+ * // Retry execution after fixing issues
938
+ * resolver.reset(graph);
939
+ * const validation = resolver.validateGraph(graph);
940
+ * if (validation.valid) {
941
+ * // Execute again
942
+ * }
943
+ * ```
944
+ */
945
+ reset(graph) {
946
+ for (const node of graph.nodes.values()) {
947
+ node.state = node.dependencies.length === 0 ? "ready" : "pending";
948
+ if (node.metadata?.error) {
949
+ delete node.metadata.error;
950
+ }
951
+ }
952
+ }
953
+ };
954
+
955
+ // src/orchestrator/services/cleanup-service.ts
956
+ import path from "path";
957
+ import chalk from "chalk";
958
+ var CleanupService = class {
959
+ constructor(prManager, verbose = false, worktreeCleanup, repoRoot = process.cwd()) {
960
+ this.prManager = prManager;
961
+ this.verbose = verbose;
962
+ this.worktreeCleanup = worktreeCleanup;
963
+ this.repoRoot = path.resolve(repoRoot);
964
+ }
965
+ prManager;
966
+ verbose;
967
+ worktreeCleanup;
968
+ repoRoot;
969
+ /**
970
+ * Clean up non-winning PRs and branches after competition
971
+ */
972
+ async cleanupCompetition(results, winner, options = {}) {
973
+ const labMode = options.labMode === true || LabPathResolver.getInstance().isLabMode();
974
+ if (labMode) {
975
+ if (this.verbose || options.verbose) {
976
+ console.log(
977
+ chalk.cyan("Lab mode active - skipping cleanup to preserve worktrees for analysis")
978
+ );
979
+ }
980
+ return;
981
+ }
982
+ const { verbose = this.verbose, preserveSubmittedOnly = false, taskId } = options;
983
+ const losers = results.filter((r) => {
984
+ if (!r.prNumber) {
985
+ if (verbose) {
986
+ console.log(chalk.gray(` \u2022 Skipping ${r.provider} ${r.strategy} - no PR number`));
987
+ }
988
+ return false;
989
+ }
990
+ if (winner.prNumber) {
991
+ const isLoser2 = r.prNumber !== winner.prNumber;
992
+ if (verbose && !isLoser2) {
993
+ console.log(
994
+ chalk.gray(` \u2022 Skipping ${r.provider} ${r.strategy} - winner's PR #${r.prNumber}`)
995
+ );
996
+ }
997
+ return isLoser2;
998
+ }
999
+ const isLoser = r.variant !== winner.variant || r.provider !== winner.provider;
1000
+ if (verbose && !isLoser) {
1001
+ console.log(chalk.gray(` \u2022 Skipping ${r.provider} ${r.strategy} - winner's variant`));
1002
+ }
1003
+ return isLoser;
1004
+ });
1005
+ const applyPendingLosers = [];
1006
+ const eligibleLosers = losers.filter((r) => {
1007
+ if (this.requiresApplyRecovery(r)) {
1008
+ applyPendingLosers.push(r);
1009
+ return false;
1010
+ }
1011
+ return true;
1012
+ });
1013
+ if (applyPendingLosers.length > 0) {
1014
+ console.log(chalk.gray("\nPreserving PRs awaiting local apply:"));
1015
+ applyPendingLosers.forEach((variant) => {
1016
+ const label = this.formatProviderVariantLabel(variant);
1017
+ const prLabel = variant.prNumber ? `PR #${variant.prNumber}` : "PR pending";
1018
+ const hint = this.getRecoveryHint(variant);
1019
+ console.log(
1020
+ chalk.gray(
1021
+ ` \u2022 ${prLabel} - ${label}${hint ? ` \u2192 ${hint}` : " (run apply command before cleanup)"}`
1022
+ )
1023
+ );
1024
+ });
1025
+ }
1026
+ const shouldPreserveSubmittedPRs = preserveSubmittedOnly;
1027
+ const preservedSubmittedPRs = [];
1028
+ const losersToCleanup = eligibleLosers.filter((r) => {
1029
+ if (!shouldPreserveSubmittedPRs) {
1030
+ return true;
1031
+ }
1032
+ if (this.isPreservedSubmittedVariant(r)) {
1033
+ preservedSubmittedPRs.push(r);
1034
+ if (verbose) {
1035
+ console.log(
1036
+ chalk.gray(
1037
+ ` \u2022 Preserving ${r.provider} ${r.strategy} PR #${r.prNumber ?? "?"} (submit-only mode)`
1038
+ )
1039
+ );
1040
+ }
1041
+ return false;
1042
+ }
1043
+ return true;
1044
+ });
1045
+ if (preservedSubmittedPRs.length > 0) {
1046
+ await this.displayPreservedPRs(preservedSubmittedPRs);
1047
+ }
1048
+ if (losersToCleanup.length === 0) {
1049
+ if (preservedSubmittedPRs.length === 0 && verbose) {
1050
+ console.log(chalk.gray("\nNo losing PRs to close - checking for orphan branches..."));
1051
+ }
1052
+ if (taskId) {
1053
+ await this.cleanupOrphanBranchesByTask(taskId, winner);
1054
+ }
1055
+ return;
1056
+ }
1057
+ const hasBranchOnlyLosers = results.some(
1058
+ (r) => !r.prNumber && (r.variant !== winner.variant || r.provider !== winner.provider)
1059
+ );
1060
+ console.log(chalk.blue(`
1061
+ Cleaning up ${losersToCleanup.length} non-winning variant(s)...
1062
+ `));
1063
+ const cleanupResults = {
1064
+ success: 0,
1065
+ degraded: 0,
1066
+ failed: 0,
1067
+ errors: [],
1068
+ warnings: [],
1069
+ preserved: preservedSubmittedPRs
1070
+ };
1071
+ const CONCURRENCY_LIMIT = 3;
1072
+ const startTime = Date.now();
1073
+ for (let batchStart = 0; batchStart < losersToCleanup.length; batchStart += CONCURRENCY_LIMIT) {
1074
+ const batchEnd = Math.min(batchStart + CONCURRENCY_LIMIT, losersToCleanup.length);
1075
+ const batch = losersToCleanup.slice(batchStart, batchEnd);
1076
+ if (verbose) {
1077
+ console.log(
1078
+ chalk.gray(
1079
+ `
1080
+ [Batch ${Math.floor(batchStart / CONCURRENCY_LIMIT) + 1}] Processing ${batch.length} variant(s) in parallel...`
1081
+ )
1082
+ );
1083
+ }
1084
+ const batchPromises = batch.map(
1085
+ (loser, batchIndex) => this.cleanupSingleVariant(loser, batchStart + batchIndex, losersToCleanup.length, verbose)
1086
+ );
1087
+ const batchResults = await Promise.allSettled(batchPromises);
1088
+ batchResults.forEach((result, index) => {
1089
+ if (result.status === "fulfilled") {
1090
+ const variantResult = result.value;
1091
+ cleanupResults.success += variantResult.success ? 1 : 0;
1092
+ cleanupResults.degraded += variantResult.degraded ? 1 : 0;
1093
+ cleanupResults.failed += variantResult.success ? 0 : 1;
1094
+ if (variantResult.error) {
1095
+ cleanupResults.errors.push(variantResult.error);
1096
+ }
1097
+ if (variantResult.warning) {
1098
+ cleanupResults.warnings.push(variantResult.warning);
1099
+ }
1100
+ } else {
1101
+ const loser = batch[index];
1102
+ if (loser) {
1103
+ const errorMsg = `Unhandled exception during cleanup of ${loser.provider} ${loser.strategy}: ${result.reason instanceof Error ? result.reason.message : String(result.reason)}`;
1104
+ cleanupResults.errors.push(errorMsg);
1105
+ cleanupResults.failed++;
1106
+ }
1107
+ }
1108
+ });
1109
+ if (batchEnd < losersToCleanup.length) {
1110
+ await new Promise((resolve) => setTimeout(resolve, 500));
1111
+ }
1112
+ }
1113
+ const elapsedSeconds = ((Date.now() - startTime) / 1e3).toFixed(1);
1114
+ console.log(chalk.bold(`
1115
+ Cleanup Summary (${elapsedSeconds}s):`));
1116
+ console.log(chalk.green(` Successfully cleaned up: ${cleanupResults.success} variant(s)`));
1117
+ if (cleanupResults.degraded > 0) {
1118
+ console.log(chalk.yellow(` Completed with warnings: ${cleanupResults.degraded} variant(s)`));
1119
+ cleanupResults.warnings.forEach((warning) => {
1120
+ console.log(chalk.gray(` \u2022 ${warning}`));
1121
+ });
1122
+ }
1123
+ if (cleanupResults.failed > 0) {
1124
+ console.log(chalk.red(` Failed cleanup: ${cleanupResults.failed} variant(s)`));
1125
+ console.log(chalk.yellow("\nManual cleanup required for:"));
1126
+ cleanupResults.errors.forEach((error) => {
1127
+ console.log(chalk.gray(` \u2022 ${error}`));
1128
+ });
1129
+ console.log(chalk.gray("\nManual cleanup commands:"));
1130
+ losersToCleanup.forEach((loser) => {
1131
+ console.log(chalk.gray(` # For ${loser.provider} ${loser.strategy}:`));
1132
+ console.log(chalk.gray(` gh pr close ${loser.prNumber} || true`));
1133
+ if (taskId && loser.provider && loser.strategy && loser.executionMode) {
1134
+ const branch = poeticVariantBranchName({
1135
+ taskId,
1136
+ provider: loser.provider,
1137
+ strategy: loser.strategy,
1138
+ executionMode: loser.executionMode,
1139
+ model: loser.model
1140
+ });
1141
+ console.log(chalk.gray(` git branch -D ${branch} || true`));
1142
+ } else {
1143
+ console.log(chalk.gray(" gh pr view <PR_NUMBER> --json headRefName -q '.headRefName'"));
1144
+ }
1145
+ });
1146
+ } else {
1147
+ console.log(chalk.green("\nAll cleanup operations completed successfully!\n"));
1148
+ }
1149
+ if (hasBranchOnlyLosers && taskId) {
1150
+ await this.cleanupOrphanBranchesByTask(taskId, winner);
1151
+ }
1152
+ if (cleanupResults.failed > 0) {
1153
+ const summary = cleanupResults.errors.join("; ");
1154
+ throw new Error(
1155
+ `Cleanup partially failed: ${cleanupResults.failed}/${losersToCleanup.length} variant(s) \u2014 ${summary}`
1156
+ );
1157
+ }
1158
+ }
1159
+ /**
1160
+ * Cleanup a single variant (PR close + branch delete)
1161
+ * Returns result object for collection by Promise.allSettled()
1162
+ */
1163
+ async cleanupSingleVariant(loser, index, total, verbose = false) {
1164
+ const label = `${loser.provider} ${loser.strategy}`;
1165
+ try {
1166
+ if (verbose) {
1167
+ console.log(
1168
+ chalk.gray(` [${index + 1}/${total}] Processing ${label} (PR #${loser.prNumber})`)
1169
+ );
1170
+ }
1171
+ let prState = "unknown";
1172
+ let branch;
1173
+ try {
1174
+ const prData = await this.prManager.executeWithRetry(
1175
+ async () => {
1176
+ const { execa: execa2 } = await import("execa");
1177
+ const result = await execa2(
1178
+ "gh",
1179
+ ["pr", "view", String(loser.prNumber), "--json", "state,mergeable,headRefName"],
1180
+ { stdio: "pipe" }
1181
+ );
1182
+ return parseJsonWithContext(result.stdout, "[Cleanup] gh pr view output");
1183
+ },
1184
+ `validate PR #${loser.prNumber} state`,
1185
+ 2
1186
+ // 2 retries
1187
+ );
1188
+ if (prData) {
1189
+ prState = prData.state ?? "unknown";
1190
+ branch = prData.headRefName ?? "";
1191
+ if (prState === "closed") {
1192
+ console.log(
1193
+ chalk.yellow(` PR #${loser.prNumber} already closed, skipping to branch cleanup`)
1194
+ );
1195
+ } else if (prState === "merged") {
1196
+ const warning = `PR #${loser.prNumber} was already merged; cleanup skipped`;
1197
+ console.log(chalk.yellow(` PR #${loser.prNumber} already merged, skipping cleanup`));
1198
+ return { success: true, degraded: true, warning };
1199
+ }
1200
+ if (branch && isProtectedPipelineBranch(branch)) {
1201
+ const warning = `PR #${loser.prNumber} branch ${branch} is protected; cleanup skipped`;
1202
+ return { success: true, degraded: true, warning };
1203
+ }
1204
+ }
1205
+ } catch (validationError) {
1206
+ console.log(
1207
+ chalk.yellow(` Could not validate PR #${loser.prNumber} state: ${validationError}`)
1208
+ );
1209
+ }
1210
+ if (branch) {
1211
+ await this.releaseWorktreesForBranch(branch, verbose, false);
1212
+ }
1213
+ if (prState === "open") {
1214
+ try {
1215
+ if (verbose) {
1216
+ console.log(chalk.gray(` \u2192 Closing PR #${loser.prNumber}`));
1217
+ }
1218
+ const prNumber = loser.prNumber;
1219
+ if (typeof prNumber === "number") {
1220
+ await this.prManager.closePR(prNumber);
1221
+ console.log(chalk.green(` Closed PR #${prNumber}`));
1222
+ }
1223
+ } catch (closeError) {
1224
+ console.log(chalk.yellow(` Failed to close PR #${loser.prNumber}: ${closeError}`));
1225
+ }
1226
+ }
1227
+ if (!branch) {
1228
+ try {
1229
+ const prNumber = loser.prNumber;
1230
+ if (typeof prNumber === "number") {
1231
+ branch = await this.prManager.getPRBranch(prNumber);
1232
+ }
1233
+ if (verbose) {
1234
+ console.log(chalk.gray(` \u2192 PR branch: ${branch}`));
1235
+ }
1236
+ } catch (branchError) {
1237
+ console.log(
1238
+ chalk.yellow(` Could not get branch name for PR #${loser.prNumber}: ${branchError}`)
1239
+ );
1240
+ return {
1241
+ success: false,
1242
+ error: `Could not determine branch name for PR #${loser.prNumber}. Try: gh pr view <PR_NUMBER> --json headRefName -q '.headRefName'`
1243
+ };
1244
+ }
1245
+ }
1246
+ if (branch) {
1247
+ if (isProtectedPipelineBranch(branch)) {
1248
+ const warning = `Branch ${branch} is protected; cleanup skipped`;
1249
+ return { success: true, degraded: true, warning };
1250
+ }
1251
+ try {
1252
+ if (verbose) {
1253
+ console.log(chalk.gray(` \u2192 Deleting branch: ${branch}`));
1254
+ }
1255
+ try {
1256
+ await this.prManager.deleteBranch(branch, { force: false });
1257
+ } catch (_regularDeleteError) {
1258
+ if (verbose) {
1259
+ console.log(chalk.gray(" \u2192 Regular delete failed, trying force delete"));
1260
+ }
1261
+ await this.prManager.deleteBranch(branch, { force: true });
1262
+ }
1263
+ console.log(chalk.green(` Deleted branch: ${branch}`));
1264
+ } catch (deleteError) {
1265
+ const errorMsg = `Failed to delete branch ${branch}: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`;
1266
+ console.log(chalk.yellow(` ${errorMsg}`));
1267
+ return { success: false, error: errorMsg };
1268
+ }
1269
+ }
1270
+ console.log(chalk.green(` Successfully cleaned up ${label} (PR #${loser.prNumber})`));
1271
+ return { success: true };
1272
+ } catch (error) {
1273
+ const errorMsg = `Failed to cleanup ${loser.provider} ${loser.strategy}: ${error instanceof Error ? error.message : String(error)}`;
1274
+ console.log(chalk.red(` ${errorMsg}`));
1275
+ return { success: false, error: errorMsg };
1276
+ }
1277
+ }
1278
+ /**
1279
+ * Proactively remove git worktrees that are checked out on the given branch.
1280
+ *
1281
+ * This prevents "branch is checked out at ..." errors when deleting branches
1282
+ * during cleanup, especially when worktree pooling is enabled.
1283
+ */
1284
+ async releaseWorktreesForBranch(branch, verbose = false, labMode = LabPathResolver.getInstance().isLabMode()) {
1285
+ if (labMode || LabPathResolver.getInstance().isLabMode()) {
1286
+ if (verbose) {
1287
+ console.log(chalk.gray(" Lab mode - preserving worktrees"));
1288
+ }
1289
+ return;
1290
+ }
1291
+ try {
1292
+ const { execa: execa2 } = await import("execa");
1293
+ const { stdout } = await execa2("git", ["worktree", "list", "--porcelain"], {
1294
+ cwd: this.repoRoot,
1295
+ stdio: "pipe"
1296
+ });
1297
+ const lines = stdout.split("\n");
1298
+ const worktrees = [];
1299
+ let currentPath = null;
1300
+ for (const line of lines) {
1301
+ if (line.startsWith("worktree ")) {
1302
+ currentPath = line.substring("worktree ".length).trim();
1303
+ } else if (line.startsWith("branch ") && currentPath) {
1304
+ const branchRef = line.substring("branch ".length).trim();
1305
+ worktrees.push({ path: currentPath, branch: branchRef });
1306
+ currentPath = null;
1307
+ } else if (line.startsWith("detached ") && currentPath) {
1308
+ worktrees.push({ path: currentPath, branch: "" });
1309
+ currentPath = null;
1310
+ }
1311
+ }
1312
+ if (worktrees.length === 0) {
1313
+ return;
1314
+ }
1315
+ const normalizedBranch = branch.startsWith("refs/heads/") ? branch : `refs/heads/${branch}`;
1316
+ const matching = worktrees.filter(
1317
+ (wt) => wt.branch === normalizedBranch || wt.branch === branch
1318
+ );
1319
+ for (const wt of matching) {
1320
+ try {
1321
+ if (verbose) {
1322
+ console.log(chalk.gray(` \u2192 Releasing worktree for branch ${branch}: ${wt.path}`));
1323
+ }
1324
+ if (this.worktreeCleanup) {
1325
+ const released = await this.worktreeCleanup.cleanup(wt.path, {
1326
+ preserve: false,
1327
+ gitCwd: this.repoRoot
1328
+ });
1329
+ if (released === false) {
1330
+ throw new Error(`worktree cleanup refused ${wt.path}`);
1331
+ }
1332
+ } else {
1333
+ await execa2("git", ["worktree", "remove", wt.path, "--force"], {
1334
+ cwd: this.repoRoot,
1335
+ stdio: "pipe"
1336
+ });
1337
+ }
1338
+ } catch (error) {
1339
+ if (verbose) {
1340
+ const msg = error instanceof Error ? error.message : String(error);
1341
+ console.log(chalk.yellow(` Failed to remove worktree ${wt.path}: ${msg}`));
1342
+ }
1343
+ }
1344
+ }
1345
+ if (matching.length > 0) {
1346
+ await pruneGitWorktreeEntries({ cwd: this.repoRoot });
1347
+ }
1348
+ } catch (error) {
1349
+ if (verbose) {
1350
+ const msg = error instanceof Error ? error.message : String(error);
1351
+ console.log(chalk.gray(` Skipping worktree release for branch ${branch}: ${msg}`));
1352
+ }
1353
+ }
1354
+ }
1355
+ requiresApplyRecovery(result) {
1356
+ if (result.submittedOnly) {
1357
+ return true;
1358
+ }
1359
+ return result.applied === false;
1360
+ }
1361
+ isPreservedSubmittedVariant(result) {
1362
+ return result.submittedOnly === true;
1363
+ }
1364
+ /**
1365
+ * Display preserved PRs that still need manual attention
1366
+ */
1367
+ async displayPreservedPRs(preserved) {
1368
+ if (preserved.length === 0) {
1369
+ return;
1370
+ }
1371
+ console.log(chalk.blue(`
1372
+ Preserved ${preserved.length} PR(s) needing attention:
1373
+ `));
1374
+ for (const variant of preserved) {
1375
+ const label = this.formatProviderVariantLabel(variant);
1376
+ const prLabel = variant.prNumber ? `PR #${variant.prNumber}` : "PR pending";
1377
+ const appliedStatus = this.formatAppliedStatus(variant);
1378
+ const hint = this.getRecoveryHint(variant);
1379
+ console.log(chalk.gray(` \u2022 ${prLabel} - ${label}`));
1380
+ if (appliedStatus) {
1381
+ console.log(chalk.gray(` ${appliedStatus}`));
1382
+ }
1383
+ if (hint) {
1384
+ console.log(chalk.gray(` Recovery: ${hint}`));
1385
+ }
1386
+ }
1387
+ console.log();
1388
+ }
1389
+ /**
1390
+ * Format provider variant label
1391
+ */
1392
+ formatProviderVariantLabel(result) {
1393
+ return `${result.provider} ${result.model || "default"} ${result.strategy}`;
1394
+ }
1395
+ /**
1396
+ * Format applied status
1397
+ */
1398
+ formatAppliedStatus(result) {
1399
+ if (result.applied === true) {
1400
+ return "Applied locally";
1401
+ }
1402
+ if (result.applied === false) {
1403
+ return "Apply failed";
1404
+ }
1405
+ if (result.submittedOnly) {
1406
+ return "Awaiting local apply";
1407
+ }
1408
+ return "";
1409
+ }
1410
+ /**
1411
+ * Get recovery hint
1412
+ */
1413
+ getRecoveryHint(result) {
1414
+ if (result.provider === "codex" && result.cloudTaskId) {
1415
+ return `Inspect historical task ${result.cloudTaskId}`;
1416
+ }
1417
+ if (result.provider === "cursor" || result.provider === "cursor-api") {
1418
+ return "Apply via Cursor IDE";
1419
+ }
1420
+ return void 0;
1421
+ }
1422
+ /**
1423
+ * OPTIONAL/OPT-IN: Prune old variant_results rows from the telemetry database.
1424
+ *
1425
+ * This method is intentionally separate from cleanupCompetition() and is NOT
1426
+ * called automatically. Historical telemetry has analytical value; callers
1427
+ * should only invoke this when explicitly managing disk space.
1428
+ *
1429
+ * The automatic size-triggered path (DbSizeManager) also covers variant_results,
1430
+ * so manual pruning is rarely needed. Use this when you want fine-grained control
1431
+ * over the retention window or need a dry-run estimate first.
1432
+ *
1433
+ * @param db - The variants telemetry database instance (DatabaseLike).
1434
+ * Obtain via TelemetryDatabase.getVariantsDb() or equivalent.
1435
+ * If undefined, the method is a no-op and returns zero deleted rows.
1436
+ * @param options - Pruning configuration (retentionDays, verbose, dryRun).
1437
+ * @returns Summary of what was (or would be) deleted.
1438
+ *
1439
+ * @example
1440
+ * ```typescript
1441
+ * // Dry-run first to see the impact
1442
+ * const estimate = await cleanupService.pruneVariantResults(variantsDb, {
1443
+ * retentionDays: 90,
1444
+ * dryRun: true,
1445
+ * verbose: true,
1446
+ * });
1447
+ * console.log(`Would delete ${estimate.deletedRows} rows`);
1448
+ *
1449
+ * // Then execute for real
1450
+ * const result = await cleanupService.pruneVariantResults(variantsDb, {
1451
+ * retentionDays: 90,
1452
+ * });
1453
+ * ```
1454
+ */
1455
+ async pruneVariantResults(db, options = {}) {
1456
+ const { retentionDays = 90, verbose = false, dryRun = false } = options;
1457
+ const cutoff = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1e3);
1458
+ const cutoffTimestamp = cutoff.toISOString();
1459
+ if (!db) {
1460
+ if (verbose) {
1461
+ console.log(
1462
+ chalk.gray("[CleanupService] pruneVariantResults: no database provided, skipping")
1463
+ );
1464
+ }
1465
+ return { deletedRows: 0, cutoffTimestamp, dryRun };
1466
+ }
1467
+ if (verbose) {
1468
+ console.log(
1469
+ chalk.gray(
1470
+ `[CleanupService] pruneVariantResults: targeting rows with completed_at < ${cutoffTimestamp} (retention: ${retentionDays}d)${dryRun ? " [DRY RUN]" : ""}`
1471
+ )
1472
+ );
1473
+ }
1474
+ try {
1475
+ if (dryRun) {
1476
+ const countStmt = db.prepare(
1477
+ "SELECT COUNT(*) as count FROM variant_results WHERE completed_at < ? AND completed_at IS NOT NULL"
1478
+ );
1479
+ const row = countStmt.get(cutoffTimestamp);
1480
+ const deletedRows2 = row?.count ?? 0;
1481
+ if (verbose) {
1482
+ console.log(
1483
+ chalk.gray(
1484
+ `[CleanupService] pruneVariantResults: dry-run \u2014 would delete ${deletedRows2} row(s)`
1485
+ )
1486
+ );
1487
+ }
1488
+ return { deletedRows: deletedRows2, cutoffTimestamp, dryRun: true };
1489
+ }
1490
+ const deleteStmt = db.prepare(
1491
+ "DELETE FROM variant_results WHERE completed_at < ? AND completed_at IS NOT NULL"
1492
+ );
1493
+ const result = deleteStmt.run(cutoffTimestamp);
1494
+ const deletedRows = result.changes ?? 0;
1495
+ if (verbose) {
1496
+ console.log(
1497
+ chalk.gray(
1498
+ `[CleanupService] pruneVariantResults: deleted ${deletedRows} row(s) older than ${cutoffTimestamp}`
1499
+ )
1500
+ );
1501
+ }
1502
+ return { deletedRows, cutoffTimestamp, dryRun: false };
1503
+ } catch (error) {
1504
+ const msg = error instanceof Error ? error.message : String(error);
1505
+ console.warn(`[CleanupService] pruneVariantResults failed: ${msg}`);
1506
+ return { deletedRows: 0, cutoffTimestamp, dryRun };
1507
+ }
1508
+ }
1509
+ /**
1510
+ * Cleanup orphan branches by task ID
1511
+ */
1512
+ async cleanupOrphanBranchesByTask(taskId, winner) {
1513
+ try {
1514
+ const { execa: execa2 } = await import("execa");
1515
+ const result = await execa2("git", ["branch", "--list", `*${taskId}*`], {
1516
+ stdio: "pipe"
1517
+ });
1518
+ const branches = result.stdout.split("\n").map((b) => b.trim().replace(/^\*\s*/, "")).filter((b) => b.length > 0);
1519
+ let deletedCount = 0;
1520
+ let winnerBranch = "";
1521
+ if (winner.prNumber) {
1522
+ try {
1523
+ winnerBranch = await this.prManager.getPRBranch(winner.prNumber);
1524
+ } catch (error) {
1525
+ const msg = error instanceof Error ? error.message : String(error);
1526
+ console.warn(
1527
+ `[CleanupService] Skipping orphan branch cleanup for task ${taskId}: failed to resolve winner branch for PR #${winner.prNumber}: ${msg}`
1528
+ );
1529
+ return 0;
1530
+ }
1531
+ } else {
1532
+ console.warn(
1533
+ `[CleanupService] Skipping orphan branch cleanup for task ${taskId}: winner has no PR number, cannot identify winning branch`
1534
+ );
1535
+ return 0;
1536
+ }
1537
+ for (const branch of branches) {
1538
+ if (branch === winnerBranch) {
1539
+ continue;
1540
+ }
1541
+ if (!isPoeticOwnedBranch(branch)) {
1542
+ continue;
1543
+ }
1544
+ if (isProtectedPipelineBranch(branch)) {
1545
+ continue;
1546
+ }
1547
+ try {
1548
+ await this.prManager.deleteBranch(branch, { force: true });
1549
+ deletedCount++;
1550
+ } catch (_error) {
1551
+ }
1552
+ }
1553
+ return deletedCount;
1554
+ } catch (_error) {
1555
+ return 0;
1556
+ }
1557
+ }
1558
+ };
1559
+
1560
+ // src/orchestrator/services/judge-display-service.ts
1561
+ import chalk2 from "chalk";
1562
+ var JudgeDisplayService = class {
1563
+ verbosity;
1564
+ showRationale;
1565
+ streaming;
1566
+ resultStreamer;
1567
+ judgeProgressHandler;
1568
+ liveScoringHandler;
1569
+ judgeEvaluatedHandler;
1570
+ judgeWinnerSelectedHandler;
1571
+ constructor(options = {}) {
1572
+ this.verbosity = options.verbosity ?? "normal";
1573
+ this.showRationale = options.showRationale ?? false;
1574
+ this.streaming = options.streaming ?? false;
1575
+ }
1576
+ /**
1577
+ * Set result streamer for real-time updates
1578
+ */
1579
+ setResultStreamer(streamer) {
1580
+ this.resultStreamer = streamer;
1581
+ }
1582
+ /**
1583
+ * Setup judge streaming listeners for a task
1584
+ * @returns Cleanup function to remove listeners
1585
+ */
1586
+ setupStreamingListeners(taskId) {
1587
+ if (!this.resultStreamer || !this.streaming) return () => {
1588
+ };
1589
+ this.removeStreamingListeners();
1590
+ this.judgeProgressHandler = (event) => {
1591
+ if (event.taskId === taskId) {
1592
+ this.displayJudgeProgress(event);
1593
+ }
1594
+ };
1595
+ this.liveScoringHandler = (event) => {
1596
+ if (event.taskId === taskId) {
1597
+ this.displayLiveScoring(event);
1598
+ }
1599
+ };
1600
+ this.judgeEvaluatedHandler = (event) => {
1601
+ if (event.taskId === taskId) {
1602
+ this.displayJudgeEvaluation(event);
1603
+ }
1604
+ };
1605
+ this.judgeWinnerSelectedHandler = (event) => {
1606
+ if (event.taskId === taskId) {
1607
+ this.displayWinnerSelection(event);
1608
+ }
1609
+ };
1610
+ this.resultStreamer.on("judgeProgress", this.judgeProgressHandler);
1611
+ this.resultStreamer.on("liveScoring", this.liveScoringHandler);
1612
+ this.resultStreamer.on("judgeEvaluated", this.judgeEvaluatedHandler);
1613
+ this.resultStreamer.on("judgeWinnerSelected", this.judgeWinnerSelectedHandler);
1614
+ return () => this.removeStreamingListeners();
1615
+ }
1616
+ /**
1617
+ * Remove all streaming listeners
1618
+ */
1619
+ removeStreamingListeners() {
1620
+ if (!this.resultStreamer) return;
1621
+ if (this.judgeProgressHandler) {
1622
+ this.resultStreamer.removeListener("judgeProgress", this.judgeProgressHandler);
1623
+ this.judgeProgressHandler = void 0;
1624
+ }
1625
+ if (this.liveScoringHandler) {
1626
+ this.resultStreamer.removeListener("liveScoring", this.liveScoringHandler);
1627
+ this.liveScoringHandler = void 0;
1628
+ }
1629
+ if (this.judgeEvaluatedHandler) {
1630
+ this.resultStreamer.removeListener("judgeEvaluated", this.judgeEvaluatedHandler);
1631
+ this.judgeEvaluatedHandler = void 0;
1632
+ }
1633
+ if (this.judgeWinnerSelectedHandler) {
1634
+ this.resultStreamer.removeListener("judgeWinnerSelected", this.judgeWinnerSelectedHandler);
1635
+ this.judgeWinnerSelectedHandler = void 0;
1636
+ }
1637
+ }
1638
+ /**
1639
+ * Display AI Judge evaluation results
1640
+ *
1641
+ * @param evaluation - The judge synthesis result to display
1642
+ * @param variantResultsMap - Optional map of variant name to result for analysis-mode detection
1643
+ */
1644
+ displayEvaluation(evaluation, variantResultsMap) {
1645
+ if (this.verbosity === "silent" || isQuietOutputRequested()) return;
1646
+ const summary = this.buildSummary(evaluation, variantResultsMap);
1647
+ const shouldShowDetails = this.verbosity === "detailed" || this.verbosity === "debug";
1648
+ if (!shouldShowDetails) {
1649
+ if (this.verbosity === "minimal") {
1650
+ const confidenceSuffix = summary.confidenceLabel ? ` (${summary.confidenceLabel})` : "";
1651
+ const analysisSuffix = summary.isAnalysisMode ? " [analysis mode]" : "";
1652
+ console.log(chalk2.bold(`Winner: ${summary.winner}${confidenceSuffix}${analysisSuffix}`));
1653
+ return;
1654
+ }
1655
+ console.log(chalk2.bold.cyan("\nAI Judge Result\n"));
1656
+ const analysisTag = summary.isAnalysisMode ? chalk2.yellow(" [analysis mode]") : "";
1657
+ console.log(chalk2.bold(`Winner: ${summary.winner}${analysisTag}`));
1658
+ if (summary.confidenceLabel) {
1659
+ console.log(chalk2.gray(` Confidence: ${summary.confidenceLabel}`));
1660
+ }
1661
+ if (summary.runnerUp) {
1662
+ console.log(
1663
+ chalk2.gray(
1664
+ ` Runner-up: ${summary.runnerUp}${summary.margin ? ` (margin ${summary.margin} pts)` : ""}`
1665
+ )
1666
+ );
1667
+ }
1668
+ if (summary.modelLabel) {
1669
+ console.log(chalk2.gray(` Model: ${summary.modelLabel}`));
1670
+ }
1671
+ if (summary.durationLabel) {
1672
+ console.log(chalk2.gray(` Evaluation Time: ${summary.durationLabel}`));
1673
+ }
1674
+ if (summary.reasons.length > 0) {
1675
+ console.log(chalk2.gray(` Reasons: ${summary.reasons.join(" | ")}`));
1676
+ }
1677
+ console.log();
1678
+ return;
1679
+ }
1680
+ console.log(chalk2.bold.cyan("\nAI Judge Evaluation:\n"));
1681
+ const detailedAnalysisTag = summary.isAnalysisMode ? chalk2.yellow(" [analysis mode]") : "";
1682
+ console.log(chalk2.bold(`Winner: ${summary.winner}${detailedAnalysisTag}`));
1683
+ const confidenceValue = typeof summary.confidence === "number" && Number.isFinite(summary.confidence) ? summary.confidence : 0;
1684
+ console.log(chalk2.gray(` Confidence: ${confidenceValue}%`));
1685
+ if (summary.modelLabel) {
1686
+ console.log(chalk2.gray(` Model: ${summary.modelLabel}`));
1687
+ }
1688
+ if (summary.durationLabel) {
1689
+ console.log(chalk2.gray(` Evaluation Time: ${summary.durationLabel}
1690
+ `));
1691
+ }
1692
+ if (evaluation.reasoning && this.showRationale) {
1693
+ console.log(chalk2.bold.blue("Reasoning:"));
1694
+ console.log(chalk2.gray(` ${evaluation.reasoning}
1695
+ `));
1696
+ }
1697
+ console.log(chalk2.bold.blue("Detailed Evaluations:"));
1698
+ evaluation.evaluations.forEach((eval_, index) => {
1699
+ const isWinner = eval_.variant === evaluation.winner;
1700
+ const variantColor = isWinner ? chalk2.green : chalk2.white;
1701
+ const variantName = eval_.variant ? eval_.variant.toUpperCase() : "UNKNOWN";
1702
+ const rankingScore = getEvaluationRankingScore(eval_);
1703
+ const qualityScore = getEvaluationQualityScore(eval_);
1704
+ console.log(variantColor(`
1705
+ ${index + 1}. ${variantName}${isWinner ? " [winner]" : ""}`));
1706
+ if (rankingScore != null) {
1707
+ console.log(chalk2.gray(` Ranking Score: ${rankingScore.toFixed(1)}/100`));
1708
+ }
1709
+ if (qualityScore != null && (rankingScore == null || Math.abs(rankingScore - qualityScore) > 0.05)) {
1710
+ console.log(chalk2.gray(` Quality Score: ${qualityScore.toFixed(1)}/100`));
1711
+ }
1712
+ if (eval_.codeQuality) {
1713
+ console.log(chalk2.gray(` Correctness: ${Number(eval_.codeQuality.correctness)}/100`));
1714
+ console.log(chalk2.gray(` Readability: ${Number(eval_.codeQuality.readability)}/100`));
1715
+ console.log(
1716
+ chalk2.gray(` Maintainability: ${Number(eval_.codeQuality.maintainability)}/100`)
1717
+ );
1718
+ console.log(
1719
+ chalk2.gray(` Completeness: ${Number(eval_.codeQuality.completeness)}/100`)
1720
+ );
1721
+ }
1722
+ if (eval_.strengths && eval_.strengths.length > 0) {
1723
+ console.log(chalk2.green(" Strengths:"));
1724
+ eval_.strengths.forEach((strength) => {
1725
+ console.log(chalk2.gray(` ${strength}`));
1726
+ });
1727
+ }
1728
+ if (eval_.weaknesses && eval_.weaknesses.length > 0) {
1729
+ console.log(chalk2.yellow(" Weaknesses:"));
1730
+ eval_.weaknesses.forEach((weakness) => {
1731
+ console.log(chalk2.gray(` \u2022 ${weakness}`));
1732
+ });
1733
+ }
1734
+ });
1735
+ if (evaluation.recommendations && evaluation.recommendations.length > 0) {
1736
+ console.log(chalk2.bold.blue("\nRecommendations:"));
1737
+ evaluation.recommendations.forEach((rec, index) => {
1738
+ console.log(chalk2.gray(` ${index + 1}. ${rec}`));
1739
+ });
1740
+ }
1741
+ console.log();
1742
+ }
1743
+ /**
1744
+ * Display judge progress updates
1745
+ */
1746
+ displayJudgeProgress(event) {
1747
+ if (isQuietOutputRequested()) return;
1748
+ if (this.verbosity === "silent" || this.verbosity === "minimal") return;
1749
+ const progressBar = this.createProgressBar(event.progress, 40);
1750
+ let output = `\r${event.variant}: ${progressBar} ${event.progress.toFixed(1)}%`;
1751
+ if (event.step) {
1752
+ output += ` | ${event.step}`;
1753
+ }
1754
+ if (event.currentScore !== void 0) {
1755
+ output += ` | Score: ${event.currentScore.toFixed(1)}`;
1756
+ }
1757
+ if (event.estimatedTimeRemaining) {
1758
+ const seconds = Math.ceil(event.estimatedTimeRemaining / 1e3);
1759
+ output += ` | ETA: ${seconds}s`;
1760
+ }
1761
+ process.stdout.write(output);
1762
+ if (event.progress >= 100) {
1763
+ process.stdout.write("\n");
1764
+ }
1765
+ }
1766
+ /**
1767
+ * Display live scoring updates
1768
+ */
1769
+ displayLiveScoring(event) {
1770
+ if (isQuietOutputRequested()) return;
1771
+ if (this.verbosity === "silent" || this.verbosity === "minimal") return;
1772
+ console.log(
1773
+ chalk2.gray(` ${event.variant}: ${event.criteria} score updated to ${event.score}`)
1774
+ );
1775
+ }
1776
+ /**
1777
+ * Display judge evaluation results (streaming event)
1778
+ */
1779
+ displayJudgeEvaluation(event) {
1780
+ if (isQuietOutputRequested()) return;
1781
+ if (this.verbosity === "silent") return;
1782
+ if (this.verbosity !== "detailed" && this.verbosity !== "debug") return;
1783
+ const overall = typeof event.evaluation.rankingScore === "number" && Number.isFinite(event.evaluation.rankingScore) ? event.evaluation.rankingScore : typeof event.evaluation.compositeScore === "number" && Number.isFinite(event.evaluation.compositeScore) ? event.evaluation.compositeScore : typeof event.evaluation.overallScore === "number" && Number.isFinite(event.evaluation.overallScore) ? event.evaluation.overallScore : 0;
1784
+ const weighted = typeof event.evaluation.weightedScore === "number" && Number.isFinite(event.evaluation.weightedScore) ? event.evaluation.weightedScore : 0;
1785
+ const quality = typeof event.evaluation.qualityScore === "number" && Number.isFinite(event.evaluation.qualityScore) ? event.evaluation.qualityScore : null;
1786
+ console.log(chalk2.green(`
1787
+ ${event.variant} evaluation completed`));
1788
+ console.log(chalk2.gray(` Ranking Score: ${overall.toFixed(1)}`));
1789
+ if (quality != null && Math.abs(overall - quality) > 0.05) {
1790
+ console.log(chalk2.gray(` Quality Score: ${quality.toFixed(1)}`));
1791
+ }
1792
+ console.log(chalk2.gray(` Weighted Score: ${weighted.toFixed(1)}`));
1793
+ }
1794
+ /**
1795
+ * Display winner selection results (streaming event)
1796
+ */
1797
+ displayWinnerSelection(event) {
1798
+ if (isQuietOutputRequested()) return;
1799
+ if (this.verbosity === "silent") return;
1800
+ const winnerLabel = event.winner === "none" ? "No winner" : event.winner;
1801
+ const confidenceLabel = `${(event.confidence * 100).toFixed(1)}%`;
1802
+ if (this.verbosity === "minimal" || this.verbosity === "normal") {
1803
+ console.log(chalk2.bold.green(`
1804
+ Winner: ${winnerLabel} (${confidenceLabel})`));
1805
+ if (this.showRationale) {
1806
+ console.log(chalk2.gray(` Reason: ${event.rationale}`));
1807
+ }
1808
+ return;
1809
+ }
1810
+ console.log(chalk2.bold.green(`
1811
+ Winner Selected: ${winnerLabel}`));
1812
+ console.log(chalk2.gray(` Confidence: ${confidenceLabel}`));
1813
+ if (this.showRationale) {
1814
+ console.log(chalk2.gray(` Rationale: ${event.rationale}`));
1815
+ }
1816
+ }
1817
+ /**
1818
+ * Create a simple progress bar
1819
+ */
1820
+ createProgressBar(progress, width) {
1821
+ const filled = Math.round(progress / 100 * width);
1822
+ return "#".repeat(filled) + ".".repeat(width - filled);
1823
+ }
1824
+ buildSummary(evaluation, variantResultsMap) {
1825
+ const evaluations = Array.isArray(evaluation.evaluations) ? evaluation.evaluations : [];
1826
+ const scored = evaluations.map((item) => ({
1827
+ variant: item.variant ?? "UNKNOWN",
1828
+ score: getEvaluationRankingScoreOrZero(item, "judge-display.buildSummary"),
1829
+ primaryReason: item.primaryReason,
1830
+ strengths: item.strengths ?? []
1831
+ })).sort((a, b) => b.score - a.score);
1832
+ const winnerScore = scored.find((entry) => entry.variant === evaluation.winner)?.score;
1833
+ const runnerUp = scored.find((entry) => entry.variant !== evaluation.winner);
1834
+ const margin = typeof winnerScore === "number" && runnerUp ? (winnerScore - runnerUp.score).toFixed(1) : void 0;
1835
+ const confidence = typeof evaluation.metadata.confidence === "number" && Number.isFinite(evaluation.metadata.confidence) ? evaluation.metadata.confidence : void 0;
1836
+ const durationLabel = evaluation.metadata.evaluationTimeMs < 1e3 ? `${evaluation.metadata.evaluationTimeMs}ms` : `${(evaluation.metadata.evaluationTimeMs / 1e3).toFixed(1)}s`;
1837
+ const reasons = [];
1838
+ if (evaluation.winnerPrimaryReason) {
1839
+ reasons.push(evaluation.winnerPrimaryReason);
1840
+ }
1841
+ const winnerReason = scored.find((entry) => entry.variant === evaluation.winner);
1842
+ if (winnerReason?.primaryReason) {
1843
+ reasons.push(winnerReason.primaryReason);
1844
+ }
1845
+ if (winnerReason?.strengths && reasons.length < 2) {
1846
+ reasons.push(...winnerReason.strengths.slice(0, 2 - reasons.length));
1847
+ }
1848
+ let isAnalysisMode = false;
1849
+ if (variantResultsMap && evaluation.winner) {
1850
+ const winnerResult = variantResultsMap.get(evaluation.winner);
1851
+ if (winnerResult) {
1852
+ const executionCategory = winnerResult.executionCategory;
1853
+ const editMode = winnerResult.completenessScore?.editMode;
1854
+ isAnalysisMode = executionCategory === "analysis" || editMode === "analysis" || winnerResult.executionIntent === "analysis";
1855
+ }
1856
+ }
1857
+ return {
1858
+ winner: evaluation.winner ?? "none",
1859
+ runnerUp: runnerUp?.variant,
1860
+ margin,
1861
+ confidence,
1862
+ confidenceLabel: confidence !== void 0 ? `${confidence.toFixed(1)}%` : void 0,
1863
+ modelLabel: evaluation.metadata.model,
1864
+ durationLabel,
1865
+ reasons: reasons.slice(0, 2),
1866
+ isAnalysisMode
1867
+ };
1868
+ }
1869
+ };
1870
+
1871
+ // src/orchestrator/pr-workflow-coordinator-impl-core.ts
1872
+ var SynthesisWinnerRestorationError = class extends Error {
1873
+ constructor(message) {
1874
+ super(message);
1875
+ this.name = "SynthesisWinnerRestorationError";
1876
+ }
1877
+ };
1878
+ var CompetitionTimeoutFailure = class extends CompetitionTimeoutError {
1879
+ observedResults;
1880
+ drain;
1881
+ /** True only when the execution cohort joined within the drain bound. */
1882
+ cleanupJoined;
1883
+ constructor(args) {
1884
+ super(args.timeoutMs, args.completedVariants, args.totalVariants);
1885
+ this.observedResults = sealVariantResultSnapshot(args.observedResults);
1886
+ this.drain = args.drain;
1887
+ this.cleanupJoined = args.drain.joined;
1888
+ }
1889
+ };
1890
+ async function awaitBoundedCohortDrain(cohortPromise, drainMs = WORKER_EXIT_DRAIN_MS) {
1891
+ const startedAt = Date.now();
1892
+ let joined = false;
1893
+ let drainTimer;
1894
+ try {
1895
+ await Promise.race([
1896
+ Promise.resolve(cohortPromise).then(
1897
+ () => {
1898
+ joined = true;
1899
+ },
1900
+ () => {
1901
+ joined = true;
1902
+ }
1903
+ ),
1904
+ new Promise((resolve) => {
1905
+ drainTimer = setTimeout(resolve, drainMs);
1906
+ })
1907
+ ]);
1908
+ } finally {
1909
+ if (drainTimer) {
1910
+ clearTimeout(drainTimer);
1911
+ }
1912
+ }
1913
+ return {
1914
+ joined,
1915
+ awaitedMs: Date.now() - startedAt,
1916
+ pendingAtDeadline: joined ? 0 : 1,
1917
+ settledCount: joined ? 1 : 0,
1918
+ aborted: false
1919
+ };
1920
+ }
1921
+ function markSynthesisWinnerFallback(mergedResult, fallbackReason, winner, applyError) {
1922
+ mergedResult.deliverySucceeded = true;
1923
+ mergedResult.synthesisApplied = false;
1924
+ mergedResult.winnerFallback = true;
1925
+ mergedResult.fallbackReason = fallbackReason;
1926
+ mergedResult.patchApplyValidated = false;
1927
+ mergedResult.gatesPassed = false;
1928
+ mergedResult.winnerClone = true;
1929
+ mergedResult.noveltyScore ??= 0;
1930
+ if (winner) {
1931
+ const winnerId = formatVariantIdentifierFromResult(winner);
1932
+ mergedResult.mergedVariants = [winnerId];
1933
+ mergedResult.contributingVariants = [winnerId];
1934
+ }
1935
+ if (mergedResult.aiGuidedFallbackAttempted === true) {
1936
+ if (applyError) {
1937
+ mergedResult.aiGuidedFallbackOutcome = "candidate_rejected";
1938
+ } else if (mergedResult.aiGuidedFallbackOutcome !== "generation_failed") {
1939
+ mergedResult.aiGuidedFallbackOutcome = "winner_equivalent";
1940
+ }
1941
+ }
1942
+ if (applyError) {
1943
+ mergedResult.applyError = applyError;
1944
+ mergedResult.error ??= applyError;
1945
+ }
1946
+ if (!mergedResult.synthesisOutcomeStatus || mergedResult.synthesisOutcomeStatus === "applied") {
1947
+ mergedResult.synthesisOutcomeStatus = applyError ? "gate_failed" : "winner_carry_forward";
1948
+ }
1949
+ }
1950
+ function markTypecheckOnlySynthesisFallback(mergedResult, winner, detail) {
1951
+ const fallbackReason = detail ? `Synthesis passed legacy typecheck-only validation, but full deterministic gates were not run; winner-only result retained (${detail})` : "Synthesis passed legacy typecheck-only validation, but full deterministic gates were not run; winner-only result retained";
1952
+ markSynthesisWinnerFallback(mergedResult, fallbackReason, winner);
1953
+ mergedResult.validationScope = "typecheck-only";
1954
+ }
1955
+ async function cleanupAgenticSynthesisWorktree(synthesisWorktree, preserveWorktrees) {
1956
+ if (preserveWorktrees || !synthesisWorktree.trim()) return;
1957
+ const worktreeAvailable = await fs.access(synthesisWorktree).then(() => true).catch(() => false);
1958
+ if (!worktreeAvailable) return;
1959
+ const repoRootResult = await execa("git", ["rev-parse", "--show-toplevel"], {
1960
+ cwd: synthesisWorktree,
1961
+ reject: false
1962
+ });
1963
+ await execa("git", ["worktree", "remove", synthesisWorktree, "--force"], {
1964
+ cwd: repoRootResult.stdout.trim() || process.cwd(),
1965
+ reject: false
1966
+ });
1967
+ await fs.rm(synthesisWorktree, { recursive: true, force: true }).catch(() => {
1968
+ });
1969
+ }
1970
+ function resolveSynthesisVerifyCommands(worktreePath) {
1971
+ try {
1972
+ const capabilities = detectProjectCapabilities(worktreePath);
1973
+ const guidance = buildProjectVerificationGuidance(worktreePath);
1974
+ const derived = [];
1975
+ for (const command of guidance.commands) {
1976
+ if (command.kind === "typecheck" || command.kind === "build") {
1977
+ derived.push(command.command);
1978
+ }
1979
+ }
1980
+ const deduped = [...new Set(derived)];
1981
+ if (deduped.length > 0) {
1982
+ return { available: true, commands: deduped };
1983
+ }
1984
+ if (hasProjectLanguage(capabilities, "typescript") && capabilities.manifests?.tsconfig) {
1985
+ return { available: true, commands: ["npx --no-install tsc --noEmit"] };
1986
+ }
1987
+ return { available: false, commands: [] };
1988
+ } catch {
1989
+ return { available: false, commands: [] };
1990
+ }
1991
+ }
1992
+ function shouldSelectCompetitionWinner(input) {
1993
+ return input.total > 0 && input.completed > 0 && !(input.judgeOff && input.total > 1);
1994
+ }
1995
+ var PRWorkflowOrchestrator = class {
1996
+ prManager;
1997
+ localExecutor;
1998
+ variantOrchestrator;
1999
+ verbose;
2000
+ orchestratorTimeoutMs;
2001
+ orchestratorDeadlineMs;
2002
+ executorTimeoutMs;
2003
+ cleanupOnCompletion;
2004
+ localFastMode;
2005
+ pushLocalVariants;
2006
+ preserveWorktrees;
2007
+ aiJudge;
2008
+ judgeOff;
2009
+ aiJudgeModel;
2010
+ aiJudgeVerbose;
2011
+ aiJudgeShowRationale;
2012
+ aiJudgeVerbosity;
2013
+ aiJudgeCriteriaWeights;
2014
+ aiJudgeMinScore;
2015
+ aiJudgeConfidenceThreshold;
2016
+ aiJudgeStreaming;
2017
+ aiJudgeTelemetry;
2018
+ aiJudgeRun;
2019
+ aiJudgePrimary;
2020
+ judgeModels;
2021
+ judgeModel;
2022
+ judgeAllowUnsafeModel;
2023
+ judgeStrict;
2024
+ anonymizeJudge;
2025
+ verificationMode;
2026
+ synthesize;
2027
+ synthesisTopN;
2028
+ synthesisStrategy;
2029
+ synthesisModel;
2030
+ resultStreamer;
2031
+ processLifecycle;
2032
+ ownsProcessLifecycle;
2033
+ enableAutoTuning;
2034
+ enablePromptOptimization;
2035
+ costTracker;
2036
+ workspaceAgentRunner;
2037
+ outputValidator;
2038
+ branchListCache;
2039
+ BRANCH_LIST_CACHE_TTL_MS = 60 * 1e3;
2040
+ // 60 seconds
2041
+ cleanupService;
2042
+ judgeDisplayService;
2043
+ judgeListenerCleanup;
2044
+ ownsResultStreamer;
2045
+ repoRoot;
2046
+ // Dependency-aware execution (experimental)
2047
+ flywheel;
2048
+ taskDependencies;
2049
+ globalMaxConcurrent;
2050
+ sharedVariantResourceManager;
2051
+ dependencyResolver;
2052
+ resourceManager;
2053
+ constructor(options = {}) {
2054
+ this.repoRoot = findProjectRoot(process.cwd()) ?? process.cwd();
2055
+ const verbosityLevel = validateVerbosity(options.verbose);
2056
+ this.verbose = verbosityLevel === "detailed" || verbosityLevel === "debug";
2057
+ this.localFastMode = options.localFast ?? false;
2058
+ this.pushLocalVariants = options.noPush === true ? false : options.pushLocalVariants ?? getRuntimeEnv("POETIC_PUSH_VARIANTS") === "1";
2059
+ this.cleanupOnCompletion = (options.cleanupOnCompletion ?? true) && !this.localFastMode;
2060
+ this.preserveWorktrees = options.preserveWorktrees ?? getRuntimeEnv("POETIC_PRESERVE_WORKTREES") === "1";
2061
+ this.aiJudge = options.aiJudge ?? true;
2062
+ this.judgeOff = options.judgeOff ?? false;
2063
+ this.aiJudgeModel = options.aiJudgeModel;
2064
+ this.aiJudgeShowRationale = options.aiJudgeShowRationale ?? false;
2065
+ this.aiJudgeRun = options.aiJudgeRun;
2066
+ this.aiJudgePrimary = options.aiJudgePrimary;
2067
+ this.judgeModels = options.judgeModels;
2068
+ this.judgeModel = options.judgeModel;
2069
+ this.judgeAllowUnsafeModel = options.judgeAllowUnsafeModel;
2070
+ this.judgeStrict = options.judgeStrict ?? false;
2071
+ this.anonymizeJudge = options.anonymizeJudge;
2072
+ this.aiJudgeVerbosity = validateVerbosity(void 0, options.aiJudgeVerbosity);
2073
+ this.aiJudgeVerbose = this.aiJudgeVerbosity === "detailed" || this.aiJudgeVerbosity === "debug";
2074
+ this.aiJudgeCriteriaWeights = options.aiJudgeCriteriaWeights;
2075
+ if (options.aiJudgeMinScore !== void 0) {
2076
+ this.aiJudgeMinScore = validatePercentage(options.aiJudgeMinScore, "aiJudgeMinScore", {
2077
+ min: 0,
2078
+ max: 100,
2079
+ allowFractional: false
2080
+ });
2081
+ } else {
2082
+ this.aiJudgeMinScore = void 0;
2083
+ }
2084
+ if (options.aiJudgeConfidenceThreshold !== void 0) {
2085
+ this.aiJudgeConfidenceThreshold = validateConfidence(options.aiJudgeConfidenceThreshold, {
2086
+ fieldName: "aiJudgeConfidenceThreshold"
2087
+ });
2088
+ } else {
2089
+ this.aiJudgeConfidenceThreshold = void 0;
2090
+ }
2091
+ this.aiJudgeStreaming = options.aiJudgeStreaming;
2092
+ this.aiJudgeTelemetry = options.aiJudgeTelemetry ?? true;
2093
+ this.verificationMode = options.verificationMode ?? "auto";
2094
+ this.synthesize = options.synthesize ?? true;
2095
+ this.synthesisTopN = options.synthesisTopN ?? 2;
2096
+ this.synthesisStrategy = options.synthesisStrategy ?? "agentic-synthesis";
2097
+ this.synthesisModel = options.synthesisModel ?? resolveSynthesisModel().value;
2098
+ this.enableAutoTuning = options.enableAutoTuning ?? false;
2099
+ this.enablePromptOptimization = options.enablePromptOptimization ?? true;
2100
+ this.resultStreamer = options.resultStreamer;
2101
+ this.ownsResultStreamer = !options.resultStreamer;
2102
+ this.branchListCache = /* @__PURE__ */ new Map();
2103
+ this.flywheel = options.flywheel ?? false;
2104
+ this.taskDependencies = options.taskDependencies;
2105
+ this.globalMaxConcurrent = Math.max(
2106
+ 1,
2107
+ resolveLocalWorktreeConcurrency(options.globalMaxConcurrent, void 0)
2108
+ );
2109
+ this.sharedVariantResourceManager = options.sharedVariantResourceManager;
2110
+ if (this.flywheel) {
2111
+ this.dependencyResolver = new DependencyGraphResolver();
2112
+ this.resourceManager = new ProviderAwareResourceManager({
2113
+ globalMaxConcurrent: this.globalMaxConcurrent,
2114
+ fairnessMode: "weighted-fair",
2115
+ enableTelemetry: true
2116
+ });
2117
+ if (this.taskDependencies) {
2118
+ const graph = this.dependencyResolver.buildGraph(this.taskDependencies);
2119
+ const validation = this.dependencyResolver.validateGraph(graph);
2120
+ if (!validation.valid) {
2121
+ throw new Error(`Invalid task dependencies: ${validation.errors.join(", ")}`);
2122
+ }
2123
+ if (validation.warnings && validation.warnings.length > 0 && this.verbose) {
2124
+ emitWarning(
2125
+ "CFG-002",
2126
+ {
2127
+ taskId: "unknown",
2128
+ subsystem: "orchestrator",
2129
+ executionPhase: "setup"
2130
+ },
2131
+ {
2132
+ severity: "INFO" /* INFO */,
2133
+ metadata: {
2134
+ operation: "validateDependencyGraph",
2135
+ warnings: validation.warnings
2136
+ }
2137
+ }
2138
+ );
2139
+ }
2140
+ }
2141
+ }
2142
+ this.executorTimeoutMs = validateTimeout(options.executorTimeoutMinutes, "minutes", {
2143
+ defaultMs: 45 * 60 * 1e3,
2144
+ // 45 minutes default
2145
+ minMs: 1 * 60 * 1e3,
2146
+ // 1 minute minimum
2147
+ maxMs: MAX_PER_VARIANT_TIMEOUT_MINUTES * 60 * 1e3,
2148
+ fieldName: "executorTimeoutMinutes"
2149
+ });
2150
+ this.orchestratorTimeoutMs = validateTimeout(options.timeoutMinutes, "minutes", {
2151
+ defaultMs: 90 * 60 * 1e3,
2152
+ // 90 minutes default
2153
+ minMs: 1 * 60 * 1e3,
2154
+ // 1 minute minimum
2155
+ maxMs: 1440 * 60 * 1e3,
2156
+ // 24 hours maximum
2157
+ fieldName: "timeoutMinutes"
2158
+ });
2159
+ if (this.orchestratorTimeoutMs < this.executorTimeoutMs) {
2160
+ const originalOrchestratorMin = this.orchestratorTimeoutMs / 6e4;
2161
+ const executorMin = this.executorTimeoutMs / 6e4;
2162
+ emitWarning(
2163
+ "CFG-002",
2164
+ {
2165
+ taskId: "unknown",
2166
+ subsystem: "orchestrator",
2167
+ executionPhase: "setup"
2168
+ },
2169
+ {
2170
+ severity: "WARN" /* WARN */,
2171
+ metadata: {
2172
+ operation: "validateTimeouts",
2173
+ originalOrchestratorTimeoutMin: originalOrchestratorMin,
2174
+ executorTimeoutMin: executorMin,
2175
+ adjustedOrchestratorTimeoutMin: executorMin,
2176
+ reason: "Orchestrator timeout must be >= executor timeout to prevent premature termination",
2177
+ suggestedFix: `Set --timeout ${Math.ceil(executorMin)} (or higher) to avoid auto-adjustment`
2178
+ }
2179
+ }
2180
+ );
2181
+ console.warn(
2182
+ `
2183
+ Timeout Auto-Adjustment:
2184
+ Orchestrator timeout (${originalOrchestratorMin} min) was less than executor timeout (${executorMin} min).
2185
+ Auto-adjusted orchestrator timeout to ${executorMin} min to prevent premature termination.
2186
+
2187
+ To configure properly:
2188
+ - Set orchestrator timeout: --timeout ${Math.ceil(executorMin)} (or higher)
2189
+ - Or reduce executor timeout: --executor-timeout ${Math.floor(originalOrchestratorMin)}
2190
+ `
2191
+ );
2192
+ this.orchestratorTimeoutMs = this.executorTimeoutMs;
2193
+ }
2194
+ if (options.deadlineMs !== void 0) {
2195
+ if (!Number.isFinite(options.deadlineMs)) {
2196
+ throw new Error(`deadlineMs must be a finite timestamp, got: ${options.deadlineMs}`);
2197
+ }
2198
+ this.orchestratorDeadlineMs = options.deadlineMs;
2199
+ this.orchestratorTimeoutMs = this.resolveRemainingOrchestratorTimeoutMs();
2200
+ this.executorTimeoutMs = Math.min(this.executorTimeoutMs, this.orchestratorTimeoutMs);
2201
+ }
2202
+ this.prManager = new GitHubPRManager();
2203
+ this.workspaceAgentRunner = new WorkspaceAgentRunner();
2204
+ this.outputValidator = new UniversalOutputValidator();
2205
+ try {
2206
+ const costCalculator = new UniversalCostCalculator(TelemetryLogger.getInstance());
2207
+ this.costTracker = new UnifiedCostTracker(costCalculator, TelemetryLogger.getInstance(), {
2208
+ enabled: true,
2209
+ budgetThresholds: {
2210
+ warning: 10,
2211
+ critical: 50,
2212
+ daily: 100,
2213
+ monthly: 1e3
2214
+ },
2215
+ optimization: {
2216
+ enableSuggestions: false,
2217
+ // Disable suggestions for now
2218
+ minSavingsThreshold: 1,
2219
+ maxSuggestionsPerHour: 5
2220
+ },
2221
+ updateIntervalMs: 3e4
2222
+ // 30 seconds
2223
+ });
2224
+ } catch (error) {
2225
+ if (this.verbose) {
2226
+ emitWarning(
2227
+ "CFG-002",
2228
+ {
2229
+ taskId: "unknown",
2230
+ subsystem: "orchestrator",
2231
+ executionPhase: "setup"
2232
+ },
2233
+ {
2234
+ severity: "WARN" /* WARN */,
2235
+ metadata: {
2236
+ error: error instanceof Error ? error.message : String(error),
2237
+ operation: "costTrackingInit"
2238
+ }
2239
+ }
2240
+ );
2241
+ }
2242
+ }
2243
+ this.localExecutor = new LocalExecutor({
2244
+ prManager: this.prManager,
2245
+ verbose: this.verbose,
2246
+ executorTimeoutMs: this.executorTimeoutMs,
2247
+ costTracker: this.costTracker,
2248
+ workspaceAgentRunner: this.workspaceAgentRunner,
2249
+ outputValidator: this.outputValidator,
2250
+ preserveWorktrees: this.preserveWorktrees,
2251
+ resultStreamer: this.resultStreamer
2252
+ });
2253
+ this.variantOrchestrator = new VariantOrchestrator();
2254
+ const existingProcessLifecycle = getProcessLifecycleManager();
2255
+ if (existingProcessLifecycle instanceof ProcessLifecycleManager) {
2256
+ this.processLifecycle = existingProcessLifecycle;
2257
+ this.ownsProcessLifecycle = false;
2258
+ } else {
2259
+ this.processLifecycle = new ProcessLifecycleManager({
2260
+ verbose: this.verbose,
2261
+ defaultTimeoutMinutes: options.executorTimeoutMinutes ?? 45,
2262
+ maxConcurrentProcesses: 50,
2263
+ cleanupOnTermination: true
2264
+ });
2265
+ setProcessLifecycleManager(this.processLifecycle);
2266
+ this.ownsProcessLifecycle = true;
2267
+ }
2268
+ this.cleanupService = new CleanupService(
2269
+ this.prManager,
2270
+ this.verbose,
2271
+ {
2272
+ cleanup: (worktreePath) => this.localExecutor.releaseWorktreeForBranchCleanup(worktreePath)
2273
+ },
2274
+ this.repoRoot
2275
+ );
2276
+ this.judgeDisplayService = new JudgeDisplayService({
2277
+ verbosity: this.aiJudgeVerbosity,
2278
+ showRationale: this.aiJudgeShowRationale,
2279
+ streaming: this.aiJudgeStreaming
2280
+ });
2281
+ }
2282
+ async executeLocalVariant(taskId, variant, prompt, retryMeta, abortSignal) {
2283
+ if (this.pushLocalVariants) {
2284
+ return this.localExecutor.executeVariantWithRetry(taskId, variant, prompt, {
2285
+ iterationIndex: retryMeta?.iterationIndex ?? 0,
2286
+ abortSignal
2287
+ });
2288
+ }
2289
+ const outcome = await this.localExecutor.executeVariantFastWithRetry(taskId, variant, prompt, {
2290
+ commit: false,
2291
+ cleanup: false,
2292
+ iterationIndex: retryMeta?.iterationIndex ?? 0,
2293
+ abortSignal
2294
+ });
2295
+ return outcome.result;
2296
+ }
2297
+ resolveRemainingOrchestratorTimeoutMs() {
2298
+ if (this.orchestratorDeadlineMs === void 0) {
2299
+ return this.orchestratorTimeoutMs;
2300
+ }
2301
+ const remainingDeadlineMs = this.orchestratorDeadlineMs - Date.now();
2302
+ if (remainingDeadlineMs <= 0) {
2303
+ throw new Error("deadlineMs must be in the future");
2304
+ }
2305
+ return Math.min(this.orchestratorTimeoutMs, remainingDeadlineMs);
2306
+ }
2307
+ /**
2308
+ * Execute all variants in competition
2309
+ * Returns results for all variants
2310
+ */
2311
+ async executeVariants(taskId, prompt, variants, retryMeta) {
2312
+ const observedResults = [];
2313
+ try {
2314
+ initEvaluationHandle(taskId, prompt, variants);
2315
+ } catch (handleError) {
2316
+ console.warn(
2317
+ `Failed to initialize competition handle for task ${taskId}: ${handleError instanceof Error ? handleError.message : String(handleError)}`
2318
+ );
2319
+ debugLog("Full stack:", handleError);
2320
+ }
2321
+ this.orchestratorTimeoutMs = this.resolveRemainingOrchestratorTimeoutMs();
2322
+ const outerController = new AbortController();
2323
+ let timeoutHandle;
2324
+ let timedOut = false;
2325
+ const timeoutPromise = new Promise((_, reject) => {
2326
+ timeoutHandle = setTimeout(() => {
2327
+ timedOut = true;
2328
+ outerController.abort(
2329
+ new Error(`Orchestrator timeout after ${this.orchestratorTimeoutMs / 6e4} minutes`)
2330
+ );
2331
+ reject(
2332
+ new Error(`Orchestrator timeout after ${this.orchestratorTimeoutMs / 6e4} minutes`)
2333
+ );
2334
+ }, this.orchestratorTimeoutMs);
2335
+ });
2336
+ let finalResult = null;
2337
+ let finalError;
2338
+ let lastDrain;
2339
+ const cohortPromise = this.executeVariantsInternal(
2340
+ taskId,
2341
+ prompt,
2342
+ variants,
2343
+ retryMeta,
2344
+ observedResults,
2345
+ outerController.signal
2346
+ );
2347
+ try {
2348
+ finalResult = await Promise.race([cohortPromise, timeoutPromise]);
2349
+ if (timeoutHandle) {
2350
+ clearTimeout(timeoutHandle);
2351
+ timeoutHandle = void 0;
2352
+ }
2353
+ try {
2354
+ await this.close();
2355
+ } catch (cleanupErr) {
2356
+ console.warn(
2357
+ `Cleanup error (post-success): ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`
2358
+ );
2359
+ }
2360
+ return finalResult;
2361
+ } catch (error) {
2362
+ if (timedOut || error instanceof Error && error.message.includes("Orchestrator timeout")) {
2363
+ const sealedResults = sealVariantResultSnapshot(observedResults);
2364
+ const completedCount = countCompletedCompetitionObservations(sealedResults);
2365
+ lastDrain = await awaitBoundedCohortDrain(cohortPromise);
2366
+ const timeoutFailure = new CompetitionTimeoutFailure({
2367
+ timeoutMs: this.orchestratorTimeoutMs,
2368
+ completedVariants: completedCount,
2369
+ totalVariants: variants.length,
2370
+ observedResults: sealedResults,
2371
+ drain: lastDrain
2372
+ });
2373
+ finalError = timeoutFailure;
2374
+ console.log(chalk3.yellow(`
2375
+ ${timeoutFailure.message}`));
2376
+ if (completedCount === 0) {
2377
+ console.log(chalk3.red("Timeout occurred before any variants completed\n"));
2378
+ } else {
2379
+ console.log(
2380
+ chalk3.red(
2381
+ `Timeout after ${completedCount}/${variants.length} variants completed` + (lastDrain.joined ? "" : " (cleanup did not fully join within drain bound)") + "\n"
2382
+ )
2383
+ );
2384
+ }
2385
+ try {
2386
+ await this.close();
2387
+ } catch (cleanupErr) {
2388
+ console.warn(
2389
+ `Cleanup error: ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`
2390
+ );
2391
+ debugLog("Full cleanup error:", cleanupErr);
2392
+ }
2393
+ throw timeoutFailure;
2394
+ }
2395
+ finalError = error;
2396
+ try {
2397
+ await this.close();
2398
+ } catch (cleanupErr) {
2399
+ console.warn(
2400
+ `Cleanup error: ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`
2401
+ );
2402
+ debugLog("Full cleanup error:", cleanupErr);
2403
+ emitWarning(
2404
+ "PR-001",
2405
+ {
2406
+ taskId,
2407
+ subsystem: "orchestrator",
2408
+ executionPhase: "cleanup"
2409
+ },
2410
+ {
2411
+ severity: "WARN" /* WARN */,
2412
+ metadata: {
2413
+ error: cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr),
2414
+ operation: "cleanup"
2415
+ }
2416
+ }
2417
+ );
2418
+ }
2419
+ throw error;
2420
+ } finally {
2421
+ if (timeoutHandle) {
2422
+ clearTimeout(timeoutHandle);
2423
+ }
2424
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
2425
+ if (finalResult) {
2426
+ const anySuccess = finalResult.variants.some((variant) => variant.success);
2427
+ const ungradedIdentity = this.judgeOff && finalResult.variants.length === 1 && finalResult.winner !== null;
2428
+ const decision = this.judgeOff ? {
2429
+ outcome: "none",
2430
+ reason: "judge_off",
2431
+ decisionStatus: "not_run",
2432
+ decisionOutcome: "no_judge",
2433
+ primaryJudge: "n/a"
2434
+ } : void 0;
2435
+ const finalState = ungradedIdentity ? createEvaluationHandleFinalState({
2436
+ outcome: "no_winner",
2437
+ completedAt,
2438
+ winner: null,
2439
+ decision
2440
+ }) : finalResult.winner ? createEvaluationHandleFinalState({
2441
+ outcome: "winner_selected",
2442
+ completedAt,
2443
+ winner: {
2444
+ provider: finalResult.winner.provider,
2445
+ model: finalResult.winner.model,
2446
+ strategy: finalResult.winner.strategy,
2447
+ executionMode: finalResult.winner.executionMode,
2448
+ variant: finalResult.winner.variant
2449
+ },
2450
+ decision
2451
+ }) : createEvaluationHandleFinalState({
2452
+ outcome: anySuccess ? "no_winner" : "all_failed",
2453
+ completedAt,
2454
+ winner: null,
2455
+ decision
2456
+ });
2457
+ const finalizeResult = finalizeEvaluationHandle(taskId, finalState);
2458
+ if (finalizeResult.kind === "persistence_failed" && !isDurableHandleCompletion(finalizeResult, anySuccess ? "completed" : "failed")) {
2459
+ console.warn(
2460
+ `Evaluation handle persistence failed for ${taskId}: ${finalizeResult.error}`
2461
+ );
2462
+ }
2463
+ } else if (finalError) {
2464
+ const message = finalError instanceof Error ? finalError.message : String(finalError);
2465
+ const isTimeout = finalError instanceof CompetitionTimeoutFailure || /orchestrator timeout|competition timed out/i.test(message);
2466
+ const finalizeResult = finalizeEvaluationHandle(
2467
+ taskId,
2468
+ createEvaluationHandleFinalState({
2469
+ outcome: isTimeout ? "timed_out" : "error",
2470
+ completedAt,
2471
+ errorMessage: finalError instanceof CompetitionTimeoutFailure ? `${message}; cleanupJoined=${finalError.cleanupJoined}` : message,
2472
+ winner: null
2473
+ })
2474
+ );
2475
+ if (finalizeResult.kind === "persistence_failed") {
2476
+ console.warn(
2477
+ `Evaluation handle persistence failed for ${taskId}: ${finalizeResult.error}`
2478
+ );
2479
+ }
2480
+ }
2481
+ }
2482
+ }
2483
+ /**
2484
+ * Internal method to execute all variants (without timeout wrapper)
2485
+ */
2486
+ async executeVariantsInternal(taskId, prompt, variants, retryMeta, observedResults = [], outerSignal) {
2487
+ console.log(chalk3.bold.cyan("\nPoetic Variant Competition\n"));
2488
+ console.log(chalk3.gray(`Task ID: ${taskId}`));
2489
+ console.log(chalk3.gray(`Variants: ${variants.length}`));
2490
+ console.log(chalk3.gray(`Executor timeout: ${this.executorTimeoutMs / 6e4} minutes`));
2491
+ console.log(
2492
+ chalk3.gray(
2493
+ `Orchestrator timeout: ${this.orchestratorTimeoutMs / 6e4} minutes (safety net)
2494
+ `
2495
+ )
2496
+ );
2497
+ if (this.aiJudgeStreaming) {
2498
+ const { ResultStreamer } = await import("./result-streamer-WEHW476R.js");
2499
+ if (!this.resultStreamer) {
2500
+ this.resultStreamer = new ResultStreamer();
2501
+ this.ownsResultStreamer = true;
2502
+ }
2503
+ this.localExecutor.setResultStreamer(this.resultStreamer);
2504
+ this.judgeDisplayService.setResultStreamer(this.resultStreamer);
2505
+ this.judgeListenerCleanup = this.judgeDisplayService.setupStreamingListeners(taskId);
2506
+ }
2507
+ const localVariants = variants;
2508
+ console.log(chalk3.blue("Execution Plan:"));
2509
+ console.log(chalk3.gray(` Local variants: ${localVariants.length}
2510
+ `));
2511
+ const results = [];
2512
+ if (this.flywheel && this.dependencyResolver && this.resourceManager) {
2513
+ console.log(chalk3.bold.blue("Executing Variants with Dependency Awareness\n"));
2514
+ return this.executeVariantsWithDependencies(
2515
+ taskId,
2516
+ prompt,
2517
+ variants,
2518
+ results,
2519
+ retryMeta,
2520
+ outerSignal
2521
+ );
2522
+ }
2523
+ console.log(chalk3.bold.blue("Executing All Variants in Parallel\n"));
2524
+ const allPromises = [];
2525
+ const localResourceManager = this.sharedVariantResourceManager ?? createLocalVariantResourceManager(this.globalMaxConcurrent);
2526
+ const controller = new AbortController();
2527
+ const signal = controller.signal;
2528
+ if (outerSignal) {
2529
+ if (outerSignal.aborted) {
2530
+ controller.abort(outerSignal.reason);
2531
+ } else {
2532
+ outerSignal.addEventListener("abort", () => controller.abort(outerSignal.reason), {
2533
+ once: true
2534
+ });
2535
+ }
2536
+ }
2537
+ const geminiCount = localVariants.filter((v) => v.provider === "gemini").length;
2538
+ if (geminiCount > 1 && isVerboseOutputRequested()) {
2539
+ console.log(
2540
+ chalk3.cyan(
2541
+ `Running ${geminiCount} Gemini variant(s) in parallel (HOME isolation, auto-fallback to serial on ECONNRESET)
2542
+ `
2543
+ )
2544
+ );
2545
+ }
2546
+ const localPromises = localVariants.map((variant) => {
2547
+ const variantLabel = `${variant.provider} ${variant.model || "default-model"} ${variant.strategy}`;
2548
+ return (async () => {
2549
+ let providerId;
2550
+ try {
2551
+ providerId = toConcurrencyProviderId(variant.provider);
2552
+ } catch (err) {
2553
+ const failureResult = this.buildFailureResult(variant, err, 0);
2554
+ this.logVariantCompleteSafe(taskId, variant, failureResult);
2555
+ return failureResult;
2556
+ }
2557
+ const acquisitionTimeoutMs = this.orchestratorTimeoutMs ?? 30 * 60 * 1e3;
2558
+ if (process.env.DEBUG_ORCHESTRATOR) {
2559
+ console.warn(
2560
+ `[DEBUG ORCHESTRATOR] Acquiring resource for ${providerId} (timeout: ${acquisitionTimeoutMs}ms)...`
2561
+ );
2562
+ }
2563
+ const handle = await localResourceManager.acquire(providerId, signal, acquisitionTimeoutMs);
2564
+ const startTime = Date.now();
2565
+ this.logVariantStartSafe(taskId, variant);
2566
+ console.log(chalk3.cyan(`\u2192 Starting: ${variantLabel} ${chalk3.gray("(local)")}`));
2567
+ try {
2568
+ const result = await this.executeLocalVariant(taskId, variant, prompt, retryMeta, signal);
2569
+ observedResults.push(result);
2570
+ const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
2571
+ if (result?.success) {
2572
+ console.log(
2573
+ chalk3.green(
2574
+ `${variantLabel}: Completed in ${elapsed}s (local)${result?.prNumber ? ` (PR #${result.prNumber})` : ""}
2575
+ `
2576
+ )
2577
+ );
2578
+ } else {
2579
+ console.log(
2580
+ chalk3.red(
2581
+ `${variantLabel}: Failed after ${elapsed}s - ${result?.error?.message || "Unknown error"}
2582
+ `
2583
+ )
2584
+ );
2585
+ const errorMsg = result?.error?.message?.toLowerCase() ?? "";
2586
+ if (errorMsg.includes("rate limit") || errorMsg.includes("ratelimit") || errorMsg.includes("too many requests") || matchesErrorPattern(errorMsg, "429")) {
2587
+ recordProviderRateLimit(providerId);
2588
+ }
2589
+ }
2590
+ try {
2591
+ updateEvaluationHandleWithResult(taskId, result);
2592
+ } catch (handleError) {
2593
+ console.warn(
2594
+ `Failed to update competition handle for local task ${taskId} variant ${variant.provider}-${variant.strategy}: ${handleError instanceof Error ? handleError.message : String(handleError)}`
2595
+ );
2596
+ debugLog("Full stack:", handleError);
2597
+ }
2598
+ this.logVariantCompleteSafe(taskId, variant, result);
2599
+ return result;
2600
+ } catch (error) {
2601
+ const elapsedSeconds = (Date.now() - startTime) / 1e3;
2602
+ const elapsed = elapsedSeconds.toFixed(1);
2603
+ console.log(
2604
+ chalk3.red(
2605
+ `${variantLabel}: Error after ${elapsed}s - ${error instanceof Error ? error.message : String(error)}
2606
+ `
2607
+ )
2608
+ );
2609
+ const errorMsg = error instanceof Error ? error.message.toLowerCase() : "";
2610
+ if (errorMsg.includes("rate limit") || errorMsg.includes("ratelimit") || errorMsg.includes("too many requests") || matchesErrorPattern(errorMsg, "429")) {
2611
+ recordProviderRateLimit(providerId);
2612
+ }
2613
+ const failureResult = this.buildFailureResult(variant, error, elapsedSeconds);
2614
+ observedResults.push(failureResult);
2615
+ try {
2616
+ updateEvaluationHandleWithResult(taskId, failureResult);
2617
+ } catch (handleError) {
2618
+ console.warn(
2619
+ `Failed to update competition handle for failed local task ${taskId} variant ${variant.provider}-${variant.strategy}: ${handleError instanceof Error ? handleError.message : String(handleError)}`
2620
+ );
2621
+ debugLog("Full stack:", handleError);
2622
+ }
2623
+ this.logVariantCompleteSafe(taskId, variant, failureResult);
2624
+ return failureResult;
2625
+ } finally {
2626
+ await handle.release();
2627
+ }
2628
+ })();
2629
+ });
2630
+ allPromises.push(...localPromises);
2631
+ const allResults = await Promise.allSettled(allPromises);
2632
+ if (outerSignal?.aborted) {
2633
+ throw outerSignal.reason instanceof Error ? outerSignal.reason : new Error("Variant execution aborted");
2634
+ }
2635
+ allResults.forEach((result) => {
2636
+ if (result.status === "fulfilled") {
2637
+ results.push(result.value);
2638
+ } else if (result.status === "rejected") {
2639
+ const failureResult = {
2640
+ success: false,
2641
+ error: result.reason instanceof Error ? result.reason : new Error(String(result.reason)),
2642
+ duration: 0,
2643
+ provider: "unknown",
2644
+ variant: "unknown",
2645
+ executionMode: "local",
2646
+ strategy: "unknown",
2647
+ completeness: 0
2648
+ };
2649
+ results.push(failureResult);
2650
+ }
2651
+ });
2652
+ const state = this.getVariantState(results);
2653
+ this.logVariantApplicationWarnings(results);
2654
+ console.log(chalk3.bold.blue("\nCompetition Results\n"));
2655
+ if (state.completed < state.total || state.succeeded === 0) {
2656
+ console.log(
2657
+ chalk3.yellow(
2658
+ state.succeeded === 0 ? this.judgeOff ? "No successful variants; no judge ran (--judge off)" : "No successful variants - judges will still evaluate available results" : `Partial Results - Only ${state.completed}/${state.total} variants completed`
2659
+ )
2660
+ );
2661
+ console.log(
2662
+ chalk3.gray(
2663
+ ` Succeeded: ${state.succeeded}, Failed: ${state.failed}, Timed out: ${state.timedOut}
2664
+ `
2665
+ )
2666
+ );
2667
+ }
2668
+ if (outerSignal?.aborted) {
2669
+ throw outerSignal.reason instanceof Error ? outerSignal.reason : new Error("Variant execution aborted before judge selection");
2670
+ }
2671
+ const winner = this.shouldRunWinnerSelection(state) ? await this.variantOrchestrator.selectWinner(results, {
2672
+ useAIJudge: this.aiJudge,
2673
+ originalPrompt: prompt,
2674
+ model: this.aiJudgeModel,
2675
+ aiJudgeVerbose: this.aiJudgeVerbose,
2676
+ aiJudgeShowRationale: this.aiJudgeShowRationale,
2677
+ aiJudgeCriteriaWeights: this.aiJudgeCriteriaWeights,
2678
+ aiJudgeMinScore: this.aiJudgeMinScore,
2679
+ aiJudgeConfidenceThreshold: this.aiJudgeConfidenceThreshold,
2680
+ aiJudgeStreaming: this.aiJudgeStreaming,
2681
+ aiJudgeRun: this.aiJudgeRun,
2682
+ aiJudgePrimary: this.aiJudgePrimary,
2683
+ judgeModels: this.judgeModels,
2684
+ judgeModel: this.judgeModel,
2685
+ judgeAllowUnsafeModel: this.judgeAllowUnsafeModel,
2686
+ judgeStrict: this.judgeStrict,
2687
+ anonymizeJudge: this.anonymizeJudge,
2688
+ aiJudgeVerbosity: this.aiJudgeVerbosity,
2689
+ verificationMode: this.verificationMode,
2690
+ resultStreamer: this.resultStreamer,
2691
+ // Enable streaming for final results
2692
+ taskId,
2693
+ competitionMode: true,
2694
+ aiJudgeTelemetry: this.aiJudgeTelemetry,
2695
+ ungradedIdentity: this.judgeOff && state.total === 1
2696
+ }) : null;
2697
+ if (winner && !this.judgeOff && this.shouldTriggerOptimization(results)) {
2698
+ try {
2699
+ const optimizer = new AutomaticPromptOptimizer({
2700
+ telemetryLogger: this.getTelemetryLogger(),
2701
+ enableAutoTuning: this.enableAutoTuning ?? false
2702
+ });
2703
+ const recommendation = await optimizer.analyzePrompt(prompt);
2704
+ if (recommendation && recommendation.action !== "no_action" && recommendation.action !== "needs_more_data") {
2705
+ const optimizationResult = await optimizer.optimizePrompt(prompt, recommendation);
2706
+ if (this.verbose) {
2707
+ console.log(chalk3.gray("Prompt optimization analysis complete"));
2708
+ if (optimizationResult.improvements.length > 0) {
2709
+ console.log(chalk3.gray(` Improvements: ${optimizationResult.improvements.length}`));
2710
+ }
2711
+ if (optimizationResult.warnings.length > 0) {
2712
+ console.log(chalk3.yellow(` Warnings: ${optimizationResult.warnings.length}`));
2713
+ }
2714
+ }
2715
+ }
2716
+ optimizer.close();
2717
+ } catch (optimizationError) {
2718
+ if (this.verbose) {
2719
+ console.log(
2720
+ chalk3.yellow(
2721
+ `Prompt optimization skipped: ${optimizationError instanceof Error ? optimizationError.message : String(optimizationError)}`
2722
+ )
2723
+ );
2724
+ }
2725
+ }
2726
+ }
2727
+ this.displayResults(results, winner);
2728
+ if (winner?.judgeEvaluation) {
2729
+ const variantResultsMap = new Map(results.map((r) => [r.variant, r]));
2730
+ this.judgeDisplayService.displayEvaluation(winner.judgeEvaluation, variantResultsMap);
2731
+ }
2732
+ let mergedResult = null;
2733
+ if (this.synthesize && winner) {
2734
+ console.log(chalk3.blue("\nGenerating synthesized solution from top variants...\n"));
2735
+ try {
2736
+ const { VariantResultsMerger } = await import("./synthesis-TGQUVAW3.js");
2737
+ const merger = new VariantResultsMerger({
2738
+ defaultTopN: 2,
2739
+ defaultStrategy: "agentic-synthesis",
2740
+ maxVariantsToMerge: 5
2741
+ });
2742
+ const synthesisMergeOptions = {
2743
+ enabled: true,
2744
+ topN: this.synthesisTopN,
2745
+ createPR: false,
2746
+ strategy: this.synthesisStrategy,
2747
+ taskId,
2748
+ aiModel: this.synthesisModel,
2749
+ taskDescription: prompt,
2750
+ judgeRationale: winner?.judgeEvaluation?.winnerPrimaryReason ?? winner?.judgeEvaluation?.rationalePacket?.selectionRationale.primary ?? winner?.judgeEvaluation?.reasoning ?? void 0,
2751
+ judgeContext: this.variantOrchestrator.getLastSynthesisJudgeContext(),
2752
+ declaredWinner: winner ? { provider: winner.provider, variant: winner.variant } : void 0
2753
+ };
2754
+ mergedResult = await merger.merge(results, synthesisMergeOptions);
2755
+ if (mergedResult?.success) {
2756
+ mergedResult.mergeGenerated = true;
2757
+ mergedResult.complementaryPatchApplied = false;
2758
+ mergedResult.deliverySucceeded = true;
2759
+ mergedResult.synthesisApplied = false;
2760
+ mergedResult.winnerFallback = mergedResult.winnerFallback === true || mergedResult.winnerClone === true;
2761
+ mergedResult.patchApplyValidated = false;
2762
+ mergedResult.gatesPassed = false;
2763
+ if (mergedResult.winnerClone === true) {
2764
+ mergedResult.fallbackReason = mergedResult.reasoning;
2765
+ mergedResult.synthesisOutcomeStatus ??= "winner_carry_forward";
2766
+ }
2767
+ }
2768
+ if (mergedResult) {
2769
+ const selectedVariants = resolveSynthesisSelectedVariants(
2770
+ results,
2771
+ mergedResult.inputVariants
2772
+ );
2773
+ const synthesisTelemetry = buildSynthesisTelemetrySnapshot({
2774
+ results,
2775
+ topVariants: selectedVariants,
2776
+ declaredWinner: synthesisMergeOptions.declaredWinner,
2777
+ synthesisIntents: synthesisMergeOptions.synthesisIntents,
2778
+ intentFilteredMaterial: synthesisMergeOptions.intentFilteredMaterial
2779
+ });
2780
+ if (synthesisTelemetry) {
2781
+ Object.assign(mergedResult, synthesisTelemetry);
2782
+ }
2783
+ }
2784
+ if (mergedResult?.success) {
2785
+ console.log(chalk3.green("\nSynthesis complete"));
2786
+ console.log(chalk3.gray(` ${mergedResult.reasoning}`));
2787
+ const winnerWorktree = winner?.retainedWorktreePath;
2788
+ if (this.synthesisStrategy === "agentic-synthesis" && mergedResult.synthesisWorktreePath) {
2789
+ const synthesisWorktree = mergedResult.synthesisWorktreePath.trim();
2790
+ try {
2791
+ if (!synthesisWorktree) {
2792
+ throw new Error("missing synthesis worktree path");
2793
+ }
2794
+ const verifyPlan = resolveSynthesisVerifyCommands(synthesisWorktree);
2795
+ if (!verifyPlan.available) {
2796
+ markSynthesisWinnerFallback(
2797
+ mergedResult,
2798
+ "Agentic synthesis worktree verification unavailable for the target language; winner-only result retained",
2799
+ winner
2800
+ );
2801
+ console.warn(
2802
+ chalk3.yellow(
2803
+ " Agentic synthesis worktree verification unavailable: no deterministic typecheck/build signal detected for the target language."
2804
+ )
2805
+ );
2806
+ console.warn(
2807
+ chalk3.gray(
2808
+ " Retaining the judged winner without complementary donor changes."
2809
+ )
2810
+ );
2811
+ await cleanupAgenticSynthesisWorktree(synthesisWorktree, this.preserveWorktrees);
2812
+ } else {
2813
+ const verifyResult = await runVerifyCommands({
2814
+ cwd: synthesisWorktree,
2815
+ baselineCwd: winnerWorktree,
2816
+ // Never let validation auto-install into the product worktree.
2817
+ // If the toolchain is unavailable, retain the judged winner.
2818
+ commands: verifyPlan.commands,
2819
+ timeoutMs: 6e4
2820
+ });
2821
+ mergedResult.validationScope = "typecheck-only";
2822
+ if (verifyResult.passed) {
2823
+ markTypecheckOnlySynthesisFallback(
2824
+ mergedResult,
2825
+ winner,
2826
+ "Agentic synthesis was not promoted because PR workflow validation is typecheck-only"
2827
+ );
2828
+ await cleanupAgenticSynthesisWorktree(synthesisWorktree, this.preserveWorktrees);
2829
+ } else {
2830
+ const failedResult = verifyResult.results.find((result) => result.exitCode !== 0);
2831
+ const baselineAwareMessage = failedResult && typeof failedResult.newErrorCount === "number" && typeof failedResult.currentErrorCount === "number" && typeof failedResult.baselineErrorCount === "number" ? `agentic synthesis introduced ${failedResult.newErrorCount} new typecheck error(s) (baseline=${failedResult.baselineErrorCount}, current=${failedResult.currentErrorCount})` : "agentic synthesis failed build gate";
2832
+ markSynthesisWinnerFallback(
2833
+ mergedResult,
2834
+ "Agentic synthesis edited worktree failed deterministic gates; winner-only result retained",
2835
+ winner,
2836
+ baselineAwareMessage
2837
+ );
2838
+ console.warn(
2839
+ chalk3.yellow(
2840
+ ` Agentic synthesis worktree failed validation: ${baselineAwareMessage}`
2841
+ )
2842
+ );
2843
+ console.warn(
2844
+ chalk3.gray(
2845
+ " Retaining the judged winner without complementary donor changes."
2846
+ )
2847
+ );
2848
+ await cleanupAgenticSynthesisWorktree(synthesisWorktree, this.preserveWorktrees);
2849
+ }
2850
+ }
2851
+ } catch (validationError) {
2852
+ const validationErrorMessage = validationError instanceof Error ? validationError.message : String(validationError);
2853
+ markSynthesisWinnerFallback(
2854
+ mergedResult,
2855
+ "Agentic synthesis worktree validation failed; winner-only result retained",
2856
+ winner,
2857
+ validationErrorMessage
2858
+ );
2859
+ console.warn(
2860
+ chalk3.yellow(
2861
+ ` Could not validate agentic synthesis worktree: ${validationError instanceof Error ? validationError.message : String(validationError)}`
2862
+ )
2863
+ );
2864
+ console.warn(
2865
+ chalk3.gray(" Retaining the judged winner without complementary donor changes.")
2866
+ );
2867
+ await cleanupAgenticSynthesisWorktree(synthesisWorktree, this.preserveWorktrees);
2868
+ }
2869
+ } else if (this.synthesisStrategy !== "agentic-synthesis" && winnerWorktree && mergedResult.complementaryPatch) {
2870
+ try {
2871
+ const augmentation = await applyComplementaryPatchToWinnerWorktree({
2872
+ winnerWorktree,
2873
+ complementaryPatch: mergedResult.complementaryPatch,
2874
+ validate: async (worktreePath, baselineWorktreePath) => {
2875
+ const verifyPlan = resolveSynthesisVerifyCommands(worktreePath);
2876
+ if (!verifyPlan.available) {
2877
+ return {
2878
+ ok: false,
2879
+ error: "Complementary synthesis was not promoted because target-language verification is unavailable"
2880
+ };
2881
+ }
2882
+ const verifyResult = await runVerifyCommands({
2883
+ cwd: worktreePath,
2884
+ baselineCwd: baselineWorktreePath,
2885
+ // Never let validation auto-install into the product worktree.
2886
+ // If the toolchain is unavailable, retain the judged winner.
2887
+ commands: verifyPlan.commands,
2888
+ timeoutMs: 6e4
2889
+ });
2890
+ if (mergedResult) {
2891
+ mergedResult.validationScope = "typecheck-only";
2892
+ }
2893
+ if (verifyResult.passed) {
2894
+ return {
2895
+ ok: false,
2896
+ error: "Complementary synthesis was not promoted because PR workflow validation is typecheck-only"
2897
+ };
2898
+ }
2899
+ const failedResult = verifyResult.results.find((result) => result.exitCode !== 0);
2900
+ const baselineAwareMessage = failedResult && typeof failedResult.newErrorCount === "number" && typeof failedResult.currentErrorCount === "number" && typeof failedResult.baselineErrorCount === "number" ? `augmented code introduced ${failedResult.newErrorCount} new typecheck error(s) (baseline=${failedResult.baselineErrorCount}, current=${failedResult.currentErrorCount})` : "augmented code failed build gate";
2901
+ return {
2902
+ ok: false,
2903
+ error: baselineAwareMessage
2904
+ };
2905
+ }
2906
+ });
2907
+ mergedResult.applyMode = augmentation.applyMode;
2908
+ mergedResult.applyError = augmentation.applyError;
2909
+ if (augmentation.winnerWorktreeDirty) {
2910
+ throw new SynthesisWinnerRestorationError(
2911
+ `Complementary synthesis failed and the winner worktree could not be restored exactly: ${augmentation.applyError ?? "unknown restoration failure"}`
2912
+ );
2913
+ }
2914
+ if (augmentation.applied && augmentation.augmentedFiles.length > 0) {
2915
+ mergedResult.complementaryPatchApplied = true;
2916
+ mergedResult.synthesisApplied = true;
2917
+ mergedResult.winnerFallback = false;
2918
+ delete mergedResult.fallbackReason;
2919
+ mergedResult.patchApplyValidated = true;
2920
+ mergedResult.gatesPassed = false;
2921
+ mergedResult.validationScope = "typecheck-only";
2922
+ console.log(
2923
+ chalk3.green(
2924
+ ` ${augmentation.augmentedFiles.length} file(s) augmented with complementary changes (${augmentation.applyMode ?? "unknown"} apply, typecheck verified)`
2925
+ )
2926
+ );
2927
+ console.log(chalk3.gray(` ${augmentation.augmentedFiles.join(", ")}`));
2928
+ } else if (augmentation.applyError) {
2929
+ if (augmentation.applyError === "Complementary synthesis was not promoted because PR workflow validation is typecheck-only") {
2930
+ markTypecheckOnlySynthesisFallback(mergedResult, winner, augmentation.applyError);
2931
+ } else {
2932
+ markSynthesisWinnerFallback(
2933
+ mergedResult,
2934
+ "Complementary patch application failed; winner-only result retained",
2935
+ winner,
2936
+ augmentation.applyError
2937
+ );
2938
+ }
2939
+ console.warn(
2940
+ chalk3.yellow(
2941
+ ` Could not apply complementary patch: ${augmentation.applyError}. Retaining judged winner.`
2942
+ )
2943
+ );
2944
+ } else {
2945
+ markSynthesisWinnerFallback(
2946
+ mergedResult,
2947
+ "Complementary patch produced no validated winner-worktree changes; winner-only result retained",
2948
+ winner
2949
+ );
2950
+ }
2951
+ } catch (applyError) {
2952
+ if (applyError instanceof SynthesisWinnerRestorationError) {
2953
+ throw applyError;
2954
+ }
2955
+ const applyErrorMessage = applyError instanceof Error ? applyError.message : String(applyError);
2956
+ markSynthesisWinnerFallback(
2957
+ mergedResult,
2958
+ "Complementary patch application failed; winner-only result retained",
2959
+ winner,
2960
+ applyErrorMessage
2961
+ );
2962
+ console.warn(
2963
+ chalk3.yellow(
2964
+ ` Could not apply complementary patch: ${applyErrorMessage}. Retaining judged winner.`
2965
+ )
2966
+ );
2967
+ }
2968
+ } else if (this.synthesisStrategy === "agentic-synthesis") {
2969
+ markSynthesisWinnerFallback(
2970
+ mergedResult,
2971
+ "Agentic synthesis did not retain an editable synthesis worktree for direct validation; winner-only result retained",
2972
+ winner
2973
+ );
2974
+ } else if (!mergedResult.complementaryPatch) {
2975
+ markSynthesisWinnerFallback(
2976
+ mergedResult,
2977
+ mergedResult.winnerClone === true ? mergedResult.reasoning ?? "Synthesis retained judged winner" : "No complementary changes from losers; winner-only result retained",
2978
+ winner
2979
+ );
2980
+ console.log(
2981
+ chalk3.gray(" No complementary changes from losers (all overlapped winner)")
2982
+ );
2983
+ } else {
2984
+ markSynthesisWinnerFallback(
2985
+ mergedResult,
2986
+ "Complementary patch could not be applied because the winner worktree was unavailable; winner-only result retained",
2987
+ winner
2988
+ );
2989
+ }
2990
+ } else if (mergedResult) {
2991
+ mergedResult.deliverySucceeded = true;
2992
+ mergedResult.synthesisApplied = false;
2993
+ mergedResult.winnerFallback = true;
2994
+ mergedResult.fallbackReason = mergedResult.error ?? "Synthesis generation failed; winner-only result retained";
2995
+ mergedResult.patchApplyValidated = false;
2996
+ mergedResult.gatesPassed = false;
2997
+ if (mergedResult.error) {
2998
+ console.log(
2999
+ chalk3.yellow(`
3000
+ Synthesis completed with warnings: ${mergedResult.error}
3001
+ `)
3002
+ );
3003
+ }
3004
+ }
3005
+ } catch (error) {
3006
+ if (error instanceof SynthesisWinnerRestorationError) {
3007
+ throw error;
3008
+ }
3009
+ console.warn(chalk3.yellow("\nSynthesis failed, but winner is still selected"));
3010
+ console.warn(
3011
+ chalk3.gray(` Error: ${error instanceof Error ? error.message : String(error)}
3012
+ `)
3013
+ );
3014
+ }
3015
+ try {
3016
+ const fs2 = await import("fs/promises");
3017
+ const pathMod = await import("path");
3018
+ const dir = pathMod.join(resolvePoeticDirFromContext(), "telemetry", "synthesis");
3019
+ await fs2.mkdir(dir, { recursive: true });
3020
+ const code = mergedResult?.code;
3021
+ const selectedVariants = resolveSynthesisSelectedVariants(
3022
+ results,
3023
+ mergedResult?.inputVariants
3024
+ );
3025
+ const artifact = {
3026
+ taskId,
3027
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3028
+ selectedVariants: selectedVariants.map((variant) => ({
3029
+ provider: variant.provider,
3030
+ variant: variant.variant ?? variant.strategy
3031
+ })),
3032
+ declaredWinner: winner ? {
3033
+ provider: winner.provider,
3034
+ variant: winner.variant ?? winner.strategy
3035
+ } : void 0,
3036
+ synthesisStrategy: this.synthesisStrategy,
3037
+ synthesisModel: this.synthesisModel,
3038
+ synthesisOutcomeStatus: resolveSynthesisOutcomeStatusForArtifact(mergedResult),
3039
+ success: didSynthesisArtifactSucceed({ mergedResult }),
3040
+ mergeGenerated: mergedResult?.mergeGenerated ?? false,
3041
+ complementaryPatchApplied: mergedResult?.complementaryPatchApplied ?? false,
3042
+ deliverySucceeded: mergedResult?.deliverySucceeded ?? false,
3043
+ synthesisApplied: mergedResult?.synthesisApplied ?? false,
3044
+ winnerFallback: mergedResult?.winnerFallback ?? false,
3045
+ fallbackReason: mergedResult?.fallbackReason,
3046
+ patchApplyValidated: mergedResult?.patchApplyValidated ?? false,
3047
+ gatesPassed: mergedResult?.gatesPassed ?? false,
3048
+ validationScope: mergedResult?.validationScope,
3049
+ gateFailureDetails: mergedResult?.gateFailureDetails,
3050
+ synthesisWorktree: mergedResult?.synthesisWorktreePath ? {
3051
+ scope: "session-local",
3052
+ name: pathMod.basename(mergedResult.synthesisWorktreePath)
3053
+ } : void 0,
3054
+ synthesisBaseRef: mergedResult?.synthesisBaseRef,
3055
+ synthesisBranch: mergedResult?.synthesisBranch,
3056
+ applyMode: mergedResult?.applyMode,
3057
+ applyError: mergedResult?.applyError,
3058
+ aiGuidedFallbackAttempted: mergedResult?.aiGuidedFallbackAttempted ?? false,
3059
+ aiGuidedFallbackOutcome: mergedResult?.aiGuidedFallbackOutcome,
3060
+ winnerClone: mergedResult?.winnerClone,
3061
+ noveltyScore: mergedResult?.noveltyScore,
3062
+ mergedVariants: mergedResult?.mergedVariants ?? [],
3063
+ contributingVariants: mergedResult?.contributingVariants,
3064
+ synthesisIntents: mergedResult?.synthesisIntents,
3065
+ donorProfiles: mergedResult?.donorProfiles,
3066
+ donorSelectionDecisions: mergedResult?.donorSelectionDecisions,
3067
+ intentMaterialSummaries: mergedResult?.intentMaterialSummaries,
3068
+ donorMaterialDiagnostic: mergedResult?.donorMaterialDiagnostic,
3069
+ harvestManifest: mergedResult?.harvestManifest,
3070
+ winnerFirstReview: mergedResult?.winnerFirstReview,
3071
+ intentFilteredHunkCount: mergedResult?.intentFilteredHunkCount,
3072
+ excludedHunkCount: mergedResult?.excludedHunkCount,
3073
+ unknownIncludedHunkCount: mergedResult?.unknownIncludedHunkCount,
3074
+ unknownExcludedHunkCount: mergedResult?.unknownExcludedHunkCount,
3075
+ overlapRejectedHunkCount: mergedResult?.overlapRejectedHunkCount,
3076
+ reasoning: mergedResult?.reasoning,
3077
+ error: mergedResult?.error,
3078
+ synthesisOutputLines: code != null ? code.split("\n").length : void 0
3079
+ };
3080
+ await fs2.writeFile(
3081
+ pathMod.join(dir, `${taskId}.json`),
3082
+ JSON.stringify(sanitizeSynthesisArtifactForPersistence(artifact), null, 2),
3083
+ "utf-8"
3084
+ );
3085
+ if (this.verbose) {
3086
+ console.log(
3087
+ chalk3.gray(` Synthesis artifact saved to .poetic/telemetry/synthesis/${taskId}.json`)
3088
+ );
3089
+ }
3090
+ } catch {
3091
+ }
3092
+ if (this.synthesisStrategy === "agentic-synthesis" && mergedResult?.synthesisApplied === true && mergedResult.synthesisWorktreePath) {
3093
+ await cleanupAgenticSynthesisWorktree(
3094
+ mergedResult.synthesisWorktreePath,
3095
+ this.preserveWorktrees
3096
+ );
3097
+ }
3098
+ }
3099
+ await this.cleanupIfEnabled(results, winner, taskId);
3100
+ return {
3101
+ taskId,
3102
+ variants: results,
3103
+ winner,
3104
+ synthesis: mergedResult,
3105
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3106
+ };
3107
+ }
3108
+ /**
3109
+ * DAG-aware variant execution with dependency resolution and resource management
3110
+ *
3111
+ * Algorithm:
3112
+ * 1. Build dependency graph from task dependencies (or infer from variants)
3113
+ * 2. Validate graph structure (detect cycles, missing nodes)
3114
+ * 3. Execute variants in topological order:
3115
+ * - Cloud variants: Submit async, mark completed immediately (non-blocking)
3116
+ * - Local variants: Acquire resource slot, execute, release slot
3117
+ * - Gemini variants: Parallel by default (HOME isolation), auto-fallback on exit 54
3118
+ * 4. Mark tasks completed/failed, unblock dependents
3119
+ * 5. Continue until all tasks terminal or blocked
3120
+ *
3121
+ * @param taskId - Unique task identifier
3122
+ * @param prompt - Task prompt
3123
+ * @param variants - Variant configurations
3124
+ * @param results - Results array (mutated in place)
3125
+ * @returns Competition result
3126
+ */
3127
+ async executeVariantsWithDependencies(taskId, prompt, variants, results, retryMeta, outerSignal) {
3128
+ if (!this.dependencyResolver || !this.resourceManager) {
3129
+ throw new Error("Dependency components not initialized (enable via flywheel)");
3130
+ }
3131
+ const taskDeps = this.taskDependencies || variants.map((v) => ({
3132
+ id: this.getVariantId(v),
3133
+ dependencies: [],
3134
+ // No dependencies if not specified (all parallel)
3135
+ metadata: { variant: v }
3136
+ }));
3137
+ const graph = this.dependencyResolver.buildGraph(taskDeps);
3138
+ const validation = this.dependencyResolver.validateGraph(graph);
3139
+ if (!validation.valid) {
3140
+ throw new Error(`Invalid dependency graph: ${validation.errors.join(", ")}`);
3141
+ }
3142
+ if (validation.warnings && validation.warnings.length > 0) {
3143
+ console.warn(chalk3.yellow(`Dependency warnings: ${validation.warnings.join(", ")}`));
3144
+ }
3145
+ const abortController = new AbortController();
3146
+ const signal = abortController.signal;
3147
+ if (outerSignal) {
3148
+ if (outerSignal.aborted) {
3149
+ abortController.abort(outerSignal.reason);
3150
+ } else {
3151
+ outerSignal.addEventListener("abort", () => abortController.abort(outerSignal.reason), {
3152
+ once: true
3153
+ });
3154
+ }
3155
+ }
3156
+ const variantMap = /* @__PURE__ */ new Map();
3157
+ for (const variant of variants) {
3158
+ variantMap.set(this.getVariantId(variant), variant);
3159
+ }
3160
+ const localVariants = variants;
3161
+ const geminiVariants = localVariants.filter((v) => v.provider === "gemini");
3162
+ const nonGeminiLocalVariants = localVariants.filter((v) => v.provider !== "gemini");
3163
+ console.log(chalk3.gray("DAG Execution Plan:"));
3164
+ console.log(chalk3.gray(` Total tasks: ${graph.nodes.size}`));
3165
+ console.log(
3166
+ chalk3.gray(` Max depth: ${this.dependencyResolver.getMaxLevel(graph) + 1} levels`)
3167
+ );
3168
+ console.log(
3169
+ chalk3.gray(` Local variants: ${nonGeminiLocalVariants.length} (resource-managed)`)
3170
+ );
3171
+ console.log(
3172
+ chalk3.gray(` Gemini variants: ${geminiVariants.length} (parallel + auto-fallback)
3173
+ `)
3174
+ );
3175
+ while (!this.dependencyResolver.isComplete(graph)) {
3176
+ const readyTasks = this.dependencyResolver.getReadyTasks(graph);
3177
+ if (readyTasks.length === 0) {
3178
+ const stats2 = this.dependencyResolver.getStatistics(graph);
3179
+ if (stats2.blockedTasks > 0) {
3180
+ console.warn(
3181
+ chalk3.yellow(`${stats2.blockedTasks} task(s) blocked due to dependency failures`)
3182
+ );
3183
+ }
3184
+ break;
3185
+ }
3186
+ console.log(chalk3.cyan(`\u2192 Ready tasks: ${readyTasks.length} (${readyTasks.join(", ")})`));
3187
+ const executionPromises = [];
3188
+ for (const variantId of readyTasks) {
3189
+ const variant = variantMap.get(variantId);
3190
+ if (!variant) {
3191
+ console.warn(chalk3.yellow(`Variant not found for task ${variantId}`));
3192
+ this.dependencyResolver.markFailed(graph, variantId, "Variant not found");
3193
+ continue;
3194
+ }
3195
+ this.dependencyResolver.markRunning(graph, variantId);
3196
+ const executionPromise = this.executeVariantWithResources(
3197
+ taskId,
3198
+ prompt,
3199
+ variant,
3200
+ variantId,
3201
+ signal,
3202
+ retryMeta
3203
+ ).then((result) => {
3204
+ results.push(result);
3205
+ if (result.success) {
3206
+ if (this.dependencyResolver) {
3207
+ const newlyReady = this.dependencyResolver.markCompleted(graph, variantId);
3208
+ if (newlyReady.length > 0 && this.verbose) {
3209
+ console.log(chalk3.gray(` Unblocked: ${newlyReady.join(", ")}`));
3210
+ }
3211
+ }
3212
+ } else {
3213
+ if (this.dependencyResolver) {
3214
+ const blocked = this.dependencyResolver.markFailed(
3215
+ graph,
3216
+ variantId,
3217
+ result.error?.message
3218
+ );
3219
+ if (blocked.length > 0) {
3220
+ console.warn(chalk3.yellow(` Blocked dependents: ${blocked.join(", ")}`));
3221
+ }
3222
+ }
3223
+ }
3224
+ try {
3225
+ updateEvaluationHandleWithResult(taskId, result);
3226
+ } catch (handleError) {
3227
+ console.warn(
3228
+ `Failed to update competition handle: ${handleError instanceof Error ? handleError.message : String(handleError)}`
3229
+ );
3230
+ debugLog("Full stack:", handleError);
3231
+ }
3232
+ }).catch((error) => {
3233
+ console.error(
3234
+ chalk3.red(
3235
+ `Execution error for ${variantId}: ${error instanceof Error ? error.message : String(error)}`
3236
+ )
3237
+ );
3238
+ if (this.dependencyResolver) {
3239
+ this.dependencyResolver.markFailed(graph, variantId, String(error));
3240
+ }
3241
+ });
3242
+ executionPromises.push(executionPromise);
3243
+ }
3244
+ await Promise.allSettled(executionPromises);
3245
+ if (outerSignal?.aborted) {
3246
+ throw outerSignal.reason instanceof Error ? outerSignal.reason : new Error("Dependency-aware variant execution aborted");
3247
+ }
3248
+ }
3249
+ const stats = this.dependencyResolver.getStatistics(graph);
3250
+ console.log(chalk3.blue("\nDAG Execution Summary:"));
3251
+ console.log(chalk3.gray(` Completed: ${stats.completedTasks}/${stats.totalTasks}`));
3252
+ console.log(chalk3.gray(` Failed: ${stats.failedTasks}`));
3253
+ console.log(chalk3.gray(` Blocked: ${stats.blockedTasks}
3254
+ `));
3255
+ const state = this.getVariantState(results);
3256
+ this.logVariantApplicationWarnings(results);
3257
+ console.log(chalk3.bold.blue("\nCompetition Results\n"));
3258
+ if (outerSignal?.aborted) {
3259
+ throw outerSignal.reason instanceof Error ? outerSignal.reason : new Error("Variant execution aborted before judge selection");
3260
+ }
3261
+ const winner = this.shouldRunWinnerSelection(state) ? await this.variantOrchestrator.selectWinner(results, {
3262
+ useAIJudge: this.aiJudge,
3263
+ originalPrompt: prompt,
3264
+ model: this.aiJudgeModel,
3265
+ aiJudgeVerbose: this.aiJudgeVerbose,
3266
+ aiJudgeShowRationale: this.aiJudgeShowRationale,
3267
+ aiJudgeCriteriaWeights: this.aiJudgeCriteriaWeights,
3268
+ aiJudgeMinScore: this.aiJudgeMinScore,
3269
+ aiJudgeConfidenceThreshold: this.aiJudgeConfidenceThreshold,
3270
+ aiJudgeStreaming: this.aiJudgeStreaming,
3271
+ aiJudgeRun: this.aiJudgeRun,
3272
+ aiJudgePrimary: this.aiJudgePrimary,
3273
+ judgeModels: this.judgeModels,
3274
+ judgeModel: this.judgeModel,
3275
+ judgeAllowUnsafeModel: this.judgeAllowUnsafeModel,
3276
+ judgeStrict: this.judgeStrict,
3277
+ anonymizeJudge: this.anonymizeJudge,
3278
+ aiJudgeVerbosity: this.aiJudgeVerbosity,
3279
+ verificationMode: this.verificationMode,
3280
+ resultStreamer: this.resultStreamer,
3281
+ taskId,
3282
+ competitionMode: true,
3283
+ aiJudgeTelemetry: this.aiJudgeTelemetry
3284
+ }) : null;
3285
+ this.displayResults(results, winner);
3286
+ if (winner?.judgeEvaluation) {
3287
+ const variantResultsMap = new Map(results.map((r) => [r.variant, r]));
3288
+ this.judgeDisplayService.displayEvaluation(winner.judgeEvaluation, variantResultsMap);
3289
+ }
3290
+ await this.cleanupIfEnabled(results, winner, taskId);
3291
+ return {
3292
+ taskId,
3293
+ variants: results,
3294
+ winner,
3295
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3296
+ };
3297
+ }
3298
+ /**
3299
+ * Execute a single variant with resource management
3300
+ *
3301
+ * Handles three execution modes:
3302
+ * 1. Cloud: Submit async, return immediately (non-blocking)
3303
+ * 2. Local (non-Gemini): Acquire resource slot, execute, release
3304
+ * 3. Gemini: Parallel by default with auto-fallback to serial on exit 54
3305
+ *
3306
+ * @param taskId - Task ID
3307
+ * @param prompt - Task prompt
3308
+ * @param variant - Variant configuration
3309
+ * @param variantId - Unique variant identifier
3310
+ * @param signal - Abort signal for cancellation
3311
+ * @returns Variant result
3312
+ */
3313
+ async executeVariantWithResources(taskId, prompt, variant, _variantId, signal, retryMeta) {
3314
+ const variantLabel = `${variant.provider} ${variant.model || "default-model"} ${variant.strategy}`;
3315
+ const startTime = Date.now();
3316
+ this.logVariantStartSafe(taskId, variant);
3317
+ try {
3318
+ let result;
3319
+ console.log(
3320
+ chalk3.cyan(`\u2192 Starting: ${variantLabel} ${chalk3.gray("(local, resource-managed)")}`)
3321
+ );
3322
+ if (!this.resourceManager) {
3323
+ throw new Error("Resource manager not initialized");
3324
+ }
3325
+ const handle = await this.resourceManager.acquire(
3326
+ variant.provider,
3327
+ signal,
3328
+ this.orchestratorTimeoutMs
3329
+ );
3330
+ try {
3331
+ result = await this.executeLocalVariant(taskId, variant, prompt, retryMeta, signal);
3332
+ } finally {
3333
+ await handle.release();
3334
+ }
3335
+ const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
3336
+ if (result.success) {
3337
+ console.log(
3338
+ chalk3.green(
3339
+ `${variantLabel}: Completed in ${elapsed}s ${result.prNumber ? `(PR #${result.prNumber})` : ""}
3340
+ `
3341
+ )
3342
+ );
3343
+ } else {
3344
+ console.log(
3345
+ chalk3.red(
3346
+ `${variantLabel}: Failed after ${elapsed}s - ${result.error?.message || "Unknown error"}
3347
+ `
3348
+ )
3349
+ );
3350
+ }
3351
+ this.logVariantCompleteSafe(taskId, variant, result);
3352
+ return result;
3353
+ } catch (error) {
3354
+ const elapsedSeconds = (Date.now() - startTime) / 1e3;
3355
+ const elapsed = elapsedSeconds.toFixed(1);
3356
+ console.log(
3357
+ chalk3.red(
3358
+ `${variantLabel}: Error after ${elapsed}s - ${error instanceof Error ? error.message : String(error)}
3359
+ `
3360
+ )
3361
+ );
3362
+ const failureResult = this.buildFailureResult(variant, error, elapsedSeconds);
3363
+ this.logVariantCompleteSafe(taskId, variant, failureResult);
3364
+ return failureResult;
3365
+ }
3366
+ }
3367
+ /**
3368
+ * Get unique variant identifier for DAG tracking
3369
+ *
3370
+ * @param variant - Variant configuration
3371
+ * @returns Unique variant ID
3372
+ */
3373
+ getVariantId(variant) {
3374
+ return `${variant.provider}:${variant.model || "default"}:${variant.strategy}:${variant.executionMode}`;
3375
+ }
3376
+ /**
3377
+ * Log cleanup telemetry event (non-blocking, best-effort)
3378
+ */
3379
+ logCleanupTelemetry(event) {
3380
+ try {
3381
+ console.log(
3382
+ JSON.stringify({
3383
+ eventType: event.eventType,
3384
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3385
+ taskId: event.taskId,
3386
+ ...event.data
3387
+ })
3388
+ );
3389
+ } catch (telemetryError) {
3390
+ console.warn(
3391
+ `Failed to log cleanup telemetry event ${event.eventType}: ${telemetryError instanceof Error ? telemetryError.message : String(telemetryError)}`
3392
+ );
3393
+ debugLog("Full stack:", telemetryError);
3394
+ }
3395
+ }
3396
+ /**
3397
+ * Best-effort cleanup trigger that runs when enabled and a winner exists.
3398
+ * Used from both the normal completion path and the timeout partial-results path.
3399
+ *
3400
+ * ENHANCED: Added robust error handling, retry logic, and detailed logging
3401
+ * to ensure cleanup triggers consistently even under error conditions.
3402
+ */
3403
+ async cleanupIfEnabled(results, winner, taskId, context) {
3404
+ const cleanupStartTime = Date.now();
3405
+ if (!this.cleanupOnCompletion) {
3406
+ this.logCleanupTelemetry({
3407
+ eventType: "cleanup.disabled",
3408
+ taskId,
3409
+ data: { reason: "configuration" }
3410
+ });
3411
+ if (this.verbose) {
3412
+ console.log(chalk3.gray("Cleanup disabled by configuration"));
3413
+ }
3414
+ return;
3415
+ }
3416
+ if (!winner) {
3417
+ this.logCleanupTelemetry({
3418
+ eventType: "cleanup.skipped",
3419
+ taskId,
3420
+ data: { reason: context?.reason ?? "no_winner" }
3421
+ });
3422
+ if (this.verbose) {
3423
+ console.log(chalk3.yellow("Cleanup skipped - no winner determined"));
3424
+ }
3425
+ return;
3426
+ }
3427
+ if (!results || results.length === 0) {
3428
+ this.logCleanupTelemetry({
3429
+ eventType: "cleanup.skipped",
3430
+ taskId,
3431
+ data: { reason: "no_results" }
3432
+ });
3433
+ if (this.verbose) {
3434
+ console.log(chalk3.yellow("Cleanup skipped - no results available"));
3435
+ }
3436
+ return;
3437
+ }
3438
+ const losersWithPRs = results.filter((r) => {
3439
+ const hasPrNumber = typeof r.prNumber === "number" && r.prNumber > 0;
3440
+ return hasPrNumber && (winner.prNumber ? r.prNumber !== winner.prNumber : r.variant !== winner.variant || r.provider !== winner.provider);
3441
+ });
3442
+ const hasLosers = losersWithPRs.length > 0;
3443
+ if (!hasLosers) {
3444
+ if (this.verbose) {
3445
+ console.log(chalk3.gray("No losing PRs detected, checking for orphan branches by task..."));
3446
+ }
3447
+ if (taskId && results.length > 1) {
3448
+ try {
3449
+ const orphanScanStart = Date.now();
3450
+ await this.cleanupService.cleanupCompetition(results, winner, {
3451
+ verbose: this.verbose,
3452
+ preserveSubmittedOnly: this.shouldPreserveSubmittedOnly(),
3453
+ taskId
3454
+ });
3455
+ const orphanCount = await this.cleanupOrphanBranchesByTask(taskId, winner);
3456
+ this.logCleanupTelemetry({
3457
+ eventType: "cleanup.orphan_scan",
3458
+ taskId,
3459
+ data: {
3460
+ branchesDeleted: orphanCount,
3461
+ durationMs: Date.now() - orphanScanStart
3462
+ }
3463
+ });
3464
+ if (orphanCount > 0) {
3465
+ console.log(chalk3.green(`Removed ${orphanCount} orphan branch(es) for task ${taskId}`));
3466
+ } else if (this.verbose) {
3467
+ console.log(chalk3.gray(`No orphan branches found for task ${taskId}`));
3468
+ }
3469
+ } catch (orphanError) {
3470
+ if (this.verbose) {
3471
+ console.log(
3472
+ chalk3.yellow(
3473
+ `Failed scanning orphan branches: ${orphanError instanceof Error ? orphanError.message : String(orphanError)}`
3474
+ )
3475
+ );
3476
+ }
3477
+ }
3478
+ } else if (results.length === 1) {
3479
+ if (this.verbose) {
3480
+ console.log(
3481
+ chalk3.gray("Skipping orphan branch scan - single variant (no orphans possible)")
3482
+ );
3483
+ }
3484
+ } else if (!taskId && this.verbose) {
3485
+ console.log(chalk3.gray("Skipping orphan branch scan - taskId not provided"));
3486
+ }
3487
+ return;
3488
+ }
3489
+ this.logCleanupTelemetry({
3490
+ eventType: "cleanup.started",
3491
+ taskId,
3492
+ data: {
3493
+ loserCount: losersWithPRs.length
3494
+ }
3495
+ });
3496
+ console.log(
3497
+ chalk3.blue(`
3498
+ Starting cleanup of ${losersWithPRs.length} non-winning variant(s)...`)
3499
+ );
3500
+ const maxRetries = 3;
3501
+ let cleanupSuccessful = false;
3502
+ let lastError = null;
3503
+ let lastErrorMessage = null;
3504
+ let cleanupAttempts = 0;
3505
+ try {
3506
+ await retryOperation(
3507
+ async () => {
3508
+ cleanupAttempts += 1;
3509
+ if (this.verbose) {
3510
+ console.log(chalk3.gray(`Cleanup attempt ${cleanupAttempts}/${maxRetries}`));
3511
+ }
3512
+ try {
3513
+ await this.cleanupService.cleanupCompetition(results, winner, {
3514
+ verbose: this.verbose,
3515
+ preserveSubmittedOnly: this.shouldPreserveSubmittedOnly(),
3516
+ taskId
3517
+ });
3518
+ } catch (cleanupError) {
3519
+ lastError = cleanupError instanceof Error ? cleanupError : new Error(String(cleanupError));
3520
+ lastErrorMessage = lastError.message;
3521
+ this.logCleanupTelemetry({
3522
+ eventType: "cleanup.retry_attempt",
3523
+ taskId,
3524
+ data: {
3525
+ attempt: cleanupAttempts,
3526
+ maxRetries,
3527
+ error: lastErrorMessage
3528
+ }
3529
+ });
3530
+ console.log(
3531
+ chalk3.yellow(`Cleanup attempt ${cleanupAttempts} failed: ${lastErrorMessage}`)
3532
+ );
3533
+ throw lastError;
3534
+ }
3535
+ cleanupSuccessful = true;
3536
+ if (this.verbose) {
3537
+ console.log(
3538
+ chalk3.green(`Cleanup completed successfully on attempt ${cleanupAttempts}`)
3539
+ );
3540
+ }
3541
+ },
3542
+ {
3543
+ maxRetries,
3544
+ initialDelayMs: 1e3,
3545
+ backoffMultiplier: 2,
3546
+ maxDelayMs: 5e3,
3547
+ onRetry: (_error, attempt) => {
3548
+ const backoffMs = calculateRetryDelayMs(attempt, {
3549
+ initialDelayMs: 1e3,
3550
+ backoffMultiplier: 2,
3551
+ maxDelayMs: 5e3
3552
+ });
3553
+ console.log(chalk3.gray(` Retrying in ${backoffMs}ms...`));
3554
+ }
3555
+ }
3556
+ );
3557
+ } catch {
3558
+ }
3559
+ const cleanupDurationMs = Date.now() - cleanupStartTime;
3560
+ this.logCleanupTelemetry({
3561
+ eventType: "cleanup.completed",
3562
+ taskId,
3563
+ data: {
3564
+ success: cleanupSuccessful,
3565
+ totalDurationMs: cleanupDurationMs,
3566
+ retryAttempts: cleanupAttempts || maxRetries
3567
+ }
3568
+ });
3569
+ if (!cleanupSuccessful && lastErrorMessage) {
3570
+ console.log(chalk3.yellow(`
3571
+ Cleanup failed after ${maxRetries} attempts:`));
3572
+ console.log(chalk3.yellow(` ${lastErrorMessage}`));
3573
+ console.log(chalk3.gray("\nManual cleanup may be required for the following variants:"));
3574
+ losersWithPRs.forEach((loser) => {
3575
+ console.log(chalk3.gray(` \u2022 ${loser.provider} ${loser.variant} (PR #${loser.prNumber})`));
3576
+ });
3577
+ console.log(chalk3.gray("\nManual cleanup commands:"));
3578
+ losersWithPRs.forEach((loser) => {
3579
+ console.log(chalk3.gray(` gh pr close ${loser.prNumber}`));
3580
+ if (taskId && loser.provider && loser.strategy && loser.executionMode) {
3581
+ const branch = poeticVariantBranchName({
3582
+ taskId,
3583
+ provider: loser.provider,
3584
+ strategy: loser.strategy,
3585
+ executionMode: loser.executionMode,
3586
+ model: loser.model
3587
+ });
3588
+ console.log(chalk3.gray(` git branch -D ${branch}`));
3589
+ } else {
3590
+ console.log(chalk3.gray(" gh pr view <PR_NUMBER> --json headRefName -q '.headRefName'"));
3591
+ }
3592
+ });
3593
+ }
3594
+ if (taskId) {
3595
+ this.clearBranchListCache(taskId);
3596
+ }
3597
+ }
3598
+ /**
3599
+ * Calculate variant state from results
3600
+ */
3601
+ getVariantState(results) {
3602
+ const isSubmittedOnly = (r) => r.submittedOnly === true;
3603
+ const validResults = results.filter((r) => r && r.success !== void 0);
3604
+ return {
3605
+ total: results.length,
3606
+ // Do not count submitted-only variants as completed
3607
+ completed: validResults.filter((r) => !isSubmittedOnly(r)).length,
3608
+ succeeded: validResults.filter((r) => r.success === true && !isSubmittedOnly(r)).length,
3609
+ failed: validResults.filter((r) => r.success === false && !r.timedOut).length,
3610
+ timedOut: validResults.filter((r) => r.timedOut === true).length
3611
+ };
3612
+ }
3613
+ /**
3614
+ * Check whether there is any provider result to send to winner selection.
3615
+ * Completion/success counts are telemetry only; the judges decide among the available outputs.
3616
+ */
3617
+ shouldRunWinnerSelection(state) {
3618
+ return shouldSelectCompetitionWinner({
3619
+ total: state.total,
3620
+ completed: state.completed,
3621
+ judgeOff: this.judgeOff
3622
+ });
3623
+ }
3624
+ /**
3625
+ * Display results in a formatted table
3626
+ */
3627
+ displayResults(results, winner) {
3628
+ console.log(chalk3.bold("Results Summary:\n"));
3629
+ const validResults = results.filter((r) => r);
3630
+ validResults.forEach((result) => {
3631
+ const isWinner = !this.judgeOff && winner && result.variant === winner.variant && result.provider === winner.provider;
3632
+ const prefix = isWinner ? chalk3.green("[winner]") : chalk3.gray(" ");
3633
+ const needsApply = this.requiresApplyRecovery(result);
3634
+ const status = result.submittedOnly ? chalk3.cyan("Submitted") : result.success && needsApply ? chalk3.yellow("Apply required") : result.success ? chalk3.green("ok") : chalk3.red("failed");
3635
+ const provider = chalk3.blue(`${result.provider}${result.model ? `:${result.model}` : ""}`);
3636
+ const strategy = chalk3.yellow(result.variant);
3637
+ const mode = chalk3.gray("local");
3638
+ const duration = chalk3.gray(`${result.duration.toFixed(1)}s`);
3639
+ const pr = result.prNumber ? chalk3.gray(`#${result.prNumber}`) : "";
3640
+ console.log(`${prefix} ${status} ${mode} ${provider} ${strategy} - ${duration} ${pr}`);
3641
+ });
3642
+ console.log();
3643
+ let selectionSummary;
3644
+ if (this.judgeOff && results.length === 1 && winner) {
3645
+ selectionSummary = chalk3.bold(
3646
+ `Ungraded result: ${winner.provider}${winner.model ? `:${winner.model}` : ""} ${winner.variant}`
3647
+ );
3648
+ } else if (this.judgeOff) {
3649
+ selectionSummary = chalk3.yellow(
3650
+ "Manual comparison (--judge off): no automatic winner selected."
3651
+ );
3652
+ } else if (winner) {
3653
+ selectionSummary = chalk3.bold.green(
3654
+ `Winner: ${winner.provider}${winner.model ? `:${winner.model}` : ""} ${winner.variant}`
3655
+ );
3656
+ } else {
3657
+ const state = this.getVariantState(results);
3658
+ selectionSummary = chalk3.yellow(
3659
+ state.completed < state.total * 0.5 ? "No winner declared by judges for the available results." : "No winner declared by judges."
3660
+ );
3661
+ }
3662
+ console.log(selectionSummary);
3663
+ if (!this.judgeOff && winner?.prNumber) {
3664
+ console.log(chalk3.gray(` PR: #${winner.prNumber}`));
3665
+ }
3666
+ console.log();
3667
+ const hasRetainedLocalWorktrees = results.some((r) => Boolean(r?.retainedWorktreePath));
3668
+ if (this.localFastMode || !this.pushLocalVariants && hasRetainedLocalWorktrees) {
3669
+ this.displayLocalFastSummary(results);
3670
+ }
3671
+ }
3672
+ /**
3673
+ * Get comparison and recommendations
3674
+ */
3675
+ async getComparison(results, resolvedWinner, noWinnerMode) {
3676
+ const comparison = await this.variantOrchestrator.compareVariants(
3677
+ results,
3678
+ resolvedWinner,
3679
+ noWinnerMode
3680
+ );
3681
+ return {
3682
+ ...comparison,
3683
+ analysis: comparison.analysis
3684
+ };
3685
+ }
3686
+ /**
3687
+ * Cleanup non-winning variant PRs and branches after competition
3688
+ * Delegates to CleanupService for all cleanup logic
3689
+ *
3690
+ * @deprecated Use CleanupService directly for new code
3691
+ */
3692
+ async cleanupCompetition(results, winner, taskId) {
3693
+ return this.cleanupService.cleanupCompetition(results, winner, {
3694
+ verbose: this.verbose,
3695
+ preserveSubmittedOnly: this.shouldPreserveSubmittedOnly(),
3696
+ taskId
3697
+ });
3698
+ }
3699
+ requiresApplyRecovery(result) {
3700
+ if (result.submittedOnly) {
3701
+ return true;
3702
+ }
3703
+ return result.applied === false;
3704
+ }
3705
+ isCloudVariant(result) {
3706
+ return result.submittedOnly === true;
3707
+ }
3708
+ formatProviderVariantLabel(result) {
3709
+ const provider = result.provider ? this.capitalizeWords(result.provider) : "Cloud";
3710
+ const variantName = typeof result.variant === "string" && result.variant.length > 0 ? result.variant : typeof result.variant === "string" ? result.variant : "";
3711
+ const variantLabel = variantName ? this.capitalizeWords(String(variantName)) : "";
3712
+ return variantLabel ? `${provider} ${variantLabel}` : provider;
3713
+ }
3714
+ logVariantApplicationWarnings(results) {
3715
+ const applyIssues = results.filter((result) => this.requiresApplyRecovery(result));
3716
+ if (applyIssues.length > 0) {
3717
+ console.log(chalk3.yellow(`${applyIssues.length} variant(s) have local-apply observations:`));
3718
+ applyIssues.forEach((result) => {
3719
+ const label = this.formatProviderVariantLabel(result);
3720
+ const prLabel = result.prNumber ? `PR #${result.prNumber}` : "PR pending";
3721
+ const hint = this.getCloudRecoveryHint(result);
3722
+ console.log(
3723
+ chalk3.gray(
3724
+ ` - ${label} (${prLabel}) - local result not applied${hint ? ` | ${hint}` : ""}`
3725
+ )
3726
+ );
3727
+ });
3728
+ }
3729
+ const submittedOnly = results.filter((result) => result.submittedOnly === true);
3730
+ if (submittedOnly.length > 0) {
3731
+ console.log(
3732
+ chalk3.gray(`${submittedOnly.length} variant(s) were submitted without local results.`)
3733
+ );
3734
+ }
3735
+ }
3736
+ getCloudRecoveryHint(result) {
3737
+ if (!this.isCloudVariant(result) || !this.requiresApplyRecovery(result)) {
3738
+ return void 0;
3739
+ }
3740
+ if (result.provider === "cursor") {
3741
+ if (result.prUrl) {
3742
+ return result.prUrl;
3743
+ }
3744
+ if (result.prNumber) {
3745
+ return `gh pr checkout ${result.prNumber}`;
3746
+ }
3747
+ return "Cursor runs locally; review the commits on the run branch";
3748
+ }
3749
+ return result.prUrl ?? (result.prNumber ? `gh pr view ${result.prNumber}` : void 0);
3750
+ }
3751
+ displayLocalFastSummary(results) {
3752
+ const retained = results.filter((r) => r.retainedWorktreePath);
3753
+ if (retained.length === 0) {
3754
+ console.log(chalk3.gray("No retained local worktrees (clean)"));
3755
+ return;
3756
+ }
3757
+ console.log(chalk3.bold.blue("Local fast-path worktrees:"));
3758
+ retained.forEach((variant) => {
3759
+ const label = this.formatProviderVariantLabel(variant);
3760
+ console.log(
3761
+ chalk3.gray(
3762
+ ` \u2022 ${label}: ${variant.retainedWorktreePath}${// Show workspace edits: prefer requested count (includes git-detected), fallback to applied
3763
+ (variant.workspaceEditsRequested ?? variant.workspaceEditsApplied) !== void 0 ? ` (${variant.workspaceEditsRequested ?? variant.workspaceEditsApplied} file${(variant.workspaceEditsRequested ?? variant.workspaceEditsApplied) === 1 ? "" : "s"} changed)` : ""}`
3764
+ )
3765
+ );
3766
+ if (variant.worktreeSummary) {
3767
+ console.log(
3768
+ chalk3.gray(
3769
+ ` Diff: ${variant.worktreeSummary.filesChanged} files (+${variant.worktreeSummary.insertions}/-${variant.worktreeSummary.deletions})`
3770
+ )
3771
+ );
3772
+ variant.worktreeSummary.statusLines.slice(0, 5).forEach((line) => {
3773
+ console.log(chalk3.gray(` ${line}`));
3774
+ });
3775
+ if (variant.worktreeSummary.statusLines.length > 5) {
3776
+ console.log(
3777
+ chalk3.gray(` \u2026 ${variant.worktreeSummary.statusLines.length - 5} more file(s)`)
3778
+ );
3779
+ }
3780
+ }
3781
+ console.log(
3782
+ chalk3.cyan(
3783
+ ` Next: cd ${variant.retainedWorktreePath} && git status && git commit -am "<message>"`
3784
+ )
3785
+ );
3786
+ });
3787
+ console.log();
3788
+ }
3789
+ capitalizeWords(value) {
3790
+ return value.split(/[\s_-]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
3791
+ }
3792
+ /**
3793
+ * Retrieve cached branch list or fetch fresh from git
3794
+ * Implements 60-second TTL cache to reduce git operations during cleanup
3795
+ * Thread-safe: validates timestamp before use
3796
+ *
3797
+ * @param taskId - Task ID for cache key
3798
+ * @param pattern - Git branch pattern (e.g., "origin/feature/T123-*")
3799
+ * @returns Array of matching branch names
3800
+ */
3801
+ async getCachedBranchList(taskId, pattern) {
3802
+ const now = Date.now();
3803
+ const cached = this.branchListCache.get(taskId);
3804
+ if (cached && now - cached.timestamp < this.BRANCH_LIST_CACHE_TTL_MS) {
3805
+ if (this.verbose) {
3806
+ console.log(
3807
+ chalk3.gray(
3808
+ ` [cache hit] Using cached branch list for task ${taskId} (${Math.round((now - cached.timestamp) / 1e3)}s old)`
3809
+ )
3810
+ );
3811
+ }
3812
+ return cached.branches;
3813
+ }
3814
+ if (this.verbose && cached) {
3815
+ console.log(
3816
+ chalk3.gray(
3817
+ ` [cache expired] Refreshing branch list for task ${taskId} (${Math.round((now - cached.timestamp) / 1e3)}s old)`
3818
+ )
3819
+ );
3820
+ }
3821
+ try {
3822
+ const { execa: execa2 } = await import("execa");
3823
+ const { stdout } = await execa2("git", ["branch", "-r", "--list", pattern], {
3824
+ cwd: this.repoRoot,
3825
+ reject: false
3826
+ });
3827
+ const branches = stdout.split("\n").map((b) => b.trim()).filter(Boolean);
3828
+ this.branchListCache.set(taskId, {
3829
+ branches,
3830
+ timestamp: now
3831
+ });
3832
+ if (this.verbose) {
3833
+ console.log(
3834
+ chalk3.gray(` [cache set] Cached ${branches.length} branches for task ${taskId}`)
3835
+ );
3836
+ }
3837
+ return branches;
3838
+ } catch (_error) {
3839
+ if (cached) {
3840
+ if (this.verbose) {
3841
+ console.log(
3842
+ chalk3.yellow(
3843
+ `Git branch list failed for task ${taskId}, using stale cache (${Math.round((now - cached.timestamp) / 1e3)}s old)`
3844
+ )
3845
+ );
3846
+ }
3847
+ return cached.branches;
3848
+ }
3849
+ return [];
3850
+ }
3851
+ }
3852
+ /**
3853
+ * Clear branch list cache entries (best-effort cleanup)
3854
+ * Can be called during orchestrator shutdown to free memory
3855
+ * Optionally filter by taskId, or clear all entries if taskId is undefined
3856
+ *
3857
+ * @param taskId - Optional task ID to clear specific cache entry, or undefined to clear all
3858
+ */
3859
+ clearBranchListCache(taskId) {
3860
+ if (taskId) {
3861
+ const hadEntry = this.branchListCache.has(taskId);
3862
+ this.branchListCache.delete(taskId);
3863
+ if (this.verbose && hadEntry) {
3864
+ console.log(chalk3.gray(` [cache cleared] Removed branch list cache for task ${taskId}`));
3865
+ }
3866
+ } else {
3867
+ const size = this.branchListCache.size;
3868
+ this.branchListCache.clear();
3869
+ if (this.verbose && size > 0) {
3870
+ console.log(chalk3.gray(` [cache cleared] Cleared ${size} branch list cache entries`));
3871
+ }
3872
+ }
3873
+ }
3874
+ /**
3875
+ * Best-effort removal of orphan competition branches that may not have associated PR results
3876
+ * Pattern: origin/poetic/var-{taskId}-*
3877
+ * - Deletes remote branches first, then attempts local removal
3878
+ * - Skips winner branch if identifiable
3879
+ */
3880
+ async cleanupOrphanBranchesByTask(taskId, winner) {
3881
+ try {
3882
+ const { execa: execa2 } = await import("execa");
3883
+ const pattern = `origin/${poeticVariantBranchPrefix(taskId)}*`;
3884
+ const remoteBranches = await this.getCachedBranchList(taskId, pattern);
3885
+ if (remoteBranches.length === 0) {
3886
+ return 0;
3887
+ }
3888
+ let winnerBranch;
3889
+ if (winner?.prNumber) {
3890
+ try {
3891
+ winnerBranch = await this.prManager.getPRBranch(winner.prNumber);
3892
+ } catch (error) {
3893
+ const msg = error instanceof Error ? error.message : String(error);
3894
+ console.warn(
3895
+ chalk3.yellow(
3896
+ `Skipping orphan branch cleanup for task ${taskId}: failed to resolve winner branch for PR #${winner.prNumber}: ${msg}`
3897
+ )
3898
+ );
3899
+ return 0;
3900
+ }
3901
+ } else {
3902
+ if (this.verbose) {
3903
+ emitWarning(
3904
+ "PR-001",
3905
+ {
3906
+ taskId,
3907
+ subsystem: "orchestrator",
3908
+ executionPhase: "cleanup"
3909
+ },
3910
+ {
3911
+ severity: "INFO" /* INFO */,
3912
+ metadata: {
3913
+ operation: "skipOrphanBranchCleanup",
3914
+ reason: "winner has no PR number, cannot identify winning branch"
3915
+ }
3916
+ }
3917
+ );
3918
+ }
3919
+ return 0;
3920
+ }
3921
+ let deletedCount = 0;
3922
+ for (const fullRef of remoteBranches) {
3923
+ const branch = fullRef.replace(/^origin\//, "");
3924
+ if (winnerBranch) {
3925
+ const isExactMatch = branch === winnerBranch;
3926
+ if (isExactMatch) {
3927
+ if (this.verbose) {
3928
+ console.log(chalk3.gray(` Skipping winner branch: ${branch}`));
3929
+ }
3930
+ continue;
3931
+ }
3932
+ }
3933
+ if (isProtectedPipelineBranch(branch)) {
3934
+ continue;
3935
+ }
3936
+ try {
3937
+ await this.prManager.deleteBranch(branch, {
3938
+ deleteLocal: true,
3939
+ deleteRemote: true,
3940
+ force: true,
3941
+ cwd: this.repoRoot
3942
+ });
3943
+ deletedCount++;
3944
+ } catch (_error) {
3945
+ try {
3946
+ const result = await execa2("git", ["push", "origin", "--delete", branch], {
3947
+ cwd: this.repoRoot,
3948
+ reject: false
3949
+ });
3950
+ if (result.exitCode === 0) {
3951
+ deletedCount++;
3952
+ continue;
3953
+ }
3954
+ const message = `${result.stderr ?? ""}
3955
+ ${result.stdout ?? ""}`.trim();
3956
+ if (isRemoteBranchMissingError(message)) {
3957
+ deletedCount++;
3958
+ continue;
3959
+ }
3960
+ if (isRetryableRemoteDeleteError(message)) {
3961
+ const expectedRemoteSha = await resolveExpectedRemoteShaForQueuedBranch(branch, {
3962
+ remote: "origin",
3963
+ cwd: this.repoRoot
3964
+ });
3965
+ await enqueueRemoteBranchCleanup(branch, {
3966
+ remote: "origin",
3967
+ reason: "cleanupOrphanBranchesByTask(fallback)",
3968
+ expectedRemoteSha,
3969
+ cwd: this.repoRoot
3970
+ }).catch(() => {
3971
+ });
3972
+ }
3973
+ } catch (error) {
3974
+ console.warn(
3975
+ `Failed to delete remote branch: ${error instanceof Error ? error.message : String(error)}`
3976
+ );
3977
+ debugLog("Full stack:", error);
3978
+ }
3979
+ }
3980
+ }
3981
+ return deletedCount;
3982
+ } catch (_error) {
3983
+ return 0;
3984
+ }
3985
+ }
3986
+ /**
3987
+ * Determine if prompt optimization should be triggered for these results
3988
+ * Only trigger if we have at least 2 successful variants
3989
+ */
3990
+ shouldTriggerOptimization(results) {
3991
+ if (!this.enablePromptOptimization) {
3992
+ return false;
3993
+ }
3994
+ const successfulVariants = results.filter((r) => r && r.success === true);
3995
+ return successfulVariants.length >= 2;
3996
+ }
3997
+ /**
3998
+ * Get telemetry logger instance (if available)
3999
+ * Returns undefined if telemetry is not available
4000
+ */
4001
+ getTelemetryLogger() {
4002
+ try {
4003
+ return TelemetryLogger.getInstance();
4004
+ } catch {
4005
+ return void 0;
4006
+ }
4007
+ }
4008
+ logVariantStartSafe(taskId, variant) {
4009
+ try {
4010
+ this.variantOrchestrator.logVariantStart(
4011
+ taskId,
4012
+ formatVariantIdentifier(variant),
4013
+ "unversioned",
4014
+ {
4015
+ provider: variant.provider,
4016
+ model: variant.model,
4017
+ executionMode: variant.executionMode,
4018
+ strategy: variant.strategy
4019
+ }
4020
+ );
4021
+ } catch (_error) {
4022
+ }
4023
+ }
4024
+ logVariantCompleteSafe(taskId, variant, result) {
4025
+ try {
4026
+ this.variantOrchestrator.logVariantComplete(
4027
+ taskId,
4028
+ formatVariantIdentifier(variant),
4029
+ result,
4030
+ result.prNumber,
4031
+ {
4032
+ provider: variant.provider,
4033
+ model: result.model || variant.model,
4034
+ executionMode: variant.executionMode,
4035
+ strategy: variant.strategy
4036
+ }
4037
+ );
4038
+ } catch (_error) {
4039
+ }
4040
+ }
4041
+ buildFailureResult(variant, error, durationSeconds) {
4042
+ const normalizedError = error instanceof Error ? error : new Error(String(error));
4043
+ const variantId = `${variant.provider}:${variant.model ?? "default"}:${variant.strategy}:${variant.executionMode ?? "local"}`;
4044
+ return {
4045
+ variant: variantId,
4046
+ provider: variant.provider,
4047
+ model: variant.model,
4048
+ strategy: variant.strategy,
4049
+ executionMode: variant.executionMode,
4050
+ success: false,
4051
+ error: normalizedError,
4052
+ duration: Math.max(0, durationSeconds),
4053
+ completeness: 0,
4054
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4055
+ };
4056
+ }
4057
+ shouldPreserveSubmittedOnly() {
4058
+ return false;
4059
+ }
4060
+ /**
4061
+ * Close resources
4062
+ */
4063
+ async close() {
4064
+ if (this.verbose) {
4065
+ console.log(chalk3.gray("Closing PRWorkflowOrchestrator..."));
4066
+ }
4067
+ const closers = [];
4068
+ try {
4069
+ if (this.localExecutor && typeof this.localExecutor.close === "function") {
4070
+ closers.push(Promise.resolve(this.localExecutor.close()));
4071
+ }
4072
+ } catch {
4073
+ }
4074
+ if (closers.length > 0) {
4075
+ await Promise.allSettled(closers);
4076
+ }
4077
+ this.variantOrchestrator.close();
4078
+ if (this.judgeListenerCleanup) {
4079
+ try {
4080
+ this.judgeListenerCleanup();
4081
+ } catch {
4082
+ }
4083
+ }
4084
+ if (this.resultStreamer && this.ownsResultStreamer) {
4085
+ try {
4086
+ this.resultStreamer.close();
4087
+ } catch {
4088
+ }
4089
+ }
4090
+ if (this.ownsProcessLifecycle) {
4091
+ try {
4092
+ await this.processLifecycle.close();
4093
+ } catch (error) {
4094
+ emitWarning(
4095
+ "PR-001",
4096
+ {
4097
+ taskId: "unknown",
4098
+ subsystem: "orchestrator",
4099
+ executionPhase: "cleanup"
4100
+ },
4101
+ {
4102
+ severity: "WARN" /* WARN */,
4103
+ metadata: {
4104
+ error: error instanceof Error ? error.message : String(error),
4105
+ operation: "processLifecycle.close"
4106
+ }
4107
+ }
4108
+ );
4109
+ } finally {
4110
+ if (getProcessLifecycleManager() === this.processLifecycle) {
4111
+ setProcessLifecycleManager(void 0);
4112
+ }
4113
+ }
4114
+ }
4115
+ if (this.verbose) {
4116
+ console.log(chalk3.green("PRWorkflowOrchestrator closed"));
4117
+ }
4118
+ }
4119
+ };
4120
+ async function executeVariantsLocalFast(taskId, prompt, variants, options = {}) {
4121
+ const prManager = new GitHubPRManager();
4122
+ let costTracker;
4123
+ try {
4124
+ const costCalculator = new UniversalCostCalculator(TelemetryLogger.getInstance());
4125
+ costTracker = new UnifiedCostTracker(costCalculator, TelemetryLogger.getInstance(), {
4126
+ enabled: true
4127
+ });
4128
+ } catch {
4129
+ costTracker = void 0;
4130
+ }
4131
+ const localExecutor = new LocalExecutor({
4132
+ prManager,
4133
+ verbose: options.verbose,
4134
+ costTracker,
4135
+ resultStreamer: options.resultStreamer,
4136
+ preserveWorktrees: options.preserveWorktrees ?? getRuntimeEnv("POETIC_PRESERVE_WORKTREES") === "1"
4137
+ });
4138
+ try {
4139
+ const outputs = [];
4140
+ for (const variant of variants) {
4141
+ if (variant.executionMode !== "local") {
4142
+ throw new Error("Local fast path only supports variants with executionMode=local.");
4143
+ }
4144
+ const result = await localExecutor.executeVariantFastWithRetry(taskId, variant, prompt, {
4145
+ commit: options.commit,
4146
+ cleanup: options.cleanup
4147
+ });
4148
+ outputs.push(result);
4149
+ }
4150
+ return {
4151
+ taskId,
4152
+ variants: outputs,
4153
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4154
+ };
4155
+ } finally {
4156
+ await localExecutor.close();
4157
+ }
4158
+ }
4159
+
4160
+ // src/orchestrator/judge-completeness-telemetry.ts
4161
+ function isRecord(value) {
4162
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4163
+ }
4164
+ function toJsonValue(value) {
4165
+ if (value === null) return null;
4166
+ if (typeof value === "string" || typeof value === "boolean") return value;
4167
+ if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
4168
+ if (Array.isArray(value)) {
4169
+ return value.map((item) => toJsonValue(item)).filter((item) => item !== void 0);
4170
+ }
4171
+ if (isRecord(value)) {
4172
+ const record = {};
4173
+ for (const [key, item] of Object.entries(value)) {
4174
+ const jsonValue = toJsonValue(item);
4175
+ if (jsonValue !== void 0) {
4176
+ record[key] = jsonValue;
4177
+ }
4178
+ }
4179
+ return record;
4180
+ }
4181
+ return void 0;
4182
+ }
4183
+ function asJsonArray(value) {
4184
+ const jsonValue = toJsonValue(value);
4185
+ return Array.isArray(jsonValue) && jsonValue.length > 0 ? jsonValue : void 0;
4186
+ }
4187
+ function getStringArray(value) {
4188
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
4189
+ }
4190
+ function collectNegativeSpace(workerPackets) {
4191
+ if (!Array.isArray(workerPackets)) return void 0;
4192
+ const entries = [];
4193
+ for (const packet of workerPackets) {
4194
+ if (!isRecord(packet) || typeof packet.variantId !== "string") continue;
4195
+ const items = getStringArray(packet.negativeSpace);
4196
+ if (items.length > 0) {
4197
+ entries.push({ variant: packet.variantId, items });
4198
+ }
4199
+ }
4200
+ return entries.length > 0 ? entries : void 0;
4201
+ }
4202
+ function collectEvidenceConcerns(workerEvidenceMatrix) {
4203
+ if (!isRecord(workerEvidenceMatrix)) return void 0;
4204
+ const concerns = [];
4205
+ const criteriaRows = Array.isArray(workerEvidenceMatrix.criteriaRows) ? workerEvidenceMatrix.criteriaRows : [];
4206
+ for (const row of criteriaRows) {
4207
+ if (!isRecord(row) || !isRecord(row.variants)) continue;
4208
+ const item = typeof row.criterion === "string" ? row.criterion : typeof row.criterionKey === "string" ? row.criterionKey : "acceptance criterion";
4209
+ for (const [variant, cell] of Object.entries(row.variants)) {
4210
+ if (!isRecord(cell)) continue;
4211
+ const evidenceStatus = cell.evidenceStatus === "valid" || cell.evidenceStatus === "invalid" || cell.evidenceStatus === "missing" ? cell.evidenceStatus : void 0;
4212
+ const evidenceKind = typeof cell.evidenceKind === "string" ? cell.evidenceKind : void 0;
4213
+ const category = evidenceKind === "unverifiable" || evidenceStatus === "invalid" ? "unverifiable" : evidenceStatus === "missing" || evidenceKind === "missing" ? "missing" : void 0;
4214
+ if (category) {
4215
+ concerns.push({
4216
+ variant,
4217
+ item,
4218
+ category,
4219
+ ...evidenceStatus ? { evidenceStatus } : {},
4220
+ ...evidenceKind ? { evidenceKind } : {}
4221
+ });
4222
+ }
4223
+ }
4224
+ }
4225
+ const emergentFindings = Array.isArray(workerEvidenceMatrix.emergentFindings) ? workerEvidenceMatrix.emergentFindings : [];
4226
+ for (const finding of emergentFindings) {
4227
+ if (!isRecord(finding) || !isRecord(finding.variants)) continue;
4228
+ const item = typeof finding.finding === "string" ? finding.finding : typeof finding.findingKey === "string" ? finding.findingKey : "emergent finding";
4229
+ for (const [variant, cell] of Object.entries(finding.variants)) {
4230
+ if (!isRecord(cell)) continue;
4231
+ const evidenceStatus = cell.evidenceStatus === "valid" || cell.evidenceStatus === "invalid" || cell.evidenceStatus === "missing" ? cell.evidenceStatus : void 0;
4232
+ const status = typeof cell.status === "string" ? cell.status : void 0;
4233
+ const category = status === "unverifiable" || evidenceStatus === "invalid" ? "unverifiable" : evidenceStatus === "missing" ? "missing" : void 0;
4234
+ if (category) {
4235
+ concerns.push({
4236
+ variant,
4237
+ item,
4238
+ category,
4239
+ ...evidenceStatus ? { evidenceStatus } : {}
4240
+ });
4241
+ }
4242
+ }
4243
+ }
4244
+ return concerns.length > 0 ? concerns : void 0;
4245
+ }
4246
+ function buildJudgeCompletenessTelemetryFromEvaluation(judgeEvaluation) {
4247
+ const audit = judgeEvaluation?.metadata?.audit;
4248
+ if (!isRecord(audit)) return void 0;
4249
+ const coverageGaps = asJsonArray(audit.coverageGaps);
4250
+ const negativeSpaceByVariant = collectNegativeSpace(audit.workerPackets);
4251
+ const evidenceConcerns = collectEvidenceConcerns(audit.workerEvidenceMatrix);
4252
+ const workerEvidenceMatrix = toJsonValue(audit.workerEvidenceMatrix);
4253
+ if (!coverageGaps && !negativeSpaceByVariant && !evidenceConcerns && workerEvidenceMatrix === void 0) {
4254
+ return void 0;
4255
+ }
4256
+ return {
4257
+ source: "judge-audit",
4258
+ ...coverageGaps ? { coverageGaps } : {},
4259
+ ...negativeSpaceByVariant ? { negativeSpaceByVariant } : {},
4260
+ ...evidenceConcerns ? { evidenceConcerns } : {},
4261
+ ...workerEvidenceMatrix !== void 0 ? { workerEvidenceMatrix } : {}
4262
+ };
4263
+ }
4264
+ function buildJudgeCompletenessTelemetryFromVariants(variants) {
4265
+ for (const variant of variants) {
4266
+ const telemetry = buildJudgeCompletenessTelemetryFromEvaluation(variant.judgeEvaluation);
4267
+ if (telemetry) return telemetry;
4268
+ }
4269
+ return void 0;
4270
+ }
4271
+
4272
+ // src/cli/competition-interruption.ts
4273
+ function shouldStopBeforeJudgeOrSynthesis(isShuttingDown, variants) {
4274
+ return isShuttingDown || variants.some((variant) => variant.terminationReason === "canceled_user");
4275
+ }
4276
+
4277
+ // src/cli/handlers/compete/concurrency-config.ts
4278
+ function asValidConcurrency(value) {
4279
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
4280
+ }
4281
+ async function loadConfiguredConcurrency(explicitRequest) {
4282
+ if (explicitRequest !== void 0) return {};
4283
+ try {
4284
+ const merged = await new ConfigManager().loadConfig();
4285
+ return {
4286
+ maxConcurrent: asValidConcurrency(merged.config.variants?.maxConcurrent),
4287
+ worktreeMax: asValidConcurrency(merged.config.worktree?.maxConcurrent)
4288
+ };
4289
+ } catch (error) {
4290
+ rethrowConfigValidityError(error);
4291
+ return {};
4292
+ }
4293
+ }
4294
+ function concurrencyAdvisoryMessage(effectiveMaxConcurrent) {
4295
+ if (typeof effectiveMaxConcurrent !== "number") return void 0;
4296
+ const legSlots = detectHostConcurrencyBudget().legSlots;
4297
+ if (effectiveMaxConcurrent <= legSlots) return void 0;
4298
+ return `Requested concurrency ${effectiveMaxConcurrent} exceeds this host's recommendation of ${legSlots} legs (see poetic doctor); running as asked with validation pacing.`;
4299
+ }
4300
+
4301
+ // src/cli/handlers/compete/research-trace-persistence.ts
4302
+ import { mkdir, writeFile } from "fs/promises";
4303
+ import path2 from "path";
4304
+ function resolveNativeResearchTraceDir(poeticDir, taskId, resolver = LabPathResolver.getInstance()) {
4305
+ const labContext = resolver.getContext();
4306
+ if (labContext) {
4307
+ return path2.join(
4308
+ poeticDir,
4309
+ "labs",
4310
+ labContext.labId,
4311
+ "runs",
4312
+ labContext.runId,
4313
+ "research",
4314
+ taskId
4315
+ );
4316
+ }
4317
+ return path2.join(poeticDir, "research", taskId);
4318
+ }
4319
+ async function persistNativeResearchTraces(input) {
4320
+ const traceDir = input.traceDir ?? resolveNativeResearchTraceDir(
4321
+ input.poeticDir ?? path2.join(process.cwd(), ".poetic"),
4322
+ input.taskId
4323
+ );
4324
+ const cleared = new Set(
4325
+ Array.from(input.clearedProviders, (provider) => provider.trim().toLowerCase())
4326
+ );
4327
+ let traceDirReady = false;
4328
+ let tracesPersisted = 0;
4329
+ const failures = [];
4330
+ for (const variant of input.variants) {
4331
+ if (variant.success !== true) continue;
4332
+ if (!cleared.has(variant.provider.trim().toLowerCase())) continue;
4333
+ const variantKey = formatVariantIdentifierFromResult(variant);
4334
+ const trace = parseCitationTrace({
4335
+ variantId: variantKey,
4336
+ provider: variant.provider,
4337
+ mode: "native",
4338
+ output: variant.result?.stdout ?? variant.output ?? "",
4339
+ corroboratedUrls: variant.result?.researchCorroboratedUrls,
4340
+ observedWebToolEvent: variant.result?.researchObservedWebToolEvent,
4341
+ excludedDomains: input.excludedDomains
4342
+ });
4343
+ variant.researchTrace = trace;
4344
+ try {
4345
+ if (!traceDirReady) {
4346
+ await mkdir(traceDir, { recursive: true });
4347
+ traceDirReady = true;
4348
+ }
4349
+ const tracePath = path2.join(
4350
+ traceDir,
4351
+ `${toVariantSlug(variantKey) || "variant"}-research-trace.json`
4352
+ );
4353
+ trace.artifactPath = tracePath;
4354
+ await writeFile(tracePath, serializeCitationTrace(trace), "utf-8");
4355
+ tracesPersisted++;
4356
+ } catch (error) {
4357
+ failures.push({
4358
+ variantId: variantKey,
4359
+ error: error instanceof Error ? error.message : String(error)
4360
+ });
4361
+ }
4362
+ }
4363
+ const totalCitations = input.variants.reduce(
4364
+ (sum, variant) => sum + (variant.researchTrace?.citations.length ?? 0),
4365
+ 0
4366
+ );
4367
+ const excludedDomainViolations = input.variants.reduce(
4368
+ (sum, variant) => sum + (variant.researchTrace?.citations.filter((citation) => citation.excludedDomainViolation).length ?? 0),
4369
+ 0
4370
+ );
4371
+ return { traceDir, totalCitations, excludedDomainViolations, tracesPersisted, failures };
4372
+ }
4373
+
4374
+ export {
4375
+ DependencyGraphResolver,
4376
+ validateVerbosity,
4377
+ PRWorkflowOrchestrator,
4378
+ executeVariantsLocalFast,
4379
+ buildJudgeCompletenessTelemetryFromVariants,
4380
+ shouldStopBeforeJudgeOrSynthesis,
4381
+ loadConfiguredConcurrency,
4382
+ concurrencyAdvisoryMessage,
4383
+ resolveNativeResearchTraceDir,
4384
+ persistNativeResearchTraces
4385
+ };
4386
+ //# sourceMappingURL=chunk-WGXYDLMX.js.map