@poetic-ai/poetic 1.42.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 (782) 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-JIMGP3LY.js +1597 -0
  17. package/dist/PromptStore-U6ZD3ZMQ.js +18 -0
  18. package/dist/actions-LUJPINLJ.js +322 -0
  19. package/dist/agent-ingest-3DJUJ7FU.js +53 -0
  20. package/dist/aggregator-DNCBINFO.js +12 -0
  21. package/dist/ai-judge-5QT5QJVU.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-JULUCUIK.js +489 -0
  25. package/dist/api-transport-4TYTNLTJ.js +1087 -0
  26. package/dist/apply-completion-mode-AW2MOS3R.js +89 -0
  27. package/dist/artifact-migrator-23L45ISD.js +267 -0
  28. package/dist/ask-HWVV6QFR.js +135 -0
  29. package/dist/auth-5KEDKAPP.js +67 -0
  30. package/dist/auth-7TT3JINV.js +78 -0
  31. package/dist/auth-E6XUNZ5M.js +68 -0
  32. package/dist/auth-H3XDZE22.js +134 -0
  33. package/dist/auth-OC4E6633.js +71 -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-VPRWOWGU.js +80 -0
  38. package/dist/autoloop-cleanup-JOGKTLWA.js +109 -0
  39. package/dist/autoloop-evidence-gates-PCDALGVJ.js +38 -0
  40. package/dist/autoloop-gate-policy-Z7FVJVXV.js +175 -0
  41. package/dist/autoloop-helpers-2KTK43GL.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-J2VKKBXQ.js +85 -0
  47. package/dist/autoloop-termination-summary-RN75F422.js +58 -0
  48. package/dist/autoloop-trajectory-XFIEXP5Z.js +282 -0
  49. package/dist/autoloop-wall-clock-T7ZVIQOC.js +12 -0
  50. package/dist/autonomous-loop-controller-PW4XVFGQ.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-VCSBJVRN.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-YHGRB4QB.js +71 -0
  60. package/dist/change-summary-WY7J5TOX.js +33 -0
  61. package/dist/chunk-23A26CSN.js +123 -0
  62. package/dist/chunk-27UTJD3M.js +265 -0
  63. package/dist/chunk-2A5CILN3.js +310 -0
  64. package/dist/chunk-2AQUWJPW.js +225 -0
  65. package/dist/chunk-2BZ53J6J.js +2344 -0
  66. package/dist/chunk-2DY5KNVM.js +276 -0
  67. package/dist/chunk-2EIA4RBE.js +659 -0
  68. package/dist/chunk-2IUXIGQD.js +1064 -0
  69. package/dist/chunk-2N42MS2Z.js +2193 -0
  70. package/dist/chunk-2QJ3H3L7.js +42 -0
  71. package/dist/chunk-2QLYTVYX.js +791 -0
  72. package/dist/chunk-2VSQMRCB.js +18 -0
  73. package/dist/chunk-2XQXYBM2.js +130 -0
  74. package/dist/chunk-2YFUIER7.js +426 -0
  75. package/dist/chunk-34CNP2HB.js +148 -0
  76. package/dist/chunk-35P3W3JX.js +456 -0
  77. package/dist/chunk-36PEBZAF.js +18 -0
  78. package/dist/chunk-3AOKYKA7.js +22 -0
  79. package/dist/chunk-3BCUNHKF.js +475 -0
  80. package/dist/chunk-3FLXLLB7.js +26 -0
  81. package/dist/chunk-3FOZ2VHV.js +100 -0
  82. package/dist/chunk-3G6FZCRF.js +106 -0
  83. package/dist/chunk-3M57DADF.js +44 -0
  84. package/dist/chunk-3S62LLWJ.js +543 -0
  85. package/dist/chunk-3ZPQLGV7.js +2904 -0
  86. package/dist/chunk-44N5WZZH.js +45 -0
  87. package/dist/chunk-45FPSA3B.js +125 -0
  88. package/dist/chunk-4BJ3O4RQ.js +929 -0
  89. package/dist/chunk-4BOP7T6L.js +2321 -0
  90. package/dist/chunk-4BTDUT2S.js +42 -0
  91. package/dist/chunk-4CSS7WVI.js +143 -0
  92. package/dist/chunk-4CUY7AFY.js +247 -0
  93. package/dist/chunk-4GSN5O5J.js +62 -0
  94. package/dist/chunk-4HN6DF7V.js +1027 -0
  95. package/dist/chunk-4IAPOG5V.js +415 -0
  96. package/dist/chunk-4IYIZQWV.js +48 -0
  97. package/dist/chunk-4NXPXE62.js +84 -0
  98. package/dist/chunk-4RCCF5BR.js +712 -0
  99. package/dist/chunk-4V7NAQ4R.js +19527 -0
  100. package/dist/chunk-4VJITV4P.js +445 -0
  101. package/dist/chunk-4YX7J6QL.js +1859 -0
  102. package/dist/chunk-527OBWQB.js +338 -0
  103. package/dist/chunk-5D4A7E3D.js +448 -0
  104. package/dist/chunk-5DLKYTQX.js +4003 -0
  105. package/dist/chunk-5EERLVZB.js +139 -0
  106. package/dist/chunk-5H72XE4H.js +256 -0
  107. package/dist/chunk-5HDP7XZG.js +91 -0
  108. package/dist/chunk-5LAMRH4X.js +969 -0
  109. package/dist/chunk-5LTN43AS.js +1972 -0
  110. package/dist/chunk-5RBHQYDB.js +2206 -0
  111. package/dist/chunk-5WCQRDRB.js +588 -0
  112. package/dist/chunk-5WRLK5KW.js +700 -0
  113. package/dist/chunk-5ZCXC23G.js +595 -0
  114. package/dist/chunk-6BM72ZMG.js +31 -0
  115. package/dist/chunk-6EDAJH2I.js +68 -0
  116. package/dist/chunk-6EQKFDBH.js +457 -0
  117. package/dist/chunk-6MFRHTRI.js +115 -0
  118. package/dist/chunk-6TZJRKNW.js +321 -0
  119. package/dist/chunk-6V7HGQFZ.js +20 -0
  120. package/dist/chunk-6VWVO2TU.js +3746 -0
  121. package/dist/chunk-6Y5TWI7H.js +146 -0
  122. package/dist/chunk-6Y5U7UFY.js +91 -0
  123. package/dist/chunk-6ZLAK3XG.js +14 -0
  124. package/dist/chunk-72XCRQED.js +34 -0
  125. package/dist/chunk-72YTZMAM.js +589 -0
  126. package/dist/chunk-73BBJOKA.js +263 -0
  127. package/dist/chunk-73NCTWKL.js +188 -0
  128. package/dist/chunk-77I6G4CO.js +1 -0
  129. package/dist/chunk-7DHRDWFS.js +3104 -0
  130. package/dist/chunk-7DNSNKJV.js +78 -0
  131. package/dist/chunk-7FMJVYBS.js +307 -0
  132. package/dist/chunk-7GDRQBQC.js +419 -0
  133. package/dist/chunk-7GPCEFUV.js +270 -0
  134. package/dist/chunk-7IL4A2PP.js +948 -0
  135. package/dist/chunk-7MMLMXO6.js +3679 -0
  136. package/dist/chunk-7QCZSLBH.js +1 -0
  137. package/dist/chunk-7R2WLDOS.js +62 -0
  138. package/dist/chunk-7T7RUJI7.js +949 -0
  139. package/dist/chunk-A2WKSVX7.js +43 -0
  140. package/dist/chunk-A3YGID55.js +133 -0
  141. package/dist/chunk-A722DEVA.js +14 -0
  142. package/dist/chunk-ACDIT7OP.js +1376 -0
  143. package/dist/chunk-ACKIPAOJ.js +302 -0
  144. package/dist/chunk-APPNGGN7.js +365 -0
  145. package/dist/chunk-APV6MK5E.js +137 -0
  146. package/dist/chunk-ASEP3M2W.js +968 -0
  147. package/dist/chunk-AT4TNPWW.js +2931 -0
  148. package/dist/chunk-ATVKCSGT.js +250 -0
  149. package/dist/chunk-AURFMVCD.js +899 -0
  150. package/dist/chunk-AX6GWE7V.js +47 -0
  151. package/dist/chunk-AY5EWJPF.js +385 -0
  152. package/dist/chunk-BAV2HJXS.js +194 -0
  153. package/dist/chunk-BBHRN366.js +89 -0
  154. package/dist/chunk-BBPSTTPA.js +1004 -0
  155. package/dist/chunk-BDATUDDJ.js +992 -0
  156. package/dist/chunk-BKE5PG5L.js +20414 -0
  157. package/dist/chunk-BLPHWMDK.js +797 -0
  158. package/dist/chunk-BSE4R6XD.js +322 -0
  159. package/dist/chunk-BXGMAU4A.js +396 -0
  160. package/dist/chunk-BXI4NXL3.js +507 -0
  161. package/dist/chunk-BZU2O43F.js +1125 -0
  162. package/dist/chunk-C3L6YQ7P.js +147 -0
  163. package/dist/chunk-C57KJOUQ.js +121 -0
  164. package/dist/chunk-CCV7BPSY.js +118 -0
  165. package/dist/chunk-CD7ISXA4.js +826 -0
  166. package/dist/chunk-CE5OZBYY.js +21 -0
  167. package/dist/chunk-CFBIG37O.js +154 -0
  168. package/dist/chunk-CJC6GZ46.js +457 -0
  169. package/dist/chunk-CKCDGXIV.js +408 -0
  170. package/dist/chunk-CKNX3TTP.js +10338 -0
  171. package/dist/chunk-CLKSETWE.js +10 -0
  172. package/dist/chunk-CP7H3HSP.js +1552 -0
  173. package/dist/chunk-CPLEWXNZ.js +66 -0
  174. package/dist/chunk-CQM3A35X.js +844 -0
  175. package/dist/chunk-CS6P76D3.js +103 -0
  176. package/dist/chunk-CTLUBNCW.js +622 -0
  177. package/dist/chunk-CUSRN6RJ.js +632 -0
  178. package/dist/chunk-D5EP5D2W.js +26 -0
  179. package/dist/chunk-D5RYINO7.js +412 -0
  180. package/dist/chunk-DBFS4HMH.js +751 -0
  181. package/dist/chunk-DC4ZYMXJ.js +115 -0
  182. package/dist/chunk-DCBZP442.js +9243 -0
  183. package/dist/chunk-DCYF7EKG.js +26 -0
  184. package/dist/chunk-DDMAFNUK.js +5351 -0
  185. package/dist/chunk-DF5SLDE4.js +966 -0
  186. package/dist/chunk-DJFW7SMX.js +348 -0
  187. package/dist/chunk-DQFLLBJW.js +121 -0
  188. package/dist/chunk-DSFM56OA.js +1203 -0
  189. package/dist/chunk-DTY4APYV.js +218 -0
  190. package/dist/chunk-DXH5JBRS.js +437 -0
  191. package/dist/chunk-E3NTPHEO.js +194 -0
  192. package/dist/chunk-E74LUIID.js +302 -0
  193. package/dist/chunk-EI57M5BI.js +194 -0
  194. package/dist/chunk-EJ4ZAWLV.js +305 -0
  195. package/dist/chunk-EJGCZGUF.js +1483 -0
  196. package/dist/chunk-EK2U3YEG.js +486 -0
  197. package/dist/chunk-ELMFYNV7.js +109 -0
  198. package/dist/chunk-ENRGKNR5.js +25 -0
  199. package/dist/chunk-ETYDXCK7.js +679 -0
  200. package/dist/chunk-EYRH3W74.js +239 -0
  201. package/dist/chunk-F23DIWNN.js +1024 -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-FD4ERYEG.js +22 -0
  207. package/dist/chunk-FH7WOJAE.js +79 -0
  208. package/dist/chunk-FHOWVDF5.js +1342 -0
  209. package/dist/chunk-FKAUPHMR.js +96 -0
  210. package/dist/chunk-FONNFJXA.js +137 -0
  211. package/dist/chunk-FQ7FSZRW.js +75 -0
  212. package/dist/chunk-FRG57FPM.js +240 -0
  213. package/dist/chunk-FUVP64ER.js +31 -0
  214. package/dist/chunk-FYOILAN5.js +6818 -0
  215. package/dist/chunk-G35UYQ6Z.js +69 -0
  216. package/dist/chunk-G36W2T2S.js +1143 -0
  217. package/dist/chunk-G3L2L5XZ.js +49 -0
  218. package/dist/chunk-G4THLFV3.js +148 -0
  219. package/dist/chunk-GAFJEYLK.js +29 -0
  220. package/dist/chunk-GFGYB2ZU.js +1689 -0
  221. package/dist/chunk-GG6KJYW6.js +85 -0
  222. package/dist/chunk-GHHFDU2U.js +55 -0
  223. package/dist/chunk-GHTZSQB7.js +57 -0
  224. package/dist/chunk-GK37ILCX.js +1231 -0
  225. package/dist/chunk-GKN3HMN4.js +2809 -0
  226. package/dist/chunk-GNVDBVJP.js +156 -0
  227. package/dist/chunk-GPEL3FBM.js +924 -0
  228. package/dist/chunk-GPSNGPZS.js +1604 -0
  229. package/dist/chunk-GSGD5E4C.js +30 -0
  230. package/dist/chunk-GSUQJJXQ.js +331 -0
  231. package/dist/chunk-GSV226X6.js +110 -0
  232. package/dist/chunk-H2AYQIHW.js +224 -0
  233. package/dist/chunk-H66DXFS5.js +1374 -0
  234. package/dist/chunk-H6G7QRMQ.js +35 -0
  235. package/dist/chunk-H7JAGHZT.js +59 -0
  236. package/dist/chunk-H7ZEFECA.js +316 -0
  237. package/dist/chunk-HAC6EHZZ.js +79 -0
  238. package/dist/chunk-HIO33P3G.js +19 -0
  239. package/dist/chunk-HMVQIPH3.js +547 -0
  240. package/dist/chunk-HOYBYAOA.js +257 -0
  241. package/dist/chunk-HX5P3CSP.js +1784 -0
  242. package/dist/chunk-I46EG2XQ.js +65 -0
  243. package/dist/chunk-I4NPDSCB.js +279 -0
  244. package/dist/chunk-I5WRT7ZR.js +514 -0
  245. package/dist/chunk-IC7I6YIJ.js +301 -0
  246. package/dist/chunk-IDCSOZVN.js +78 -0
  247. package/dist/chunk-IFCBYECK.js +112 -0
  248. package/dist/chunk-IFZCPEY2.js +66 -0
  249. package/dist/chunk-IKFP2KUR.js +48 -0
  250. package/dist/chunk-IRFBN336.js +878 -0
  251. package/dist/chunk-IUXNGKA6.js +152 -0
  252. package/dist/chunk-IV2RVAN7.js +1356 -0
  253. package/dist/chunk-IZYIQQ7X.js +53 -0
  254. package/dist/chunk-J3UUR7DE.js +210 -0
  255. package/dist/chunk-J54VUAY2.js +566 -0
  256. package/dist/chunk-J62KPGII.js +464 -0
  257. package/dist/chunk-J6P3FWWW.js +130 -0
  258. package/dist/chunk-JKBHJQMT.js +434 -0
  259. package/dist/chunk-JLS65NUQ.js +14 -0
  260. package/dist/chunk-JOSYEJKY.js +141 -0
  261. package/dist/chunk-JPKSXKNB.js +94 -0
  262. package/dist/chunk-JQNJB2BB.js +2440 -0
  263. package/dist/chunk-JRVNSWSQ.js +2626 -0
  264. package/dist/chunk-JSWMRQYG.js +28 -0
  265. package/dist/chunk-JZKNBBIB.js +152 -0
  266. package/dist/chunk-K54Y7MLK.js +160 -0
  267. package/dist/chunk-K65546RE.js +183 -0
  268. package/dist/chunk-KM3F7SYE.js +702 -0
  269. package/dist/chunk-KNDYMVWN.js +102 -0
  270. package/dist/chunk-KNT72VR6.js +132 -0
  271. package/dist/chunk-KP6YILMU.js +482 -0
  272. package/dist/chunk-KQEBSK3T.js +274 -0
  273. package/dist/chunk-KT6VHSPF.js +84 -0
  274. package/dist/chunk-KTMW65UX.js +14 -0
  275. package/dist/chunk-KZ5CJVBP.js +1813 -0
  276. package/dist/chunk-L4427KOE.js +26 -0
  277. package/dist/chunk-L6OM4A22.js +189 -0
  278. package/dist/chunk-L7E6XCRA.js +1042 -0
  279. package/dist/chunk-L7JZLXQL.js +173 -0
  280. package/dist/chunk-LAMKBTXX.js +40 -0
  281. package/dist/chunk-LDCF2MKN.js +132 -0
  282. package/dist/chunk-LEIIWPWQ.js +78 -0
  283. package/dist/chunk-LFTQVYBB.js +31 -0
  284. package/dist/chunk-LG3PDRTR.js +2872 -0
  285. package/dist/chunk-LGHII5ET.js +23 -0
  286. package/dist/chunk-LH5QY22X.js +1205 -0
  287. package/dist/chunk-LIVJ6266.js +438 -0
  288. package/dist/chunk-LKRAR3IH.js +276 -0
  289. package/dist/chunk-LO23NABI.js +3063 -0
  290. package/dist/chunk-LO3X5NLS.js +326 -0
  291. package/dist/chunk-LPITVM7M.js +339 -0
  292. package/dist/chunk-LR5IJIGV.js +810 -0
  293. package/dist/chunk-LRGMHROI.js +79 -0
  294. package/dist/chunk-LUVKFFWR.js +315 -0
  295. package/dist/chunk-LWCBNGH6.js +35 -0
  296. package/dist/chunk-LWTN3WRV.js +260 -0
  297. package/dist/chunk-M3HQYKQX.js +308 -0
  298. package/dist/chunk-M6GVSPEH.js +1016 -0
  299. package/dist/chunk-MF5HP6XV.js +221 -0
  300. package/dist/chunk-MHLCBZJB.js +328 -0
  301. package/dist/chunk-MN6PL4AN.js +120 -0
  302. package/dist/chunk-MOEY65Z6.js +5678 -0
  303. package/dist/chunk-MQ4WA34C.js +206 -0
  304. package/dist/chunk-MWHF5V7U.js +223 -0
  305. package/dist/chunk-MWHLBPNU.js +211 -0
  306. package/dist/chunk-MWK5UZQ3.js +1068 -0
  307. package/dist/chunk-MYLH2S4G.js +64 -0
  308. package/dist/chunk-MZ5WYKNA.js +28 -0
  309. package/dist/chunk-N4VTRA7K.js +131 -0
  310. package/dist/chunk-N5DX4JAK.js +12 -0
  311. package/dist/chunk-N65O4XTH.js +5011 -0
  312. package/dist/chunk-NEQUQHOX.js +223 -0
  313. package/dist/chunk-NGK6PEOG.js +25 -0
  314. package/dist/chunk-NJVD4PWE.js +1033 -0
  315. package/dist/chunk-NM6PMYY4.js +768 -0
  316. package/dist/chunk-NN4PJDHP.js +708 -0
  317. package/dist/chunk-NP2V3L7K.js +226 -0
  318. package/dist/chunk-NRLY536M.js +260 -0
  319. package/dist/chunk-NRNE225N.js +1270 -0
  320. package/dist/chunk-NS2K2GTP.js +605 -0
  321. package/dist/chunk-NS33V3IM.js +51 -0
  322. package/dist/chunk-NSHASMZZ.js +71 -0
  323. package/dist/chunk-NWOYOA6H.js +378 -0
  324. package/dist/chunk-NWRUSEXG.js +322 -0
  325. package/dist/chunk-NZGDAWIP.js +1905 -0
  326. package/dist/chunk-O47UOKU3.js +395 -0
  327. package/dist/chunk-O4G2W3ST.js +9831 -0
  328. package/dist/chunk-O6V4PNLO.js +63 -0
  329. package/dist/chunk-OA4GPILI.js +624 -0
  330. package/dist/chunk-OGMSYL6J.js +227 -0
  331. package/dist/chunk-OIS7J26S.js +319 -0
  332. package/dist/chunk-OMX5VL43.js +79 -0
  333. package/dist/chunk-ON3G73BU.js +264 -0
  334. package/dist/chunk-OPYFYTWQ.js +220 -0
  335. package/dist/chunk-OQ6K46CK.js +1734 -0
  336. package/dist/chunk-OYZYO7TV.js +47 -0
  337. package/dist/chunk-OZ4REHIN.js +4386 -0
  338. package/dist/chunk-P47VN5F4.js +282 -0
  339. package/dist/chunk-P5I4X7A7.js +353 -0
  340. package/dist/chunk-P6VQROCO.js +594 -0
  341. package/dist/chunk-P7CQGPLS.js +30 -0
  342. package/dist/chunk-PCAGC5MR.js +1763 -0
  343. package/dist/chunk-PFTQBXS6.js +5181 -0
  344. package/dist/chunk-PGSPX4SU.js +15 -0
  345. package/dist/chunk-PIKLF7BM.js +432 -0
  346. package/dist/chunk-PJWJ3SAV.js +22 -0
  347. package/dist/chunk-PKIFMV72.js +100 -0
  348. package/dist/chunk-PL37JDNA.js +189 -0
  349. package/dist/chunk-PTH5E5XO.js +195 -0
  350. package/dist/chunk-PW6AXLQC.js +4128 -0
  351. package/dist/chunk-PYITM4N2.js +79 -0
  352. package/dist/chunk-PZ5AY32C.js +10 -0
  353. package/dist/chunk-Q3RO7N35.js +45 -0
  354. package/dist/chunk-Q3WIC6GQ.js +2670 -0
  355. package/dist/chunk-Q5XIXSHX.js +271 -0
  356. package/dist/chunk-QGJDMEOV.js +34 -0
  357. package/dist/chunk-QNOB37UH.js +58 -0
  358. package/dist/chunk-QOCOVLUH.js +462 -0
  359. package/dist/chunk-QTCJ5CC5.js +172 -0
  360. package/dist/chunk-QVFV5IP2.js +232 -0
  361. package/dist/chunk-QVZMFDYG.js +29 -0
  362. package/dist/chunk-R35PEUKH.js +511 -0
  363. package/dist/chunk-R4UWBC35.js +200 -0
  364. package/dist/chunk-R6MLCREW.js +44 -0
  365. package/dist/chunk-R6W23LKN.js +254 -0
  366. package/dist/chunk-R7XDDX2A.js +4007 -0
  367. package/dist/chunk-RDFRCT64.js +168 -0
  368. package/dist/chunk-RE5VZDFQ.js +58 -0
  369. package/dist/chunk-RGROYC2G.js +638 -0
  370. package/dist/chunk-RGWHUI5E.js +68 -0
  371. package/dist/chunk-RHVG6UNL.js +205 -0
  372. package/dist/chunk-RI4EX2QE.js +18 -0
  373. package/dist/chunk-RJAAKDRX.js +17 -0
  374. package/dist/chunk-ROMHOSMQ.js +185 -0
  375. package/dist/chunk-RWREC3KJ.js +517 -0
  376. package/dist/chunk-RYNETRDJ.js +118 -0
  377. package/dist/chunk-RZY7RKM5.js +500 -0
  378. package/dist/chunk-S2MNWFAG.js +52 -0
  379. package/dist/chunk-S2VQCZO4.js +22 -0
  380. package/dist/chunk-S54MKU6V.js +117 -0
  381. package/dist/chunk-S5OIDFRM.js +302 -0
  382. package/dist/chunk-SCW4ZF6R.js +150 -0
  383. package/dist/chunk-SLS2N4PH.js +2213 -0
  384. package/dist/chunk-SNLBO4BF.js +247 -0
  385. package/dist/chunk-SP3LFU6B.js +60 -0
  386. package/dist/chunk-SQQTDDQA.js +537 -0
  387. package/dist/chunk-STV6LYYE.js +45 -0
  388. package/dist/chunk-SURZ2WFE.js +326 -0
  389. package/dist/chunk-SZ7DL357.js +1047 -0
  390. package/dist/chunk-T5E4NQCM.js +5742 -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-TGQZHDY2.js +2373 -0
  397. package/dist/chunk-TJJZ2OKV.js +6783 -0
  398. package/dist/chunk-TRSVUPCX.js +25 -0
  399. package/dist/chunk-TSXGRLPR.js +107 -0
  400. package/dist/chunk-U2S3YEX3.js +224 -0
  401. package/dist/chunk-U45RTRGY.js +818 -0
  402. package/dist/chunk-U6C3VVWS.js +13 -0
  403. package/dist/chunk-UDMS5AD3.js +307 -0
  404. package/dist/chunk-UGX7GI37.js +94 -0
  405. package/dist/chunk-UH3JJSHK.js +1 -0
  406. package/dist/chunk-UHRBTZYY.js +208 -0
  407. package/dist/chunk-UHT2KRG5.js +193 -0
  408. package/dist/chunk-UI2F6DJ5.js +118 -0
  409. package/dist/chunk-UMAKSB4Z.js +284 -0
  410. package/dist/chunk-UR2IBGIM.js +521 -0
  411. package/dist/chunk-UUH2RVKS.js +585 -0
  412. package/dist/chunk-UVJ4PJDK.js +4533 -0
  413. package/dist/chunk-V53UG2OT.js +9924 -0
  414. package/dist/chunk-V72RMBM4.js +48 -0
  415. package/dist/chunk-VBNCKCCI.js +16 -0
  416. package/dist/chunk-VNSYKC25.js +24 -0
  417. package/dist/chunk-VPHVFK4A.js +1984 -0
  418. package/dist/chunk-VTLNJQ44.js +133 -0
  419. package/dist/chunk-VTW7HP3R.js +100 -0
  420. package/dist/chunk-VVGEPBPS.js +218 -0
  421. package/dist/chunk-VVLLL7I4.js +166 -0
  422. package/dist/chunk-VX3UMWB7.js +483 -0
  423. package/dist/chunk-VXF4Q3FW.js +20 -0
  424. package/dist/chunk-W3JMT2YY.js +712 -0
  425. package/dist/chunk-WDUORIHF.js +877 -0
  426. package/dist/chunk-WDVTY4U6.js +148 -0
  427. package/dist/chunk-WIFZCHEG.js +12566 -0
  428. package/dist/chunk-WIRN3F75.js +736 -0
  429. package/dist/chunk-WMPU2UOV.js +82 -0
  430. package/dist/chunk-WTOKKE2V.js +784 -0
  431. package/dist/chunk-WX5IRLF6.js +740 -0
  432. package/dist/chunk-WZ6U3O7I.js +1581 -0
  433. package/dist/chunk-XAONGNST.js +57 -0
  434. package/dist/chunk-XB5YLCLB.js +13 -0
  435. package/dist/chunk-XEP5NQ5Y.js +688 -0
  436. package/dist/chunk-XGYF2QMZ.js +351 -0
  437. package/dist/chunk-XHEKQENB.js +255 -0
  438. package/dist/chunk-XNO4FM6X.js +1124 -0
  439. package/dist/chunk-XPHKYHO4.js +878 -0
  440. package/dist/chunk-XPK2I4NC.js +405 -0
  441. package/dist/chunk-XPU2XADL.js +2175 -0
  442. package/dist/chunk-XQD2B6BB.js +507 -0
  443. package/dist/chunk-XT2ZQVTC.js +558 -0
  444. package/dist/chunk-XTXJGGUV.js +351 -0
  445. package/dist/chunk-XUXVDPSZ.js +50 -0
  446. package/dist/chunk-XV7NZL4B.js +57 -0
  447. package/dist/chunk-XZE4XARH.js +563 -0
  448. package/dist/chunk-XZYR5EDO.js +152 -0
  449. package/dist/chunk-Y3J4JMTU.js +61 -0
  450. package/dist/chunk-Y55LZN5U.js +52 -0
  451. package/dist/chunk-Y5VN7DMP.js +112 -0
  452. package/dist/chunk-Y67VAHN4.js +459 -0
  453. package/dist/chunk-YAXSKEUH.js +3544 -0
  454. package/dist/chunk-YB3JD4E6.js +975 -0
  455. package/dist/chunk-YESZJFK6.js +220 -0
  456. package/dist/chunk-YGXKOBQQ.js +292 -0
  457. package/dist/chunk-YMX76IOS.js +31 -0
  458. package/dist/chunk-YOTXESEH.js +257 -0
  459. package/dist/chunk-YTYIEZQY.js +119 -0
  460. package/dist/chunk-YVORHQ2S.js +579 -0
  461. package/dist/chunk-Z2CUQDAR.js +3429 -0
  462. package/dist/chunk-Z2KYOFHS.js +7000 -0
  463. package/dist/chunk-Z6PC7QX6.js +161 -0
  464. package/dist/chunk-ZDTGECTN.js +235 -0
  465. package/dist/chunk-ZIPWI2LY.js +151 -0
  466. package/dist/chunk-ZSKKMTQJ.js +554 -0
  467. package/dist/chunk-ZTT5IVPY.js +1160 -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-IXL26KJT.js +40 -0
  472. package/dist/cli-validation-WLXWLUJL.js +111 -0
  473. package/dist/commit-utils-P7CRJF5N.js +202 -0
  474. package/dist/compete-config-resolver-R5ULXMYH.js +76 -0
  475. package/dist/compete-request-62JESVET.js +364 -0
  476. package/dist/compete-results-QEPG6FZX.js +208 -0
  477. package/dist/competition-outcome-tracker-R32OOZ43.js +38 -0
  478. package/dist/config-JCOKXOQT.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-7T4E2BQO.js +67 -0
  483. package/dist/config-validator-KKOHOW7O.js +72 -0
  484. package/dist/cost-YC42XUF3.js +53 -0
  485. package/dist/coverage-orchestrator-CISNKJC2.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-GJOYE7AE.js +186 -0
  492. package/dist/domain-analyzer-AWF3RP6E.js +29 -0
  493. package/dist/ensure-initialized-744DIZEZ.js +52 -0
  494. package/dist/entry.js +940 -0
  495. package/dist/environment-YS45U5ZI.js +81 -0
  496. package/dist/error-parser-core-PPZ36A4S.js +50 -0
  497. package/dist/escalation-ladder-MKTCEGSA.js +130 -0
  498. package/dist/evaluation-context-KV4GZNN7.js +35 -0
  499. package/dist/evidence-plan-resolver-GBSYSAPX.js +85 -0
  500. package/dist/execution-data-writer-3ODTBDLH.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-R3DPPMD3.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-XBN7DFIM.js +149 -0
  507. package/dist/file-utils-XIVR2ZMA.js +47 -0
  508. package/dist/flywheel-autoloop-executor-UILGOFFK.js +249 -0
  509. package/dist/flywheel-competition-executor-JOBEXTRB.js +259 -0
  510. package/dist/flywheel-executor-6JFLA6J5.js +369 -0
  511. package/dist/flywheel-git-isolation-UC5NIEVU.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-XEY5SHM6.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-DPVWWIYY.js +73 -0
  519. package/dist/git-worktree-IY6V6DUO.js +18 -0
  520. package/dist/github-pr-manager-4LXEKJTA.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 +108661 -0
  525. package/dist/instructions-6BURLQJC.js +64 -0
  526. package/dist/invoke-provider-auth-GRUYP44M.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-BJRFLGK4.js +23 -0
  531. package/dist/linux-host-class-UY4KVLFD.js +29 -0
  532. package/dist/llm-judge-executor-F7Z3HO77.js +133 -0
  533. package/dist/local-executor-CEHWE2PL.js +223 -0
  534. package/dist/logger-33TR6EE5.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-6UDN5X3F.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-XGYBG2DW.js +72 -0
  542. package/dist/next-PB5ZXZKB.js +90 -0
  543. package/dist/next-ZBDK725T.js +69 -0
  544. package/dist/optimization-config-resolver-O6WKR47U.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-VAGYBV3J.js +270 -0
  552. package/dist/plan-backlog-show-fast-SG2CZPW3.js +406 -0
  553. package/dist/plan-sprint-list-fast-LURAX47V.js +162 -0
  554. package/dist/plan-sprint-status-fast-FJAODCHD.js +208 -0
  555. package/dist/plan-task-status-fast-HNYBMQI4.js +349 -0
  556. package/dist/plan-to-flywheel-Z4U3GWPN.js +456 -0
  557. package/dist/planning-backlog-3CQ5QQBQ.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-SE5EVXAP.js +149 -0
  565. package/dist/prompts-WZZPGWBX.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-N5X57V3Y.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-YRHMQAEI.js +70 -0
  575. package/dist/quickstart-FIRLKGJI.js +62 -0
  576. package/dist/readiness-VZTMSG6J.js +96 -0
  577. package/dist/registry-YODFY77A.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-D6TX6FRG.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-F5WQEUOM.js +160 -0
  587. package/dist/run-poetic-tui-J6LWRJUP.js +13517 -0
  588. package/dist/run-simulation.js +376 -0
  589. package/dist/runner-CS2TNGHA.js +1092 -0
  590. package/dist/runner-HHH7ZN2Z.js +1571 -0
  591. package/dist/safety-OCC4KJJR.js +64 -0
  592. package/dist/safety-stanza-7SV3HGG3.js +60 -0
  593. package/dist/sandbox-32QXJEMV.js +81 -0
  594. package/dist/sandbox-RSO7VP6V.js +94 -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-UIXPYOXQ.js +338 -0
  603. package/dist/sprint-bridge-4BHMSC3M.js +68 -0
  604. package/dist/sprint-execution-service-2B7WHL5L.js +311 -0
  605. package/dist/sprint-manager-IDQUDNQI.js +91 -0
  606. package/dist/sqlite-wrapper-UDWCTNLJ.js +17 -0
  607. package/dist/stale-cleanup-orchestrator-XWXV7KCZ.js +62 -0
  608. package/dist/storage-access-F6ALDN4S.js +22 -0
  609. package/dist/synthesis-XD6EDVHF.js +185 -0
  610. package/dist/task-classifier-LNLXSHOM.js +494 -0
  611. package/dist/task-list-fast-PTMA4LUC.js +147 -0
  612. package/dist/task-manager-XAT7GOWB.js +93 -0
  613. package/dist/task-splitter-U7DJ7W6A.js +79 -0
  614. package/dist/task-type-detector-OLVOMXZO.js +21 -0
  615. package/dist/task-type-resolver-KKNQYSB4.js +42 -0
  616. package/dist/telemetry-5HWBBXLX.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-XUOZNZZ6.js +125 -0
  620. package/dist/token-estimator-MEQUL3EJ.js +37 -0
  621. package/dist/transports-KNSSV2V4.js +255 -0
  622. package/dist/unified-cost-tracker-4TFRBVPR.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-KLRNG6XA.js +33 -0
  627. package/dist/variant-state-cleanup-MZGGLQAJ.js +280 -0
  628. package/dist/variant-success-PJXWE3ZV.js +12 -0
  629. package/dist/variant-worker-KUWKBLAH.js +4196 -0
  630. package/dist/variant-worker.js +24 -0
  631. package/dist/variants-JE2FSAQS.js +233 -0
  632. package/dist/verification-toolchains-V24UHW6Q.js +28 -0
  633. package/dist/verify-commands-H3DTCSGI.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-7SA2VS2Y.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 +7042 -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/npm-shrinkwrap.json +4950 -0
  720. package/package.json +331 -0
  721. package/schemas/README.md +80 -0
  722. package/schemas/config-v1.schema.json +136 -0
  723. package/schemas/execution-config.schema.json +47 -0
  724. package/schemas/judge-scoring.schema.json +370 -0
  725. package/schemas/poetic.config.schema.json +2214 -0
  726. package/schemas/provider-config.schema.json +203 -0
  727. package/schemas/telemetry-config.schema.json +79 -0
  728. package/schemas/user-preferences.schema.json +141 -0
  729. package/scripts/assert-node-runtime.mjs +140 -0
  730. package/scripts/preflight-native.mjs +49 -0
  731. package/scripts/preinstall-node-check.mjs +78 -0
  732. package/scripts/setup-git-hooks.mjs +24 -0
  733. package/scripts/sync.sh +2722 -0
  734. package/scripts/write-node-launcher.sh +108 -0
  735. package/src/resources/gemini/slash-packs/default/plan.toml +15 -0
  736. package/src/resources/gemini/slash-packs/default/summary.toml +16 -0
  737. package/src/resources/gemini/slash-packs/default/tests.toml +16 -0
  738. package/templates/.poetic/README.md +37 -0
  739. package/templates/.poetic/agents/README.md +296 -0
  740. package/templates/.poetic/agents/api-documenter.md +147 -0
  741. package/templates/.poetic/agents/backend-architect.md +31 -0
  742. package/templates/.poetic/agents/code-reviewer.md +157 -0
  743. package/templates/.poetic/agents/data-scientist.md +179 -0
  744. package/templates/.poetic/agents/database-optimizer.md +145 -0
  745. package/templates/.poetic/agents/debugger.md +31 -0
  746. package/templates/.poetic/agents/deployment-engineer.md +164 -0
  747. package/templates/.poetic/agents/devops-troubleshooter.md +139 -0
  748. package/templates/.poetic/agents/frontend-developer.md +150 -0
  749. package/templates/.poetic/agents/javascript-pro.md +36 -0
  750. package/templates/.poetic/agents/performance-engineer.md +151 -0
  751. package/templates/.poetic/agents/python-pro.md +137 -0
  752. package/templates/.poetic/agents/test-automator.md +147 -0
  753. package/templates/.poetic/agents/typescript-pro.md +34 -0
  754. package/templates/.poetic/config/poetic.config.jsonc +69 -0
  755. package/templates/.poetic/config/project-context.template.json +6 -0
  756. package/templates/.poetic/config/task-type-aliases.presets/kanban.yaml +14 -0
  757. package/templates/.poetic/config/task-type-aliases.presets/scrum.yaml +17 -0
  758. package/templates/.poetic/config/task-type-aliases.presets/xp.yaml +12 -0
  759. package/templates/.poetic/config/task-type-aliases.yaml +28 -0
  760. package/templates/.poetic/gitignore.template +55 -0
  761. package/templates/.poetic/task-types/analysis.yaml +40 -0
  762. package/templates/.poetic/task-types/architecture.yaml +38 -0
  763. package/templates/.poetic/task-types/doc.yaml +35 -0
  764. package/templates/.poetic/task-types/feature.yaml +23 -0
  765. package/templates/.poetic/task-types/general.yaml +6 -0
  766. package/templates/.poetic/task-types/security.yaml +39 -0
  767. package/templates/AGENTS.template.md +99 -0
  768. package/templates/CLAUDE.template.md +1 -0
  769. package/templates/GEMINI.template.md +1 -0
  770. package/templates/builtin-workflows/code-review.yaml +73 -0
  771. package/templates/builtin-workflows/compete-streak.yaml +78 -0
  772. package/templates/builtin-workflows/hello-verify.yaml +10 -0
  773. package/templates/builtin-workflows/judge-regression.yaml +114 -0
  774. package/templates/builtin-workflows/skills/code-review/SKILL.md +60 -0
  775. package/templates/builtin-workflows/skills/hello-verify/SKILL.md +6 -0
  776. package/templates/guard-kit/GUARD_SETUP.md.template +255 -0
  777. package/templates/guard-kit/check.mjs.template +777 -0
  778. package/templates/guard-kit/config.json.template +6 -0
  779. package/templates/guard-kit/poetic-guard.yml.template +189 -0
  780. package/templates/profiles/README.md +56 -0
  781. package/templates/profiles/frontier-claude.json +27 -0
  782. package/templates/profiles/frontier-codex.json +26 -0
@@ -0,0 +1,3104 @@
1
+ import {
2
+ deriveTestVerificationDisplay,
3
+ gateStatusToDisplayVerdict
4
+ } from "./chunk-QNOB37UH.js";
5
+ import {
6
+ evaluateStageCompletionProof,
7
+ resolveProviderExecutionIntentFromStage,
8
+ stageHasHostDeterministicCompletionSurface
9
+ } from "./chunk-5ZCXC23G.js";
10
+ import {
11
+ collectDeclaredStageTargets
12
+ } from "./chunk-IFCBYECK.js";
13
+ import {
14
+ decideStageChangeScope
15
+ } from "./chunk-HAC6EHZZ.js";
16
+ import {
17
+ providerReportsUsage,
18
+ readCostMetricsUnavailableReason,
19
+ readUsageUnavailableReason
20
+ } from "./chunk-XUXVDPSZ.js";
21
+ import {
22
+ cleanupSynthesisInputPatches,
23
+ resolveBasicCompetitionInterruption,
24
+ resolveSynthesisInputPatchDir,
25
+ runBasicCompetition,
26
+ selectWinnerWithJudge
27
+ } from "./chunk-DCBZP442.js";
28
+ import {
29
+ createEvaluationHandleFinalState,
30
+ finalizeEvaluationHandleAsync,
31
+ isDurableHandleCompletion,
32
+ toEvaluationHandleWinnerMetadata,
33
+ updateEvaluationHandleWithResultAsync
34
+ } from "./chunk-2IUXIGQD.js";
35
+ import {
36
+ JudgeCoordinator,
37
+ evaluateMatrixAuthority,
38
+ generateCompetitionId,
39
+ resolveMatrixAuthorityPolicy,
40
+ resolveTypedCompletenessAuthority
41
+ } from "./chunk-WIFZCHEG.js";
42
+ import {
43
+ validateStrategy
44
+ } from "./chunk-LWTN3WRV.js";
45
+ import {
46
+ isAcceptedMatrixVerdict
47
+ } from "./chunk-5LAMRH4X.js";
48
+ import {
49
+ findAllowlistViolations
50
+ } from "./chunk-ZIPWI2LY.js";
51
+ import {
52
+ ArtifactNotFoundError,
53
+ createSecurityBoundary,
54
+ deriveAiJudgeInvocationArgs,
55
+ resolvePromptArtifacts
56
+ } from "./chunk-4HN6DF7V.js";
57
+ import {
58
+ getProjectRoot
59
+ } from "./chunk-CQM3A35X.js";
60
+ import {
61
+ applyFlywheelModelDefaults
62
+ } from "./chunk-FH7WOJAE.js";
63
+ import {
64
+ extractEvidenceAnchors,
65
+ isNegativeClaim
66
+ } from "./chunk-O4G2W3ST.js";
67
+ import {
68
+ shouldExcludeFile
69
+ } from "./chunk-NS33V3IM.js";
70
+ import {
71
+ filterWorktreeRunSentinelPaths
72
+ } from "./chunk-I5WRT7ZR.js";
73
+ import {
74
+ taskVariantId
75
+ } from "./chunk-34CNP2HB.js";
76
+ import {
77
+ runVerifyCommands
78
+ } from "./chunk-LO23NABI.js";
79
+ import {
80
+ createExecutionContext
81
+ } from "./chunk-UI2F6DJ5.js";
82
+ import {
83
+ normalizeReasoningEffortInput
84
+ } from "./chunk-4BTDUT2S.js";
85
+
86
+ // src/automation/flywheel-competition-executor.ts
87
+ import * as fs from "fs/promises";
88
+ import * as path from "path";
89
+ import chalk from "chalk";
90
+
91
+ // src/automation/flywheel-to-core-verification-finding.ts
92
+ function toCoreVerificationFinding(finding) {
93
+ const kind = finding.kind === "coverage" ? "other" : finding.kind;
94
+ const outputParts = [];
95
+ if (finding.kind === "coverage") {
96
+ const coverageDetail = finding.outputTail?.trim() ? finding.outputTail.trim() : finding.command ? `Coverage observation for ${finding.command}` : "Coverage observation";
97
+ outputParts.push(
98
+ coverageDetail.toLowerCase().includes("coverage") ? coverageDetail : `Coverage: ${coverageDetail}`
99
+ );
100
+ } else if (finding.outputTail) {
101
+ outputParts.push(finding.outputTail);
102
+ }
103
+ if (finding.recommendedNextStep) {
104
+ const next = finding.recommendedNextStep.trim();
105
+ if (next && !outputParts.some((part) => part.includes(next))) {
106
+ outputParts.push(next);
107
+ }
108
+ }
109
+ const mapped = {
110
+ kind,
111
+ command: finding.command,
112
+ exitCode: finding.exitCode,
113
+ severity: finding.severity
114
+ };
115
+ if (outputParts.length > 0) {
116
+ mapped.outputTail = outputParts.join("\n");
117
+ }
118
+ return mapped;
119
+ }
120
+
121
+ // src/automation/verification-polarity.ts
122
+ function hasExplicitVerificationSignal(input) {
123
+ if (input.verification && typeof input.verification.passed === "boolean") {
124
+ return true;
125
+ }
126
+ if (typeof input.verification?.status === "string" && input.verification.status.trim()) {
127
+ return true;
128
+ }
129
+ if (typeof input.testStatus === "string" && input.testStatus.trim()) {
130
+ return true;
131
+ }
132
+ if (typeof input.rawTestStatus === "string" && input.rawTestStatus.trim()) {
133
+ return true;
134
+ }
135
+ if (typeof input.exitCode === "number") {
136
+ return true;
137
+ }
138
+ if (typeof input.failedTests === "number") {
139
+ return true;
140
+ }
141
+ return false;
142
+ }
143
+ function verificationRecordsBaselineClean(verification) {
144
+ if (!verification) {
145
+ return false;
146
+ }
147
+ if (verification.passedBaseline === false) {
148
+ return false;
149
+ }
150
+ const status = verification.status?.trim().toLowerCase();
151
+ if (status === "baseline_clean") {
152
+ return true;
153
+ }
154
+ if (verification.passedBaseline !== true) {
155
+ return false;
156
+ }
157
+ return !status || gateStatusToDisplayVerdict(status) !== "unavailable";
158
+ }
159
+ function verificationPolarityAllowsStageSuccess(input) {
160
+ if (!hasExplicitVerificationSignal(input)) {
161
+ return true;
162
+ }
163
+ if (verificationRecordsBaselineClean(input.verification)) {
164
+ return true;
165
+ }
166
+ if (input.verification?.passed === false) {
167
+ return false;
168
+ }
169
+ const status = input.verification?.status?.trim().toLowerCase();
170
+ if (status === "failed" || status === "unavailable") {
171
+ return false;
172
+ }
173
+ const hasExplicitTestSignal = typeof input.testStatus === "string" && input.testStatus.trim().length > 0 || typeof input.rawTestStatus === "string" && input.rawTestStatus.trim().length > 0 || typeof input.exitCode === "number" || typeof input.failedTests === "number";
174
+ if (hasExplicitTestSignal) {
175
+ const display = deriveTestVerificationDisplay({
176
+ testStatus: input.testStatus,
177
+ rawTestStatus: input.rawTestStatus,
178
+ exitCode: input.exitCode,
179
+ failedTests: input.failedTests
180
+ });
181
+ return display === "passed";
182
+ }
183
+ return input.verification?.passed === true || status === "passed";
184
+ }
185
+
186
+ // src/automation/flywheel-competition-executor.ts
187
+ var CANDIDATE_GATE_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
188
+ function isNoChangesDetectedError(errorMessage) {
189
+ return Boolean(errorMessage?.includes("No changes detected (git status clean)"));
190
+ }
191
+ function generateCandidateFeedback(variantEvaluation, result) {
192
+ if (!variantEvaluation && !result) return void 0;
193
+ const parts = [];
194
+ const score = variantEvaluation?.qualityScore ?? result.judgeScore ?? result.completeness;
195
+ if (score !== void 0) {
196
+ parts.push(`Score: ${Number(score).toFixed(1)}/100`);
197
+ }
198
+ const changedFiles = extractChangedFilesFromResult(result);
199
+ const fileCount = changedFiles.length;
200
+ const linesAdded = result.gitMetrics?.linesAdded ?? result.linesAdded ?? 0;
201
+ const linesDeleted = result.gitMetrics?.linesDeleted ?? result.linesRemoved ?? 0;
202
+ if (fileCount > 0 || linesAdded > 0 || linesDeleted > 0) {
203
+ parts.push(`Changes: ${fileCount} file(s), +${linesAdded}/-${linesDeleted} lines`);
204
+ }
205
+ const testStatus = result.testStatus;
206
+ if (testStatus) {
207
+ parts.push(`Tests: ${testStatus}`);
208
+ }
209
+ const strengths = variantEvaluation?.strengths;
210
+ if (strengths && strengths.length > 0) {
211
+ const topStrengths = strengths.slice(0, 2).join("; ");
212
+ parts.push(`Strengths: ${topStrengths}`);
213
+ }
214
+ const weaknesses = variantEvaluation?.weaknesses;
215
+ if (weaknesses && weaknesses.length > 0) {
216
+ const topWeaknesses = weaknesses.slice(0, 2).join("; ");
217
+ parts.push(`Areas for improvement: ${topWeaknesses}`);
218
+ }
219
+ const cq = variantEvaluation?.codeQuality;
220
+ if (cq) {
221
+ const metrics = [];
222
+ if (cq.correctness !== void 0) metrics.push(`correctness=${cq.correctness}`);
223
+ if (cq.completeness !== void 0) metrics.push(`completeness=${cq.completeness}`);
224
+ if (metrics.length > 0) {
225
+ parts.push(`Quality: ${metrics.join(", ")}`);
226
+ }
227
+ }
228
+ return parts.length > 0 ? `${parts.join(". ")}.` : void 0;
229
+ }
230
+ function extractChangedFilesFromResult(result) {
231
+ if ("changedFiles" in result && Array.isArray(result.changedFiles)) {
232
+ return result.changedFiles;
233
+ }
234
+ const statusLines = result.worktreeSummary?.statusLines;
235
+ if (statusLines && Array.isArray(statusLines) && statusLines.length > 0) {
236
+ return statusLines.map((line) => extractChangedFileFromStatusLine(String(line))).filter((line) => Boolean(line));
237
+ }
238
+ const filesChanged = result.gitMetrics?.filesChanged;
239
+ if (typeof filesChanged === "number" && filesChanged > 0) {
240
+ return Array.from({ length: filesChanged }, (_, i) => `file${i + 1}`);
241
+ }
242
+ return [];
243
+ }
244
+ function resultHasChangeTracking(result) {
245
+ if ("changedFiles" in result && Array.isArray(result.changedFiles)) {
246
+ return true;
247
+ }
248
+ const statusLines = result.worktreeSummary?.statusLines;
249
+ if (Array.isArray(statusLines)) {
250
+ return true;
251
+ }
252
+ return typeof result.gitMetrics?.filesChanged === "number";
253
+ }
254
+ function extractChangedFileFromStatusLine(line) {
255
+ const trimmed = line.trim();
256
+ if (!trimmed) return null;
257
+ const arrowIdx = trimmed.lastIndexOf("->");
258
+ if (arrowIdx !== -1) {
259
+ const candidate = trimmed.slice(arrowIdx + 2).trim();
260
+ return candidate || null;
261
+ }
262
+ const match = trimmed.match(/^[MADRCU?! ]{1,2}\s*(.+)$/);
263
+ return match?.[1]?.trim() ?? null;
264
+ }
265
+ function candidateHasChangedFiles(candidate) {
266
+ return Array.isArray(candidate.changedFiles) && candidate.changedFiles.length > 0;
267
+ }
268
+ function candidateHasConcreteZeroChanges(candidate) {
269
+ return candidate.changeTrackingAvailable === true && !candidateHasChangedFiles(candidate);
270
+ }
271
+ function stageHasDeterministicChecks(stage) {
272
+ return stageHasHostDeterministicCompletionSurface(stage);
273
+ }
274
+ function renderCandidateGateCommand(command, candidate) {
275
+ return command.replaceAll("{{provider}}", shellArg(candidate.variant.provider)).replaceAll("{{model}}", shellArg(candidate.variant.model ?? "")).replaceAll("{{strategy}}", shellArg(candidate.variant.strategy ?? "")).replaceAll("{{variant}}", shellArg(formatCompetitionCandidateVariantDisplay(candidate)));
276
+ }
277
+ function formatCompetitionCandidateVariantDisplay(candidate) {
278
+ return formatCompetitionVariantDisplay(candidate.variant);
279
+ }
280
+ function formatCompetitionVariantDisplay(variant) {
281
+ const parts = [variant.provider, variant.model, variant.strategy ?? "conservative"].filter(
282
+ (part) => typeof part === "string" && part.length > 0
283
+ );
284
+ return parts.join(":");
285
+ }
286
+ function shellArg(value) {
287
+ if (/^[A-Za-z0-9._:@/+,-]+$/.test(value)) {
288
+ return value;
289
+ }
290
+ return `'${value.replace(/'/g, `'\\''`)}'`;
291
+ }
292
+ async function validateWorktreeAgainstStageChecks(stage, worktreePath, stdout, options) {
293
+ if (!stageHasHostDeterministicCompletionSurface(stage)) return false;
294
+ const proof = await evaluateStageCompletionProof({
295
+ stage,
296
+ worktreePath,
297
+ stdout,
298
+ attemptChangedFiles: options?.attemptChangedFiles ?? [],
299
+ allowlist: options?.allowlist ?? computeExpectedAllowlist(stage),
300
+ stageId: stage.id
301
+ });
302
+ return proof.contractsSatisfied && proof.hasHostSurface && proof.mayAcceptOutcome;
303
+ }
304
+ function getVariantTelemetryStatePath(taskId, provider, strategy, model, mode, reasoningEffort) {
305
+ const variantKey = taskVariantId(
306
+ taskId,
307
+ provider,
308
+ model,
309
+ strategy,
310
+ mode,
311
+ void 0,
312
+ void 0,
313
+ reasoningEffort
314
+ );
315
+ return path.join(
316
+ getProjectRoot(),
317
+ ".poetic",
318
+ "telemetry",
319
+ "state",
320
+ "variants",
321
+ `${variantKey}.json`
322
+ );
323
+ }
324
+ function getValueAtPath(root, keys) {
325
+ let current = root;
326
+ for (const key of keys) {
327
+ if (!current || typeof current !== "object") return void 0;
328
+ current = current[key];
329
+ }
330
+ return current;
331
+ }
332
+ function getFiniteNumberAtPath(root, keys) {
333
+ const value = getValueAtPath(root, keys);
334
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
335
+ }
336
+ function getStringAtPath(root, keys) {
337
+ const value = getValueAtPath(root, keys);
338
+ return typeof value === "string" ? value : void 0;
339
+ }
340
+ function extractNativeObservedCostFromVariantState(state) {
341
+ return getFiniteNumberAtPath(state, ["result", "totalCostUsd"]) ?? getFiniteNumberAtPath(state, ["result", "total_cost_usd"]) ?? getFiniteNumberAtPath(state, ["result", "totalCost"]) ?? getFiniteNumberAtPath(state, ["result", "total_cost"]) ?? null;
342
+ }
343
+ function extractCostMetricsAmountFromVariantState(state) {
344
+ return getFiniteNumberAtPath(state, ["costMetrics", "totalCostUsd"]) ?? getFiniteNumberAtPath(state, ["costMetrics", "totalCost"]) ?? null;
345
+ }
346
+ function resolveCostMetricsUnavailableReason(costMetrics) {
347
+ if (!costMetrics || typeof costMetrics !== "object") {
348
+ return void 0;
349
+ }
350
+ const usageReason = readUsageUnavailableReason({ costMetrics });
351
+ if (usageReason !== void 0) {
352
+ return usageReason;
353
+ }
354
+ const reason = readCostMetricsUnavailableReason(
355
+ costMetrics
356
+ );
357
+ if (reason !== void 0) {
358
+ return reason;
359
+ }
360
+ if (costMetrics.pricingStatus === "error") {
361
+ return "pricing_unavailable";
362
+ }
363
+ return void 0;
364
+ }
365
+ function markCandidateCostUnavailable(candidate, reason) {
366
+ candidate.cost = 0;
367
+ candidate.costUnavailableReason = reason;
368
+ }
369
+ async function hydrateCandidateCostsFromTelemetry(taskId, candidates, stageIdForLogs, verbose) {
370
+ await Promise.all(
371
+ candidates.map(async (candidate) => {
372
+ if (!candidate.success) return;
373
+ if (typeof candidate.cost === "number" && Number.isFinite(candidate.cost) && candidate.costUnavailableReason === void 0) {
374
+ return;
375
+ }
376
+ if (typeof candidate.cost === "number" && Number.isFinite(candidate.cost) && candidate.cost > 0) {
377
+ candidate.costUnavailableReason = void 0;
378
+ return;
379
+ }
380
+ const provider = candidate.variant.provider;
381
+ const strategy = candidate.variant.strategy ?? "conservative";
382
+ if (!provider || !strategy) return;
383
+ if (!providerReportsUsage(provider)) {
384
+ candidate.costUnavailableReason = candidate.costUnavailableReason ?? "provider_not_reported";
385
+ return;
386
+ }
387
+ const variantStatePath = getVariantTelemetryStatePath(
388
+ taskId,
389
+ provider,
390
+ strategy,
391
+ candidate.variant.model,
392
+ candidate.variant.executionMode,
393
+ normalizeReasoningEffortInput(candidate.variant.reasoning)
394
+ );
395
+ try {
396
+ const raw = await fs.readFile(variantStatePath, "utf8");
397
+ const state = JSON.parse(raw);
398
+ const nativeObservedCost = extractNativeObservedCostFromVariantState(state);
399
+ const metricsCost = extractCostMetricsAmountFromVariantState(state);
400
+ const costMetrics = getValueAtPath(state, ["costMetrics"]);
401
+ const unavailableReason = resolveCostMetricsUnavailableReason(costMetrics);
402
+ if (typeof nativeObservedCost === "number") {
403
+ candidate.cost = nativeObservedCost;
404
+ candidate.costUnavailableReason = void 0;
405
+ return;
406
+ }
407
+ if (typeof metricsCost === "number" && metricsCost > 0) {
408
+ candidate.cost = metricsCost;
409
+ candidate.costUnavailableReason = void 0;
410
+ return;
411
+ }
412
+ if (unavailableReason !== void 0) {
413
+ markCandidateCostUnavailable(candidate, unavailableReason);
414
+ return;
415
+ }
416
+ if (typeof metricsCost === "number") {
417
+ candidate.cost = metricsCost;
418
+ candidate.costUnavailableReason = void 0;
419
+ return;
420
+ }
421
+ markCandidateCostUnavailable(
422
+ candidate,
423
+ candidate.costUnavailableReason ?? "provider_not_reported"
424
+ );
425
+ } catch {
426
+ markCandidateCostUnavailable(
427
+ candidate,
428
+ candidate.costUnavailableReason ?? "provider_not_reported"
429
+ );
430
+ }
431
+ if (verbose) {
432
+ console.warn(
433
+ chalk.yellow(
434
+ ` [${stageIdForLogs}] Unable to hydrate cost from telemetry for ${provider}:${strategy}`
435
+ )
436
+ );
437
+ }
438
+ })
439
+ );
440
+ }
441
+ function variantSpecToConfig(spec, executionIntent, stage, defaultProviderExecutionTransport, unknownStrategyPolicy) {
442
+ const validatedStrategy = validateStrategy(spec.strategy, unknownStrategyPolicy);
443
+ const model = spec.model ?? applyFlywheelModelDefaults(stage, spec.provider);
444
+ const modelReasoningEffort = normalizeReasoningEffortInput(spec.reasoning);
445
+ return {
446
+ provider: spec.provider,
447
+ model,
448
+ ...modelReasoningEffort ? { modelReasoningEffort } : {},
449
+ strategy: validatedStrategy,
450
+ executionMode: "local",
451
+ // Competition stages always run locally
452
+ executionIntent,
453
+ ...spec.providerExecutionTransport ?? stage.providerExecutionTransport ?? defaultProviderExecutionTransport ? {
454
+ executionTransport: spec.providerExecutionTransport ?? stage.providerExecutionTransport ?? defaultProviderExecutionTransport
455
+ } : {},
456
+ allowEmptyResults: stage.allowEmptyResults,
457
+ isBasicCompetition: true,
458
+ // Don't auto-commit - flywheel manages commits
459
+ disableAutoCommit: true,
460
+ structuredFileTargets: computeExpectedAllowlist(stage)
461
+ };
462
+ }
463
+ function assertNoDuplicateVariantSpecs(variants, options) {
464
+ if (options.allowDuplicates) return;
465
+ const keyCounts = /* @__PURE__ */ new Map();
466
+ const keyToVariants = /* @__PURE__ */ new Map();
467
+ for (const variant of variants) {
468
+ const modelKey = variant.model ?? "default";
469
+ const strategyKey = variant.strategy ?? "conservative";
470
+ const effortKey = variant.modelReasoningEffort ?? "default";
471
+ const key = `${variant.provider}:${modelKey}:${strategyKey}:${effortKey}`;
472
+ keyCounts.set(key, (keyCounts.get(key) ?? 0) + 1);
473
+ if (!keyToVariants.has(key)) {
474
+ keyToVariants.set(key, []);
475
+ }
476
+ keyToVariants.get(key)?.push(variant);
477
+ }
478
+ const duplicates = [...keyCounts.entries()].filter(([, count]) => count > 1);
479
+ if (duplicates.length === 0) return;
480
+ const details = duplicates.map(([key, count]) => {
481
+ const parts = key.split(":");
482
+ const provider = parts[0] ?? "unknown";
483
+ const model = parts[1] === "default" ? "(default)" : parts[1];
484
+ const strategy = parts[2] ?? "conservative";
485
+ const effort = parts[3] === "default" ? void 0 : parts[3];
486
+ return ` \u2022 ${provider}:${model}:${strategy}${effort ? `:effort-${effort}` : ""} \u2014 appears ${count} times`;
487
+ }).join("\n");
488
+ throw new Error(
489
+ `Duplicate variant specs detected in competition stage
490
+
491
+ What this means:
492
+ Competition stages should compare different variants, not the same variant
493
+ to itself. Duplicates are identified by provider+model+strategy+reasoningEffort identity.
494
+
495
+ Duplicate variants found:
496
+ ${details}
497
+
498
+ How to fix:
499
+ 1. Remove duplicate entries from your competition.variants configuration
500
+ 2. Or change model/strategy to make variants distinct
501
+ 3. Or use different providers for same strategy (e.g., claude:conservative + codex:conservative)
502
+
503
+ Escape hatch (not recommended):
504
+ Set competition.allowDuplicateVariantSpecs: true in your stage config
505
+
506
+ Tip: This guard prevents wasted compute on redundant comparisons.`
507
+ );
508
+ }
509
+ function resolveCompetitionExecutionIntent(stage) {
510
+ return resolveProviderExecutionIntentFromStage(stage);
511
+ }
512
+ function getVariantDurationMs(result) {
513
+ if (typeof result.executionDurationMs === "number" && Number.isFinite(result.executionDurationMs)) {
514
+ return result.executionDurationMs;
515
+ }
516
+ if (typeof result.totalDurationSec === "number" && Number.isFinite(result.totalDurationSec)) {
517
+ return result.totalDurationSec * 1e3;
518
+ }
519
+ return Math.max(0, Math.round((result.duration ?? 0) * 1e3));
520
+ }
521
+ var CHANGED_FILES_EXCLUDE_PATTERNS = [
522
+ "node_modules",
523
+ ".cursor",
524
+ ".vscode",
525
+ "coverage",
526
+ "dist",
527
+ ".poetic/tmp",
528
+ ".git"
529
+ ];
530
+ function shouldExcludeChangedFile(filePath) {
531
+ const normalized = filePath.replace(/\\/g, "/");
532
+ if (shouldExcludeFile(normalized)) return true;
533
+ for (const pattern of CHANGED_FILES_EXCLUDE_PATTERNS) {
534
+ if (normalized === pattern || normalized.startsWith(`${pattern}/`)) return true;
535
+ }
536
+ return false;
537
+ }
538
+ function extractChangedFiles(result) {
539
+ const statusLines = result.worktreeSummary?.statusLines;
540
+ if (!Array.isArray(statusLines) || statusLines.length === 0) return void 0;
541
+ const files = statusLines.map((line) => extractChangedFileFromStatusLine(String(line))).filter((v) => Boolean(v)).filter((f) => !shouldExcludeChangedFile(f));
542
+ return files.length > 0 ? files : void 0;
543
+ }
544
+ function normalizeCoveragePath(value) {
545
+ return value.replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+/g, "/");
546
+ }
547
+ function tryGetPct(metric) {
548
+ if (!metric || typeof metric !== "object") return null;
549
+ const pct = metric.pct;
550
+ return typeof pct === "number" && Number.isFinite(pct) ? pct : null;
551
+ }
552
+ function getCoveragePctForEntry(entry) {
553
+ if (!entry || typeof entry !== "object") return null;
554
+ const record = entry;
555
+ return tryGetPct(record.lines) ?? tryGetPct(record.statements) ?? tryGetPct(record.functions) ?? tryGetPct(record.branches) ?? null;
556
+ }
557
+ function getTotalLinesForEntry(entry) {
558
+ if (!entry || typeof entry !== "object") return null;
559
+ const record = entry;
560
+ const lines = record.lines;
561
+ if (!lines || typeof lines !== "object") return null;
562
+ const total = lines.total;
563
+ return typeof total === "number" && Number.isFinite(total) ? total : null;
564
+ }
565
+ async function loadCoverageSummaryJson(worktreePath, summaryPath, options = {}) {
566
+ try {
567
+ const resolved = path.join(worktreePath, summaryPath);
568
+ if (typeof options.minMtimeMs === "number") {
569
+ const stats = await fs.stat(resolved);
570
+ if (stats.mtimeMs < options.minMtimeMs) return null;
571
+ }
572
+ const raw = await fs.readFile(resolved, "utf8");
573
+ const parsed = JSON.parse(raw);
574
+ if (!parsed || typeof parsed !== "object") return null;
575
+ return parsed;
576
+ } catch {
577
+ return null;
578
+ }
579
+ }
580
+ function findCoverageEntry(summary, target) {
581
+ const normalizedTarget = normalizeCoveragePath(target);
582
+ const direct = summary[normalizedTarget];
583
+ if (direct && typeof direct === "object") {
584
+ return direct;
585
+ }
586
+ const candidates = [];
587
+ for (const [key, value] of Object.entries(summary)) {
588
+ if (key === "total") continue;
589
+ if (!value || typeof value !== "object") continue;
590
+ const normalizedKey = normalizeCoveragePath(key);
591
+ if (normalizedKey === normalizedTarget || normalizedKey.endsWith(`/${normalizedTarget}`)) {
592
+ candidates.push({ key, entry: value });
593
+ }
594
+ }
595
+ if (candidates.length === 0) return null;
596
+ candidates.sort((a, b) => a.key.length - b.key.length);
597
+ return candidates[0]?.entry ?? null;
598
+ }
599
+ function computeCoverageStatsForTargets(summary, targets) {
600
+ const byTarget = {};
601
+ const linesByTarget = {};
602
+ const missingTargets = [];
603
+ const pcts = [];
604
+ const lineCounts = [];
605
+ for (const target of targets) {
606
+ if (!summary) {
607
+ byTarget[target] = null;
608
+ linesByTarget[target] = null;
609
+ missingTargets.push(target);
610
+ continue;
611
+ }
612
+ const entry = findCoverageEntry(summary, target);
613
+ const pct = entry ? getCoveragePctForEntry(entry) : null;
614
+ const lines = entry ? getTotalLinesForEntry(entry) : null;
615
+ byTarget[target] = pct;
616
+ linesByTarget[target] = lines;
617
+ if (pct === null) {
618
+ missingTargets.push(target);
619
+ } else {
620
+ pcts.push(pct);
621
+ }
622
+ if (typeof lines === "number") {
623
+ lineCounts.push(lines);
624
+ }
625
+ }
626
+ if (pcts.length === 0) {
627
+ return {
628
+ byTarget,
629
+ linesByTarget,
630
+ avgPct: null,
631
+ minPct: null,
632
+ totalLines: null,
633
+ maxTargetLines: null,
634
+ missingTargets
635
+ };
636
+ }
637
+ const avgRaw = pcts.reduce((sum, v) => sum + v, 0) / pcts.length;
638
+ const minRaw = Math.min(...pcts);
639
+ const round2 = (v) => Math.round(v * 100) / 100;
640
+ const totalLines = lineCounts.length > 0 ? lineCounts.reduce((sum, v) => sum + v, 0) : null;
641
+ const maxTargetLines = lineCounts.length > 0 ? Math.max(...lineCounts) : null;
642
+ return {
643
+ byTarget,
644
+ linesByTarget,
645
+ avgPct: round2(avgRaw),
646
+ minPct: round2(minRaw),
647
+ totalLines,
648
+ maxTargetLines,
649
+ missingTargets
650
+ };
651
+ }
652
+ function parseBaselineLinesPctFromPrompt(prompt) {
653
+ const match = prompt.match(/Baseline:\s*lines\s+(\d+(?:\.\d+)?)%/i);
654
+ if (!match) return null;
655
+ const value = Number.parseFloat(match[1] ?? "");
656
+ return Number.isFinite(value) ? value : null;
657
+ }
658
+ function resolveAutoCoverageMode(params) {
659
+ const { maxTargetLines, largeFileLineThreshold, baselineAvgPct, threshold, minDeltaPct } = params;
660
+ if (typeof maxTargetLines === "number" && maxTargetLines > largeFileLineThreshold) {
661
+ return "delta";
662
+ }
663
+ if (typeof threshold === "number" && typeof baselineAvgPct === "number" && threshold - baselineAvgPct > minDeltaPct) {
664
+ return "delta";
665
+ }
666
+ return "absolute";
667
+ }
668
+ function computeExpectedAllowlist(stage) {
669
+ return collectDeclaredStageTargets(stage);
670
+ }
671
+ function computeCompetitionDrift(candidates, expectedAllowlist, mode) {
672
+ const allDeliveredFiles = /* @__PURE__ */ new Set();
673
+ const allViolations = /* @__PURE__ */ new Set();
674
+ for (const candidate of candidates) {
675
+ if (!candidate.success || !candidate.changedFiles) continue;
676
+ const changedFiles = filterWorktreeRunSentinelPaths(candidate.changedFiles);
677
+ for (const file of changedFiles) {
678
+ allDeliveredFiles.add(file);
679
+ }
680
+ const decision = decideStageChangeScope({
681
+ changedPaths: changedFiles,
682
+ explicitScope: expectedAllowlist,
683
+ allowlistMode: mode,
684
+ mutationOrigin: "provider"
685
+ });
686
+ for (const violation of decision.allowlistViolations) {
687
+ allViolations.add(violation);
688
+ }
689
+ }
690
+ const deliveredFiles = [...allDeliveredFiles];
691
+ const violations = [...allViolations];
692
+ const hasDrift = violations.length > 0;
693
+ const lines = [];
694
+ lines.push(`Competition stage (${candidates.length} candidates)`);
695
+ lines.push(`Mode: ${mode}`);
696
+ lines.push(`Total delivered files: ${deliveredFiles.length}`);
697
+ lines.push(`Expected allowlist entries: ${expectedAllowlist.length}`);
698
+ if (hasDrift) {
699
+ lines.push(`Drift: ${violations.length} file(s) outside allowlist`);
700
+ for (const v of violations.slice(0, 3)) {
701
+ lines.push(` - ${v}`);
702
+ }
703
+ if (violations.length > 3) {
704
+ lines.push(` ... and ${violations.length - 3} more`);
705
+ }
706
+ } else {
707
+ lines.push("Drift: none");
708
+ }
709
+ return {
710
+ mode,
711
+ deliveredFiles,
712
+ expectedFiles: expectedAllowlist,
713
+ violations,
714
+ hasDrift,
715
+ summary: lines.join("\n")
716
+ };
717
+ }
718
+ var DEFAULT_COHERENCE_THRESHOLD = 0.3;
719
+ function jaccardSimilarity(setA, setB) {
720
+ if (setA.size === 0 && setB.size === 0) return 1;
721
+ const intersection = new Set([...setA].filter((x) => setB.has(x)));
722
+ const union = /* @__PURE__ */ new Set([...setA, ...setB]);
723
+ return union.size > 0 ? intersection.size / union.size : 0;
724
+ }
725
+ function computeCoherenceMetrics(candidates, threshold = DEFAULT_COHERENCE_THRESHOLD, expectedAllowlist) {
726
+ const allowlist = (expectedAllowlist ?? []).filter((v) => typeof v === "string" && v.length > 0);
727
+ const hasAllowlist = allowlist.length > 0;
728
+ const isAllowlisted = (filePath) => {
729
+ const normalized = filePath.replace(/\\/g, "/");
730
+ for (const entry of allowlist) {
731
+ const rule = entry.replace(/\\/g, "/");
732
+ if (rule.endsWith("/")) {
733
+ if (normalized.startsWith(rule)) return true;
734
+ } else if (normalized === rule) {
735
+ return true;
736
+ }
737
+ }
738
+ return false;
739
+ };
740
+ const filterCandidateFiles = (files) => {
741
+ if (!files) return void 0;
742
+ if (!hasAllowlist) return files;
743
+ const filtered = files.filter(isAllowlisted);
744
+ return filtered.length > 0 ? filtered : void 0;
745
+ };
746
+ const successfulCandidates = candidates.filter(
747
+ (c) => c.success && filterCandidateFiles(c.changedFiles)?.length
748
+ );
749
+ if (successfulCandidates.length < 2) {
750
+ return {
751
+ pairwiseSimilarity: {},
752
+ averageSimilarity: 1,
753
+ // Single candidate = coherent with itself
754
+ isCoherent: true,
755
+ coherenceThreshold: threshold
756
+ };
757
+ }
758
+ const fileSets = /* @__PURE__ */ new Map();
759
+ for (const [index, candidate] of successfulCandidates.entries()) {
760
+ const provider = candidate.variant.provider;
761
+ const model = candidate.variant.model ?? "";
762
+ const strategy = candidate.variant.strategy ?? "";
763
+ const key = `${provider}:${model}:${strategy}:${index}`;
764
+ fileSets.set(key, new Set(filterCandidateFiles(candidate.changedFiles) || []));
765
+ }
766
+ const pairwiseSimilarity = {};
767
+ const candidateKeys = Array.from(fileSets.keys());
768
+ let totalSimilarity = 0;
769
+ let pairCount = 0;
770
+ for (let i = 0; i < candidateKeys.length; i++) {
771
+ for (let j = i + 1; j < candidateKeys.length; j++) {
772
+ const keyA = candidateKeys[i] ?? "";
773
+ const keyB = candidateKeys[j] ?? "";
774
+ const setA = fileSets.get(keyA);
775
+ const setB = fileSets.get(keyB);
776
+ if (!setA || !setB) continue;
777
+ const similarity = jaccardSimilarity(setA, setB);
778
+ const pairKey = `${keyA}|${keyB}`;
779
+ pairwiseSimilarity[pairKey] = Math.round(similarity * 100) / 100;
780
+ totalSimilarity += similarity;
781
+ pairCount++;
782
+ }
783
+ }
784
+ const averageSimilarity = pairCount > 0 ? totalSimilarity / pairCount : 1;
785
+ const isCoherent = averageSimilarity >= threshold;
786
+ const allFileSets = Array.from(fileSets.values());
787
+ const allFiles = new Set(allFileSets.flatMap((s) => [...s]));
788
+ const commonFiles = [...allFiles].filter((file) => allFileSets.every((set) => set.has(file)));
789
+ const uniqueFiles = {};
790
+ for (const [candidateKey, files] of fileSets) {
791
+ const unique = [...files].filter(
792
+ (file) => !Array.from(fileSets.entries()).filter(([k]) => k !== candidateKey).some(([, otherSet]) => otherSet.has(file))
793
+ );
794
+ if (unique.length > 0) {
795
+ uniqueFiles[candidateKey] = unique;
796
+ }
797
+ }
798
+ return {
799
+ pairwiseSimilarity,
800
+ averageSimilarity: Math.round(averageSimilarity * 100) / 100,
801
+ isCoherent,
802
+ coherenceThreshold: threshold,
803
+ fileOverlap: {
804
+ commonFiles,
805
+ uniqueFiles
806
+ }
807
+ };
808
+ }
809
+ function matchVariantResult(spec, results) {
810
+ const baseMatches = results.filter(
811
+ (v) => v.provider === spec.provider && (spec.model === void 0 || v.model === spec.model) && (spec.strategy === void 0 || v.strategy === spec.strategy)
812
+ );
813
+ if (baseMatches.length <= 1) return baseMatches[0];
814
+ const specEffort = normalizeReasoningEffortInput(spec.reasoning);
815
+ if (specEffort !== void 0) {
816
+ const effortMatch = baseMatches.find(
817
+ (v) => normalizeReasoningEffortInput(v.requestedReasoningEffort) === specEffort
818
+ );
819
+ if (effortMatch) return effortMatch;
820
+ }
821
+ return baseMatches[0];
822
+ }
823
+ function resolveCandidateCompletenessFallback(result) {
824
+ const typed = resolveTypedCompletenessAuthority(result);
825
+ if (typed.present) {
826
+ return typed.usable ? typed.score : -1;
827
+ }
828
+ return result.completeness;
829
+ }
830
+ function variantResultToCandidate(spec, result) {
831
+ if (!result) {
832
+ return {
833
+ variant: spec,
834
+ success: false,
835
+ error: "Variant not found in results",
836
+ cost: 0,
837
+ costUnavailableReason: "provider_not_reported",
838
+ durationMs: 0
839
+ };
840
+ }
841
+ const variantEvaluation = result.judgeEvaluation?.evaluations?.find(
842
+ (e) => e.variant === result.variant
843
+ );
844
+ const aiJudgeScore = variantEvaluation?.qualityScore != null ? Number(variantEvaluation.qualityScore) : void 0;
845
+ const score = aiJudgeScore ?? result.judgeScore ?? resolveCandidateCompletenessFallback(result);
846
+ const feedback = generateCandidateFeedback(variantEvaluation, result);
847
+ const testStatus = result.testStatus;
848
+ const testsExecuted = result.testsExecuted;
849
+ const nativeObservedCost = getFiniteNumberAtPath(result, ["result", "totalCostUsd"]) ?? getFiniteNumberAtPath(result, ["result", "total_cost_usd"]) ?? getFiniteNumberAtPath(result, ["result", "totalCost"]) ?? getFiniteNumberAtPath(result, ["totalCostUsd"]);
850
+ const metricsCost = getFiniteNumberAtPath(result.costMetrics, ["totalCost"]) ?? getFiniteNumberAtPath(result.costMetrics, ["totalCostUsd"]);
851
+ const metricsUnavailableReason = resolveCostMetricsUnavailableReason(result.costMetrics);
852
+ let cost;
853
+ let costUnavailableReason;
854
+ if (typeof nativeObservedCost === "number") {
855
+ cost = nativeObservedCost;
856
+ costUnavailableReason = void 0;
857
+ } else if (typeof metricsCost === "number" && metricsCost > 0) {
858
+ cost = metricsCost;
859
+ costUnavailableReason = void 0;
860
+ } else if (metricsUnavailableReason !== void 0) {
861
+ cost = 0;
862
+ costUnavailableReason = metricsUnavailableReason;
863
+ } else if (typeof metricsCost === "number") {
864
+ cost = metricsCost;
865
+ costUnavailableReason = void 0;
866
+ } else {
867
+ cost = 0;
868
+ costUnavailableReason = "provider_not_reported";
869
+ }
870
+ return {
871
+ variant: spec,
872
+ success: result.success,
873
+ error: result.error?.message,
874
+ score,
875
+ feedback,
876
+ cost,
877
+ costUnavailableReason,
878
+ durationMs: getVariantDurationMs(result),
879
+ worktreePath: result.retainedWorktreePath,
880
+ changedFiles: extractChangedFiles(result),
881
+ changeTrackingAvailable: resultHasChangeTracking(result),
882
+ testStatus,
883
+ testsExecuted,
884
+ mergeInvariantValidation: result.mergeInvariantValidation
885
+ };
886
+ }
887
+ function resolveCompetitionCostAggregate(candidates) {
888
+ let sum = 0;
889
+ let firstExplicitReason;
890
+ let sawPricingUnavailable = false;
891
+ let sawUnavailable = false;
892
+ for (const candidate of candidates) {
893
+ if (candidate.costUnavailableReason !== void 0) {
894
+ sawUnavailable = true;
895
+ if (candidate.costUnavailableReason === "pricing_unavailable") {
896
+ sawPricingUnavailable = true;
897
+ } else if (firstExplicitReason === void 0) {
898
+ firstExplicitReason = candidate.costUnavailableReason;
899
+ }
900
+ sum = 0;
901
+ continue;
902
+ }
903
+ if (typeof candidate.cost !== "number" || !Number.isFinite(candidate.cost)) {
904
+ sawUnavailable = true;
905
+ if (firstExplicitReason === void 0) {
906
+ firstExplicitReason = "provider_not_reported";
907
+ }
908
+ sum = 0;
909
+ continue;
910
+ }
911
+ if (!sawUnavailable) {
912
+ sum += candidate.cost;
913
+ }
914
+ }
915
+ if (sawUnavailable) {
916
+ return {
917
+ cost: 0,
918
+ costUnavailableReason: sawPricingUnavailable ? "pricing_unavailable" : firstExplicitReason ?? "provider_not_reported"
919
+ };
920
+ }
921
+ return { cost: sum };
922
+ }
923
+ function candidateMatchesVariantResult(candidate, result) {
924
+ if (candidate.variant.provider !== result.provider) return false;
925
+ if (candidate.variant.model !== void 0 && candidate.variant.model !== result.model) {
926
+ return false;
927
+ }
928
+ if (candidate.variant.strategy !== void 0 && candidate.variant.strategy !== result.strategy) {
929
+ return false;
930
+ }
931
+ const specEffort = normalizeReasoningEffortInput(candidate.variant.reasoning);
932
+ const resultEffort = normalizeReasoningEffortInput(result.requestedReasoningEffort);
933
+ if (specEffort !== void 0 && resultEffort !== void 0 && specEffort !== resultEffort) {
934
+ return false;
935
+ }
936
+ return true;
937
+ }
938
+ function isJudgeType(value) {
939
+ return value === "ai" || value === "multi-lens" || value === "multi-agent";
940
+ }
941
+ function buildMultiJudgeEvidenceBlock(args) {
942
+ const synthesisContext = args.judgeResult?.synthesisContext;
943
+ if (!synthesisContext && !args.matrixRan) {
944
+ return void 0;
945
+ }
946
+ const judgesWithVerdicts = synthesisContext?.judgeResults ? Object.entries(synthesisContext.judgeResults).filter(([, result]) => result !== void 0 && result !== null).map(([judgeId]) => judgeId) : [];
947
+ return {
948
+ selectedJudge: synthesisContext?.selectedJudge,
949
+ judgeRunRequested: args.judgeRunRequested ?? [],
950
+ judgesWithVerdicts,
951
+ allJudgesAgree: synthesisContext?.disagreement?.allAgree,
952
+ matrixAuthority: args.matrixAuthority,
953
+ matrixRan: args.matrixRan,
954
+ matrixProfileAgreement: args.matrixProfileAgreement,
955
+ matrixNonSelectionReasons: args.matrixNonSelectionReasons && args.matrixNonSelectionReasons.length > 0 ? args.matrixNonSelectionReasons : void 0
956
+ };
957
+ }
958
+ function findCandidateForVariantResult(candidates, result) {
959
+ return candidates.find((candidate) => candidateMatchesVariantResult(candidate, result));
960
+ }
961
+ function recordDeterministicTestSignalObservation(candidates, verbose) {
962
+ const hasVerifiedPassingCandidate = candidates.some(
963
+ (c) => c.success && c.testsExecuted !== void 0 && c.testStatus === "passed"
964
+ );
965
+ if (!hasVerifiedPassingCandidate) return;
966
+ for (const candidate of candidates) {
967
+ if (!candidate.success) continue;
968
+ if (!candidate.testsExecuted) continue;
969
+ const status = candidate.testStatus ?? "not_run";
970
+ if (status !== "failed" && status !== "error" && status !== "timeout") continue;
971
+ const note = `Verified failing test observation recorded (testStatus=${status}).`;
972
+ candidate.feedback = candidate.feedback ? `${note}
973
+
974
+ ${candidate.feedback}` : note;
975
+ if (verbose) {
976
+ const id = `${candidate.variant.provider}:${candidate.variant.model ?? ""}:${candidate.variant.strategy ?? ""}`;
977
+ console.log(
978
+ chalk.yellow(` Test observation: ${id} retained score ${candidate.score ?? 0}`)
979
+ );
980
+ }
981
+ }
982
+ }
983
+ function variantIdForSpec(spec) {
984
+ const provider = spec.provider ?? "";
985
+ const model = spec.model ?? "";
986
+ const strategy = spec.strategy ?? "";
987
+ return `${provider}:${model}:${strategy}`;
988
+ }
989
+ function variantResultDiagnosticId(result) {
990
+ const provider = result.provider ?? "unknown";
991
+ const model = result.model ?? "";
992
+ const strategy = result.strategy ?? "";
993
+ const variant = result.variant ? ` (${result.variant})` : "";
994
+ return `${provider}:${model}:${strategy}${variant}`;
995
+ }
996
+ function buildWinnerInfoFromJudgeVerdict(candidates, judgedWinner, judgeVisibleCandidates) {
997
+ const rankedPool = judgeVisibleCandidates && judgeVisibleCandidates.length > 0 ? judgeVisibleCandidates : candidates.filter((c) => c.success);
998
+ if (rankedPool.length === 0) {
999
+ return {
1000
+ winner: null,
1001
+ noWinnerReason: "all-failed",
1002
+ wasTie: false,
1003
+ rankings: []
1004
+ };
1005
+ }
1006
+ const ranked = [...rankedPool].sort((a, b) => {
1007
+ const scoreA = Number(a.score ?? 0);
1008
+ const scoreB = Number(b.score ?? 0);
1009
+ if (scoreB !== scoreA) return scoreB - scoreA;
1010
+ return variantIdForSpec(a.variant).localeCompare(variantIdForSpec(b.variant));
1011
+ });
1012
+ const rankings = ranked.map((c, i) => ({
1013
+ variant: c.variant,
1014
+ score: c.score ?? 0,
1015
+ rank: i + 1
1016
+ }));
1017
+ const topScore = Number(ranked[0]?.score ?? 0);
1018
+ const tiedAtTop = ranked.filter((c) => Number(c.score ?? 0) === topScore);
1019
+ const wasTie = tiedAtTop.length > 1;
1020
+ if (!judgedWinner) {
1021
+ return {
1022
+ winner: null,
1023
+ wasTie,
1024
+ rankings
1025
+ };
1026
+ }
1027
+ const winner = findCandidateForVariantResult(rankedPool, judgedWinner) ?? findCandidateForVariantResult(candidates, judgedWinner);
1028
+ if (!winner) {
1029
+ return {
1030
+ winner: null,
1031
+ wasTie,
1032
+ rankings,
1033
+ noWinnerReason: "judge-error",
1034
+ noWinnerDiagnostic: `AI judge selected an unmatched winner (${variantResultDiagnosticId(
1035
+ judgedWinner
1036
+ )}); judge-visible candidates: ${rankedPool.map((candidate) => variantIdForSpec(candidate.variant)).join(", ")}`
1037
+ };
1038
+ }
1039
+ return {
1040
+ winner,
1041
+ wasTie,
1042
+ rankings
1043
+ };
1044
+ }
1045
+ function attachGateObservationsToVariantResult(result, candidate) {
1046
+ const candidateFindings = candidate.verification?.findings ?? [];
1047
+ const gateError = candidate.success === false ? candidate.error : void 0;
1048
+ if (candidateFindings.length === 0 && !gateError) {
1049
+ return result;
1050
+ }
1051
+ const existingFindings = result.verification?.findings ?? [];
1052
+ const mergedFindings = [...existingFindings];
1053
+ for (const finding of candidateFindings) {
1054
+ const mapped = toCoreVerificationFinding(finding);
1055
+ const alreadyPresent = mergedFindings.some(
1056
+ (existing) => existing.kind === mapped.kind && existing.command === mapped.command && existing.exitCode === mapped.exitCode
1057
+ );
1058
+ if (!alreadyPresent) {
1059
+ mergedFindings.push(mapped);
1060
+ }
1061
+ }
1062
+ if (gateError && mergedFindings.length === existingFindings.length) {
1063
+ mergedFindings.push({
1064
+ kind: "other",
1065
+ command: "candidate-gate",
1066
+ exitCode: 1,
1067
+ severity: "error",
1068
+ outputTail: gateError
1069
+ });
1070
+ }
1071
+ const verificationPassed = candidate.verification?.passed === false ? false : gateError ? false : result.verification?.passed ?? true;
1072
+ result.verification = {
1073
+ ...result.verification ?? {},
1074
+ passed: verificationPassed,
1075
+ findings: mergedFindings
1076
+ };
1077
+ return result;
1078
+ }
1079
+ function buildJudgeVisibleVariantResults(finishedCandidates, basicVariants) {
1080
+ const results = [];
1081
+ for (const candidate of finishedCandidates) {
1082
+ const matching = matchVariantResult(candidate.variant, basicVariants);
1083
+ if (!matching) continue;
1084
+ results.push(attachGateObservationsToVariantResult(matching, candidate));
1085
+ }
1086
+ return results;
1087
+ }
1088
+ function determineWinner(candidates, config, expectedAllowlist) {
1089
+ const SCORE_COLLISION_DECIMALS = 6;
1090
+ const SCORE_COLLISION_MULTIPLIER = 10 ** SCORE_COLLISION_DECIMALS;
1091
+ const quantizeScore = (score) => {
1092
+ if (!Number.isFinite(score)) return 0;
1093
+ return Math.round(score * SCORE_COLLISION_MULTIPLIER) / SCORE_COLLISION_MULTIPLIER;
1094
+ };
1095
+ const variantIdFor = variantIdForSpec;
1096
+ const buildCollisionReport = (args) => {
1097
+ const tiedAtTop2 = [...args.tiedAtTop].map((c) => {
1098
+ const raw = Number(c.score ?? 0);
1099
+ const q = quantizeScore(raw);
1100
+ return { candidate: c, scoreRaw: raw, scoreQuantized: q, id: variantIdFor(c.variant) };
1101
+ }).sort((a, b) => a.id.localeCompare(b.id)).map((x) => ({
1102
+ variant: x.candidate.variant,
1103
+ scoreRaw: x.scoreRaw,
1104
+ scoreQuantized: x.scoreQuantized
1105
+ }));
1106
+ const otherCollisionGroups2 = [...args.otherCollisionGroups].sort((a, b) => b.scoreQuantized - a.scoreQuantized).map((group) => ({
1107
+ scoreQuantized: group.scoreQuantized,
1108
+ entries: [...group.entries].map((e) => ({ ...e, id: variantIdFor(e.variant) })).sort((a, b) => a.id.localeCompare(b.id)).map((e) => ({ variant: e.variant, scoreRaw: e.scoreRaw }))
1109
+ }));
1110
+ return {
1111
+ precisionDecimals: SCORE_COLLISION_DECIMALS,
1112
+ quantization: "round",
1113
+ topScoreRaw: args.topScoreRaw,
1114
+ topScoreQuantized: args.topScoreQuantized,
1115
+ successfulCandidateCount: args.successfulCount,
1116
+ collisionGroupCount: args.collisionGroupsAll.length,
1117
+ collisionPairCount: args.collisionGroupsAll.reduce(
1118
+ (sum, g) => sum + g.entries.length * (g.entries.length - 1) / 2,
1119
+ 0
1120
+ ),
1121
+ tiedAtTopPairCount: args.tiedAtTop.length * (args.tiedAtTop.length - 1) / 2,
1122
+ tiedAtTop: tiedAtTop2,
1123
+ otherCollisionGroups: otherCollisionGroups2,
1124
+ applied: args.applied
1125
+ };
1126
+ };
1127
+ const computeCollisionGroups = (rankedSuccessful) => {
1128
+ const groups = /* @__PURE__ */ new Map();
1129
+ for (const candidate of rankedSuccessful) {
1130
+ const scoreRaw = Number(candidate.score ?? 0);
1131
+ const scoreQuantized = quantizeScore(scoreRaw);
1132
+ const existing = groups.get(scoreQuantized);
1133
+ if (existing) {
1134
+ existing.push({ variant: candidate.variant, scoreRaw });
1135
+ } else {
1136
+ groups.set(scoreQuantized, [{ variant: candidate.variant, scoreRaw }]);
1137
+ }
1138
+ }
1139
+ const out = [];
1140
+ for (const [scoreQuantized, entries] of groups.entries()) {
1141
+ if (entries.length < 2) continue;
1142
+ out.push({ scoreQuantized, entries });
1143
+ }
1144
+ return out;
1145
+ };
1146
+ const successfulCandidates = candidates.filter((c) => c.success);
1147
+ const threshold = config.judgeConfig?.threshold ?? 0;
1148
+ const allowBelowThresholdWinner = config.judgeConfig?.allowBelowThresholdWinner ?? true;
1149
+ if (successfulCandidates.length === 0) {
1150
+ return {
1151
+ winner: null,
1152
+ noWinnerReason: "all-failed",
1153
+ wasTie: false,
1154
+ rankings: []
1155
+ };
1156
+ }
1157
+ const cleanCandidates = successfulCandidates.filter(
1158
+ (c) => !c.verification || c.verification.passed
1159
+ );
1160
+ const candidatesWithFindings = successfulCandidates.filter(
1161
+ (c) => c.verification && !c.verification.passed
1162
+ );
1163
+ const candidatesToRank = cleanCandidates.length > 0 ? cleanCandidates : successfulCandidates;
1164
+ const ranked = [...candidatesToRank].sort((a, b) => {
1165
+ const scoreA = Number(a.score ?? 0);
1166
+ const scoreB = Number(b.score ?? 0);
1167
+ const qa = quantizeScore(scoreA);
1168
+ const qb = quantizeScore(scoreB);
1169
+ if (qb !== qa) return qb - qa;
1170
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1171
+ });
1172
+ const rankings = ranked.map((c, i) => ({
1173
+ variant: c.variant,
1174
+ score: c.score ?? 0,
1175
+ rank: i + 1
1176
+ }));
1177
+ const topScore = Number(ranked[0]?.score ?? 0);
1178
+ const topScoreQuantized = quantizeScore(topScore);
1179
+ const tiedAtTop = ranked.filter((c) => quantizeScore(Number(c.score ?? 0)) === topScoreQuantized);
1180
+ const wasTie = tiedAtTop.length > 1;
1181
+ const collisionGroups = computeCollisionGroups(ranked);
1182
+ const otherCollisionGroups = collisionGroups.filter((g) => g.scoreQuantized !== topScoreQuantized).slice(0, 10);
1183
+ const scoreCollisionReportBase = wasTie || otherCollisionGroups.length > 0 ? {
1184
+ ranked,
1185
+ successfulCount: candidatesToRank.length,
1186
+ collisionGroupsAll: collisionGroups,
1187
+ topScoreRaw: topScore,
1188
+ topScoreQuantized,
1189
+ tiedAtTop,
1190
+ otherCollisionGroups
1191
+ } : null;
1192
+ if (wasTie) {
1193
+ if (config.applyWinner) {
1194
+ const tieBreakerConfig = config.tieBreaker ?? (config.candidateGate?.coverage ? { mode: "prefer-low-drift-then-diff" } : { mode: "prefer-first-ranked" });
1195
+ let winner2 = null;
1196
+ let resolvedBy = "rank";
1197
+ const getCandidateChangedFileCount = (candidate) => Array.isArray(candidate.changedFiles) ? candidate.changedFiles.length : 0;
1198
+ const getCandidateDriftViolations = (candidate) => {
1199
+ if (!Array.isArray(candidate.changedFiles) || candidate.changedFiles.length === 0) return 0;
1200
+ if (!Array.isArray(expectedAllowlist) || expectedAllowlist.length === 0) return 0;
1201
+ return findAllowlistViolations(candidate.changedFiles, expectedAllowlist).length;
1202
+ };
1203
+ if (tieBreakerConfig.mode === "inconclusive") {
1204
+ const aiJudgeDisabled = config.judgeConfig?.disableAiJudge === true;
1205
+ if (aiJudgeDisabled) {
1206
+ const scoreCollisionReport2 = scoreCollisionReportBase && scoreCollisionReportBase.tiedAtTop.length > 1 ? buildCollisionReport({
1207
+ ...scoreCollisionReportBase,
1208
+ applied: {
1209
+ applyWinner: Boolean(config.applyWinner),
1210
+ wasTie: true,
1211
+ noWinnerReason: "tie",
1212
+ tieBreakerMode: tieBreakerConfig.mode,
1213
+ resolvedBy: void 0,
1214
+ winnerVariant: void 0
1215
+ }
1216
+ }) : void 0;
1217
+ return {
1218
+ winner: null,
1219
+ noWinnerReason: "tie",
1220
+ wasTie: true,
1221
+ rankings,
1222
+ scoreCollisionReport: scoreCollisionReport2
1223
+ };
1224
+ }
1225
+ winner2 = tiedAtTop[0] ?? null;
1226
+ resolvedBy = "rank";
1227
+ } else if (tieBreakerConfig.mode === "prefer-first-ranked") {
1228
+ winner2 = tiedAtTop[0] ?? null;
1229
+ } else if (tieBreakerConfig.mode === "prefer-strategy" && tieBreakerConfig.strategy) {
1230
+ winner2 = tiedAtTop.find((c) => c.variant.strategy === tieBreakerConfig.strategy) ?? tiedAtTop[0] ?? null;
1231
+ resolvedBy = "strategy";
1232
+ } else if (tieBreakerConfig.mode === "prefer-low-drift") {
1233
+ winner2 = [...tiedAtTop].sort((a, b) => {
1234
+ const driftDelta = getCandidateDriftViolations(a) - getCandidateDriftViolations(b);
1235
+ if (driftDelta !== 0) return driftDelta;
1236
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1237
+ })[0] ?? null;
1238
+ resolvedBy = "drift";
1239
+ } else if (tieBreakerConfig.mode === "prefer-smaller-diff") {
1240
+ winner2 = [...tiedAtTop].sort((a, b) => {
1241
+ const diffDelta = getCandidateChangedFileCount(a) - getCandidateChangedFileCount(b);
1242
+ if (diffDelta !== 0) return diffDelta;
1243
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1244
+ })[0] ?? null;
1245
+ resolvedBy = "diff";
1246
+ } else if (tieBreakerConfig.mode === "prefer-low-drift-then-diff") {
1247
+ winner2 = [...tiedAtTop].sort((a, b) => {
1248
+ const driftDelta = getCandidateDriftViolations(a) - getCandidateDriftViolations(b);
1249
+ if (driftDelta !== 0) return driftDelta;
1250
+ const diffDelta = getCandidateChangedFileCount(a) - getCandidateChangedFileCount(b);
1251
+ if (diffDelta !== 0) return diffDelta;
1252
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1253
+ })[0] ?? null;
1254
+ if (winner2) {
1255
+ const winnerDrift = getCandidateDriftViolations(winner2);
1256
+ const allSameDrift = tiedAtTop.every(
1257
+ (c) => getCandidateDriftViolations(c) === winnerDrift
1258
+ );
1259
+ if (!allSameDrift) {
1260
+ resolvedBy = "drift";
1261
+ } else {
1262
+ const winnerDiff = getCandidateChangedFileCount(winner2);
1263
+ const allSameDiff = tiedAtTop.every(
1264
+ (c) => getCandidateChangedFileCount(c) === winnerDiff
1265
+ );
1266
+ resolvedBy = allSameDiff ? "rank" : "diff";
1267
+ }
1268
+ } else {
1269
+ resolvedBy = "drift";
1270
+ }
1271
+ } else {
1272
+ winner2 = tiedAtTop[0] ?? null;
1273
+ }
1274
+ if (!winner2) winner2 = ranked[0] ?? null;
1275
+ if (winner2) {
1276
+ const scoreCollisionReport2 = scoreCollisionReportBase && scoreCollisionReportBase.tiedAtTop.length > 1 ? buildCollisionReport({
1277
+ ...scoreCollisionReportBase,
1278
+ applied: {
1279
+ applyWinner: true,
1280
+ wasTie: true,
1281
+ noWinnerReason: void 0,
1282
+ tieBreakerMode: tieBreakerConfig.mode,
1283
+ resolvedBy,
1284
+ winnerVariant: winner2.variant
1285
+ }
1286
+ }) : void 0;
1287
+ return {
1288
+ winner: winner2,
1289
+ wasTie: true,
1290
+ // Still record that there was a tie
1291
+ rankings,
1292
+ tieBreaker: {
1293
+ mode: tieBreakerConfig.mode,
1294
+ preferredStrategy: tieBreakerConfig.strategy,
1295
+ resolvedBy,
1296
+ winnerDriftViolations: getCandidateDriftViolations(winner2),
1297
+ winnerChangedFiles: getCandidateChangedFileCount(winner2),
1298
+ tieScore: topScore,
1299
+ tieScoreRounded: topScoreQuantized,
1300
+ tieScoreRoundedDecimals: SCORE_COLLISION_DECIMALS,
1301
+ tiedCount: tiedAtTop.length
1302
+ },
1303
+ scoreCollisionReport: scoreCollisionReport2
1304
+ };
1305
+ }
1306
+ }
1307
+ const scoreCollisionReport = scoreCollisionReportBase && scoreCollisionReportBase.tiedAtTop.length > 1 ? buildCollisionReport({
1308
+ ...scoreCollisionReportBase,
1309
+ applied: {
1310
+ applyWinner: Boolean(config.applyWinner),
1311
+ wasTie: true,
1312
+ noWinnerReason: "tie",
1313
+ tieBreakerMode: config.tieBreaker?.mode,
1314
+ resolvedBy: void 0,
1315
+ winnerVariant: void 0
1316
+ }
1317
+ }) : void 0;
1318
+ return {
1319
+ winner: null,
1320
+ noWinnerReason: "tie",
1321
+ wasTie: true,
1322
+ rankings,
1323
+ scoreCollisionReport
1324
+ };
1325
+ }
1326
+ if (topScore < threshold) {
1327
+ const verificationPolicy = config.verificationPolicy ?? "findings";
1328
+ if (verificationPolicy === "findings") {
1329
+ const bestRepairable = candidatesWithFindings.map((c) => ({
1330
+ candidate: c,
1331
+ effectiveScore: c.scoreBeforeTestSignal ?? c.score ?? 0
1332
+ })).filter((x) => x.effectiveScore >= threshold).sort((a, b) => b.effectiveScore - a.effectiveScore)[0]?.candidate;
1333
+ if (bestRepairable) {
1334
+ const restoredScore = bestRepairable.scoreBeforeTestSignal ?? bestRepairable.score;
1335
+ return {
1336
+ winner: {
1337
+ ...bestRepairable,
1338
+ score: restoredScore,
1339
+ feedback: bestRepairable.feedback ? `Selected for repair (tests recorded findings; observed score: ${restoredScore}).
1340
+
1341
+ ${bestRepairable.feedback}` : `Selected for repair (tests recorded findings; observed score: ${restoredScore}).`
1342
+ },
1343
+ wasTie: false,
1344
+ rankings
1345
+ };
1346
+ }
1347
+ }
1348
+ if (allowBelowThresholdWinner) {
1349
+ const winner2 = ranked[0] ?? null;
1350
+ if (winner2) {
1351
+ return {
1352
+ winner: winner2,
1353
+ wasTie: false,
1354
+ rankings,
1355
+ belowThresholdWinner: {
1356
+ threshold,
1357
+ winnerScore: topScore
1358
+ },
1359
+ scoreCollisionReport: scoreCollisionReportBase && (scoreCollisionReportBase.tiedAtTop.length > 1 || scoreCollisionReportBase.otherCollisionGroups.length > 0) ? buildCollisionReport({
1360
+ ...scoreCollisionReportBase,
1361
+ applied: {
1362
+ applyWinner: Boolean(config.applyWinner),
1363
+ wasTie: false,
1364
+ noWinnerReason: void 0,
1365
+ tieBreakerMode: config.tieBreaker?.mode,
1366
+ resolvedBy: void 0,
1367
+ winnerVariant: winner2.variant
1368
+ }
1369
+ }) : void 0
1370
+ };
1371
+ }
1372
+ }
1373
+ return {
1374
+ winner: null,
1375
+ noWinnerReason: "below-threshold",
1376
+ wasTie: false,
1377
+ rankings,
1378
+ scoreCollisionReport: scoreCollisionReportBase && (scoreCollisionReportBase.tiedAtTop.length > 1 || scoreCollisionReportBase.otherCollisionGroups.length > 0) ? buildCollisionReport({
1379
+ ...scoreCollisionReportBase,
1380
+ applied: {
1381
+ applyWinner: Boolean(config.applyWinner),
1382
+ wasTie: false,
1383
+ noWinnerReason: "below-threshold",
1384
+ tieBreakerMode: config.tieBreaker?.mode,
1385
+ resolvedBy: void 0,
1386
+ winnerVariant: void 0
1387
+ }
1388
+ }) : void 0
1389
+ };
1390
+ }
1391
+ const winner = ranked[0] ?? null;
1392
+ return {
1393
+ winner,
1394
+ wasTie: false,
1395
+ rankings,
1396
+ scoreCollisionReport: scoreCollisionReportBase && (scoreCollisionReportBase.tiedAtTop.length > 1 || scoreCollisionReportBase.otherCollisionGroups.length > 0) ? buildCollisionReport({
1397
+ ...scoreCollisionReportBase,
1398
+ applied: {
1399
+ applyWinner: Boolean(config.applyWinner),
1400
+ wasTie: false,
1401
+ noWinnerReason: void 0,
1402
+ tieBreakerMode: config.tieBreaker?.mode,
1403
+ resolvedBy: void 0,
1404
+ winnerVariant: winner?.variant
1405
+ }
1406
+ }) : void 0
1407
+ };
1408
+ }
1409
+ var __internalDetermineWinner = determineWinner;
1410
+ var __internalRecordDeterministicTestSignalObservation = recordDeterministicTestSignalObservation;
1411
+ var __internalExtractChangedFilesFromResult = extractChangedFilesFromResult;
1412
+ var __internalGetVariantTelemetryStatePath = getVariantTelemetryStatePath;
1413
+ var __internalHydrateCandidateCostsFromTelemetry = hydrateCandidateCostsFromTelemetry;
1414
+ var __internalVariantResultToCandidate = variantResultToCandidate;
1415
+ var __internalMatchVariantResult = matchVariantResult;
1416
+ var __internalCandidateMatchesVariantResult = candidateMatchesVariantResult;
1417
+ var __internalResolveCompetitionCostAggregate = resolveCompetitionCostAggregate;
1418
+ function synthesizeDeterministicRationalePacket(candidates, winnerInfo, config) {
1419
+ const { winner, wasTie, noWinnerReason, tieBreaker, belowThresholdWinner } = winnerInfo;
1420
+ const buildVariantId = (candidate) => {
1421
+ const parts = [candidate.variant.provider];
1422
+ if (candidate.variant.model) parts.push(candidate.variant.model);
1423
+ if (candidate.variant.strategy) parts.push(candidate.variant.strategy);
1424
+ return parts.join(":");
1425
+ };
1426
+ const candidateToVariantResult = (candidate) => ({
1427
+ variant: buildVariantId(candidate),
1428
+ success: candidate.success,
1429
+ testStatus: candidate.testStatus,
1430
+ testsExecuted: candidate.testsExecuted ? {
1431
+ scope: candidate.testsExecuted.scope ?? "touched",
1432
+ filesTested: candidate.testsExecuted.filesTested ?? [],
1433
+ exitCode: candidate.testsExecuted.exitCode,
1434
+ durationMs: candidate.testsExecuted.durationMs
1435
+ } : void 0,
1436
+ emptyChanges: !candidate.changedFiles?.length,
1437
+ gitMetrics: candidate.changedFiles ? { filesChanged: candidate.changedFiles.length, linesAdded: 0, linesDeleted: 0 } : void 0,
1438
+ worktreeSummary: candidate.changedFiles ? {
1439
+ filesChanged: candidate.changedFiles.length,
1440
+ insertions: 0,
1441
+ deletions: 0,
1442
+ statusLines: candidate.changedFiles.map((f) => `M ${f}`)
1443
+ } : void 0
1444
+ });
1445
+ const effectiveWinner = winner;
1446
+ const winnerId = effectiveWinner ? buildVariantId(effectiveWinner) : "none";
1447
+ const scores = {};
1448
+ for (const candidate of candidates) {
1449
+ const variantId = buildVariantId(candidate);
1450
+ scores[variantId] = candidate.score ?? 0;
1451
+ }
1452
+ let unverifiedNegativeClaimCount = 0;
1453
+ const scoreBreakdown = {};
1454
+ for (const candidate of candidates) {
1455
+ const variantId = buildVariantId(candidate);
1456
+ const finalScore = candidate.score ?? 0;
1457
+ const subscores = {};
1458
+ const penalties = {};
1459
+ if (typeof candidate.score === "number") {
1460
+ subscores.delivery = candidate.score;
1461
+ }
1462
+ const deductions = [];
1463
+ if (candidate.testStatus === "failed" || candidate.testStatus === "error") {
1464
+ const testPenalty = candidate.scoreBeforeTestSignal ? candidate.scoreBeforeTestSignal - (candidate.score ?? 0) : 10;
1465
+ penalties.testFailure = testPenalty;
1466
+ const testEvidence = [];
1467
+ testEvidence.push({
1468
+ type: "metric",
1469
+ value: `testStatus: ${candidate.testStatus}`,
1470
+ context: "Test execution result"
1471
+ });
1472
+ if (candidate.testsExecuted?.exitCode !== void 0) {
1473
+ testEvidence.push({
1474
+ type: "metric",
1475
+ value: `exit code: ${candidate.testsExecuted.exitCode}`,
1476
+ context: "Test runner exit code"
1477
+ });
1478
+ }
1479
+ deductions.push({
1480
+ code: "test_failure",
1481
+ delta: -testPenalty,
1482
+ evidence: testEvidence,
1483
+ reason: "Tests failed during verification"
1484
+ });
1485
+ }
1486
+ if (!candidate.changedFiles?.length && candidate.success) {
1487
+ deductions.push({
1488
+ code: "empty_changes",
1489
+ delta: -50,
1490
+ evidence: [
1491
+ {
1492
+ type: "metric",
1493
+ value: "0 files changed",
1494
+ context: "Git status shows no changes"
1495
+ }
1496
+ ],
1497
+ reason: "No code changes detected"
1498
+ });
1499
+ }
1500
+ if (Array.isArray(candidate.changedFiles) && candidate.changedFiles.length > 10) {
1501
+ const excessPenalty = Math.min(10, (candidate.changedFiles.length - 10) * 2);
1502
+ penalties.other = excessPenalty;
1503
+ deductions.push({
1504
+ code: "off_target_files",
1505
+ delta: -excessPenalty,
1506
+ evidence: [
1507
+ {
1508
+ type: "metric",
1509
+ value: `${candidate.changedFiles.length} files changed`,
1510
+ context: "Excessive file changes may indicate scope creep"
1511
+ }
1512
+ ],
1513
+ reason: "Modified more than 10 files"
1514
+ });
1515
+ }
1516
+ const weights = {
1517
+ delivery: 1
1518
+ // Deterministic mode uses completeness as sole factor
1519
+ };
1520
+ const testStatus = candidate.testStatus;
1521
+ const testsExecuted = candidate.testsExecuted;
1522
+ scoreBreakdown[variantId] = {
1523
+ finalScore,
1524
+ subscores,
1525
+ weights,
1526
+ penalties: Object.keys(penalties).length > 0 ? penalties : void 0,
1527
+ aggregationMethod: "weighted_average",
1528
+ // Default for deterministic scoring
1529
+ // P2: Include floor (harmonic mean floor = 18 in Judge v2.2)
1530
+ floorApplied: 18,
1531
+ // P2b: Structured test status (first-class signal)
1532
+ ...testStatus && {
1533
+ testSignal: {
1534
+ status: testStatus,
1535
+ scope: testsExecuted?.scope,
1536
+ exitCode: testsExecuted?.exitCode,
1537
+ durationMs: testsExecuted?.durationMs,
1538
+ penaltyApplied: testStatus === "failed" || testStatus === "error" ? (penalties.testFailure ?? 0) > 0 : false
1539
+ }
1540
+ },
1541
+ // Include deduction trace with evidence (v0.5.0)
1542
+ deductions: deductions.length > 0 ? deductions : void 0
1543
+ };
1544
+ }
1545
+ const highestScoringCandidate = candidates.filter((candidate) => candidate.success && typeof candidate.score === "number").sort((a, b) => {
1546
+ const scoreDelta = Number(b.score ?? 0) - Number(a.score ?? 0);
1547
+ if (scoreDelta !== 0) return scoreDelta;
1548
+ return buildVariantId(a).localeCompare(buildVariantId(b));
1549
+ })[0];
1550
+ const highestScoringCandidateId = highestScoringCandidate ? buildVariantId(highestScoringCandidate) : void 0;
1551
+ const highestScore = highestScoringCandidate?.score ?? 0;
1552
+ const winnerScore = effectiveWinner?.score ?? 0;
1553
+ const winnerHasHighestDeterministicScore = Boolean(effectiveWinner) && (!highestScoringCandidate || highestScoringCandidateId === winnerId || Number(winnerScore) >= Number(highestScore));
1554
+ const candidateAnalysis = candidates.map((candidate) => {
1555
+ const variantId = buildVariantId(candidate);
1556
+ const isWinner = effectiveWinner && buildVariantId(effectiveWinner) === variantId;
1557
+ const strengths = [];
1558
+ const weaknesses = [];
1559
+ const missedRequirements = [];
1560
+ const riskyAreas = [];
1561
+ if (candidate.success) {
1562
+ strengths.push("Execution succeeded");
1563
+ if (typeof candidate.score === "number" && candidate.score > 80) {
1564
+ strengths.push(`High score: ${candidate.score}`);
1565
+ }
1566
+ if (candidate.testsExecuted && candidate.testStatus) {
1567
+ const scope = candidate.testsExecuted.scope ?? "unknown";
1568
+ if (candidate.testStatus === "passed") {
1569
+ strengths.push(`Tests passed (${scope})`);
1570
+ } else if (candidate.testStatus !== "not_run") {
1571
+ weaknesses.push(`Tests ${candidate.testStatus} (${scope})`);
1572
+ }
1573
+ }
1574
+ if (Array.isArray(candidate.changedFiles) && candidate.changedFiles.length > 0) {
1575
+ strengths.push(`Modified ${candidate.changedFiles.length} file(s)`);
1576
+ }
1577
+ } else {
1578
+ weaknesses.push("Execution failed");
1579
+ if (candidate.error) {
1580
+ weaknesses.push(`Error: ${candidate.error}`);
1581
+ }
1582
+ }
1583
+ if (!isWinner && candidate.success) {
1584
+ const candidateScore = candidate.score ?? 0;
1585
+ if (effectiveWinner && typeof candidate.score === "number") {
1586
+ if (candidateScore > winnerScore) {
1587
+ weaknesses.push(
1588
+ `Not selected despite higher deterministic score (${candidateScore} vs selected ${winnerScore})`
1589
+ );
1590
+ } else if (candidateScore === winnerScore) {
1591
+ weaknesses.push("Final tie-breaker selected another candidate");
1592
+ } else {
1593
+ weaknesses.push("Lower score than winner");
1594
+ }
1595
+ } else {
1596
+ weaknesses.push("Did not win final selection");
1597
+ }
1598
+ }
1599
+ const variantForEvidence = candidateToVariantResult(candidate);
1600
+ const weaknessEvidence = {
1601
+ weaknesses: weaknesses.map((weakness, index) => {
1602
+ const isNegative = isNegativeClaim(weakness);
1603
+ const anchors = isNegative ? extractEvidenceAnchors(weakness, variantForEvidence) : [];
1604
+ const verified = !isNegative || anchors.length > 0;
1605
+ if (isNegative && !verified) {
1606
+ unverifiedNegativeClaimCount++;
1607
+ }
1608
+ return {
1609
+ index,
1610
+ anchors: anchors.map((a) => ({
1611
+ type: a.type,
1612
+ value: a.value,
1613
+ context: a.context
1614
+ })),
1615
+ verified
1616
+ };
1617
+ })
1618
+ };
1619
+ return {
1620
+ variantId,
1621
+ strengths,
1622
+ weaknesses,
1623
+ missedRequirements,
1624
+ riskyAreas,
1625
+ evidence: weaknessEvidence.weaknesses?.length ? weaknessEvidence : void 0
1626
+ };
1627
+ });
1628
+ let primaryReason = "Winner selected by deterministic scoring";
1629
+ const keyFactors = [];
1630
+ const selectionEvidence = [];
1631
+ if (noWinnerReason) {
1632
+ const reasons = {
1633
+ "all-failed": "All variants failed execution",
1634
+ tie: "Tie between top variants",
1635
+ "below-threshold": `All scores below threshold (${config.judgeConfig?.threshold ?? 0})`,
1636
+ "judge-error": "Judge evaluation failed",
1637
+ incomparable: "Candidates touched disjoint files (low coherence)"
1638
+ };
1639
+ primaryReason = reasons[noWinnerReason] ?? noWinnerReason;
1640
+ } else if (wasTie && tieBreaker) {
1641
+ primaryReason = `Tie resolved by ${tieBreaker.mode} tiebreaker`;
1642
+ keyFactors.push(`Tiebreaker mode: ${tieBreaker.mode}`);
1643
+ if (tieBreaker.resolvedBy) {
1644
+ keyFactors.push(`Resolved by: ${tieBreaker.resolvedBy}`);
1645
+ }
1646
+ } else if (winner) {
1647
+ primaryReason = winnerHasHighestDeterministicScore ? "Highest deterministic score" : "Final winner selected by judge or selection policy despite lower deterministic score";
1648
+ keyFactors.push(`Score: ${winner.score ?? 0}`);
1649
+ if (!winnerHasHighestDeterministicScore && highestScoringCandidateId) {
1650
+ keyFactors.push(`Top deterministic score: ${highestScoringCandidateId} (${highestScore})`);
1651
+ keyFactors.push(`Selected winner score: ${winnerId} (${winnerScore})`);
1652
+ }
1653
+ selectionEvidence.push({
1654
+ type: "metric",
1655
+ value: `score: ${winner.score ?? 0}`,
1656
+ context: "Winner deterministic score"
1657
+ });
1658
+ if (winner.changedFiles?.length) {
1659
+ selectionEvidence.push({
1660
+ type: "metric",
1661
+ value: `${winner.changedFiles.length} files changed`,
1662
+ context: "Winner modified files"
1663
+ });
1664
+ }
1665
+ if (belowThresholdWinner) {
1666
+ keyFactors.push(
1667
+ `Below threshold: ${belowThresholdWinner.winnerScore} < ${belowThresholdWinner.threshold}`
1668
+ );
1669
+ }
1670
+ if (winner.testsExecuted && winner.testStatus === "passed") {
1671
+ keyFactors.push("Verified passing tests");
1672
+ selectionEvidence.push({
1673
+ type: "metric",
1674
+ value: "testStatus: passed",
1675
+ context: `Tests verified (${winner.testsExecuted.scope ?? "unknown"} scope)`
1676
+ });
1677
+ }
1678
+ if (winner.feedback) {
1679
+ keyFactors.push("Has feedback from deterministic evaluation");
1680
+ }
1681
+ }
1682
+ const rejectionReasons = {};
1683
+ const rejectionReasonsEvidence = {};
1684
+ for (const candidate of candidates) {
1685
+ const variantId = buildVariantId(candidate);
1686
+ if (effectiveWinner && buildVariantId(effectiveWinner) === variantId) continue;
1687
+ let reason;
1688
+ if (!candidate.success) {
1689
+ reason = candidate.error ?? "Execution failed";
1690
+ } else if (candidate.testsExecuted && candidate.testStatus && candidate.testStatus !== "passed") {
1691
+ reason = `Verified failing tests (testStatus=${candidate.testStatus})`;
1692
+ } else if (typeof candidate.score === "number" && typeof effectiveWinner?.score === "number") {
1693
+ if (candidate.score > effectiveWinner.score) {
1694
+ reason = `Not selected despite higher deterministic score (${candidate.score} vs selected ${effectiveWinner.score})`;
1695
+ } else if (candidate.score === effectiveWinner.score) {
1696
+ reason = `Final tie-breaker selected another candidate (${candidate.score} vs selected ${effectiveWinner.score})`;
1697
+ } else {
1698
+ reason = `Lower score (${candidate.score} vs ${effectiveWinner.score})`;
1699
+ }
1700
+ } else {
1701
+ reason = "Did not win deterministic selection";
1702
+ }
1703
+ rejectionReasons[variantId] = reason;
1704
+ if (isNegativeClaim(reason)) {
1705
+ const variantForEvidence = candidateToVariantResult(candidate);
1706
+ const anchors = extractEvidenceAnchors(reason, variantForEvidence);
1707
+ const verified = anchors.length > 0;
1708
+ rejectionReasonsEvidence[variantId] = {
1709
+ anchors: anchors.map((a) => ({
1710
+ type: a.type,
1711
+ value: a.value,
1712
+ context: a.context
1713
+ })),
1714
+ verified
1715
+ };
1716
+ if (!verified) {
1717
+ unverifiedNegativeClaimCount++;
1718
+ }
1719
+ }
1720
+ }
1721
+ const suggestedImprovements = [];
1722
+ const failedCount = candidates.filter((c) => !c.success).length;
1723
+ if (failedCount > 0) {
1724
+ suggestedImprovements.push(`${failedCount} variant(s) failed execution - investigate errors`);
1725
+ }
1726
+ if (wasTie) {
1727
+ suggestedImprovements.push("Consider refining task requirements to reduce ties");
1728
+ }
1729
+ let baseConfidence = noWinnerReason ? 0 : wasTie ? 60 : 100;
1730
+ if (unverifiedNegativeClaimCount > 0) {
1731
+ const penalty = Math.min(0.25, unverifiedNegativeClaimCount * 0.05);
1732
+ baseConfidence = Math.max(0, baseConfidence * (1 - penalty));
1733
+ }
1734
+ return {
1735
+ winnerId,
1736
+ scores,
1737
+ scoreBreakdown,
1738
+ // P1 Fix: Include detailed score breakdown with deduction traces
1739
+ candidateAnalysis,
1740
+ selectionRationale: {
1741
+ primary: primaryReason,
1742
+ keyFactors,
1743
+ confidence: baseConfidence,
1744
+ evidence: selectionEvidence.length > 0 ? selectionEvidence : void 0
1745
+ },
1746
+ rejectionReasons,
1747
+ rejectionReasonsEvidence: Object.keys(rejectionReasonsEvidence).length > 0 ? rejectionReasonsEvidence : void 0,
1748
+ suggestedImprovements,
1749
+ unverifiedNegativeClaimCount: unverifiedNegativeClaimCount > 0 ? unverifiedNegativeClaimCount : void 0
1750
+ };
1751
+ }
1752
+ function buildCompetitionBundle(taskId, candidates, basicResult) {
1753
+ const lines = [];
1754
+ lines.push("# Competition Bundle");
1755
+ lines.push("");
1756
+ lines.push(`Task ID: ${taskId}`);
1757
+ lines.push("");
1758
+ for (const candidate of candidates) {
1759
+ const provider = candidate.variant.provider;
1760
+ const model = candidate.variant.model;
1761
+ const strategy = candidate.variant.strategy;
1762
+ const header = [provider, model, strategy].filter(Boolean).join(" / ");
1763
+ const result = matchVariantResult(candidate.variant, basicResult.variants);
1764
+ lines.push(`## ${header || provider}`);
1765
+ lines.push("");
1766
+ lines.push(`- Success: ${candidate.success ? "yes" : "no"}`);
1767
+ lines.push(`- Score: ${candidate.score ?? 0}`);
1768
+ lines.push(`- Cost: $${candidate.cost.toFixed(4)}`);
1769
+ lines.push(`- Duration: ${(candidate.durationMs / 1e3).toFixed(1)}s`);
1770
+ if (candidate.error) {
1771
+ lines.push(`- Error: ${candidate.error}`);
1772
+ }
1773
+ const diff = result?.worktreeDiff;
1774
+ if (typeof diff === "string" && diff.trim().length > 0) {
1775
+ lines.push("");
1776
+ lines.push("```diff");
1777
+ lines.push(diff.trimEnd());
1778
+ lines.push("```");
1779
+ } else {
1780
+ lines.push("");
1781
+ lines.push("_No diff captured._");
1782
+ }
1783
+ lines.push("");
1784
+ }
1785
+ return lines.join("\n");
1786
+ }
1787
+ async function executeCompetitionStage(ctx) {
1788
+ const { stage, artifactStore, options } = ctx;
1789
+ const securityBoundary = ctx.securityBoundary ?? createSecurityBoundary(artifactStore.getWorkflowId());
1790
+ const startTime = Date.now();
1791
+ const config = stage.competition;
1792
+ if (!config || !config.variants || config.variants.length === 0) {
1793
+ throw new Error(`Stage '${stage.id}' is type=competition but has no variants configured`);
1794
+ }
1795
+ if (options.verbose) {
1796
+ console.log(chalk.blue(`
1797
+ Competition Stage: ${stage.id}`));
1798
+ console.log(chalk.gray(` Variants: ${config.variants.length}`));
1799
+ console.log(chalk.gray(` Providers: ${config.variants.map((v) => v.provider).join(", ")}`));
1800
+ }
1801
+ let resolvedPrompt = stage.prompt ?? "";
1802
+ try {
1803
+ resolvedPrompt = await resolvePromptArtifacts(
1804
+ stage.prompt ?? "",
1805
+ stage.inputs,
1806
+ artifactStore,
1807
+ stage.id,
1808
+ securityBoundary
1809
+ );
1810
+ } catch (error) {
1811
+ if (error instanceof ArtifactNotFoundError) {
1812
+ const result = {
1813
+ stageId: stage.id,
1814
+ stageType: "competition",
1815
+ validationPassed: false,
1816
+ cost: 0,
1817
+ candidates: [],
1818
+ winner: null,
1819
+ summary: `Failed to resolve input artifacts: ${error.message}`,
1820
+ durationMs: Date.now() - startTime
1821
+ };
1822
+ return result;
1823
+ }
1824
+ throw error;
1825
+ }
1826
+ if (options.verbose) {
1827
+ console.log(chalk.gray(` Prompt length: ${resolvedPrompt.length} chars`));
1828
+ }
1829
+ const effectiveMode = options.allowlistMode ?? "warn";
1830
+ const expectedAllowlistForSkip = computeExpectedAllowlist(stage);
1831
+ const requireChangesDemandsEdits = stage.validation?.requireChanges === true && stage.allowEmptyResults !== true;
1832
+ if (!requireChangesDemandsEdits && stageHasDeterministicChecks(stage) && typeof options.workerCwd === "string" && options.workerCwd.length > 0) {
1833
+ try {
1834
+ const skipProof = await evaluateStageCompletionProof({
1835
+ stage,
1836
+ worktreePath: options.workerCwd,
1837
+ stdout: "",
1838
+ attemptChangedFiles: [],
1839
+ allowlist: expectedAllowlistForSkip,
1840
+ stageId: stage.id
1841
+ });
1842
+ const alreadySatisfied = skipProof.contractsSatisfied && skipProof.hasHostSurface && skipProof.mayAcceptOutcome;
1843
+ if (alreadySatisfied) {
1844
+ const driftContext = computeCompetitionDrift([], expectedAllowlistForSkip, effectiveMode);
1845
+ const coherenceMetrics = computeCoherenceMetrics(
1846
+ [],
1847
+ DEFAULT_COHERENCE_THRESHOLD,
1848
+ expectedAllowlistForSkip
1849
+ );
1850
+ try {
1851
+ await artifactStore.save(stage.id, "stage-change", "json", {
1852
+ stageId: stage.id,
1853
+ stageType: "competition",
1854
+ mode: effectiveMode,
1855
+ deliveredFiles: driftContext.deliveredFiles,
1856
+ expectedFiles: driftContext.expectedFiles,
1857
+ violations: driftContext.violations,
1858
+ hasDrift: driftContext.hasDrift,
1859
+ candidateCount: 0,
1860
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1861
+ skipped: true,
1862
+ reason: "already-satisfied"
1863
+ });
1864
+ await artifactStore.save(
1865
+ stage.id,
1866
+ "stage-change-summary",
1867
+ "text",
1868
+ `${driftContext.summary}
1869
+
1870
+ Skipped: stage already satisfied`
1871
+ );
1872
+ const rationalePacket = {
1873
+ winnerId: "none",
1874
+ scores: {},
1875
+ candidateAnalysis: [],
1876
+ selectionRationale: {
1877
+ primary: "Competition skipped: stage already satisfied by deterministic checks",
1878
+ keyFactors: [
1879
+ "deterministic validation checks passed",
1880
+ "validation.requireChanges=false",
1881
+ "no variants executed"
1882
+ ],
1883
+ confidence: 100
1884
+ },
1885
+ rejectionReasons: {},
1886
+ suggestedImprovements: []
1887
+ };
1888
+ await artifactStore.save(stage.id, "judgeRationale", "json", rationalePacket);
1889
+ await artifactStore.save(stage.id, "winnerDiff", "diff", "");
1890
+ } catch {
1891
+ }
1892
+ return {
1893
+ stageId: stage.id,
1894
+ stageType: "competition",
1895
+ validationPassed: true,
1896
+ validationScore: 100,
1897
+ cost: 0,
1898
+ summary: "Competition skipped: stage already satisfied (idempotent)",
1899
+ durationMs: Date.now() - startTime,
1900
+ candidates: [],
1901
+ winner: null,
1902
+ winnerApplied: false,
1903
+ coherenceMetrics,
1904
+ markedIncomparable: false,
1905
+ scoringMode: "deterministic",
1906
+ competitionJudgeResult: {
1907
+ judgeType: config.judgeConfig?.type ?? "ai",
1908
+ aiJudgeAttempted: false,
1909
+ aiJudgeInvoked: false,
1910
+ aiJudgeError: void 0,
1911
+ judgeInvocationReason: "deterministic-shortcut",
1912
+ rankings: [],
1913
+ wasTie: false
1914
+ },
1915
+ driftContext,
1916
+ ...skipProof.evidence ? { completionEvidence: skipProof.evidence } : {}
1917
+ };
1918
+ }
1919
+ } catch {
1920
+ }
1921
+ }
1922
+ const executionIntent = resolveCompetitionExecutionIntent(stage);
1923
+ const variantConfigs = config.variants.map(
1924
+ (spec) => variantSpecToConfig(
1925
+ spec,
1926
+ executionIntent,
1927
+ stage,
1928
+ options.providerExecutionTransport,
1929
+ config.unknownStrategyPolicy
1930
+ )
1931
+ );
1932
+ const allowDuplicateVariantSpecs = config.allowDuplicateVariantSpecs ?? config.allowDuplicateStrategies;
1933
+ if (config.allowDuplicateVariantSpecs !== void 0 && config.allowDuplicateStrategies !== void 0 && config.allowDuplicateVariantSpecs !== config.allowDuplicateStrategies) {
1934
+ throw new Error(
1935
+ `Invalid competition config for stage '${stage.id}': \`competition.allowDuplicateVariantSpecs\` and \`competition.allowDuplicateStrategies\` are both set but differ. Use \`competition.allowDuplicateVariantSpecs\` and remove the deprecated \`competition.allowDuplicateStrategies\`.`
1936
+ );
1937
+ }
1938
+ assertNoDuplicateVariantSpecs(variantConfigs, {
1939
+ allowDuplicates: allowDuplicateVariantSpecs
1940
+ });
1941
+ const taskId = generateCompetitionId();
1942
+ const flywheelProjectRoot = getProjectRoot();
1943
+ const competitionOptions = {
1944
+ abortSignal: options.abortSignal,
1945
+ workerCwd: options.workerCwd,
1946
+ verbose: options.verbose,
1947
+ maxConcurrentVariants: options.maxConcurrentVariants,
1948
+ perVariantTimeoutMinutes: options.perVariantTimeoutMinutes,
1949
+ timeoutMinutes: options.timeoutMinutes,
1950
+ // Flywheel never consumes basic-competition synthesis (candidate gates / judge /
1951
+ // apply use variant results only). Always disable synthesis at this boundary so
1952
+ // agentic synthesis compute is not spent on discarded product. (Candidate gates
1953
+ // also run after Basic Competition returns, so early synthesis cannot see that
1954
+ // evidence and can emit misleading "0 eligible variants" warnings.)
1955
+ synthesize: false,
1956
+ deferEvaluationHandleFinalization: true,
1957
+ // Preserve worktrees only when needed for post-processing (e.g. candidateGate commands).
1958
+ // Winner application in flywheel-executor prefers `worktreeDiff` and does not require retained worktrees.
1959
+ preserveWorktrees: config.preserveCandidates ?? Boolean(config.candidateGate),
1960
+ executionContext: createExecutionContext({
1961
+ repoRoot: flywheelProjectRoot,
1962
+ poeticDir: path.join(flywheelProjectRoot, ".poetic"),
1963
+ taskId,
1964
+ envOverrides: config.preserveCandidates ?? Boolean(config.candidateGate) ? {
1965
+ POETIC_PRESERVE_WORKTREES: "1",
1966
+ POETIC_RETAIN_BASIC_WORKTREE: "1"
1967
+ } : {}
1968
+ })
1969
+ };
1970
+ let basicResult;
1971
+ try {
1972
+ basicResult = await runBasicCompetition(
1973
+ taskId,
1974
+ resolvedPrompt,
1975
+ variantConfigs,
1976
+ competitionOptions
1977
+ );
1978
+ } catch (error) {
1979
+ const errorMsg = error instanceof Error ? error.message : String(error);
1980
+ await finalizeEvaluationHandleAsync(
1981
+ taskId,
1982
+ createEvaluationHandleFinalState({
1983
+ outcome: "error",
1984
+ winner: null,
1985
+ errorMessage: errorMsg
1986
+ })
1987
+ );
1988
+ const result = {
1989
+ stageId: stage.id,
1990
+ stageType: "competition",
1991
+ validationPassed: false,
1992
+ cost: 0,
1993
+ candidates: [],
1994
+ winner: null,
1995
+ summary: `Competition execution failed: ${errorMsg}`,
1996
+ durationMs: Date.now() - startTime,
1997
+ competitionJudgeResult: {
1998
+ judgeType: config.judgeConfig?.type ?? "ai",
1999
+ aiJudgeAttempted: false,
2000
+ aiJudgeInvoked: false,
2001
+ aiJudgeError: errorMsg,
2002
+ judgeInvocationReason: "error",
2003
+ rankings: [],
2004
+ wasTie: false,
2005
+ noWinnerReason: "judge-error"
2006
+ }
2007
+ };
2008
+ return result;
2009
+ }
2010
+ let deferredHandleFinalized = false;
2011
+ const finalizeDeferredHandle = async (state) => {
2012
+ let finalizeResult = await finalizeEvaluationHandleAsync(taskId, state);
2013
+ if (finalizeResult.kind === "not_terminal") {
2014
+ await Promise.all(
2015
+ basicResult.variants.map(
2016
+ (variant) => updateEvaluationHandleWithResultAsync(taskId, variant)
2017
+ )
2018
+ );
2019
+ finalizeResult = await finalizeEvaluationHandleAsync(taskId, state);
2020
+ }
2021
+ if (finalizeResult.kind !== "absent" && !isDurableHandleCompletion(finalizeResult, state.status)) {
2022
+ throw new Error(
2023
+ `Evaluation handle did not reach durable ${state.status} state (kind=${finalizeResult.kind})`
2024
+ );
2025
+ }
2026
+ deferredHandleFinalized = true;
2027
+ };
2028
+ try {
2029
+ const basicInterruption = resolveBasicCompetitionInterruption(basicResult);
2030
+ if (basicInterruption) {
2031
+ const interruptedCandidates = config.variants.map(
2032
+ (spec) => variantResultToCandidate(spec, matchVariantResult(spec, basicResult.variants))
2033
+ );
2034
+ const { cost, costUnavailableReason: costUnavailableReason2 } = resolveCompetitionCostAggregate(interruptedCandidates);
2035
+ const timedOut = basicInterruption.kind === "timed_out";
2036
+ await finalizeDeferredHandle(
2037
+ timedOut ? createEvaluationHandleFinalState({
2038
+ outcome: "timed_out",
2039
+ winner: null,
2040
+ errorMessage: `Competition timed out after ${basicInterruption.timeout.timeoutMs}ms`
2041
+ }) : createEvaluationHandleFinalState({ outcome: "no_winner", winner: null })
2042
+ );
2043
+ await cleanupSynthesisInputPatches(basicResult.variants, {
2044
+ expectedRoot: resolveSynthesisInputPatchDir(
2045
+ competitionOptions.executionContext.poeticDir,
2046
+ taskId
2047
+ )
2048
+ });
2049
+ return {
2050
+ stageId: stage.id,
2051
+ stageType: "competition",
2052
+ validationPassed: false,
2053
+ cost,
2054
+ costUnavailableReason: costUnavailableReason2,
2055
+ candidates: interruptedCandidates,
2056
+ winner: null,
2057
+ summary: timedOut ? "Competition timed out; no winner selected" : `Competition canceled by ${basicInterruption.kind === "canceled" ? basicInterruption.signal : "unknown signal"}; no winner selected`,
2058
+ durationMs: Date.now() - startTime,
2059
+ competitionJudgeResult: {
2060
+ judgeType: config.judgeConfig?.type ?? "ai",
2061
+ aiJudgeAttempted: false,
2062
+ aiJudgeInvoked: false,
2063
+ judgeInvocationReason: timedOut ? "error" : "canceled",
2064
+ rankings: [],
2065
+ wasTie: false,
2066
+ noWinnerReason: timedOut ? "judge-error" : "canceled"
2067
+ }
2068
+ };
2069
+ }
2070
+ let aiJudgeAttempted = false;
2071
+ let aiJudgeInvoked = false;
2072
+ let judgedWinner = null;
2073
+ let aiJudgeError;
2074
+ let latestJudgeEscalation;
2075
+ let latestMainJudgeResult;
2076
+ let latestTiebreakJudgeResult;
2077
+ let matrixDefaultWinnerSource = "unknown";
2078
+ let eligibleVariantResultsForMatrix = [];
2079
+ let matrixRan = false;
2080
+ let matrixProfileAgreement;
2081
+ let effectiveMatrixAuthority;
2082
+ const matrixAuthorityWarnings = [];
2083
+ const matrixAuthorityNonSelectionReasons = [];
2084
+ const candidates = await Promise.all(
2085
+ config.variants.map(async (spec) => {
2086
+ const matchingResult = matchVariantResult(spec, basicResult.variants);
2087
+ const candidate = variantResultToCandidate(spec, matchingResult);
2088
+ if (candidate.success) return candidate;
2089
+ if (!isNoChangesDetectedError(candidate.error)) return candidate;
2090
+ if (requireChangesDemandsEdits) {
2091
+ return candidate;
2092
+ }
2093
+ if (!stageHasDeterministicChecks(stage)) return candidate;
2094
+ if (!candidate.worktreePath) return candidate;
2095
+ const stdout = getStringAtPath(matchingResult, ["result", "stdout"]) ?? "";
2096
+ const canAcceptNoop = await validateWorktreeAgainstStageChecks(
2097
+ stage,
2098
+ candidate.worktreePath,
2099
+ stdout,
2100
+ {
2101
+ attemptChangedFiles: candidate.changedFiles ?? [],
2102
+ allowlist: expectedAllowlistForSkip
2103
+ }
2104
+ );
2105
+ if (!canAcceptNoop) return candidate;
2106
+ return {
2107
+ ...candidate,
2108
+ success: true,
2109
+ error: void 0,
2110
+ score: candidate.score ?? 0
2111
+ };
2112
+ })
2113
+ );
2114
+ const finishedExecutionKeys = new Set(
2115
+ candidates.filter((c) => c.success).map((c) => variantIdForSpec(c.variant))
2116
+ );
2117
+ if (stage.validation?.requireChanges === true && stage.allowEmptyResults !== true) {
2118
+ for (let idx = 0; idx < candidates.length; idx++) {
2119
+ const candidate = candidates[idx];
2120
+ if (!candidate?.success || !candidateHasConcreteZeroChanges(candidate)) continue;
2121
+ candidates[idx] = {
2122
+ ...candidate,
2123
+ success: false,
2124
+ error: "Candidate produced no applicable changes but validation.requireChanges is enabled"
2125
+ };
2126
+ }
2127
+ }
2128
+ await hydrateCandidateCostsFromTelemetry(taskId, candidates, stage.id, options.verbose);
2129
+ const verificationPolicy = config.verificationPolicy ?? "findings";
2130
+ const candidatesWithTestFindings = [];
2131
+ for (let idx = 0; idx < candidates.length; idx++) {
2132
+ const candidate = candidates[idx];
2133
+ if (!candidate) continue;
2134
+ if (candidate.success && candidate.testsExecuted && candidate.testStatus && candidate.testStatus !== "passed" && candidate.testStatus !== "not_run") {
2135
+ const variantId = `${candidate.variant.provider}:${candidate.variant.model ?? ""}:${candidate.variant.strategy ?? ""}`;
2136
+ const testScope = candidate.testsExecuted.scope ?? "unknown";
2137
+ const exitCode = candidate.testsExecuted.exitCode ?? 1;
2138
+ const testLabel = `touched tests (scope: ${testScope})`;
2139
+ const verificationUnavailable = candidate.testStatus === "unavailable";
2140
+ const finding = {
2141
+ kind: "test",
2142
+ command: testLabel,
2143
+ exitCode,
2144
+ severity: verificationUnavailable ? "warning" : "error",
2145
+ recommendedNextStep: verificationUnavailable ? `Install or enable test tooling for scope: ${testScope}` : `Fix failing tests in scope: ${testScope}`
2146
+ };
2147
+ candidate.verification = {
2148
+ passed: false,
2149
+ findings: [finding]
2150
+ };
2151
+ if (verificationPolicy === "blocking") {
2152
+ candidatesWithTestFindings.push(
2153
+ `${variantId} (${verificationUnavailable ? "verification unavailable" : "disqualified"})`
2154
+ );
2155
+ candidates[idx] = {
2156
+ ...candidate,
2157
+ success: false,
2158
+ error: verificationUnavailable ? `Candidate gate unavailable: touched tests unavailable (scope: ${testScope})` : `Candidate gate failed: touched tests ${candidate.testStatus} (scope: ${testScope})`
2159
+ };
2160
+ } else {
2161
+ candidatesWithTestFindings.push(`${variantId} (findings recorded)`);
2162
+ }
2163
+ }
2164
+ }
2165
+ if (candidatesWithTestFindings.length > 0 && options.verbose) {
2166
+ const mode = verificationPolicy === "blocking" ? "disqualified" : "recorded findings for";
2167
+ console.log(
2168
+ chalk.yellow(
2169
+ ` ${candidatesWithTestFindings.length} candidate(s) ${mode}: ${candidatesWithTestFindings.join(", ")}`
2170
+ )
2171
+ );
2172
+ }
2173
+ if (config.candidateGate) {
2174
+ const gate = config.candidateGate;
2175
+ const gateResults = [];
2176
+ const gatedCandidates = await Promise.all(
2177
+ candidates.map(async (candidate) => {
2178
+ if (!candidate.success) {
2179
+ gateResults.push({
2180
+ provider: candidate.variant.provider,
2181
+ model: candidate.variant.model,
2182
+ strategy: candidate.variant.strategy,
2183
+ worktreePath: candidate.worktreePath,
2184
+ ran: false,
2185
+ passed: false,
2186
+ error: "Candidate did not execute successfully (gate not run)",
2187
+ commandResults: []
2188
+ });
2189
+ return candidate;
2190
+ }
2191
+ if (!candidate.worktreePath) {
2192
+ const msg = "Candidate gate requires a retained worktreePath but none was provided";
2193
+ gateResults.push({
2194
+ provider: candidate.variant.provider,
2195
+ model: candidate.variant.model,
2196
+ strategy: candidate.variant.strategy,
2197
+ worktreePath: candidate.worktreePath,
2198
+ ran: false,
2199
+ passed: false,
2200
+ error: msg,
2201
+ commandResults: []
2202
+ });
2203
+ return { ...candidate, success: false, error: `Candidate gate failed: ${msg}` };
2204
+ }
2205
+ const findings = [
2206
+ ...candidate.verification?.findings ?? []
2207
+ ];
2208
+ const renderedCommands = gate.commands.map(
2209
+ (command) => renderCandidateGateCommand(command, candidate)
2210
+ );
2211
+ const verifyResult = await runVerifyCommands({
2212
+ cwd: candidate.worktreePath,
2213
+ commands: renderedCommands,
2214
+ commandProvenance: "candidate-gate-config",
2215
+ timeoutMs: CANDIDATE_GATE_COMMAND_TIMEOUT_MS
2216
+ });
2217
+ const commandResults = verifyResult.results;
2218
+ const gatePassed = verifyResult.passed;
2219
+ let gateError;
2220
+ const failedCommand = commandResults.find((result2) => result2.exitCode !== 0);
2221
+ if (failedCommand) {
2222
+ gateError = `Verify command failed (exit ${failedCommand.exitCode}): ${failedCommand.command}`;
2223
+ findings.push({
2224
+ kind: "gate-command",
2225
+ command: failedCommand.command,
2226
+ exitCode: failedCommand.exitCode,
2227
+ outputTail: failedCommand.outputTail ?? failedCommand.stderrTail ?? failedCommand.stdoutTail,
2228
+ severity: "error",
2229
+ recommendedNextStep: `Fix gate command failure: ${failedCommand.command}`
2230
+ });
2231
+ }
2232
+ gateResults.push({
2233
+ provider: candidate.variant.provider,
2234
+ model: candidate.variant.model,
2235
+ strategy: candidate.variant.strategy,
2236
+ worktreePath: candidate.worktreePath,
2237
+ ran: true,
2238
+ passed: gatePassed,
2239
+ error: gateError,
2240
+ commandResults
2241
+ });
2242
+ if (!gatePassed) {
2243
+ candidate.verification = {
2244
+ passed: false,
2245
+ findings
2246
+ };
2247
+ if (verificationPolicy === "blocking") {
2248
+ return { ...candidate, success: false, error: `Candidate gate failed: ${gateError}` };
2249
+ }
2250
+ }
2251
+ return candidate;
2252
+ })
2253
+ );
2254
+ candidates.splice(0, candidates.length, ...gatedCandidates);
2255
+ try {
2256
+ await artifactStore.save(stage.id, "candidate-gates", "json", {
2257
+ taskId,
2258
+ stageId: stage.id,
2259
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2260
+ commands: gate.commands,
2261
+ candidateCount: candidates.length,
2262
+ passedCount: gateResults.filter((r) => r.passed).length,
2263
+ results: gateResults
2264
+ });
2265
+ } catch (error) {
2266
+ if (options.verbose) {
2267
+ console.warn(
2268
+ chalk.yellow(` Warning: Failed to persist candidate gate artifacts: ${error}`)
2269
+ );
2270
+ }
2271
+ }
2272
+ }
2273
+ const coverageConfig = config.candidateGate?.coverage;
2274
+ let usedCoverageScoring = false;
2275
+ let coverageDataAvailable = false;
2276
+ if (coverageConfig && Array.isArray(coverageConfig.targets) && coverageConfig.targets.length > 0) {
2277
+ const summaryPath = coverageConfig.summaryPath ?? "coverage/coverage-summary.json";
2278
+ const threshold = coverageConfig.threshold;
2279
+ const coverageMode = coverageConfig.mode ?? "absolute";
2280
+ const minDeltaPct = coverageConfig.minDeltaPct ?? 15;
2281
+ const largeFileLineThreshold = coverageConfig.largeFileLineThreshold ?? 300;
2282
+ const baselineSummary = typeof options.workerCwd === "string" && options.workerCwd.length > 0 ? await loadCoverageSummaryJson(options.workerCwd, summaryPath) : null;
2283
+ const baselineStats = computeCoverageStatsForTargets(baselineSummary, coverageConfig.targets);
2284
+ const baselineFromPrompt = parseBaselineLinesPctFromPrompt(resolvedPrompt);
2285
+ const effectiveBaselineAvgPct = baselineStats.avgPct ?? baselineFromPrompt;
2286
+ const perCandidateCoverage = [];
2287
+ for (let idx = 0; idx < candidates.length; idx++) {
2288
+ const candidate = candidates[idx];
2289
+ if (!candidate) continue;
2290
+ const worktreePath = candidate.worktreePath;
2291
+ let avgPct = null;
2292
+ let minPct = null;
2293
+ let maxTargetLines = null;
2294
+ let byTarget = {};
2295
+ let missingTargets = [];
2296
+ let disqualified = false;
2297
+ let disqualifyReason;
2298
+ let deltaAvgPct = null;
2299
+ const baselineAvgPct = effectiveBaselineAvgPct;
2300
+ if (candidate.success) {
2301
+ if (!worktreePath) {
2302
+ byTarget = Object.fromEntries(coverageConfig.targets.map((t) => [t, null]));
2303
+ missingTargets = [...coverageConfig.targets];
2304
+ const hasGateConfig = typeof threshold === "number" || coverageMode === "delta" || coverageMode === "auto";
2305
+ if (hasGateConfig) {
2306
+ disqualified = true;
2307
+ disqualifyReason = "Missing worktreePath required for coverage gate evaluation";
2308
+ }
2309
+ } else {
2310
+ const candidateSummary = await loadCoverageSummaryJson(worktreePath, summaryPath);
2311
+ const stats = computeCoverageStatsForTargets(candidateSummary, coverageConfig.targets);
2312
+ avgPct = stats.avgPct;
2313
+ minPct = stats.minPct;
2314
+ maxTargetLines = stats.maxTargetLines;
2315
+ byTarget = stats.byTarget;
2316
+ missingTargets = stats.missingTargets;
2317
+ deltaAvgPct = typeof avgPct === "number" ? Math.round(
2318
+ (avgPct - (typeof baselineAvgPct === "number" ? baselineAvgPct : 0)) * 100
2319
+ ) / 100 : null;
2320
+ let effectiveMode2 = coverageMode;
2321
+ if (coverageMode === "auto" && typeof maxTargetLines === "number") {
2322
+ effectiveMode2 = resolveAutoCoverageMode({
2323
+ maxTargetLines,
2324
+ largeFileLineThreshold,
2325
+ baselineAvgPct,
2326
+ threshold,
2327
+ minDeltaPct
2328
+ });
2329
+ }
2330
+ if (effectiveMode2 === "absolute" && typeof threshold === "number") {
2331
+ if (missingTargets.length > 0) {
2332
+ disqualified = true;
2333
+ disqualifyReason = `Missing coverage for targets: ${missingTargets.join(", ")}`;
2334
+ } else if (typeof minPct === "number" && minPct < threshold) {
2335
+ disqualified = true;
2336
+ disqualifyReason = `Coverage below threshold (${minPct.toFixed(1)}% < ${threshold}%)`;
2337
+ } else if (minPct === null) {
2338
+ disqualified = true;
2339
+ disqualifyReason = "Coverage data missing (unable to evaluate threshold)";
2340
+ }
2341
+ } else if (effectiveMode2 === "delta") {
2342
+ if (missingTargets.length > 0) {
2343
+ disqualified = true;
2344
+ disqualifyReason = `Missing coverage for targets: ${missingTargets.join(", ")}`;
2345
+ } else if (typeof deltaAvgPct === "number" && deltaAvgPct < minDeltaPct) {
2346
+ disqualified = true;
2347
+ disqualifyReason = `Coverage improvement below minimum (${deltaAvgPct.toFixed(1)}pp < ${minDeltaPct}pp)`;
2348
+ } else if (deltaAvgPct === null) {
2349
+ disqualified = true;
2350
+ disqualifyReason = "Coverage data missing (unable to evaluate delta)";
2351
+ }
2352
+ }
2353
+ }
2354
+ }
2355
+ let effectiveCandidate = candidate;
2356
+ if (effectiveCandidate.success && disqualified) {
2357
+ effectiveCandidate = {
2358
+ ...effectiveCandidate,
2359
+ success: false,
2360
+ error: `Candidate gate failed: ${disqualifyReason ?? "coverage threshold"}`
2361
+ };
2362
+ candidates[idx] = effectiveCandidate;
2363
+ }
2364
+ if (effectiveCandidate.success && typeof avgPct === "number") {
2365
+ effectiveCandidate = { ...effectiveCandidate, score: avgPct };
2366
+ candidates[idx] = effectiveCandidate;
2367
+ coverageDataAvailable = true;
2368
+ }
2369
+ perCandidateCoverage.push({
2370
+ provider: effectiveCandidate.variant.provider,
2371
+ model: effectiveCandidate.variant.model,
2372
+ strategy: effectiveCandidate.variant.strategy,
2373
+ worktreePath,
2374
+ success: effectiveCandidate.success,
2375
+ avgPct,
2376
+ minPct,
2377
+ maxTargetLines,
2378
+ baselineAvgPct,
2379
+ deltaAvgPct,
2380
+ byTarget,
2381
+ missingTargets,
2382
+ disqualified: disqualified || void 0,
2383
+ disqualifyReason
2384
+ });
2385
+ }
2386
+ try {
2387
+ await artifactStore.save(stage.id, "candidate-coverage", "json", {
2388
+ taskId,
2389
+ stageId: stage.id,
2390
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2391
+ summaryPath,
2392
+ gateConfig: {
2393
+ mode: coverageMode,
2394
+ threshold,
2395
+ minDeltaPct,
2396
+ largeFileLineThreshold
2397
+ },
2398
+ targets: coverageConfig.targets,
2399
+ baseline: {
2400
+ avgPct: effectiveBaselineAvgPct,
2401
+ minPct: baselineStats.minPct ?? baselineFromPrompt,
2402
+ totalLines: baselineStats.totalLines,
2403
+ maxTargetLines: baselineStats.maxTargetLines,
2404
+ byTarget: baselineStats.byTarget,
2405
+ missingTargets: baselineStats.missingTargets
2406
+ },
2407
+ candidates: perCandidateCoverage
2408
+ });
2409
+ } catch (error) {
2410
+ if (options.verbose) {
2411
+ console.warn(
2412
+ chalk.yellow(` Warning: Failed to persist candidate coverage artifacts: ${error}`)
2413
+ );
2414
+ }
2415
+ }
2416
+ usedCoverageScoring = coverageDataAvailable;
2417
+ }
2418
+ recordDeterministicTestSignalObservation(candidates, options.verbose);
2419
+ const expectedAllowlist = computeExpectedAllowlist(stage);
2420
+ const { cost: totalCost, costUnavailableReason } = resolveCompetitionCostAggregate(candidates);
2421
+ const finishedCandidates = candidates.filter(
2422
+ (c) => finishedExecutionKeys.has(variantIdForSpec(c.variant))
2423
+ );
2424
+ const shouldInvokeAiJudgeForFinished = finishedCandidates.length >= 2 && config.judgeConfig?.disableAiJudge !== true;
2425
+ const allCandidatesDisqualified = candidates.every((c) => !c.success);
2426
+ if (allCandidatesDisqualified && verificationPolicy === "blocking" && !shouldInvokeAiJudgeForFinished) {
2427
+ let disqualificationSummary = "Competition failed: All candidates disqualified by verification gates";
2428
+ const testGateUnavailable = candidates.filter(
2429
+ (c) => c.error?.includes("touched tests unavailable")
2430
+ );
2431
+ const testGateFailures = candidates.filter(
2432
+ (c) => !c.error?.includes("touched tests unavailable") && (c.error?.includes("touched tests") || c.error?.includes("Candidate gate failed"))
2433
+ );
2434
+ const coverageGateFailures = candidates.filter((c) => c.error?.includes("coverage"));
2435
+ const verifyFailures = candidates.filter(
2436
+ (c) => c.error?.includes("Verify stage failed") || c.error?.includes("verify.commands")
2437
+ );
2438
+ const requireChangesNoops = candidates.filter(
2439
+ (c) => c.error?.includes("validation.requireChanges is enabled")
2440
+ );
2441
+ const rootCauses = [];
2442
+ if (testGateUnavailable.length > 0) {
2443
+ rootCauses.push(
2444
+ `${testGateUnavailable.length} candidate(s) had unavailable deterministic test verification (touched tests unavailable)`
2445
+ );
2446
+ }
2447
+ if (testGateFailures.length > 0) {
2448
+ rootCauses.push(
2449
+ `${testGateFailures.length} candidate(s) failed deterministic test gate (touched tests failed)`
2450
+ );
2451
+ }
2452
+ if (coverageGateFailures.length > 0) {
2453
+ rootCauses.push(
2454
+ `${coverageGateFailures.length} candidate(s) failed coverage gate (below threshold)`
2455
+ );
2456
+ }
2457
+ if (verifyFailures.length > 0) {
2458
+ rootCauses.push(`${verifyFailures.length} candidate(s) failed verify stage commands`);
2459
+ }
2460
+ if (requireChangesNoops.length > 0) {
2461
+ rootCauses.push(
2462
+ `${requireChangesNoops.length} candidate(s) produced no applicable changes while validation.requireChanges is enabled`
2463
+ );
2464
+ }
2465
+ if (rootCauses.length > 0) {
2466
+ disqualificationSummary += `. Root cause: ${rootCauses.join("; ")}`;
2467
+ }
2468
+ const candidateErrors = candidates.filter((c) => c.error).map((c) => {
2469
+ const variantId = formatCompetitionCandidateVariantDisplay(c);
2470
+ return `${variantId} - ${c.error}`;
2471
+ }).join("; ");
2472
+ if (candidateErrors) {
2473
+ disqualificationSummary += `. Candidate details: ${candidateErrors}`;
2474
+ }
2475
+ const result2 = {
2476
+ stageId: stage.id,
2477
+ stageType: "competition",
2478
+ validationPassed: false,
2479
+ validationScore: 0,
2480
+ cost: totalCost,
2481
+ costUnavailableReason,
2482
+ summary: disqualificationSummary,
2483
+ durationMs: Date.now() - startTime,
2484
+ candidates,
2485
+ winner: null,
2486
+ winnerApplied: false,
2487
+ scoringMode: "deterministic",
2488
+ competitionJudgeResult: {
2489
+ judgeType: config.judgeConfig?.type ?? "ai",
2490
+ aiJudgeAttempted: false,
2491
+ aiJudgeInvoked: false,
2492
+ aiJudgeError: void 0,
2493
+ judgeInvocationReason: "no-successful-candidates",
2494
+ rankings: [],
2495
+ wasTie: false,
2496
+ noWinnerReason: "all-failed"
2497
+ }
2498
+ };
2499
+ try {
2500
+ await artifactStore.save(stage.id, "candidates", "json", {
2501
+ taskId,
2502
+ variantCount: candidates.length,
2503
+ successCount: 0,
2504
+ candidates: candidates.map((c) => ({
2505
+ provider: c.variant.provider,
2506
+ model: c.variant.model,
2507
+ strategy: c.variant.strategy,
2508
+ success: c.success,
2509
+ error: c.error,
2510
+ cost: c.cost,
2511
+ costUnavailableReason: c.costUnavailableReason
2512
+ })),
2513
+ winner: null,
2514
+ rankings: [],
2515
+ allDisqualifiedByTestGate: true,
2516
+ aiJudgeInvoked: result2.competitionJudgeResult?.aiJudgeInvoked ?? false,
2517
+ scoringMode: result2.scoringMode ?? "deterministic",
2518
+ judgeInvocationReason: result2.competitionJudgeResult?.judgeInvocationReason ?? "no-successful-candidates"
2519
+ });
2520
+ } catch (error) {
2521
+ if (options.verbose) {
2522
+ console.warn(chalk.yellow(` Warning: Failed to persist failure artifacts: ${error}`));
2523
+ }
2524
+ }
2525
+ await finalizeDeferredHandle(
2526
+ createEvaluationHandleFinalState({ outcome: "all_failed", winner: null })
2527
+ );
2528
+ await cleanupSynthesisInputPatches(basicResult.variants, {
2529
+ expectedRoot: resolveSynthesisInputPatchDir(
2530
+ competitionOptions.executionContext.poeticDir,
2531
+ taskId
2532
+ )
2533
+ });
2534
+ return result2;
2535
+ }
2536
+ const shouldInvokeAiJudge = shouldInvokeAiJudgeForFinished;
2537
+ if (shouldInvokeAiJudge) {
2538
+ if (options.verbose) {
2539
+ console.log(chalk.blue(" Invoking AI judge for competition evaluation..."));
2540
+ }
2541
+ const judgeVisibleVariantResults = buildJudgeVisibleVariantResults(
2542
+ finishedCandidates,
2543
+ basicResult.variants
2544
+ );
2545
+ if (judgeVisibleVariantResults.length < 2) {
2546
+ if (options.verbose) {
2547
+ console.warn(
2548
+ chalk.yellow(
2549
+ ` Skipping AI judge: expected \u22652 finished variants but resolved ${judgeVisibleVariantResults.length}`
2550
+ )
2551
+ );
2552
+ }
2553
+ } else {
2554
+ aiJudgeAttempted = true;
2555
+ try {
2556
+ const { aiJudgeRun, aiJudgePrimary } = deriveAiJudgeInvocationArgs(config.judgeConfig);
2557
+ eligibleVariantResultsForMatrix = judgeVisibleVariantResults;
2558
+ matrixDefaultWinnerSource = aiJudgePrimary;
2559
+ const judgeResult = await selectWinnerWithJudge(
2560
+ resolvedPrompt,
2561
+ judgeVisibleVariantResults,
2562
+ {
2563
+ taskId,
2564
+ aiJudgeTelemetry: true,
2565
+ aiJudgeRun,
2566
+ aiJudgePrimary,
2567
+ anonymizeJudge: config.judgeConfig?.anonymizeJudge,
2568
+ // The flywheel owns the explicit Matrix escalation block below;
2569
+ // opt out of the coordinator's automatic Matrix run to avoid a
2570
+ // duplicate Matrix call.
2571
+ autoMatrix: false
2572
+ }
2573
+ );
2574
+ latestMainJudgeResult = judgeResult;
2575
+ if (isJudgeType(judgeResult.synthesisContext?.selectedJudge)) {
2576
+ matrixDefaultWinnerSource = judgeResult.synthesisContext.selectedJudge;
2577
+ }
2578
+ latestJudgeEscalation = judgeResult.decision?.escalation;
2579
+ judgedWinner = judgeResult.winner;
2580
+ aiJudgeInvoked = true;
2581
+ for (const candidate of candidates) {
2582
+ if (!finishedExecutionKeys.has(variantIdForSpec(candidate.variant))) continue;
2583
+ const matchingResult = matchVariantResult(candidate.variant, basicResult.variants);
2584
+ if (!matchingResult) continue;
2585
+ const updated = variantResultToCandidate(candidate.variant, matchingResult);
2586
+ candidate.score = updated.score;
2587
+ candidate.feedback = updated.feedback;
2588
+ }
2589
+ recordDeterministicTestSignalObservation(candidates, options.verbose);
2590
+ if (options.verbose) {
2591
+ console.log(chalk.green(" ok AI judge evaluation complete"));
2592
+ }
2593
+ } catch (error) {
2594
+ const errorMsg = error instanceof Error ? error.message : String(error);
2595
+ if (options.verbose) {
2596
+ console.warn(chalk.yellow(` AI judge invocation failed: ${errorMsg}`));
2597
+ }
2598
+ aiJudgeError = errorMsg;
2599
+ aiJudgeInvoked = false;
2600
+ }
2601
+ }
2602
+ }
2603
+ let winnerInfo = aiJudgeInvoked ? buildWinnerInfoFromJudgeVerdict(candidates, judgedWinner, finishedCandidates) : determineWinner(candidates, config, expectedAllowlist);
2604
+ if (aiJudgeError && shouldInvokeAiJudge) {
2605
+ winnerInfo = {
2606
+ winner: null,
2607
+ rankings: [],
2608
+ wasTie: false,
2609
+ noWinnerReason: "judge-error",
2610
+ tieBreaker: void 0
2611
+ };
2612
+ }
2613
+ let tieBreakAiJudgeInvoked = false;
2614
+ if (!aiJudgeInvoked && usedCoverageScoring && winnerInfo.wasTie && config.judgeConfig && candidates.length > 1) {
2615
+ const successful = candidates.filter((c) => c.success && typeof c.score === "number");
2616
+ const SCORE_COLLISION_DECIMALS = 6;
2617
+ const SCORE_COLLISION_MULTIPLIER = 10 ** SCORE_COLLISION_DECIMALS;
2618
+ const quantizeScore = (score) => {
2619
+ if (!Number.isFinite(score)) return 0;
2620
+ return Math.round(score * SCORE_COLLISION_MULTIPLIER) / SCORE_COLLISION_MULTIPLIER;
2621
+ };
2622
+ const topScoreRaw = successful.reduce((max, c) => Math.max(max, c.score ?? 0), -Infinity);
2623
+ const topScoreQuantized = quantizeScore(topScoreRaw);
2624
+ const tiedAtTop = successful.filter(
2625
+ (c) => quantizeScore(Number(c.score ?? 0)) === topScoreQuantized
2626
+ );
2627
+ if (tiedAtTop.length >= 2) {
2628
+ const first = tiedAtTop[0];
2629
+ const getCandidateChangedFileCount = (candidate) => Array.isArray(candidate.changedFiles) ? candidate.changedFiles.length : 0;
2630
+ const getCandidateDriftViolations = (candidate) => {
2631
+ if (!Array.isArray(candidate.changedFiles) || candidate.changedFiles.length === 0)
2632
+ return 0;
2633
+ if (!Array.isArray(expectedAllowlist) || expectedAllowlist.length === 0) return 0;
2634
+ return findAllowlistViolations(candidate.changedFiles, expectedAllowlist).length;
2635
+ };
2636
+ const allSameDrift = first ? tiedAtTop.every(
2637
+ (c) => getCandidateDriftViolations(c) === getCandidateDriftViolations(first)
2638
+ ) : false;
2639
+ const allSameDiff = first ? tiedAtTop.every(
2640
+ (c) => getCandidateChangedFileCount(c) === getCandidateChangedFileCount(first)
2641
+ ) : false;
2642
+ if (allSameDrift && allSameDiff && typeof options.workerCwd === "string") {
2643
+ try {
2644
+ const { aiJudgeRun, aiJudgePrimary } = deriveAiJudgeInvocationArgs(config.judgeConfig);
2645
+ const tiedVariantResults = tiedAtTop.map((candidate) => matchVariantResult(candidate.variant, basicResult.variants)).filter(Boolean);
2646
+ if (tiedVariantResults.length >= 2) {
2647
+ const tiebreakJudgeResult = await selectWinnerWithJudge(
2648
+ resolvedPrompt,
2649
+ tiedVariantResults,
2650
+ {
2651
+ taskId,
2652
+ evaluationPhase: "tiebreak",
2653
+ aiJudgeTelemetry: true,
2654
+ aiJudgeRun,
2655
+ aiJudgePrimary,
2656
+ anonymizeJudge: config.judgeConfig?.anonymizeJudge,
2657
+ // Matrix escalation for this stage is owned by the explicit
2658
+ // block keyed off the main judge's escalation; keep the
2659
+ // tie-breaker from launching its own automatic Matrix run.
2660
+ autoMatrix: false
2661
+ }
2662
+ );
2663
+ latestTiebreakJudgeResult = tiebreakJudgeResult;
2664
+ const tiebreakWinner = tiebreakJudgeResult.winner;
2665
+ if (tiebreakWinner) {
2666
+ const winningCandidate = findCandidateForVariantResult(candidates, tiebreakWinner);
2667
+ if (winningCandidate) {
2668
+ tieBreakAiJudgeInvoked = true;
2669
+ winnerInfo = {
2670
+ ...winnerInfo,
2671
+ winner: winningCandidate
2672
+ };
2673
+ }
2674
+ }
2675
+ }
2676
+ } catch (error) {
2677
+ if (options.verbose) {
2678
+ console.warn(chalk.yellow(` AI judge tie-breaker failed: ${String(error)}`));
2679
+ }
2680
+ }
2681
+ }
2682
+ }
2683
+ }
2684
+ const defaultWinnerCandidate = winnerInfo.winner;
2685
+ if (latestJudgeEscalation?.recommended === "matrix" && eligibleVariantResultsForMatrix.length >= 2) {
2686
+ const matrixPolicy = resolveMatrixAuthorityPolicy(config.judgeConfig?.matrixAuthority);
2687
+ effectiveMatrixAuthority = matrixPolicy;
2688
+ try {
2689
+ const matrixCoordinator = new JudgeCoordinator();
2690
+ const matrixResult = await matrixCoordinator.evaluateProfileMatrix(
2691
+ eligibleVariantResultsForMatrix,
2692
+ resolvedPrompt,
2693
+ {
2694
+ taskId,
2695
+ anonymizeJudge: config.judgeConfig?.anonymizeJudge,
2696
+ evaluationContext: latestMainJudgeResult?.evaluationContext,
2697
+ matrixEscalationContext: {
2698
+ reasons: latestJudgeEscalation.reasons
2699
+ }
2700
+ }
2701
+ );
2702
+ const defaultWinnerResult = basicResult.variants.find(
2703
+ (variant) => defaultWinnerCandidate ? candidateMatchesVariantResult(defaultWinnerCandidate, variant) : false
2704
+ );
2705
+ const defaultWinner = defaultWinnerResult ? `${defaultWinnerResult.provider}:${defaultWinnerResult.variant}` : "none";
2706
+ const authorityDecision = evaluateMatrixAuthority({
2707
+ policy: matrixPolicy,
2708
+ defaultWinner,
2709
+ defaultWinnerSource: matrixDefaultWinnerSource,
2710
+ matrixEvaluatorType: matrixResult.matrixEvaluatorType,
2711
+ matrixResult,
2712
+ variants: eligibleVariantResultsForMatrix
2713
+ });
2714
+ matrixRan = true;
2715
+ matrixProfileAgreement = authorityDecision.profileAgreement;
2716
+ if (authorityDecision.selectedByMatrix && authorityDecision.matrixWinner && isAcceptedMatrixVerdict(authorityDecision.winnerStatus)) {
2717
+ const matrixWinnerCandidate = findCandidateForVariantResult(
2718
+ candidates,
2719
+ authorityDecision.matrixWinner
2720
+ );
2721
+ if (matrixWinnerCandidate) {
2722
+ winnerInfo = {
2723
+ ...winnerInfo,
2724
+ winner: matrixWinnerCandidate
2725
+ };
2726
+ } else {
2727
+ matrixAuthorityWarnings.push(
2728
+ "Matrix authority selected a variant that could not be resolved to a candidate"
2729
+ );
2730
+ }
2731
+ } else {
2732
+ if (!isAcceptedMatrixVerdict(authorityDecision.winnerStatus) && authorityDecision.nonSelectionReasons.length === 0) {
2733
+ matrixAuthorityNonSelectionReasons.push(
2734
+ `matrix winner status is ${authorityDecision.winnerStatus}`
2735
+ );
2736
+ }
2737
+ if (authorityDecision.winnerStatus === "conditional") {
2738
+ matrixAuthorityNonSelectionReasons.push(
2739
+ ...authorityDecision.winnerCaveats.slice(0, 3)
2740
+ );
2741
+ }
2742
+ if (authorityDecision.nonSelectionReasons.length > 0) {
2743
+ matrixAuthorityNonSelectionReasons.push(
2744
+ ...authorityDecision.nonSelectionReasons.slice(0, 3)
2745
+ );
2746
+ }
2747
+ }
2748
+ } catch (error) {
2749
+ matrixAuthorityWarnings.push(`Matrix authority evaluation failed: ${String(error)}`);
2750
+ }
2751
+ }
2752
+ const successCount = candidates.filter((c) => c.success).length;
2753
+ const persistedAiJudgeInvoked = tieBreakAiJudgeInvoked || aiJudgeInvoked;
2754
+ const persistedScoringMode = aiJudgeInvoked ? "ai-judge" : tieBreakAiJudgeInvoked ? "hybrid" : "deterministic";
2755
+ const persistedJudgeInvocationReason = aiJudgeError ? "error" : tieBreakAiJudgeInvoked || aiJudgeInvoked ? "multiple-successful-candidates" : successCount === 0 ? "no-successful-candidates" : successCount === 1 ? "single-successful-candidate" : "deterministic-shortcut";
2756
+ const judgeResultForEvidence = latestMainJudgeResult ?? latestTiebreakJudgeResult;
2757
+ const hasNewJudgeSchemaFields = config.judgeConfig?.judgeRun !== void 0 || config.judgeConfig?.matrixAuthority !== void 0 || matrixRan;
2758
+ const persistedMatrixAuthority = effectiveMatrixAuthority ?? (config.judgeConfig?.matrixAuthority !== void 0 ? resolveMatrixAuthorityPolicy(config.judgeConfig.matrixAuthority) : void 0);
2759
+ const { judgeRunRequested } = deriveAiJudgeInvocationArgs(config.judgeConfig);
2760
+ const multiJudgeEvidence = hasNewJudgeSchemaFields ? buildMultiJudgeEvidenceBlock({
2761
+ judgeResult: judgeResultForEvidence,
2762
+ judgeRunRequested,
2763
+ matrixAuthority: persistedMatrixAuthority,
2764
+ matrixRan,
2765
+ matrixProfileAgreement,
2766
+ matrixNonSelectionReasons: matrixAuthorityNonSelectionReasons
2767
+ }) : void 0;
2768
+ try {
2769
+ await artifactStore.save(stage.id, "candidates", "json", {
2770
+ taskId,
2771
+ variantCount: candidates.length,
2772
+ successCount: candidates.filter((c) => c.success).length,
2773
+ candidates: candidates.map((c) => ({
2774
+ provider: c.variant.provider,
2775
+ model: c.variant.model,
2776
+ strategy: c.variant.strategy,
2777
+ success: c.success,
2778
+ score: c.score,
2779
+ error: c.error,
2780
+ cost: c.cost,
2781
+ costUnavailableReason: c.costUnavailableReason
2782
+ })),
2783
+ winner: winnerInfo.winner ? {
2784
+ provider: winnerInfo.winner.variant.provider,
2785
+ model: winnerInfo.winner.variant.model,
2786
+ score: winnerInfo.winner.score
2787
+ } : null,
2788
+ rankings: winnerInfo.rankings,
2789
+ aiJudgeInvoked: persistedAiJudgeInvoked,
2790
+ scoringMode: persistedScoringMode,
2791
+ judgeInvocationReason: persistedJudgeInvocationReason,
2792
+ ...multiJudgeEvidence ? { multiJudgeEvidence } : {}
2793
+ });
2794
+ await artifactStore.save(
2795
+ stage.id,
2796
+ "bundle",
2797
+ "text",
2798
+ buildCompetitionBundle(taskId, candidates, basicResult)
2799
+ );
2800
+ if (winnerInfo.winner) {
2801
+ await artifactStore.save(stage.id, "winner", "json", {
2802
+ variant: winnerInfo.winner.variant,
2803
+ score: winnerInfo.winner.score,
2804
+ feedback: winnerInfo.winner.feedback,
2805
+ commitSha: winnerInfo.winner.commitSha,
2806
+ changedFiles: winnerInfo.winner.changedFiles
2807
+ });
2808
+ }
2809
+ const winnerResult = winnerInfo.winner ? matchVariantResult(winnerInfo.winner.variant, basicResult.variants) : void 0;
2810
+ const winnerDiff = typeof winnerResult?.worktreeDiff === "string" ? winnerResult.worktreeDiff : "";
2811
+ await artifactStore.save(stage.id, "winnerDiff", "diff", winnerDiff);
2812
+ let rationalePacket = basicResult.variants.find((v) => v.judgeEvaluation?.rationalePacket)?.judgeEvaluation?.rationalePacket;
2813
+ if (!rationalePacket) {
2814
+ rationalePacket = synthesizeDeterministicRationalePacket(candidates, winnerInfo, config);
2815
+ } else {
2816
+ const buildVariantId = (candidate) => {
2817
+ const parts = [candidate.variant.provider];
2818
+ if (candidate.variant.model) parts.push(candidate.variant.model);
2819
+ if (candidate.variant.strategy) parts.push(candidate.variant.strategy);
2820
+ return parts.join(":");
2821
+ };
2822
+ const finalWinnerId = winnerInfo.winner ? buildVariantId(winnerInfo.winner) : "none";
2823
+ const normalizedJudgeWinnerId = rationalePacket.winnerId ?? "none";
2824
+ if (normalizedJudgeWinnerId !== finalWinnerId) {
2825
+ rationalePacket = {
2826
+ ...rationalePacket,
2827
+ rawWinnerId: rationalePacket.winnerId ?? void 0,
2828
+ winnerId: finalWinnerId,
2829
+ winnerOverridden: true
2830
+ };
2831
+ }
2832
+ }
2833
+ await artifactStore.save(stage.id, "judgeRationale", "json", rationalePacket);
2834
+ for (const [index, candidate] of candidates.entries()) {
2835
+ const provider = candidate.variant.provider;
2836
+ const suffix = provider ? `${provider}-${index + 1}` : `${index + 1}`;
2837
+ const artifactName = `candidate-${suffix}`;
2838
+ const matchingResult = matchVariantResult(candidate.variant, basicResult.variants);
2839
+ await artifactStore.save(stage.id, artifactName, "json", {
2840
+ candidate,
2841
+ variantResult: matchingResult ? {
2842
+ provider: matchingResult.provider,
2843
+ model: matchingResult.model,
2844
+ strategy: matchingResult.strategy,
2845
+ success: matchingResult.success,
2846
+ completeness: matchingResult.completeness,
2847
+ judgeScore: matchingResult.judgeScore,
2848
+ worktreeDiff: matchingResult.worktreeDiff,
2849
+ worktreeSummary: matchingResult.worktreeSummary,
2850
+ retainedWorktreePath: matchingResult.retainedWorktreePath,
2851
+ logFilePath: matchingResult.logFilePath,
2852
+ logTail: matchingResult.logTail,
2853
+ costMetrics: matchingResult.costMetrics,
2854
+ error: matchingResult.error?.message
2855
+ } : null
2856
+ });
2857
+ candidate.resultArtifactPath = `${stage.id}.${artifactName}`;
2858
+ }
2859
+ } catch (error) {
2860
+ if (options.verbose) {
2861
+ console.warn(chalk.yellow(` Warning: Failed to persist competition artifacts: ${error}`));
2862
+ }
2863
+ }
2864
+ const coherenceMetrics = computeCoherenceMetrics(
2865
+ candidates,
2866
+ DEFAULT_COHERENCE_THRESHOLD,
2867
+ expectedAllowlist
2868
+ );
2869
+ const markedIncomparable = !coherenceMetrics.isCoherent;
2870
+ const warnings = [];
2871
+ if (markedIncomparable) {
2872
+ warnings.push(
2873
+ `Low coherence between successful candidates (avg ${coherenceMetrics.averageSimilarity.toFixed(2)} < ${coherenceMetrics.coherenceThreshold.toFixed(2)})`
2874
+ );
2875
+ }
2876
+ if (aiJudgeError) {
2877
+ warnings.push(`AI judge invocation failed: ${aiJudgeError}`);
2878
+ }
2879
+ if (winnerInfo.noWinnerDiagnostic) {
2880
+ warnings.push(winnerInfo.noWinnerDiagnostic);
2881
+ }
2882
+ warnings.push(...matrixAuthorityWarnings);
2883
+ if (winnerInfo.belowThresholdWinner) {
2884
+ warnings.push(
2885
+ `Winner selected below threshold (${winnerInfo.belowThresholdWinner.winnerScore} < ${winnerInfo.belowThresholdWinner.threshold})`
2886
+ );
2887
+ }
2888
+ const driftContext = computeCompetitionDrift(candidates, expectedAllowlist, effectiveMode);
2889
+ try {
2890
+ await artifactStore.save(stage.id, "stage-change", "json", {
2891
+ stageId: stage.id,
2892
+ stageType: "competition",
2893
+ mode: effectiveMode,
2894
+ deliveredFiles: driftContext.deliveredFiles,
2895
+ expectedFiles: driftContext.expectedFiles,
2896
+ violations: driftContext.violations,
2897
+ hasDrift: driftContext.hasDrift,
2898
+ candidateCount: candidates.length,
2899
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2900
+ });
2901
+ await artifactStore.save(stage.id, "stage-change-summary", "text", driftContext.summary);
2902
+ } catch (error) {
2903
+ if (options.verbose) {
2904
+ console.warn(chalk.yellow(` Warning: Failed to persist drift context: ${error}`));
2905
+ }
2906
+ }
2907
+ const effectiveWinnerInfo = winnerInfo;
2908
+ const winnerVerificationAllowsSuccess = effectiveWinnerInfo.winner ? verificationPolarityAllowsStageSuccess({
2909
+ verification: effectiveWinnerInfo.winner.verification,
2910
+ testStatus: effectiveWinnerInfo.winner.testStatus,
2911
+ rawTestStatus: effectiveWinnerInfo.winner.testStatus,
2912
+ exitCode: effectiveWinnerInfo.winner.testsExecuted?.exitCode
2913
+ }) : false;
2914
+ const validationPassed = successCount > 0 && effectiveWinnerInfo.winner !== null && winnerVerificationAllowsSuccess;
2915
+ let summary = buildCompetitionSummary(candidates, effectiveWinnerInfo, config);
2916
+ if (aiJudgeError && shouldInvokeAiJudge) {
2917
+ summary = `Competition failed: AI judge invocation failed: ${aiJudgeError}`;
2918
+ }
2919
+ if (markedIncomparable) {
2920
+ summary += ` (low coherence: ${coherenceMetrics.averageSimilarity.toFixed(2)})`;
2921
+ }
2922
+ const scoringMode = aiJudgeInvoked ? "ai-judge" : tieBreakAiJudgeInvoked ? "hybrid" : "deterministic";
2923
+ const judgeInvocationReason = aiJudgeError ? "error" : tieBreakAiJudgeInvoked || aiJudgeInvoked ? "multiple-successful-candidates" : successCount === 0 ? "no-successful-candidates" : successCount === 1 ? "single-successful-candidate" : "deterministic-shortcut";
2924
+ const winnerNeedsRepair = Boolean(
2925
+ effectiveWinnerInfo.winner?.verification && !effectiveWinnerInfo.winner.verification.passed
2926
+ );
2927
+ const stageVerification = effectiveWinnerInfo.winner?.verification;
2928
+ const result = {
2929
+ stageId: stage.id,
2930
+ stageType: "competition",
2931
+ competitionTaskId: taskId,
2932
+ validationPassed,
2933
+ validationScore: effectiveWinnerInfo.winner?.score,
2934
+ cost: totalCost,
2935
+ costUnavailableReason,
2936
+ warnings: warnings.length > 0 ? warnings : void 0,
2937
+ summary,
2938
+ durationMs: Date.now() - startTime,
2939
+ candidates,
2940
+ winner: effectiveWinnerInfo.winner,
2941
+ winnerApplied: false,
2942
+ // MVP: winner application happens in the workflow executor
2943
+ winnerNeedsRepair,
2944
+ verification: stageVerification,
2945
+ coherenceMetrics,
2946
+ markedIncomparable,
2947
+ scoringMode,
2948
+ competitionJudgeResult: {
2949
+ judgeType: config.judgeConfig?.type ?? "ai",
2950
+ aiJudgeAttempted,
2951
+ aiJudgeInvoked: tieBreakAiJudgeInvoked || aiJudgeInvoked,
2952
+ aiJudgeError,
2953
+ judgeInvocationReason,
2954
+ rankings: effectiveWinnerInfo.rankings,
2955
+ wasTie: effectiveWinnerInfo.wasTie,
2956
+ noWinnerReason: effectiveWinnerInfo.noWinnerReason,
2957
+ belowThresholdWinner: effectiveWinnerInfo.belowThresholdWinner,
2958
+ tieBreaker: effectiveWinnerInfo.tieBreaker,
2959
+ scoreCollisionReport: effectiveWinnerInfo.scoreCollisionReport
2960
+ },
2961
+ driftContext
2962
+ };
2963
+ if (options.verbose) {
2964
+ console.log(chalk.green(" ok Competition complete"));
2965
+ console.log(
2966
+ chalk.gray(
2967
+ ` Winner: ${effectiveWinnerInfo.winner ? formatCompetitionCandidateVariantDisplay(effectiveWinnerInfo.winner) : "none"}`
2968
+ )
2969
+ );
2970
+ console.log(
2971
+ chalk.gray(
2972
+ ` Total cost: ${costUnavailableReason !== void 0 ? "unavailable" : `$${totalCost.toFixed(4)}`}`
2973
+ )
2974
+ );
2975
+ console.log(
2976
+ chalk.gray(
2977
+ ` Coherence: ${coherenceMetrics.averageSimilarity.toFixed(2)} (${coherenceMetrics.isCoherent ? "coherent" : "INCOHERENT"})`
2978
+ )
2979
+ );
2980
+ if (driftContext.hasDrift) {
2981
+ console.log(
2982
+ chalk.yellow(
2983
+ ` Drift: ${driftContext.violations.length} file(s) outside allowlist (mode: ${effectiveMode})`
2984
+ )
2985
+ );
2986
+ }
2987
+ }
2988
+ const authoritativeWinner = effectiveWinnerInfo.winner ? basicResult.variants.find(
2989
+ (variant) => candidateMatchesVariantResult(effectiveWinnerInfo.winner, variant)
2990
+ ) : void 0;
2991
+ if (effectiveWinnerInfo.winner && !authoritativeWinner) {
2992
+ const errorMessage = "Final competition winner could not be resolved to an executed variant";
2993
+ await finalizeDeferredHandle(
2994
+ createEvaluationHandleFinalState({ outcome: "error", winner: null, errorMessage })
2995
+ );
2996
+ await cleanupSynthesisInputPatches(basicResult.variants, {
2997
+ expectedRoot: resolveSynthesisInputPatchDir(
2998
+ competitionOptions.executionContext.poeticDir,
2999
+ taskId
3000
+ )
3001
+ });
3002
+ throw new Error(errorMessage);
3003
+ }
3004
+ await finalizeDeferredHandle(
3005
+ authoritativeWinner ? createEvaluationHandleFinalState({
3006
+ outcome: "winner_selected",
3007
+ winner: toEvaluationHandleWinnerMetadata(authoritativeWinner)
3008
+ }) : createEvaluationHandleFinalState({
3009
+ outcome: successCount === 0 ? "all_failed" : "no_winner",
3010
+ winner: null
3011
+ })
3012
+ );
3013
+ await cleanupSynthesisInputPatches(basicResult.variants, {
3014
+ expectedRoot: resolveSynthesisInputPatchDir(
3015
+ competitionOptions.executionContext.poeticDir,
3016
+ taskId
3017
+ )
3018
+ });
3019
+ return result;
3020
+ } catch (error) {
3021
+ const errorMessage = error instanceof Error ? error.message : String(error);
3022
+ if (!deferredHandleFinalized) {
3023
+ await finalizeEvaluationHandleAsync(
3024
+ taskId,
3025
+ createEvaluationHandleFinalState({ outcome: "error", winner: null, errorMessage })
3026
+ ).catch(() => {
3027
+ });
3028
+ }
3029
+ await cleanupSynthesisInputPatches(basicResult.variants, {
3030
+ expectedRoot: resolveSynthesisInputPatchDir(
3031
+ competitionOptions.executionContext.poeticDir,
3032
+ taskId
3033
+ )
3034
+ }).catch(() => {
3035
+ });
3036
+ return {
3037
+ stageId: stage.id,
3038
+ stageType: "competition",
3039
+ validationPassed: false,
3040
+ cost: 0,
3041
+ candidates: [],
3042
+ winner: null,
3043
+ summary: `Competition post-processing failed: ${errorMessage}`,
3044
+ durationMs: Date.now() - startTime,
3045
+ competitionJudgeResult: {
3046
+ judgeType: config.judgeConfig?.type ?? "ai",
3047
+ aiJudgeAttempted: false,
3048
+ aiJudgeInvoked: false,
3049
+ aiJudgeError: errorMessage,
3050
+ judgeInvocationReason: "error",
3051
+ rankings: [],
3052
+ wasTie: false,
3053
+ noWinnerReason: "judge-error"
3054
+ }
3055
+ };
3056
+ }
3057
+ }
3058
+ function buildCompetitionSummary(candidates, winnerInfo, config) {
3059
+ const successCount = candidates.filter((c) => c.success).length;
3060
+ const failCount = candidates.length - successCount;
3061
+ let summary = `Competition: ${successCount}/${candidates.length} variants succeeded`;
3062
+ if (failCount > 0) {
3063
+ summary += ` (${failCount} failed)`;
3064
+ }
3065
+ if (winnerInfo.winner) {
3066
+ summary += `. Winner: ${formatCompetitionCandidateVariantDisplay(winnerInfo.winner)}`;
3067
+ if (winnerInfo.winner.score !== void 0) {
3068
+ summary += ` (score: ${winnerInfo.winner.score})`;
3069
+ }
3070
+ if (winnerInfo.belowThresholdWinner) {
3071
+ summary += ` (below threshold: ${winnerInfo.belowThresholdWinner.winnerScore} < ${winnerInfo.belowThresholdWinner.threshold})`;
3072
+ }
3073
+ } else if (winnerInfo.noWinnerReason) {
3074
+ const reasons = {
3075
+ "all-failed": "all variants failed",
3076
+ tie: "tie between top variants",
3077
+ "below-threshold": `all scores below threshold (${config.judgeConfig?.threshold ?? 0})`,
3078
+ "judge-error": "judge evaluation failed",
3079
+ incomparable: "candidates touched disjoint files (low coherence)"
3080
+ };
3081
+ summary += `. No winner: ${reasons[winnerInfo.noWinnerReason] ?? winnerInfo.noWinnerReason}`;
3082
+ }
3083
+ return summary;
3084
+ }
3085
+ function isCompetitionStage(stage) {
3086
+ return stage.type === "competition" && stage.competition !== void 0;
3087
+ }
3088
+
3089
+ export {
3090
+ verificationPolarityAllowsStageSuccess,
3091
+ computeCoherenceMetrics,
3092
+ __internalDetermineWinner,
3093
+ __internalRecordDeterministicTestSignalObservation,
3094
+ __internalExtractChangedFilesFromResult,
3095
+ __internalGetVariantTelemetryStatePath,
3096
+ __internalHydrateCandidateCostsFromTelemetry,
3097
+ __internalVariantResultToCandidate,
3098
+ __internalMatchVariantResult,
3099
+ __internalCandidateMatchesVariantResult,
3100
+ __internalResolveCompetitionCostAggregate,
3101
+ executeCompetitionStage,
3102
+ isCompetitionStage
3103
+ };
3104
+ //# sourceMappingURL=chunk-7DHRDWFS.js.map