@ebrindley/build 0.0.0-stage → 1.42.1-rc28

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 (878) hide show
  1. package/.build-project/providers/catalog.json +13951 -0
  2. package/.build-project/providers/pricing.json +1978 -0
  3. package/.build-project/providers/registry.json +4103 -0
  4. package/.github/SECURITY.md +75 -0
  5. package/.nvmrc +1 -0
  6. package/CHANGELOG.md +661 -0
  7. package/CODE_OF_CONDUCT.md +44 -0
  8. package/CONTRIBUTING.md +24 -0
  9. package/INSTALL.md +623 -0
  10. package/LICENSE +21 -0
  11. package/README.md +118 -2
  12. package/THIRD_PARTY_NOTICES.txt +26 -0
  13. package/dist/ai-judge-UE5UOYOO.js +191 -0
  14. package/dist/allowlist-grounding-KPLN6NC5.js +16 -0
  15. package/dist/allowlist-utils-MZZKKXRD.js +31 -0
  16. package/dist/apply-completion-mode-EM37UZHB.js +110 -0
  17. package/dist/artifact-migrator-WPACNSEP.js +276 -0
  18. package/dist/ask-2OZ4JFQR.js +176 -0
  19. package/dist/auth-6UKBTJUQ.js +185 -0
  20. package/dist/auth-H5KJL6HL.js +165 -0
  21. package/dist/auth-LVJRJDMU.js +12 -0
  22. package/dist/auth-NHZOCNRR.js +94 -0
  23. package/dist/auth-PBXHWXGW.js +95 -0
  24. package/dist/auth-T7Y5DCAH.js +91 -0
  25. package/dist/auth-TVVKCHQW.js +13 -0
  26. package/dist/auth-UHB2UCSS.js +97 -0
  27. package/dist/auth-VACA3VUL.js +98 -0
  28. package/dist/auth-VVLC77S3.js +44 -0
  29. package/dist/auth-liveness-XO4AGDDD.js +53 -0
  30. package/dist/autoloop-cleanup-SI3VGAAR.js +106 -0
  31. package/dist/autoloop-evidence-gates-J5GG5YQB.js +39 -0
  32. package/dist/autoloop-gate-policy-SUNAEP6Q.js +169 -0
  33. package/dist/autoloop-helpers-VQGQNTT6.js +52 -0
  34. package/dist/autoloop-ledger-P6TIDP7C.js +96 -0
  35. package/dist/autoloop-ledger-subscriber-HFAGOZXH.js +161 -0
  36. package/dist/autoloop-run-defaults-GWGZBNT7.js +27 -0
  37. package/dist/autoloop-run-lock-GBWRM5A2.js +197 -0
  38. package/dist/autoloop-success-C32QVWOP.js +93 -0
  39. package/dist/autoloop-termination-summary-GI6IBQWD.js +58 -0
  40. package/dist/autoloop-trajectory-AMKSQISD.js +70 -0
  41. package/dist/autoloop-wall-clock-T7ZVIQOC.js +12 -0
  42. package/dist/automatic-branch-cleanup-R62X2C5O.js +49 -0
  43. package/dist/autonomous-loop-controller-2WL363LW.js +4386 -0
  44. package/dist/backend-YUTFDZXZ.js +30 -0
  45. package/dist/background-executor-Z3ODTMD7.js +260 -0
  46. package/dist/backlog-75QPEAMW.js +403 -0
  47. package/dist/backlog-execution-intent-GWUV5TUK.js +19 -0
  48. package/dist/backup-active-store-XHWLN34M.js +16 -0
  49. package/dist/backup-machine-stores-UI4LTJOY.js +251 -0
  50. package/dist/backup-telemetry-db-Z4ICYCNW.js +26 -0
  51. package/dist/branch-archive-manager-FMSQ7YJF.js +18 -0
  52. package/dist/branch-cleanup-manager-ST6FJGND.js +35 -0
  53. package/dist/build-gate-7NKWPY62.js +68 -0
  54. package/dist/build-root-S7DINODY.js +18 -0
  55. package/dist/change-summary-R6CB6VXJ.js +50 -0
  56. package/dist/chunk-24MNKKOM.js +173 -0
  57. package/dist/chunk-2H6VZFIO.js +235 -0
  58. package/dist/chunk-2JIX3EKV.js +39 -0
  59. package/dist/chunk-2KO7HVZM.js +106 -0
  60. package/dist/chunk-2L36U25O.js +100 -0
  61. package/dist/chunk-2NMNFUQA.js +475 -0
  62. package/dist/chunk-2OUAEH67.js +83 -0
  63. package/dist/chunk-2VLJUXJU.js +115 -0
  64. package/dist/chunk-2VUEDIUM.js +77 -0
  65. package/dist/chunk-2Y2IIHPI.js +430 -0
  66. package/dist/chunk-2YRG3LHZ.js +220 -0
  67. package/dist/chunk-2Z5Q3SUY.js +65 -0
  68. package/dist/chunk-32IYXIE5.js +873 -0
  69. package/dist/chunk-33IGPPUI.js +292 -0
  70. package/dist/chunk-352PCJLK.js +283 -0
  71. package/dist/chunk-35J4NE6S.js +226 -0
  72. package/dist/chunk-3C7WBIVK.js +1016 -0
  73. package/dist/chunk-3H3EY6U7.js +1225 -0
  74. package/dist/chunk-3H4MWYIC.js +198 -0
  75. package/dist/chunk-3HHWQR3N.js +2479 -0
  76. package/dist/chunk-3JKNRYEE.js +14 -0
  77. package/dist/chunk-3LECCYZY.js +128 -0
  78. package/dist/chunk-3LOY6YZI.js +852 -0
  79. package/dist/chunk-3M57DADF.js +44 -0
  80. package/dist/chunk-3NOTLVLG.js +3803 -0
  81. package/dist/chunk-3OPP2OZB.js +1480 -0
  82. package/dist/chunk-3P5IN5E7.js +9 -0
  83. package/dist/chunk-3PL22IYZ.js +20 -0
  84. package/dist/chunk-3REDAJUJ.js +14 -0
  85. package/dist/chunk-3S2R4XJI.js +203 -0
  86. package/dist/chunk-3UBZI5DW.js +61 -0
  87. package/dist/chunk-3VV5OBGG.js +308 -0
  88. package/dist/chunk-3WY5TU2O.js +823 -0
  89. package/dist/chunk-43OKHTW4.js +82 -0
  90. package/dist/chunk-45KUJBDI.js +112 -0
  91. package/dist/chunk-47X5LM7B.js +224 -0
  92. package/dist/chunk-4B6FQJ77.js +268 -0
  93. package/dist/chunk-4BTDUT2S.js +42 -0
  94. package/dist/chunk-4DJL2VXA.js +24 -0
  95. package/dist/chunk-4EBSXZ73.js +48 -0
  96. package/dist/chunk-4QKP6I4C.js +294 -0
  97. package/dist/chunk-4U6XK2DG.js +300 -0
  98. package/dist/chunk-4UMRUFBD.js +132 -0
  99. package/dist/chunk-4US4SYJ4.js +569 -0
  100. package/dist/chunk-4ZPLWEZO.js +154 -0
  101. package/dist/chunk-56WPYDJH.js +624 -0
  102. package/dist/chunk-57WRCJJW.js +50 -0
  103. package/dist/chunk-5AW4RMNG.js +24 -0
  104. package/dist/chunk-5EQN56OZ.js +155 -0
  105. package/dist/chunk-5F43TUIN.js +38 -0
  106. package/dist/chunk-5FKHIKTS.js +115 -0
  107. package/dist/chunk-5HDP7XZG.js +91 -0
  108. package/dist/chunk-5KQETTNS.js +152 -0
  109. package/dist/chunk-5PDVN2KO.js +498 -0
  110. package/dist/chunk-5UBIFVRD.js +509 -0
  111. package/dist/chunk-5YDE3Q62.js +46 -0
  112. package/dist/chunk-626AJVMU.js +302 -0
  113. package/dist/chunk-633XZ7UF.js +3583 -0
  114. package/dist/chunk-63DHNHGA.js +236 -0
  115. package/dist/chunk-666656AR.js +568 -0
  116. package/dist/chunk-67YRJPJO.js +19 -0
  117. package/dist/chunk-6CAU7VBA.js +20 -0
  118. package/dist/chunk-6CB3KJRY.js +21 -0
  119. package/dist/chunk-6DBMALXL.js +29 -0
  120. package/dist/chunk-6E25C4IA.js +269 -0
  121. package/dist/chunk-6FIBNIQU.js +73 -0
  122. package/dist/chunk-6G57FYBV.js +189 -0
  123. package/dist/chunk-6KZKRTG3.js +4885 -0
  124. package/dist/chunk-6LAH2UV2.js +525 -0
  125. package/dist/chunk-6PZY2TTU.js +921 -0
  126. package/dist/chunk-6T6NHXK4.js +230 -0
  127. package/dist/chunk-6TBEX4R4.js +432 -0
  128. package/dist/chunk-6TRD7TEE.js +911 -0
  129. package/dist/chunk-6XCP2RAI.js +47 -0
  130. package/dist/chunk-726G6WDL.js +351 -0
  131. package/dist/chunk-75EMT7BF.js +616 -0
  132. package/dist/chunk-762ACDZJ.js +4696 -0
  133. package/dist/chunk-77I6G4CO.js +1 -0
  134. package/dist/chunk-7DJ6SQH3.js +510 -0
  135. package/dist/chunk-7HPCIOMA.js +1383 -0
  136. package/dist/chunk-7HYBSRPZ.js +17503 -0
  137. package/dist/chunk-7KBEOPVB.js +73 -0
  138. package/dist/chunk-7LHJDJB3.js +2222 -0
  139. package/dist/chunk-7NVJMH52.js +306 -0
  140. package/dist/chunk-7RMARDVH.js +33 -0
  141. package/dist/chunk-7SEWU4QG.js +36 -0
  142. package/dist/chunk-7TUTZTI2.js +911 -0
  143. package/dist/chunk-7VBDFPUM.js +340 -0
  144. package/dist/chunk-7VRJHTGZ.js +6406 -0
  145. package/dist/chunk-7YAOUUKK.js +493 -0
  146. package/dist/chunk-AAAODV76.js +860 -0
  147. package/dist/chunk-AB4HUJVQ.js +339 -0
  148. package/dist/chunk-AEQWV746.js +611 -0
  149. package/dist/chunk-AHU3FKPA.js +11639 -0
  150. package/dist/chunk-AISTV5XU.js +226 -0
  151. package/dist/chunk-AJBTKGJZ.js +48 -0
  152. package/dist/chunk-AJJNW7XT.js +248 -0
  153. package/dist/chunk-AJN5Y5YZ.js +160 -0
  154. package/dist/chunk-ALDTFNZ3.js +150 -0
  155. package/dist/chunk-ARARVIZK.js +281 -0
  156. package/dist/chunk-ATBM6AW5.js +53 -0
  157. package/dist/chunk-ATKEKM3E.js +206 -0
  158. package/dist/chunk-AUJLW6JZ.js +92 -0
  159. package/dist/chunk-AY3MHEFM.js +24 -0
  160. package/dist/chunk-B7PYTV72.js +236 -0
  161. package/dist/chunk-B7YRSULE.js +1423 -0
  162. package/dist/chunk-BAWJNMWF.js +339 -0
  163. package/dist/chunk-BBPIILO2.js +88 -0
  164. package/dist/chunk-BD3PGW6A.js +957 -0
  165. package/dist/chunk-BDPYFAB4.js +44 -0
  166. package/dist/chunk-BIUV23HH.js +729 -0
  167. package/dist/chunk-BQ3VAGXH.js +243 -0
  168. package/dist/chunk-BQJOGAWT.js +31 -0
  169. package/dist/chunk-BT7EG7CO.js +68 -0
  170. package/dist/chunk-BV3XQQLU.js +27 -0
  171. package/dist/chunk-BY6ODHNZ.js +78 -0
  172. package/dist/chunk-BZRLSZNV.js +79 -0
  173. package/dist/chunk-C3DH3NCY.js +2773 -0
  174. package/dist/chunk-C3KCMAJP.js +756 -0
  175. package/dist/chunk-C7AGUJ5K.js +267 -0
  176. package/dist/chunk-CBSWKQCX.js +342 -0
  177. package/dist/chunk-CE5OZBYY.js +21 -0
  178. package/dist/chunk-CFCVYHSW.js +373 -0
  179. package/dist/chunk-CHA2HDE5.js +126 -0
  180. package/dist/chunk-CIHWPGS5.js +146 -0
  181. package/dist/chunk-CJBSZX3F.js +127 -0
  182. package/dist/chunk-CLA6QIJM.js +43 -0
  183. package/dist/chunk-CPSVQR2I.js +365 -0
  184. package/dist/chunk-CRPRVNQ4.js +254 -0
  185. package/dist/chunk-CSIE4Y7C.js +1093 -0
  186. package/dist/chunk-CSOPSYDY.js +142 -0
  187. package/dist/chunk-CSXLLEGB.js +205 -0
  188. package/dist/chunk-CTDLERWU.js +293 -0
  189. package/dist/chunk-CULBXMSK.js +110 -0
  190. package/dist/chunk-D2M2Y5ID.js +21 -0
  191. package/dist/chunk-D37WY7SH.js +1060 -0
  192. package/dist/chunk-D4VJFCGZ.js +89 -0
  193. package/dist/chunk-D6WTZMZB.js +48 -0
  194. package/dist/chunk-DBHOWDUH.js +976 -0
  195. package/dist/chunk-DCACX7BV.js +19364 -0
  196. package/dist/chunk-DFHX4XYA.js +128 -0
  197. package/dist/chunk-DIKBRRKE.js +176 -0
  198. package/dist/chunk-DJG5RIOR.js +9 -0
  199. package/dist/chunk-DNIOIISW.js +616 -0
  200. package/dist/chunk-DOA5G7IA.js +315 -0
  201. package/dist/chunk-DP7FKP6W.js +855 -0
  202. package/dist/chunk-DS2JZ677.js +79 -0
  203. package/dist/chunk-DSRLVYBS.js +82 -0
  204. package/dist/chunk-EAEVKNJA.js +209 -0
  205. package/dist/chunk-EEUESN3T.js +575 -0
  206. package/dist/chunk-EJ4LUU5Y.js +73 -0
  207. package/dist/chunk-EJIWTPSZ.js +1063 -0
  208. package/dist/chunk-EJVCDTAN.js +116 -0
  209. package/dist/chunk-EKLUBDBQ.js +627 -0
  210. package/dist/chunk-EN62WLFD.js +849 -0
  211. package/dist/chunk-ENYRCL43.js +26 -0
  212. package/dist/chunk-EP22ZMFO.js +273 -0
  213. package/dist/chunk-EP4SVAVI.js +87 -0
  214. package/dist/chunk-EPAMVGI3.js +1562 -0
  215. package/dist/chunk-EPRMH6HO.js +24 -0
  216. package/dist/chunk-ES6NWJ36.js +4057 -0
  217. package/dist/chunk-ETA2K4KI.js +30 -0
  218. package/dist/chunk-ETAD4NKD.js +31 -0
  219. package/dist/chunk-EUWIIDQ7.js +93 -0
  220. package/dist/chunk-EVE3OD2W.js +141 -0
  221. package/dist/chunk-EXA26FFC.js +459 -0
  222. package/dist/chunk-EXSPAA35.js +244 -0
  223. package/dist/chunk-F55YABKV.js +258 -0
  224. package/dist/chunk-F5DNGU5W.js +27 -0
  225. package/dist/chunk-F622MJYV.js +103 -0
  226. package/dist/chunk-F6NIQD74.js +5111 -0
  227. package/dist/chunk-FAWJTC34.js +43 -0
  228. package/dist/chunk-FAZBRHGG.js +47 -0
  229. package/dist/chunk-FIEUSGNJ.js +39 -0
  230. package/dist/chunk-FKCG7K6H.js +1146 -0
  231. package/dist/chunk-FOVVXV45.js +229 -0
  232. package/dist/chunk-FRBPKBFE.js +30 -0
  233. package/dist/chunk-FSA5BPFI.js +268 -0
  234. package/dist/chunk-FSJ5TTZ3.js +29 -0
  235. package/dist/chunk-FT7SGLXT.js +193 -0
  236. package/dist/chunk-FUUVZZUB.js +62 -0
  237. package/dist/chunk-FYMRVUNZ.js +1697 -0
  238. package/dist/chunk-FYTAA5FG.js +162 -0
  239. package/dist/chunk-G3VB2UCZ.js +3892 -0
  240. package/dist/chunk-G6OIMVXH.js +405 -0
  241. package/dist/chunk-G7PQCXVH.js +228 -0
  242. package/dist/chunk-GAB6UW52.js +1087 -0
  243. package/dist/chunk-GAFJEYLK.js +29 -0
  244. package/dist/chunk-GC4CRMTS.js +642 -0
  245. package/dist/chunk-GFHSIWHL.js +5297 -0
  246. package/dist/chunk-GI5M67YA.js +735 -0
  247. package/dist/chunk-GIJWHUWF.js +191 -0
  248. package/dist/chunk-GO6DRECI.js +1 -0
  249. package/dist/chunk-GOFVBTMN.js +314 -0
  250. package/dist/chunk-GQIP72ZJ.js +13 -0
  251. package/dist/chunk-GQXLXRFA.js +28 -0
  252. package/dist/chunk-GT6HFKJB.js +48 -0
  253. package/dist/chunk-GVJGSSKM.js +174 -0
  254. package/dist/chunk-GWHGTG37.js +36 -0
  255. package/dist/chunk-GZAJHLKO.js +18 -0
  256. package/dist/chunk-GZK62I3N.js +314 -0
  257. package/dist/chunk-H3HGMISG.js +483 -0
  258. package/dist/chunk-H3ISZJMJ.js +403 -0
  259. package/dist/chunk-H4HXVWEC.js +9 -0
  260. package/dist/chunk-H6MJGKAW.js +120 -0
  261. package/dist/chunk-HBTTGVR5.js +353 -0
  262. package/dist/chunk-HBZ322WZ.js +35 -0
  263. package/dist/chunk-HEP3ILP4.js +34 -0
  264. package/dist/chunk-HGFXODKO.js +106 -0
  265. package/dist/chunk-HHWDTB6S.js +59 -0
  266. package/dist/chunk-HKO45NLZ.js +286 -0
  267. package/dist/chunk-HLVTEA6A.js +89 -0
  268. package/dist/chunk-HS3SY6HN.js +160 -0
  269. package/dist/chunk-HT5OCGKN.js +899 -0
  270. package/dist/chunk-HXIIEMGF.js +78 -0
  271. package/dist/chunk-I56TH7VM.js +46 -0
  272. package/dist/chunk-I6FN3R5D.js +352 -0
  273. package/dist/chunk-I7SCBHJN.js +655 -0
  274. package/dist/chunk-IJM4GKAT.js +529 -0
  275. package/dist/chunk-IMEYU36R.js +344 -0
  276. package/dist/chunk-INJ3SS6A.js +936 -0
  277. package/dist/chunk-IUKOPCCE.js +441 -0
  278. package/dist/chunk-IVEPZQJO.js +33 -0
  279. package/dist/chunk-IVZEONFC.js +43 -0
  280. package/dist/chunk-IWBHRSG7.js +936 -0
  281. package/dist/chunk-IYY3HQAD.js +484 -0
  282. package/dist/chunk-J2ICMYDA.js +48 -0
  283. package/dist/chunk-J2QCFLUN.js +505 -0
  284. package/dist/chunk-J5HM6V5P.js +1039 -0
  285. package/dist/chunk-J6NZX6QH.js +398 -0
  286. package/dist/chunk-JBBB2Y47.js +432 -0
  287. package/dist/chunk-JDCZQZU7.js +42 -0
  288. package/dist/chunk-JEDNXGSS.js +169 -0
  289. package/dist/chunk-JHP7OT6K.js +89 -0
  290. package/dist/chunk-JLS65NUQ.js +14 -0
  291. package/dist/chunk-JNMWYMC6.js +38 -0
  292. package/dist/chunk-JNSTWNNW.js +25 -0
  293. package/dist/chunk-JOSK6GEU.js +9564 -0
  294. package/dist/chunk-JQUMSIGC.js +100 -0
  295. package/dist/chunk-JVHGMURQ.js +1106 -0
  296. package/dist/chunk-JYXS47FQ.js +951 -0
  297. package/dist/chunk-K2ZMW2Z5.js +2147 -0
  298. package/dist/chunk-K7FAFORM.js +14 -0
  299. package/dist/chunk-KBJXX3ON.js +333 -0
  300. package/dist/chunk-KHFKVQWY.js +486 -0
  301. package/dist/chunk-KHMEI3DQ.js +173 -0
  302. package/dist/chunk-KHW3UD7B.js +69 -0
  303. package/dist/chunk-KKQKWAMF.js +365 -0
  304. package/dist/chunk-KOKXJV2U.js +455 -0
  305. package/dist/chunk-KQ4NGOJI.js +14 -0
  306. package/dist/chunk-KQYQOXMS.js +342 -0
  307. package/dist/chunk-KTMW65UX.js +14 -0
  308. package/dist/chunk-KUEWV2JH.js +593 -0
  309. package/dist/chunk-KXYDV3HP.js +1523 -0
  310. package/dist/chunk-KZ4JMGZ5.js +96 -0
  311. package/dist/chunk-KZWGBUIO.js +2659 -0
  312. package/dist/chunk-L2CBG5IX.js +1892 -0
  313. package/dist/chunk-L2S235CU.js +314 -0
  314. package/dist/chunk-L32WD57F.js +98 -0
  315. package/dist/chunk-LDJCKAJP.js +123 -0
  316. package/dist/chunk-LDWNBEN7.js +541 -0
  317. package/dist/chunk-LJVH57G2.js +241 -0
  318. package/dist/chunk-LPQ7NZEN.js +209 -0
  319. package/dist/chunk-LRGH3CCV.js +148 -0
  320. package/dist/chunk-LULOGMMM.js +1133 -0
  321. package/dist/chunk-LWGKN2GY.js +8284 -0
  322. package/dist/chunk-LX4F24ZH.js +157 -0
  323. package/dist/chunk-M4BUEXXF.js +839 -0
  324. package/dist/chunk-M6UHOC4I.js +553 -0
  325. package/dist/chunk-MCBNWZNO.js +657 -0
  326. package/dist/chunk-MEMSY6VY.js +223 -0
  327. package/dist/chunk-MHLEZQQI.js +145 -0
  328. package/dist/chunk-MJ6WNSIX.js +192 -0
  329. package/dist/chunk-MKASIKWZ.js +442 -0
  330. package/dist/chunk-MNOVBYFU.js +60 -0
  331. package/dist/chunk-MO2BYAAF.js +2896 -0
  332. package/dist/chunk-MP6P7Y2A.js +180 -0
  333. package/dist/chunk-MQ4TFJAG.js +3365 -0
  334. package/dist/chunk-MT2WAIR3.js +131 -0
  335. package/dist/chunk-MTU7VTNN.js +1122 -0
  336. package/dist/chunk-MULMXX4V.js +150 -0
  337. package/dist/chunk-MW2DWWVA.js +147 -0
  338. package/dist/chunk-MY3ZPUN4.js +151 -0
  339. package/dist/chunk-MYLH2S4G.js +64 -0
  340. package/dist/chunk-MZ5WYKNA.js +28 -0
  341. package/dist/chunk-N3Q2JNPV.js +249 -0
  342. package/dist/chunk-N5DX4JAK.js +12 -0
  343. package/dist/chunk-NAINGKHF.js +35 -0
  344. package/dist/chunk-NEQUQHOX.js +223 -0
  345. package/dist/chunk-NHNPEZS4.js +1408 -0
  346. package/dist/chunk-NHTIXJCR.js +17 -0
  347. package/dist/chunk-NKLPMBNV.js +1154 -0
  348. package/dist/chunk-NMVZ5YES.js +199 -0
  349. package/dist/chunk-NRFRY3GE.js +256 -0
  350. package/dist/chunk-NTD6CSI6.js +1266 -0
  351. package/dist/chunk-NUO7B3SH.js +318 -0
  352. package/dist/chunk-NVOHIJKG.js +1319 -0
  353. package/dist/chunk-NXH3RX7O.js +523 -0
  354. package/dist/chunk-NXZ3DURF.js +257 -0
  355. package/dist/chunk-O26L6F7F.js +209 -0
  356. package/dist/chunk-O5RRIUEP.js +124 -0
  357. package/dist/chunk-O5X6BKAO.js +10 -0
  358. package/dist/chunk-O6ZQUVTR.js +31 -0
  359. package/dist/chunk-O7FE75QZ.js +306 -0
  360. package/dist/chunk-OC7Z6AJQ.js +81 -0
  361. package/dist/chunk-OH7IEZ63.js +307 -0
  362. package/dist/chunk-OI734GRS.js +115 -0
  363. package/dist/chunk-OJBH62DK.js +684 -0
  364. package/dist/chunk-OKJLVSTJ.js +247 -0
  365. package/dist/chunk-OMX5VL43.js +79 -0
  366. package/dist/chunk-ONHAMBN6.js +12 -0
  367. package/dist/chunk-ONYPLIVE.js +753 -0
  368. package/dist/chunk-OSK7QWPD.js +637 -0
  369. package/dist/chunk-OTXLMJKP.js +438 -0
  370. package/dist/chunk-OV5PKQMA.js +213 -0
  371. package/dist/chunk-OXK5HA4B.js +31 -0
  372. package/dist/chunk-OYDWFQA4.js +272 -0
  373. package/dist/chunk-OZAUKWHB.js +22 -0
  374. package/dist/chunk-P5P2EKGH.js +94 -0
  375. package/dist/chunk-P6SSWAKY.js +29 -0
  376. package/dist/chunk-P7CQGPLS.js +30 -0
  377. package/dist/chunk-P7RVCHQV.js +197 -0
  378. package/dist/chunk-PEBWDYIW.js +726 -0
  379. package/dist/chunk-PFCXFO7A.js +9193 -0
  380. package/dist/chunk-PFLDWMX6.js +168 -0
  381. package/dist/chunk-PHZGLQSK.js +15883 -0
  382. package/dist/chunk-PNFTPNSR.js +20 -0
  383. package/dist/chunk-PPHXX4W7.js +175 -0
  384. package/dist/chunk-PPZESPJT.js +262 -0
  385. package/dist/chunk-PRDHI2L5.js +296 -0
  386. package/dist/chunk-PSTKWHHN.js +32 -0
  387. package/dist/chunk-PV53ODOT.js +555 -0
  388. package/dist/chunk-PVJBTI7P.js +24 -0
  389. package/dist/chunk-PXKERBKX.js +100 -0
  390. package/dist/chunk-PZ5AY32C.js +10 -0
  391. package/dist/chunk-Q3DHEZA5.js +85 -0
  392. package/dist/chunk-Q5RZDVQK.js +204 -0
  393. package/dist/chunk-Q64IR2Z2.js +4933 -0
  394. package/dist/chunk-Q6Z5UGPL.js +398 -0
  395. package/dist/chunk-QAMAV4DT.js +627 -0
  396. package/dist/chunk-QBWF4444.js +112 -0
  397. package/dist/chunk-QDKYT4CI.js +22805 -0
  398. package/dist/chunk-QFLBRWCJ.js +126 -0
  399. package/dist/chunk-QILAQACE.js +107 -0
  400. package/dist/chunk-QJ6OEH4K.js +3683 -0
  401. package/dist/chunk-QK3NLYTV.js +320 -0
  402. package/dist/chunk-QOFLUS24.js +535 -0
  403. package/dist/chunk-QOIASNEJ.js +98 -0
  404. package/dist/chunk-QP4UTSOV.js +3587 -0
  405. package/dist/chunk-QP5ST7RI.js +904 -0
  406. package/dist/chunk-QS5AGRZN.js +167 -0
  407. package/dist/chunk-QTAOU53N.js +107 -0
  408. package/dist/chunk-QTCLJHLZ.js +351 -0
  409. package/dist/chunk-QTOLTG4L.js +119 -0
  410. package/dist/chunk-QWDV4OSL.js +142 -0
  411. package/dist/chunk-QWMQ74KD.js +508 -0
  412. package/dist/chunk-QX6LOMMH.js +158 -0
  413. package/dist/chunk-QXBKIHY7.js +238 -0
  414. package/dist/chunk-QXBKTJT6.js +270 -0
  415. package/dist/chunk-QYQOVOLR.js +196 -0
  416. package/dist/chunk-R2CKS6WT.js +73 -0
  417. package/dist/chunk-R2TIYG7U.js +68 -0
  418. package/dist/chunk-R2W3LESH.js +465 -0
  419. package/dist/chunk-R5EXHMUN.js +100 -0
  420. package/dist/chunk-RBBTBCHX.js +289 -0
  421. package/dist/chunk-RBKLOUXA.js +121 -0
  422. package/dist/chunk-RCP2Y6DQ.js +86 -0
  423. package/dist/chunk-RCYEJSD5.js +260 -0
  424. package/dist/chunk-RFDVSI4N.js +134 -0
  425. package/dist/chunk-RGJU63FV.js +1717 -0
  426. package/dist/chunk-RI4EX2QE.js +18 -0
  427. package/dist/chunk-RIMARPCF.js +152 -0
  428. package/dist/chunk-RJ6RSNT6.js +42 -0
  429. package/dist/chunk-RNI2GUIF.js +131 -0
  430. package/dist/chunk-RPHUWJ3K.js +264 -0
  431. package/dist/chunk-RPIMAMV7.js +361 -0
  432. package/dist/chunk-RQFX6YRN.js +49 -0
  433. package/dist/chunk-RRC5BL7B.js +285 -0
  434. package/dist/chunk-RSYTSBOO.js +79 -0
  435. package/dist/chunk-RWQQIKIC.js +35 -0
  436. package/dist/chunk-RZUBOZH2.js +373 -0
  437. package/dist/chunk-S2E632FQ.js +380 -0
  438. package/dist/chunk-S2VQCZO4.js +22 -0
  439. package/dist/chunk-S2XIMQJQ.js +681 -0
  440. package/dist/chunk-S47ISY27.js +183 -0
  441. package/dist/chunk-S6I4KISU.js +142 -0
  442. package/dist/chunk-S6TAFQI5.js +2403 -0
  443. package/dist/chunk-SBBNT5ZJ.js +27 -0
  444. package/dist/chunk-SDJV2DTQ.js +491 -0
  445. package/dist/chunk-SDPIFNLD.js +33 -0
  446. package/dist/chunk-SF6YK3JI.js +835 -0
  447. package/dist/chunk-SK3ZFONO.js +976 -0
  448. package/dist/chunk-SKTFRFQ7.js +1775 -0
  449. package/dist/chunk-SNGM452K.js +2002 -0
  450. package/dist/chunk-STW7OFOA.js +581 -0
  451. package/dist/chunk-SU6UFUQY.js +1351 -0
  452. package/dist/chunk-SVJM3LJA.js +27 -0
  453. package/dist/chunk-SVUNZOPG.js +129 -0
  454. package/dist/chunk-T5XLUYV3.js +34 -0
  455. package/dist/chunk-T7E5JS6N.js +57 -0
  456. package/dist/chunk-TA3N5MMO.js +450 -0
  457. package/dist/chunk-TAJPCXSB.js +13 -0
  458. package/dist/chunk-TDEMDRN2.js +1639 -0
  459. package/dist/chunk-TDSEX5CF.js +24 -0
  460. package/dist/chunk-TGCVL74Y.js +28 -0
  461. package/dist/chunk-TGXXYDL4.js +1012 -0
  462. package/dist/chunk-TIKTYUJO.js +296 -0
  463. package/dist/chunk-TIZAJD4M.js +6029 -0
  464. package/dist/chunk-TLSEZZCG.js +5549 -0
  465. package/dist/chunk-TMBDRHAX.js +19 -0
  466. package/dist/chunk-TRURQUBP.js +1217 -0
  467. package/dist/chunk-TSQ256N5.js +152 -0
  468. package/dist/chunk-TUQMMFEQ.js +2244 -0
  469. package/dist/chunk-U424MJLC.js +81 -0
  470. package/dist/chunk-U4DRS6ZW.js +11 -0
  471. package/dist/chunk-U5KS22IN.js +204 -0
  472. package/dist/chunk-UAPHFJPN.js +673 -0
  473. package/dist/chunk-UB7LQITD.js +1040 -0
  474. package/dist/chunk-UBVRHGAZ.js +237 -0
  475. package/dist/chunk-UDNNAQN5.js +98 -0
  476. package/dist/chunk-UJP3XM54.js +342 -0
  477. package/dist/chunk-UJYDH2MW.js +305 -0
  478. package/dist/chunk-UKMPASIC.js +399 -0
  479. package/dist/chunk-UKUL3EHK.js +763 -0
  480. package/dist/chunk-UPHU64NB.js +1327 -0
  481. package/dist/chunk-URMSZXAD.js +43 -0
  482. package/dist/chunk-US3RT6CY.js +525 -0
  483. package/dist/chunk-UTDEOPKV.js +30 -0
  484. package/dist/chunk-UUUDKV7N.js +13 -0
  485. package/dist/chunk-UVKWU3SM.js +39 -0
  486. package/dist/chunk-V2TVPO3X.js +521 -0
  487. package/dist/chunk-V3KLVK7B.js +398 -0
  488. package/dist/chunk-V3YFFHDR.js +17 -0
  489. package/dist/chunk-VAG6GUBR.js +1162 -0
  490. package/dist/chunk-VBENAHDA.js +1814 -0
  491. package/dist/chunk-VBNCKCCI.js +16 -0
  492. package/dist/chunk-VCGSWN5M.js +1300 -0
  493. package/dist/chunk-VE2O2I7M.js +115 -0
  494. package/dist/chunk-VIFHYTI5.js +31 -0
  495. package/dist/chunk-VJER3FUS.js +5080 -0
  496. package/dist/chunk-VLMDM56Q.js +268 -0
  497. package/dist/chunk-VMFZEVVX.js +99 -0
  498. package/dist/chunk-VNDPQVUZ.js +1853 -0
  499. package/dist/chunk-VSPJRLGA.js +4783 -0
  500. package/dist/chunk-VSWC5ZXI.js +103 -0
  501. package/dist/chunk-VYI4DSZP.js +2017 -0
  502. package/dist/chunk-W4BAIQ6L.js +1212 -0
  503. package/dist/chunk-W7VQAL2K.js +2203 -0
  504. package/dist/chunk-WEI3ZDZH.js +33 -0
  505. package/dist/chunk-WEIUS5NT.js +26 -0
  506. package/dist/chunk-WEW7UFWE.js +546 -0
  507. package/dist/chunk-WGQAXLNA.js +384 -0
  508. package/dist/chunk-WJAL4JL3.js +206 -0
  509. package/dist/chunk-WKFOJ5ZG.js +141 -0
  510. package/dist/chunk-WMWQEFLN.js +2177 -0
  511. package/dist/chunk-WNECKKO2.js +154 -0
  512. package/dist/chunk-WPKLYOAM.js +195 -0
  513. package/dist/chunk-WSH37YQN.js +243 -0
  514. package/dist/chunk-WV3KQDPE.js +84 -0
  515. package/dist/chunk-WZFC4V4U.js +389 -0
  516. package/dist/chunk-XCOIBNET.js +13 -0
  517. package/dist/chunk-XDM65LBX.js +53 -0
  518. package/dist/chunk-XGU6PBO5.js +645 -0
  519. package/dist/chunk-XHOI4V62.js +43 -0
  520. package/dist/chunk-XIBVFMLQ.js +6858 -0
  521. package/dist/chunk-XJ2E7YEJ.js +117 -0
  522. package/dist/chunk-XON4ZCYX.js +69 -0
  523. package/dist/chunk-XQPEWJPI.js +127 -0
  524. package/dist/chunk-XSJTIFUY.js +31 -0
  525. package/dist/chunk-XT7OVWM3.js +64 -0
  526. package/dist/chunk-XTXYIISX.js +1104 -0
  527. package/dist/chunk-XV7NZL4B.js +57 -0
  528. package/dist/chunk-XWIZ6B5S.js +109 -0
  529. package/dist/chunk-XWLIKOBX.js +240 -0
  530. package/dist/chunk-XZOXEIN4.js +156 -0
  531. package/dist/chunk-XZRS7I7W.js +3673 -0
  532. package/dist/chunk-Y4ZDDHB6.js +44 -0
  533. package/dist/chunk-Y733RB7T.js +194 -0
  534. package/dist/chunk-YBHUB4XR.js +14931 -0
  535. package/dist/chunk-YKC75XK4.js +147 -0
  536. package/dist/chunk-YKMXFVK7.js +27 -0
  537. package/dist/chunk-YO5BAJ55.js +225 -0
  538. package/dist/chunk-YPDCLXNZ.js +568 -0
  539. package/dist/chunk-YSQPGVFK.js +116 -0
  540. package/dist/chunk-YTVVTIWJ.js +716 -0
  541. package/dist/chunk-YVCMDVBB.js +698 -0
  542. package/dist/chunk-YYTOA6DP.js +114 -0
  543. package/dist/chunk-Z5WGNULV.js +88 -0
  544. package/dist/chunk-Z6NGVVXG.js +66 -0
  545. package/dist/chunk-Z7CDQNH3.js +20 -0
  546. package/dist/chunk-ZH4G3FU5.js +187 -0
  547. package/dist/chunk-ZJB6SQPA.js +257 -0
  548. package/dist/chunk-ZL6E4HMY.js +42 -0
  549. package/dist/chunk-ZMLOC3DW.js +62 -0
  550. package/dist/chunk-ZORW64QH.js +101 -0
  551. package/dist/chunk-ZVVD2XGV.js +1369 -0
  552. package/dist/cli-utils-ER33ODC5.js +31 -0
  553. package/dist/cli-validation-6CHPTANV.js +146 -0
  554. package/dist/commit-utils-3STAY7C7.js +49 -0
  555. package/dist/compatibility-notice-IHNXR2JR.js +21 -0
  556. package/dist/compete-config-resolver-V3GDNJMM.js +125 -0
  557. package/dist/compete-results-XUM3PJHS.js +318 -0
  558. package/dist/competition-outcome-tracker-NWSMVUPG.js +62 -0
  559. package/dist/config-4HHE4OIK.js +238 -0
  560. package/dist/config-D6YAZASH.js +10 -0
  561. package/dist/config-MIPRDYYV.js +46 -0
  562. package/dist/config-audit-GA5DCUAI.js +371 -0
  563. package/dist/config-explain-4LMO556H.js +71 -0
  564. package/dist/config-loader-RGP634PC.js +51 -0
  565. package/dist/config-manager-J2UTO635.js +114 -0
  566. package/dist/config-merger-TVUJBZTS.js +14 -0
  567. package/dist/config-validator-H4ZVIE56.js +122 -0
  568. package/dist/cost-HSIV5U2Y.js +85 -0
  569. package/dist/data-migration-state-OAUL2WPQ.js +35 -0
  570. package/dist/db-migrator-NUOW5NKR.js +34 -0
  571. package/dist/default-paths-UILB62BN.js +49 -0
  572. package/dist/discovery-V6GYUJUC.js +53 -0
  573. package/dist/doctor-BBSMCDWE.js +271 -0
  574. package/dist/doctor-context-blocks-LPY75VZA.js +231 -0
  575. package/dist/doctor-instructions-import-JXHDDOE5.js +70 -0
  576. package/dist/doctor-purpose-6YJOXPBE.js +30 -0
  577. package/dist/domain-analyzer-S35ABUNA.js +48 -0
  578. package/dist/ensure-initialized-Q6PEU55O.js +78 -0
  579. package/dist/entry.js +922 -0
  580. package/dist/error-parser-core-MZFMFANN.js +70 -0
  581. package/dist/evaluation-context-GQBYDAEV.js +63 -0
  582. package/dist/evidence-plan-resolver-5FUAP3SA.js +111 -0
  583. package/dist/execution-data-writer-YCG5UH37.js +72 -0
  584. package/dist/execution-policy-applier-PWZM5LNA.js +63 -0
  585. package/dist/execution-preflight-DASJWWQF.js +223 -0
  586. package/dist/execution-roles-KNSNNB2D.js +112 -0
  587. package/dist/exit-code-error-QIY5DOKF.js +18 -0
  588. package/dist/external-temp-cleanup-CAW7LQ6R.js +360 -0
  589. package/dist/factory-YCYCB7AE.js +209 -0
  590. package/dist/file-utils-ZQYNBQBW.js +45 -0
  591. package/dist/flywheel-allowlist-revert-H22HA6JE.js +21 -0
  592. package/dist/flywheel-autoloop-executor-PDOASJEZ.js +316 -0
  593. package/dist/flywheel-autoloop-unverified-TOKYFCDC.js +36 -0
  594. package/dist/flywheel-competition-executor-YJUMMEJO.js +320 -0
  595. package/dist/flywheel-executor-JWU43KAY.js +437 -0
  596. package/dist/flywheel-git-isolation-FQ2TRWMB.js +56 -0
  597. package/dist/flywheel-manifest-HDPNMWWF.js +114 -0
  598. package/dist/flywheel-model-defaults-UHAKTZT3.js +110 -0
  599. package/dist/flywheel-preflight-III2C7TH.js +163 -0
  600. package/dist/flywheel-resume-2O45MS7Y.js +31 -0
  601. package/dist/flywheel-resume-execution-lease-P2BK257J.js +59 -0
  602. package/dist/flywheel-safety-AVAVFXIJ.js +19 -0
  603. package/dist/flywheel-scope-decision-ALJUUNGG.js +14 -0
  604. package/dist/get-telemetry-logger-MPDVO2JA.js +155 -0
  605. package/dist/git-message-style-KCXGMTDT.js +104 -0
  606. package/dist/guidance-profile-config-G3K5YQOO.js +113 -0
  607. package/dist/guidance-profile-renderer-TX4TNDFL.js +23 -0
  608. package/dist/identity-XLQJ4YJF.js +25 -0
  609. package/dist/index-query-6NUY4FKX.js +37 -0
  610. package/dist/index.js +85588 -0
  611. package/dist/indexer-DL54CM3K.js +44 -0
  612. package/dist/init-OUZ72344.js +245 -0
  613. package/dist/instructions-import-offer-NSYXSITC.js +363 -0
  614. package/dist/instructions-run-NBII7W36.js +114 -0
  615. package/dist/interrupted-work-E4TLKJLE.js +43 -0
  616. package/dist/invoke-provider-auth-NEWEIHCI.js +38 -0
  617. package/dist/judge-scoring.json +64 -0
  618. package/dist/lab-mode-YXQ2Y3NG.js +44 -0
  619. package/dist/lab-utils-5QAMDJR5.js +29 -0
  620. package/dist/linux-host-class-YDWQX65O.js +31 -0
  621. package/dist/llm-judge-executor-OJSNCTFJ.js +179 -0
  622. package/dist/local-ci-config-VZ4WWDT5.js +48 -0
  623. package/dist/local-executor-DCMDDRX2.js +280 -0
  624. package/dist/logger-5KNKS3O4.js +154 -0
  625. package/dist/matrix-prompt-builder-4ZBOGZSB.js +527 -0
  626. package/dist/matrix-result-parser-EZJM4YXP.js +14 -0
  627. package/dist/merge-batch-RTEEMVDB.js +313 -0
  628. package/dist/merge-batch-members-VIWGVRHP.js +24 -0
  629. package/dist/merge-queue-TIIUSOY6.js +126 -0
  630. package/dist/merge-queue-trust-DUNZ4J65.js +21 -0
  631. package/dist/metadata-UKSMWM6J.js +29 -0
  632. package/dist/model-catalog-readiness-R5KJBP5M.js +202 -0
  633. package/dist/model-invocations-db-XTUPPQ34.js +70 -0
  634. package/dist/model-resolver-JFZ2MHOJ.js +39 -0
  635. package/dist/model-resolver-SCQ57KAQ.js +217 -0
  636. package/dist/model-roles-D3OR4NAH.js +110 -0
  637. package/dist/monitor-F4SIU5G2.js +96 -0
  638. package/dist/nested-worktrees-2WUWQ75N.js +23 -0
  639. package/dist/next-S3IRLVER.js +96 -0
  640. package/dist/next-UKPFRXOO.js +148 -0
  641. package/dist/opportunistic-TL4S26VX.js +86 -0
  642. package/dist/optimization-config-resolver-NAEIYU6A.js +148 -0
  643. package/dist/package-HJR4QJT4.js +10 -0
  644. package/dist/parse-git-status-7PIYFPS2.js +21 -0
  645. package/dist/path-security-5WJSY56G.js +41 -0
  646. package/dist/paths-JUI7C4KU.js +45 -0
  647. package/dist/plan-backlog-list-fast-SSTQL5XP.js +89 -0
  648. package/dist/plan-backlog-show-fast-PFRAQ3JB.js +114 -0
  649. package/dist/plan-sprint-list-fast-HD2KBZSY.js +110 -0
  650. package/dist/plan-sprint-status-fast-YFYH7WQF.js +116 -0
  651. package/dist/plan-task-status-fast-JU5PNLUU.js +114 -0
  652. package/dist/plan-to-flywheel-PY5MSY2H.js +529 -0
  653. package/dist/preflight-PJHGTJNZ.js +12 -0
  654. package/dist/process-registry-B4ZUCN7T.js +28 -0
  655. package/dist/process-scanner-TU3QHWVB.js +23 -0
  656. package/dist/processes-6FHVGT72.js +28 -0
  657. package/dist/processes-json-fast-YWTMUWXB.js +72 -0
  658. package/dist/profile-HWTC56SG.js +209 -0
  659. package/dist/project-runtime-paths-2UQNG5Y4.js +41 -0
  660. package/dist/protected-branches-N36LDBFY.js +71 -0
  661. package/dist/provider-aware-resource-manager-YTFAHNGJ.js +40 -0
  662. package/dist/provider-matrix-2KO2V5OM.js +214 -0
  663. package/dist/provider-matrix-renderer-MEC3PER7.js +139 -0
  664. package/dist/provider-output-forwarding-2AHL7YMA.js +26 -0
  665. package/dist/provider-registry-WCZ65QHC.js +136 -0
  666. package/dist/provider-temp-cleanup-IUNPJCZF.js +14 -0
  667. package/dist/prune-engine-EOQVWEP6.js +448 -0
  668. package/dist/publication-turn-S42RZTQF.js +44 -0
  669. package/dist/quality-gate-JQMVCKOO.js +72 -0
  670. package/dist/quickstart-3O6FRCFB.js +105 -0
  671. package/dist/readiness-GW6ABRHB.js +139 -0
  672. package/dist/readiness-KFZCXDTT.js +215 -0
  673. package/dist/registry-7XG376SY.js +217 -0
  674. package/dist/repair-helpers-TTV5FEF4.js +117 -0
  675. package/dist/repo-root-YG6MQZDW.js +28 -0
  676. package/dist/resolution-engine-FFEK7HQ2.js +187 -0
  677. package/dist/resolve-provider-cli-ZEXVZKET.js +44 -0
  678. package/dist/restore-telemetry-db-E7BR5PO7.js +459 -0
  679. package/dist/routing-events-AW6SRZ6G.js +13 -0
  680. package/dist/routing-history-store-FMDDQL6W.js +39 -0
  681. package/dist/routing-planner-C6OHO3EY.js +221 -0
  682. package/dist/runner-KHDNQ5KU.js +1194 -0
  683. package/dist/runner-PIS2BW7Y.js +1801 -0
  684. package/dist/safety-E3JJVSFL.js +67 -0
  685. package/dist/safety-stanza-HE6GXP4G.js +49 -0
  686. package/dist/sandbox-7LBZC5PE.js +72 -0
  687. package/dist/sandbox-ASWCDYZL.js +80 -0
  688. package/dist/schema-extensions.sql +234 -0
  689. package/dist/security-JI22TBEB.js +17 -0
  690. package/dist/setup-bb-plugin-FQXLA76Y.js +531 -0
  691. package/dist/setup-claude-code-NF4ZSHVE.js +197 -0
  692. package/dist/setup-temp-cleanup-2APZ4HMA.js +29 -0
  693. package/dist/shared-utils-34HJZ6JX.js +40 -0
  694. package/dist/simple-artifact-goal-MQLDDMMX.js +29 -0
  695. package/dist/sprint-N7JFTEGL.js +403 -0
  696. package/dist/sprint-bridge-KJXIBNRJ.js +117 -0
  697. package/dist/sprint-completion-dependents-34SR7JVL.js +43 -0
  698. package/dist/sprint-execution-service-A6JPUBWY.js +376 -0
  699. package/dist/sprint-manager-MU2ZUWN2.js +140 -0
  700. package/dist/sqlite-timeout-config-U2CT4LKU.js +13 -0
  701. package/dist/sqlite-wrapper-FSGJ2QEW.js +19 -0
  702. package/dist/stale-cleanup-orchestrator-4X6324VF.js +71 -0
  703. package/dist/storage-access-I3V5LER7.js +31 -0
  704. package/dist/store-XVG64ZR2.js +25 -0
  705. package/dist/task-classifier-MN2DYE5R.js +558 -0
  706. package/dist/task-list-fast-7AT6LTTA.js +112 -0
  707. package/dist/task-manager-LHPBBRRE.js +136 -0
  708. package/dist/task-report-OLPAWBTK.js +64 -0
  709. package/dist/task-type-detector-6RG3YNZF.js +27 -0
  710. package/dist/task-type-resolver-EQHOUIHT.js +64 -0
  711. package/dist/telemetry-5VYSK772.js +212 -0
  712. package/dist/telemetry-health-tracker-4GFW2EMP.js +12 -0
  713. package/dist/telemetry-path-resolver-H3NFHHQY.js +34 -0
  714. package/dist/telemetry-reliability-URJDTNPZ.js +76 -0
  715. package/dist/transports-NREZQTJK.js +106 -0
  716. package/dist/unified-cost-tracker-5MTBJ2CL.js +59 -0
  717. package/dist/unified-state-cleanup-GGAXLHXF.js +292 -0
  718. package/dist/universal-cost-calculator-JTFEJVWK.js +70 -0
  719. package/dist/user-agents-QLIGPLP2.js +30 -0
  720. package/dist/variant-execution-I4ZZUAWY.js +319 -0
  721. package/dist/variant-opt-parser-JHCXKY2K.js +251 -0
  722. package/dist/variant-request-input-PL37N3AN.js +11 -0
  723. package/dist/variant-state-cleanup-KHMXRBZN.js +287 -0
  724. package/dist/variant-worker-COB5YTJX.js +4517 -0
  725. package/dist/variant-worker.js +26 -0
  726. package/dist/variants-XGDSXYG3.js +267 -0
  727. package/dist/verification-command-YSPU4VBH.js +66 -0
  728. package/dist/verify-command-timeout-DQUYH33Z.js +11 -0
  729. package/dist/verify-commands-LOHMOFKC.js +65 -0
  730. package/dist/warning-JSKSFKBT.js +13 -0
  731. package/dist/work-edge-K65NHVWY.js +50 -0
  732. package/dist/work-item-writer-KY5ZWZWW.js +30 -0
  733. package/dist/worker-JNXXEIT6.js +1504 -0
  734. package/dist/worker.js +21 -0
  735. package/dist/workspace-tree-identity-JO5PSKTW.js +52 -0
  736. package/dist/worktree-environment-WTVABAQW.js +64 -0
  737. package/dist/worktree-metrics-VZRQI26T.js +66 -0
  738. package/dist/writeback-TQFQBJNU.js +50 -0
  739. package/docs/CLI_REFERENCE.md +8287 -0
  740. package/docs/PROVIDER_SETUP.md +1737 -0
  741. package/docs/README.md +96 -0
  742. package/docs/TROUBLESHOOTING.md +2209 -0
  743. package/docs/getting-started/QUICK_START.md +260 -0
  744. package/docs/getting-started/README.md +198 -0
  745. package/docs/getting-started/SETUP.md +25 -0
  746. package/docs/reference/AGENT_CONTEXT.md +84 -0
  747. package/docs/reference/DELIVERY_ONBOARDING.md +198 -0
  748. package/docs/reference/PROVIDER_RELEASE_TIERS.md +34 -0
  749. package/docs/reference/SECURITY.md +291 -0
  750. package/docs/reference/TELEMETRY_PRIVACY.md +259 -0
  751. package/integrations/bb-plugin-build/README.md +391 -0
  752. package/integrations/bb-plugin-build/app.css +431 -0
  753. package/integrations/bb-plugin-build/app.tsx +6210 -0
  754. package/integrations/bb-plugin-build/package.json +45 -0
  755. package/integrations/bb-plugin-build/server.ts +488 -0
  756. package/integrations/bb-plugin-build/src/adapter.ts +3672 -0
  757. package/integrations/bb-plugin-build/src/backlog-authoring-model.ts +150 -0
  758. package/integrations/bb-plugin-build/src/backlog-authoring-schema.ts +458 -0
  759. package/integrations/bb-plugin-build/src/backlog-authoring-service.ts +467 -0
  760. package/integrations/bb-plugin-build/src/backlog-authoring-view.ts +1025 -0
  761. package/integrations/bb-plugin-build/src/command-evidence-schema.ts +13 -0
  762. package/integrations/bb-plugin-build/src/competition-defaults-schema.ts +122 -0
  763. package/integrations/bb-plugin-build/src/competition-defaults-service.ts +105 -0
  764. package/integrations/bb-plugin-build/src/competition-defaults-view.ts +138 -0
  765. package/integrations/bb-plugin-build/src/contract.ts +718 -0
  766. package/integrations/bb-plugin-build/src/execution-activity-view.ts +98 -0
  767. package/integrations/bb-plugin-build/src/finalize-model.ts +205 -0
  768. package/integrations/bb-plugin-build/src/finalize-schema.ts +150 -0
  769. package/integrations/bb-plugin-build/src/finalize-service.ts +330 -0
  770. package/integrations/bb-plugin-build/src/finalize-view.ts +159 -0
  771. package/integrations/bb-plugin-build/src/judge-operations-readback.ts +303 -0
  772. package/integrations/bb-plugin-build/src/judge-operations-schema.ts +33 -0
  773. package/integrations/bb-plugin-build/src/judge-operations-view.ts +459 -0
  774. package/integrations/bb-plugin-build/src/model.ts +1318 -0
  775. package/integrations/bb-plugin-build/src/monitor-service.ts +233 -0
  776. package/integrations/bb-plugin-build/src/panel-read-ux.ts +97 -0
  777. package/integrations/bb-plugin-build/src/patch-preview-schema.ts +166 -0
  778. package/integrations/bb-plugin-build/src/patch-preview-service.ts +480 -0
  779. package/integrations/bb-plugin-build/src/patch-preview-view.ts +109 -0
  780. package/integrations/bb-plugin-build/src/planning-readback.ts +228 -0
  781. package/integrations/bb-plugin-build/src/planning-service.ts +647 -0
  782. package/integrations/bb-plugin-build/src/planning-sync-evidence.ts +37 -0
  783. package/integrations/bb-plugin-build/src/planning-workspace-readback.ts +33 -0
  784. package/integrations/bb-plugin-build/src/planning-workspace-schema.ts +131 -0
  785. package/integrations/bb-plugin-build/src/planning-workspace.ts +333 -0
  786. package/integrations/bb-plugin-build/src/poll-handoff.ts +136 -0
  787. package/integrations/bb-plugin-build/src/project-target-server.ts +21 -0
  788. package/integrations/bb-plugin-build/src/project-target.ts +45 -0
  789. package/integrations/bb-plugin-build/src/reference-index.ts +218 -0
  790. package/integrations/bb-plugin-build/src/repository-identity.ts +17 -0
  791. package/integrations/bb-plugin-build/src/repository-schema.ts +30 -0
  792. package/integrations/bb-plugin-build/src/result-explorer-view.ts +597 -0
  793. package/integrations/bb-plugin-build/src/result-readback-model.ts +163 -0
  794. package/integrations/bb-plugin-build/src/result-readback-schema.ts +319 -0
  795. package/integrations/bb-plugin-build/src/result-readback-service.ts +333 -0
  796. package/integrations/bb-plugin-build/src/run-page-view.ts +332 -0
  797. package/integrations/bb-plugin-build/src/setup-config-schema.ts +293 -0
  798. package/integrations/bb-plugin-build/src/setup-config-service.ts +620 -0
  799. package/integrations/bb-plugin-build/src/setup-config-view.ts +388 -0
  800. package/integrations/bb-plugin-build/src/sprint-close-model.ts +150 -0
  801. package/integrations/bb-plugin-build/src/sprint-close-schema.ts +128 -0
  802. package/integrations/bb-plugin-build/src/sprint-close-service.ts +293 -0
  803. package/integrations/bb-plugin-build/src/sprint-close-view.ts +116 -0
  804. package/integrations/bb-plugin-build/src/sprint-composition-model.ts +709 -0
  805. package/integrations/bb-plugin-build/src/sprint-composition-readback.ts +231 -0
  806. package/integrations/bb-plugin-build/src/sprint-composition-schema.ts +597 -0
  807. package/integrations/bb-plugin-build/src/sprint-composition-service.ts +773 -0
  808. package/integrations/bb-plugin-build/src/sprint-composition-view.ts +1221 -0
  809. package/integrations/bb-plugin-build/src/sprint-execution-schema.ts +188 -0
  810. package/integrations/bb-plugin-build/src/sprint-execution-service.ts +289 -0
  811. package/integrations/bb-plugin-build/src/sprint-execution-view.ts +54 -0
  812. package/integrations/bb-plugin-build/src/task-authoring-model.ts +563 -0
  813. package/integrations/bb-plugin-build/src/task-authoring-schema.ts +629 -0
  814. package/integrations/bb-plugin-build/src/task-authoring-service.ts +842 -0
  815. package/integrations/bb-plugin-build/src/task-authoring-view.ts +1227 -0
  816. package/integrations/bb-plugin-build/src/task-catalog-schema.ts +46 -0
  817. package/integrations/bb-plugin-build/src/task-catalog-service.ts +44 -0
  818. package/integrations/bb-plugin-build/src/task-detail-readback.ts +56 -0
  819. package/integrations/bb-plugin-build/src/task-detail-schema.ts +171 -0
  820. package/integrations/bb-plugin-build/src/task-navigation.ts +446 -0
  821. package/integrations/bb-plugin-build/src/workbench-route.ts +74 -0
  822. package/package.json +306 -4
  823. package/schemas/README.md +80 -0
  824. package/schemas/build.config.schema.json +2110 -0
  825. package/schemas/config-v1.schema.json +136 -0
  826. package/schemas/execution-config.schema.json +47 -0
  827. package/schemas/judge-scoring.schema.json +257 -0
  828. package/schemas/provider-config.schema.json +179 -0
  829. package/schemas/telemetry-config.schema.json +79 -0
  830. package/schemas/user-preferences.schema.json +141 -0
  831. package/scripts/assert-node-runtime.mjs +146 -0
  832. package/scripts/preflight-native.mjs +49 -0
  833. package/scripts/setup-git-hooks.mjs +39 -0
  834. package/scripts/sync.sh +2871 -0
  835. package/scripts/write-node-launcher.sh +138 -0
  836. package/src/resources/gemini/slash-packs/default/plan.toml +15 -0
  837. package/src/resources/gemini/slash-packs/default/summary.toml +16 -0
  838. package/src/resources/gemini/slash-packs/default/tests.toml +16 -0
  839. package/templates/.build-project/README.md +41 -0
  840. package/templates/.build-project/agents/README.md +50 -0
  841. package/templates/.build-project/agents/architect.md +10 -0
  842. package/templates/.build-project/agents/code-reviewer.md +10 -0
  843. package/templates/.build-project/agents/debugger.md +10 -0
  844. package/templates/.build-project/agents/documenter.md +10 -0
  845. package/templates/.build-project/agents/test-automator.md +10 -0
  846. package/templates/.build-project/config/build.config.jsonc +64 -0
  847. package/templates/.build-project/config/project-context.template.json +6 -0
  848. package/templates/.build-project/config/task-type-aliases.presets/kanban.yaml +14 -0
  849. package/templates/.build-project/config/task-type-aliases.presets/scrum.yaml +17 -0
  850. package/templates/.build-project/config/task-type-aliases.presets/xp.yaml +12 -0
  851. package/templates/.build-project/config/task-type-aliases.yaml +29 -0
  852. package/templates/.build-project/gitignore.template +70 -0
  853. package/templates/.build-project/task-types/analysis.yaml +38 -0
  854. package/templates/.build-project/task-types/architecture.yaml +35 -0
  855. package/templates/.build-project/task-types/doc.yaml +34 -0
  856. package/templates/.build-project/task-types/feature.yaml +22 -0
  857. package/templates/.build-project/task-types/general.yaml +4 -0
  858. package/templates/.build-project/task-types/security.yaml +38 -0
  859. package/templates/AGENTS.template.md +85 -0
  860. package/templates/CLAUDE.template.md +1 -0
  861. package/templates/GEMINI.template.md +1 -0
  862. package/templates/builtin-workflows/code-review.yaml +73 -0
  863. package/templates/builtin-workflows/skills/code-review/SKILL.md +61 -0
  864. package/templates/builtin-workflows/skills/execution-contract-analysis/SKILL.md +24 -0
  865. package/templates/builtin-workflows/skills/execution-contract-code/SKILL.md +19 -0
  866. package/templates/builtin-workflows/skills/execution-contract-structured/SKILL.md +17 -0
  867. package/templates/ci/incident-intake.mjs +787 -0
  868. package/templates/ci/incidents.yml.template +103 -0
  869. package/templates/ci/node.yml.template +17 -0
  870. package/templates/ci/python.yml.template +17 -0
  871. package/templates/guard-kit/GUARD_SETUP.md.template +258 -0
  872. package/templates/guard-kit/build-guard.yml.template +189 -0
  873. package/templates/guard-kit/check.mjs.template +932 -0
  874. package/templates/guard-kit/config.json.template +7 -0
  875. package/templates/guard-kit/policy.json.template +1 -0
  876. package/templates/profiles/README.md +57 -0
  877. package/templates/profiles/frontier-claude.json +23 -0
  878. package/templates/profiles/frontier-codex.json +23 -0
@@ -0,0 +1,3803 @@
1
+ import {
2
+ assignDuplicateVariantInstanceIds,
3
+ cleanupSynthesisInputPatches,
4
+ resolveBasicCompetitionInterruption,
5
+ resolveSynthesisInputPatchDir,
6
+ runBasicCompetition,
7
+ selectWinnerWithJudge
8
+ } from "./chunk-YBHUB4XR.js";
9
+ import {
10
+ createEvaluationHandleFinalState,
11
+ finalizeEvaluationHandleAsync,
12
+ isDurableHandleCompletion,
13
+ toEvaluationHandleWinnerMetadata,
14
+ updateEvaluationHandleWithResultAsync
15
+ } from "./chunk-NTD6CSI6.js";
16
+ import {
17
+ evaluateStageCompletionProof,
18
+ proofEstablishesSatisfaction,
19
+ resolveProviderExecutionIntentFromStage,
20
+ stageHasHostDeterministicCompletionSurface
21
+ } from "./chunk-QAMAV4DT.js";
22
+ import {
23
+ collectDeclaredStageTargets
24
+ } from "./chunk-45KUJBDI.js";
25
+ import {
26
+ changesHaveVerifiableCodeSurface
27
+ } from "./chunk-OXK5HA4B.js";
28
+ import {
29
+ providerReportsUsage,
30
+ readCostMetricsUnavailableReason,
31
+ readUsageUnavailableReason
32
+ } from "./chunk-JQUMSIGC.js";
33
+ import {
34
+ JudgeCoordinator,
35
+ evaluateMatrixAuthority,
36
+ extractEvidenceAnchors,
37
+ generateCompetitionId,
38
+ isNegativeClaim,
39
+ resolveMatrixAuthorityPolicy,
40
+ resolveTypedCompletenessAuthority
41
+ } from "./chunk-DCACX7BV.js";
42
+ import {
43
+ resolveJudgeModelRoles
44
+ } from "./chunk-ARARVIZK.js";
45
+ import {
46
+ isAcceptedMatrixVerdict
47
+ } from "./chunk-6PZY2TTU.js";
48
+ import {
49
+ categorizeFile
50
+ } from "./chunk-QTCLJHLZ.js";
51
+ import {
52
+ ArtifactNotFoundError,
53
+ createSecurityBoundary,
54
+ resolvePromptArtifacts
55
+ } from "./chunk-SK3ZFONO.js";
56
+ import {
57
+ isProviderInvocationFailure,
58
+ judgeProviderFailed
59
+ } from "./chunk-UJYDH2MW.js";
60
+ import {
61
+ deriveAiJudgeInvocationArgs
62
+ } from "./chunk-EJVCDTAN.js";
63
+ import {
64
+ applyFlywheelModelDefaults
65
+ } from "./chunk-DSRLVYBS.js";
66
+ import {
67
+ decideStageChangeScope
68
+ } from "./chunk-DS2JZ677.js";
69
+ import {
70
+ findAllowlistViolations,
71
+ isPathAllowed,
72
+ normalizePath
73
+ } from "./chunk-XZOXEIN4.js";
74
+ import {
75
+ getProjectRoot
76
+ } from "./chunk-6TRD7TEE.js";
77
+ import {
78
+ JUDGE_FEATURE_FLAGS
79
+ } from "./chunk-ZJB6SQPA.js";
80
+ import {
81
+ resolveJudgeRunSet
82
+ } from "./chunk-IVZEONFC.js";
83
+ import {
84
+ filterWorktreeRunSentinelPaths
85
+ } from "./chunk-2NMNFUQA.js";
86
+ import {
87
+ formatVariantIdentifier,
88
+ parseVariantIdentifier
89
+ } from "./chunk-TGXXYDL4.js";
90
+ import {
91
+ isRecoverableCompetitionDiff
92
+ } from "./chunk-SKTFRFQ7.js";
93
+ import {
94
+ deriveTestVerificationDisplay,
95
+ gateStatusToDisplayVerdict
96
+ } from "./chunk-R2CKS6WT.js";
97
+ import {
98
+ deriveVariantOutcome,
99
+ hasUnavailableTestVerificationEvidence,
100
+ repairOutcomeCanSupersedeRawTouchedFailure
101
+ } from "./chunk-3OPP2OZB.js";
102
+ import {
103
+ isUnavailableVerificationFinding
104
+ } from "./chunk-PXKERBKX.js";
105
+ import {
106
+ prepareUntrackedIntentIndex
107
+ } from "./chunk-QFLBRWCJ.js";
108
+ import {
109
+ parseDiffGitHeaderPaths,
110
+ parseUnifiedDiffPathLine
111
+ } from "./chunk-5FKHIKTS.js";
112
+ import {
113
+ taskVariantId
114
+ } from "./chunk-F55YABKV.js";
115
+ import {
116
+ readTrackedToolOutputRootsSync,
117
+ shouldExcludeFile
118
+ } from "./chunk-5EQN56OZ.js";
119
+ import {
120
+ runVerifyCommands
121
+ } from "./chunk-AHU3FKPA.js";
122
+ import {
123
+ isUnderRootToolOutputDir
124
+ } from "./chunk-QOIASNEJ.js";
125
+ import {
126
+ LabPathResolver
127
+ } from "./chunk-C3KCMAJP.js";
128
+ import {
129
+ execGit
130
+ } from "./chunk-MHLEZQQI.js";
131
+ import {
132
+ isInvalidExplicitConfigError
133
+ } from "./chunk-QJ6OEH4K.js";
134
+ import {
135
+ normalizeReasoningEffortInput
136
+ } from "./chunk-4BTDUT2S.js";
137
+ import {
138
+ createExecutionContext
139
+ } from "./chunk-7VRJHTGZ.js";
140
+ import {
141
+ sanitizeString
142
+ } from "./chunk-CPSVQR2I.js";
143
+
144
+ // src/automation/flywheel-competition-executor.ts
145
+ import * as fs from "fs/promises";
146
+ import * as path from "path";
147
+ import chalk from "chalk";
148
+
149
+ // src/automation/competition-pick-label.ts
150
+ function competitionPickLabel(successCount) {
151
+ return successCount === 0 ? "Judge pick (gates failed)" : "Winner";
152
+ }
153
+
154
+ // src/automation/gate-evidence.ts
155
+ var DETAIL_TAIL_LINES = 6;
156
+ var DETAIL_LINE_MAX_CHARS = 200;
157
+ var GATE_EVIDENCE_ARTIFACT_NAME = "verification-findings";
158
+ function selectFailingGateFindings(findings) {
159
+ return (findings ?? []).filter(
160
+ (finding) => finding.severity === "error" || Number.isFinite(finding.exitCode) && finding.exitCode !== 0
161
+ ).map((finding) => ({
162
+ ...finding,
163
+ command: sanitizeString(finding.command),
164
+ ...finding.outputTail === void 0 ? {} : { outputTail: sanitizeString(finding.outputTail) }
165
+ }));
166
+ }
167
+ function formatFailingGateDetail(findings) {
168
+ const failing = selectFailingGateFindings(findings);
169
+ const first = failing[0];
170
+ if (!first) return void 0;
171
+ const others = failing.length - 1;
172
+ const more = others > 0 ? ` (+${others} more failing gate${others === 1 ? "" : "s"})` : "";
173
+ const head = isUnavailableVerificationFinding(first) ? `${first.command} unavailable (exit ${first.exitCode})${more}` : `${first.command} exited ${first.exitCode}${more}`;
174
+ const tail = (first.outputTail ?? "").split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line.length > 0).slice(-DETAIL_TAIL_LINES).map(
175
+ (line) => line.length > DETAIL_LINE_MAX_CHARS ? `${line.slice(0, DETAIL_LINE_MAX_CHARS)}...` : line
176
+ );
177
+ return tail.length > 0 ? `${head}
178
+ ${tail.map((line) => ` ${line}`).join("\n")}` : head;
179
+ }
180
+ function gateEvidenceField(verification) {
181
+ const failing = selectFailingGateFindings(verification?.findings);
182
+ return failing.length > 0 ? { verificationFindings: failing } : {};
183
+ }
184
+ async function persistGateEvidenceArtifact(artifactStore, stageId, verification) {
185
+ const failing = selectFailingGateFindings(verification?.findings);
186
+ if (failing.length === 0) return;
187
+ try {
188
+ await artifactStore.save(stageId, GATE_EVIDENCE_ARTIFACT_NAME, "json", { findings: failing });
189
+ } catch {
190
+ }
191
+ }
192
+
193
+ // src/automation/verification-polarity.ts
194
+ function normalizedSignal(value) {
195
+ const trimmed = value?.trim().toLowerCase();
196
+ return trimmed ? trimmed : void 0;
197
+ }
198
+ function testsNotRunWithoutTestableSurface(input) {
199
+ if (input.testSkipReason !== "no-test-files-changed") return false;
200
+ const changedFiles = input.changedFiles;
201
+ if (!changedFiles || changedFiles.length === 0) return false;
202
+ if (changesHaveVerifiableCodeSurface([...changedFiles])) return false;
203
+ if (normalizedSignal(input.testStatus) !== "not_run") return false;
204
+ const raw = normalizedSignal(input.rawTestStatus);
205
+ if (raw !== void 0 && raw !== "not_run") return false;
206
+ if (input.exitCode !== void 0 && input.exitCode !== null) return false;
207
+ if (typeof input.failedTests === "number" && input.failedTests !== 0) return false;
208
+ return true;
209
+ }
210
+ function hasExplicitVerificationSignal(input) {
211
+ if (input.verification && typeof input.verification.passed === "boolean") {
212
+ return true;
213
+ }
214
+ if (typeof input.verification?.status === "string" && input.verification.status.trim()) {
215
+ return true;
216
+ }
217
+ if (typeof input.testStatus === "string" && input.testStatus.trim()) {
218
+ return true;
219
+ }
220
+ if (typeof input.rawTestStatus === "string" && input.rawTestStatus.trim()) {
221
+ return true;
222
+ }
223
+ if (typeof input.exitCode === "number") {
224
+ return true;
225
+ }
226
+ if (typeof input.failedTests === "number") {
227
+ return true;
228
+ }
229
+ return false;
230
+ }
231
+ function verificationRecordsBaselineClean(verification) {
232
+ if (!verification) {
233
+ return false;
234
+ }
235
+ if (verification.passedBaseline === false) {
236
+ return false;
237
+ }
238
+ const status = verification.status?.trim().toLowerCase();
239
+ if (status === "baseline_clean") {
240
+ return true;
241
+ }
242
+ if (verification.passedBaseline !== true) {
243
+ return false;
244
+ }
245
+ return !status || gateStatusToDisplayVerdict(status) !== "unavailable";
246
+ }
247
+ function verificationPolarityAllowsStageSuccess(input) {
248
+ if (!hasExplicitVerificationSignal(input)) {
249
+ return true;
250
+ }
251
+ if (verificationRecordsBaselineClean(input.verification)) {
252
+ return true;
253
+ }
254
+ if (input.verification?.passed === false) {
255
+ return false;
256
+ }
257
+ const status = input.verification?.status?.trim().toLowerCase();
258
+ if (status === "failed" || status === "unavailable") {
259
+ return false;
260
+ }
261
+ if (testsNotRunWithoutTestableSurface(input)) {
262
+ return !status || gateStatusToDisplayVerdict(status) !== "unavailable";
263
+ }
264
+ 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";
265
+ if (hasExplicitTestSignal) {
266
+ const display = deriveTestVerificationDisplay({
267
+ testStatus: input.testStatus,
268
+ rawTestStatus: input.rawTestStatus,
269
+ exitCode: input.exitCode,
270
+ failedTests: input.failedTests
271
+ });
272
+ return display === "passed";
273
+ }
274
+ return input.verification?.passed === true || status === "passed";
275
+ }
276
+
277
+ // src/automation/flywheel-apply-winner.ts
278
+ function toPolarityInput(input) {
279
+ return {
280
+ verification: input.verification,
281
+ testStatus: input.testStatus,
282
+ rawTestStatus: input.rawTestStatus,
283
+ exitCode: input.exitCode,
284
+ failedTests: input.failedTests
285
+ };
286
+ }
287
+ function classifyVerificationBlocker(input) {
288
+ if (verificationPolarityAllowsStageSuccess(toPolarityInput(input))) {
289
+ return void 0;
290
+ }
291
+ const status = input.verification?.status?.trim().toLowerCase();
292
+ const display = deriveTestVerificationDisplay({
293
+ testStatus: input.testStatus,
294
+ rawTestStatus: input.rawTestStatus,
295
+ exitCode: input.exitCode,
296
+ failedTests: input.failedTests,
297
+ // A recorded unavailable test run keeps its non-zero exit (missing
298
+ // toolchain, zero tests collected) without becoming a gate failure.
299
+ testsUnavailable: hasUnavailableTestVerificationEvidence({
300
+ testStatus: input.rawTestStatus ?? input.testStatus ?? void 0
301
+ })
302
+ });
303
+ if (status === "failed" || display === "failed") {
304
+ return "gates-failed";
305
+ }
306
+ if (input.verification?.passed === false && status !== "unavailable") {
307
+ return "gates-failed";
308
+ }
309
+ if (status === "unavailable" || display === "unavailable" || input.testStatus === "unavailable" || input.testStatus === "not_run") {
310
+ return "tests-unavailable";
311
+ }
312
+ return "gates-failed";
313
+ }
314
+ function classifyStageValidationFailure(input) {
315
+ const verificationBlocker = classifyVerificationBlocker(input);
316
+ if (verificationBlocker) return verificationBlocker;
317
+ if (input.score < input.threshold) return "below-threshold";
318
+ return void 0;
319
+ }
320
+ function formatStageValidationFailureMessage(predicate, score, threshold, findings) {
321
+ const base = formatStageValidationFailureHead(predicate, score, threshold);
322
+ const detail = formatFailingGateDetail(findings);
323
+ return detail ? `${base}: ${detail}` : base;
324
+ }
325
+ function describeStageValidationFailure(input) {
326
+ const predicate = classifyStageValidationFailure(input);
327
+ return {
328
+ predicate,
329
+ message: formatStageValidationFailureMessage(
330
+ predicate,
331
+ input.score,
332
+ input.threshold,
333
+ input.verification?.findings
334
+ )
335
+ };
336
+ }
337
+ function formatStageValidationFailureHead(predicate, score, threshold) {
338
+ switch (predicate) {
339
+ case "tests-unavailable":
340
+ return `Verification unavailable (score ${score}, threshold ${threshold})`;
341
+ case "gates-failed":
342
+ return `Gates failed (score ${score}, threshold ${threshold})`;
343
+ case "below-threshold":
344
+ return `Score ${score} below threshold ${threshold}`;
345
+ default:
346
+ return `Validation did not pass (score ${score}, threshold ${threshold})`;
347
+ }
348
+ }
349
+ function formatWinnerDeliveryRefusalReason(predicate) {
350
+ switch (predicate) {
351
+ case "tests-unavailable":
352
+ return "tests unavailable";
353
+ case "gates-failed":
354
+ return "gates failed";
355
+ case "below-threshold":
356
+ return "score below threshold";
357
+ }
358
+ }
359
+ function winnerHasNoApplicableTests(winner) {
360
+ if (winner.testStatus !== "not_run") return false;
361
+ if (winner.testsExecuted?.skipReason !== "no-test-files-changed") return false;
362
+ const changedFiles = winner.changedFiles ?? [];
363
+ if (changedFiles.length === 0) return false;
364
+ return changedFiles.every((file) => categorizeFile(file) === "docs");
365
+ }
366
+ function resolveTrustedCandidateTestStatus(candidate) {
367
+ const status = candidate.testStatus;
368
+ if (candidate.repairedTestStatus !== void 0 && (status === "failed" || status === "error" || status === "timeout")) {
369
+ return candidate.repairedTestStatus;
370
+ }
371
+ return status;
372
+ }
373
+ function isExecutedTestFailure(finding) {
374
+ return finding.kind === "test" && finding.severity === "error" && finding.exitCode !== 0 && finding.exitCode !== 127;
375
+ }
376
+ function isExecutedNonTestGateFailure(finding) {
377
+ return finding.kind !== "test" && finding.severity === "error" && finding.exitCode !== 0;
378
+ }
379
+ function summaryRecordsUnavailable(summary) {
380
+ const status = summary.status;
381
+ if (typeof status === "string") return status.trim().toLowerCase() === "unavailable";
382
+ return summary.passed === false && (summary.findings ?? []).some(isUnavailableVerificationFinding);
383
+ }
384
+ function classifyCompetitionValidationFailure(result) {
385
+ const winner = result.winner;
386
+ const testStatus = winner?.testStatus;
387
+ const verificationSummary = winner?.verification ?? result.verification;
388
+ const statusFromTest = testStatus === "unavailable" || testStatus === "not_run" ? "unavailable" : testStatus === "failed" || testStatus === "error" || testStatus === "timeout" ? "failed" : testStatus === "passed" ? "passed" : void 0;
389
+ const executedGateFailed = verificationSummary?.findings?.some(isExecutedNonTestGateFailure);
390
+ const aggregateUnavailable = !executedGateFailed && !verificationSummary?.findings?.some(isExecutedTestFailure) && verificationSummary && summaryRecordsUnavailable(verificationSummary);
391
+ const gateStatus = statusFromTest === "unavailable" && executedGateFailed ? "failed" : aggregateUnavailable && (statusFromTest === void 0 || statusFromTest === "passed") ? "unavailable" : statusFromTest;
392
+ return classifyStageValidationFailure({
393
+ success: winner?.success === true,
394
+ score: winner?.score ?? result.validationScore ?? 0,
395
+ // Threshold is not persisted on the stage result. A successful winner
396
+ // whose verification does not block and whose validationPassed is false
397
+ // is the below-threshold case; a non-success winner without a
398
+ // verification blocker stays unclassified so the generic fallback remains.
399
+ threshold: winner?.success === true ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY,
400
+ verification: verificationSummary ? {
401
+ passed: verificationSummary.passed && gateStatus !== "failed",
402
+ status: gateStatus === "unavailable" ? "unavailable" : gateStatus === "failed" ? "failed" : verificationSummary.passed ? "passed" : gateStatus ?? "failed"
403
+ } : gateStatus ? { passed: gateStatus === "passed", status: gateStatus } : void 0,
404
+ testStatus,
405
+ rawTestStatus: testStatus,
406
+ exitCode: winner?.testsExecuted?.exitCode
407
+ });
408
+ }
409
+ function resolveWinnerDeliveryRefusalReason(result) {
410
+ if (result.validationPassed !== true) {
411
+ const predicate = classifyCompetitionValidationFailure(result);
412
+ if (predicate) return formatWinnerDeliveryRefusalReason(predicate);
413
+ return "validation did not pass";
414
+ }
415
+ if (result.winner?.success !== true) return "selected winner is not successful";
416
+ const invariantStatus = result.winner.mergeInvariantValidation?.status;
417
+ if (invariantStatus !== void 0 && invariantStatus !== "passed") {
418
+ return "merge invariant validation did not pass";
419
+ }
420
+ return void 0;
421
+ }
422
+ function normalizeAllowlistEntriesForMatching(allowlist) {
423
+ return allowlist.map((entry) => {
424
+ const hadTrailingSlash = entry.endsWith("/");
425
+ const normalized = normalizePath(entry);
426
+ if (hadTrailingSlash && !normalized.endsWith("/")) {
427
+ return `${normalized}/`;
428
+ }
429
+ return normalized;
430
+ });
431
+ }
432
+ function isNullDiffEndpoint(filePath) {
433
+ return normalizePath(filePath) === "/dev/null";
434
+ }
435
+ function parseDiffGitHeader(line) {
436
+ const parsed = parseDiffGitHeaderPaths(line);
437
+ if (!parsed) return null;
438
+ return {
439
+ aPath: normalizePath(parsed.aPath),
440
+ bPath: normalizePath(parsed.bPath)
441
+ };
442
+ }
443
+ function resolveDiffBlockEndpoints(header, blockLines) {
444
+ let aPath = header.aPath;
445
+ let bPath = header.bPath;
446
+ let aIsNull = isNullDiffEndpoint(aPath);
447
+ let bIsNull = isNullDiffEndpoint(bPath);
448
+ let sawRenameOrCopyMarker = false;
449
+ const markerKinds = /* @__PURE__ */ new Set();
450
+ let markerFrom;
451
+ let markerTo;
452
+ const parseMarkerPath = (line, prefix) => {
453
+ const token = line.slice(prefix.length);
454
+ if (!token) return void 0;
455
+ const aToken = token.startsWith('"') ? `"a/${token.slice(1)}` : `a/${token}`;
456
+ const bToken = token.startsWith('"') ? `"b/${token.slice(1)}` : `b/${token}`;
457
+ return parseDiffGitHeaderPaths(`diff --git ${aToken} ${bToken}`)?.aPath;
458
+ };
459
+ for (const line of blockLines) {
460
+ if (line.startsWith("@@")) break;
461
+ if (line.startsWith("rename from ")) {
462
+ sawRenameOrCopyMarker = true;
463
+ markerKinds.add("rename");
464
+ markerFrom = parseMarkerPath(line, "rename from ");
465
+ continue;
466
+ }
467
+ if (line.startsWith("rename to ")) {
468
+ sawRenameOrCopyMarker = true;
469
+ markerKinds.add("rename");
470
+ markerTo = parseMarkerPath(line, "rename to ");
471
+ continue;
472
+ }
473
+ if (line.startsWith("copy from ")) {
474
+ sawRenameOrCopyMarker = true;
475
+ markerKinds.add("copy");
476
+ markerFrom = parseMarkerPath(line, "copy from ");
477
+ continue;
478
+ }
479
+ if (line.startsWith("copy to ")) {
480
+ sawRenameOrCopyMarker = true;
481
+ markerKinds.add("copy");
482
+ markerTo = parseMarkerPath(line, "copy to ");
483
+ continue;
484
+ }
485
+ if (line.startsWith("--- ")) {
486
+ const parsed = parseUnifiedDiffPathLine(line);
487
+ if (parsed === "/dev/null") {
488
+ aIsNull = true;
489
+ } else if (parsed) {
490
+ aPath = normalizePath(parsed);
491
+ aIsNull = false;
492
+ }
493
+ continue;
494
+ }
495
+ if (line.startsWith("+++ ")) {
496
+ const parsed = parseUnifiedDiffPathLine(line);
497
+ if (parsed === "/dev/null") {
498
+ bIsNull = true;
499
+ } else if (parsed) {
500
+ bPath = normalizePath(parsed);
501
+ bIsNull = false;
502
+ }
503
+ }
504
+ }
505
+ if (aIsNull) aPath = "/dev/null";
506
+ if (bIsNull) bPath = "/dev/null";
507
+ const isRenameOrCopy = sawRenameOrCopyMarker || !aIsNull && !bIsNull && aPath !== bPath;
508
+ const markerPaths = [markerFrom, markerTo].filter((value) => Boolean(value));
509
+ const markersConsistent = !sawRenameOrCopyMarker || markerKinds.size === 1 && markerFrom === aPath && markerTo === bPath;
510
+ return { aPath, bPath, isRenameOrCopy, markersConsistent, markerPaths };
511
+ }
512
+ function isDiffBlockAllowlisted(endpoints, allowlist) {
513
+ if (!endpoints.markersConsistent) return false;
514
+ const aNull = isNullDiffEndpoint(endpoints.aPath);
515
+ const bNull = isNullDiffEndpoint(endpoints.bPath);
516
+ if (aNull && bNull) return false;
517
+ if (aNull) return isPathAllowed(endpoints.bPath, allowlist);
518
+ if (bNull) return isPathAllowed(endpoints.aPath, allowlist);
519
+ if (endpoints.isRenameOrCopy || endpoints.aPath !== endpoints.bPath) {
520
+ return isPathAllowed(endpoints.aPath, allowlist) && isPathAllowed(endpoints.bPath, allowlist);
521
+ }
522
+ return isPathAllowed(endpoints.aPath, allowlist);
523
+ }
524
+ function disallowedEndpointsForBlock(endpoints, allowlist) {
525
+ if (isDiffBlockAllowlisted(endpoints, allowlist)) {
526
+ return [];
527
+ }
528
+ const violations = /* @__PURE__ */ new Set();
529
+ if (!isNullDiffEndpoint(endpoints.aPath) && !isPathAllowed(endpoints.aPath, allowlist)) {
530
+ violations.add(endpoints.aPath);
531
+ }
532
+ if (!isNullDiffEndpoint(endpoints.bPath) && !isPathAllowed(endpoints.bPath, allowlist)) {
533
+ violations.add(endpoints.bPath);
534
+ }
535
+ for (const markerPath of endpoints.markerPaths) {
536
+ if (!isPathAllowed(markerPath, allowlist)) violations.add(markerPath);
537
+ }
538
+ if (violations.size === 0) {
539
+ if (!isNullDiffEndpoint(endpoints.aPath)) violations.add(endpoints.aPath);
540
+ if (!isNullDiffEndpoint(endpoints.bPath)) violations.add(endpoints.bPath);
541
+ }
542
+ return [...violations];
543
+ }
544
+ function iterateDiffFileBlocks(diffText, onBlock) {
545
+ let currentBlock = [];
546
+ let currentHeader = null;
547
+ const flush = () => {
548
+ if (currentBlock.length === 0 || !currentHeader) {
549
+ currentBlock = [];
550
+ currentHeader = null;
551
+ return;
552
+ }
553
+ onBlock(currentHeader, currentBlock);
554
+ currentBlock = [];
555
+ currentHeader = null;
556
+ };
557
+ for (const line of diffText.split("\n")) {
558
+ if (line.startsWith("diff --git ")) {
559
+ flush();
560
+ currentBlock = [line];
561
+ currentHeader = parseDiffGitHeader(line);
562
+ continue;
563
+ }
564
+ if (currentBlock.length === 0) continue;
565
+ currentBlock.push(line);
566
+ }
567
+ flush();
568
+ }
569
+ function findDisallowedDiffEndpoints(diffText, allowlist) {
570
+ const normalizedAllowlist = normalizeAllowlistEntriesForMatching(allowlist);
571
+ const violations = /* @__PURE__ */ new Set();
572
+ iterateDiffFileBlocks(diffText, (header, blockLines) => {
573
+ const endpoints = resolveDiffBlockEndpoints(header, blockLines);
574
+ for (const path2 of disallowedEndpointsForBlock(endpoints, normalizedAllowlist)) {
575
+ violations.add(path2);
576
+ }
577
+ });
578
+ return [...violations];
579
+ }
580
+ function filterUnifiedDiffToAllowlist(diffText, allowlist) {
581
+ const normalizedAllowlist = normalizeAllowlistEntriesForMatching(allowlist);
582
+ const fileBlocks = [];
583
+ iterateDiffFileBlocks(diffText, (header, blockLines) => {
584
+ const endpoints = resolveDiffBlockEndpoints(header, blockLines);
585
+ if (isDiffBlockAllowlisted(endpoints, normalizedAllowlist)) {
586
+ fileBlocks.push(blockLines.join("\n"));
587
+ }
588
+ });
589
+ const filtered = fileBlocks.join("\n");
590
+ if (filtered.trim().length === 0) return "";
591
+ return filtered.endsWith("\n") ? filtered : `${filtered}
592
+ `;
593
+ }
594
+ function shouldRestrictWinnerPatchToAllowlist(mode, allowlist) {
595
+ if (allowlist.length === 0) return false;
596
+ return mode === "strict" || mode === "filter";
597
+ }
598
+ function applyWinnerAllowlistFilter(patch, allowlist, mode) {
599
+ if (!shouldRestrictWinnerPatchToAllowlist(mode, allowlist)) {
600
+ return patch;
601
+ }
602
+ return filterUnifiedDiffToAllowlist(patch, [...allowlist]);
603
+ }
604
+ function assertWinnerPatchAllowlistEndpoints(patch, allowlist, mode) {
605
+ if (!shouldRestrictWinnerPatchToAllowlist(mode, allowlist)) {
606
+ return;
607
+ }
608
+ if (patch.trim().length === 0) {
609
+ return;
610
+ }
611
+ const violations = findDisallowedDiffEndpoints(patch, [...allowlist]);
612
+ if (violations.length === 0) {
613
+ return;
614
+ }
615
+ throw new Error(
616
+ `Winner patch has non-allowlisted endpoint(s) under ${mode} allowlist mode: ${violations.join(", ")}`
617
+ );
618
+ }
619
+ async function loadWinnerVariantResult(result, stageId, artifactStore) {
620
+ if (!result.winner?.resultArtifactPath || !artifactStore) {
621
+ return void 0;
622
+ }
623
+ const raw = await artifactStore.load(result.winner.resultArtifactPath, stageId);
624
+ const parsed = JSON.parse(raw);
625
+ const variantResult = parsed && typeof parsed === "object" && "variantResult" in parsed ? parsed.variantResult : void 0;
626
+ return variantResult && typeof variantResult === "object" ? variantResult : void 0;
627
+ }
628
+ function nonEmptyPatch(value) {
629
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
630
+ }
631
+ async function diffWinnerWorktree(worktreePath, pathspec, baseRef = "HEAD") {
632
+ if (!worktreePath) return void 0;
633
+ const args = ["diff", "--binary", baseRef];
634
+ if (pathspec.length > 0) {
635
+ args.push("--", ...pathspec);
636
+ }
637
+ const intentIndex = await prepareUntrackedIntentIndex({ worktreePath });
638
+ try {
639
+ const diff = await execGit(args, {
640
+ cwd: worktreePath,
641
+ timeoutMs: 0,
642
+ stripFinalNewline: false,
643
+ ...intentIndex.indexPath ? { env: { GIT_INDEX_FILE: intentIndex.indexPath } } : {}
644
+ });
645
+ if (diff.exitCode !== 0) throw new Error(diff.stderr);
646
+ return nonEmptyPatch(diff.stdout);
647
+ } finally {
648
+ await intentIndex.dispose();
649
+ }
650
+ }
651
+ async function resolveWinnerPatch(params) {
652
+ const variantResult = await loadWinnerVariantResult(
653
+ params.result,
654
+ params.stageId,
655
+ params.artifactStore
656
+ );
657
+ const storedPatch = nonEmptyPatch(variantResult?.worktreeDiff);
658
+ const artifactPatchUsable = storedPatch !== void 0 && variantResult?.worktreeDiffReplayable !== false && isRecoverableCompetitionDiff(storedPatch);
659
+ const artifactPatch = artifactPatchUsable ? storedPatch : void 0;
660
+ const artifactRejected = storedPatch !== void 0 && !artifactPatchUsable;
661
+ const truncatedError = () => new Error(
662
+ "Winner diff truncated for context budget and no retained winner worktree is available to recover the full patch"
663
+ );
664
+ const baselineRef = typeof variantResult?.baselineRef === "string" && variantResult.baselineRef.length > 0 ? variantResult.baselineRef : void 0;
665
+ if (artifactRejected && !baselineRef) throw truncatedError();
666
+ const diffBase = artifactRejected ? baselineRef : void 0;
667
+ if (artifactPatch && params.filterTiming === "after-resolution") {
668
+ return {
669
+ patch: applyWinnerAllowlistFilter(artifactPatch, params.allowlist, params.allowlistMode)
670
+ };
671
+ }
672
+ if (artifactPatch) {
673
+ const filteredPatch = applyWinnerAllowlistFilter(
674
+ artifactPatch,
675
+ params.allowlist,
676
+ params.allowlistMode
677
+ );
678
+ if (filteredPatch.trim().length > 0) {
679
+ return { patch: filteredPatch };
680
+ }
681
+ }
682
+ const fallbackPathspec = params.filterTiming === "before-fallback" ? params.fallbackDiffPathspec ?? [] : [];
683
+ const retainedPatch = await diffWinnerWorktree(
684
+ typeof variantResult?.retainedWorktreePath === "string" ? variantResult.retainedWorktreePath : void 0,
685
+ fallbackPathspec,
686
+ diffBase
687
+ );
688
+ if (retainedPatch) {
689
+ return {
690
+ patch: params.filterTiming === "after-resolution" ? applyWinnerAllowlistFilter(retainedPatch, params.allowlist, params.allowlistMode) : retainedPatch
691
+ };
692
+ }
693
+ const winnerPatch = await diffWinnerWorktree(
694
+ params.result.winner?.worktreePath,
695
+ fallbackPathspec,
696
+ diffBase
697
+ );
698
+ if (!winnerPatch) {
699
+ if (artifactRejected) throw truncatedError();
700
+ return void 0;
701
+ }
702
+ return {
703
+ patch: params.filterTiming === "after-resolution" ? applyWinnerAllowlistFilter(winnerPatch, params.allowlist, params.allowlistMode) : winnerPatch
704
+ };
705
+ }
706
+ async function applyCompetitionWinnerPatch(params) {
707
+ const resolvedPatch = await resolveWinnerPatch(params);
708
+ const patch = resolvedPatch?.patch;
709
+ if (!patch || patch.trim().length === 0) {
710
+ return { applied: false };
711
+ }
712
+ const normalizedPatch = patch.endsWith("\n") ? patch : `${patch}
713
+ `;
714
+ assertWinnerPatchAllowlistEndpoints(normalizedPatch, params.allowlist, params.allowlistMode);
715
+ if (params.artifactStore) {
716
+ try {
717
+ await params.artifactStore.save(params.stageId, "winnerDiff", "diff", normalizedPatch);
718
+ } catch {
719
+ }
720
+ }
721
+ try {
722
+ const applied = await execGit(["apply", "--3way", "--whitespace=nowarn", "-"], {
723
+ cwd: params.targetWorktreePath,
724
+ timeoutMs: 0,
725
+ input: normalizedPatch
726
+ });
727
+ if (applied.exitCode !== 0) throw new Error(applied.stderr);
728
+ } catch (applyError) {
729
+ try {
730
+ const reversed = await execGit(["apply", "--reverse", "--check", "-"], {
731
+ cwd: params.targetWorktreePath,
732
+ timeoutMs: 0,
733
+ input: normalizedPatch
734
+ });
735
+ if (reversed.exitCode !== 0) throw new Error(reversed.stderr);
736
+ params.onAlreadyApplied?.();
737
+ } catch {
738
+ throw applyError;
739
+ }
740
+ }
741
+ return { applied: true, normalizedPatch };
742
+ }
743
+
744
+ // src/automation/flywheel-competition-identity.ts
745
+ var admissions = /* @__PURE__ */ new WeakMap();
746
+ function admitFlywheelVariantSpecs(specs, configs) {
747
+ return specs.map((spec, index) => {
748
+ const config = configs[index];
749
+ const admitted = { ...spec, model: config.model };
750
+ admissions.set(admitted, { config });
751
+ return admitted;
752
+ });
753
+ }
754
+ function recordedVariant(result) {
755
+ const parsed = parseVariantIdentifier(result.variant ?? "");
756
+ return parsed.provider === result.provider && parsed.executionMode ? parsed : {};
757
+ }
758
+ function recordedEffort(result) {
759
+ return normalizeReasoningEffortInput(
760
+ recordedVariant(result).reasoningEffort ?? result.requestedReasoningEffort
761
+ );
762
+ }
763
+ function recordedModels(result) {
764
+ const canonical = recordedVariant(result).model;
765
+ return [
766
+ result.model,
767
+ result.resolvedModel,
768
+ canonical === "default" ? void 0 : canonical
769
+ ].filter((model) => model !== void 0);
770
+ }
771
+ function configMatchesResult(config, result) {
772
+ if (config.provider !== result.provider) return false;
773
+ if (config.variantInstanceId !== result.variantInstanceId) return false;
774
+ if (result.executionMode && config.executionMode !== result.executionMode) return false;
775
+ const canonical = parseVariantIdentifier(formatVariantIdentifier(config));
776
+ if (config.model) {
777
+ const expectedModels = [config.model, canonical.model, config.fallbackModel];
778
+ const models = result.modelInput ? [result.modelInput] : recordedModels(result);
779
+ if (models.length > 0 && !models.some((model) => expectedModels.includes(model))) return false;
780
+ }
781
+ const effort = normalizeReasoningEffortInput(config.modelReasoningEffort);
782
+ const recorded = recordedEffort(result);
783
+ return recorded === void 0 || effort === recorded;
784
+ }
785
+ function bindFlywheelVariantResults(specs, results) {
786
+ const matches = specs.map((spec) => {
787
+ const config = admissions.get(spec).config;
788
+ const compatible = results.filter((result) => configMatchesResult(config, result));
789
+ const exact = compatible.filter(
790
+ (result) => (result.modelInput ?? result.model ?? recordedVariant(result).model) === config.model && recordedEffort(result) === normalizeReasoningEffortInput(config.modelReasoningEffort)
791
+ );
792
+ return exact.length > 0 ? exact : compatible;
793
+ });
794
+ for (const [index, spec] of specs.entries()) {
795
+ const possible = matches[index];
796
+ const result = possible[0];
797
+ if (possible.length > 1 || result && matches.filter((m) => m.includes(result)).length > 1) {
798
+ throw new Error(`Ambiguous competition execution identity for ${variantIdForSpec(spec)}`);
799
+ }
800
+ admissions.get(spec).result = result;
801
+ }
802
+ }
803
+ function specMatchesResult(spec, result) {
804
+ if (spec.provider !== result.provider) return false;
805
+ const models = result.modelInput ? [result.modelInput] : recordedModels(result);
806
+ if (spec.model !== void 0 && !models.includes(spec.model)) return false;
807
+ if (spec.executionMode && result.executionMode && spec.executionMode !== result.executionMode) {
808
+ return false;
809
+ }
810
+ const effort = normalizeReasoningEffortInput(spec.reasoning);
811
+ const recorded = recordedEffort(result);
812
+ return effort === void 0 || recorded === void 0 || effort === recorded;
813
+ }
814
+ function matchVariantResult(spec, results) {
815
+ const admission = admissions.get(spec);
816
+ if (admission) {
817
+ return admission.result && results.includes(admission.result) ? admission.result : void 0;
818
+ }
819
+ const compatible = results.filter((result) => specMatchesResult(spec, result));
820
+ const effort = normalizeReasoningEffortInput(spec.reasoning);
821
+ const exact = effort === void 0 ? [] : compatible.filter((result) => recordedEffort(result) === effort);
822
+ const matches = exact.length > 0 ? exact : compatible;
823
+ return matches.length === 1 && !matches[0].variantInstanceId ? matches[0] : void 0;
824
+ }
825
+ function candidateMatchesVariantResult(candidate, result) {
826
+ const admission = admissions.get(candidate.variant);
827
+ if (!admission) return !result.variantInstanceId && specMatchesResult(candidate.variant, result);
828
+ const bound = admission.result;
829
+ if (!bound || bound.provider !== result.provider) return false;
830
+ if (bound.variantInstanceId !== result.variantInstanceId) return false;
831
+ if (bound.modelInput && result.modelInput && bound.modelInput !== result.modelInput) return false;
832
+ if (bound.model && result.model && bound.model !== result.model && bound.resolvedModel !== result.model && bound.model !== result.resolvedModel)
833
+ return false;
834
+ if (bound.executionMode && result.executionMode && bound.executionMode !== result.executionMode)
835
+ return false;
836
+ const effort = recordedEffort(bound);
837
+ const recorded = recordedEffort(result);
838
+ return effort === void 0 || recorded === void 0 || effort === recorded;
839
+ }
840
+ function findCandidateForVariantResult(candidates, result) {
841
+ const matches = candidates.filter(
842
+ (candidate) => candidateMatchesVariantResult(candidate, result)
843
+ );
844
+ return matches.length === 1 ? matches[0] : void 0;
845
+ }
846
+ function variantIdForSpec(spec) {
847
+ const admission = admissions.get(spec);
848
+ return admission ? `${formatVariantIdentifier(admission.config)}#${admission.config.variantInstanceId ?? ""}` : `${spec.provider ?? ""}:${spec.model ?? ""}`;
849
+ }
850
+ function candidateScoreId(candidate) {
851
+ return admissions.has(candidate.variant) ? variantIdForSpec(candidate.variant) : [candidate.variant.provider, candidate.variant.model].filter(Boolean).join(":");
852
+ }
853
+ function reconcileJudgeRationaleWinner(packet, judgedCandidate, finalCandidate, hasJudgeVerdict) {
854
+ const finalWinnerId = finalCandidate ? candidateScoreId(finalCandidate) : "none";
855
+ if ((packet.winnerId ?? "none") === finalWinnerId) return packet;
856
+ const selectionChanged = hasJudgeVerdict && judgedCandidate !== finalCandidate;
857
+ return {
858
+ ...packet,
859
+ rawWinnerId: packet.rawWinnerId ?? packet.winnerId ?? void 0,
860
+ winnerId: finalWinnerId,
861
+ ...selectionChanged ? { winnerOverridden: true } : {}
862
+ };
863
+ }
864
+ function observedVariantSpec(result) {
865
+ return { provider: result.provider, model: result.model, reasoning: recordedEffort(result) };
866
+ }
867
+
868
+ // src/automation/flywheel-judge-preflight.ts
869
+ function validateWorkflowJudgeModels(config, workerCwd) {
870
+ const mainJudge = config.judgeConfig?.disableAiJudge !== true;
871
+ const coverageTieJudge = Boolean(
872
+ workerCwd && config.judgeConfig && config.candidateGate?.coverage?.targets?.length
873
+ );
874
+ if (config.variants.length < 2 || !mainJudge && !coverageTieJudge) return;
875
+ try {
876
+ resolveJudgeModelRoles({
877
+ allowUnsafeModel: config.judgeConfig?.allowUnsafeModel === true,
878
+ activeJudgeTypes: resolveJudgeRunSet(
879
+ deriveAiJudgeInvocationArgs(config.judgeConfig),
880
+ JUDGE_FEATURE_FLAGS.JUDGE_PROFILE === "shadow"
881
+ )
882
+ });
883
+ } catch (error) {
884
+ if (isInvalidExplicitConfigError(error)) throw error;
885
+ throw new Error(
886
+ "Workflow judges require configured quality models. Correct the judge configuration, or use build run competition with --judge-force-model for deliberate fast-model judging.\n" + (error instanceof Error ? error.message : String(error)),
887
+ { cause: error }
888
+ );
889
+ }
890
+ }
891
+
892
+ // src/automation/flywheel-to-core-verification-finding.ts
893
+ function toCoreVerificationFinding(finding) {
894
+ const kind = finding.kind === "coverage" ? "other" : finding.kind;
895
+ const outputParts = [];
896
+ if (finding.kind === "coverage") {
897
+ const coverageDetail = finding.outputTail?.trim() ? finding.outputTail.trim() : finding.command ? `Coverage observation for ${finding.command}` : "Coverage observation";
898
+ outputParts.push(
899
+ coverageDetail.toLowerCase().includes("coverage") ? coverageDetail : `Coverage: ${coverageDetail}`
900
+ );
901
+ } else if (finding.outputTail) {
902
+ outputParts.push(finding.outputTail);
903
+ }
904
+ if (finding.recommendedNextStep) {
905
+ const next = finding.recommendedNextStep.trim();
906
+ if (next && !outputParts.some((part) => part.includes(next))) {
907
+ outputParts.push(next);
908
+ }
909
+ }
910
+ const mapped = {
911
+ kind,
912
+ command: finding.command,
913
+ exitCode: finding.exitCode,
914
+ severity: finding.severity
915
+ };
916
+ if (outputParts.length > 0) {
917
+ mapped.outputTail = outputParts.join("\n");
918
+ }
919
+ return mapped;
920
+ }
921
+
922
+ // src/automation/flywheel-competition-executor.ts
923
+ var CANDIDATE_GATE_COMMAND_TIMEOUT_MS = 5 * 60 * 1e3;
924
+ function isNoChangesDetectedError(errorMessage) {
925
+ return Boolean(errorMessage?.includes("No changes detected (git status clean)"));
926
+ }
927
+ function generateCandidateFeedback(variantEvaluation, result) {
928
+ if (!variantEvaluation && !result) return void 0;
929
+ const parts = [];
930
+ const score = variantEvaluation?.qualityScore ?? result.judgeScore ?? result.completeness;
931
+ if (score !== void 0) {
932
+ parts.push(`Score: ${Number(score).toFixed(1)}/100`);
933
+ }
934
+ const changedFiles = extractChangedFilesFromResult(result);
935
+ const fileCount = changedFiles.length;
936
+ const linesAdded = result.gitMetrics?.linesAdded ?? result.linesAdded ?? 0;
937
+ const linesDeleted = result.gitMetrics?.linesDeleted ?? result.linesRemoved ?? 0;
938
+ if (fileCount > 0 || linesAdded > 0 || linesDeleted > 0) {
939
+ parts.push(`Changes: ${fileCount} file(s), +${linesAdded}/-${linesDeleted} lines`);
940
+ }
941
+ const testStatus = result.testStatus;
942
+ if (testStatus) {
943
+ parts.push(`Tests: ${testStatus}`);
944
+ }
945
+ const strengths = variantEvaluation?.strengths;
946
+ if (strengths && strengths.length > 0) {
947
+ const topStrengths = strengths.slice(0, 2).join("; ");
948
+ parts.push(`Strengths: ${topStrengths}`);
949
+ }
950
+ const weaknesses = variantEvaluation?.weaknesses;
951
+ if (weaknesses && weaknesses.length > 0) {
952
+ const topWeaknesses = weaknesses.slice(0, 2).join("; ");
953
+ parts.push(`Areas for improvement: ${topWeaknesses}`);
954
+ }
955
+ const cq = variantEvaluation?.codeQuality;
956
+ if (cq) {
957
+ const metrics = [];
958
+ if (cq.correctness !== void 0) metrics.push(`correctness=${cq.correctness}`);
959
+ if (cq.completeness !== void 0) metrics.push(`completeness=${cq.completeness}`);
960
+ if (metrics.length > 0) {
961
+ parts.push(`Quality: ${metrics.join(", ")}`);
962
+ }
963
+ }
964
+ return parts.length > 0 ? `${parts.join(". ")}.` : void 0;
965
+ }
966
+ function extractChangedFilesFromResult(result) {
967
+ if ("changedFiles" in result && Array.isArray(result.changedFiles)) {
968
+ return result.changedFiles;
969
+ }
970
+ const statusLines = result.worktreeSummary?.statusLines;
971
+ if (statusLines && Array.isArray(statusLines) && statusLines.length > 0) {
972
+ return statusLines.map((line) => extractChangedFileFromStatusLine(String(line))).filter((line) => Boolean(line));
973
+ }
974
+ const filesChanged = result.gitMetrics?.filesChanged;
975
+ if (typeof filesChanged === "number" && filesChanged > 0) {
976
+ return Array.from({ length: filesChanged }, (_, i) => `file${i + 1}`);
977
+ }
978
+ return [];
979
+ }
980
+ function resultHasChangeTracking(result) {
981
+ if ("changedFiles" in result && Array.isArray(result.changedFiles)) {
982
+ return true;
983
+ }
984
+ const statusLines = result.worktreeSummary?.statusLines;
985
+ if (Array.isArray(statusLines)) {
986
+ return true;
987
+ }
988
+ return typeof result.gitMetrics?.filesChanged === "number";
989
+ }
990
+ function extractChangedFileFromStatusLine(line) {
991
+ const trimmed = line.trim();
992
+ if (!trimmed) return null;
993
+ const arrowIdx = trimmed.lastIndexOf("->");
994
+ if (arrowIdx !== -1) {
995
+ const candidate = trimmed.slice(arrowIdx + 2).trim();
996
+ return candidate || null;
997
+ }
998
+ const match = trimmed.match(/^[MADRCU?! ]{1,2}\s*(.+)$/);
999
+ return match?.[1]?.trim() ?? null;
1000
+ }
1001
+ function candidateHasChangedFiles(candidate) {
1002
+ return Array.isArray(candidate.changedFiles) && candidate.changedFiles.length > 0;
1003
+ }
1004
+ function candidateHasConcreteZeroChanges(candidate) {
1005
+ return candidate.changeTrackingAvailable === true && !candidateHasChangedFiles(candidate);
1006
+ }
1007
+ function stageHasDeterministicChecks(stage) {
1008
+ return stageHasHostDeterministicCompletionSurface(stage);
1009
+ }
1010
+ function renderCandidateGateCommand(command, candidate) {
1011
+ return command.replaceAll("{{provider}}", shellArg(candidate.variant.provider)).replaceAll("{{model}}", shellArg(candidate.variant.model ?? "")).replaceAll("{{variant}}", shellArg(formatCompetitionCandidateVariantDisplay(candidate)));
1012
+ }
1013
+ function formatCompetitionCandidateVariantDisplay(candidate) {
1014
+ return formatCompetitionVariantDisplay(candidate.variant);
1015
+ }
1016
+ function formatCompetitionVariantDisplay(variant) {
1017
+ const effort = normalizeReasoningEffortInput(variant.reasoning);
1018
+ const parts = [variant.provider, variant.model, effort ? `effort-${effort}` : void 0].filter(
1019
+ (part) => typeof part === "string" && part.length > 0
1020
+ );
1021
+ return parts.join(":");
1022
+ }
1023
+ function shellArg(value) {
1024
+ if (/^[A-Za-z0-9._:@/+,-]+$/.test(value)) {
1025
+ return value;
1026
+ }
1027
+ return `'${value.replace(/'/g, `'\\''`)}'`;
1028
+ }
1029
+ async function validateWorktreeAgainstStageChecks(stage, worktreePath, stdout, options) {
1030
+ if (!stageHasHostDeterministicCompletionSurface(stage)) return false;
1031
+ const proof = await evaluateStageCompletionProof({
1032
+ stage,
1033
+ worktreePath,
1034
+ stdout,
1035
+ attemptChangedFiles: options?.attemptChangedFiles ?? [],
1036
+ allowlist: options?.allowlist ?? computeExpectedAllowlist(stage),
1037
+ stageId: stage.id
1038
+ });
1039
+ return proofEstablishesSatisfaction(proof);
1040
+ }
1041
+ function getVariantTelemetryStatePath(taskId, provider, model, mode, reasoningEffort) {
1042
+ const variantKey = taskVariantId(
1043
+ taskId,
1044
+ provider,
1045
+ model,
1046
+ mode,
1047
+ void 0,
1048
+ void 0,
1049
+ reasoningEffort
1050
+ );
1051
+ return path.join(
1052
+ LabPathResolver.getInstance().getVariantStateDir(path.join(getProjectRoot(), ".build-project")),
1053
+ `${variantKey}.json`
1054
+ );
1055
+ }
1056
+ function getValueAtPath(root, keys) {
1057
+ let current = root;
1058
+ for (const key of keys) {
1059
+ if (!current || typeof current !== "object") return void 0;
1060
+ current = current[key];
1061
+ }
1062
+ return current;
1063
+ }
1064
+ function getFiniteNumberAtPath(root, keys) {
1065
+ const value = getValueAtPath(root, keys);
1066
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1067
+ }
1068
+ function getStringAtPath(root, keys) {
1069
+ const value = getValueAtPath(root, keys);
1070
+ return typeof value === "string" ? value : void 0;
1071
+ }
1072
+ function extractNativeObservedCostFromVariantState(state) {
1073
+ return getFiniteNumberAtPath(state, ["result", "totalCostUsd"]) ?? getFiniteNumberAtPath(state, ["result", "total_cost_usd"]) ?? getFiniteNumberAtPath(state, ["result", "totalCost"]) ?? getFiniteNumberAtPath(state, ["result", "total_cost"]) ?? null;
1074
+ }
1075
+ function extractCostMetricsAmountFromVariantState(state) {
1076
+ return getFiniteNumberAtPath(state, ["costMetrics", "totalCostUsd"]) ?? getFiniteNumberAtPath(state, ["costMetrics", "totalCost"]) ?? null;
1077
+ }
1078
+ function resolveCostMetricsUnavailableReason(costMetrics) {
1079
+ if (!costMetrics || typeof costMetrics !== "object") {
1080
+ return void 0;
1081
+ }
1082
+ const usageReason = readUsageUnavailableReason({ costMetrics });
1083
+ if (usageReason !== void 0) {
1084
+ return usageReason;
1085
+ }
1086
+ const reason = readCostMetricsUnavailableReason(
1087
+ costMetrics
1088
+ );
1089
+ if (reason !== void 0) {
1090
+ return reason;
1091
+ }
1092
+ if (costMetrics.pricingStatus === "error") {
1093
+ return "pricing_unavailable";
1094
+ }
1095
+ return void 0;
1096
+ }
1097
+ function markCandidateCostUnavailable(candidate, reason) {
1098
+ candidate.cost = 0;
1099
+ candidate.costUnavailableReason = reason;
1100
+ }
1101
+ async function hydrateCandidateCostsFromTelemetry(taskId, candidates, stageIdForLogs, verbose) {
1102
+ await Promise.all(
1103
+ candidates.map(async (candidate) => {
1104
+ if (!candidate.success) return;
1105
+ if (typeof candidate.cost === "number" && Number.isFinite(candidate.cost) && candidate.costUnavailableReason === void 0) {
1106
+ return;
1107
+ }
1108
+ if (typeof candidate.cost === "number" && Number.isFinite(candidate.cost) && candidate.cost > 0) {
1109
+ candidate.costUnavailableReason = void 0;
1110
+ return;
1111
+ }
1112
+ const provider = candidate.variant.provider;
1113
+ if (!provider) return;
1114
+ if (!providerReportsUsage(provider)) {
1115
+ candidate.costUnavailableReason = candidate.costUnavailableReason ?? "provider_not_reported";
1116
+ return;
1117
+ }
1118
+ const variantStatePath = getVariantTelemetryStatePath(
1119
+ taskId,
1120
+ provider,
1121
+ candidate.variant.model,
1122
+ candidate.variant.executionMode,
1123
+ normalizeReasoningEffortInput(candidate.variant.reasoning)
1124
+ );
1125
+ try {
1126
+ const raw = await fs.readFile(variantStatePath, "utf8");
1127
+ const state = JSON.parse(raw);
1128
+ const nativeObservedCost = extractNativeObservedCostFromVariantState(state);
1129
+ const metricsCost = extractCostMetricsAmountFromVariantState(state);
1130
+ const costMetrics = getValueAtPath(state, ["costMetrics"]);
1131
+ const unavailableReason = resolveCostMetricsUnavailableReason(costMetrics);
1132
+ if (typeof nativeObservedCost === "number") {
1133
+ candidate.cost = nativeObservedCost;
1134
+ candidate.costUnavailableReason = void 0;
1135
+ return;
1136
+ }
1137
+ if (typeof metricsCost === "number" && metricsCost > 0) {
1138
+ candidate.cost = metricsCost;
1139
+ candidate.costUnavailableReason = void 0;
1140
+ return;
1141
+ }
1142
+ if (unavailableReason !== void 0) {
1143
+ markCandidateCostUnavailable(candidate, unavailableReason);
1144
+ return;
1145
+ }
1146
+ if (typeof metricsCost === "number") {
1147
+ candidate.cost = metricsCost;
1148
+ candidate.costUnavailableReason = void 0;
1149
+ return;
1150
+ }
1151
+ markCandidateCostUnavailable(
1152
+ candidate,
1153
+ candidate.costUnavailableReason ?? "provider_not_reported"
1154
+ );
1155
+ } catch {
1156
+ markCandidateCostUnavailable(
1157
+ candidate,
1158
+ candidate.costUnavailableReason ?? "provider_not_reported"
1159
+ );
1160
+ }
1161
+ if (verbose) {
1162
+ console.warn(
1163
+ chalk.yellow(
1164
+ ` [${stageIdForLogs}] Unable to hydrate cost from telemetry for ${formatCompetitionCandidateVariantDisplay(candidate)}`
1165
+ )
1166
+ );
1167
+ }
1168
+ })
1169
+ );
1170
+ }
1171
+ function variantSpecToConfig(spec, executionIntent, stage, defaultProviderExecutionTransport, executionContract) {
1172
+ const model = spec.model ?? applyFlywheelModelDefaults(stage, spec.provider);
1173
+ const modelReasoningEffort = normalizeReasoningEffortInput(spec.reasoning);
1174
+ return {
1175
+ provider: spec.provider,
1176
+ model,
1177
+ ...modelReasoningEffort ? { modelReasoningEffort } : {},
1178
+ // Inert slot: variant strategies were removed as a behavioral axis (ADR-025).
1179
+ // A `strategy` in workflow YAML is accepted and ignored.
1180
+ ...executionContract ? { promptContractOverride: executionContract } : {},
1181
+ executionMode: "local",
1182
+ // Competition stages always run locally
1183
+ executionIntent,
1184
+ ...spec.providerExecutionTransport ?? stage.providerExecutionTransport ?? defaultProviderExecutionTransport ? {
1185
+ executionTransport: spec.providerExecutionTransport ?? stage.providerExecutionTransport ?? defaultProviderExecutionTransport
1186
+ } : {},
1187
+ allowEmptyResults: stage.allowEmptyResults,
1188
+ isBasicCompetition: true,
1189
+ // Don't auto-commit - flywheel manages commits
1190
+ disableAutoCommit: true,
1191
+ structuredFileTargets: computeExpectedAllowlist(stage)
1192
+ };
1193
+ }
1194
+ function assertNoDuplicateVariantSpecs(variants, options) {
1195
+ if (options.allowDuplicates) return;
1196
+ const keyToVariants = /* @__PURE__ */ new Map();
1197
+ for (const variant of variants) {
1198
+ const modelKey = variant.model ?? "default";
1199
+ const effortKey = variant.modelReasoningEffort ?? "default";
1200
+ const key = `${variant.provider}:${modelKey}:${effortKey}`;
1201
+ const existing = keyToVariants.get(key);
1202
+ if (existing) {
1203
+ existing.push(variant);
1204
+ } else {
1205
+ keyToVariants.set(key, [variant]);
1206
+ }
1207
+ }
1208
+ const duplicates = [...keyToVariants.entries()].filter(([, group]) => group.length > 1);
1209
+ if (duplicates.length === 0) return;
1210
+ const details = duplicates.map(([, group]) => {
1211
+ const variant = group[0];
1212
+ const label = [
1213
+ variant?.provider ?? "unknown",
1214
+ variant?.model ?? "(default)",
1215
+ variant?.modelReasoningEffort ? `effort-${variant.modelReasoningEffort}` : void 0
1216
+ ].filter((part) => typeof part === "string" && part.length > 0).join(":");
1217
+ return ` \u2022 ${label} \u2014 appears ${group.length} times`;
1218
+ }).join("\n");
1219
+ throw new Error(
1220
+ `Duplicate variant specs detected in competition stage
1221
+
1222
+ What this means:
1223
+ Competition stages should compare different variants, not the same variant
1224
+ to itself. Duplicates are identified by provider+model+reasoningEffort identity.
1225
+
1226
+ Duplicate variants found:
1227
+ ${details}
1228
+
1229
+ How to fix:
1230
+ 1. Remove duplicate entries from your competition.variants configuration
1231
+ 2. Or change the model or reasoning effort to make variants distinct
1232
+ 3. Or use different providers (e.g., claude + codex)
1233
+
1234
+ Escape hatch (not recommended):
1235
+ Set competition.allowDuplicateVariantSpecs: true in your stage config
1236
+
1237
+ Tip: This guard prevents wasted compute on redundant comparisons.`
1238
+ );
1239
+ }
1240
+ function resolveCompetitionExecutionIntent(stage) {
1241
+ return resolveProviderExecutionIntentFromStage(stage);
1242
+ }
1243
+ function getVariantDurationMs(result) {
1244
+ if (typeof result.executionDurationMs === "number" && Number.isFinite(result.executionDurationMs)) {
1245
+ return result.executionDurationMs;
1246
+ }
1247
+ if (typeof result.totalDurationSec === "number" && Number.isFinite(result.totalDurationSec)) {
1248
+ return result.totalDurationSec * 1e3;
1249
+ }
1250
+ return Math.max(0, Math.round((result.duration ?? 0) * 1e3));
1251
+ }
1252
+ function extractChangedFiles(result) {
1253
+ const statusLines = result.worktreeSummary?.statusLines;
1254
+ if (!Array.isArray(statusLines) || statusLines.length === 0) return void 0;
1255
+ const candidates = statusLines.map((line) => extractChangedFileFromStatusLine(String(line))).filter((v) => Boolean(v));
1256
+ const trackedRoots = result.retainedWorktreePath && candidates.some(isUnderRootToolOutputDir) ? readTrackedToolOutputRootsSync(result.retainedWorktreePath, result.baselineRef || "HEAD") : void 0;
1257
+ const files = candidates.filter((f) => !shouldExcludeFile(f, trackedRoots));
1258
+ return files.length > 0 ? files : void 0;
1259
+ }
1260
+ function normalizeCoveragePath(value) {
1261
+ return value.replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+/g, "/");
1262
+ }
1263
+ function tryGetPct(metric) {
1264
+ if (!metric || typeof metric !== "object") return null;
1265
+ const pct = metric.pct;
1266
+ return typeof pct === "number" && Number.isFinite(pct) ? pct : null;
1267
+ }
1268
+ function getCoveragePctForEntry(entry) {
1269
+ if (!entry || typeof entry !== "object") return null;
1270
+ const record = entry;
1271
+ return tryGetPct(record.lines) ?? tryGetPct(record.statements) ?? tryGetPct(record.functions) ?? tryGetPct(record.branches) ?? null;
1272
+ }
1273
+ function getTotalLinesForEntry(entry) {
1274
+ if (!entry || typeof entry !== "object") return null;
1275
+ const record = entry;
1276
+ const lines = record.lines;
1277
+ if (!lines || typeof lines !== "object") return null;
1278
+ const total = lines.total;
1279
+ return typeof total === "number" && Number.isFinite(total) ? total : null;
1280
+ }
1281
+ async function loadCoverageSummaryJson(worktreePath, summaryPath, options = {}) {
1282
+ try {
1283
+ const resolved = path.join(worktreePath, summaryPath);
1284
+ if (typeof options.minMtimeMs === "number") {
1285
+ const stats = await fs.stat(resolved);
1286
+ if (stats.mtimeMs < options.minMtimeMs) return null;
1287
+ }
1288
+ const raw = await fs.readFile(resolved, "utf8");
1289
+ const parsed = JSON.parse(raw);
1290
+ if (!parsed || typeof parsed !== "object") return null;
1291
+ return parsed;
1292
+ } catch {
1293
+ return null;
1294
+ }
1295
+ }
1296
+ function findCoverageEntry(summary, target) {
1297
+ const normalizedTarget = normalizeCoveragePath(target);
1298
+ const direct = summary[normalizedTarget];
1299
+ if (direct && typeof direct === "object") {
1300
+ return direct;
1301
+ }
1302
+ const candidates = [];
1303
+ for (const [key, value] of Object.entries(summary)) {
1304
+ if (key === "total") continue;
1305
+ if (!value || typeof value !== "object") continue;
1306
+ const normalizedKey = normalizeCoveragePath(key);
1307
+ if (normalizedKey === normalizedTarget || normalizedKey.endsWith(`/${normalizedTarget}`)) {
1308
+ candidates.push({ key, entry: value });
1309
+ }
1310
+ }
1311
+ if (candidates.length === 0) return null;
1312
+ candidates.sort((a, b) => a.key.length - b.key.length);
1313
+ return candidates[0]?.entry ?? null;
1314
+ }
1315
+ function computeCoverageStatsForTargets(summary, targets) {
1316
+ const byTarget = {};
1317
+ const linesByTarget = {};
1318
+ const missingTargets = [];
1319
+ const pcts = [];
1320
+ const lineCounts = [];
1321
+ for (const target of targets) {
1322
+ if (!summary) {
1323
+ byTarget[target] = null;
1324
+ linesByTarget[target] = null;
1325
+ missingTargets.push(target);
1326
+ continue;
1327
+ }
1328
+ const entry = findCoverageEntry(summary, target);
1329
+ const pct = entry ? getCoveragePctForEntry(entry) : null;
1330
+ const lines = entry ? getTotalLinesForEntry(entry) : null;
1331
+ byTarget[target] = pct;
1332
+ linesByTarget[target] = lines;
1333
+ if (pct === null) {
1334
+ missingTargets.push(target);
1335
+ } else {
1336
+ pcts.push(pct);
1337
+ }
1338
+ if (typeof lines === "number") {
1339
+ lineCounts.push(lines);
1340
+ }
1341
+ }
1342
+ if (pcts.length === 0) {
1343
+ return {
1344
+ byTarget,
1345
+ linesByTarget,
1346
+ avgPct: null,
1347
+ minPct: null,
1348
+ totalLines: null,
1349
+ maxTargetLines: null,
1350
+ missingTargets
1351
+ };
1352
+ }
1353
+ const avgRaw = pcts.reduce((sum, v) => sum + v, 0) / pcts.length;
1354
+ const minRaw = Math.min(...pcts);
1355
+ const round2 = (v) => Math.round(v * 100) / 100;
1356
+ const totalLines = lineCounts.length > 0 ? lineCounts.reduce((sum, v) => sum + v, 0) : null;
1357
+ const maxTargetLines = lineCounts.length > 0 ? Math.max(...lineCounts) : null;
1358
+ return {
1359
+ byTarget,
1360
+ linesByTarget,
1361
+ avgPct: round2(avgRaw),
1362
+ minPct: round2(minRaw),
1363
+ totalLines,
1364
+ maxTargetLines,
1365
+ missingTargets
1366
+ };
1367
+ }
1368
+ function parseBaselineLinesPctFromPrompt(prompt) {
1369
+ const match = prompt.match(/Baseline:\s*lines\s+(\d+(?:\.\d+)?)%/i);
1370
+ if (!match) return null;
1371
+ const value = Number.parseFloat(match[1] ?? "");
1372
+ return Number.isFinite(value) ? value : null;
1373
+ }
1374
+ function resolveAutoCoverageMode(params) {
1375
+ const { maxTargetLines, largeFileLineThreshold, baselineAvgPct, threshold, minDeltaPct } = params;
1376
+ if (typeof maxTargetLines === "number" && maxTargetLines > largeFileLineThreshold) {
1377
+ return "delta";
1378
+ }
1379
+ if (typeof threshold === "number" && typeof baselineAvgPct === "number" && threshold - baselineAvgPct > minDeltaPct) {
1380
+ return "delta";
1381
+ }
1382
+ return "absolute";
1383
+ }
1384
+ function computeExpectedAllowlist(stage) {
1385
+ return collectDeclaredStageTargets(stage);
1386
+ }
1387
+ function computeCompetitionDrift(candidates, expectedAllowlist, mode) {
1388
+ const allDeliveredFiles = /* @__PURE__ */ new Set();
1389
+ const allViolations = /* @__PURE__ */ new Set();
1390
+ for (const candidate of candidates) {
1391
+ if (!candidate.success || !candidate.changedFiles) continue;
1392
+ const changedFiles = filterWorktreeRunSentinelPaths(candidate.changedFiles);
1393
+ for (const file of changedFiles) {
1394
+ allDeliveredFiles.add(file);
1395
+ }
1396
+ const decision = decideStageChangeScope({
1397
+ changedPaths: changedFiles,
1398
+ explicitScope: expectedAllowlist,
1399
+ allowlistMode: mode,
1400
+ mutationOrigin: "provider"
1401
+ });
1402
+ for (const violation of decision.allowlistViolations) {
1403
+ allViolations.add(violation);
1404
+ }
1405
+ }
1406
+ const deliveredFiles = [...allDeliveredFiles];
1407
+ const violations = [...allViolations];
1408
+ const hasDrift = violations.length > 0;
1409
+ const lines = [];
1410
+ lines.push(`Competition stage (${candidates.length} candidates)`);
1411
+ lines.push(`Mode: ${mode}`);
1412
+ lines.push(`Total delivered files: ${deliveredFiles.length}`);
1413
+ lines.push(`Expected allowlist entries: ${expectedAllowlist.length}`);
1414
+ if (hasDrift) {
1415
+ lines.push(`Drift: ${violations.length} file(s) outside allowlist`);
1416
+ for (const v of violations.slice(0, 3)) {
1417
+ lines.push(` - ${v}`);
1418
+ }
1419
+ if (violations.length > 3) {
1420
+ lines.push(` ... and ${violations.length - 3} more`);
1421
+ }
1422
+ } else {
1423
+ lines.push("Drift: none");
1424
+ }
1425
+ return {
1426
+ mode,
1427
+ deliveredFiles,
1428
+ expectedFiles: expectedAllowlist,
1429
+ violations,
1430
+ hasDrift,
1431
+ summary: lines.join("\n")
1432
+ };
1433
+ }
1434
+ var DEFAULT_COHERENCE_THRESHOLD = 0.3;
1435
+ function jaccardSimilarity(setA, setB) {
1436
+ if (setA.size === 0 && setB.size === 0) return 1;
1437
+ const intersection = new Set([...setA].filter((x) => setB.has(x)));
1438
+ const union = /* @__PURE__ */ new Set([...setA, ...setB]);
1439
+ return union.size > 0 ? intersection.size / union.size : 0;
1440
+ }
1441
+ function computeCoherenceMetrics(candidates, threshold = DEFAULT_COHERENCE_THRESHOLD, expectedAllowlist) {
1442
+ const allowlist = (expectedAllowlist ?? []).filter((v) => typeof v === "string" && v.length > 0);
1443
+ const hasAllowlist = allowlist.length > 0;
1444
+ const isAllowlisted = (filePath) => {
1445
+ const normalized = filePath.replace(/\\/g, "/");
1446
+ for (const entry of allowlist) {
1447
+ const rule = entry.replace(/\\/g, "/");
1448
+ if (rule.endsWith("/")) {
1449
+ if (normalized.startsWith(rule)) return true;
1450
+ } else if (normalized === rule) {
1451
+ return true;
1452
+ }
1453
+ }
1454
+ return false;
1455
+ };
1456
+ const filterCandidateFiles = (files) => {
1457
+ if (!files) return void 0;
1458
+ if (!hasAllowlist) return files;
1459
+ const filtered = files.filter(isAllowlisted);
1460
+ return filtered.length > 0 ? filtered : void 0;
1461
+ };
1462
+ const successfulCandidates = candidates.filter(
1463
+ (c) => c.success && filterCandidateFiles(c.changedFiles)?.length
1464
+ );
1465
+ if (successfulCandidates.length < 2) {
1466
+ return {
1467
+ pairwiseSimilarity: {},
1468
+ averageSimilarity: 1,
1469
+ // Single candidate = coherent with itself
1470
+ isCoherent: true,
1471
+ coherenceThreshold: threshold
1472
+ };
1473
+ }
1474
+ const fileSets = /* @__PURE__ */ new Map();
1475
+ for (const [index, candidate] of successfulCandidates.entries()) {
1476
+ const provider = candidate.variant.provider;
1477
+ const model = candidate.variant.model ?? "";
1478
+ const key = `${provider}:${model}:${index}`;
1479
+ fileSets.set(key, new Set(filterCandidateFiles(candidate.changedFiles) || []));
1480
+ }
1481
+ const pairwiseSimilarity = {};
1482
+ const candidateKeys = Array.from(fileSets.keys());
1483
+ let totalSimilarity = 0;
1484
+ let pairCount = 0;
1485
+ for (let i = 0; i < candidateKeys.length; i++) {
1486
+ for (let j = i + 1; j < candidateKeys.length; j++) {
1487
+ const keyA = candidateKeys[i] ?? "";
1488
+ const keyB = candidateKeys[j] ?? "";
1489
+ const setA = fileSets.get(keyA);
1490
+ const setB = fileSets.get(keyB);
1491
+ if (!setA || !setB) continue;
1492
+ const similarity = jaccardSimilarity(setA, setB);
1493
+ const pairKey = `${keyA}|${keyB}`;
1494
+ pairwiseSimilarity[pairKey] = Math.round(similarity * 100) / 100;
1495
+ totalSimilarity += similarity;
1496
+ pairCount++;
1497
+ }
1498
+ }
1499
+ const averageSimilarity = pairCount > 0 ? totalSimilarity / pairCount : 1;
1500
+ const isCoherent = averageSimilarity >= threshold;
1501
+ const allFileSets = Array.from(fileSets.values());
1502
+ const allFiles = new Set(allFileSets.flatMap((s) => [...s]));
1503
+ const commonFiles = [...allFiles].filter((file) => allFileSets.every((set) => set.has(file)));
1504
+ const uniqueFiles = {};
1505
+ for (const [candidateKey, files] of fileSets) {
1506
+ const unique = [...files].filter(
1507
+ (file) => !Array.from(fileSets.entries()).filter(([k]) => k !== candidateKey).some(([, otherSet]) => otherSet.has(file))
1508
+ );
1509
+ if (unique.length > 0) {
1510
+ uniqueFiles[candidateKey] = unique;
1511
+ }
1512
+ }
1513
+ return {
1514
+ pairwiseSimilarity,
1515
+ averageSimilarity: Math.round(averageSimilarity * 100) / 100,
1516
+ isCoherent,
1517
+ coherenceThreshold: threshold,
1518
+ fileOverlap: {
1519
+ commonFiles,
1520
+ uniqueFiles
1521
+ }
1522
+ };
1523
+ }
1524
+ function resolveCandidateCompletenessFallback(result) {
1525
+ const typed = resolveTypedCompletenessAuthority(result);
1526
+ if (typed.present) {
1527
+ return typed.usable ? typed.score : -1;
1528
+ }
1529
+ return result.completeness;
1530
+ }
1531
+ function variantResultToCandidate(spec, result) {
1532
+ if (!result) {
1533
+ return {
1534
+ variant: spec,
1535
+ success: false,
1536
+ error: "Variant not found in results",
1537
+ cost: 0,
1538
+ costUnavailableReason: "provider_not_reported",
1539
+ durationMs: 0
1540
+ };
1541
+ }
1542
+ const variantEvaluation = result.judgeEvaluation?.evaluations?.find(
1543
+ (e) => e.variant === result.variant
1544
+ );
1545
+ const aiJudgeScore = variantEvaluation?.qualityScore != null ? Number(variantEvaluation.qualityScore) : void 0;
1546
+ const score = aiJudgeScore ?? result.judgeScore ?? resolveCandidateCompletenessFallback(result);
1547
+ const feedback = generateCandidateFeedback(variantEvaluation, result);
1548
+ const testStatus = result.testStatus;
1549
+ const testsExecuted = result.testsExecuted;
1550
+ const nativeObservedCost = getFiniteNumberAtPath(result, ["result", "totalCostUsd"]) ?? getFiniteNumberAtPath(result, ["result", "total_cost_usd"]) ?? getFiniteNumberAtPath(result, ["result", "totalCost"]) ?? getFiniteNumberAtPath(result, ["totalCostUsd"]);
1551
+ const metricsCost = getFiniteNumberAtPath(result.costMetrics, ["totalCost"]) ?? getFiniteNumberAtPath(result.costMetrics, ["totalCostUsd"]);
1552
+ const metricsUnavailableReason = resolveCostMetricsUnavailableReason(result.costMetrics);
1553
+ let cost;
1554
+ let costUnavailableReason;
1555
+ if (typeof nativeObservedCost === "number") {
1556
+ cost = nativeObservedCost;
1557
+ costUnavailableReason = void 0;
1558
+ } else if (typeof metricsCost === "number" && metricsCost > 0) {
1559
+ cost = metricsCost;
1560
+ costUnavailableReason = void 0;
1561
+ } else if (metricsUnavailableReason !== void 0) {
1562
+ cost = 0;
1563
+ costUnavailableReason = metricsUnavailableReason;
1564
+ } else if (typeof metricsCost === "number") {
1565
+ cost = metricsCost;
1566
+ costUnavailableReason = void 0;
1567
+ } else {
1568
+ cost = 0;
1569
+ costUnavailableReason = "provider_not_reported";
1570
+ }
1571
+ return {
1572
+ variant: spec,
1573
+ success: result.success,
1574
+ error: result.error?.message,
1575
+ ...isProviderInvocationFailure(result) ? { providerFailed: true } : {},
1576
+ score,
1577
+ feedback,
1578
+ cost,
1579
+ costUnavailableReason,
1580
+ durationMs: getVariantDurationMs(result),
1581
+ worktreePath: result.retainedWorktreePath,
1582
+ changedFiles: extractChangedFiles(result),
1583
+ changeTrackingAvailable: resultHasChangeTracking(result),
1584
+ testStatus,
1585
+ testsExecuted,
1586
+ ...repairOutcomeCanSupersedeRawTouchedFailure(result) ? { repairedTestStatus: deriveVariantOutcome(result).verification.testStatus } : {},
1587
+ mergeInvariantValidation: result.mergeInvariantValidation
1588
+ };
1589
+ }
1590
+ function resolveCompetitionCostAggregate(candidates) {
1591
+ let sum = 0;
1592
+ let firstExplicitReason;
1593
+ let sawPricingUnavailable = false;
1594
+ let sawUnavailable = false;
1595
+ for (const candidate of candidates) {
1596
+ if (candidate.costUnavailableReason !== void 0) {
1597
+ sawUnavailable = true;
1598
+ if (candidate.costUnavailableReason === "pricing_unavailable") {
1599
+ sawPricingUnavailable = true;
1600
+ } else if (firstExplicitReason === void 0) {
1601
+ firstExplicitReason = candidate.costUnavailableReason;
1602
+ }
1603
+ sum = 0;
1604
+ continue;
1605
+ }
1606
+ if (typeof candidate.cost !== "number" || !Number.isFinite(candidate.cost)) {
1607
+ sawUnavailable = true;
1608
+ if (firstExplicitReason === void 0) {
1609
+ firstExplicitReason = "provider_not_reported";
1610
+ }
1611
+ sum = 0;
1612
+ continue;
1613
+ }
1614
+ if (!sawUnavailable) {
1615
+ sum += candidate.cost;
1616
+ }
1617
+ }
1618
+ if (sawUnavailable) {
1619
+ return {
1620
+ cost: 0,
1621
+ costUnavailableReason: sawPricingUnavailable ? "pricing_unavailable" : firstExplicitReason ?? "provider_not_reported"
1622
+ };
1623
+ }
1624
+ return { cost: sum };
1625
+ }
1626
+ function isJudgeType(value) {
1627
+ return value === "ai" || value === "multi-lens";
1628
+ }
1629
+ function buildMultiJudgeEvidenceBlock(args) {
1630
+ const synthesisContext = args.judgeResult?.synthesisContext;
1631
+ if (!synthesisContext && !args.matrixRan) {
1632
+ return void 0;
1633
+ }
1634
+ const judgesWithVerdicts = synthesisContext?.judgeResults ? Object.entries(synthesisContext.judgeResults).filter(([, result]) => result !== void 0 && result !== null).map(([judgeId]) => judgeId) : [];
1635
+ return {
1636
+ selectedJudge: synthesisContext?.selectedJudge,
1637
+ judgeRunRequested: args.judgeRunRequested ?? [],
1638
+ judgesWithVerdicts,
1639
+ allJudgesAgree: synthesisContext?.disagreement?.allAgree,
1640
+ matrixAuthority: args.matrixAuthority,
1641
+ matrixRan: args.matrixRan,
1642
+ matrixProfileAgreement: args.matrixProfileAgreement,
1643
+ matrixNonSelectionReasons: args.matrixNonSelectionReasons && args.matrixNonSelectionReasons.length > 0 ? args.matrixNonSelectionReasons : void 0
1644
+ };
1645
+ }
1646
+ function recordDeterministicTestSignalObservation(candidates, verbose) {
1647
+ const hasVerifiedPassingCandidate = candidates.some(
1648
+ (c) => c.success && c.testsExecuted !== void 0 && c.testStatus === "passed"
1649
+ );
1650
+ if (!hasVerifiedPassingCandidate) return;
1651
+ for (const candidate of candidates) {
1652
+ if (!candidate.success) continue;
1653
+ if (!candidate.testsExecuted) continue;
1654
+ const status = candidate.testStatus ?? "not_run";
1655
+ if (status !== "failed" && status !== "error" && status !== "timeout") continue;
1656
+ const note = `Verified failing test observation recorded (testStatus=${status}).`;
1657
+ candidate.feedback = candidate.feedback ? `${note}
1658
+
1659
+ ${candidate.feedback}` : note;
1660
+ if (verbose) {
1661
+ const id = formatCompetitionCandidateVariantDisplay(candidate);
1662
+ console.log(
1663
+ chalk.yellow(` Test observation: ${id} retained score ${candidate.score ?? 0}`)
1664
+ );
1665
+ }
1666
+ }
1667
+ }
1668
+ function variantResultDiagnosticId(result) {
1669
+ const provider = result.provider ?? "unknown";
1670
+ const model = result.model ?? "";
1671
+ const variant = result.variant ? ` (${result.variant})` : "";
1672
+ return `${provider}:${model}${variant}`;
1673
+ }
1674
+ function buildWinnerInfoFromJudgeVerdict(candidates, judgedWinner, judgeVisibleCandidates) {
1675
+ const rankedPool = judgeVisibleCandidates && judgeVisibleCandidates.length > 0 ? judgeVisibleCandidates : candidates.filter((c) => c.success);
1676
+ if (rankedPool.length === 0) {
1677
+ return {
1678
+ winner: null,
1679
+ noWinnerReason: "all-failed",
1680
+ wasTie: false,
1681
+ rankings: []
1682
+ };
1683
+ }
1684
+ const ranked = [...rankedPool].sort((a, b) => {
1685
+ const scoreA = Number(a.score ?? 0);
1686
+ const scoreB = Number(b.score ?? 0);
1687
+ if (scoreB !== scoreA) return scoreB - scoreA;
1688
+ return variantIdForSpec(a.variant).localeCompare(variantIdForSpec(b.variant));
1689
+ });
1690
+ const rankings = ranked.map((c, i) => ({
1691
+ variant: c.variant,
1692
+ score: c.score ?? 0,
1693
+ rank: i + 1
1694
+ }));
1695
+ const topScore = Number(ranked[0]?.score ?? 0);
1696
+ const tiedAtTop = ranked.filter((c) => Number(c.score ?? 0) === topScore);
1697
+ const wasTie = tiedAtTop.length > 1;
1698
+ if (!judgedWinner) {
1699
+ return {
1700
+ winner: null,
1701
+ wasTie,
1702
+ rankings
1703
+ };
1704
+ }
1705
+ const winner = findCandidateForVariantResult(candidates, judgedWinner);
1706
+ if (!winner) {
1707
+ return {
1708
+ winner: null,
1709
+ wasTie,
1710
+ rankings,
1711
+ noWinnerReason: "judge-error",
1712
+ noWinnerDiagnostic: `AI judge selected an unmatched winner (${variantResultDiagnosticId(
1713
+ judgedWinner
1714
+ )}); judge-visible candidates: ${rankedPool.map((candidate) => variantIdForSpec(candidate.variant)).join(", ")}`
1715
+ };
1716
+ }
1717
+ return {
1718
+ winner,
1719
+ wasTie,
1720
+ rankings
1721
+ };
1722
+ }
1723
+ function attachGateObservationsToVariantResult(result, candidate) {
1724
+ const candidateFindings = candidate.verification?.findings ?? [];
1725
+ const gateError = candidate.success === false ? candidate.error : void 0;
1726
+ if (candidateFindings.length === 0 && !gateError) {
1727
+ return result;
1728
+ }
1729
+ const existingFindings = result.verification?.findings ?? [];
1730
+ const mergedFindings = [...existingFindings];
1731
+ for (const finding of candidateFindings) {
1732
+ const mapped = toCoreVerificationFinding(finding);
1733
+ const alreadyPresent = mergedFindings.some(
1734
+ (existing) => existing.kind === mapped.kind && existing.command === mapped.command && existing.exitCode === mapped.exitCode
1735
+ );
1736
+ if (!alreadyPresent) {
1737
+ mergedFindings.push(mapped);
1738
+ }
1739
+ }
1740
+ if (gateError && mergedFindings.length === existingFindings.length) {
1741
+ mergedFindings.push({
1742
+ kind: "other",
1743
+ command: "candidate-gate",
1744
+ exitCode: 1,
1745
+ severity: "error",
1746
+ outputTail: gateError
1747
+ });
1748
+ }
1749
+ const verificationPassed = candidate.verification?.passed === false ? false : gateError ? false : result.verification?.passed ?? true;
1750
+ result.verification = {
1751
+ ...result.verification ?? {},
1752
+ passed: verificationPassed,
1753
+ findings: mergedFindings
1754
+ };
1755
+ return result;
1756
+ }
1757
+ function buildJudgeVisibleVariantResults(finishedCandidates, basicVariants) {
1758
+ const results = [];
1759
+ for (const candidate of finishedCandidates) {
1760
+ const matching = matchVariantResult(candidate.variant, basicVariants);
1761
+ if (!matching) continue;
1762
+ results.push(attachGateObservationsToVariantResult(matching, candidate));
1763
+ }
1764
+ return results;
1765
+ }
1766
+ function determineWinner(candidates, config, expectedAllowlist) {
1767
+ const SCORE_COLLISION_DECIMALS = 6;
1768
+ const SCORE_COLLISION_MULTIPLIER = 10 ** SCORE_COLLISION_DECIMALS;
1769
+ const quantizeScore = (score) => {
1770
+ if (!Number.isFinite(score)) return 0;
1771
+ return Math.round(score * SCORE_COLLISION_MULTIPLIER) / SCORE_COLLISION_MULTIPLIER;
1772
+ };
1773
+ const variantIdFor = variantIdForSpec;
1774
+ const buildCollisionReport = (args) => {
1775
+ const tiedAtTop2 = [...args.tiedAtTop].map((c) => {
1776
+ const raw = Number(c.score ?? 0);
1777
+ const q = quantizeScore(raw);
1778
+ return { candidate: c, scoreRaw: raw, scoreQuantized: q, id: variantIdFor(c.variant) };
1779
+ }).sort((a, b) => a.id.localeCompare(b.id)).map((x) => ({
1780
+ variant: x.candidate.variant,
1781
+ scoreRaw: x.scoreRaw,
1782
+ scoreQuantized: x.scoreQuantized
1783
+ }));
1784
+ const otherCollisionGroups2 = [...args.otherCollisionGroups].sort((a, b) => b.scoreQuantized - a.scoreQuantized).map((group) => ({
1785
+ scoreQuantized: group.scoreQuantized,
1786
+ 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 }))
1787
+ }));
1788
+ return {
1789
+ precisionDecimals: SCORE_COLLISION_DECIMALS,
1790
+ quantization: "round",
1791
+ topScoreRaw: args.topScoreRaw,
1792
+ topScoreQuantized: args.topScoreQuantized,
1793
+ successfulCandidateCount: args.successfulCount,
1794
+ collisionGroupCount: args.collisionGroupsAll.length,
1795
+ collisionPairCount: args.collisionGroupsAll.reduce(
1796
+ (sum, g) => sum + g.entries.length * (g.entries.length - 1) / 2,
1797
+ 0
1798
+ ),
1799
+ tiedAtTopPairCount: args.tiedAtTop.length * (args.tiedAtTop.length - 1) / 2,
1800
+ tiedAtTop: tiedAtTop2,
1801
+ otherCollisionGroups: otherCollisionGroups2,
1802
+ applied: args.applied
1803
+ };
1804
+ };
1805
+ const computeCollisionGroups = (rankedSuccessful) => {
1806
+ const groups = /* @__PURE__ */ new Map();
1807
+ for (const candidate of rankedSuccessful) {
1808
+ const scoreRaw = Number(candidate.score ?? 0);
1809
+ const scoreQuantized = quantizeScore(scoreRaw);
1810
+ const existing = groups.get(scoreQuantized);
1811
+ if (existing) {
1812
+ existing.push({ variant: candidate.variant, scoreRaw });
1813
+ } else {
1814
+ groups.set(scoreQuantized, [{ variant: candidate.variant, scoreRaw }]);
1815
+ }
1816
+ }
1817
+ const out = [];
1818
+ for (const [scoreQuantized, entries] of groups.entries()) {
1819
+ if (entries.length < 2) continue;
1820
+ out.push({ scoreQuantized, entries });
1821
+ }
1822
+ return out;
1823
+ };
1824
+ const successfulCandidates = candidates.filter((c) => c.success);
1825
+ const threshold = config.judgeConfig?.threshold ?? 0;
1826
+ const allowBelowThresholdWinner = config.judgeConfig?.allowBelowThresholdWinner ?? true;
1827
+ if (successfulCandidates.length === 0) {
1828
+ return {
1829
+ winner: null,
1830
+ noWinnerReason: "all-failed",
1831
+ wasTie: false,
1832
+ rankings: []
1833
+ };
1834
+ }
1835
+ const cleanCandidates = successfulCandidates.filter(
1836
+ (c) => !c.verification || c.verification.passed
1837
+ );
1838
+ const candidatesWithFindings = successfulCandidates.filter(
1839
+ (c) => c.verification && !c.verification.passed
1840
+ );
1841
+ const candidatesToRank = cleanCandidates.length > 0 ? cleanCandidates : successfulCandidates;
1842
+ const ranked = [...candidatesToRank].sort((a, b) => {
1843
+ const scoreA = Number(a.score ?? 0);
1844
+ const scoreB = Number(b.score ?? 0);
1845
+ const qa = quantizeScore(scoreA);
1846
+ const qb = quantizeScore(scoreB);
1847
+ if (qb !== qa) return qb - qa;
1848
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1849
+ });
1850
+ const rankings = ranked.map((c, i) => ({
1851
+ variant: c.variant,
1852
+ score: c.score ?? 0,
1853
+ rank: i + 1
1854
+ }));
1855
+ const topScore = Number(ranked[0]?.score ?? 0);
1856
+ const topScoreQuantized = quantizeScore(topScore);
1857
+ const tiedAtTop = ranked.filter((c) => quantizeScore(Number(c.score ?? 0)) === topScoreQuantized);
1858
+ const wasTie = tiedAtTop.length > 1;
1859
+ const collisionGroups = computeCollisionGroups(ranked);
1860
+ const otherCollisionGroups = collisionGroups.filter((g) => g.scoreQuantized !== topScoreQuantized).slice(0, 10);
1861
+ const scoreCollisionReportBase = wasTie || otherCollisionGroups.length > 0 ? {
1862
+ ranked,
1863
+ successfulCount: candidatesToRank.length,
1864
+ collisionGroupsAll: collisionGroups,
1865
+ topScoreRaw: topScore,
1866
+ topScoreQuantized,
1867
+ tiedAtTop,
1868
+ otherCollisionGroups
1869
+ } : null;
1870
+ if (wasTie) {
1871
+ if (config.applyWinner) {
1872
+ const tieBreakerConfig = config.tieBreaker ?? (config.candidateGate?.coverage ? { mode: "prefer-low-drift-then-diff" } : { mode: "prefer-first-ranked" });
1873
+ let winner2 = null;
1874
+ let resolvedBy = "rank";
1875
+ const getCandidateChangedFileCount = (candidate) => Array.isArray(candidate.changedFiles) ? candidate.changedFiles.length : 0;
1876
+ const getCandidateDriftViolations = (candidate) => {
1877
+ if (!Array.isArray(candidate.changedFiles) || candidate.changedFiles.length === 0) return 0;
1878
+ if (!Array.isArray(expectedAllowlist) || expectedAllowlist.length === 0) return 0;
1879
+ return findAllowlistViolations(candidate.changedFiles, expectedAllowlist).length;
1880
+ };
1881
+ if (tieBreakerConfig.mode === "inconclusive") {
1882
+ const aiJudgeDisabled = config.judgeConfig?.disableAiJudge === true;
1883
+ if (aiJudgeDisabled) {
1884
+ const scoreCollisionReport2 = scoreCollisionReportBase && scoreCollisionReportBase.tiedAtTop.length > 1 ? buildCollisionReport({
1885
+ ...scoreCollisionReportBase,
1886
+ applied: {
1887
+ applyWinner: Boolean(config.applyWinner),
1888
+ wasTie: true,
1889
+ noWinnerReason: "tie",
1890
+ tieBreakerMode: tieBreakerConfig.mode,
1891
+ resolvedBy: void 0,
1892
+ winnerVariant: void 0
1893
+ }
1894
+ }) : void 0;
1895
+ return {
1896
+ winner: null,
1897
+ noWinnerReason: "tie",
1898
+ wasTie: true,
1899
+ rankings,
1900
+ scoreCollisionReport: scoreCollisionReport2
1901
+ };
1902
+ }
1903
+ winner2 = tiedAtTop[0] ?? null;
1904
+ resolvedBy = "rank";
1905
+ } else if (tieBreakerConfig.mode === "prefer-first-ranked") {
1906
+ winner2 = tiedAtTop[0] ?? null;
1907
+ } else if (tieBreakerConfig.mode === "prefer-low-drift") {
1908
+ winner2 = [...tiedAtTop].sort((a, b) => {
1909
+ const driftDelta = getCandidateDriftViolations(a) - getCandidateDriftViolations(b);
1910
+ if (driftDelta !== 0) return driftDelta;
1911
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1912
+ })[0] ?? null;
1913
+ resolvedBy = "drift";
1914
+ } else if (tieBreakerConfig.mode === "prefer-smaller-diff") {
1915
+ winner2 = [...tiedAtTop].sort((a, b) => {
1916
+ const diffDelta = getCandidateChangedFileCount(a) - getCandidateChangedFileCount(b);
1917
+ if (diffDelta !== 0) return diffDelta;
1918
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1919
+ })[0] ?? null;
1920
+ resolvedBy = "diff";
1921
+ } else if (tieBreakerConfig.mode === "prefer-low-drift-then-diff") {
1922
+ winner2 = [...tiedAtTop].sort((a, b) => {
1923
+ const driftDelta = getCandidateDriftViolations(a) - getCandidateDriftViolations(b);
1924
+ if (driftDelta !== 0) return driftDelta;
1925
+ const diffDelta = getCandidateChangedFileCount(a) - getCandidateChangedFileCount(b);
1926
+ if (diffDelta !== 0) return diffDelta;
1927
+ return variantIdFor(a.variant).localeCompare(variantIdFor(b.variant));
1928
+ })[0] ?? null;
1929
+ if (winner2) {
1930
+ const winnerDrift = getCandidateDriftViolations(winner2);
1931
+ const allSameDrift = tiedAtTop.every(
1932
+ (c) => getCandidateDriftViolations(c) === winnerDrift
1933
+ );
1934
+ if (!allSameDrift) {
1935
+ resolvedBy = "drift";
1936
+ } else {
1937
+ const winnerDiff = getCandidateChangedFileCount(winner2);
1938
+ const allSameDiff = tiedAtTop.every(
1939
+ (c) => getCandidateChangedFileCount(c) === winnerDiff
1940
+ );
1941
+ resolvedBy = allSameDiff ? "rank" : "diff";
1942
+ }
1943
+ } else {
1944
+ resolvedBy = "drift";
1945
+ }
1946
+ } else {
1947
+ winner2 = tiedAtTop[0] ?? null;
1948
+ }
1949
+ if (!winner2) winner2 = ranked[0] ?? null;
1950
+ if (winner2) {
1951
+ const scoreCollisionReport2 = scoreCollisionReportBase && scoreCollisionReportBase.tiedAtTop.length > 1 ? buildCollisionReport({
1952
+ ...scoreCollisionReportBase,
1953
+ applied: {
1954
+ applyWinner: true,
1955
+ wasTie: true,
1956
+ noWinnerReason: void 0,
1957
+ tieBreakerMode: tieBreakerConfig.mode,
1958
+ resolvedBy,
1959
+ winnerVariant: winner2.variant
1960
+ }
1961
+ }) : void 0;
1962
+ return {
1963
+ winner: winner2,
1964
+ wasTie: true,
1965
+ // Still record that there was a tie
1966
+ rankings,
1967
+ tieBreaker: {
1968
+ mode: tieBreakerConfig.mode,
1969
+ resolvedBy,
1970
+ winnerDriftViolations: getCandidateDriftViolations(winner2),
1971
+ winnerChangedFiles: getCandidateChangedFileCount(winner2),
1972
+ tieScore: topScore,
1973
+ tieScoreRounded: topScoreQuantized,
1974
+ tieScoreRoundedDecimals: SCORE_COLLISION_DECIMALS,
1975
+ tiedCount: tiedAtTop.length
1976
+ },
1977
+ scoreCollisionReport: scoreCollisionReport2
1978
+ };
1979
+ }
1980
+ }
1981
+ const scoreCollisionReport = scoreCollisionReportBase && scoreCollisionReportBase.tiedAtTop.length > 1 ? buildCollisionReport({
1982
+ ...scoreCollisionReportBase,
1983
+ applied: {
1984
+ applyWinner: Boolean(config.applyWinner),
1985
+ wasTie: true,
1986
+ noWinnerReason: "tie",
1987
+ tieBreakerMode: config.tieBreaker?.mode,
1988
+ resolvedBy: void 0,
1989
+ winnerVariant: void 0
1990
+ }
1991
+ }) : void 0;
1992
+ return {
1993
+ winner: null,
1994
+ noWinnerReason: "tie",
1995
+ wasTie: true,
1996
+ rankings,
1997
+ scoreCollisionReport
1998
+ };
1999
+ }
2000
+ if (topScore < threshold) {
2001
+ const verificationPolicy = config.verificationPolicy ?? "findings";
2002
+ if (verificationPolicy === "findings") {
2003
+ const bestRepairable = candidatesWithFindings.map((c) => ({
2004
+ candidate: c,
2005
+ effectiveScore: c.scoreBeforeTestSignal ?? c.score ?? 0
2006
+ })).filter((x) => x.effectiveScore >= threshold).sort((a, b) => b.effectiveScore - a.effectiveScore)[0]?.candidate;
2007
+ if (bestRepairable) {
2008
+ const restoredScore = bestRepairable.scoreBeforeTestSignal ?? bestRepairable.score;
2009
+ return {
2010
+ winner: {
2011
+ ...bestRepairable,
2012
+ score: restoredScore,
2013
+ feedback: bestRepairable.feedback ? `Selected for repair (tests recorded findings; observed score: ${restoredScore}).
2014
+
2015
+ ${bestRepairable.feedback}` : `Selected for repair (tests recorded findings; observed score: ${restoredScore}).`
2016
+ },
2017
+ wasTie: false,
2018
+ rankings
2019
+ };
2020
+ }
2021
+ }
2022
+ if (allowBelowThresholdWinner) {
2023
+ const winner2 = ranked[0] ?? null;
2024
+ if (winner2) {
2025
+ return {
2026
+ winner: winner2,
2027
+ wasTie: false,
2028
+ rankings,
2029
+ belowThresholdWinner: {
2030
+ threshold,
2031
+ winnerScore: topScore
2032
+ },
2033
+ scoreCollisionReport: scoreCollisionReportBase && (scoreCollisionReportBase.tiedAtTop.length > 1 || scoreCollisionReportBase.otherCollisionGroups.length > 0) ? buildCollisionReport({
2034
+ ...scoreCollisionReportBase,
2035
+ applied: {
2036
+ applyWinner: Boolean(config.applyWinner),
2037
+ wasTie: false,
2038
+ noWinnerReason: void 0,
2039
+ tieBreakerMode: config.tieBreaker?.mode,
2040
+ resolvedBy: void 0,
2041
+ winnerVariant: winner2.variant
2042
+ }
2043
+ }) : void 0
2044
+ };
2045
+ }
2046
+ }
2047
+ return {
2048
+ winner: null,
2049
+ noWinnerReason: "below-threshold",
2050
+ wasTie: false,
2051
+ rankings,
2052
+ scoreCollisionReport: scoreCollisionReportBase && (scoreCollisionReportBase.tiedAtTop.length > 1 || scoreCollisionReportBase.otherCollisionGroups.length > 0) ? buildCollisionReport({
2053
+ ...scoreCollisionReportBase,
2054
+ applied: {
2055
+ applyWinner: Boolean(config.applyWinner),
2056
+ wasTie: false,
2057
+ noWinnerReason: "below-threshold",
2058
+ tieBreakerMode: config.tieBreaker?.mode,
2059
+ resolvedBy: void 0,
2060
+ winnerVariant: void 0
2061
+ }
2062
+ }) : void 0
2063
+ };
2064
+ }
2065
+ const winner = ranked[0] ?? null;
2066
+ return {
2067
+ winner,
2068
+ wasTie: false,
2069
+ rankings,
2070
+ scoreCollisionReport: scoreCollisionReportBase && (scoreCollisionReportBase.tiedAtTop.length > 1 || scoreCollisionReportBase.otherCollisionGroups.length > 0) ? buildCollisionReport({
2071
+ ...scoreCollisionReportBase,
2072
+ applied: {
2073
+ applyWinner: Boolean(config.applyWinner),
2074
+ wasTie: false,
2075
+ noWinnerReason: void 0,
2076
+ tieBreakerMode: config.tieBreaker?.mode,
2077
+ resolvedBy: void 0,
2078
+ winnerVariant: winner?.variant
2079
+ }
2080
+ }) : void 0
2081
+ };
2082
+ }
2083
+ var __internalDetermineWinner = determineWinner;
2084
+ var __internalRecordDeterministicTestSignalObservation = recordDeterministicTestSignalObservation;
2085
+ var __internalExtractChangedFilesFromResult = extractChangedFilesFromResult;
2086
+ var __internalGetVariantTelemetryStatePath = getVariantTelemetryStatePath;
2087
+ var __internalHydrateCandidateCostsFromTelemetry = hydrateCandidateCostsFromTelemetry;
2088
+ var __internalVariantResultToCandidate = variantResultToCandidate;
2089
+ var __internalMatchVariantResult = matchVariantResult;
2090
+ var __internalCandidateMatchesVariantResult = candidateMatchesVariantResult;
2091
+ var __internalResolveCompetitionCostAggregate = resolveCompetitionCostAggregate;
2092
+ function synthesizeDeterministicRationalePacket(candidates, winnerInfo, config) {
2093
+ const { winner, wasTie, noWinnerReason, tieBreaker, belowThresholdWinner } = winnerInfo;
2094
+ const buildVariantId = candidateScoreId;
2095
+ const candidateToVariantResult = (candidate) => ({
2096
+ variant: buildVariantId(candidate),
2097
+ success: candidate.success,
2098
+ testStatus: candidate.testStatus,
2099
+ testsExecuted: candidate.testsExecuted ? {
2100
+ scope: candidate.testsExecuted.scope ?? "touched",
2101
+ filesTested: candidate.testsExecuted.filesTested ?? [],
2102
+ exitCode: candidate.testsExecuted.exitCode,
2103
+ durationMs: candidate.testsExecuted.durationMs
2104
+ } : void 0,
2105
+ emptyChanges: !candidate.changedFiles?.length,
2106
+ gitMetrics: candidate.changedFiles ? { filesChanged: candidate.changedFiles.length, linesAdded: 0, linesDeleted: 0 } : void 0,
2107
+ worktreeSummary: candidate.changedFiles ? {
2108
+ filesChanged: candidate.changedFiles.length,
2109
+ insertions: 0,
2110
+ deletions: 0,
2111
+ statusLines: candidate.changedFiles.map((f) => `M ${f}`)
2112
+ } : void 0
2113
+ });
2114
+ const effectiveWinner = winner;
2115
+ const winnerId = effectiveWinner ? buildVariantId(effectiveWinner) : "none";
2116
+ const scores = {};
2117
+ for (const candidate of candidates) {
2118
+ const variantId = buildVariantId(candidate);
2119
+ scores[variantId] = candidate.score ?? 0;
2120
+ }
2121
+ let unverifiedNegativeClaimCount = 0;
2122
+ const scoreBreakdown = {};
2123
+ for (const candidate of candidates) {
2124
+ const variantId = buildVariantId(candidate);
2125
+ const finalScore = candidate.score ?? 0;
2126
+ const subscores = {};
2127
+ const penalties = {};
2128
+ if (typeof candidate.score === "number") {
2129
+ subscores.delivery = candidate.score;
2130
+ }
2131
+ const deductions = [];
2132
+ if (candidate.testStatus === "failed" || candidate.testStatus === "error") {
2133
+ const testPenalty = candidate.scoreBeforeTestSignal ? candidate.scoreBeforeTestSignal - (candidate.score ?? 0) : 10;
2134
+ penalties.testFailure = testPenalty;
2135
+ const testEvidence = [];
2136
+ testEvidence.push({
2137
+ type: "metric",
2138
+ value: `testStatus: ${candidate.testStatus}`,
2139
+ context: "Test execution result"
2140
+ });
2141
+ if (candidate.testsExecuted?.exitCode !== void 0) {
2142
+ testEvidence.push({
2143
+ type: "metric",
2144
+ value: `exit code: ${candidate.testsExecuted.exitCode}`,
2145
+ context: "Test runner exit code"
2146
+ });
2147
+ }
2148
+ deductions.push({
2149
+ code: "test_failure",
2150
+ delta: -testPenalty,
2151
+ evidence: testEvidence,
2152
+ reason: "Tests failed during verification"
2153
+ });
2154
+ }
2155
+ if (!candidate.changedFiles?.length && candidate.success) {
2156
+ deductions.push({
2157
+ code: "empty_changes",
2158
+ delta: -50,
2159
+ evidence: [
2160
+ {
2161
+ type: "metric",
2162
+ value: "0 files changed",
2163
+ context: "Git status shows no changes"
2164
+ }
2165
+ ],
2166
+ reason: "No code changes detected"
2167
+ });
2168
+ }
2169
+ if (Array.isArray(candidate.changedFiles) && candidate.changedFiles.length > 10) {
2170
+ const excessPenalty = Math.min(10, (candidate.changedFiles.length - 10) * 2);
2171
+ penalties.other = excessPenalty;
2172
+ deductions.push({
2173
+ code: "off_target_files",
2174
+ delta: -excessPenalty,
2175
+ evidence: [
2176
+ {
2177
+ type: "metric",
2178
+ value: `${candidate.changedFiles.length} files changed`,
2179
+ context: "Excessive file changes may indicate scope creep"
2180
+ }
2181
+ ],
2182
+ reason: "Modified more than 10 files"
2183
+ });
2184
+ }
2185
+ const weights = {
2186
+ delivery: 1
2187
+ // Deterministic mode uses completeness as sole factor
2188
+ };
2189
+ const testStatus = candidate.testStatus;
2190
+ const testsExecuted = candidate.testsExecuted;
2191
+ scoreBreakdown[variantId] = {
2192
+ finalScore,
2193
+ subscores,
2194
+ weights,
2195
+ penalties: Object.keys(penalties).length > 0 ? penalties : void 0,
2196
+ aggregationMethod: "weighted_average",
2197
+ // Default for deterministic scoring
2198
+ // P2: Include floor (harmonic mean floor = 18 in Judge v2.2)
2199
+ floorApplied: 18,
2200
+ // P2b: Structured test status (first-class signal)
2201
+ ...testStatus && {
2202
+ testSignal: {
2203
+ status: testStatus,
2204
+ scope: testsExecuted?.scope,
2205
+ exitCode: testsExecuted?.exitCode,
2206
+ durationMs: testsExecuted?.durationMs,
2207
+ penaltyApplied: testStatus === "failed" || testStatus === "error" ? (penalties.testFailure ?? 0) > 0 : false
2208
+ }
2209
+ },
2210
+ // Include deduction trace with evidence (v0.5.0)
2211
+ deductions: deductions.length > 0 ? deductions : void 0
2212
+ };
2213
+ }
2214
+ const highestScoringCandidate = candidates.filter((candidate) => candidate.success && typeof candidate.score === "number").sort((a, b) => {
2215
+ const scoreDelta = Number(b.score ?? 0) - Number(a.score ?? 0);
2216
+ if (scoreDelta !== 0) return scoreDelta;
2217
+ return buildVariantId(a).localeCompare(buildVariantId(b));
2218
+ })[0];
2219
+ const highestScoringCandidateId = highestScoringCandidate ? buildVariantId(highestScoringCandidate) : void 0;
2220
+ const highestScore = highestScoringCandidate?.score ?? 0;
2221
+ const winnerScore = effectiveWinner?.score ?? 0;
2222
+ const winnerHasHighestDeterministicScore = Boolean(effectiveWinner) && (!highestScoringCandidate || highestScoringCandidateId === winnerId || Number(winnerScore) >= Number(highestScore));
2223
+ const candidateAnalysis = candidates.map((candidate) => {
2224
+ const variantId = buildVariantId(candidate);
2225
+ const isWinner = effectiveWinner && buildVariantId(effectiveWinner) === variantId;
2226
+ const strengths = [];
2227
+ const weaknesses = [];
2228
+ const missedRequirements = [];
2229
+ const riskyAreas = [];
2230
+ if (candidate.success) {
2231
+ strengths.push("Execution succeeded");
2232
+ if (typeof candidate.score === "number" && candidate.score > 80) {
2233
+ strengths.push(`High score: ${candidate.score}`);
2234
+ }
2235
+ if (candidate.testsExecuted && candidate.testStatus) {
2236
+ const scope = candidate.testsExecuted.scope ?? "unknown";
2237
+ if (candidate.testStatus === "passed") {
2238
+ strengths.push(`Tests passed (${scope})`);
2239
+ } else if (candidate.testStatus !== "not_run") {
2240
+ weaknesses.push(`Tests ${candidate.testStatus} (${scope})`);
2241
+ }
2242
+ }
2243
+ if (Array.isArray(candidate.changedFiles) && candidate.changedFiles.length > 0) {
2244
+ strengths.push(`Modified ${candidate.changedFiles.length} file(s)`);
2245
+ }
2246
+ } else {
2247
+ weaknesses.push("Execution failed");
2248
+ if (candidate.error) {
2249
+ weaknesses.push(`Error: ${candidate.error}`);
2250
+ }
2251
+ }
2252
+ if (!isWinner && candidate.success) {
2253
+ const candidateScore = candidate.score ?? 0;
2254
+ if (effectiveWinner && typeof candidate.score === "number") {
2255
+ if (candidateScore > winnerScore) {
2256
+ weaknesses.push(
2257
+ `Not selected despite higher deterministic score (${candidateScore} vs selected ${winnerScore})`
2258
+ );
2259
+ } else if (candidateScore === winnerScore) {
2260
+ weaknesses.push("Final tie-breaker selected another candidate");
2261
+ } else {
2262
+ weaknesses.push("Lower score than winner");
2263
+ }
2264
+ } else {
2265
+ weaknesses.push("Did not win final selection");
2266
+ }
2267
+ }
2268
+ const variantForEvidence = candidateToVariantResult(candidate);
2269
+ const weaknessEvidence = {
2270
+ weaknesses: weaknesses.map((weakness, index) => {
2271
+ const isNegative = isNegativeClaim(weakness);
2272
+ const anchors = isNegative ? extractEvidenceAnchors(weakness, variantForEvidence) : [];
2273
+ const verified = !isNegative || anchors.length > 0;
2274
+ if (isNegative && !verified) {
2275
+ unverifiedNegativeClaimCount++;
2276
+ }
2277
+ return {
2278
+ index,
2279
+ anchors: anchors.map((a) => ({
2280
+ type: a.type,
2281
+ value: a.value,
2282
+ context: a.context
2283
+ })),
2284
+ verified
2285
+ };
2286
+ })
2287
+ };
2288
+ return {
2289
+ variantId,
2290
+ strengths,
2291
+ weaknesses,
2292
+ missedRequirements,
2293
+ riskyAreas,
2294
+ evidence: weaknessEvidence.weaknesses?.length ? weaknessEvidence : void 0
2295
+ };
2296
+ });
2297
+ let primaryReason = "Winner selected by deterministic scoring";
2298
+ const keyFactors = [];
2299
+ const selectionEvidence = [];
2300
+ if (noWinnerReason) {
2301
+ const reasons = {
2302
+ "all-failed": "All variants failed execution",
2303
+ tie: "Tie between top variants",
2304
+ "below-threshold": `All scores below threshold (${config.judgeConfig?.threshold ?? 0})`,
2305
+ "judge-error": "Judge evaluation failed",
2306
+ incomparable: "Candidates touched disjoint files (low coherence)"
2307
+ };
2308
+ primaryReason = reasons[noWinnerReason] ?? noWinnerReason;
2309
+ } else if (wasTie && tieBreaker) {
2310
+ primaryReason = `Tie resolved by ${tieBreaker.mode} tiebreaker`;
2311
+ keyFactors.push(`Tiebreaker mode: ${tieBreaker.mode}`);
2312
+ if (tieBreaker.resolvedBy) {
2313
+ keyFactors.push(`Resolved by: ${tieBreaker.resolvedBy}`);
2314
+ }
2315
+ } else if (winner) {
2316
+ primaryReason = winnerHasHighestDeterministicScore ? "Highest deterministic score" : "Final winner selected by judge or selection policy despite lower deterministic score";
2317
+ keyFactors.push(`Score: ${winner.score ?? 0}`);
2318
+ if (!winnerHasHighestDeterministicScore && highestScoringCandidateId) {
2319
+ keyFactors.push(`Top deterministic score: ${highestScoringCandidateId} (${highestScore})`);
2320
+ keyFactors.push(`Selected winner score: ${winnerId} (${winnerScore})`);
2321
+ }
2322
+ selectionEvidence.push({
2323
+ type: "metric",
2324
+ value: `score: ${winner.score ?? 0}`,
2325
+ context: "Winner deterministic score"
2326
+ });
2327
+ if (winner.changedFiles?.length) {
2328
+ selectionEvidence.push({
2329
+ type: "metric",
2330
+ value: `${winner.changedFiles.length} files changed`,
2331
+ context: "Winner modified files"
2332
+ });
2333
+ }
2334
+ if (belowThresholdWinner) {
2335
+ keyFactors.push(
2336
+ `Below threshold: ${belowThresholdWinner.winnerScore} < ${belowThresholdWinner.threshold}`
2337
+ );
2338
+ }
2339
+ if (winner.testsExecuted && winner.testStatus === "passed") {
2340
+ keyFactors.push("Verified passing tests");
2341
+ selectionEvidence.push({
2342
+ type: "metric",
2343
+ value: "testStatus: passed",
2344
+ context: `Tests verified (${winner.testsExecuted.scope ?? "unknown"} scope)`
2345
+ });
2346
+ }
2347
+ if (winner.feedback) {
2348
+ keyFactors.push("Has feedback from deterministic evaluation");
2349
+ }
2350
+ }
2351
+ const rejectionReasons = {};
2352
+ const rejectionReasonsEvidence = {};
2353
+ for (const candidate of candidates) {
2354
+ const variantId = buildVariantId(candidate);
2355
+ if (effectiveWinner && buildVariantId(effectiveWinner) === variantId) continue;
2356
+ let reason;
2357
+ if (!candidate.success) {
2358
+ reason = candidate.error ?? "Execution failed";
2359
+ } else if (candidate.testsExecuted && candidate.testStatus && candidate.testStatus !== "passed") {
2360
+ reason = `Verified failing tests (testStatus=${candidate.testStatus})`;
2361
+ } else if (typeof candidate.score === "number" && typeof effectiveWinner?.score === "number") {
2362
+ if (candidate.score > effectiveWinner.score) {
2363
+ reason = `Not selected despite higher deterministic score (${candidate.score} vs selected ${effectiveWinner.score})`;
2364
+ } else if (candidate.score === effectiveWinner.score) {
2365
+ reason = `Final tie-breaker selected another candidate (${candidate.score} vs selected ${effectiveWinner.score})`;
2366
+ } else {
2367
+ reason = `Lower score (${candidate.score} vs ${effectiveWinner.score})`;
2368
+ }
2369
+ } else {
2370
+ reason = "Did not win deterministic selection";
2371
+ }
2372
+ rejectionReasons[variantId] = reason;
2373
+ if (isNegativeClaim(reason)) {
2374
+ const variantForEvidence = candidateToVariantResult(candidate);
2375
+ const anchors = extractEvidenceAnchors(reason, variantForEvidence);
2376
+ const verified = anchors.length > 0;
2377
+ rejectionReasonsEvidence[variantId] = {
2378
+ anchors: anchors.map((a) => ({
2379
+ type: a.type,
2380
+ value: a.value,
2381
+ context: a.context
2382
+ })),
2383
+ verified
2384
+ };
2385
+ if (!verified) {
2386
+ unverifiedNegativeClaimCount++;
2387
+ }
2388
+ }
2389
+ }
2390
+ const suggestedImprovements = [];
2391
+ const failedCount = candidates.filter((c) => !c.success).length;
2392
+ if (failedCount > 0) {
2393
+ suggestedImprovements.push(`${failedCount} variant(s) failed execution - investigate errors`);
2394
+ }
2395
+ if (wasTie) {
2396
+ suggestedImprovements.push("Consider refining task requirements to reduce ties");
2397
+ }
2398
+ let baseConfidence = noWinnerReason ? 0 : wasTie ? 60 : 100;
2399
+ if (unverifiedNegativeClaimCount > 0) {
2400
+ const penalty = Math.min(0.25, unverifiedNegativeClaimCount * 0.05);
2401
+ baseConfidence = Math.max(0, baseConfidence * (1 - penalty));
2402
+ }
2403
+ return {
2404
+ winnerId,
2405
+ scores,
2406
+ scoreBreakdown,
2407
+ // P1 Fix: Include detailed score breakdown with deduction traces
2408
+ candidateAnalysis,
2409
+ selectionRationale: {
2410
+ primary: primaryReason,
2411
+ keyFactors,
2412
+ confidence: baseConfidence,
2413
+ evidence: selectionEvidence.length > 0 ? selectionEvidence : void 0
2414
+ },
2415
+ rejectionReasons,
2416
+ rejectionReasonsEvidence: Object.keys(rejectionReasonsEvidence).length > 0 ? rejectionReasonsEvidence : void 0,
2417
+ suggestedImprovements,
2418
+ unverifiedNegativeClaimCount: unverifiedNegativeClaimCount > 0 ? unverifiedNegativeClaimCount : void 0
2419
+ };
2420
+ }
2421
+ function buildCompetitionBundle(taskId, candidates, basicResult) {
2422
+ const lines = [];
2423
+ lines.push("# Competition Bundle");
2424
+ lines.push("");
2425
+ lines.push(`Task ID: ${taskId}`);
2426
+ lines.push("");
2427
+ for (const candidate of candidates) {
2428
+ const provider = candidate.variant.provider;
2429
+ const model = candidate.variant.model;
2430
+ const header = [provider, model].filter(Boolean).join(" / ");
2431
+ const result = matchVariantResult(candidate.variant, basicResult.variants);
2432
+ lines.push(`## ${header || provider}`);
2433
+ lines.push("");
2434
+ lines.push(`- Success: ${candidate.success ? "yes" : "no"}`);
2435
+ lines.push(`- Score: ${candidate.score ?? 0}`);
2436
+ lines.push(`- Cost: $${candidate.cost.toFixed(4)}`);
2437
+ lines.push(`- Duration: ${(candidate.durationMs / 1e3).toFixed(1)}s`);
2438
+ if (candidate.error) {
2439
+ lines.push(`- Error: ${candidate.error}`);
2440
+ }
2441
+ const diff = result?.worktreeDiff;
2442
+ if (typeof diff === "string" && diff.trim().length > 0) {
2443
+ lines.push("");
2444
+ lines.push("```diff");
2445
+ lines.push(diff.trimEnd());
2446
+ lines.push("```");
2447
+ } else {
2448
+ lines.push("");
2449
+ lines.push("_No diff captured._");
2450
+ }
2451
+ lines.push("");
2452
+ }
2453
+ return lines.join("\n");
2454
+ }
2455
+ async function executeCompetitionStage(ctx) {
2456
+ const { stage, artifactStore, options } = ctx;
2457
+ const securityBoundary = ctx.securityBoundary ?? createSecurityBoundary(artifactStore.getWorkflowId());
2458
+ const startTime = Date.now();
2459
+ const config = stage.competition;
2460
+ if (!config || !config.variants || config.variants.length === 0) {
2461
+ throw new Error(`Stage '${stage.id}' is type=competition but has no variants configured`);
2462
+ }
2463
+ if (options.verbose) {
2464
+ console.log(chalk.blue(`
2465
+ Competition Stage: ${stage.id}`));
2466
+ console.log(chalk.gray(` Variants: ${config.variants.length}`));
2467
+ console.log(chalk.gray(` Providers: ${config.variants.map((v) => v.provider).join(", ")}`));
2468
+ }
2469
+ let resolvedPrompt = stage.prompt ?? "";
2470
+ try {
2471
+ resolvedPrompt = await resolvePromptArtifacts(
2472
+ stage.prompt ?? "",
2473
+ stage.inputs,
2474
+ artifactStore,
2475
+ stage.id,
2476
+ securityBoundary
2477
+ );
2478
+ } catch (error) {
2479
+ if (error instanceof ArtifactNotFoundError) {
2480
+ const result = {
2481
+ stageId: stage.id,
2482
+ stageType: "competition",
2483
+ validationPassed: false,
2484
+ cost: 0,
2485
+ candidates: [],
2486
+ winner: null,
2487
+ summary: `Failed to resolve input artifacts: ${error.message}`,
2488
+ durationMs: Date.now() - startTime
2489
+ };
2490
+ return result;
2491
+ }
2492
+ throw error;
2493
+ }
2494
+ if (options.verbose) {
2495
+ console.log(chalk.gray(` Prompt length: ${resolvedPrompt.length} chars`));
2496
+ }
2497
+ const effectiveMode = options.allowlistMode ?? "warn";
2498
+ const expectedAllowlistForSkip = computeExpectedAllowlist(stage);
2499
+ const requireChangesDemandsEdits = stage.validation?.requireChanges === true && stage.allowEmptyResults !== true;
2500
+ if (!requireChangesDemandsEdits && stageHasDeterministicChecks(stage) && typeof options.workerCwd === "string" && options.workerCwd.length > 0) {
2501
+ try {
2502
+ const skipProof = await evaluateStageCompletionProof({
2503
+ stage,
2504
+ worktreePath: options.workerCwd,
2505
+ stdout: "",
2506
+ attemptChangedFiles: [],
2507
+ allowlist: expectedAllowlistForSkip,
2508
+ stageId: stage.id
2509
+ });
2510
+ const alreadySatisfied = proofEstablishesSatisfaction(skipProof);
2511
+ if (alreadySatisfied) {
2512
+ const driftContext = computeCompetitionDrift([], expectedAllowlistForSkip, effectiveMode);
2513
+ const coherenceMetrics = computeCoherenceMetrics(
2514
+ [],
2515
+ DEFAULT_COHERENCE_THRESHOLD,
2516
+ expectedAllowlistForSkip
2517
+ );
2518
+ try {
2519
+ await artifactStore.save(stage.id, "stage-change", "json", {
2520
+ stageId: stage.id,
2521
+ stageType: "competition",
2522
+ mode: effectiveMode,
2523
+ deliveredFiles: driftContext.deliveredFiles,
2524
+ expectedFiles: driftContext.expectedFiles,
2525
+ violations: driftContext.violations,
2526
+ hasDrift: driftContext.hasDrift,
2527
+ candidateCount: 0,
2528
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2529
+ skipped: true,
2530
+ reason: "already-satisfied"
2531
+ });
2532
+ await artifactStore.save(
2533
+ stage.id,
2534
+ "stage-change-summary",
2535
+ "text",
2536
+ `${driftContext.summary}
2537
+
2538
+ Skipped: stage already satisfied`
2539
+ );
2540
+ const rationalePacket = {
2541
+ winnerId: "none",
2542
+ scores: {},
2543
+ candidateAnalysis: [],
2544
+ selectionRationale: {
2545
+ primary: "Competition skipped: stage already satisfied by deterministic checks",
2546
+ keyFactors: [
2547
+ "deterministic validation checks passed",
2548
+ "validation.requireChanges=false",
2549
+ "no variants executed"
2550
+ ],
2551
+ confidence: 100
2552
+ },
2553
+ rejectionReasons: {},
2554
+ suggestedImprovements: []
2555
+ };
2556
+ await artifactStore.save(stage.id, "judgeRationale", "json", rationalePacket);
2557
+ await artifactStore.save(stage.id, "winnerDiff", "diff", "");
2558
+ } catch {
2559
+ }
2560
+ return {
2561
+ stageId: stage.id,
2562
+ stageType: "competition",
2563
+ validationPassed: true,
2564
+ validationScore: 100,
2565
+ cost: 0,
2566
+ summary: "Competition skipped: stage already satisfied (idempotent)",
2567
+ durationMs: Date.now() - startTime,
2568
+ candidates: [],
2569
+ winner: null,
2570
+ winnerApplied: false,
2571
+ coherenceMetrics,
2572
+ markedIncomparable: false,
2573
+ scoringMode: "deterministic",
2574
+ competitionJudgeResult: {
2575
+ judgeType: config.judgeConfig?.type ?? "ai",
2576
+ aiJudgeAttempted: false,
2577
+ aiJudgeInvoked: false,
2578
+ aiJudgeError: void 0,
2579
+ judgeInvocationReason: "deterministic-shortcut",
2580
+ rankings: [],
2581
+ wasTie: false
2582
+ },
2583
+ driftContext,
2584
+ ...skipProof.evidence ? { completionEvidence: skipProof.evidence } : {}
2585
+ };
2586
+ }
2587
+ } catch {
2588
+ }
2589
+ }
2590
+ validateWorkflowJudgeModels(config, options.workerCwd);
2591
+ const executionIntent = resolveCompetitionExecutionIntent(stage);
2592
+ const variantConfigs = assignDuplicateVariantInstanceIds(
2593
+ config.variants.map(
2594
+ (spec) => variantSpecToConfig(
2595
+ spec,
2596
+ executionIntent,
2597
+ stage,
2598
+ options.providerExecutionTransport,
2599
+ config.executionContract
2600
+ )
2601
+ )
2602
+ );
2603
+ const admittedSpecs = admitFlywheelVariantSpecs(config.variants, variantConfigs);
2604
+ const allowDuplicateVariantSpecs = config.allowDuplicateVariantSpecs ?? config.allowDuplicateStrategies;
2605
+ if (config.allowDuplicateVariantSpecs !== void 0 && config.allowDuplicateStrategies !== void 0 && config.allowDuplicateVariantSpecs !== config.allowDuplicateStrategies) {
2606
+ throw new Error(
2607
+ `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\`.`
2608
+ );
2609
+ }
2610
+ assertNoDuplicateVariantSpecs(variantConfigs, {
2611
+ allowDuplicates: allowDuplicateVariantSpecs
2612
+ });
2613
+ const taskId = generateCompetitionId();
2614
+ const flywheelProjectRoot = getProjectRoot();
2615
+ const declaredVerifyCommands = (stage.verify?.commands ?? []).filter(
2616
+ (command) => command.trim().length > 0
2617
+ );
2618
+ const candidateGateCommands = Array.from(
2619
+ /* @__PURE__ */ new Set([...config.candidateGate?.commands ?? [], ...declaredVerifyCommands])
2620
+ );
2621
+ const preserveCandidateWorktrees = config.preserveCandidates === true || Boolean(config.candidateGate) || candidateGateCommands.length > 0;
2622
+ const competitionOptions = {
2623
+ abortSignal: options.abortSignal,
2624
+ workerCwd: options.workerCwd,
2625
+ verbose: options.verbose,
2626
+ maxConcurrentVariants: options.maxConcurrentVariants,
2627
+ perVariantTimeoutMinutes: options.perVariantTimeoutMinutes,
2628
+ timeoutMinutes: options.timeoutMinutes,
2629
+ // Flywheel never consumes basic-competition synthesis (candidate gates / judge /
2630
+ // apply use variant results only). Always disable synthesis at this boundary so
2631
+ // agentic synthesis compute is not spent on discarded product. (Candidate gates
2632
+ // also run after Basic Competition returns, so early synthesis cannot see that
2633
+ // evidence and can emit misleading "0 eligible variants" warnings.)
2634
+ synthesize: false,
2635
+ deferEvaluationHandleFinalization: true,
2636
+ // Preserve worktrees only when needed for post-processing (candidate gate commands,
2637
+ // declared verify commands, coverage parsing).
2638
+ // Winner application in flywheel-executor prefers `worktreeDiff` and does not require retained worktrees.
2639
+ preserveWorktrees: preserveCandidateWorktrees,
2640
+ executionContext: createExecutionContext({
2641
+ repoRoot: flywheelProjectRoot,
2642
+ buildDir: path.join(flywheelProjectRoot, ".build-project"),
2643
+ taskId,
2644
+ envOverrides: preserveCandidateWorktrees ? {
2645
+ BUILD_PRESERVE_WORKTREES: "1",
2646
+ BUILD_RETAIN_BASIC_WORKTREE: "1"
2647
+ } : {}
2648
+ })
2649
+ };
2650
+ let basicResult;
2651
+ try {
2652
+ basicResult = await runBasicCompetition(
2653
+ taskId,
2654
+ resolvedPrompt,
2655
+ variantConfigs,
2656
+ competitionOptions
2657
+ );
2658
+ } catch (error) {
2659
+ const errorMsg = error instanceof Error ? error.message : String(error);
2660
+ await finalizeEvaluationHandleAsync(
2661
+ taskId,
2662
+ createEvaluationHandleFinalState({
2663
+ outcome: "error",
2664
+ winner: null,
2665
+ errorMessage: errorMsg
2666
+ })
2667
+ );
2668
+ const result = {
2669
+ stageId: stage.id,
2670
+ stageType: "competition",
2671
+ validationPassed: false,
2672
+ cost: 0,
2673
+ candidates: [],
2674
+ winner: null,
2675
+ summary: `Competition execution failed: ${errorMsg}`,
2676
+ durationMs: Date.now() - startTime,
2677
+ competitionJudgeResult: {
2678
+ judgeType: config.judgeConfig?.type ?? "ai",
2679
+ aiJudgeAttempted: false,
2680
+ aiJudgeInvoked: false,
2681
+ aiJudgeError: errorMsg,
2682
+ judgeInvocationReason: "error",
2683
+ rankings: [],
2684
+ wasTie: false,
2685
+ noWinnerReason: "judge-error"
2686
+ }
2687
+ };
2688
+ return result;
2689
+ }
2690
+ let deferredHandleFinalized = false;
2691
+ const finalizeDeferredHandle = async (state) => {
2692
+ let finalizeResult = await finalizeEvaluationHandleAsync(taskId, state);
2693
+ if (finalizeResult.kind === "not_terminal") {
2694
+ await Promise.all(
2695
+ basicResult.variants.map(
2696
+ (variant) => updateEvaluationHandleWithResultAsync(taskId, variant)
2697
+ )
2698
+ );
2699
+ finalizeResult = await finalizeEvaluationHandleAsync(taskId, state);
2700
+ }
2701
+ if (finalizeResult.kind !== "absent" && !isDurableHandleCompletion(finalizeResult, state.status)) {
2702
+ throw new Error(
2703
+ `Evaluation handle did not reach durable ${state.status} state (kind=${finalizeResult.kind})`
2704
+ );
2705
+ }
2706
+ deferredHandleFinalized = true;
2707
+ };
2708
+ let observedCandidates;
2709
+ let aiJudgeAttempted = false;
2710
+ let aiJudgeInvoked = false;
2711
+ let tieBreakAiJudgeInvoked = false;
2712
+ try {
2713
+ const basicInterruption = resolveBasicCompetitionInterruption(basicResult);
2714
+ let bindingError;
2715
+ try {
2716
+ bindFlywheelVariantResults(admittedSpecs, basicResult.variants);
2717
+ } catch (error) {
2718
+ observedCandidates = basicResult.variants.map(
2719
+ (variant) => variantResultToCandidate(observedVariantSpec(variant), variant)
2720
+ );
2721
+ if (!basicInterruption) throw error;
2722
+ bindingError = error instanceof Error ? error.message : String(error);
2723
+ }
2724
+ if (basicInterruption) {
2725
+ const interruptedCandidates = observedCandidates ?? admittedSpecs.map(
2726
+ (spec) => variantResultToCandidate(spec, matchVariantResult(spec, basicResult.variants))
2727
+ );
2728
+ observedCandidates = interruptedCandidates;
2729
+ const { cost, costUnavailableReason: costUnavailableReason2 } = resolveCompetitionCostAggregate(interruptedCandidates);
2730
+ const timedOut = basicInterruption.kind === "timed_out";
2731
+ await finalizeDeferredHandle(
2732
+ timedOut ? createEvaluationHandleFinalState({
2733
+ outcome: "timed_out",
2734
+ winner: null,
2735
+ errorMessage: `Competition timed out after ${basicInterruption.timeout.timeoutMs}ms`
2736
+ }) : createEvaluationHandleFinalState({ outcome: "no_winner", winner: null })
2737
+ );
2738
+ await cleanupSynthesisInputPatches(basicResult.variants, {
2739
+ expectedRoot: resolveSynthesisInputPatchDir(
2740
+ competitionOptions.executionContext.buildDir,
2741
+ taskId
2742
+ )
2743
+ });
2744
+ return {
2745
+ stageId: stage.id,
2746
+ stageType: "competition",
2747
+ validationPassed: false,
2748
+ cost,
2749
+ costUnavailableReason: costUnavailableReason2,
2750
+ candidates: interruptedCandidates,
2751
+ warnings: bindingError ? [bindingError] : void 0,
2752
+ winner: null,
2753
+ summary: timedOut ? "Competition timed out; no winner selected" : `Competition canceled by ${basicInterruption.kind === "canceled" ? basicInterruption.signal : "unknown signal"}; no winner selected`,
2754
+ durationMs: Date.now() - startTime,
2755
+ competitionJudgeResult: {
2756
+ judgeType: config.judgeConfig?.type ?? "ai",
2757
+ aiJudgeAttempted: false,
2758
+ aiJudgeInvoked: false,
2759
+ judgeInvocationReason: timedOut ? "error" : "canceled",
2760
+ rankings: [],
2761
+ wasTie: false,
2762
+ noWinnerReason: timedOut ? "judge-error" : "canceled"
2763
+ }
2764
+ };
2765
+ }
2766
+ let judgedWinner = null;
2767
+ let aiJudgeError;
2768
+ let latestJudgeEscalation;
2769
+ let latestMainJudgeResult;
2770
+ let latestTiebreakJudgeResult;
2771
+ let matrixDefaultWinnerSource = "unknown";
2772
+ let eligibleVariantResultsForMatrix = [];
2773
+ let matrixRan = false;
2774
+ let matrixProfileAgreement;
2775
+ let effectiveMatrixAuthority;
2776
+ const matrixAuthorityWarnings = [];
2777
+ const matrixAuthorityNonSelectionReasons = [];
2778
+ const candidates = await Promise.all(
2779
+ admittedSpecs.map(async (spec) => {
2780
+ const matchingResult = matchVariantResult(spec, basicResult.variants);
2781
+ const candidate = variantResultToCandidate(spec, matchingResult);
2782
+ if (candidate.success) return candidate;
2783
+ if (!isNoChangesDetectedError(candidate.error)) return candidate;
2784
+ if (requireChangesDemandsEdits) {
2785
+ return candidate;
2786
+ }
2787
+ if (!stageHasDeterministicChecks(stage)) return candidate;
2788
+ if (!candidate.worktreePath) return candidate;
2789
+ const stdout = getStringAtPath(matchingResult, ["result", "stdout"]) ?? "";
2790
+ const canAcceptNoop = await validateWorktreeAgainstStageChecks(
2791
+ stage,
2792
+ candidate.worktreePath,
2793
+ stdout,
2794
+ {
2795
+ attemptChangedFiles: candidate.changedFiles ?? [],
2796
+ allowlist: expectedAllowlistForSkip
2797
+ }
2798
+ );
2799
+ if (!canAcceptNoop) return candidate;
2800
+ return {
2801
+ ...candidate,
2802
+ success: true,
2803
+ error: void 0,
2804
+ score: candidate.score ?? 0
2805
+ };
2806
+ })
2807
+ );
2808
+ observedCandidates = candidates;
2809
+ const finishedExecutionKeys = new Set(
2810
+ candidates.filter((c) => c.success).map((c) => variantIdForSpec(c.variant))
2811
+ );
2812
+ if (stage.validation?.requireChanges === true && stage.allowEmptyResults !== true) {
2813
+ for (let idx = 0; idx < candidates.length; idx++) {
2814
+ const candidate = candidates[idx];
2815
+ if (!candidate?.success || !candidateHasConcreteZeroChanges(candidate)) continue;
2816
+ candidates[idx] = {
2817
+ ...candidate,
2818
+ success: false,
2819
+ error: "Candidate produced no applicable changes but validation.requireChanges is enabled"
2820
+ };
2821
+ }
2822
+ }
2823
+ await hydrateCandidateCostsFromTelemetry(taskId, candidates, stage.id, options.verbose);
2824
+ const verificationPolicy = config.verificationPolicy ?? "findings";
2825
+ const candidatesWithTestFindings = [];
2826
+ for (let idx = 0; idx < candidates.length; idx++) {
2827
+ const candidate = candidates[idx];
2828
+ if (!candidate) continue;
2829
+ const trustedTestStatus = resolveTrustedCandidateTestStatus(candidate);
2830
+ if (candidate.success && candidate.testsExecuted && trustedTestStatus && trustedTestStatus !== "passed" && trustedTestStatus !== "not_run") {
2831
+ const variantId = formatCompetitionCandidateVariantDisplay(candidate);
2832
+ const testScope = candidate.testsExecuted.scope ?? "unknown";
2833
+ const exitCode = candidate.testsExecuted.exitCode ?? 1;
2834
+ const testLabel = `touched tests (scope: ${testScope})`;
2835
+ const verificationUnavailable = candidate.testStatus === "unavailable";
2836
+ const finding = {
2837
+ kind: "test",
2838
+ command: testLabel,
2839
+ exitCode,
2840
+ severity: verificationUnavailable ? "warning" : "error",
2841
+ recommendedNextStep: verificationUnavailable ? `Install or enable test tooling for scope: ${testScope}` : `Fix failing tests in scope: ${testScope}`
2842
+ };
2843
+ candidate.verification = {
2844
+ passed: false,
2845
+ findings: [finding]
2846
+ };
2847
+ if (verificationPolicy === "blocking") {
2848
+ candidatesWithTestFindings.push(
2849
+ `${variantId} (${verificationUnavailable ? "verification unavailable" : "disqualified"})`
2850
+ );
2851
+ candidates[idx] = {
2852
+ ...candidate,
2853
+ success: false,
2854
+ error: verificationUnavailable ? `Candidate gate unavailable: touched tests unavailable (scope: ${testScope})` : `Candidate gate failed: touched tests ${candidate.testStatus} (scope: ${testScope})`
2855
+ };
2856
+ } else {
2857
+ candidatesWithTestFindings.push(`${variantId} (findings recorded)`);
2858
+ }
2859
+ }
2860
+ }
2861
+ if (candidatesWithTestFindings.length > 0 && options.verbose) {
2862
+ const mode = verificationPolicy === "blocking" ? "disqualified" : "recorded findings for";
2863
+ console.log(
2864
+ chalk.yellow(
2865
+ ` ${candidatesWithTestFindings.length} candidate(s) ${mode}: ${candidatesWithTestFindings.join(", ")}`
2866
+ )
2867
+ );
2868
+ }
2869
+ const candidateGatePassedVariantIds = /* @__PURE__ */ new Set();
2870
+ if (candidateGateCommands.length > 0) {
2871
+ const gate = { ...config.candidateGate ?? {}, commands: candidateGateCommands };
2872
+ const gateResults = [];
2873
+ const gatedCandidates = await Promise.all(
2874
+ candidates.map(async (candidate) => {
2875
+ if (!candidate.success) {
2876
+ gateResults.push({
2877
+ provider: candidate.variant.provider,
2878
+ model: candidate.variant.model,
2879
+ worktreePath: candidate.worktreePath,
2880
+ ran: false,
2881
+ passed: false,
2882
+ error: "Candidate did not execute successfully (gate not run)",
2883
+ commandResults: []
2884
+ });
2885
+ return candidate;
2886
+ }
2887
+ if (!candidate.worktreePath) {
2888
+ const msg = "Candidate gate requires a retained worktreePath but none was provided";
2889
+ gateResults.push({
2890
+ provider: candidate.variant.provider,
2891
+ model: candidate.variant.model,
2892
+ worktreePath: candidate.worktreePath,
2893
+ ran: false,
2894
+ passed: false,
2895
+ error: msg,
2896
+ commandResults: []
2897
+ });
2898
+ return { ...candidate, success: false, error: `Candidate gate failed: ${msg}` };
2899
+ }
2900
+ const findings = [
2901
+ ...candidate.verification?.findings ?? []
2902
+ ];
2903
+ const renderedCommands = gate.commands.map(
2904
+ (command) => renderCandidateGateCommand(command, candidate)
2905
+ );
2906
+ const verifyResult = await runVerifyCommands({
2907
+ cwd: candidate.worktreePath,
2908
+ commands: renderedCommands,
2909
+ commandProvenance: "candidate-gate-config",
2910
+ timeoutMs: CANDIDATE_GATE_COMMAND_TIMEOUT_MS
2911
+ });
2912
+ const commandResults = verifyResult.results;
2913
+ const gatePassed = verifyResult.passed;
2914
+ if (gatePassed) {
2915
+ candidateGatePassedVariantIds.add(variantIdForSpec(candidate.variant));
2916
+ }
2917
+ let gateError;
2918
+ const failedCommand = commandResults.find((result2) => result2.exitCode !== 0);
2919
+ if (failedCommand) {
2920
+ gateError = `Verify command failed (exit ${failedCommand.exitCode}): ${failedCommand.command}`;
2921
+ findings.push({
2922
+ kind: "gate-command",
2923
+ command: failedCommand.command,
2924
+ exitCode: failedCommand.exitCode,
2925
+ outputTail: failedCommand.outputTail ?? failedCommand.stderrTail ?? failedCommand.stdoutTail,
2926
+ severity: "error",
2927
+ recommendedNextStep: `Fix gate command failure: ${failedCommand.command}`
2928
+ });
2929
+ }
2930
+ gateResults.push({
2931
+ provider: candidate.variant.provider,
2932
+ model: candidate.variant.model,
2933
+ worktreePath: candidate.worktreePath,
2934
+ ran: true,
2935
+ passed: gatePassed,
2936
+ error: gateError,
2937
+ commandResults
2938
+ });
2939
+ if (!gatePassed) {
2940
+ candidate.verification = {
2941
+ passed: false,
2942
+ findings
2943
+ };
2944
+ if (verificationPolicy === "blocking") {
2945
+ return { ...candidate, success: false, error: `Candidate gate failed: ${gateError}` };
2946
+ }
2947
+ }
2948
+ return candidate;
2949
+ })
2950
+ );
2951
+ candidates.splice(0, candidates.length, ...gatedCandidates);
2952
+ try {
2953
+ await artifactStore.save(stage.id, "candidate-gates", "json", {
2954
+ taskId,
2955
+ stageId: stage.id,
2956
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2957
+ commands: gate.commands,
2958
+ candidateCount: candidates.length,
2959
+ passedCount: gateResults.filter((r) => r.passed).length,
2960
+ results: gateResults
2961
+ });
2962
+ } catch (error) {
2963
+ if (options.verbose) {
2964
+ console.warn(
2965
+ chalk.yellow(` Warning: Failed to persist candidate gate artifacts: ${error}`)
2966
+ );
2967
+ }
2968
+ }
2969
+ }
2970
+ const coverageConfig = config.candidateGate?.coverage;
2971
+ let usedCoverageScoring = false;
2972
+ let coverageDataAvailable = false;
2973
+ if (coverageConfig && Array.isArray(coverageConfig.targets) && coverageConfig.targets.length > 0) {
2974
+ const summaryPath = coverageConfig.summaryPath ?? "coverage/coverage-summary.json";
2975
+ const threshold = coverageConfig.threshold;
2976
+ const coverageMode = coverageConfig.mode ?? "absolute";
2977
+ const minDeltaPct = coverageConfig.minDeltaPct ?? 15;
2978
+ const largeFileLineThreshold = coverageConfig.largeFileLineThreshold ?? 300;
2979
+ const baselineSummary = typeof options.workerCwd === "string" && options.workerCwd.length > 0 ? await loadCoverageSummaryJson(options.workerCwd, summaryPath) : null;
2980
+ const baselineStats = computeCoverageStatsForTargets(baselineSummary, coverageConfig.targets);
2981
+ const baselineFromPrompt = parseBaselineLinesPctFromPrompt(resolvedPrompt);
2982
+ const effectiveBaselineAvgPct = baselineStats.avgPct ?? baselineFromPrompt;
2983
+ const perCandidateCoverage = [];
2984
+ for (let idx = 0; idx < candidates.length; idx++) {
2985
+ const candidate = candidates[idx];
2986
+ if (!candidate) continue;
2987
+ const worktreePath = candidate.worktreePath;
2988
+ let avgPct = null;
2989
+ let minPct = null;
2990
+ let maxTargetLines = null;
2991
+ let byTarget = {};
2992
+ let missingTargets = [];
2993
+ let disqualified = false;
2994
+ let disqualifyReason;
2995
+ let deltaAvgPct = null;
2996
+ const baselineAvgPct = effectiveBaselineAvgPct;
2997
+ if (candidate.success) {
2998
+ if (!worktreePath) {
2999
+ byTarget = Object.fromEntries(coverageConfig.targets.map((t) => [t, null]));
3000
+ missingTargets = [...coverageConfig.targets];
3001
+ const hasGateConfig = typeof threshold === "number" || coverageMode === "delta" || coverageMode === "auto";
3002
+ if (hasGateConfig) {
3003
+ disqualified = true;
3004
+ disqualifyReason = "Missing worktreePath required for coverage gate evaluation";
3005
+ }
3006
+ } else {
3007
+ const candidateSummary = await loadCoverageSummaryJson(worktreePath, summaryPath);
3008
+ const stats = computeCoverageStatsForTargets(candidateSummary, coverageConfig.targets);
3009
+ avgPct = stats.avgPct;
3010
+ minPct = stats.minPct;
3011
+ maxTargetLines = stats.maxTargetLines;
3012
+ byTarget = stats.byTarget;
3013
+ missingTargets = stats.missingTargets;
3014
+ deltaAvgPct = typeof avgPct === "number" ? Math.round(
3015
+ (avgPct - (typeof baselineAvgPct === "number" ? baselineAvgPct : 0)) * 100
3016
+ ) / 100 : null;
3017
+ let effectiveMode2 = coverageMode;
3018
+ if (coverageMode === "auto" && typeof maxTargetLines === "number") {
3019
+ effectiveMode2 = resolveAutoCoverageMode({
3020
+ maxTargetLines,
3021
+ largeFileLineThreshold,
3022
+ baselineAvgPct,
3023
+ threshold,
3024
+ minDeltaPct
3025
+ });
3026
+ }
3027
+ if (effectiveMode2 === "absolute" && typeof threshold === "number") {
3028
+ if (missingTargets.length > 0) {
3029
+ disqualified = true;
3030
+ disqualifyReason = `Missing coverage for targets: ${missingTargets.join(", ")}`;
3031
+ } else if (typeof minPct === "number" && minPct < threshold) {
3032
+ disqualified = true;
3033
+ disqualifyReason = `Coverage below threshold (${minPct.toFixed(1)}% < ${threshold}%)`;
3034
+ } else if (minPct === null) {
3035
+ disqualified = true;
3036
+ disqualifyReason = "Coverage data missing (unable to evaluate threshold)";
3037
+ }
3038
+ } else if (effectiveMode2 === "delta") {
3039
+ if (missingTargets.length > 0) {
3040
+ disqualified = true;
3041
+ disqualifyReason = `Missing coverage for targets: ${missingTargets.join(", ")}`;
3042
+ } else if (typeof deltaAvgPct === "number" && deltaAvgPct < minDeltaPct) {
3043
+ disqualified = true;
3044
+ disqualifyReason = `Coverage improvement below minimum (${deltaAvgPct.toFixed(1)}pp < ${minDeltaPct}pp)`;
3045
+ } else if (deltaAvgPct === null) {
3046
+ disqualified = true;
3047
+ disqualifyReason = "Coverage data missing (unable to evaluate delta)";
3048
+ }
3049
+ }
3050
+ }
3051
+ }
3052
+ let effectiveCandidate = candidate;
3053
+ if (effectiveCandidate.success && disqualified) {
3054
+ effectiveCandidate = {
3055
+ ...effectiveCandidate,
3056
+ success: false,
3057
+ error: `Candidate gate failed: ${disqualifyReason ?? "coverage threshold"}`
3058
+ };
3059
+ candidates[idx] = effectiveCandidate;
3060
+ }
3061
+ if (effectiveCandidate.success && typeof avgPct === "number") {
3062
+ effectiveCandidate = { ...effectiveCandidate, score: avgPct };
3063
+ candidates[idx] = effectiveCandidate;
3064
+ coverageDataAvailable = true;
3065
+ }
3066
+ perCandidateCoverage.push({
3067
+ provider: effectiveCandidate.variant.provider,
3068
+ model: effectiveCandidate.variant.model,
3069
+ worktreePath,
3070
+ success: effectiveCandidate.success,
3071
+ avgPct,
3072
+ minPct,
3073
+ maxTargetLines,
3074
+ baselineAvgPct,
3075
+ deltaAvgPct,
3076
+ byTarget,
3077
+ missingTargets,
3078
+ disqualified: disqualified || void 0,
3079
+ disqualifyReason
3080
+ });
3081
+ }
3082
+ try {
3083
+ await artifactStore.save(stage.id, "candidate-coverage", "json", {
3084
+ taskId,
3085
+ stageId: stage.id,
3086
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3087
+ summaryPath,
3088
+ gateConfig: {
3089
+ mode: coverageMode,
3090
+ threshold,
3091
+ minDeltaPct,
3092
+ largeFileLineThreshold
3093
+ },
3094
+ targets: coverageConfig.targets,
3095
+ baseline: {
3096
+ avgPct: effectiveBaselineAvgPct,
3097
+ minPct: baselineStats.minPct ?? baselineFromPrompt,
3098
+ totalLines: baselineStats.totalLines,
3099
+ maxTargetLines: baselineStats.maxTargetLines,
3100
+ byTarget: baselineStats.byTarget,
3101
+ missingTargets: baselineStats.missingTargets
3102
+ },
3103
+ candidates: perCandidateCoverage
3104
+ });
3105
+ } catch (error) {
3106
+ if (options.verbose) {
3107
+ console.warn(
3108
+ chalk.yellow(` Warning: Failed to persist candidate coverage artifacts: ${error}`)
3109
+ );
3110
+ }
3111
+ }
3112
+ usedCoverageScoring = coverageDataAvailable;
3113
+ }
3114
+ recordDeterministicTestSignalObservation(candidates, options.verbose);
3115
+ const expectedAllowlist = computeExpectedAllowlist(stage);
3116
+ const { cost: totalCost, costUnavailableReason } = resolveCompetitionCostAggregate(candidates);
3117
+ const finishedCandidates = candidates.filter(
3118
+ (c) => finishedExecutionKeys.has(variantIdForSpec(c.variant))
3119
+ );
3120
+ const shouldInvokeAiJudgeForFinished = finishedCandidates.length >= 2 && config.judgeConfig?.disableAiJudge !== true;
3121
+ const allCandidatesDisqualified = candidates.every((c) => !c.success);
3122
+ if (allCandidatesDisqualified && verificationPolicy === "blocking" && !shouldInvokeAiJudgeForFinished) {
3123
+ let disqualificationSummary = "Competition failed: All candidates disqualified by verification gates";
3124
+ const testGateUnavailable = candidates.filter(
3125
+ (c) => c.error?.includes("touched tests unavailable")
3126
+ );
3127
+ const testGateFailures = candidates.filter(
3128
+ (c) => !c.error?.includes("touched tests unavailable") && (c.error?.includes("touched tests") || c.error?.includes("Candidate gate failed"))
3129
+ );
3130
+ const coverageGateFailures = candidates.filter((c) => c.error?.includes("coverage"));
3131
+ const verifyFailures = candidates.filter(
3132
+ (c) => c.error?.includes("Verify stage failed") || c.error?.includes("verify.commands")
3133
+ );
3134
+ const requireChangesNoops = candidates.filter(
3135
+ (c) => c.error?.includes("validation.requireChanges is enabled")
3136
+ );
3137
+ const rootCauses = [];
3138
+ if (testGateUnavailable.length > 0) {
3139
+ rootCauses.push(
3140
+ `${testGateUnavailable.length} candidate(s) had unavailable deterministic test verification (touched tests unavailable)`
3141
+ );
3142
+ }
3143
+ if (testGateFailures.length > 0) {
3144
+ rootCauses.push(
3145
+ `${testGateFailures.length} candidate(s) failed deterministic test gate (touched tests failed)`
3146
+ );
3147
+ }
3148
+ if (coverageGateFailures.length > 0) {
3149
+ rootCauses.push(
3150
+ `${coverageGateFailures.length} candidate(s) failed coverage gate (below threshold)`
3151
+ );
3152
+ }
3153
+ if (verifyFailures.length > 0) {
3154
+ rootCauses.push(`${verifyFailures.length} candidate(s) failed verify stage commands`);
3155
+ }
3156
+ if (requireChangesNoops.length > 0) {
3157
+ rootCauses.push(
3158
+ `${requireChangesNoops.length} candidate(s) produced no applicable changes while validation.requireChanges is enabled`
3159
+ );
3160
+ }
3161
+ if (rootCauses.length > 0) {
3162
+ disqualificationSummary += `. Root cause: ${rootCauses.join("; ")}`;
3163
+ }
3164
+ const candidateErrors = candidates.filter((c) => c.error).map((c) => {
3165
+ const variantId = formatCompetitionCandidateVariantDisplay(c);
3166
+ return `${variantId} - ${c.error}`;
3167
+ }).join("; ");
3168
+ if (candidateErrors) {
3169
+ disqualificationSummary += `. Candidate details: ${candidateErrors}`;
3170
+ }
3171
+ const result2 = {
3172
+ stageId: stage.id,
3173
+ stageType: "competition",
3174
+ validationPassed: false,
3175
+ validationScore: 0,
3176
+ cost: totalCost,
3177
+ costUnavailableReason,
3178
+ summary: disqualificationSummary,
3179
+ durationMs: Date.now() - startTime,
3180
+ candidates,
3181
+ winner: null,
3182
+ winnerApplied: false,
3183
+ scoringMode: "deterministic",
3184
+ competitionJudgeResult: {
3185
+ judgeType: config.judgeConfig?.type ?? "ai",
3186
+ aiJudgeAttempted: false,
3187
+ aiJudgeInvoked: false,
3188
+ aiJudgeError: void 0,
3189
+ judgeInvocationReason: "no-successful-candidates",
3190
+ rankings: [],
3191
+ wasTie: false,
3192
+ noWinnerReason: "all-failed"
3193
+ }
3194
+ };
3195
+ try {
3196
+ await artifactStore.save(stage.id, "candidates", "json", {
3197
+ taskId,
3198
+ variantCount: candidates.length,
3199
+ successCount: 0,
3200
+ candidates: candidates.map((c) => ({
3201
+ provider: c.variant.provider,
3202
+ model: c.variant.model,
3203
+ success: c.success,
3204
+ error: c.error,
3205
+ cost: c.cost,
3206
+ costUnavailableReason: c.costUnavailableReason
3207
+ })),
3208
+ winner: null,
3209
+ rankings: [],
3210
+ allDisqualifiedByTestGate: true,
3211
+ aiJudgeInvoked: result2.competitionJudgeResult?.aiJudgeInvoked ?? false,
3212
+ scoringMode: result2.scoringMode ?? "deterministic",
3213
+ judgeInvocationReason: result2.competitionJudgeResult?.judgeInvocationReason ?? "no-successful-candidates"
3214
+ });
3215
+ } catch (error) {
3216
+ if (options.verbose) {
3217
+ console.warn(chalk.yellow(` Warning: Failed to persist failure artifacts: ${error}`));
3218
+ }
3219
+ }
3220
+ await finalizeDeferredHandle(
3221
+ createEvaluationHandleFinalState({ outcome: "all_failed", winner: null })
3222
+ );
3223
+ await cleanupSynthesisInputPatches(basicResult.variants, {
3224
+ expectedRoot: resolveSynthesisInputPatchDir(
3225
+ competitionOptions.executionContext.buildDir,
3226
+ taskId
3227
+ )
3228
+ });
3229
+ return result2;
3230
+ }
3231
+ const shouldInvokeAiJudge = shouldInvokeAiJudgeForFinished;
3232
+ if (shouldInvokeAiJudge) {
3233
+ if (options.verbose) {
3234
+ console.log(chalk.blue(" Invoking AI judge for competition evaluation..."));
3235
+ }
3236
+ const judgeVisibleVariantResults = buildJudgeVisibleVariantResults(
3237
+ finishedCandidates,
3238
+ basicResult.variants
3239
+ );
3240
+ if (judgeVisibleVariantResults.length < 2) {
3241
+ if (options.verbose) {
3242
+ console.warn(
3243
+ chalk.yellow(
3244
+ ` Skipping AI judge: expected \u22652 finished variants but resolved ${judgeVisibleVariantResults.length}`
3245
+ )
3246
+ );
3247
+ }
3248
+ } else {
3249
+ aiJudgeAttempted = true;
3250
+ try {
3251
+ const { aiJudgeRun, aiJudgePrimary } = deriveAiJudgeInvocationArgs(config.judgeConfig);
3252
+ eligibleVariantResultsForMatrix = judgeVisibleVariantResults;
3253
+ matrixDefaultWinnerSource = aiJudgePrimary;
3254
+ const judgeResult = await selectWinnerWithJudge(
3255
+ resolvedPrompt,
3256
+ judgeVisibleVariantResults,
3257
+ {
3258
+ taskId,
3259
+ aiJudgeTelemetry: true,
3260
+ aiJudgeRun,
3261
+ aiJudgePrimary,
3262
+ anonymizeJudge: config.judgeConfig?.anonymizeJudge,
3263
+ judgeAllowUnsafeModel: config.judgeConfig?.allowUnsafeModel === true,
3264
+ // The flywheel owns the explicit Matrix escalation block below;
3265
+ // opt out of the coordinator's automatic Matrix run to avoid a
3266
+ // duplicate Matrix call.
3267
+ autoMatrix: false
3268
+ }
3269
+ );
3270
+ latestMainJudgeResult = judgeResult;
3271
+ if (isJudgeType(judgeResult.synthesisContext?.selectedJudge)) {
3272
+ matrixDefaultWinnerSource = judgeResult.synthesisContext.selectedJudge;
3273
+ }
3274
+ latestJudgeEscalation = judgeResult.decision?.escalation;
3275
+ judgedWinner = judgeResult.winner;
3276
+ aiJudgeInvoked = true;
3277
+ for (const candidate of candidates) {
3278
+ if (!finishedExecutionKeys.has(variantIdForSpec(candidate.variant))) continue;
3279
+ const matchingResult = matchVariantResult(candidate.variant, basicResult.variants);
3280
+ if (!matchingResult) continue;
3281
+ const updated = variantResultToCandidate(candidate.variant, matchingResult);
3282
+ candidate.score = updated.score;
3283
+ candidate.feedback = updated.feedback;
3284
+ }
3285
+ recordDeterministicTestSignalObservation(candidates, options.verbose);
3286
+ if (options.verbose) {
3287
+ console.log(chalk.green(" ok AI judge evaluation complete"));
3288
+ }
3289
+ } catch (error) {
3290
+ const errorMsg = error instanceof Error ? error.message : String(error);
3291
+ if (options.verbose) {
3292
+ console.warn(chalk.yellow(` AI judge invocation failed: ${errorMsg}`));
3293
+ }
3294
+ aiJudgeError = errorMsg;
3295
+ aiJudgeInvoked = false;
3296
+ }
3297
+ }
3298
+ }
3299
+ let winnerInfo = aiJudgeInvoked ? buildWinnerInfoFromJudgeVerdict(candidates, judgedWinner, finishedCandidates) : determineWinner(candidates, config, expectedAllowlist);
3300
+ if (aiJudgeError && shouldInvokeAiJudge) {
3301
+ winnerInfo = {
3302
+ winner: null,
3303
+ rankings: [],
3304
+ wasTie: false,
3305
+ noWinnerReason: "judge-error",
3306
+ tieBreaker: void 0
3307
+ };
3308
+ }
3309
+ if (!aiJudgeInvoked && usedCoverageScoring && winnerInfo.wasTie && config.judgeConfig && candidates.length > 1) {
3310
+ const successful = candidates.filter((c) => c.success && typeof c.score === "number");
3311
+ const SCORE_COLLISION_DECIMALS = 6;
3312
+ const SCORE_COLLISION_MULTIPLIER = 10 ** SCORE_COLLISION_DECIMALS;
3313
+ const quantizeScore = (score) => {
3314
+ if (!Number.isFinite(score)) return 0;
3315
+ return Math.round(score * SCORE_COLLISION_MULTIPLIER) / SCORE_COLLISION_MULTIPLIER;
3316
+ };
3317
+ const topScoreRaw = successful.reduce((max, c) => Math.max(max, c.score ?? 0), -Infinity);
3318
+ const topScoreQuantized = quantizeScore(topScoreRaw);
3319
+ const tiedAtTop = successful.filter(
3320
+ (c) => quantizeScore(Number(c.score ?? 0)) === topScoreQuantized
3321
+ );
3322
+ if (tiedAtTop.length >= 2) {
3323
+ const first = tiedAtTop[0];
3324
+ const getCandidateChangedFileCount = (candidate) => Array.isArray(candidate.changedFiles) ? candidate.changedFiles.length : 0;
3325
+ const getCandidateDriftViolations = (candidate) => {
3326
+ if (!Array.isArray(candidate.changedFiles) || candidate.changedFiles.length === 0)
3327
+ return 0;
3328
+ if (!Array.isArray(expectedAllowlist) || expectedAllowlist.length === 0) return 0;
3329
+ return findAllowlistViolations(candidate.changedFiles, expectedAllowlist).length;
3330
+ };
3331
+ const allSameDrift = first ? tiedAtTop.every(
3332
+ (c) => getCandidateDriftViolations(c) === getCandidateDriftViolations(first)
3333
+ ) : false;
3334
+ const allSameDiff = first ? tiedAtTop.every(
3335
+ (c) => getCandidateChangedFileCount(c) === getCandidateChangedFileCount(first)
3336
+ ) : false;
3337
+ if (allSameDrift && allSameDiff && typeof options.workerCwd === "string") {
3338
+ try {
3339
+ const { aiJudgeRun, aiJudgePrimary } = deriveAiJudgeInvocationArgs(config.judgeConfig);
3340
+ const tiedVariantResults = tiedAtTop.map((candidate) => matchVariantResult(candidate.variant, basicResult.variants)).filter(Boolean);
3341
+ if (tiedVariantResults.length >= 2) {
3342
+ const tiebreakJudgeResult = await selectWinnerWithJudge(
3343
+ resolvedPrompt,
3344
+ tiedVariantResults,
3345
+ {
3346
+ taskId,
3347
+ evaluationPhase: "tiebreak",
3348
+ aiJudgeTelemetry: true,
3349
+ aiJudgeRun,
3350
+ aiJudgePrimary,
3351
+ anonymizeJudge: config.judgeConfig?.anonymizeJudge,
3352
+ judgeAllowUnsafeModel: config.judgeConfig?.allowUnsafeModel === true,
3353
+ // Matrix escalation for this stage is owned by the explicit
3354
+ // block keyed off the main judge's escalation; keep the
3355
+ // tie-breaker from launching its own automatic Matrix run.
3356
+ autoMatrix: false
3357
+ }
3358
+ );
3359
+ latestTiebreakJudgeResult = tiebreakJudgeResult;
3360
+ const tiebreakWinner = tiebreakJudgeResult.winner;
3361
+ if (tiebreakWinner) {
3362
+ const winningCandidate = findCandidateForVariantResult(candidates, tiebreakWinner);
3363
+ if (winningCandidate) {
3364
+ tieBreakAiJudgeInvoked = true;
3365
+ winnerInfo = {
3366
+ ...winnerInfo,
3367
+ winner: winningCandidate
3368
+ };
3369
+ }
3370
+ }
3371
+ }
3372
+ } catch (error) {
3373
+ if (options.verbose) {
3374
+ console.warn(chalk.yellow(` AI judge tie-breaker failed: ${String(error)}`));
3375
+ }
3376
+ }
3377
+ }
3378
+ }
3379
+ }
3380
+ const defaultWinnerCandidate = winnerInfo.winner;
3381
+ if (latestJudgeEscalation?.recommended === "matrix" && eligibleVariantResultsForMatrix.length >= 2) {
3382
+ const matrixPolicy = resolveMatrixAuthorityPolicy(config.judgeConfig?.matrixAuthority);
3383
+ effectiveMatrixAuthority = matrixPolicy;
3384
+ try {
3385
+ const matrixCoordinator = new JudgeCoordinator();
3386
+ const matrixResult = await matrixCoordinator.evaluateProfileMatrix(
3387
+ eligibleVariantResultsForMatrix,
3388
+ resolvedPrompt,
3389
+ {
3390
+ taskId,
3391
+ anonymizeJudge: config.judgeConfig?.anonymizeJudge,
3392
+ judgeAllowUnsafeModel: config.judgeConfig?.allowUnsafeModel === true,
3393
+ evaluationContext: latestMainJudgeResult?.evaluationContext,
3394
+ matrixEscalationContext: {
3395
+ reasons: latestJudgeEscalation.reasons
3396
+ }
3397
+ }
3398
+ );
3399
+ const defaultWinnerResult = defaultWinnerCandidate ? matchVariantResult(defaultWinnerCandidate.variant, basicResult.variants) : void 0;
3400
+ const defaultWinner = defaultWinnerResult ? `${defaultWinnerResult.provider}:${defaultWinnerResult.variant}` : "none";
3401
+ const authorityDecision = evaluateMatrixAuthority({
3402
+ policy: matrixPolicy,
3403
+ defaultWinner,
3404
+ defaultWinnerSource: matrixDefaultWinnerSource,
3405
+ matrixEvaluatorType: matrixResult.matrixEvaluatorType,
3406
+ matrixResult,
3407
+ variants: eligibleVariantResultsForMatrix
3408
+ });
3409
+ matrixRan = true;
3410
+ matrixProfileAgreement = authorityDecision.profileAgreement;
3411
+ if (authorityDecision.selectedByMatrix && authorityDecision.matrixWinner && isAcceptedMatrixVerdict(authorityDecision.winnerStatus)) {
3412
+ const matrixWinnerCandidate = findCandidateForVariantResult(
3413
+ candidates,
3414
+ authorityDecision.matrixWinner
3415
+ );
3416
+ if (matrixWinnerCandidate) {
3417
+ winnerInfo = {
3418
+ ...winnerInfo,
3419
+ winner: matrixWinnerCandidate
3420
+ };
3421
+ } else {
3422
+ matrixAuthorityWarnings.push(
3423
+ "Matrix authority selected a variant that could not be resolved to a candidate"
3424
+ );
3425
+ }
3426
+ } else {
3427
+ if (!isAcceptedMatrixVerdict(authorityDecision.winnerStatus) && authorityDecision.nonSelectionReasons.length === 0) {
3428
+ matrixAuthorityNonSelectionReasons.push(
3429
+ `matrix winner status is ${authorityDecision.winnerStatus}`
3430
+ );
3431
+ }
3432
+ if (authorityDecision.winnerStatus === "conditional") {
3433
+ matrixAuthorityNonSelectionReasons.push(
3434
+ ...authorityDecision.winnerCaveats.slice(0, 3)
3435
+ );
3436
+ }
3437
+ if (authorityDecision.nonSelectionReasons.length > 0) {
3438
+ matrixAuthorityNonSelectionReasons.push(
3439
+ ...authorityDecision.nonSelectionReasons.slice(0, 3)
3440
+ );
3441
+ }
3442
+ }
3443
+ } catch (error) {
3444
+ matrixAuthorityWarnings.push(`Matrix authority evaluation failed: ${String(error)}`);
3445
+ }
3446
+ }
3447
+ const successCount = candidates.filter((c) => c.success).length;
3448
+ const persistedAiJudgeInvoked = tieBreakAiJudgeInvoked || aiJudgeInvoked;
3449
+ const persistedScoringMode = aiJudgeInvoked ? "ai-judge" : tieBreakAiJudgeInvoked ? "hybrid" : "deterministic";
3450
+ const persistedJudgeInvocationReason = aiJudgeError ? "error" : tieBreakAiJudgeInvoked || aiJudgeInvoked ? "multiple-successful-candidates" : successCount === 0 ? "no-successful-candidates" : successCount === 1 ? "single-successful-candidate" : "deterministic-shortcut";
3451
+ const judgeResultForEvidence = latestMainJudgeResult ?? latestTiebreakJudgeResult;
3452
+ const hasNewJudgeSchemaFields = config.judgeConfig?.judgeRun !== void 0 || config.judgeConfig?.matrixAuthority !== void 0 || matrixRan;
3453
+ const persistedMatrixAuthority = effectiveMatrixAuthority ?? (config.judgeConfig?.matrixAuthority !== void 0 ? resolveMatrixAuthorityPolicy(config.judgeConfig.matrixAuthority) : void 0);
3454
+ const { judgeRunRequested } = deriveAiJudgeInvocationArgs(config.judgeConfig);
3455
+ const multiJudgeEvidence = hasNewJudgeSchemaFields ? buildMultiJudgeEvidenceBlock({
3456
+ judgeResult: judgeResultForEvidence,
3457
+ judgeRunRequested,
3458
+ matrixAuthority: persistedMatrixAuthority,
3459
+ matrixRan,
3460
+ matrixProfileAgreement,
3461
+ matrixNonSelectionReasons: matrixAuthorityNonSelectionReasons
3462
+ }) : void 0;
3463
+ try {
3464
+ await artifactStore.save(stage.id, "candidates", "json", {
3465
+ taskId,
3466
+ variantCount: candidates.length,
3467
+ successCount: candidates.filter((c) => c.success).length,
3468
+ candidates: candidates.map((c) => ({
3469
+ provider: c.variant.provider,
3470
+ model: c.variant.model,
3471
+ success: c.success,
3472
+ score: c.score,
3473
+ error: c.error,
3474
+ cost: c.cost,
3475
+ costUnavailableReason: c.costUnavailableReason
3476
+ })),
3477
+ winner: winnerInfo.winner ? {
3478
+ provider: winnerInfo.winner.variant.provider,
3479
+ model: winnerInfo.winner.variant.model,
3480
+ score: winnerInfo.winner.score
3481
+ } : null,
3482
+ rankings: winnerInfo.rankings,
3483
+ aiJudgeInvoked: persistedAiJudgeInvoked,
3484
+ scoringMode: persistedScoringMode,
3485
+ judgeInvocationReason: persistedJudgeInvocationReason,
3486
+ ...multiJudgeEvidence ? { multiJudgeEvidence } : {}
3487
+ });
3488
+ await artifactStore.save(
3489
+ stage.id,
3490
+ "bundle",
3491
+ "text",
3492
+ buildCompetitionBundle(taskId, candidates, basicResult)
3493
+ );
3494
+ if (winnerInfo.winner) {
3495
+ await artifactStore.save(stage.id, "winner", "json", {
3496
+ variant: winnerInfo.winner.variant,
3497
+ score: winnerInfo.winner.score,
3498
+ feedback: winnerInfo.winner.feedback,
3499
+ commitSha: winnerInfo.winner.commitSha,
3500
+ changedFiles: winnerInfo.winner.changedFiles
3501
+ });
3502
+ }
3503
+ const winnerResult = winnerInfo.winner ? matchVariantResult(winnerInfo.winner.variant, basicResult.variants) : void 0;
3504
+ const winnerDiff = typeof winnerResult?.worktreeDiff === "string" ? winnerResult.worktreeDiff : "";
3505
+ await artifactStore.save(stage.id, "winnerDiff", "diff", winnerDiff);
3506
+ let rationalePacket = basicResult.variants.find((v) => v.judgeEvaluation?.rationalePacket)?.judgeEvaluation?.rationalePacket;
3507
+ if (!rationalePacket) {
3508
+ rationalePacket = synthesizeDeterministicRationalePacket(candidates, winnerInfo, config);
3509
+ } else {
3510
+ const judgedCandidate = judgeResultForEvidence ? judgeResultForEvidence.winner ? findCandidateForVariantResult(candidates, judgeResultForEvidence.winner) : null : void 0;
3511
+ rationalePacket = reconcileJudgeRationaleWinner(
3512
+ rationalePacket,
3513
+ judgedCandidate,
3514
+ winnerInfo.winner,
3515
+ judgeResultForEvidence !== void 0
3516
+ );
3517
+ }
3518
+ await artifactStore.save(stage.id, "judgeRationale", "json", rationalePacket);
3519
+ for (const [index, candidate] of candidates.entries()) {
3520
+ const artifactName = `candidate-${candidate.variant.provider ? `${candidate.variant.provider}-` : ""}${index + 1}`;
3521
+ const matchingResult = matchVariantResult(candidate.variant, basicResult.variants);
3522
+ await artifactStore.save(stage.id, artifactName, "json", {
3523
+ candidate,
3524
+ variantResult: matchingResult ? {
3525
+ provider: matchingResult.provider,
3526
+ model: matchingResult.model,
3527
+ success: matchingResult.success,
3528
+ completeness: matchingResult.completeness,
3529
+ judgeScore: matchingResult.judgeScore,
3530
+ worktreeDiff: matchingResult.worktreeDiff,
3531
+ worktreeDiffReplayable: matchingResult.worktreeDiffReplayable,
3532
+ baselineRef: matchingResult.baselineRef,
3533
+ worktreeSummary: matchingResult.worktreeSummary,
3534
+ retainedWorktreePath: matchingResult.retainedWorktreePath,
3535
+ logFilePath: matchingResult.logFilePath,
3536
+ logTail: matchingResult.logTail,
3537
+ costMetrics: matchingResult.costMetrics,
3538
+ error: matchingResult.error?.message
3539
+ } : null
3540
+ });
3541
+ candidate.resultArtifactPath = `${stage.id}.${artifactName}`;
3542
+ }
3543
+ } catch (error) {
3544
+ if (options.verbose) {
3545
+ console.warn(chalk.yellow(` Warning: Failed to persist competition artifacts: ${error}`));
3546
+ }
3547
+ }
3548
+ const coherenceMetrics = computeCoherenceMetrics(
3549
+ candidates,
3550
+ DEFAULT_COHERENCE_THRESHOLD,
3551
+ expectedAllowlist
3552
+ );
3553
+ const markedIncomparable = !coherenceMetrics.isCoherent;
3554
+ const warnings = [];
3555
+ if (markedIncomparable) {
3556
+ warnings.push(
3557
+ `Low coherence between successful candidates (avg ${coherenceMetrics.averageSimilarity.toFixed(2)} < ${coherenceMetrics.coherenceThreshold.toFixed(2)})`
3558
+ );
3559
+ }
3560
+ if (aiJudgeError) {
3561
+ warnings.push(`AI judge invocation failed: ${aiJudgeError}`);
3562
+ }
3563
+ if (winnerInfo.noWinnerDiagnostic) {
3564
+ warnings.push(winnerInfo.noWinnerDiagnostic);
3565
+ }
3566
+ warnings.push(...matrixAuthorityWarnings);
3567
+ if (winnerInfo.belowThresholdWinner) {
3568
+ warnings.push(
3569
+ `Winner selected below threshold (${winnerInfo.belowThresholdWinner.winnerScore} < ${winnerInfo.belowThresholdWinner.threshold})`
3570
+ );
3571
+ }
3572
+ const driftContext = computeCompetitionDrift(candidates, expectedAllowlist, effectiveMode);
3573
+ try {
3574
+ await artifactStore.save(stage.id, "stage-change", "json", {
3575
+ stageId: stage.id,
3576
+ stageType: "competition",
3577
+ mode: effectiveMode,
3578
+ deliveredFiles: driftContext.deliveredFiles,
3579
+ expectedFiles: driftContext.expectedFiles,
3580
+ violations: driftContext.violations,
3581
+ hasDrift: driftContext.hasDrift,
3582
+ candidateCount: candidates.length,
3583
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
3584
+ });
3585
+ await artifactStore.save(stage.id, "stage-change-summary", "text", driftContext.summary);
3586
+ } catch (error) {
3587
+ if (options.verbose) {
3588
+ console.warn(chalk.yellow(` Warning: Failed to persist drift context: ${error}`));
3589
+ }
3590
+ }
3591
+ const effectiveWinnerInfo = winnerInfo;
3592
+ const winnerTestsNotApplicable = effectiveWinnerInfo.winner !== null && winnerHasNoApplicableTests(effectiveWinnerInfo.winner) && candidateGatePassedVariantIds.has(variantIdForSpec(effectiveWinnerInfo.winner.variant));
3593
+ const winnerTrustedTestStatus = effectiveWinnerInfo.winner ? resolveTrustedCandidateTestStatus(effectiveWinnerInfo.winner) : void 0;
3594
+ const winnerRepairSuperseded = winnerTrustedTestStatus !== effectiveWinnerInfo.winner?.testStatus;
3595
+ const winnerVerificationAllowsSuccess = effectiveWinnerInfo.winner ? verificationPolarityAllowsStageSuccess({
3596
+ verification: effectiveWinnerInfo.winner.verification,
3597
+ testStatus: winnerTestsNotApplicable ? void 0 : winnerTrustedTestStatus,
3598
+ rawTestStatus: winnerTestsNotApplicable ? void 0 : winnerTrustedTestStatus,
3599
+ // The stale pre-repair exit code restates the superseded failure.
3600
+ exitCode: winnerTestsNotApplicable || winnerRepairSuperseded ? void 0 : effectiveWinnerInfo.winner.testsExecuted?.exitCode
3601
+ }) : false;
3602
+ const validationPassed = successCount > 0 && effectiveWinnerInfo.winner !== null && winnerVerificationAllowsSuccess;
3603
+ let summary = buildCompetitionSummary(candidates, effectiveWinnerInfo, config);
3604
+ if (aiJudgeError && shouldInvokeAiJudge) {
3605
+ summary = `Competition failed: AI judge invocation failed: ${aiJudgeError}`;
3606
+ }
3607
+ if (markedIncomparable) {
3608
+ summary += ` (low coherence: ${coherenceMetrics.averageSimilarity.toFixed(2)})`;
3609
+ }
3610
+ const scoringMode = aiJudgeInvoked ? "ai-judge" : tieBreakAiJudgeInvoked ? "hybrid" : "deterministic";
3611
+ const judgeInvocationReason = aiJudgeError ? "error" : tieBreakAiJudgeInvoked || aiJudgeInvoked ? "multiple-successful-candidates" : successCount === 0 ? "no-successful-candidates" : successCount === 1 ? "single-successful-candidate" : "deterministic-shortcut";
3612
+ const winnerNeedsRepair = Boolean(
3613
+ effectiveWinnerInfo.winner?.verification && !effectiveWinnerInfo.winner.verification.passed
3614
+ );
3615
+ const stageVerification = effectiveWinnerInfo.winner?.verification;
3616
+ const result = {
3617
+ stageId: stage.id,
3618
+ stageType: "competition",
3619
+ competitionTaskId: taskId,
3620
+ validationPassed,
3621
+ validationScore: effectiveWinnerInfo.winner?.score,
3622
+ cost: totalCost,
3623
+ costUnavailableReason,
3624
+ warnings: warnings.length > 0 ? warnings : void 0,
3625
+ summary,
3626
+ durationMs: Date.now() - startTime,
3627
+ candidates,
3628
+ winner: effectiveWinnerInfo.winner,
3629
+ winnerApplied: false,
3630
+ // MVP: winner application happens in the workflow executor
3631
+ winnerNeedsRepair,
3632
+ verification: stageVerification,
3633
+ coherenceMetrics,
3634
+ markedIncomparable,
3635
+ scoringMode,
3636
+ competitionJudgeResult: {
3637
+ judgeType: config.judgeConfig?.type ?? "ai",
3638
+ aiJudgeAttempted,
3639
+ aiJudgeInvoked: tieBreakAiJudgeInvoked || aiJudgeInvoked,
3640
+ aiJudgeError,
3641
+ aiJudgeProviderFailed: judgeProviderFailed(latestMainJudgeResult?.decision) || void 0,
3642
+ judgeInvocationReason,
3643
+ rankings: effectiveWinnerInfo.rankings,
3644
+ wasTie: effectiveWinnerInfo.wasTie,
3645
+ noWinnerReason: effectiveWinnerInfo.noWinnerReason,
3646
+ belowThresholdWinner: effectiveWinnerInfo.belowThresholdWinner,
3647
+ tieBreaker: effectiveWinnerInfo.tieBreaker,
3648
+ scoreCollisionReport: effectiveWinnerInfo.scoreCollisionReport
3649
+ },
3650
+ driftContext
3651
+ };
3652
+ if (!validationPassed && effectiveWinnerInfo.winner && successCount > 0 && !aiJudgeError) {
3653
+ const refusal = resolveWinnerDeliveryRefusalReason(result);
3654
+ if (refusal) result.summary = `${summary}; winner not accepted: ${refusal}`;
3655
+ }
3656
+ if (options.verbose) {
3657
+ console.log(chalk.green(" ok Competition complete"));
3658
+ console.log(
3659
+ chalk.gray(
3660
+ ` Winner: ${effectiveWinnerInfo.winner ? formatCompetitionCandidateVariantDisplay(effectiveWinnerInfo.winner) : "none"}`
3661
+ )
3662
+ );
3663
+ console.log(
3664
+ chalk.gray(
3665
+ ` Total cost: ${costUnavailableReason !== void 0 ? "unavailable" : `$${totalCost.toFixed(4)}`}`
3666
+ )
3667
+ );
3668
+ console.log(
3669
+ chalk.gray(
3670
+ ` Coherence: ${coherenceMetrics.averageSimilarity.toFixed(2)} (${coherenceMetrics.isCoherent ? "coherent" : "INCOHERENT"})`
3671
+ )
3672
+ );
3673
+ if (driftContext.hasDrift) {
3674
+ console.log(
3675
+ chalk.yellow(
3676
+ ` Drift: ${driftContext.violations.length} file(s) outside allowlist (mode: ${effectiveMode})`
3677
+ )
3678
+ );
3679
+ }
3680
+ }
3681
+ const authoritativeWinner = effectiveWinnerInfo.winner ? matchVariantResult(effectiveWinnerInfo.winner.variant, basicResult.variants) : void 0;
3682
+ if (effectiveWinnerInfo.winner && !authoritativeWinner) {
3683
+ const errorMessage = "Final competition winner could not be resolved to an executed variant";
3684
+ await finalizeDeferredHandle(
3685
+ createEvaluationHandleFinalState({ outcome: "error", winner: null, errorMessage })
3686
+ );
3687
+ await cleanupSynthesisInputPatches(basicResult.variants, {
3688
+ expectedRoot: resolveSynthesisInputPatchDir(
3689
+ competitionOptions.executionContext.buildDir,
3690
+ taskId
3691
+ )
3692
+ });
3693
+ throw new Error(errorMessage);
3694
+ }
3695
+ await finalizeDeferredHandle(
3696
+ authoritativeWinner ? createEvaluationHandleFinalState({
3697
+ outcome: "winner_selected",
3698
+ winner: toEvaluationHandleWinnerMetadata(authoritativeWinner)
3699
+ }) : createEvaluationHandleFinalState({
3700
+ outcome: successCount === 0 ? "all_failed" : "no_winner",
3701
+ winner: null
3702
+ })
3703
+ );
3704
+ await cleanupSynthesisInputPatches(basicResult.variants, {
3705
+ expectedRoot: resolveSynthesisInputPatchDir(
3706
+ competitionOptions.executionContext.buildDir,
3707
+ taskId
3708
+ )
3709
+ });
3710
+ return result;
3711
+ } catch (error) {
3712
+ const errorMessage = error instanceof Error ? error.message : String(error);
3713
+ if (!deferredHandleFinalized) {
3714
+ await finalizeEvaluationHandleAsync(
3715
+ taskId,
3716
+ createEvaluationHandleFinalState({ outcome: "error", winner: null, errorMessage })
3717
+ ).catch(() => {
3718
+ });
3719
+ }
3720
+ await cleanupSynthesisInputPatches(basicResult.variants, {
3721
+ expectedRoot: resolveSynthesisInputPatchDir(
3722
+ competitionOptions.executionContext.buildDir,
3723
+ taskId
3724
+ )
3725
+ }).catch(() => {
3726
+ });
3727
+ return {
3728
+ stageId: stage.id,
3729
+ stageType: "competition",
3730
+ competitionTaskId: taskId,
3731
+ validationPassed: false,
3732
+ ...observedCandidates ? resolveCompetitionCostAggregate(observedCandidates) : { cost: 0, costUnavailableReason: "provider_not_reported" },
3733
+ candidates: observedCandidates ?? [],
3734
+ winner: null,
3735
+ summary: `Competition post-processing failed: ${errorMessage}`,
3736
+ durationMs: Date.now() - startTime,
3737
+ competitionJudgeResult: {
3738
+ judgeType: config.judgeConfig?.type ?? "ai",
3739
+ aiJudgeAttempted,
3740
+ aiJudgeInvoked: tieBreakAiJudgeInvoked || aiJudgeInvoked,
3741
+ aiJudgeError: errorMessage,
3742
+ judgeInvocationReason: "error",
3743
+ rankings: [],
3744
+ wasTie: false,
3745
+ noWinnerReason: "judge-error"
3746
+ }
3747
+ };
3748
+ }
3749
+ }
3750
+ function buildCompetitionSummary(candidates, winnerInfo, config) {
3751
+ const successCount = candidates.filter((c) => c.success).length;
3752
+ const failCount = candidates.length - successCount;
3753
+ let summary = `Competition: ${successCount}/${candidates.length} variants succeeded`;
3754
+ if (failCount > 0) {
3755
+ summary += ` (${failCount} failed)`;
3756
+ }
3757
+ if (winnerInfo.winner) {
3758
+ summary += `. ${competitionPickLabel(successCount)}: ${formatCompetitionCandidateVariantDisplay(winnerInfo.winner)}`;
3759
+ if (winnerInfo.winner.score !== void 0) {
3760
+ summary += ` (score: ${winnerInfo.winner.score})`;
3761
+ }
3762
+ if (winnerInfo.belowThresholdWinner) {
3763
+ summary += ` (below threshold: ${winnerInfo.belowThresholdWinner.winnerScore} < ${winnerInfo.belowThresholdWinner.threshold})`;
3764
+ }
3765
+ } else if (winnerInfo.noWinnerReason) {
3766
+ const reasons = {
3767
+ "all-failed": "all variants failed",
3768
+ tie: "tie between top variants",
3769
+ "below-threshold": `all scores below threshold (${config.judgeConfig?.threshold ?? 0})`,
3770
+ "judge-error": "judge evaluation failed",
3771
+ incomparable: "candidates touched disjoint files (low coherence)"
3772
+ };
3773
+ summary += `. No winner: ${reasons[winnerInfo.noWinnerReason] ?? winnerInfo.noWinnerReason}`;
3774
+ }
3775
+ return summary;
3776
+ }
3777
+ function isCompetitionStage(stage) {
3778
+ return stage.type === "competition" && stage.competition !== void 0;
3779
+ }
3780
+
3781
+ export {
3782
+ selectFailingGateFindings,
3783
+ gateEvidenceField,
3784
+ persistGateEvidenceArtifact,
3785
+ verificationPolarityAllowsStageSuccess,
3786
+ describeStageValidationFailure,
3787
+ resolveWinnerDeliveryRefusalReason,
3788
+ shouldRestrictWinnerPatchToAllowlist,
3789
+ applyCompetitionWinnerPatch,
3790
+ computeCoherenceMetrics,
3791
+ __internalDetermineWinner,
3792
+ __internalRecordDeterministicTestSignalObservation,
3793
+ __internalExtractChangedFilesFromResult,
3794
+ __internalGetVariantTelemetryStatePath,
3795
+ __internalHydrateCandidateCostsFromTelemetry,
3796
+ __internalVariantResultToCandidate,
3797
+ __internalMatchVariantResult,
3798
+ __internalCandidateMatchesVariantResult,
3799
+ __internalResolveCompetitionCostAggregate,
3800
+ executeCompetitionStage,
3801
+ isCompetitionStage
3802
+ };
3803
+ //# sourceMappingURL=chunk-3NOTLVLG.js.map