@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,2896 @@
1
+ import {
2
+ classifyTask,
3
+ classifyTaskForRouting,
4
+ stripPromptInjections,
5
+ toCanonicalRoutingClassificationInput
6
+ } from "./chunk-JHP7OT6K.js";
7
+ import {
8
+ getP1SemanticChecks
9
+ } from "./chunk-G6OIMVXH.js";
10
+ import {
11
+ assertReviewerOrderUsable,
12
+ resolveReviewerEligibility
13
+ } from "./chunk-JDCZQZU7.js";
14
+ import {
15
+ applyExecutionPolicy,
16
+ describeExecutionPolicyStampMismatch,
17
+ isCurrentExecutionPolicyWorkflow,
18
+ isExecutionPolicyEngaged
19
+ } from "./chunk-YTVVTIWJ.js";
20
+ import {
21
+ expectsCodeEdits,
22
+ extractTaskContract
23
+ } from "./chunk-SU6UFUQY.js";
24
+ import {
25
+ parsePromptSpec
26
+ } from "./chunk-INJ3SS6A.js";
27
+ import {
28
+ getTask
29
+ } from "./chunk-7LHJDJB3.js";
30
+ import {
31
+ TaskTypeAliasMap
32
+ } from "./chunk-2KO7HVZM.js";
33
+ import {
34
+ hasUnfilledMarkers
35
+ } from "./chunk-UAPHFJPN.js";
36
+ import {
37
+ TaskTypeRegistry
38
+ } from "./chunk-6T6NHXK4.js";
39
+ import {
40
+ buildPromptFromTask,
41
+ parseTaskBody,
42
+ stripTaskHeaderMetadata
43
+ } from "./chunk-US3RT6CY.js";
44
+ import {
45
+ classifyIntent
46
+ } from "./chunk-GI5M67YA.js";
47
+ import {
48
+ extractAcceptanceCriteria
49
+ } from "./chunk-XON4ZCYX.js";
50
+ import {
51
+ classifyExplicitNoEdit
52
+ } from "./chunk-PPHXX4W7.js";
53
+ import {
54
+ classifyTaskDependency
55
+ } from "./chunk-NXH3RX7O.js";
56
+ import {
57
+ extractCreateAnnotatedFilePaths
58
+ } from "./chunk-ETA2K4KI.js";
59
+ import {
60
+ getPlanningRoot
61
+ } from "./chunk-CSXLLEGB.js";
62
+ import {
63
+ getBucketArchivePathByKind,
64
+ getBucketPathByKind
65
+ } from "./chunk-V3KLVK7B.js";
66
+ import {
67
+ resolveExecutionRoles
68
+ } from "./chunk-32IYXIE5.js";
69
+ import {
70
+ getWorkflowYamlPath
71
+ } from "./chunk-6TRD7TEE.js";
72
+ import {
73
+ resolveCandidates,
74
+ resolveDefaultProvider,
75
+ resolveJudgeType,
76
+ resolveProviderModel,
77
+ resolveProviderReasoningEffort
78
+ } from "./chunk-C3DH3NCY.js";
79
+ import {
80
+ PROVIDER_REGISTRY_CONFIG_PATHS,
81
+ classifyRepoPath,
82
+ shouldIgnoreRepoPath
83
+ } from "./chunk-RBBTBCHX.js";
84
+ import {
85
+ hasKnownVerifyExecutable,
86
+ partitionVerifyCommands
87
+ } from "./chunk-AHU3FKPA.js";
88
+ import {
89
+ getProjectReferencePathExtensions
90
+ } from "./chunk-RPIMAMV7.js";
91
+ import {
92
+ resolveExecutionBoundary
93
+ } from "./chunk-2VUEDIUM.js";
94
+ import {
95
+ matchesFamilyAlias
96
+ } from "./chunk-FAZBRHGG.js";
97
+ import {
98
+ execGit
99
+ } from "./chunk-MHLEZQQI.js";
100
+ import {
101
+ ProviderRegistry
102
+ } from "./chunk-QJ6OEH4K.js";
103
+ import {
104
+ normalizeReasoningEffortInput
105
+ } from "./chunk-4BTDUT2S.js";
106
+ import {
107
+ listMarkdownFilesRecursive,
108
+ readMarkdownFile
109
+ } from "./chunk-352PCJLK.js";
110
+ import {
111
+ BUILD_TASK_TYPE_MIN_CONFIDENCE,
112
+ readEnv
113
+ } from "./chunk-7VRJHTGZ.js";
114
+
115
+ // src/core/providers/routing/registry-capability-reader.ts
116
+ var NOMINAL_INPUT_TOKENS = 5e3;
117
+ var NOMINAL_OUTPUT_TOKENS = 2e3;
118
+ function perMillion(per1m, per1k) {
119
+ if (typeof per1m === "number") return per1m;
120
+ if (typeof per1k === "number") return per1k * 1e3;
121
+ return void 0;
122
+ }
123
+ function toModelPricing(pricing) {
124
+ return {
125
+ inputPer1m: perMillion(pricing.input_per_1m_tokens, pricing.input_per_1k_tokens),
126
+ outputPer1m: perMillion(pricing.output_per_1m_tokens, pricing.output_per_1k_tokens)
127
+ };
128
+ }
129
+ function resolveConfiguredModel(providerId, model, registry) {
130
+ return ProviderRegistry.resolveModel(providerId, model, registry);
131
+ }
132
+ function toRegistryRoutingSnapshot(config, registry) {
133
+ const pricingByModel = {};
134
+ for (const [modelId, pricing] of Object.entries(config.pricing?.models ?? {})) {
135
+ pricingByModel[modelId] = toModelPricing(pricing);
136
+ }
137
+ const roles = config.models.roles ?? {};
138
+ const resolvedRoles = {};
139
+ for (const [role, roleModel] of Object.entries(roles)) {
140
+ resolvedRoles[role] = resolveConfiguredModel(config.id, roleModel, registry);
141
+ }
142
+ return {
143
+ id: config.id,
144
+ enabled: config.enabled,
145
+ order: config.order,
146
+ defaultModel: resolveConfiguredModel(config.id, config.models.default, registry),
147
+ modelRoles: resolvedRoles,
148
+ mappings: { ...config.models.mappings ?? {} },
149
+ allowedPatterns: [...config.models.allowed_patterns ?? []],
150
+ // Overlay and consumer registries predate this field, so read it defensively
151
+ // rather than trusting the schema default to have been applied.
152
+ familyAliases: Array.isArray(config.models.family_aliases) ? [...config.models.family_aliases] : [],
153
+ models: config.models.available.map((model) => ({
154
+ id: model.id,
155
+ capabilities: [...model.capabilities]
156
+ })),
157
+ operational: {
158
+ streaming: config.capabilities.streaming,
159
+ toolUse: config.capabilities.tool_use,
160
+ vision: config.capabilities.vision,
161
+ functionCalling: config.capabilities.function_calling
162
+ },
163
+ currency: config.pricing?.currency ?? "USD",
164
+ pricingByModel
165
+ };
166
+ }
167
+ function readEnabledRegistryRoutingSnapshots(registry) {
168
+ return ProviderRegistry.getEnabledProviders(registry).map(
169
+ (config) => toRegistryRoutingSnapshot(config, registry)
170
+ );
171
+ }
172
+ function readRegistryRoutingSnapshot(providerId, registry) {
173
+ try {
174
+ return toRegistryRoutingSnapshot(
175
+ ProviderRegistry.getProviderConfig(providerId, registry),
176
+ registry
177
+ );
178
+ } catch {
179
+ return void 0;
180
+ }
181
+ }
182
+ function estimateAdvisoryUsd(snapshot, modelId) {
183
+ const pricing = snapshot.pricingByModel[modelId] ?? snapshot.pricingByModel[modelId.toLowerCase()] ?? Object.entries(snapshot.pricingByModel).find(
184
+ ([key]) => key.toLowerCase() === modelId.toLowerCase()
185
+ )?.[1];
186
+ if (!pricing) return null;
187
+ if (pricing.inputPer1m == null && pricing.outputPer1m == null) return null;
188
+ return ((pricing.inputPer1m ?? 0) * NOMINAL_INPUT_TOKENS + (pricing.outputPer1m ?? 0) * NOMINAL_OUTPUT_TOKENS) / 1e6;
189
+ }
190
+
191
+ // src/core/routing/canonical-candidates.ts
192
+ var REASONING_CATEGORIES = /* @__PURE__ */ new Set(["analyze", "review"]);
193
+ var REASONING_ACTIVITIES = /* @__PURE__ */ new Set(["planning", "research", "architecture", "design"]);
194
+ function preferredModelRole(_classification) {
195
+ return void 0;
196
+ }
197
+ function canonicalInventoryModelId(snapshot, model) {
198
+ const needle = model.trim();
199
+ if (!needle) return void 0;
200
+ const exact = snapshot.models.find((entry) => entry.id === needle);
201
+ if (exact) return exact.id;
202
+ const insensitive = snapshot.models.find(
203
+ (entry) => entry.id.toLowerCase() === needle.toLowerCase()
204
+ );
205
+ return insensitive?.id;
206
+ }
207
+ function mappingTarget(snapshot, model) {
208
+ if (model in snapshot.mappings) {
209
+ return snapshot.mappings[model];
210
+ }
211
+ const match = Object.entries(snapshot.mappings).find(
212
+ ([key]) => key.toLowerCase() === model.toLowerCase()
213
+ );
214
+ return match?.[1];
215
+ }
216
+ function resolveModelAgainstSnapshot(snapshot, model) {
217
+ const trimmed = model.trim();
218
+ if (!trimmed) return void 0;
219
+ const mapped = mappingTarget(snapshot, trimmed);
220
+ if (mapped) {
221
+ return canonicalInventoryModelId(snapshot, mapped) ?? mapped;
222
+ }
223
+ if (matchesFamilyAlias(snapshot.familyAliases, trimmed)) {
224
+ return trimmed;
225
+ }
226
+ for (const pattern of snapshot.allowedPatterns) {
227
+ let regex;
228
+ try {
229
+ regex = new RegExp(pattern);
230
+ } catch {
231
+ continue;
232
+ }
233
+ if (regex.test(trimmed)) {
234
+ return canonicalInventoryModelId(snapshot, trimmed) ?? trimmed;
235
+ }
236
+ }
237
+ return canonicalInventoryModelId(snapshot, trimmed);
238
+ }
239
+ function selectModelForSnapshot(snapshot, role) {
240
+ if (role) {
241
+ const roleModel = snapshot.modelRoles[role];
242
+ if (roleModel) {
243
+ const resolved2 = resolveModelAgainstSnapshot(snapshot, roleModel);
244
+ if (!resolved2) return void 0;
245
+ return {
246
+ model: resolved2,
247
+ source: "classification-role"
248
+ };
249
+ }
250
+ }
251
+ const resolved = resolveModelAgainstSnapshot(snapshot, snapshot.defaultModel);
252
+ if (!resolved) return void 0;
253
+ return {
254
+ model: resolved,
255
+ source: "registry"
256
+ };
257
+ }
258
+ function advisoryCostFor(snapshot, model) {
259
+ const estimatedUsd = estimateAdvisoryUsd(snapshot, model);
260
+ return {
261
+ estimatedUsd,
262
+ currency: snapshot.currency,
263
+ usedInRanking: false,
264
+ source: estimatedUsd == null ? "unknown" : "registry-pricing"
265
+ };
266
+ }
267
+ function modelCapabilitiesFor(snapshot, model) {
268
+ const exact = snapshot.models.find((entry) => entry.id === model);
269
+ if (exact) return [...exact.capabilities];
270
+ const insensitive = snapshot.models.find(
271
+ (entry) => entry.id.toLowerCase() === model.toLowerCase()
272
+ );
273
+ return insensitive ? [...insensitive.capabilities] : [];
274
+ }
275
+ function buildCanonicalRoutingCandidates(options = {}) {
276
+ const snapshots = options.snapshots ?? readEnabledRegistryRoutingSnapshots(options.registry);
277
+ const role = preferredModelRole(options.classification);
278
+ return snapshots.flatMap((snapshot) => {
279
+ const selected = selectModelForSnapshot(snapshot, role);
280
+ if (!selected) return [];
281
+ return [
282
+ {
283
+ provider: snapshot.id,
284
+ model: selected.model,
285
+ registryOrder: snapshot.order,
286
+ defaultModel: selected.model === snapshot.defaultModel,
287
+ modelCapabilities: modelCapabilitiesFor(snapshot, selected.model),
288
+ operational: { ...snapshot.operational },
289
+ advisoryCost: advisoryCostFor(snapshot, selected.model)
290
+ }
291
+ ];
292
+ });
293
+ }
294
+ function classificationFitScore(candidate, classification) {
295
+ if (!classification) return 0;
296
+ const caps = new Set(candidate.modelCapabilities.map((capability) => capability.toLowerCase()));
297
+ let score = 0;
298
+ const wantsReasoning = REASONING_CATEGORIES.has(classification.category) || REASONING_ACTIVITIES.has(classification.activity);
299
+ if (wantsReasoning && (caps.has("reasoning") || caps.has("thinking"))) {
300
+ score += 2;
301
+ }
302
+ if ((classification.category === "execute" || classification.category === "test") && caps.has("code")) {
303
+ score += 2;
304
+ }
305
+ if (classification.category === "document" && (caps.has("fast") || caps.has("docs") || caps.has("documentation"))) {
306
+ score += 1;
307
+ }
308
+ return score;
309
+ }
310
+
311
+ // src/core/routing/canonical-decision.ts
312
+ var CanonicalRoutingError = class extends Error {
313
+ constructor(message) {
314
+ super(message);
315
+ this.name = "CanonicalRoutingError";
316
+ }
317
+ };
318
+ function isFullClassification(value) {
319
+ return "judgeTaskType" in value && "provenance" in value;
320
+ }
321
+ function resolveClassification(input) {
322
+ if (input.classification) {
323
+ return {
324
+ classification: isFullClassification(input.classification) ? toCanonicalRoutingClassificationInput(input.classification) : input.classification,
325
+ source: "input"
326
+ };
327
+ }
328
+ if (input.prompt != null && input.prompt.trim() !== "") {
329
+ return {
330
+ classification: toCanonicalRoutingClassificationInput(classifyTaskForRouting(input.prompt)),
331
+ source: "prompt"
332
+ };
333
+ }
334
+ return { classification: void 0, source: "none" };
335
+ }
336
+ function normalizePin(value) {
337
+ const trimmed = value?.trim();
338
+ return trimmed ? trimmed : void 0;
339
+ }
340
+ function withUsedInRanking(cost, usedInRanking) {
341
+ return { ...cost, usedInRanking };
342
+ }
343
+ function applyModelOverride(candidate, snapshot, model) {
344
+ const estimatedUsd = snapshot ? estimateAdvisoryUsd(snapshot, model) : null;
345
+ return {
346
+ ...candidate,
347
+ model,
348
+ defaultModel: snapshot ? model === snapshot.defaultModel : false,
349
+ modelCapabilities: snapshot ? modelCapabilitiesFor(snapshot, model) : [],
350
+ advisoryCost: {
351
+ estimatedUsd,
352
+ currency: snapshot?.currency ?? candidate.advisoryCost.currency,
353
+ usedInRanking: false,
354
+ source: estimatedUsd == null ? "unknown" : "registry-pricing"
355
+ }
356
+ };
357
+ }
358
+ function compareCandidates(left, right, classification) {
359
+ const leftFit = classificationFitScore(left, classification);
360
+ const rightFit = classificationFitScore(right, classification);
361
+ if (leftFit !== rightFit) return rightFit - leftFit;
362
+ return left.registryOrder - right.registryOrder;
363
+ }
364
+ function clampConfidence(value) {
365
+ if (value < 0.3) return 0.3;
366
+ if (value > 0.95) return 0.95;
367
+ return value;
368
+ }
369
+ function unpinnedConfidence(classification) {
370
+ if (!classification) return 0.6;
371
+ return clampConfidence((classification.analyticsConfidence + classification.judgeConfidence) / 2);
372
+ }
373
+ function alternativeConfidence(primary, index) {
374
+ const scaled = primary * (0.8 - index * 0.08);
375
+ return Math.max(0.1, Math.min(primary, scaled));
376
+ }
377
+ function selectionRationale(args) {
378
+ const rationale = [];
379
+ if (args.providerSource === "explicit") {
380
+ rationale.push("explicit provider pin");
381
+ } else {
382
+ rationale.push("registry candidate order");
383
+ }
384
+ if (args.modelSource === "explicit") {
385
+ rationale.push("explicit model pin");
386
+ } else if (args.modelSource === "classification-role") {
387
+ rationale.push("classification-selected model role");
388
+ } else {
389
+ rationale.push("registry default model");
390
+ }
391
+ if (args.classification) {
392
+ rationale.push(
393
+ `canonical classification ${args.classification.category}/${args.classification.activity}`
394
+ );
395
+ }
396
+ rationale.push("advisory cost not used for ranking");
397
+ return rationale;
398
+ }
399
+ function toAlternative(candidate, confidence) {
400
+ return {
401
+ provider: candidate.provider,
402
+ model: candidate.model,
403
+ confidence,
404
+ rationale: [`unselected alternative ${candidate.provider}:${candidate.model}`],
405
+ advisoryCost: candidate.advisoryCost
406
+ };
407
+ }
408
+ function collectSnapshots(input) {
409
+ if (input.snapshots) return [...input.snapshots];
410
+ return readEnabledRegistryRoutingSnapshots(input.registry);
411
+ }
412
+ function registryKnowsProvider(providerId, registry) {
413
+ try {
414
+ ProviderRegistry.getProviderConfig(providerId, registry);
415
+ return true;
416
+ } catch {
417
+ return false;
418
+ }
419
+ }
420
+ function resolveCanonicalRoutingModel(providerId, model, snapshot, registry) {
421
+ const trimmed = model.trim();
422
+ if (!trimmed) return void 0;
423
+ if (registryKnowsProvider(providerId, registry)) {
424
+ const attempts = [trimmed];
425
+ const mappingKey = Object.keys(snapshot.mappings).find(
426
+ (key) => key.toLowerCase() === trimmed.toLowerCase()
427
+ );
428
+ if (mappingKey && !attempts.includes(mappingKey)) {
429
+ attempts.push(mappingKey);
430
+ }
431
+ const inventoryId = canonicalInventoryModelId(snapshot, trimmed);
432
+ if (inventoryId && !attempts.includes(inventoryId)) {
433
+ attempts.push(inventoryId);
434
+ }
435
+ for (const attempt of attempts) {
436
+ try {
437
+ const resolved = ProviderRegistry.resolveModel(providerId, attempt, registry);
438
+ return canonicalInventoryModelId(snapshot, resolved) ?? resolved;
439
+ } catch {
440
+ }
441
+ }
442
+ return void 0;
443
+ }
444
+ return resolveModelAgainstSnapshot(snapshot, trimmed);
445
+ }
446
+ function requireCandidate(candidate, message) {
447
+ if (!candidate) {
448
+ throw new CanonicalRoutingError(message);
449
+ }
450
+ return candidate;
451
+ }
452
+ function idsEqual(left, right) {
453
+ return left.trim().toLowerCase() === right.trim().toLowerCase();
454
+ }
455
+ function resolvePinnedProviderSnapshot(providerPin, snapshots, registry) {
456
+ const fromSnapshots = snapshots.find((snapshot) => idsEqual(snapshot.id, providerPin));
457
+ if (fromSnapshots) {
458
+ if (!fromSnapshots.enabled) {
459
+ throw new CanonicalRoutingError(
460
+ `Explicit provider pin '${providerPin}' targets a disabled provider`
461
+ );
462
+ }
463
+ return fromSnapshots;
464
+ }
465
+ const fromRegistry = readRegistryRoutingSnapshot(providerPin, registry);
466
+ if (fromRegistry) {
467
+ if (!fromRegistry.enabled) {
468
+ throw new CanonicalRoutingError(
469
+ `Explicit provider pin '${providerPin}' targets a disabled provider`
470
+ );
471
+ }
472
+ return snapshots.find((snapshot) => snapshot.id === fromRegistry.id) ?? fromRegistry;
473
+ }
474
+ throw new CanonicalRoutingError(
475
+ `Explicit provider pin '${providerPin}' is not a configured registry provider`
476
+ );
477
+ }
478
+ function decideCanonicalRouting(input = {}) {
479
+ const costMode = input.costMode ?? "advisory";
480
+ const { classification, source: classificationSource } = resolveClassification(input);
481
+ const providerPin = normalizePin(input.pins?.provider);
482
+ const modelPin = normalizePin(input.pins?.model);
483
+ const snapshots = collectSnapshots(input);
484
+ const snapshotsById = new Map(snapshots.map((snapshot) => [snapshot.id, snapshot]));
485
+ let resolvedProviderPinId;
486
+ if (providerPin) {
487
+ const resolved = resolvePinnedProviderSnapshot(providerPin, snapshots, input.registry);
488
+ resolvedProviderPinId = resolved.id;
489
+ if (!snapshotsById.has(resolved.id)) {
490
+ snapshots.push(resolved);
491
+ snapshotsById.set(resolved.id, resolved);
492
+ }
493
+ }
494
+ const candidates = buildCanonicalRoutingCandidates({
495
+ snapshots: snapshots.filter((entry) => entry.enabled),
496
+ classification,
497
+ registry: input.registry
498
+ });
499
+ if (candidates.length === 0) {
500
+ throw new CanonicalRoutingError(
501
+ "No enabled registry providers are available to build a routing decision"
502
+ );
503
+ }
504
+ const ranked = [...candidates].sort(
505
+ (left, right) => compareCandidates(left, right, classification)
506
+ );
507
+ let selected;
508
+ let providerSource = "registry";
509
+ let modelSource = "registry";
510
+ if (resolvedProviderPinId) {
511
+ selected = requireCandidate(
512
+ ranked.find((candidate) => candidate.provider === resolvedProviderPinId),
513
+ `Explicit provider pin '${providerPin}' could not be applied`
514
+ );
515
+ providerSource = "explicit";
516
+ } else if (modelPin) {
517
+ const matching = ranked.filter((candidate) => {
518
+ const snapshot = snapshotsById.get(candidate.provider);
519
+ if (!snapshot) return false;
520
+ return resolveCanonicalRoutingModel(candidate.provider, modelPin, snapshot, input.registry) != null;
521
+ });
522
+ const owner = ProviderRegistry.resolveProviderByModel(modelPin, input.registry);
523
+ selected = requireCandidate(
524
+ matching.find((candidate) => candidate.provider === owner) ?? matching[0],
525
+ `Explicit model pin '${modelPin}' is not in the registry inventory`
526
+ );
527
+ } else {
528
+ selected = requireCandidate(ranked[0], "No routing candidate available");
529
+ }
530
+ const selectedSnapshot = snapshotsById.get(selected.provider);
531
+ if (!selectedSnapshot) {
532
+ throw new CanonicalRoutingError(
533
+ `Routing candidate '${selected.provider}' is missing registry capabilities`
534
+ );
535
+ }
536
+ if (modelPin) {
537
+ const resolvedModel = resolveCanonicalRoutingModel(
538
+ selected.provider,
539
+ modelPin,
540
+ selectedSnapshot,
541
+ input.registry
542
+ );
543
+ if (!resolvedModel) {
544
+ throw new CanonicalRoutingError(
545
+ `Explicit model pin '${modelPin}' is not in the registry inventory for '${selected.provider}'`
546
+ );
547
+ }
548
+ selected = applyModelOverride(selected, selectedSnapshot, resolvedModel);
549
+ modelSource = "explicit";
550
+ } else {
551
+ const selectedModel = selectModelForSnapshot(
552
+ selectedSnapshot,
553
+ preferredModelRole(classification)
554
+ );
555
+ if (!selectedModel) {
556
+ throw new CanonicalRoutingError(
557
+ `Configured model for '${selected.provider}' is not in the registry inventory`
558
+ );
559
+ }
560
+ modelSource = selectedModel.source;
561
+ const resolvedModel = resolveCanonicalRoutingModel(
562
+ selected.provider,
563
+ selectedModel.model,
564
+ selectedSnapshot,
565
+ input.registry
566
+ );
567
+ if (!resolvedModel) {
568
+ throw new CanonicalRoutingError(
569
+ `Configured model for '${selected.provider}' is not in the registry inventory`
570
+ );
571
+ }
572
+ if (resolvedModel !== selected.model) {
573
+ selected = applyModelOverride(selected, selectedSnapshot, resolvedModel);
574
+ }
575
+ }
576
+ selected = {
577
+ ...selected,
578
+ advisoryCost: withUsedInRanking(selected.advisoryCost, false)
579
+ };
580
+ const confidence = providerSource === "explicit" || modelSource === "explicit" ? 1 : unpinnedConfidence(classification);
581
+ const alternatives = ranked.filter(
582
+ (candidate) => candidate.provider !== selected.provider || candidate.model !== selected.model
583
+ ).map(
584
+ (candidate, index) => toAlternative(
585
+ {
586
+ ...candidate,
587
+ advisoryCost: withUsedInRanking(candidate.advisoryCost, false)
588
+ },
589
+ alternativeConfidence(confidence, index)
590
+ )
591
+ );
592
+ const provenance = {
593
+ ...providerPin ? { providerPin: { value: providerPin, source: "explicit" } } : {},
594
+ ...modelPin ? { modelPin: { value: modelPin, source: "explicit" } } : {},
595
+ providerSource,
596
+ modelSource,
597
+ ...classification ? { classification } : {},
598
+ classificationSource,
599
+ ...input.executionStrategy ? { executionStrategyInput: input.executionStrategy } : {},
600
+ costMode
601
+ };
602
+ return {
603
+ provider: selected.provider,
604
+ model: selected.model,
605
+ confidence,
606
+ alternatives,
607
+ rationale: selectionRationale({
608
+ providerSource,
609
+ modelSource,
610
+ classification
611
+ }),
612
+ provenance,
613
+ advisoryCost: selected.advisoryCost
614
+ };
615
+ }
616
+
617
+ // src/automation/flywheel-routing.ts
618
+ function normalizePin2(value) {
619
+ const trimmed = value?.trim();
620
+ return trimmed ? trimmed : void 0;
621
+ }
622
+ function requireEnabledProvider(stageId, provider, registry) {
623
+ const providerConfig = ProviderRegistry.getProviderConfig(provider, registry);
624
+ if (providerConfig.enabled !== true) {
625
+ throw new Error(`Stage '${stageId}' references disabled provider '${provider}'`);
626
+ }
627
+ return providerConfig.id;
628
+ }
629
+ function planFlywheelStageRouting(input) {
630
+ const prompt = input.stage.prompt ?? "";
631
+ const classification = input.classification ?? classifyTaskForRouting(prompt);
632
+ const stageProviderPin = normalizePin2(input.stage.provider);
633
+ const forceProviderPin = normalizePin2(input.hints?.forceProvider);
634
+ const explicitProvider = stageProviderPin ?? forceProviderPin;
635
+ const explicitModel = normalizePin2(input.stage.model);
636
+ const applyAutomaticRanking = input.hints?.providerRouting === "auto" && !explicitProvider;
637
+ if (explicitProvider) {
638
+ const snapshot = input.snapshots?.find(
639
+ (entry) => entry.id.trim().toLowerCase() === explicitProvider.toLowerCase()
640
+ );
641
+ if (snapshot) {
642
+ if (!snapshot.enabled) {
643
+ throw new Error(
644
+ `Stage '${input.stage.id}' references disabled provider '${explicitProvider}'`
645
+ );
646
+ }
647
+ } else if (input.snapshots) {
648
+ throw new CanonicalRoutingError(
649
+ `Explicit provider pin '${explicitProvider}' is not a configured registry provider`
650
+ );
651
+ } else {
652
+ requireEnabledProvider(input.stage.id, explicitProvider, input.registry);
653
+ }
654
+ }
655
+ const pins = (() => {
656
+ if (!explicitProvider && !explicitModel) return void 0;
657
+ return {
658
+ ...explicitProvider ? { provider: explicitProvider } : {},
659
+ ...explicitModel ? { model: explicitModel } : {}
660
+ };
661
+ })();
662
+ const decision = decideCanonicalRouting({
663
+ classification: applyAutomaticRanking || pins ? classification : void 0,
664
+ pins,
665
+ costMode: "advisory",
666
+ snapshots: input.snapshots,
667
+ registry: input.registry
668
+ });
669
+ const appliedProvider = decision.provider;
670
+ const hintsApplied = ["canonical-routing"];
671
+ if (stageProviderPin) {
672
+ hintsApplied.push("stage.provider");
673
+ } else if (forceProviderPin) {
674
+ hintsApplied.push("routingHints.forceProvider");
675
+ } else if (applyAutomaticRanking) {
676
+ hintsApplied.push("provider-routing-auto");
677
+ } else {
678
+ hintsApplied.push("configured-default");
679
+ }
680
+ if (input.hints?.modelPreference === "cost") {
681
+ hintsApplied.push("advisory-cost-ignored");
682
+ }
683
+ return {
684
+ provider: appliedProvider,
685
+ model: explicitModel ? decision.model : void 0,
686
+ confidence: decision.confidence,
687
+ reasoning: decision.rationale.join("; "),
688
+ alternatives: decision.alternatives.map((alternative) => alternative.provider),
689
+ hintsApplied,
690
+ canonicalDecision: decision,
691
+ classification
692
+ };
693
+ }
694
+
695
+ // src/planning/workflow-executor-providers.ts
696
+ function collectCompetitionExecutorProviders(workflow) {
697
+ const providers = /* @__PURE__ */ new Set();
698
+ const visit = (stage) => {
699
+ if (stage.type === "competition") {
700
+ for (const variant of stage.competition?.variants ?? []) {
701
+ const provider = variant.provider?.trim();
702
+ if (provider) providers.add(provider);
703
+ }
704
+ }
705
+ if (stage.type === "orchestrator" && stage.seededPlan) {
706
+ for (const subStage of stage.seededPlan.subStages) visit(subStage);
707
+ }
708
+ };
709
+ for (const stage of workflow.stages) visit(stage);
710
+ return [...providers];
711
+ }
712
+ function collectTaskExecutorProviders(workflow) {
713
+ const providers = new Set(collectCompetitionExecutorProviders(workflow));
714
+ let routedDefault;
715
+ const visit = (stage) => {
716
+ const type = stage.type ?? "standard";
717
+ const explicit = stage.provider?.trim();
718
+ if (explicit && (type === "standard" || type === "competition")) {
719
+ providers.add(explicit);
720
+ } else if (type === "standard") {
721
+ routedDefault ??= planFlywheelStageRouting({ stage: { id: stage.id, prompt: "" } }).provider;
722
+ providers.add(routedDefault);
723
+ }
724
+ if (stage.type === "orchestrator" && stage.seededPlan) {
725
+ for (const subStage of stage.seededPlan.subStages) visit(subStage);
726
+ }
727
+ };
728
+ for (const stage of workflow.stages) visit(stage);
729
+ return [...providers].sort();
730
+ }
731
+ function resolveTaskExecutionRoles(workflow, options) {
732
+ const executors = collectTaskExecutorProviders(workflow);
733
+ return resolveExecutionRoles({
734
+ cwd: options.cwd,
735
+ cli: { executorProvider: executors[0], reviewPolicy: options.reviewPolicy },
736
+ additionalReviewerExcludes: executors.slice(1),
737
+ ...resolveReviewerEligibility(options.cwd)
738
+ });
739
+ }
740
+ function describeDormantPolicyMismatch(workflow, options) {
741
+ const record = workflow.metadata?.executionPolicyDormant;
742
+ if (!record || typeof record.executor !== "string" || typeof record.reviewer !== "string" || typeof record.gate !== "string" || !Array.isArray(record.executors)) {
743
+ return "the dormant-policy record is missing or malformed";
744
+ }
745
+ const recorded = [...record.executors].sort().join(",");
746
+ const current = collectTaskExecutorProviders(workflow).join(",");
747
+ if (recorded !== current) {
748
+ return `executors changed since generation (recorded '${recorded}', now '${current}')`;
749
+ }
750
+ if (current !== record.executor) {
751
+ return `tasks run on '${current}', not the recorded executor '${record.executor}'`;
752
+ }
753
+ const roles = resolveExecutionRoles({
754
+ cwd: options.cwd,
755
+ cli: {
756
+ executorProvider: record.executor,
757
+ ...options.reviewPolicy ? { reviewPolicy: options.reviewPolicy } : {}
758
+ },
759
+ additionalReviewerExcludes: collectCompetitionExecutorProviders(workflow),
760
+ ...resolveReviewerEligibility(options.cwd)
761
+ });
762
+ if (isExecutionPolicyEngaged(roles)) {
763
+ return "review would now be engaged for the recorded executor";
764
+ }
765
+ if (roles.reviewer.provider.value !== record.reviewer) {
766
+ return `reviewer changed since generation (recorded '${record.reviewer}', now '${roles.reviewer.provider.value}')`;
767
+ }
768
+ const gate = roles.reviewer.gate?.value ?? "off";
769
+ if (gate !== record.gate) {
770
+ return `review gate changed since generation (recorded '${record.gate}', now '${gate}')`;
771
+ }
772
+ return void 0;
773
+ }
774
+
775
+ // src/automation/unreviewed-executor-effort.ts
776
+ function isNonCompetitionExecution(stage) {
777
+ return (stage.type ?? "standard") === "standard";
778
+ }
779
+ function bindExecutorEffortWithoutPolicy(workflow, roles, cwd) {
780
+ const executorProvider = roles.executor.provider.value;
781
+ const effortFor = (provider) => {
782
+ const target = provider?.trim() || executorProvider;
783
+ const resolved = target.toLowerCase() === executorProvider.trim().toLowerCase() ? roles.executor.reasoningEffort : resolveProviderReasoningEffort(target, void 0, cwd);
784
+ return normalizeReasoningEffortInput(resolved?.value);
785
+ };
786
+ const withEffort = (stage, inheritedProvider) => {
787
+ if (!isNonCompetitionExecution(stage) || stage.modelReasoningEffort != null) return stage;
788
+ const effort = effortFor(stage.provider ?? inheritedProvider);
789
+ return effort ? { ...stage, modelReasoningEffort: effort } : stage;
790
+ };
791
+ const stages = workflow.stages.map((stage) => {
792
+ if (stage.type !== "orchestrator") return withEffort(stage);
793
+ if (!stage.seededPlan) return stage;
794
+ return {
795
+ ...stage,
796
+ seededPlan: {
797
+ ...stage.seededPlan,
798
+ subStages: stage.seededPlan.subStages.map((sub) => withEffort(sub, stage.provider))
799
+ }
800
+ };
801
+ });
802
+ return { ...workflow, stages };
803
+ }
804
+
805
+ // src/planning/provider-plan-notice.ts
806
+ function defaultModelFor(provider, cwd) {
807
+ try {
808
+ return resolveProviderModel(provider, void 0, cwd).value;
809
+ } catch {
810
+ return "default";
811
+ }
812
+ }
813
+ function indexStages(workflow) {
814
+ const byId = /* @__PURE__ */ new Map();
815
+ const visit = (stage) => {
816
+ byId.set(stage.id, stage);
817
+ if (stage.type === "orchestrator" && stage.seededPlan) {
818
+ for (const subStage of stage.seededPlan.subStages) visit(subStage);
819
+ }
820
+ };
821
+ for (const stage of workflow.stages) visit(stage);
822
+ return byId;
823
+ }
824
+ function collectCandidates(workflow, bound, roles, cliProviderOverride, cwd) {
825
+ const labels = /* @__PURE__ */ new Set();
826
+ const boundById = indexStages(bound);
827
+ const add = (provider, model) => {
828
+ labels.add(`${provider}:${model?.trim() || defaultModelFor(provider, cwd)}`);
829
+ };
830
+ const visit = (original) => {
831
+ if (original.type === "orchestrator" && original.seededPlan) {
832
+ for (const subStage of original.seededPlan.subStages) visit(subStage);
833
+ return;
834
+ }
835
+ const stage = boundById.get(original.id) ?? original;
836
+ if (stage.type === "competition") {
837
+ for (const variant of stage.competition?.variants ?? []) add(variant.provider, variant.model);
838
+ return;
839
+ }
840
+ if ((stage.type ?? "standard") !== "standard") return;
841
+ const provider = stage.provider ?? cliProviderOverride ?? roles.executor.provider.value;
842
+ const executorModel = provider === roles.executor.provider.value && !cliProviderOverride ? roles.executor.model.value : void 0;
843
+ add(provider, stage.model ?? executorModel);
844
+ };
845
+ for (const stage of workflow.stages) visit(stage);
846
+ return [...labels];
847
+ }
848
+ function describeProviderPlan(workflow, bound, roles, options) {
849
+ try {
850
+ const candidates = collectCandidates(
851
+ workflow,
852
+ bound,
853
+ roles,
854
+ options.cliProviderOverride,
855
+ options.cwd
856
+ );
857
+ if (candidates.length === 0) return void 0;
858
+ const review = options.reviewOff ? "review off" : options.reviewEngaged ? `review ${roles.reviewer.provider.value}:${roles.reviewer.model.value}` : "review not run";
859
+ return `Provider plan: candidates ${candidates.join(", ")}; ${review}.`;
860
+ } catch {
861
+ return void 0;
862
+ }
863
+ }
864
+
865
+ // src/planning/generated-workflow-policy.ts
866
+ function describeDormantReview(roles, eligibility) {
867
+ if (roles.reviewer.bindingSource === "explicit") {
868
+ return `Task review unavailable: roles.reviewer.provider '${roles.reviewer.provider.value}' does the work.`;
869
+ }
870
+ const installed = eligibility.installedReviewerProviders ?? eligibility.eligibleReviewerProviders;
871
+ const providers = installed && installed.length > 0 ? installed : [roles.executor.provider.value];
872
+ if (providers.length === 1) {
873
+ return `Task review skipped: ${providers[0]} is the only installed provider.`;
874
+ }
875
+ const contributors = new Set(roles.reviewerExcludes.map((id) => id.trim().toLowerCase()));
876
+ const independent = providers.filter((provider) => !contributors.has(provider.toLowerCase()));
877
+ return independent.length === 0 ? `Task review unavailable: every installed provider (${providers.join(", ")}) does the work.` : `Task review unavailable: the installed providers that do not do the work (${independent.join(", ")}) are outside the provider order.`;
878
+ }
879
+ function applyExecutionPolicyToGeneratedWorkflow(workflow, options) {
880
+ const existingStamp = workflow.metadata?.executionPolicy;
881
+ if (existingStamp !== void 0) {
882
+ if (isCurrentExecutionPolicyWorkflow(workflow)) return workflow;
883
+ throw new Error(
884
+ `Generated workflow has a stale or malformed execution-policy stamp (${describeExecutionPolicyStampMismatch(existingStamp)}); regenerate the workflow.`
885
+ );
886
+ }
887
+ const cliOverrides = {
888
+ executorProvider: options.cliProviderOverride,
889
+ reviewPolicy: options.reviewPolicy,
890
+ orchestratorProvider: options.orchestratorOverrideIsExplicit ? options.orchestratorProviderOverride : void 0,
891
+ orchestratorModel: options.orchestratorOverrideIsExplicit ? options.orchestratorModelOverride : void 0
892
+ };
893
+ const eligibility = resolveReviewerEligibility(process.cwd());
894
+ const { eligibleReviewerProviders } = eligibility;
895
+ const roles = resolveExecutionRoles({
896
+ cwd: process.cwd(),
897
+ cli: Object.values(cliOverrides).some(Boolean) ? cliOverrides : void 0,
898
+ additionalReviewerExcludes: collectCompetitionExecutorProviders(workflow),
899
+ ...eligibility,
900
+ effectiveOrchestrator: options.orchestratorProviderOverride && !options.orchestratorOverrideIsExplicit ? {
901
+ provider: options.orchestratorProviderOverride,
902
+ model: options.orchestratorModelOverride,
903
+ sourcePath: "artifact:executionDefaults"
904
+ } : void 0
905
+ });
906
+ const hasTaskExecutionStage = workflow.stages.some((stage) => {
907
+ const stageType = stage.type ?? "standard";
908
+ if (stageType === "standard" || stageType === "competition") return true;
909
+ return stage.seededPlan?.subStages.some((subStage) => {
910
+ const subStageType = subStage.type ?? "standard";
911
+ return subStageType === "standard" || subStageType === "competition";
912
+ });
913
+ });
914
+ const sameAsExecutor = roles.reviewAssurance?.executorSeparation === "same-as-executor" || roles.sameVendorReview;
915
+ if (hasTaskExecutionStage && roles.reviewer.gate?.value !== "off") {
916
+ assertReviewerOrderUsable(roles, eligibleReviewerProviders, process.cwd());
917
+ }
918
+ const engaged = isExecutionPolicyEngaged(roles);
919
+ if (engaged && sameAsExecutor && hasTaskExecutionStage) {
920
+ throw new Error(
921
+ `Execution policy requires executor separation (reviewer provider != executor provider(s)), but reviewer resolved to executor provider '${roles.executor.provider.value}'. Configure another reviewer provider (reviewer may match the orchestrator), or set the reviewer gate to off.`
922
+ );
923
+ }
924
+ if (!engaged && sameAsExecutor && hasTaskExecutionStage && roles.reviewer.gate?.value !== "off") {
925
+ options.warnings.push(describeDormantReview(roles, eligibility));
926
+ }
927
+ const stamped = applyExecutionPolicy(workflow, roles, {
928
+ cliProviderOverride: options.cliProviderOverride,
929
+ onNotice: (message) => options.warnings.push(message)
930
+ });
931
+ const unstampedBound = engaged ? stamped : bindExecutorEffortWithoutPolicy(stamped, roles, process.cwd());
932
+ if (!engaged && hasTaskExecutionStage && roles.reviewer.gate?.value !== "off") {
933
+ const routedRoles = resolveTaskExecutionRoles(unstampedBound, {
934
+ cwd: process.cwd(),
935
+ reviewPolicy: options.reviewPolicy
936
+ });
937
+ if (isExecutionPolicyEngaged(routedRoles)) {
938
+ throw new Error(
939
+ "The routed task providers require review, although the configured executor left review dormant. Regenerate with an explicit --provider matching the intended executor so review can be bound."
940
+ );
941
+ }
942
+ }
943
+ let executors;
944
+ const dormantExecutor = options.cliProviderOverride ?? roles.executor.provider.value;
945
+ if (!engaged && hasTaskExecutionStage) {
946
+ try {
947
+ executors = collectTaskExecutorProviders(unstampedBound);
948
+ } catch {
949
+ executors = void 0;
950
+ }
951
+ if (executors && !(executors.length === 1 && executors[0] === dormantExecutor)) {
952
+ executors = void 0;
953
+ }
954
+ }
955
+ const bound = executors ? {
956
+ ...unstampedBound,
957
+ metadata: {
958
+ ...unstampedBound.metadata,
959
+ executionPolicyDormant: {
960
+ reason: sameAsExecutor ? "reviewer-same-as-executor" : "policy-not-engaged",
961
+ executor: dormantExecutor,
962
+ executors,
963
+ reviewer: roles.reviewer.provider.value,
964
+ gate: roles.reviewer.gate?.value ?? "off"
965
+ }
966
+ }
967
+ } : unstampedBound;
968
+ if (hasTaskExecutionStage && options.onProviderPlan) {
969
+ const plan = describeProviderPlan(workflow, bound, roles, {
970
+ cliProviderOverride: options.cliProviderOverride,
971
+ reviewOff: options.reviewPolicy === "off" || roles.reviewer.gate?.value === "off",
972
+ reviewEngaged: engaged,
973
+ cwd: process.cwd()
974
+ });
975
+ if (plan) options.onProviderPlan(plan);
976
+ }
977
+ return bound;
978
+ }
979
+
980
+ // src/planning/stage-contract-adapter.ts
981
+ var CODE_ONLY_NO_CHANGE_PHRASE = /\b(?:no|without)\s+code\s+changes?\b/gi;
982
+ function stageIsExplicitNoEdit(text, policyExecutionIntent) {
983
+ return classifyExplicitNoEdit(
984
+ policyExecutionIntent === "edit" ? text.replace(CODE_ONLY_NO_CHANGE_PHRASE, " ") : text
985
+ );
986
+ }
987
+ function resolveStageContract({
988
+ text,
989
+ title,
990
+ metadataExecutionIntent,
991
+ policyExecutionIntent,
992
+ policyIntentAuthority
993
+ }) {
994
+ if (metadataExecutionIntent) {
995
+ return fromIntent(metadataExecutionIntent, "metadata", metadataExecutionIntent === "analysis");
996
+ }
997
+ if (policyIntentAuthority === "explicit" && policyExecutionIntent) {
998
+ return fromIntent(
999
+ policyExecutionIntent,
1000
+ "task-type-policy",
1001
+ policyExecutionIntent === "analysis"
1002
+ );
1003
+ }
1004
+ if (policyExecutionIntent === "analysis") {
1005
+ return fromIntent("analysis", "task-type-policy", true);
1006
+ }
1007
+ const stageText = [title, text].filter(Boolean).join("\n\n");
1008
+ if (stageIsExplicitNoEdit(stageText, policyExecutionIntent)) {
1009
+ return fromIntent("analysis", "explicit-no-edit", true);
1010
+ }
1011
+ if (policyExecutionIntent === "edit") {
1012
+ return fromIntent("edit", "task-type-policy", false);
1013
+ }
1014
+ if (detectExplicitEdit(stageText)) {
1015
+ return fromIntent("edit", "explicit-edit", false);
1016
+ }
1017
+ const promptSpec = parsePromptSpec(stageText);
1018
+ if (promptSpec.isAnalysisIntent || promptSpec.editsRequired === false) {
1019
+ return fromIntent("analysis", "prompt-spec", true);
1020
+ }
1021
+ if (promptSpec.fileConstraint.mode !== "none") {
1022
+ return fromIntent("edit", "file-marker", false);
1023
+ }
1024
+ const contract = extractTaskContract(stageText, { validateQuotes: false });
1025
+ if (expectsCodeEdits(contract.deliverableType)) {
1026
+ return fromIntent("edit", "task-contract", false);
1027
+ }
1028
+ if (isAnalysisStageSemantics(stageText)) {
1029
+ return fromIntent("analysis", "stage-semantics", true);
1030
+ }
1031
+ return fromIntent("edit", "stage-semantics", false);
1032
+ }
1033
+ function fromIntent(intent, source, authoritativeAnalysis) {
1034
+ return {
1035
+ capabilities: intent === "analysis" ? {
1036
+ modifiesFiles: false,
1037
+ producesText: true,
1038
+ executionIntent: intent
1039
+ } : {
1040
+ modifiesFiles: true,
1041
+ executionIntent: intent
1042
+ },
1043
+ source,
1044
+ authoritativeAnalysis
1045
+ };
1046
+ }
1047
+ function detectExplicitEdit(text) {
1048
+ return /\b(implement|fix|repair|patch|add|create|write|update|modify|refactor|rewrite)\b/i.test(
1049
+ text
1050
+ );
1051
+ }
1052
+ function isAnalysisStageSemantics(text) {
1053
+ return /\b(plan|design|analy[sz]e|inspect|investigate|review|audit|assess|evaluate|verify|validate|diagnose|research)\b/i.test(
1054
+ text
1055
+ );
1056
+ }
1057
+
1058
+ // src/planning/sprint-to-workflow.ts
1059
+ import * as fs from "fs/promises";
1060
+ import * as path from "path";
1061
+ import * as yaml from "js-yaml";
1062
+
1063
+ // src/core/routing/fusion-default-activities.ts
1064
+ var FUSION_DEFAULT_ACTIVITIES = /* @__PURE__ */ new Set([
1065
+ "architecture",
1066
+ "design",
1067
+ "research",
1068
+ "planning"
1069
+ ]);
1070
+
1071
+ // src/core/routing/select-execution-strategy.ts
1072
+ var COMPETE_ACTIVITIES = /* @__PURE__ */ new Set([
1073
+ ...FUSION_DEFAULT_ACTIVITIES,
1074
+ "development",
1075
+ "debugging"
1076
+ ]);
1077
+ var SINGLE_PASS_CATEGORIES = /* @__PURE__ */ new Set(["analyze", "review", "document"]);
1078
+ function hasExplicitFlywheelConfig(task) {
1079
+ return Boolean(task.flywheel?.type || task.flywheel?.competition || task.flywheel?.autoloop);
1080
+ }
1081
+ function selectExecutionStrategy(task) {
1082
+ const reasons = [];
1083
+ const alternatives = [];
1084
+ let strategy;
1085
+ let confidence;
1086
+ const hasExplicitConfig = hasExplicitFlywheelConfig(task);
1087
+ if (hasExplicitConfig) {
1088
+ const explicitType = task.flywheel?.type;
1089
+ const hasCompetition = Boolean(task.flywheel?.competition);
1090
+ if (explicitType === "competition" || hasCompetition) {
1091
+ strategy = "compete";
1092
+ reasons.push("Explicit flywheel.competition or type=competition configured");
1093
+ } else if (explicitType === "standard") {
1094
+ strategy = "single-pass";
1095
+ reasons.push("Explicit flywheel.type=standard configured");
1096
+ } else if (explicitType === "verify") {
1097
+ strategy = "single-pass";
1098
+ reasons.push("Explicit flywheel.type=verify configured (local verification)");
1099
+ } else {
1100
+ strategy = "compete";
1101
+ reasons.push("Explicit flywheel config present");
1102
+ }
1103
+ return {
1104
+ strategy,
1105
+ reasons,
1106
+ confidence: 100,
1107
+ hasExplicitConfig: true
1108
+ };
1109
+ }
1110
+ const activity = task.taskClassification?.activity;
1111
+ if (activity && COMPETE_ACTIVITIES.has(activity)) {
1112
+ strategy = "compete";
1113
+ reasons.push(`activity=${activity}: Benefits from multi-perspective Fusion/competition`);
1114
+ confidence = 90;
1115
+ if (FUSION_DEFAULT_ACTIVITIES.has(activity)) {
1116
+ alternatives.push({
1117
+ strategy: "single-pass",
1118
+ reason: "Could use single-pass if time/cost constrained"
1119
+ });
1120
+ }
1121
+ if (activity === "debugging") {
1122
+ alternatives.push({
1123
+ strategy: "autoloop",
1124
+ reason: "Iterative debugging could be more effective for complex bugs"
1125
+ });
1126
+ }
1127
+ return { strategy, reasons, confidence, alternatives, hasExplicitConfig: false };
1128
+ }
1129
+ const executionIntent = task.metadata?.executionIntent;
1130
+ if (executionIntent === "analysis") {
1131
+ strategy = "single-pass";
1132
+ reasons.push("executionIntent=analysis: Single provider sufficient for generic analysis");
1133
+ confidence = 90;
1134
+ alternatives.push({
1135
+ strategy: "compete",
1136
+ reason: "Use Fusion/competition when the task is architecture, design, research, or planning"
1137
+ });
1138
+ return { strategy, reasons, confidence, alternatives, hasExplicitConfig: false };
1139
+ }
1140
+ if (executionIntent === "edit") {
1141
+ reasons.push("executionIntent=edit: Code changes benefit from multi-variant competition");
1142
+ }
1143
+ const category = task.taskClassification?.category;
1144
+ if (!executionIntent && category && SINGLE_PASS_CATEGORIES.has(category)) {
1145
+ strategy = "single-pass";
1146
+ reasons.push(`category=${category}: Single provider sufficient for non-edit oriented work`);
1147
+ confidence = 75;
1148
+ alternatives.push({
1149
+ strategy: "compete",
1150
+ reason: "Competition could provide higher confidence at higher cost"
1151
+ });
1152
+ return { strategy, reasons, confidence, alternatives, hasExplicitConfig: false };
1153
+ }
1154
+ if (executionIntent === "edit") {
1155
+ strategy = "compete";
1156
+ confidence = 75;
1157
+ reasons.push("Default for edit tasks: Competition for quality assurance");
1158
+ } else {
1159
+ strategy = "compete";
1160
+ confidence = 60;
1161
+ reasons.push("No classification signals: Defaulting to competition for quality assurance");
1162
+ }
1163
+ alternatives.push(
1164
+ { strategy: "single-pass", reason: "For simple, well-defined tasks with low risk" },
1165
+ { strategy: "autoloop", reason: "For complex tasks requiring iterative refinement" },
1166
+ { strategy: "parallel", reason: "For independent subtasks that can run concurrently" }
1167
+ );
1168
+ return { strategy, reasons, confidence, alternatives, hasExplicitConfig: false };
1169
+ }
1170
+ function resolveOrderedProviders() {
1171
+ try {
1172
+ const ordered = resolveCandidates("global", { preserveFallbackChain: true }).map(
1173
+ (candidate) => candidate.provider
1174
+ );
1175
+ const distinct = [...new Set(ordered.filter((provider) => provider.length > 0))];
1176
+ if (distinct.length > 0) return distinct;
1177
+ } catch {
1178
+ }
1179
+ return [resolveDefaultProvider().value];
1180
+ }
1181
+ function getDefaultCompetitionVariantsForProvider(provider) {
1182
+ const requested = typeof provider === "string" && provider.trim().length > 0 && provider !== "multi" ? provider.trim() : void 0;
1183
+ const ordered = resolveOrderedProviders();
1184
+ const preferred = requested ?? ordered[0] ?? resolveDefaultProvider().value;
1185
+ const second = ordered.find((candidate) => candidate !== preferred);
1186
+ return second ? [{ provider: preferred }, { provider: second }] : [{ provider: preferred }];
1187
+ }
1188
+
1189
+ // src/core/task-types/effective-policy.ts
1190
+ var DEFAULT_TASK_TYPE_MIN_CONFIDENCE = 0.3;
1191
+ function getTaskTypeMinConfidence() {
1192
+ return readEnv(BUILD_TASK_TYPE_MIN_CONFIDENCE).value ?? DEFAULT_TASK_TYPE_MIN_CONFIDENCE;
1193
+ }
1194
+ function getEffectiveTaskTypePolicy(options) {
1195
+ const { policy, resolvedBy } = options;
1196
+ const confidence = options.confidence;
1197
+ const threshold = getTaskTypeMinConfidence();
1198
+ const isMatcher = resolvedBy === "matcher";
1199
+ const suppressed = isMatcher && typeof confidence === "number" && confidence < threshold;
1200
+ return {
1201
+ policy: suppressed ? stripRestrictivePolicy(policy) : policy,
1202
+ suppressed,
1203
+ threshold
1204
+ };
1205
+ }
1206
+ function stripRestrictivePolicy(policy) {
1207
+ return {
1208
+ ...policy,
1209
+ decomposition: policy.decomposition ? {
1210
+ ...policy.decomposition,
1211
+ maxParallelGroups: void 0,
1212
+ requiredStageTypes: void 0
1213
+ } : void 0,
1214
+ allowlist: void 0,
1215
+ // A read-only analysis intent is restrictive; the edit default is not.
1216
+ executionIntent: policy.executionIntent === "analysis" ? void 0 : policy.executionIntent,
1217
+ routing: policy.routing ? {
1218
+ ...policy.routing,
1219
+ preferCompetition: void 0
1220
+ } : void 0
1221
+ };
1222
+ }
1223
+
1224
+ // src/core/task-types/resolver.ts
1225
+ var DEFAULT_TASK_TYPE_ID = "general";
1226
+ function normalizeText(text) {
1227
+ return text.toLowerCase();
1228
+ }
1229
+ function isNegatedDocConstraint(text) {
1230
+ const normalized = normalizeText(text);
1231
+ return /\b(?:do not|don't|no)\s+(?:edit|touch|change|modify|update|write|create|add)?\s*docs?\b/.test(
1232
+ normalized
1233
+ ) || /\bdocs?\s+(?:should|must)\s+not\s+be\s+(?:edited|changed|modified|updated|touched)\b/.test(
1234
+ normalized
1235
+ );
1236
+ }
1237
+ function hasStrongCodeOnlySignals(text) {
1238
+ const normalized = normalizeText(text);
1239
+ return normalized.includes("code-only") || normalized.includes("src/") || normalized.includes("tests/") || /\b(?:test|tests|cli|command|commands|handler|warning|error|validation)\b/.test(normalized);
1240
+ }
1241
+ function hasDirectDocumentationDeliverableIntent(text) {
1242
+ return /\b(?:fix|create|update|add|write|generate|improve)\b.{0,40}\b(?:doc|docs|documentation|readme|guideline|guide|instructions|specification)\b/i.test(
1243
+ text
1244
+ ) || /\b(?:doc|docs|documentation|readme|guideline|guide|instructions|specification)\b.{0,40}\b(?:file|page|section|content|reference)\b/i.test(
1245
+ text
1246
+ ) || /(?:^|[\s`'"])(?:docs\/[^\s`'"]+|(?:readme|changelog|claude|agents|gemini)\.md)\b/i.test(text);
1247
+ }
1248
+ function countKeywordMatches(text, keywords) {
1249
+ const normalized = normalizeText(text);
1250
+ const matched = [];
1251
+ for (const keyword of keywords) {
1252
+ const k = keyword.trim().toLowerCase();
1253
+ if (!k) continue;
1254
+ if (normalized.includes(k)) {
1255
+ matched.push(keyword);
1256
+ }
1257
+ }
1258
+ return { count: matched.length, matched };
1259
+ }
1260
+ function countRegexMatches(text, regexStrings) {
1261
+ const matched = [];
1262
+ for (const raw of regexStrings) {
1263
+ try {
1264
+ const re = new RegExp(raw, "i");
1265
+ if (re.test(text)) {
1266
+ matched.push(raw);
1267
+ }
1268
+ } catch {
1269
+ }
1270
+ }
1271
+ return { count: matched.length, matched };
1272
+ }
1273
+ function canonicalMatches(classification, match) {
1274
+ if (!classification || !match?.canonical) return { ok: true, reasons: [], matched: false };
1275
+ const reasons = [];
1276
+ let matchedAny = false;
1277
+ if (Array.isArray(match.canonical.category) && match.canonical.category.length > 0) {
1278
+ const ok = match.canonical.category.includes(classification.category);
1279
+ if (!ok) {
1280
+ return {
1281
+ ok: false,
1282
+ reasons: [`canonical.category mismatch (${classification.category})`],
1283
+ matched: false
1284
+ };
1285
+ }
1286
+ matchedAny = true;
1287
+ reasons.push(`canonical.category=${classification.category}`);
1288
+ }
1289
+ if (Array.isArray(match.canonical.judgeTaskKind) && match.canonical.judgeTaskKind.length > 0) {
1290
+ const ok = match.canonical.judgeTaskKind.includes(classification.judgeTaskKind);
1291
+ if (!ok) {
1292
+ return {
1293
+ ok: false,
1294
+ reasons: [`canonical.judgeTaskKind mismatch (${classification.judgeTaskKind})`],
1295
+ matched: false
1296
+ };
1297
+ }
1298
+ matchedAny = true;
1299
+ reasons.push(`canonical.judgeTaskKind=${classification.judgeTaskKind}`);
1300
+ }
1301
+ return { ok: true, reasons, matched: matchedAny };
1302
+ }
1303
+ function getPriority(typeDef) {
1304
+ const raw = typeDef.match?.priority;
1305
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : 0;
1306
+ }
1307
+ function resolveTaskTypeFromCandidates(options) {
1308
+ const { taskText, candidates, classification, fallbackId = DEFAULT_TASK_TYPE_ID } = options;
1309
+ const scored = [];
1310
+ for (const candidate of candidates) {
1311
+ const match = candidate.match;
1312
+ if (!match) {
1313
+ continue;
1314
+ }
1315
+ if (match.suppressWhenCodeOnly === true && hasStrongCodeOnlySignals(taskText)) {
1316
+ if (isNegatedDocConstraint(taskText) || !hasDirectDocumentationDeliverableIntent(taskText)) {
1317
+ continue;
1318
+ }
1319
+ }
1320
+ const {
1321
+ ok: canonicalOk,
1322
+ reasons: canonicalReasons,
1323
+ matched: canonicalMatched
1324
+ } = canonicalMatches(classification, match);
1325
+ if (!canonicalOk) {
1326
+ continue;
1327
+ }
1328
+ const keywords = Array.isArray(match.keywords) ? match.keywords : [];
1329
+ const regex = Array.isArray(match.regex) ? match.regex : [];
1330
+ const keywordMatches = countKeywordMatches(taskText, keywords);
1331
+ const regexMatches = countRegexMatches(taskText, regex);
1332
+ const hasAnySignal = keywordMatches.count > 0 || regexMatches.count > 0;
1333
+ if (!hasAnySignal) {
1334
+ continue;
1335
+ }
1336
+ const reasons = [];
1337
+ reasons.push(...canonicalReasons);
1338
+ for (const k of keywordMatches.matched) reasons.push(`keyword:${k}`);
1339
+ for (const r of regexMatches.matched) reasons.push(`regex:${r}`);
1340
+ const priority = getPriority(candidate);
1341
+ const confidence = Math.min(
1342
+ 1,
1343
+ (canonicalMatched ? 0.3 : 0) + Math.min(0.5, keywordMatches.count * 0.1) + Math.min(0.3, regexMatches.count * 0.1)
1344
+ );
1345
+ scored.push({ id: candidate.id, priority, confidence, reasons });
1346
+ }
1347
+ if (scored.length === 0) {
1348
+ return { id: fallbackId, resolvedBy: "fallback", reasons: ["no matcher candidates"] };
1349
+ }
1350
+ scored.sort((a, b) => {
1351
+ if (b.priority !== a.priority) return b.priority - a.priority;
1352
+ if (b.confidence !== a.confidence) return b.confidence - a.confidence;
1353
+ return a.id.localeCompare(b.id);
1354
+ });
1355
+ const best = scored[0];
1356
+ if (!best) {
1357
+ return { id: fallbackId, resolvedBy: "fallback", reasons: ["no matcher candidates"] };
1358
+ }
1359
+ return {
1360
+ id: best.id,
1361
+ resolvedBy: "matcher",
1362
+ confidence: best.confidence,
1363
+ reasons: best.reasons
1364
+ };
1365
+ }
1366
+ function hasInvestigationSignals(text) {
1367
+ return /\b(investigat|analy[sz]e|audit|assess|review|root\s*cause)\b/i.test(text);
1368
+ }
1369
+ function classificationForTaskTypeMatching(taskText, classification) {
1370
+ let category = classification.category;
1371
+ let judgeTaskKind = classification.judgeTaskKind;
1372
+ if (isNegatedDocConstraint(taskText) && hasStrongCodeOnlySignals(taskText)) {
1373
+ if (category === "document") {
1374
+ category = "execute";
1375
+ }
1376
+ if ((category === "execute" || category === "test") && !["implementation", "bugfix", "refactor"].includes(judgeTaskKind)) {
1377
+ judgeTaskKind = "implementation";
1378
+ }
1379
+ }
1380
+ if (category === "document" && hasInvestigationSignals(taskText)) {
1381
+ category = "analyze";
1382
+ judgeTaskKind = "analysis";
1383
+ }
1384
+ return { category, judgeTaskKind };
1385
+ }
1386
+ function resolveTaskTypeWithDeclaration(options) {
1387
+ const hasId = options.hasId ?? (() => true);
1388
+ const explicitId = options.explicitId?.trim();
1389
+ if (explicitId && hasId(explicitId)) {
1390
+ const resolvedBy = options.explicitResolvedBy ?? "frontmatter";
1391
+ return { id: explicitId, resolvedBy, reasons: [`${resolvedBy} override`] };
1392
+ }
1393
+ const declaredType = typeof options.declaredType === "string" && options.declaredType.length > 0 ? options.declaredType : void 0;
1394
+ if (declaredType) {
1395
+ const mappedId = options.resolveDeclared?.(declaredType);
1396
+ if (typeof mappedId === "string" && mappedId.length > 0 && hasId(mappedId)) {
1397
+ return {
1398
+ id: mappedId,
1399
+ resolvedBy: "declared",
1400
+ reasons: [`declared:${declaredType}`]
1401
+ };
1402
+ }
1403
+ return {
1404
+ id: options.fallbackId ?? DEFAULT_TASK_TYPE_ID,
1405
+ resolvedBy: "fallback",
1406
+ reasons: [`declared:${declaredType} unmapped; inference skipped`]
1407
+ };
1408
+ }
1409
+ const infer = options.inferFallback ?? resolveTaskTypeForText;
1410
+ return infer({
1411
+ taskText: options.taskText,
1412
+ candidates: options.candidates,
1413
+ fallbackId: options.fallbackId,
1414
+ stripInjections: options.stripInjections
1415
+ });
1416
+ }
1417
+ function resolveTaskTypeForText(options) {
1418
+ const stripInjections = options.stripInjections ?? true;
1419
+ const matcherText = stripInjections ? stripPromptInjections(options.taskText) : options.taskText;
1420
+ const classification = classifyTask(matcherText, {
1421
+ stripInjections: false
1422
+ });
1423
+ const matcherClassification = classificationForTaskTypeMatching(matcherText, classification);
1424
+ return resolveTaskTypeFromCandidates({
1425
+ taskText: matcherText,
1426
+ candidates: options.candidates,
1427
+ classification: matcherClassification,
1428
+ fallbackId: options.fallbackId
1429
+ });
1430
+ }
1431
+
1432
+ // src/planning/create-intent-targets.ts
1433
+ var PATH_REFERENCE_EXTENSION_ALTERNATION = getProjectReferencePathExtensions().map((ext) => ext.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
1434
+ var PATH_TOKEN_PATTERN = new RegExp(
1435
+ String.raw`(?:^|[\s\u0060'"])((?:\.?\.\/)?(?:[A-Za-z0-9_.-]+\/)+[A-Za-z0-9_.-]*\.(?:${PATH_REFERENCE_EXTENSION_ALTERNATION}))(?:$|[\s\u0060'",.;:)])`,
1436
+ "gi"
1437
+ );
1438
+ function isRepoRelativeTargetPath(value) {
1439
+ const normalized = value.replace(/\\/g, "/").trim();
1440
+ if (normalized.length === 0) return false;
1441
+ if (normalized.startsWith("/") || /^[A-Za-z]:/.test(normalized)) return false;
1442
+ return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
1443
+ }
1444
+ function extractLikelyPathReferences(text) {
1445
+ const candidates = /* @__PURE__ */ new Set();
1446
+ for (const match of text.matchAll(PATH_TOKEN_PATTERN)) {
1447
+ const raw = match[1]?.trim();
1448
+ if (!raw) continue;
1449
+ const candidate = raw.replace(/^\.\//, "");
1450
+ if (!isRepoRelativeTargetPath(candidate)) continue;
1451
+ candidates.add(candidate);
1452
+ }
1453
+ return Array.from(candidates);
1454
+ }
1455
+ function normalizeTargetPath(value) {
1456
+ return value.trim().replace(/^`|`$/g, "").replace(/^\.\//, "").replace(/#L\d+(?:-L?\d+)?$/i, "").replace(/\s+\(\s*(?:new|create|modify)\s*\)$/i, "").replace(/[),.;:]+$/g, "");
1457
+ }
1458
+ function extractCreateAnnotatedFileTargets(text) {
1459
+ const targets = /* @__PURE__ */ new Set();
1460
+ for (const path2 of extractCreateAnnotatedFilePaths(text)) {
1461
+ const target = normalizeTargetPath(path2);
1462
+ if (target) targets.add(target);
1463
+ }
1464
+ return Array.from(targets);
1465
+ }
1466
+ function hasCreateFileIntent(text) {
1467
+ return /\b(?:create|scaffold|generate|introduce)\b[\s\S]{0,120}\b(?:file|module|component|template|fixture|script|document|doc)\b/i.test(
1468
+ text
1469
+ ) || /\bnew\s+(?:file|module|component|template|fixture|script|document|doc)\b/i.test(text);
1470
+ }
1471
+ function collectProseUnits(text) {
1472
+ const units = [];
1473
+ let block = "";
1474
+ let inFence = false;
1475
+ let verifyDepth;
1476
+ const flush = () => {
1477
+ const pending = block.trim();
1478
+ block = "";
1479
+ if (pending.length === 0) return;
1480
+ for (const sentence of pending.split(/(?<=[.!?])\s+/)) {
1481
+ const unit = sentence.trim();
1482
+ if (unit.length > 0) units.push(unit);
1483
+ }
1484
+ };
1485
+ for (const rawLine of text.split(/\r?\n/)) {
1486
+ const trimmed = rawLine.trim();
1487
+ if (/^```/.test(trimmed)) {
1488
+ flush();
1489
+ inFence = !inFence;
1490
+ continue;
1491
+ }
1492
+ if (inFence) continue;
1493
+ const heading = /^(#{1,6})\s+/.exec(trimmed);
1494
+ if (heading) {
1495
+ flush();
1496
+ const depth = (heading[1] ?? "").length;
1497
+ if (verifyDepth === void 0 || depth <= verifyDepth) {
1498
+ verifyDepth = /^#{1,6}\s+how\s+to\s+verify\b/i.test(trimmed) ? depth : void 0;
1499
+ }
1500
+ continue;
1501
+ }
1502
+ if (verifyDepth !== void 0) continue;
1503
+ if (trimmed.length === 0) {
1504
+ flush();
1505
+ continue;
1506
+ }
1507
+ const listMarker = /^(?:[-*+]|\d+[.)])\s+/.exec(trimmed);
1508
+ if (listMarker) {
1509
+ flush();
1510
+ block = trimmed.slice(listMarker[0].length);
1511
+ continue;
1512
+ }
1513
+ block = block.length > 0 ? `${block} ${trimmed}` : trimmed;
1514
+ }
1515
+ flush();
1516
+ return units;
1517
+ }
1518
+ function inferCreateIntentTargets(options) {
1519
+ const text = `${options.title ?? ""}
1520
+
1521
+ ${options.body ?? ""}`;
1522
+ const annotatedTargets = extractCreateAnnotatedFileTargets(text);
1523
+ if (annotatedTargets.length > 0) return annotatedTargets;
1524
+ const targets = /* @__PURE__ */ new Set();
1525
+ for (const unit of collectProseUnits(text)) {
1526
+ if (!hasCreateFileIntent(unit)) continue;
1527
+ for (const reference of extractLikelyPathReferences(unit)) {
1528
+ const target = normalizeTargetPath(reference);
1529
+ if (target.length > 0 && !target.endsWith("/")) targets.add(target);
1530
+ }
1531
+ }
1532
+ return Array.from(targets);
1533
+ }
1534
+
1535
+ // src/planning/dry-run-target-warnings.ts
1536
+ var IGNORED_TARGET_PREFIXES = [
1537
+ ".build-project/planning/",
1538
+ ".build-project/tmp/",
1539
+ ".build-project/cache/",
1540
+ ".build-project/state/",
1541
+ ".build-project/telemetry/",
1542
+ ".build-project/runs/",
1543
+ ".build-project/artifacts/",
1544
+ ".build-project/workflows/",
1545
+ "node_modules/",
1546
+ "dist/",
1547
+ "build/",
1548
+ "coverage/"
1549
+ ];
1550
+ function normalizeTarget(targetPath) {
1551
+ return targetPath.replace(/\\/g, "/").replace(/^\.\//, "");
1552
+ }
1553
+ function isIgnoredTargetPath(targetPath) {
1554
+ const normalized = normalizeTarget(targetPath);
1555
+ return IGNORED_TARGET_PREFIXES.some(
1556
+ (prefix) => normalized === prefix.slice(0, -1) || normalized.startsWith(prefix)
1557
+ );
1558
+ }
1559
+ async function collectGitignoredTargets(options) {
1560
+ const { repoRoot, targets } = options;
1561
+ const queried = /* @__PURE__ */ new Map();
1562
+ for (const target of targets) {
1563
+ const normalized = normalizeTarget(target);
1564
+ if (!isRepoRelativeTargetPath(normalized)) continue;
1565
+ const existing = queried.get(normalized);
1566
+ if (existing) {
1567
+ existing.push(target);
1568
+ } else {
1569
+ queried.set(normalized, [target]);
1570
+ }
1571
+ }
1572
+ if (queried.size === 0) {
1573
+ return { targets: [], source: "git" };
1574
+ }
1575
+ let ignoredPaths;
1576
+ try {
1577
+ const result = await execGit(["check-ignore", "-z", "--stdin"], {
1578
+ cwd: repoRoot,
1579
+ input: `${[...queried.keys()].join("\0")}\0`
1580
+ });
1581
+ if (result.exitCode === 0 || result.exitCode === 1) {
1582
+ ignoredPaths = new Set(result.stdout.split("\0").filter((entry) => entry.length > 0));
1583
+ }
1584
+ } catch {
1585
+ }
1586
+ if (!ignoredPaths) {
1587
+ return { targets: targets.filter(isIgnoredTargetPath), source: "static-fallback" };
1588
+ }
1589
+ const ignoredTargets = [];
1590
+ for (const [normalized, originals] of queried) {
1591
+ if (ignoredPaths.has(normalized)) ignoredTargets.push(...originals);
1592
+ }
1593
+ return { targets: ignoredTargets, source: "git" };
1594
+ }
1595
+ function describeUndeliverableReason(normalized) {
1596
+ if (PROVIDER_REGISTRY_CONFIG_PATHS.includes(normalized)) {
1597
+ return "provider-registry config that provider-authored edits may never write";
1598
+ }
1599
+ switch (classifyRepoPath(normalized)) {
1600
+ case "runtime-artifact":
1601
+ return "runtime artifact path the pipeline does not apply";
1602
+ case "generated-artifact":
1603
+ return "generated output the pipeline does not apply";
1604
+ case "planning-artifact":
1605
+ return "excluded planning path the pipeline does not apply";
1606
+ default:
1607
+ return "excluded from applied changes by the delivery classifier";
1608
+ }
1609
+ }
1610
+ function collectUndeliverableTargets(targets) {
1611
+ const seen = /* @__PURE__ */ new Set();
1612
+ const entries = [];
1613
+ for (const target of targets) {
1614
+ const normalized = normalizeTarget(target);
1615
+ if (normalized.length === 0 || seen.has(normalized)) continue;
1616
+ seen.add(normalized);
1617
+ if (!shouldIgnoreRepoPath(normalized)) continue;
1618
+ entries.push({ path: target, reason: describeUndeliverableReason(normalized) });
1619
+ }
1620
+ return entries;
1621
+ }
1622
+ function formatUndeliverableTargetsWarning(taskId, entries) {
1623
+ if (entries.length === 0) return void 0;
1624
+ const detail = entries.map((entry) => `${entry.path} (${entry.reason})`).join(", ");
1625
+ return `Task ${taskId}: target path(s) cannot be delivered by the pipeline: ${detail}`;
1626
+ }
1627
+
1628
+ // src/planning/stage-dependency-order.ts
1629
+ function orderStagesByDeclaredDeps(stages) {
1630
+ const ids = new Set(stages.map((stage) => stage.id));
1631
+ const placed = /* @__PURE__ */ new Set();
1632
+ const remaining = [...stages];
1633
+ const ordered = [];
1634
+ while (remaining.length > 0) {
1635
+ const nextIndex = remaining.findIndex(
1636
+ (stage) => (stage.deps ?? []).every((dep) => dep === stage.id || !ids.has(dep) || placed.has(dep))
1637
+ );
1638
+ if (nextIndex === -1) {
1639
+ ordered.push(...remaining);
1640
+ break;
1641
+ }
1642
+ const next = remaining[nextIndex];
1643
+ remaining.splice(nextIndex, 1);
1644
+ placed.add(next.id);
1645
+ ordered.push(next);
1646
+ }
1647
+ return ordered;
1648
+ }
1649
+
1650
+ // src/planning/sprint-to-workflow.ts
1651
+ function quoteVerifyArg(value) {
1652
+ if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(value)) return value;
1653
+ return `'${value.replace(/'/g, "'\\''")}'`;
1654
+ }
1655
+ function extractExactOneLineContent(text) {
1656
+ const match = text.match(/\bexactly\s+one\s+line\s*:\s*([^\n]+)/i);
1657
+ let content = match?.[1]?.trim();
1658
+ if (!content) return void 0;
1659
+ const openingQuote = content[0];
1660
+ if (openingQuote === '"' || openingQuote === "'" || openingQuote === "`") {
1661
+ let escaped = false;
1662
+ let decoded = "";
1663
+ for (let i = 1; i < content.length; i++) {
1664
+ const ch = content[i];
1665
+ if (escaped) {
1666
+ decoded += ch;
1667
+ escaped = false;
1668
+ continue;
1669
+ }
1670
+ if (ch === "\\") {
1671
+ escaped = true;
1672
+ continue;
1673
+ }
1674
+ if (ch === openingQuote) {
1675
+ content = decoded;
1676
+ return content && content.length > 0 ? content : void 0;
1677
+ }
1678
+ decoded += ch;
1679
+ }
1680
+ }
1681
+ content = content.replace(/\.\s+(?:(?:Do not|Verify|Validation)\b|Acceptance:).*$/i, "").trim();
1682
+ content = content.replace(/\.$/, "").trim();
1683
+ return content && content.length > 0 ? content : void 0;
1684
+ }
1685
+ function buildExactLineVerifyCommand(pathValue, content) {
1686
+ const encodedContent = Buffer.from(content, "utf8").toString("base64");
1687
+ return `build assert exact-line ${quoteVerifyArg(pathValue)} --content-base64 ${encodedContent}`;
1688
+ }
1689
+ function stripWrappingQuotes(value) {
1690
+ const quote = value[0];
1691
+ if (value.length >= 2 && (quote === '"' || quote === "'") && value.endsWith(quote) && !value.slice(1, -1).includes(quote)) {
1692
+ return value.slice(1, -1);
1693
+ }
1694
+ return value;
1695
+ }
1696
+ function normalizeBodyVerifyLine(line, inFence) {
1697
+ let value = line.trim().replace(/^\s*(?:[-*+]|\d+[.)])\s+/, "").trim();
1698
+ if (!value) return void 0;
1699
+ const codeSpan = value.match(/`([^`]+)`/);
1700
+ if (codeSpan?.[1]) {
1701
+ value = stripWrappingQuotes(codeSpan[1].trim()).trim();
1702
+ return value.length > 0 ? { command: value, reportRejection: true } : void 0;
1703
+ }
1704
+ const hasRunPrefix = /^run\s+/i.test(value);
1705
+ value = stripWrappingQuotes(value.replace(/^run\s+/i, "").trim()).replace(/(?<![./]);$/g, "").replace(/(?<![./])\.$/g, "").trim();
1706
+ const hasCommandSyntax = /^[a-z][a-z0-9._+-]*\s+-/.test(value) || /(?:&&|;|\||[<>]|\$\()/.test(value);
1707
+ if (value.length === 0) return void 0;
1708
+ if (inFence) return { command: value, reportRejection: true };
1709
+ return {
1710
+ command: value,
1711
+ reportRejection: hasRunPrefix || hasCommandSyntax || hasKnownVerifyExecutable(value),
1712
+ prose: true
1713
+ };
1714
+ }
1715
+ function extractBodyVerifyCommands(text) {
1716
+ const lines = text.split(/\r?\n/);
1717
+ const ignoredProse = [];
1718
+ const candidates = /* @__PURE__ */ new Map();
1719
+ let inVerifySection = false;
1720
+ let sectionFound = false;
1721
+ let inFence = false;
1722
+ let verifyDepth = 0;
1723
+ for (const line of lines) {
1724
+ const trimmed = line.trim();
1725
+ if (/^```/.test(trimmed)) {
1726
+ if (inVerifySection) {
1727
+ inFence = !inFence;
1728
+ }
1729
+ continue;
1730
+ }
1731
+ const heading = !inFence ? /^(#{1,6})\s+/.exec(trimmed) : null;
1732
+ if (heading) {
1733
+ const depth = (heading[1] ?? "").length;
1734
+ if (/^#{1,6}\s+how\s+to\s+verify\b/i.test(trimmed)) {
1735
+ if (!inVerifySection || depth <= verifyDepth) verifyDepth = depth;
1736
+ inVerifySection = true;
1737
+ sectionFound = true;
1738
+ continue;
1739
+ }
1740
+ if (inVerifySection) {
1741
+ if (depth <= verifyDepth) break;
1742
+ continue;
1743
+ }
1744
+ }
1745
+ if (!inVerifySection) continue;
1746
+ const normalized = normalizeBodyVerifyLine(line, inFence);
1747
+ if (!normalized) continue;
1748
+ if (normalized.prose) {
1749
+ if (normalized.reportRejection) ignoredProse.push(normalized.command);
1750
+ continue;
1751
+ }
1752
+ candidates.set(
1753
+ normalized.command,
1754
+ (candidates.get(normalized.command) ?? false) || normalized.reportRejection
1755
+ );
1756
+ }
1757
+ const partitioned = partitionVerifyCommands([...candidates.keys()]);
1758
+ return {
1759
+ commands: partitioned.accepted,
1760
+ rejected: partitioned.rejected.filter(({ command }) => candidates.get(command) === true),
1761
+ ignoredProse,
1762
+ sectionFound
1763
+ };
1764
+ }
1765
+ function annotatePromptWithCreateTargets(prompt, createTargets) {
1766
+ if (createTargets.length === 0) return prompt;
1767
+ const remaining = new Set(createTargets);
1768
+ const lines = prompt.split("\n").map((line) => {
1769
+ const match = line.match(/^(\s*)FILE:\s*(.+)$/i);
1770
+ if (!match) return line;
1771
+ const indent = match[1] ?? "";
1772
+ const target = normalizeTargetPath(match[2] ?? "");
1773
+ if (!remaining.has(target)) return line;
1774
+ remaining.delete(target);
1775
+ return `${indent}FILE: ${target} (create)`;
1776
+ });
1777
+ if (remaining.size === 0) return lines.join("\n");
1778
+ const insertion = Array.from(remaining, (target) => `FILE: ${target} (create)`).join("\n");
1779
+ const checklistIndex = lines.findIndex((line) => /^##\s+Checklist\b/i.test(line));
1780
+ if (checklistIndex >= 0) {
1781
+ lines.splice(checklistIndex, 0, "", insertion, "");
1782
+ return lines.join("\n");
1783
+ }
1784
+ return `${lines.join("\n").trimEnd()}
1785
+
1786
+ ${insertion}
1787
+ `;
1788
+ }
1789
+ function addCreateIntentValidation(stage, createTargets) {
1790
+ if (createTargets.length === 0) return;
1791
+ stage.validation = stage.validation ?? { enabled: false };
1792
+ const requiredFiles = new Set(stage.validation.requiredFiles ?? []);
1793
+ const checks = [...stage.validation.checks ?? []];
1794
+ const existingFileExistsChecks = new Set(
1795
+ checks.filter((check) => check.type === "file-exists").map((check) => normalizeTargetPath(check.path))
1796
+ );
1797
+ for (const target of createTargets) {
1798
+ requiredFiles.add(target);
1799
+ if (!existingFileExistsChecks.has(target)) {
1800
+ checks.push({ type: "file-exists", path: target });
1801
+ existingFileExistsChecks.add(target);
1802
+ }
1803
+ }
1804
+ stage.validation.requiredFiles = Array.from(requiredFiles);
1805
+ stage.validation.checks = checks;
1806
+ }
1807
+ function taskTypeFrameworkToJudgeType(framework, defaultJudgeType) {
1808
+ if (framework === "multi-lens") return "multi-lens";
1809
+ if (framework === "ai-judge") return "ai";
1810
+ return defaultJudgeType;
1811
+ }
1812
+ function getPolicyAwareDefaultCompetitionVariants(provider, _policy) {
1813
+ return getDefaultCompetitionVariantsForProvider(provider);
1814
+ }
1815
+ function taskTypeDefaultStrategyWarning(taskId, policy) {
1816
+ if (!policy?.routing?.defaultStrategy) return void 0;
1817
+ return `Task ${taskId}: taskType policy 'routing.defaultStrategy' is accepted and ignored (variant strategies were removed; see ADR-025)`;
1818
+ }
1819
+ function createDefaultCompetitionConfig(provider, overrides, policy, defaultJudgeType = "ai") {
1820
+ const policyDefaultScore = policy?.judging?.defaultScore;
1821
+ const policyMinimumScore = policy?.judging?.minimumScore;
1822
+ const defaultThresholdRaw = policyDefaultScore ?? 70;
1823
+ const minimumThresholdRaw = policyMinimumScore ?? -Infinity;
1824
+ const defaultThreshold = Math.max(defaultThresholdRaw, minimumThresholdRaw);
1825
+ const config = {
1826
+ variants: getPolicyAwareDefaultCompetitionVariants(provider, policy),
1827
+ judgeConfig: {
1828
+ type: overrides?.judgeType ?? taskTypeFrameworkToJudgeType(policy?.judging?.framework, defaultJudgeType),
1829
+ threshold: defaultThreshold
1830
+ },
1831
+ preserveCandidates: false,
1832
+ applyWinner: true,
1833
+ // Delivery-safe default: verification failures disqualify candidates.
1834
+ verificationPolicy: "blocking",
1835
+ // Enable automatic repair for winners with verification findings
1836
+ repairOnFindings: {
1837
+ enabled: true,
1838
+ maxIterations: 3,
1839
+ timeboxMs: resolveExecutionBoundary("bounded-loop").hardCeilingMs
1840
+ },
1841
+ // Default to 'inconclusive': refuse to break score ties without an LLM verdict.
1842
+ // Users can opt back into deterministic tie-breaking by setting the stage's
1843
+ // tieBreaker explicitly (e.g. 'prefer-first-ranked').
1844
+ tieBreaker: {
1845
+ mode: "inconclusive"
1846
+ }
1847
+ };
1848
+ if (overrides) {
1849
+ if (overrides.verificationPolicy) {
1850
+ config.verificationPolicy = overrides.verificationPolicy;
1851
+ }
1852
+ if (overrides.repairOnFindings !== void 0) {
1853
+ if (!overrides.repairOnFindings.enabled) {
1854
+ config.repairOnFindings = { enabled: false };
1855
+ } else {
1856
+ config.repairOnFindings = {
1857
+ enabled: true,
1858
+ maxIterations: overrides.repairOnFindings.maxIterations ?? 3,
1859
+ timeboxMs: overrides.repairOnFindings.timeboxMs ?? resolveExecutionBoundary("bounded-loop").hardCeilingMs
1860
+ };
1861
+ }
1862
+ }
1863
+ if (overrides.judgeType) {
1864
+ config.judgeConfig = {
1865
+ ...config.judgeConfig ?? { threshold: defaultThreshold },
1866
+ type: overrides.judgeType
1867
+ };
1868
+ }
1869
+ if (overrides.disableAiJudge) {
1870
+ config.judgeConfig = {
1871
+ ...config.judgeConfig ?? { type: defaultJudgeType, threshold: defaultThreshold },
1872
+ disableAiJudge: true
1873
+ };
1874
+ }
1875
+ if (overrides.judgeAllowUnsafeModel) {
1876
+ config.judgeConfig = {
1877
+ ...config.judgeConfig ?? { type: defaultJudgeType, threshold: defaultThreshold },
1878
+ allowUnsafeModel: true
1879
+ };
1880
+ }
1881
+ if (overrides.aiJudgeRun !== void 0 && overrides.aiJudgeRun !== false) {
1882
+ config.judgeConfig = {
1883
+ ...config.judgeConfig ?? { type: defaultJudgeType, threshold: defaultThreshold },
1884
+ runComparison: true
1885
+ };
1886
+ }
1887
+ }
1888
+ return config;
1889
+ }
1890
+ async function validateAndFilterDependencies(task, sprintTaskIds, completedTaskIds) {
1891
+ const validDeps = [];
1892
+ const satisfiedArchivedDeps = [];
1893
+ const crossSprintDeps = [];
1894
+ const missingDeps = [];
1895
+ const dependencies = Array.isArray(task.dependencies) ? task.dependencies : [];
1896
+ for (const dep of dependencies) {
1897
+ if (sprintTaskIds.has(dep)) {
1898
+ try {
1899
+ const { yaml: depTask } = await getTask(dep, { includeArchive: false });
1900
+ if (depTask.status === "blocked" || depTask.status === "cancelled") {
1901
+ crossSprintDeps.push(`${dep} (status: ${depTask.status})`);
1902
+ continue;
1903
+ }
1904
+ } catch {
1905
+ }
1906
+ validDeps.push(dep);
1907
+ } else {
1908
+ try {
1909
+ const { yaml: depTask, isArchived } = await getTask(dep, { includeArchive: true });
1910
+ const classification = classifyTaskDependency(dep, {
1911
+ task: { status: depTask.status, isArchived }
1912
+ });
1913
+ if (classification.satisfied) {
1914
+ satisfiedArchivedDeps.push(dep);
1915
+ } else {
1916
+ crossSprintDeps.push(isArchived ? `${dep} (archived status: ${depTask.status})` : dep);
1917
+ }
1918
+ } catch {
1919
+ const classification = classifyTaskDependency(dep, {
1920
+ task: null,
1921
+ recordedComplete: completedTaskIds.has(dep)
1922
+ });
1923
+ if (classification.satisfied) {
1924
+ satisfiedArchivedDeps.push(dep);
1925
+ } else {
1926
+ missingDeps.push(dep);
1927
+ }
1928
+ }
1929
+ }
1930
+ }
1931
+ const canExecute = crossSprintDeps.length === 0 && missingDeps.length === 0;
1932
+ return { validDeps, satisfiedArchivedDeps, crossSprintDeps, missingDeps, canExecute };
1933
+ }
1934
+ async function buildTaskTypeContext(registry) {
1935
+ const candidates = registry.listIds().map((id) => registry.get(id)).filter((v) => v !== null);
1936
+ let aliasMap = TaskTypeAliasMap.empty();
1937
+ try {
1938
+ aliasMap = await TaskTypeAliasMap.load({ cwd: process.cwd() });
1939
+ } catch {
1940
+ }
1941
+ return { registry, candidates, aliasMap };
1942
+ }
1943
+ function resolveTaskTypePolicy(options) {
1944
+ const { task, taskText, ctx } = options;
1945
+ if (!ctx) return null;
1946
+ const explicitId = task.taskType?.trim() || task.resolvedTaskTypeId?.trim() || void 0;
1947
+ const resolution = resolveTaskTypeWithDeclaration({
1948
+ taskText: stripPromptInjections(taskText),
1949
+ candidates: ctx.candidates,
1950
+ explicitId,
1951
+ explicitResolvedBy: "frontmatter",
1952
+ declaredType: task.declaredType,
1953
+ resolveDeclared: (declared) => ctx.aliasMap.resolve(declared),
1954
+ hasId: (id) => ctx.registry.get(id) !== null,
1955
+ fallbackId: "general",
1956
+ // Preserve the original matcher behavior here: the pure candidate matcher
1957
+ // over already-stripped text (NOT the classification-aware variant), so the
1958
+ // declared-term gate adds a step in front without changing matcher scoring.
1959
+ inferFallback: ({ taskText: text, candidates, fallbackId }) => resolveTaskTypeFromCandidates({ taskText: text, candidates, fallbackId })
1960
+ });
1961
+ const def = ctx.registry.get(resolution.id);
1962
+ const effective = getEffectiveTaskTypePolicy({
1963
+ policy: def?.policy ?? {},
1964
+ confidence: resolution.confidence,
1965
+ resolvedBy: resolution.resolvedBy
1966
+ });
1967
+ return { resolution, policy: effective.policy, policySuppressed: effective.suppressed };
1968
+ }
1969
+ function inferStageContract(task, description, policyExecutionIntent, policyIntentAuthority) {
1970
+ let contract = resolveStageContract({
1971
+ title: task.title,
1972
+ text: description,
1973
+ metadataExecutionIntent: task.metadata?.executionIntent,
1974
+ policyExecutionIntent,
1975
+ policyIntentAuthority
1976
+ });
1977
+ if (contract.source === "stage-semantics") {
1978
+ const intent = classifyIntent(description);
1979
+ const isHighConfidenceAnalysis = intent.category === "analyze" && intent.confidence > 0.8;
1980
+ contract = {
1981
+ capabilities: {
1982
+ modifiesFiles: !isHighConfidenceAnalysis,
1983
+ executionIntent: isHighConfidenceAnalysis ? "analysis" : "edit"
1984
+ },
1985
+ source: "intent-classifier",
1986
+ authoritativeAnalysis: false
1987
+ };
1988
+ }
1989
+ for (const key of ["modifiesFiles", "readsFiles", "producesText"]) {
1990
+ const value = task.metadata?.[key];
1991
+ if (typeof value === "boolean") contract.capabilities[key] = value;
1992
+ }
1993
+ return contract;
1994
+ }
1995
+ async function readTaskBody(taskId) {
1996
+ try {
1997
+ const { filePath } = await getTask(taskId, { includeArchive: true });
1998
+ const { body } = await readMarkdownFile(filePath);
1999
+ return parseTaskBody(body);
2000
+ } catch {
2001
+ return {
2002
+ description: "",
2003
+ subtasks: [],
2004
+ notes: "",
2005
+ fileMarkers: [],
2006
+ rawBody: ""
2007
+ };
2008
+ }
2009
+ }
2010
+ async function mapTaskToStage(task, body, sprintTaskIds, completedTaskIds, strict, defaultProvider, competitionOverrides, taskTypeContext, defaultJudgeType = "ai") {
2011
+ const warnings = [];
2012
+ const errors = [];
2013
+ const depValidation = await validateAndFilterDependencies(task, sprintTaskIds, completedTaskIds);
2014
+ if (task.status === "blocked") {
2015
+ const msg = `Task ${task.id} is blocked and cannot be executed until unblocked. Run: build plan task unblock ${task.id} --to todo`;
2016
+ if (strict) {
2017
+ errors.push(msg);
2018
+ } else {
2019
+ warnings.push(`SKIPPING: ${msg}`);
2020
+ return {
2021
+ stage: null,
2022
+ skipped: true,
2023
+ warnings,
2024
+ errors,
2025
+ skipMeta: { taskId: task.id, reason: "blocked", message: msg }
2026
+ };
2027
+ }
2028
+ }
2029
+ if (depValidation.satisfiedArchivedDeps.length > 0) {
2030
+ warnings.push(
2031
+ `Task ${task.id} has archived/completed deps (satisfied): ${depValidation.satisfiedArchivedDeps.join(", ")}`
2032
+ );
2033
+ }
2034
+ if (depValidation.crossSprintDeps.length > 0) {
2035
+ const msg = `Task ${task.id} has cross-sprint deps that are not yet done: ${depValidation.crossSprintDeps.join(", ")}`;
2036
+ if (strict) {
2037
+ errors.push(msg);
2038
+ } else {
2039
+ warnings.push(`SKIPPING: ${msg}`);
2040
+ return {
2041
+ stage: null,
2042
+ skipped: true,
2043
+ warnings,
2044
+ errors,
2045
+ skipMeta: { taskId: task.id, reason: "crossSprintDep", message: msg }
2046
+ };
2047
+ }
2048
+ }
2049
+ if (depValidation.missingDeps.length > 0) {
2050
+ const msg = `Task ${task.id} has missing deps: ${depValidation.missingDeps.join(", ")}`;
2051
+ if (strict) {
2052
+ errors.push(msg);
2053
+ } else {
2054
+ warnings.push(`SKIPPING: ${msg}`);
2055
+ return {
2056
+ stage: null,
2057
+ skipped: true,
2058
+ warnings,
2059
+ errors,
2060
+ skipMeta: { taskId: task.id, reason: "missing", message: msg }
2061
+ };
2062
+ }
2063
+ }
2064
+ const taskText = `${task.title}
2065
+
2066
+ ${body.rawBody || body.description || ""}`;
2067
+ const classificationText = stripTaskHeaderMetadata(taskText);
2068
+ const taskTypePolicy = resolveTaskTypePolicy({
2069
+ task,
2070
+ taskText: classificationText,
2071
+ ctx: taskTypeContext
2072
+ });
2073
+ if (task.taskType && taskTypeContext && taskTypePolicy?.resolution.resolvedBy !== "frontmatter") {
2074
+ warnings.push(`Task ${task.id}: unknown taskType override '${task.taskType}' (falling back)`);
2075
+ }
2076
+ if (taskTypePolicy && (taskTypePolicy.resolution.id !== "general" || task.taskType)) {
2077
+ const suppressedNote = taskTypePolicy.policySuppressed ? "; low-confidence match, restrictive policy suppressed" : "";
2078
+ warnings.push(
2079
+ `Task ${task.id}: taskType=${taskTypePolicy.resolution.id} (${taskTypePolicy.resolution.resolvedBy}${suppressedNote})`
2080
+ );
2081
+ }
2082
+ const resolvedBy = taskTypePolicy?.resolution.resolvedBy;
2083
+ const stagePolicyExecutionIntent = resolvedBy === "fallback" ? void 0 : taskTypePolicy?.policy.executionIntent;
2084
+ const policyIntentAuthority = stagePolicyExecutionIntent === void 0 ? void 0 : resolvedBy === "frontmatter" ? "explicit" : "inferred";
2085
+ const stageContract = inferStageContract(
2086
+ task,
2087
+ classificationText,
2088
+ stagePolicyExecutionIntent,
2089
+ policyIntentAuthority
2090
+ );
2091
+ const capabilities = stageContract.capabilities;
2092
+ if (capabilities.executionIntent === "analysis" && policyIntentAuthority === "inferred" && stagePolicyExecutionIntent === "edit") {
2093
+ warnings.push(
2094
+ `Task ${task.id}: runs read-only (${stageContract.source}) although taskType=${taskTypePolicy?.resolution.id} expects edits; no files will change. To edit, run: build plan task update ${task.id} --execution-intent edit`
2095
+ );
2096
+ }
2097
+ const validation = capabilities.executionIntent === "analysis" ? { enabled: false } : { enabled: true, threshold: 60 };
2098
+ void (capabilities.executionIntent === "analysis");
2099
+ const stage = {
2100
+ id: task.id,
2101
+ name: task.title,
2102
+ deps: depValidation.validDeps.length > 0 ? depValidation.validDeps : void 0,
2103
+ prompt: buildPromptFromTask(task, body),
2104
+ templateVariables: {
2105
+ reviewAcceptanceCriteria: extractAcceptanceCriteria(body.rawBody || body.description || "", {
2106
+ checkboxFallback: false
2107
+ })
2108
+ },
2109
+ capabilities,
2110
+ validation
2111
+ };
2112
+ const declaredTargets = [
2113
+ ...body.fileMarkers,
2114
+ ...task.flywheel?.validation?.requiredFiles ?? []
2115
+ ];
2116
+ const inferredTargetCandidates = Array.from(
2117
+ new Set(
2118
+ declaredTargets.length > 0 ? declaredTargets : extractLikelyPathReferences(classificationText)
2119
+ )
2120
+ );
2121
+ const inferredAllowlistTargets = inferredTargetCandidates.filter(isRepoRelativeTargetPath);
2122
+ const unusableTargets = inferredTargetCandidates.filter(
2123
+ (target) => !isRepoRelativeTargetPath(target)
2124
+ );
2125
+ if (unusableTargets.length > 0) {
2126
+ warnings.push(
2127
+ `Task ${task.id}: ignored target path(s) that cannot be repo-relative: ${unusableTargets.join(", ")}`
2128
+ );
2129
+ }
2130
+ const groundedInferredAllowlistTargets = inferredAllowlistTargets.filter(
2131
+ (target) => !isIgnoredTargetPath(target)
2132
+ );
2133
+ const removedStrategyPolicyWarning = taskTypeDefaultStrategyWarning(
2134
+ task.id,
2135
+ taskTypePolicy?.policy
2136
+ );
2137
+ if (removedStrategyPolicyWarning) {
2138
+ warnings.push(removedStrategyPolicyWarning);
2139
+ }
2140
+ if (taskTypePolicy) {
2141
+ stage.templateVariables = {
2142
+ ...stage.templateVariables,
2143
+ taskTypeId: taskTypePolicy.resolution.id,
2144
+ taskTypeResolvedBy: taskTypePolicy.resolution.resolvedBy
2145
+ };
2146
+ const taskTypeAllowlistMode = taskTypePolicy.policy.allowlist?.mode;
2147
+ const hasAllowlistScope = (stage.allowlist?.length ?? 0) > 0 || (task.flywheel?.allowlist?.length ?? 0) > 0 || groundedInferredAllowlistTargets.length > 0;
2148
+ const requiresNonEmptyAllowlist = taskTypePolicy.policy.allowlist?.requireNonEmpty === true;
2149
+ if (!task.flywheel?.allowlistMode && taskTypeAllowlistMode && !stage.allowlistMode) {
2150
+ if (taskTypeAllowlistMode === "strict" && requiresNonEmptyAllowlist && !hasAllowlistScope && capabilities.executionIntent !== "analysis") {
2151
+ const msg = `Task ${task.id}: taskType policy requires a non-empty allowlist; refine the task scope before execution`;
2152
+ if (strict) {
2153
+ errors.push(msg);
2154
+ } else {
2155
+ warnings.push(`SKIPPING: ${msg}`);
2156
+ return {
2157
+ stage: null,
2158
+ skipped: true,
2159
+ warnings,
2160
+ errors,
2161
+ skipMeta: { taskId: task.id, reason: "refinement", message: msg }
2162
+ };
2163
+ }
2164
+ } else {
2165
+ stage.allowlistMode = taskTypeAllowlistMode;
2166
+ }
2167
+ }
2168
+ if (requiresNonEmptyAllowlist && stage.allowlistMode === "strict" && !hasAllowlistScope) {
2169
+ warnings.push(`Task ${task.id}: taskType policy requires a non-empty allowlist (strict)`);
2170
+ }
2171
+ }
2172
+ if (task.routing) {
2173
+ if (task.routing.provider) stage.provider = task.routing.provider;
2174
+ if (task.routing.model) stage.model = task.routing.model;
2175
+ if (task.routing.reasoning || task.routing.profile) {
2176
+ stage.templateVariables = {
2177
+ ...stage.templateVariables,
2178
+ routingReasoning: task.routing.reasoning,
2179
+ routingProfile: task.routing.profile
2180
+ };
2181
+ }
2182
+ if (task.routing.strategy) {
2183
+ warnings.push(
2184
+ `Task ${task.id}: routing pin 'strategy' is accepted and ignored (variant strategies were removed; see ADR-025)`
2185
+ );
2186
+ }
2187
+ const pins = [
2188
+ task.routing.provider && `provider=${task.routing.provider}`,
2189
+ task.routing.model && `model=${task.routing.model}`
2190
+ ].filter(Boolean).join(", ");
2191
+ if (pins) {
2192
+ warnings.push(`Task ${task.id} has routing pins: ${pins}`);
2193
+ }
2194
+ }
2195
+ if (task.flywheel) {
2196
+ if (task.flywheel.modelReasoningEffort) {
2197
+ stage.modelReasoningEffort = task.flywheel.modelReasoningEffort;
2198
+ }
2199
+ if (task.flywheel.type) {
2200
+ stage.type = task.flywheel.type;
2201
+ }
2202
+ if (task.flywheel.inputs && task.flywheel.inputs.length > 0) {
2203
+ stage.inputs = task.flywheel.inputs;
2204
+ }
2205
+ if (task.flywheel.outputs) {
2206
+ stage.outputs = task.flywheel.outputs;
2207
+ }
2208
+ if (task.flywheel.validation) {
2209
+ stage.validation = {
2210
+ ...stage.validation ?? { enabled: false },
2211
+ ...task.flywheel.validation
2212
+ };
2213
+ }
2214
+ if (task.flywheel.competition) {
2215
+ stage.type = "competition";
2216
+ stage.competition = task.flywheel.competition;
2217
+ }
2218
+ if (task.flywheel.allowEmptyResults !== void 0) {
2219
+ stage.allowEmptyResults = task.flywheel.allowEmptyResults;
2220
+ }
2221
+ if (task.flywheel.allowlist && task.flywheel.allowlist.length > 0) {
2222
+ stage.allowlist = task.flywheel.allowlist;
2223
+ }
2224
+ if (task.flywheel.allowlistMode) {
2225
+ stage.allowlistMode = task.flywheel.allowlistMode;
2226
+ }
2227
+ if (task.flywheel.allowDenylist && task.flywheel.allowDenylist.length > 0) {
2228
+ stage.allowDenylist = task.flywheel.allowDenylist;
2229
+ }
2230
+ if (task.flywheel.verify && task.flywheel.verify.commands.length > 0) {
2231
+ stage.verify = task.flywheel.verify;
2232
+ }
2233
+ if (task.flywheel.type === "autoloop" || task.flywheel.autoloop) {
2234
+ stage.type = "autoloop";
2235
+ stage.autoloop = task.flywheel.autoloop ?? {};
2236
+ warnings.push(
2237
+ `Task ${task.id}: Explicit autoloop configuration applied (maxIterations: ${stage.autoloop.maxIterations ?? 3})`
2238
+ );
2239
+ }
2240
+ if (stage.type === "verify" && stage.verify?.commands && stage.verify.commands.length > 0) {
2241
+ if (stage.validation?.semanticChecks) {
2242
+ delete stage.validation.semanticChecks;
2243
+ }
2244
+ }
2245
+ }
2246
+ if (!hasExplicitFlywheelConfig(task)) {
2247
+ const isExplicitAnalysisIntent = capabilities.executionIntent === "analysis" && stageContract.authoritativeAnalysis;
2248
+ const isFusionDefaultActivity = task.taskClassification?.activity !== void 0 && FUSION_DEFAULT_ACTIVITIES.has(task.taskClassification.activity);
2249
+ const useMatchedAnalysisIntent = !task.taskClassification && taskTypePolicy?.resolution.id === "analysis" && taskTypePolicy.policy.executionIntent === "analysis";
2250
+ const policyExecutionIntent = taskTypePolicy?.policy.executionIntent;
2251
+ const strategyExecutionIntent = task.metadata?.executionIntent ?? (policyExecutionIntent === "analysis" && (task.taskType || useMatchedAnalysisIntent) ? policyExecutionIntent : void 0);
2252
+ const strategyTask = strategyExecutionIntent && strategyExecutionIntent !== task.metadata?.executionIntent ? {
2253
+ ...task,
2254
+ metadata: {
2255
+ ...task.metadata,
2256
+ executionIntent: strategyExecutionIntent
2257
+ }
2258
+ } : task;
2259
+ const policyPreferCompetition = taskTypePolicy?.policy.routing?.preferCompetition;
2260
+ const preferCompetition = isFusionDefaultActivity || policyPreferCompetition === true && !isExplicitAnalysisIntent;
2261
+ const policyPrefersSinglePass = !isFusionDefaultActivity && policyPreferCompetition === false;
2262
+ const strategySelection = competitionOverrides?.forceSinglePass ? {
2263
+ strategy: "single-pass",
2264
+ reasons: ["--single-pass requested"],
2265
+ confidence: 100,
2266
+ hasExplicitConfig: false
2267
+ } : isExplicitAnalysisIntent && !isFusionDefaultActivity ? {
2268
+ strategy: "single-pass",
2269
+ reasons: ["analysis intent avoids competition fan-in"],
2270
+ confidence: 100,
2271
+ hasExplicitConfig: false
2272
+ } : preferCompetition ? {
2273
+ strategy: "compete",
2274
+ reasons: [
2275
+ isFusionDefaultActivity ? "activity defaults to Fusion-style competition" : "taskType policy prefers competition"
2276
+ ],
2277
+ confidence: 100,
2278
+ hasExplicitConfig: false
2279
+ } : policyPrefersSinglePass ? {
2280
+ strategy: "single-pass",
2281
+ reasons: ["taskType policy routing.preferCompetition=false prefers single-pass"],
2282
+ confidence: 100,
2283
+ hasExplicitConfig: false
2284
+ } : selectExecutionStrategy(strategyTask);
2285
+ const preferredProvider = task.routing?.provider ?? defaultProvider;
2286
+ if (strategySelection.strategy === "compete") {
2287
+ stage.type = "competition";
2288
+ stage.competition = createDefaultCompetitionConfig(
2289
+ preferredProvider,
2290
+ competitionOverrides,
2291
+ taskTypePolicy?.policy,
2292
+ defaultJudgeType
2293
+ );
2294
+ const competitionVariants = stage.competition.variants;
2295
+ const secondCandidateNote = competitionVariants.length > 1 ? `; ${competitionVariants[0]?.provider} is the preferred candidate and ${competitionVariants[1]?.provider} is added from the provider order (--single-pass runs the preferred provider alone)` : "";
2296
+ warnings.push(
2297
+ `Task ${task.id}: Strategy selection \u2192 competition (${strategySelection.reasons.join("; ")})${secondCandidateNote}`
2298
+ );
2299
+ } else if (strategySelection.strategy === "single-pass") {
2300
+ stage.type = "standard";
2301
+ warnings.push(
2302
+ `Task ${task.id}: Strategy selection \u2192 single-pass (${strategySelection.reasons.join("; ")})`
2303
+ );
2304
+ } else if (strategySelection.strategy === "autoloop" || strategySelection.strategy === "parallel") {
2305
+ stage.type = "standard";
2306
+ warnings.push(
2307
+ `Task ${task.id}: Strategy selection \u2192 ${strategySelection.strategy} (mapped to standard; full support pending) (${strategySelection.reasons.join("; ")})`
2308
+ );
2309
+ }
2310
+ }
2311
+ if (stage.type === "competition" && task.flywheel?.validation?.enabled === void 0) {
2312
+ stage.validation = { ...stage.validation ?? { enabled: false }, enabled: false };
2313
+ }
2314
+ if (stage.type === "competition" && stage.competition && competitionOverrides?.judgeType) {
2315
+ stage.competition.judgeConfig = {
2316
+ ...stage.competition.judgeConfig ?? { threshold: 70 },
2317
+ type: competitionOverrides.judgeType
2318
+ };
2319
+ }
2320
+ if (stage.type === "competition" && stage.competition && competitionOverrides?.judgeAllowUnsafeModel) {
2321
+ stage.competition.judgeConfig = {
2322
+ ...stage.competition.judgeConfig ?? { type: defaultJudgeType, threshold: 70 },
2323
+ allowUnsafeModel: true
2324
+ };
2325
+ }
2326
+ if (stage.type === "competition" && stage.competition && taskTypePolicy) {
2327
+ if (!stage.competition.judgeConfig) {
2328
+ stage.competition.judgeConfig = {
2329
+ type: defaultJudgeType,
2330
+ threshold: 70
2331
+ };
2332
+ }
2333
+ const judgeConfig = stage.competition.judgeConfig;
2334
+ const defaultScore = taskTypePolicy.policy.judging?.defaultScore;
2335
+ if (judgeConfig.threshold === void 0 && typeof defaultScore === "number") {
2336
+ judgeConfig.threshold = defaultScore;
2337
+ }
2338
+ const minimumScore = taskTypePolicy.policy.judging?.minimumScore;
2339
+ if (typeof minimumScore === "number") {
2340
+ const current = judgeConfig.threshold ?? 0;
2341
+ if (current < minimumScore) {
2342
+ judgeConfig.threshold = minimumScore;
2343
+ warnings.push(
2344
+ `Task ${task.id}: clamped judge threshold to ${minimumScore} (taskType minimumScore)`
2345
+ );
2346
+ }
2347
+ }
2348
+ }
2349
+ if (stage.allowEmptyResults === void 0) {
2350
+ const descriptionText = `${task.title ?? ""}
2351
+ ${body.rawBody ?? body.description ?? ""}`.toLowerCase();
2352
+ const idempotentPatterns = /\b(idempotent|make no (?:repository |file )?changes|no changes (?:needed|required|expected)|already (?:correct|satisfied|present)|succeed with (?:no|zero) (?:changes|edits|file changes))\b/;
2353
+ if (idempotentPatterns.test(descriptionText)) {
2354
+ stage.allowEmptyResults = true;
2355
+ warnings.push(
2356
+ `Task ${task.id}: auto-detected idempotent intent from description \u2192 allowEmptyResults=true`
2357
+ );
2358
+ }
2359
+ }
2360
+ if (stage.capabilities?.executionIntent === "analysis" && stage.allowEmptyResults === void 0) {
2361
+ stage.allowEmptyResults = true;
2362
+ }
2363
+ if (stage.validation?.requireChanges === void 0) {
2364
+ const isEditIntent = stage.capabilities?.executionIntent === "edit";
2365
+ const isApplyWinnerCompetition = stage.type === "competition" && stage.competition?.applyWinner === true;
2366
+ if (stage.allowEmptyResults === true || stage.type === "verify") {
2367
+ stage.validation = stage.validation ?? { enabled: false };
2368
+ stage.validation.requireChanges = false;
2369
+ } else if (isEditIntent || isApplyWinnerCompetition) {
2370
+ stage.validation = stage.validation ?? { enabled: false };
2371
+ stage.validation.requireChanges = true;
2372
+ }
2373
+ }
2374
+ if (stage.capabilities?.executionIntent === "analysis" && !stage.outputs) {
2375
+ stage.outputs = { report: "text" };
2376
+ }
2377
+ const taskTargetPaths = Array.from(
2378
+ /* @__PURE__ */ new Set([
2379
+ ...inferredAllowlistTargets,
2380
+ ...stage.allowlist ?? [],
2381
+ ...stage.validation?.requiredFiles ?? []
2382
+ ])
2383
+ );
2384
+ if ((stage.allowlist?.length ?? 0) === 0 && groundedInferredAllowlistTargets.length > 0) {
2385
+ stage.allowlist = groundedInferredAllowlistTargets;
2386
+ }
2387
+ const exactLineContent = extractExactOneLineContent(body.rawBody ?? body.description ?? "");
2388
+ const exactLineTargets = (stage.allowlist ?? []).filter((target) => !isIgnoredTargetPath(target));
2389
+ if (exactLineContent && exactLineTargets.length === 1) {
2390
+ const command = buildExactLineVerifyCommand(exactLineTargets[0], exactLineContent);
2391
+ const existingCommands = stage.verify?.commands ?? [];
2392
+ if (!existingCommands.includes(command)) {
2393
+ stage.verify = { commands: [...existingCommands, command] };
2394
+ warnings.push(`Task ${task.id}: added exact-line verify command for ${exactLineTargets[0]}`);
2395
+ }
2396
+ }
2397
+ if ((stage.verify?.commands?.length ?? 0) === 0) {
2398
+ const bodyVerifyCommands = extractBodyVerifyCommands(body.rawBody ?? body.description ?? "");
2399
+ for (const rejected of bodyVerifyCommands.rejected) {
2400
+ warnings.push(
2401
+ `Task ${task.id}: dropped How to Verify command ${JSON.stringify(rejected.command)} because ${rejected.reason.replace(/^Verify command rejected:\s*/i, "")}`
2402
+ );
2403
+ }
2404
+ for (const line of bodyVerifyCommands.ignoredProse) {
2405
+ warnings.push(
2406
+ `Task ${task.id}: ignored How to Verify line ${JSON.stringify(line.length > 120 ? `${line.slice(0, 117)}...` : line)} because it is not in backticks or a fenced block; only backticked or fenced commands run`
2407
+ );
2408
+ }
2409
+ if (bodyVerifyCommands.commands.length > 0) {
2410
+ stage.verify = { commands: bodyVerifyCommands.commands };
2411
+ warnings.push(
2412
+ `Task ${task.id}: added ${bodyVerifyCommands.commands.length} verify command(s) from How to Verify`
2413
+ );
2414
+ } else if (bodyVerifyCommands.sectionFound) {
2415
+ warnings.push(
2416
+ `Task ${task.id}: How to Verify has no runnable commands; the quality gate will use project-resolved verification commands`
2417
+ );
2418
+ }
2419
+ }
2420
+ const { targets: ignoredTargets } = await collectGitignoredTargets({
2421
+ repoRoot: getPlanningRoot(),
2422
+ targets: taskTargetPaths
2423
+ });
2424
+ if (ignoredTargets.length > 0) {
2425
+ const describeIgnored = (targets) => `Task ${task.id}: target path(s) are gitignored/runtime-scoped and may produce no fan-in material: ` + targets.join(", ");
2426
+ const refusableTargets = strict ? ignoredTargets.filter(isIgnoredTargetPath) : [];
2427
+ const advisoryTargets = ignoredTargets.filter((target) => !refusableTargets.includes(target));
2428
+ if (refusableTargets.length > 0) {
2429
+ errors.push(describeIgnored(refusableTargets));
2430
+ }
2431
+ if (advisoryTargets.length > 0) {
2432
+ warnings.push(
2433
+ `${describeIgnored(advisoryTargets)}. Use tracked paths for change-producing sprint validation tasks.`
2434
+ );
2435
+ }
2436
+ }
2437
+ const undeliverableWarning = formatUndeliverableTargetsWarning(
2438
+ task.id,
2439
+ collectUndeliverableTargets(taskTargetPaths)
2440
+ );
2441
+ if (undeliverableWarning) {
2442
+ warnings.push(undeliverableWarning);
2443
+ }
2444
+ const explicitDeliverables = (task.flywheel?.validation?.requiredFiles?.length ?? 0) > 0;
2445
+ const createIntentTargets = explicitDeliverables ? [] : inferCreateIntentTargets({
2446
+ title: task.title,
2447
+ body: body.rawBody || body.description || ""
2448
+ });
2449
+ if (createIntentTargets.length > 0) {
2450
+ stage.prompt = annotatePromptWithCreateTargets(stage.prompt ?? "", createIntentTargets);
2451
+ const validationTargets = createIntentTargets.filter((target) => !isIgnoredTargetPath(target));
2452
+ addCreateIntentValidation(stage, validationTargets);
2453
+ }
2454
+ if (stage.validation?.enabled && stage.outputs && Object.keys(stage.outputs).length > 1) {
2455
+ if (!stage.validation.target) {
2456
+ if (Object.hasOwn(stage.outputs, "bundle")) {
2457
+ stage.validation.target = "bundle";
2458
+ } else {
2459
+ const entries = Object.entries(stage.outputs);
2460
+ const diffEntry = entries.find(([, type]) => type === "diff");
2461
+ const filesEntry = entries.find(([, type]) => type === "files");
2462
+ stage.validation.target = diffEntry?.[0] ?? filesEntry?.[0] ?? Object.keys(stage.outputs)[0] ?? void 0;
2463
+ }
2464
+ if (stage.validation.target) {
2465
+ warnings.push(
2466
+ `Stage ${task.id}: defaulted validation.target to '${stage.validation.target}' for multi-output stage`
2467
+ );
2468
+ }
2469
+ }
2470
+ }
2471
+ const hasAssignmentOutput = stage.type !== "competition" && Boolean(stage.outputs && Object.hasOwn(stage.outputs, "assignment"));
2472
+ if (hasAssignmentOutput && stage.capabilities?.executionIntent === "analysis") {
2473
+ stage.validation = stage.validation ?? { enabled: false };
2474
+ stage.validation.semanticChecks = stage.validation.semanticChecks ?? getP1SemanticChecks();
2475
+ stage.validation.onFailure = stage.validation.onFailure ?? "retry-with-feedback";
2476
+ stage.validation.maxRetries = stage.validation.maxRetries ?? 2;
2477
+ warnings.push(
2478
+ `Stage ${task.id}: applied default semantic assignment gates + retry-with-feedback (${stage.validation.maxRetries} retries)`
2479
+ );
2480
+ }
2481
+ return {
2482
+ stage,
2483
+ contract: {
2484
+ executionIntent: capabilities.executionIntent === "analysis" ? "analysis" : "edit",
2485
+ source: stageContract.source
2486
+ },
2487
+ skipped: false,
2488
+ warnings,
2489
+ errors
2490
+ };
2491
+ }
2492
+ async function buildWorkflowStages(tasks, sprintTaskIds, completedTaskIds, strict, initialSkippedTaskIds, defaultProvider, competitionOverrides, taskTypeContext, defaultJudgeType = "ai") {
2493
+ const stages = [];
2494
+ const stageContracts = {};
2495
+ const skippedTaskIds = new Set(initialSkippedTaskIds);
2496
+ const skippedTasks = [];
2497
+ const allWarnings = [];
2498
+ const allErrors = [];
2499
+ const mappingResults = /* @__PURE__ */ new Map();
2500
+ for (const task of tasks) {
2501
+ const body = await readTaskBody(task.id);
2502
+ const result = await mapTaskToStage(
2503
+ task,
2504
+ body,
2505
+ sprintTaskIds,
2506
+ completedTaskIds,
2507
+ strict,
2508
+ defaultProvider,
2509
+ competitionOverrides,
2510
+ taskTypeContext,
2511
+ defaultJudgeType
2512
+ );
2513
+ mappingResults.set(task.id, result);
2514
+ if (result.skipped) {
2515
+ skippedTaskIds.add(task.id);
2516
+ if (result.skipMeta) {
2517
+ skippedTasks.push(result.skipMeta);
2518
+ }
2519
+ }
2520
+ allWarnings.push(...result.warnings);
2521
+ allErrors.push(...result.errors);
2522
+ }
2523
+ let changed = true;
2524
+ while (changed) {
2525
+ changed = false;
2526
+ for (const [taskId, result] of mappingResults) {
2527
+ if (result.skipped) continue;
2528
+ if (!result.stage) continue;
2529
+ const hasSkippedDep = result.stage.deps?.some((dep) => skippedTaskIds.has(dep)) ?? false;
2530
+ if (hasSkippedDep) {
2531
+ const skippedDeps = result.stage.deps?.filter((dep) => skippedTaskIds.has(dep)) ?? [];
2532
+ const msg = `Task ${taskId} depends on skipped tasks: ${skippedDeps.join(", ")}`;
2533
+ allWarnings.push(`SKIPPING: ${msg}`);
2534
+ skippedTaskIds.add(taskId);
2535
+ skippedTasks.push({ taskId, reason: "dependsOnSkipped", message: msg });
2536
+ result.skipped = true;
2537
+ result.stage = null;
2538
+ changed = true;
2539
+ }
2540
+ }
2541
+ }
2542
+ for (const [_taskId, result] of mappingResults) {
2543
+ if (result.stage && !result.skipped) {
2544
+ if (result.stage.deps) {
2545
+ result.stage.deps = result.stage.deps.filter((dep) => !skippedTaskIds.has(dep));
2546
+ }
2547
+ stages.push(result.stage);
2548
+ if (result.contract) stageContracts[result.stage.id] = result.contract;
2549
+ }
2550
+ }
2551
+ return {
2552
+ // Declared dependencies decide stage order, so the default previous-stage dependency
2553
+ // later given to a stage without deps never contradicts one.
2554
+ stages: orderStagesByDeclaredDeps(stages),
2555
+ stageContracts,
2556
+ skippedTaskIds,
2557
+ skippedTasks,
2558
+ warnings: allWarnings,
2559
+ errors: allErrors
2560
+ };
2561
+ }
2562
+ async function collectTasksWithUnfilledSpecMarkers(tasks) {
2563
+ const taskIds = [];
2564
+ for (const task of tasks) {
2565
+ const body = await readTaskBody(task.id);
2566
+ if (hasUnfilledMarkers(body.rawBody || body.description || "")) {
2567
+ taskIds.push(task.id);
2568
+ }
2569
+ }
2570
+ return taskIds;
2571
+ }
2572
+ async function loadSprintData(sprintId) {
2573
+ const planningRoot = getPlanningRoot();
2574
+ const sprintPath = path.join(getBucketPathByKind("sprint", planningRoot), `${sprintId}.md`);
2575
+ try {
2576
+ const { frontMatter } = await readMarkdownFile(sprintPath);
2577
+ return {
2578
+ taskIds: frontMatter.taskIds || [],
2579
+ completedTaskIds: frontMatter.completedTaskIds || []
2580
+ };
2581
+ } catch (_error) {
2582
+ try {
2583
+ const archivedRoot = getBucketArchivePathByKind("sprint", planningRoot);
2584
+ const files = await listMarkdownFilesRecursive(archivedRoot);
2585
+ const file = files.find((p) => path.basename(p) === `${sprintId}.md`);
2586
+ if (!file) {
2587
+ throw new Error("not found");
2588
+ }
2589
+ const { frontMatter } = await readMarkdownFile(file);
2590
+ return {
2591
+ taskIds: frontMatter.taskIds || [],
2592
+ completedTaskIds: frontMatter.completedTaskIds || []
2593
+ };
2594
+ } catch {
2595
+ throw new Error(`Sprint not found: ${sprintId}`);
2596
+ }
2597
+ }
2598
+ }
2599
+ async function validateAndLoadTasks(taskIds, strict) {
2600
+ const tasks = [];
2601
+ const warnings = [];
2602
+ const errors = [];
2603
+ const skippedIds = [];
2604
+ const archivedIds = [];
2605
+ const doneIds = [];
2606
+ const skippedTasks = [];
2607
+ for (const taskId of taskIds) {
2608
+ try {
2609
+ const { yaml: task, isArchived } = await getTask(taskId, { includeArchive: true });
2610
+ if (isArchived) {
2611
+ const msg = `Task ${taskId} is archived (already completed).`;
2612
+ if (strict) {
2613
+ errors.push(msg);
2614
+ } else {
2615
+ warnings.push(`SKIPPING: ${msg}`);
2616
+ skippedIds.push(taskId);
2617
+ archivedIds.push(taskId);
2618
+ skippedTasks.push({ taskId, reason: "archived", message: msg });
2619
+ }
2620
+ continue;
2621
+ }
2622
+ if (task.status === "done") {
2623
+ const msg = `Task ${taskId} is already done (status: done).`;
2624
+ if (strict) {
2625
+ errors.push(msg);
2626
+ } else {
2627
+ warnings.push(`SKIPPING: ${msg}`);
2628
+ skippedIds.push(taskId);
2629
+ doneIds.push(taskId);
2630
+ skippedTasks.push({ taskId, reason: "done", message: msg });
2631
+ }
2632
+ continue;
2633
+ }
2634
+ tasks.push(task);
2635
+ } catch {
2636
+ const isBacklogId = taskId.startsWith("backlog-") || taskId.includes("backlog");
2637
+ if (isBacklogId) {
2638
+ const msg = `Task ${taskId} looks like a backlog ID without a task file. Use 'build plan sprint add-task --split' to create task files.`;
2639
+ if (strict) {
2640
+ errors.push(msg);
2641
+ } else {
2642
+ warnings.push(`SKIPPING: ${msg}`);
2643
+ skippedIds.push(taskId);
2644
+ skippedTasks.push({ taskId, reason: "backlogId", message: msg });
2645
+ }
2646
+ } else {
2647
+ const msg = `Task file not found: ${taskId}`;
2648
+ if (strict) {
2649
+ errors.push(msg);
2650
+ } else {
2651
+ warnings.push(`SKIPPING: ${msg}`);
2652
+ skippedIds.push(taskId);
2653
+ skippedTasks.push({ taskId, reason: "missing", message: msg });
2654
+ }
2655
+ }
2656
+ }
2657
+ }
2658
+ return { tasks, warnings, errors, skippedIds, archivedIds, doneIds, skippedTasks };
2659
+ }
2660
+ async function writeWorkflowYaml(workflow, sprintId, workflowId) {
2661
+ let filePath;
2662
+ if (workflowId) {
2663
+ filePath = getWorkflowYamlPath(workflowId);
2664
+ const artifactDir = path.dirname(filePath);
2665
+ await fs.mkdir(artifactDir, { recursive: true });
2666
+ } else {
2667
+ const planningRoot = getPlanningRoot();
2668
+ const workflowsDir = path.join(planningRoot, ".build-project", "workflows");
2669
+ await fs.mkdir(workflowsDir, { recursive: true });
2670
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
2671
+ const filename = `sprint-${sprintId}-${timestamp}.yaml`;
2672
+ filePath = path.join(workflowsDir, filename);
2673
+ }
2674
+ const yamlContent = yaml.dump(workflow, {
2675
+ indent: 2,
2676
+ lineWidth: 120,
2677
+ noRefs: true
2678
+ });
2679
+ await fs.writeFile(filePath, yamlContent, "utf-8");
2680
+ return filePath;
2681
+ }
2682
+ async function generateSprintWorkflow(options) {
2683
+ const {
2684
+ sprintId,
2685
+ taskIds: specificTaskIds,
2686
+ provider,
2687
+ strict = false,
2688
+ competitionOverrides,
2689
+ acceptIncompleteSpec = false
2690
+ } = options;
2691
+ const warnings = [];
2692
+ const errors = [];
2693
+ const skippedTaskIds = [];
2694
+ const skippedTasks = [];
2695
+ let sprintTaskIds;
2696
+ let sprintCompletedTaskIds;
2697
+ try {
2698
+ const sprint = await loadSprintData(sprintId);
2699
+ if (specificTaskIds) {
2700
+ const sprintMembers = new Set(sprint.taskIds);
2701
+ const outsideSprint = [...new Set(specificTaskIds)].filter((id) => !sprintMembers.has(id));
2702
+ if (outsideSprint.length > 0) {
2703
+ return {
2704
+ workflow: null,
2705
+ yamlPath: "",
2706
+ warnings: [],
2707
+ errors: [
2708
+ `Selected task(s) are not members of sprint ${sprintId}: ${outsideSprint.join(", ")}`
2709
+ ],
2710
+ skippedTaskIds: [],
2711
+ skippedTasks: []
2712
+ };
2713
+ }
2714
+ }
2715
+ sprintTaskIds = specificTaskIds ?? sprint.taskIds;
2716
+ sprintCompletedTaskIds = sprint.completedTaskIds;
2717
+ } catch (error) {
2718
+ const msg = error instanceof Error ? error.message : String(error);
2719
+ return {
2720
+ workflow: null,
2721
+ yamlPath: "",
2722
+ warnings: [],
2723
+ errors: [msg],
2724
+ skippedTaskIds: [],
2725
+ skippedTasks: []
2726
+ };
2727
+ }
2728
+ if (sprintTaskIds.length === 0) {
2729
+ const msg = "Sprint has no tasks. Add tasks with `build plan sprint add-task` first.";
2730
+ return {
2731
+ workflow: null,
2732
+ yamlPath: "",
2733
+ warnings: [],
2734
+ errors: [msg],
2735
+ skippedTaskIds: [],
2736
+ skippedTasks: []
2737
+ };
2738
+ }
2739
+ const loadResult = await validateAndLoadTasks(sprintTaskIds, strict);
2740
+ warnings.push(...loadResult.warnings);
2741
+ errors.push(...loadResult.errors);
2742
+ skippedTaskIds.push(...loadResult.skippedIds);
2743
+ skippedTasks.push(...loadResult.skippedTasks);
2744
+ for (const id of loadResult.archivedIds) {
2745
+ if (!skippedTaskIds.includes(id)) {
2746
+ skippedTaskIds.push(id);
2747
+ }
2748
+ }
2749
+ if (strict && errors.length > 0) {
2750
+ return { workflow: null, yamlPath: "", warnings, errors, skippedTaskIds, skippedTasks };
2751
+ }
2752
+ const incompleteSpecTaskIds = await collectTasksWithUnfilledSpecMarkers(loadResult.tasks);
2753
+ if (incompleteSpecTaskIds.length > 0) {
2754
+ const message = `Task spec(s) contain unfilled <<<FILL>>> placeholders: ${incompleteSpecTaskIds.join(", ")}`;
2755
+ if (!acceptIncompleteSpec) {
2756
+ return {
2757
+ workflow: null,
2758
+ yamlPath: "",
2759
+ warnings,
2760
+ errors: [
2761
+ `${message}. Complete the task specs or rerun with --accept-incomplete-spec to proceed anyway.`
2762
+ ],
2763
+ skippedTaskIds,
2764
+ skippedTasks
2765
+ };
2766
+ }
2767
+ warnings.push(`${message}; continuing because --accept-incomplete-spec was provided.`);
2768
+ }
2769
+ let taskTypeContext = null;
2770
+ try {
2771
+ taskTypeContext = await buildTaskTypeContext(
2772
+ await TaskTypeRegistry.load({ cwd: process.cwd() })
2773
+ );
2774
+ } catch (error) {
2775
+ warnings.push(
2776
+ `Task types disabled (failed to load registry): ${error instanceof Error ? error.message : String(error)}`
2777
+ );
2778
+ }
2779
+ const defaultJudgeType = resolveJudgeType(void 0, process.cwd()).value;
2780
+ const completedTaskIds = /* @__PURE__ */ new Set([...loadResult.archivedIds, ...loadResult.doneIds]);
2781
+ for (const id of sprintCompletedTaskIds) completedTaskIds.add(id);
2782
+ const sprintTaskSet = new Set(sprintTaskIds.filter((id) => !completedTaskIds.has(id)));
2783
+ const buildResult = await buildWorkflowStages(
2784
+ loadResult.tasks,
2785
+ sprintTaskSet,
2786
+ completedTaskIds,
2787
+ strict,
2788
+ new Set(loadResult.skippedIds),
2789
+ provider,
2790
+ competitionOverrides,
2791
+ taskTypeContext,
2792
+ defaultJudgeType
2793
+ );
2794
+ warnings.push(...buildResult.warnings);
2795
+ errors.push(...buildResult.errors);
2796
+ for (const id of buildResult.skippedTaskIds) {
2797
+ if (!skippedTaskIds.includes(id)) {
2798
+ skippedTaskIds.push(id);
2799
+ }
2800
+ }
2801
+ for (const s of buildResult.skippedTasks) {
2802
+ if (!skippedTasks.some((existing) => existing.taskId === s.taskId)) {
2803
+ skippedTasks.push(s);
2804
+ }
2805
+ }
2806
+ if (strict && errors.length > 0) {
2807
+ return { workflow: null, yamlPath: "", warnings, errors, skippedTaskIds, skippedTasks };
2808
+ }
2809
+ if (buildResult.stages.length === 0) {
2810
+ const allSkippedMsg = `All ${skippedTaskIds.length} task(s) were skipped. Nothing to execute.`;
2811
+ if (strict) {
2812
+ return {
2813
+ workflow: null,
2814
+ yamlPath: "",
2815
+ warnings,
2816
+ errors: [...errors, allSkippedMsg],
2817
+ skippedTaskIds,
2818
+ skippedTasks
2819
+ };
2820
+ }
2821
+ return {
2822
+ workflow: null,
2823
+ yamlPath: "",
2824
+ warnings: [...warnings, allSkippedMsg],
2825
+ errors: [],
2826
+ skippedTaskIds,
2827
+ skippedTasks
2828
+ };
2829
+ }
2830
+ const workflow = {
2831
+ name: `Sprint: ${sprintId}`,
2832
+ stages: buildResult.stages,
2833
+ strict: {
2834
+ // Warn-first by default: allow stages to make ripple edits without hard-failing.
2835
+ allowlistMode: "warn"
2836
+ // No denylist here: the flywheel's DEFAULT_WORKFLOW_DENYLIST (root manifests and
2837
+ // lockfiles of every ecosystem, CI workflows) applies when none is declared.
2838
+ },
2839
+ git: {
2840
+ commitStrategy: "pass-only",
2841
+ // Default to Run → Review → Integrate: preserve the integration branch/worktree.
2842
+ historyCleanup: "keep-all",
2843
+ skipHooksOnIntermediate: true
2844
+ }
2845
+ };
2846
+ if (provider) {
2847
+ for (const stage of workflow.stages) {
2848
+ if (!stage.provider) {
2849
+ stage.provider = provider;
2850
+ }
2851
+ }
2852
+ }
2853
+ const stampedWorkflow = applyExecutionPolicyToGeneratedWorkflow(workflow, {
2854
+ cliProviderOverride: provider,
2855
+ reviewPolicy: options.reviewPolicy,
2856
+ warnings,
2857
+ // Sprint output already carries its informational lines (strategy selection) here.
2858
+ onProviderPlan: (plan) => warnings.push(plan)
2859
+ });
2860
+ let yamlPath = "";
2861
+ if (!options.dryRun) {
2862
+ yamlPath = await writeWorkflowYaml(stampedWorkflow, sprintId, options.workflowId);
2863
+ }
2864
+ return {
2865
+ workflow: stampedWorkflow,
2866
+ yamlPath,
2867
+ warnings,
2868
+ errors,
2869
+ skippedTaskIds,
2870
+ skippedTasks,
2871
+ runnableTasks: buildResult.stages.map((stage) => ({
2872
+ taskId: stage.id,
2873
+ title: stage.name ?? stage.id
2874
+ })),
2875
+ stageContracts: buildResult.stageContracts
2876
+ };
2877
+ }
2878
+
2879
+ export {
2880
+ getEffectiveTaskTypePolicy,
2881
+ getDefaultCompetitionVariantsForProvider,
2882
+ resolveTaskTypeFromCandidates,
2883
+ resolveTaskTypeWithDeclaration,
2884
+ resolveTaskTypeForText,
2885
+ readEnabledRegistryRoutingSnapshots,
2886
+ CanonicalRoutingError,
2887
+ decideCanonicalRouting,
2888
+ planFlywheelStageRouting,
2889
+ resolveTaskExecutionRoles,
2890
+ describeDormantPolicyMismatch,
2891
+ applyExecutionPolicyToGeneratedWorkflow,
2892
+ resolveStageContract,
2893
+ createDefaultCompetitionConfig,
2894
+ generateSprintWorkflow
2895
+ };
2896
+ //# sourceMappingURL=chunk-MO2BYAAF.js.map