@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,2403 @@
1
+ import {
2
+ estimateRuntime
3
+ } from "./chunk-RNI2GUIF.js";
4
+ import {
5
+ listActive
6
+ } from "./chunk-Q6Z5UGPL.js";
7
+ import {
8
+ findBacklogItem,
9
+ listBacklogItems,
10
+ validateDebtItem
11
+ } from "./chunk-NKLPMBNV.js";
12
+ import {
13
+ isBacklogExecutionProvenanceActivelyExecuting,
14
+ loadBacklogExecutionProvenance
15
+ } from "./chunk-3WY5TU2O.js";
16
+ import {
17
+ DEFAULT_LEASE_TTL_MS,
18
+ HumanReviewRequiredError,
19
+ InvalidTransitionError,
20
+ LeaseExpiredError,
21
+ loadSprintCompletedTaskIds
22
+ } from "./chunk-R5EXHMUN.js";
23
+ import {
24
+ normalizeTaskStatus
25
+ } from "./chunk-NAINGKHF.js";
26
+ import {
27
+ getArchivedFilePath
28
+ } from "./chunk-US3RT6CY.js";
29
+ import {
30
+ buildGraphBlockersView,
31
+ loadWorkGraphContext
32
+ } from "./chunk-PV53ODOT.js";
33
+ import {
34
+ classifyTaskDependency
35
+ } from "./chunk-NXH3RX7O.js";
36
+ import {
37
+ keepActivity
38
+ } from "./chunk-J2QCFLUN.js";
39
+ import {
40
+ getPlanningRoot,
41
+ withIndexRegeneration
42
+ } from "./chunk-CSXLLEGB.js";
43
+ import {
44
+ generateIndexes
45
+ } from "./chunk-VAG6GUBR.js";
46
+ import {
47
+ createWorkItemFile
48
+ } from "./chunk-CIHWPGS5.js";
49
+ import {
50
+ isExpiryLive
51
+ } from "./chunk-6G57FYBV.js";
52
+ import {
53
+ assertBucketWriteAvailable,
54
+ checkSharedBucketReadability,
55
+ planningReadOk,
56
+ unwrapPlanningRead
57
+ } from "./chunk-AJBTKGJZ.js";
58
+ import {
59
+ getBucketArchivePathByKind,
60
+ getBucketByName,
61
+ getBucketPathByKind
62
+ } from "./chunk-V3KLVK7B.js";
63
+ import {
64
+ LocalFileBackend,
65
+ checkVersion
66
+ } from "./chunk-4US4SYJ4.js";
67
+ import {
68
+ StaleVersionError
69
+ } from "./chunk-TDSEX5CF.js";
70
+ import {
71
+ resolvePlanningContextForRoot
72
+ } from "./chunk-BBPIILO2.js";
73
+ import {
74
+ assertSafePathComponent
75
+ } from "./chunk-S2VQCZO4.js";
76
+ import {
77
+ generateId
78
+ } from "./chunk-4DJL2VXA.js";
79
+ import {
80
+ listMarkdownFiles,
81
+ listMarkdownFilesRecursive,
82
+ normalizeMarkdownContent,
83
+ parseMarkdownFile,
84
+ readMarkdownFile,
85
+ writeMarkdownFile
86
+ } from "./chunk-352PCJLK.js";
87
+ import {
88
+ emitWarning
89
+ } from "./chunk-7VRJHTGZ.js";
90
+
91
+ // src/core/read-models/next.ts
92
+ import * as fs3 from "fs/promises";
93
+ import * as path4 from "path";
94
+ import { execa } from "execa";
95
+
96
+ // src/planning/issue-manager.ts
97
+ import * as path from "path";
98
+
99
+ // src/planning/issue-fingerprint.ts
100
+ import { createHash } from "crypto";
101
+ function normalizeSnippet(snippet) {
102
+ return snippet.split("\n").map((line) => line.trim()).filter((line, i, arr) => !(line === "" && arr[i - 1] === "")).join("\n").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").trim();
103
+ }
104
+ function normalizePath(filepath) {
105
+ return filepath.replace(/\\/g, "/").replace(/^\.\//, "").toLowerCase();
106
+ }
107
+ function sha256(input) {
108
+ return createHash("sha256").update(input, "utf8").digest("hex");
109
+ }
110
+ function generateFingerprint(input) {
111
+ const normalizedSnippet = normalizeSnippet(input.snippet);
112
+ const normalizedPath = normalizePath(input.path);
113
+ const snippetHash = sha256(normalizedSnippet);
114
+ const compositeInput = [input.ruleId, snippetHash, input.symbolName ?? "", normalizedPath].join(
115
+ "\0"
116
+ );
117
+ const compositeHash = sha256(compositeInput);
118
+ return {
119
+ ruleId: input.ruleId,
120
+ snippetHash,
121
+ symbolName: input.symbolName,
122
+ path: normalizedPath,
123
+ compositeHash
124
+ };
125
+ }
126
+ function matchFingerprint(candidate, existing) {
127
+ if (candidate.compositeHash === existing.compositeHash) {
128
+ return "exact";
129
+ }
130
+ if (candidate.ruleId === existing.ruleId && candidate.symbolName && existing.symbolName && candidate.symbolName === existing.symbolName) {
131
+ return "fuzzy";
132
+ }
133
+ return "none";
134
+ }
135
+ function findDuplicate(candidate, existingFingerprints) {
136
+ let bestExact = null;
137
+ let bestFuzzy = null;
138
+ for (const existing of existingFingerprints) {
139
+ const strength = matchFingerprint(candidate, existing.fingerprint);
140
+ if (strength === "exact") {
141
+ if (!bestExact || existing.findingId < bestExact.existingFindingId) {
142
+ bestExact = {
143
+ strength: "exact",
144
+ existingFindingId: existing.findingId,
145
+ fingerprint: existing.fingerprint
146
+ };
147
+ }
148
+ continue;
149
+ }
150
+ if (strength === "fuzzy") {
151
+ const confidence = computeFuzzyConfidence(candidate, existing.fingerprint);
152
+ const reason = describeFuzzyMatch(candidate, existing.fingerprint);
153
+ if (!bestFuzzy || confidence > (bestFuzzy.confidence ?? 0) || Math.abs(confidence - (bestFuzzy.confidence ?? 0)) < Number.EPSILON && existing.findingId < bestFuzzy.existingFindingId) {
154
+ bestFuzzy = {
155
+ strength: "fuzzy",
156
+ existingFindingId: existing.findingId,
157
+ fingerprint: existing.fingerprint,
158
+ confidence,
159
+ reason
160
+ };
161
+ }
162
+ }
163
+ }
164
+ if (bestExact) return bestExact;
165
+ return bestFuzzy;
166
+ }
167
+ function computeFuzzyConfidence(candidate, existing) {
168
+ let confidence = 0.55;
169
+ if (candidate.snippetHash === existing.snippetHash) confidence += 0.25;
170
+ if (candidate.path === existing.path) confidence += 0.2;
171
+ return Math.min(1, confidence);
172
+ }
173
+ function describeFuzzyMatch(candidate, existing) {
174
+ const details = ["matched ruleId + symbolName"];
175
+ details.push(
176
+ candidate.snippetHash === existing.snippetHash ? "same snippet hash" : "different snippet hash"
177
+ );
178
+ details.push(candidate.path === existing.path ? "same path" : "different path");
179
+ return details.join("; ");
180
+ }
181
+ function trackOccurrence(currentCount, now = /* @__PURE__ */ new Date()) {
182
+ return {
183
+ lastSeenAt: now.toISOString(),
184
+ occurrenceCount: currentCount + 1
185
+ };
186
+ }
187
+
188
+ // src/planning/issue-state-machine.ts
189
+ var FINDING_TRANSITIONS = {
190
+ raw: ["open", "closed"],
191
+ open: ["closed"],
192
+ closed: []
193
+ };
194
+ var ISSUE_TRANSITIONS = {
195
+ open: ["claimed", "investigating", "wontfix", "duplicate"],
196
+ claimed: ["claimed", "resolved", "open", "wontfix", "duplicate", "investigating"],
197
+ investigating: ["claimed", "open", "resolved", "wontfix", "duplicate"],
198
+ resolved: [],
199
+ // terminal
200
+ wontfix: [],
201
+ // terminal
202
+ duplicate: []
203
+ // terminal
204
+ };
205
+ function requiresHumanActorForIssue(toStatus, category, severity) {
206
+ if (toStatus === "wontfix" && (category === "security" || severity === "critical")) {
207
+ return true;
208
+ }
209
+ return false;
210
+ }
211
+ function requiresHumanActorForFinding(finding, toStatus) {
212
+ return finding.status === "raw" && toStatus === "open" && finding.requiresHumanReview;
213
+ }
214
+ function isEffectivelyClaimed(entity, now = /* @__PURE__ */ new Date()) {
215
+ if (!entity.claimedBy || !entity.expiresAt) return false;
216
+ return isExpiryLive(entity.expiresAt, now.toISOString());
217
+ }
218
+ function assertClaimTransitionAuthorized(issue, toStatus, actor, now) {
219
+ const carriesClaim = issue.status === "claimed" || issue.status === "investigating" && issue.claimedBy !== void 0;
220
+ if (!carriesClaim || toStatus === "claimed") return;
221
+ if (issue.claimedBy !== actor.actorId) {
222
+ throw new InvalidTransitionError(
223
+ issue.id,
224
+ issue.status,
225
+ toStatus,
226
+ `Only the claimant ${issue.claimedBy ?? "unknown"} can transition an owned issue`
227
+ );
228
+ }
229
+ if (!isEffectivelyClaimed(issue, now)) {
230
+ throw new LeaseExpiredError(issue.id, issue.expiresAt ?? "unknown");
231
+ }
232
+ }
233
+ function transitionFinding(input) {
234
+ const { finding, toStatus, actor, expectedVersion, closedReason, fixCommit, deferredNote } = input;
235
+ const now = input.now ?? /* @__PURE__ */ new Date();
236
+ const nowISO = now.toISOString();
237
+ checkVersion(finding.id, finding.version, expectedVersion);
238
+ const allowed = FINDING_TRANSITIONS[finding.status];
239
+ if (!allowed.includes(toStatus)) {
240
+ throw new InvalidTransitionError(finding.id, finding.status, toStatus);
241
+ }
242
+ if (requiresHumanActorForFinding(finding, toStatus) && actor.actorType !== "human") {
243
+ throw new HumanReviewRequiredError(
244
+ finding.id,
245
+ `${finding.status} \u2192 ${toStatus}`,
246
+ finding.category,
247
+ finding.severity
248
+ );
249
+ }
250
+ if (toStatus === "closed" && !closedReason) {
251
+ throw new InvalidTransitionError(
252
+ finding.id,
253
+ finding.status,
254
+ toStatus,
255
+ "closedReason is required when closing a finding"
256
+ );
257
+ }
258
+ const updated = {
259
+ ...finding,
260
+ status: toStatus,
261
+ version: finding.version + 1,
262
+ updatedAt: nowISO
263
+ };
264
+ if (toStatus === "closed") {
265
+ updated.closedReason = closedReason;
266
+ updated.closedBy = actor;
267
+ updated.closedAt = nowISO;
268
+ if (fixCommit) updated.fixCommit = fixCommit;
269
+ if (deferredNote) updated.deferredNote = deferredNote;
270
+ }
271
+ return updated;
272
+ }
273
+ function transitionIssue(input) {
274
+ const { issue, toStatus, actor, expectedVersion, resolution, leaseTtlMs } = input;
275
+ const now = input.now ?? /* @__PURE__ */ new Date();
276
+ const nowISO = now.toISOString();
277
+ checkVersion(issue.id, issue.version, expectedVersion);
278
+ const allowed = ISSUE_TRANSITIONS[issue.status];
279
+ if (!allowed.includes(toStatus)) {
280
+ throw new InvalidTransitionError(issue.id, issue.status, toStatus);
281
+ }
282
+ assertClaimTransitionAuthorized(issue, toStatus, actor, now);
283
+ if (requiresHumanActorForIssue(toStatus, issue.category, issue.severity)) {
284
+ if (actor.actorType !== "human") {
285
+ throw new HumanReviewRequiredError(
286
+ issue.id,
287
+ `${issue.status} \u2192 ${toStatus}`,
288
+ issue.category,
289
+ issue.severity
290
+ );
291
+ }
292
+ }
293
+ const updated = {
294
+ ...issue,
295
+ status: toStatus,
296
+ version: issue.version + 1,
297
+ updatedAt: nowISO
298
+ };
299
+ switch (toStatus) {
300
+ case "claimed": {
301
+ if (isEffectivelyClaimed(issue, now) && issue.claimedBy !== actor.actorId) {
302
+ throw new InvalidTransitionError(
303
+ issue.id,
304
+ issue.status,
305
+ toStatus,
306
+ `Already claimed by ${issue.claimedBy}`
307
+ );
308
+ }
309
+ const ttl = getValidLeaseTtlMs(leaseTtlMs, issue.id, issue.status, toStatus);
310
+ updated.claimedBy = actor.actorId;
311
+ updated.claimedAt = nowISO;
312
+ updated.expiresAt = new Date(now.getTime() + ttl).toISOString();
313
+ break;
314
+ }
315
+ case "resolved":
316
+ if (!resolution) {
317
+ throw new InvalidTransitionError(
318
+ issue.id,
319
+ issue.status,
320
+ toStatus,
321
+ "Resolution required when resolving"
322
+ );
323
+ }
324
+ updated.resolution = resolution;
325
+ updated.resolvedBy = actor;
326
+ updated.resolvedAt = nowISO;
327
+ if (input.fixCommit !== void 0) {
328
+ const fixCommit = input.fixCommit.trim();
329
+ if (fixCommit.length === 0) {
330
+ throw new InvalidTransitionError(
331
+ issue.id,
332
+ issue.status,
333
+ toStatus,
334
+ "fixCommit must be a non-empty string when provided"
335
+ );
336
+ }
337
+ updated.fixCommit = fixCommit;
338
+ }
339
+ if (input.fixPr !== void 0) {
340
+ if (!Number.isInteger(input.fixPr) || input.fixPr <= 0) {
341
+ throw new InvalidTransitionError(
342
+ issue.id,
343
+ issue.status,
344
+ toStatus,
345
+ "fixPr must be a positive integer when provided"
346
+ );
347
+ }
348
+ updated.fixPr = input.fixPr;
349
+ }
350
+ updated.claimedBy = void 0;
351
+ updated.claimedAt = void 0;
352
+ updated.expiresAt = void 0;
353
+ break;
354
+ case "open":
355
+ updated.claimedBy = void 0;
356
+ updated.claimedAt = void 0;
357
+ updated.expiresAt = void 0;
358
+ break;
359
+ case "investigating":
360
+ break;
361
+ case "wontfix":
362
+ case "duplicate":
363
+ updated.claimedBy = void 0;
364
+ updated.claimedAt = void 0;
365
+ updated.expiresAt = void 0;
366
+ break;
367
+ }
368
+ return updated;
369
+ }
370
+ function promoteFinding(input) {
371
+ const { finding, issueId, actor, expectedVersion } = input;
372
+ const now = input.now ?? /* @__PURE__ */ new Date();
373
+ const nowISO = now.toISOString();
374
+ const updatedFinding = transitionFinding({
375
+ finding,
376
+ toStatus: "closed",
377
+ actor,
378
+ expectedVersion,
379
+ now,
380
+ closedReason: "promoted"
381
+ });
382
+ const newIssue = {
383
+ id: issueId,
384
+ kind: "issue",
385
+ title: finding.title,
386
+ status: "open",
387
+ version: 1,
388
+ severity: finding.severity ?? "medium",
389
+ category: finding.category,
390
+ findingIds: [finding.id],
391
+ originProvenance: { ...finding.reportedBy },
392
+ relatedIssues: [],
393
+ createdAt: nowISO,
394
+ updatedAt: nowISO
395
+ };
396
+ return { updatedFinding, newIssue };
397
+ }
398
+ function renewLease(input) {
399
+ const { entity, actor, expectedVersion, leaseTtlMs } = input;
400
+ const now = input.now ?? /* @__PURE__ */ new Date();
401
+ checkVersion(entity.id, entity.version, expectedVersion);
402
+ if (entity.claimedBy !== actor.actorId) {
403
+ throw new InvalidTransitionError(
404
+ entity.id,
405
+ entity.status,
406
+ entity.status,
407
+ "Only the claimant can renew the lease"
408
+ );
409
+ }
410
+ if (!isEffectivelyClaimed(entity, now)) {
411
+ throw new LeaseExpiredError(entity.id, entity.expiresAt ?? "unknown");
412
+ }
413
+ const ttl = getValidLeaseTtlMs(leaseTtlMs, entity.id, entity.status, entity.status);
414
+ return {
415
+ ...entity,
416
+ version: entity.version + 1,
417
+ expiresAt: new Date(now.getTime() + ttl).toISOString(),
418
+ updatedAt: now.toISOString()
419
+ };
420
+ }
421
+ function getValidLeaseTtlMs(leaseTtlMs, entityId, fromStatus, toStatus) {
422
+ const ttl = leaseTtlMs ?? DEFAULT_LEASE_TTL_MS;
423
+ if (!Number.isFinite(ttl) || ttl <= 0) {
424
+ throw new InvalidTransitionError(
425
+ entityId,
426
+ fromStatus,
427
+ toStatus,
428
+ "Lease TTL must be a positive finite number"
429
+ );
430
+ }
431
+ return ttl;
432
+ }
433
+ function matchesSuppression(finding, suppressions, now = /* @__PURE__ */ new Date()) {
434
+ for (const s of suppressions) {
435
+ if (s.expiresAt && new Date(s.expiresAt) <= now) continue;
436
+ const ruleMatch = !s.ruleId || s.ruleId === finding.fingerprint.ruleId;
437
+ const pathMatch = !s.pathGlob || matchGlob(s.pathGlob, finding.fingerprint.path);
438
+ if (ruleMatch && pathMatch) return s;
439
+ }
440
+ return null;
441
+ }
442
+ function matchGlob(pattern, filepath) {
443
+ const GLOBSTAR = "\0GLOBSTAR\0";
444
+ const GLOB = "\0GLOB\0";
445
+ const QMARK = "\0QMARK\0";
446
+ const tokenized = pattern.replace(/\*\*/g, GLOBSTAR).replace(/\*/g, GLOB).replace(/\?/g, QMARK);
447
+ const escaped = tokenized.replace(/[-/\\^$+?.()|[\]{}]/g, "\\$&");
448
+ const regexStr = escaped.replaceAll(GLOBSTAR, ".*").replaceAll(GLOB, "[^/]*").replaceAll(QMARK, "[^/]");
449
+ return new RegExp(`^${regexStr}$`).test(filepath);
450
+ }
451
+ function evaluateIngest(finding, suppressions, now = /* @__PURE__ */ new Date()) {
452
+ const matched = matchesSuppression(finding, suppressions, now);
453
+ if (matched) {
454
+ return {
455
+ status: "closed",
456
+ requiresHumanReview: false,
457
+ matchedSuppression: matched,
458
+ closedReason: "dismissed",
459
+ closedBy: {
460
+ actorType: "system",
461
+ actorId: `suppression:${matched.id}`
462
+ },
463
+ closedAt: now.toISOString()
464
+ };
465
+ }
466
+ const needsHuman = finding.category === "security" || finding.severity === "critical";
467
+ return { status: "raw", requiresHumanReview: needsHuman };
468
+ }
469
+
470
+ // src/planning/issue-validation.ts
471
+ var DEFAULT_CONSENSUS_CONFIG = {
472
+ minValidations: 2,
473
+ confirmedThreshold: 0.67,
474
+ rejectedThreshold: 0.67,
475
+ minAverageConfidence: 0.7
476
+ };
477
+ function appendValidation(input) {
478
+ const { finding, validation, expectedVersion } = input;
479
+ if (finding.version !== expectedVersion) {
480
+ throw new StaleVersionError(finding.version, expectedVersion, finding.id);
481
+ }
482
+ const updatedValidations = [...finding.validations, validation];
483
+ const validatorConfidence = updatedValidations.length > 0 ? updatedValidations.reduce((sum, v) => sum + v.confidence, 0) / updatedValidations.length : void 0;
484
+ return {
485
+ ...finding,
486
+ validations: updatedValidations,
487
+ validatorConfidence,
488
+ version: finding.version + 1,
489
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
490
+ };
491
+ }
492
+ function appendObservation(input) {
493
+ const { finding, observation, expectedVersion } = input;
494
+ if (finding.version !== expectedVersion) {
495
+ throw new StaleVersionError(finding.version, expectedVersion, finding.id);
496
+ }
497
+ const observations = getObservations(finding);
498
+ return {
499
+ ...finding,
500
+ observations: [...observations, observation],
501
+ version: finding.version + 1,
502
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
503
+ };
504
+ }
505
+ function getObservations(finding) {
506
+ if (Array.isArray(finding.observations) && finding.observations.length > 0) {
507
+ return finding.observations;
508
+ }
509
+ return [
510
+ createObservation(
511
+ finding.reportedBy,
512
+ finding.reporterConfidence,
513
+ finding.severity,
514
+ finding.codeLocations,
515
+ new Date(finding.reportedAt)
516
+ )
517
+ ];
518
+ }
519
+ function computeAgreement(finding) {
520
+ const identities = new Set(
521
+ getObservations(finding).map((observation) => observationIdentity(observation.reporter))
522
+ );
523
+ return identities.size;
524
+ }
525
+ function computeConsensus(finding, config = DEFAULT_CONSENSUS_CONFIG) {
526
+ const validations = finding.validations;
527
+ const count = validations.length;
528
+ if (count < config.minValidations) {
529
+ return {
530
+ outcome: "insufficient",
531
+ validationCount: count,
532
+ confirmedCount: validations.filter((v) => v.verdict === "confirmed").length,
533
+ rejectedCount: validations.filter((v) => v.verdict === "rejected").length,
534
+ uncertainCount: validations.filter((v) => v.verdict === "uncertain").length,
535
+ averageConfidence: count > 0 ? validations.reduce((s, v) => s + v.confidence, 0) / count : 0,
536
+ autoTriageRecommended: false
537
+ };
538
+ }
539
+ const confirmedCount = validations.filter((v) => v.verdict === "confirmed").length;
540
+ const rejectedCount = validations.filter((v) => v.verdict === "rejected").length;
541
+ const uncertainCount = validations.filter((v) => v.verdict === "uncertain").length;
542
+ const avgConfidence = validations.reduce((s, v) => s + v.confidence, 0) / count;
543
+ const confirmedRatio = confirmedCount / count;
544
+ const rejectedRatio = rejectedCount / count;
545
+ let outcome;
546
+ if (confirmedRatio >= config.confirmedThreshold) {
547
+ outcome = "confirmed";
548
+ } else if (rejectedRatio >= config.rejectedThreshold) {
549
+ outcome = "rejected";
550
+ } else {
551
+ outcome = "uncertain";
552
+ }
553
+ const isGated = finding.category === "security" || finding.severity === "critical";
554
+ const meetsConfidence = avgConfidence >= config.minAverageConfidence;
555
+ const autoTriageRecommended = !isGated && meetsConfidence && outcome !== "uncertain";
556
+ let recommendedStatus;
557
+ if (autoTriageRecommended) {
558
+ recommendedStatus = outcome === "confirmed" ? "triaged" : "rejected";
559
+ }
560
+ return {
561
+ outcome,
562
+ validationCount: count,
563
+ confirmedCount,
564
+ rejectedCount,
565
+ uncertainCount,
566
+ averageConfidence: avgConfidence,
567
+ autoTriageRecommended,
568
+ recommendedStatus
569
+ };
570
+ }
571
+ function createValidation(validator, verdict, confidence, reasoning, now = /* @__PURE__ */ new Date()) {
572
+ if (!Number.isFinite(confidence)) {
573
+ throw new Error(
574
+ `Validation confidence must be a finite number, received: ${String(confidence)}`
575
+ );
576
+ }
577
+ return {
578
+ validator,
579
+ verdict,
580
+ confidence: Math.max(0, Math.min(1, confidence)),
581
+ reasoning,
582
+ validatedAt: now.toISOString()
583
+ };
584
+ }
585
+ function createObservation(reporter, confidence, severity, codeLocations, now = /* @__PURE__ */ new Date()) {
586
+ if (!Number.isFinite(confidence)) {
587
+ throw new Error(
588
+ `Observation confidence must be a finite number, received: ${String(confidence)}`
589
+ );
590
+ }
591
+ return {
592
+ reporter,
593
+ confidence: Math.max(0, Math.min(1, confidence)),
594
+ ...severity ? { severity } : {},
595
+ codeLocations,
596
+ observedAt: Number.isNaN(now.getTime()) ? (/* @__PURE__ */ new Date()).toISOString() : now.toISOString()
597
+ };
598
+ }
599
+ function observationIdentity(reporter) {
600
+ return `${reporter.provider}:${reporter.model}:${reporter.harness}`;
601
+ }
602
+
603
+ // src/planning/issue-manager.ts
604
+ function getCoordBackend(repoRoot) {
605
+ return new LocalFileBackend(path.join(repoRoot, ".build-project", "planning", "coordination"));
606
+ }
607
+ async function withEntityLock(repoRoot, entityId, fn) {
608
+ const backend = getCoordBackend(repoRoot);
609
+ const DELAYS_MS = [0, 100, 200, 400, 800, 1600, 2400, 2500];
610
+ let handle = null;
611
+ for (let attempt = 0; attempt < DELAYS_MS.length; attempt++) {
612
+ const delay = DELAYS_MS[attempt] ?? 0;
613
+ if (delay > 0) {
614
+ await new Promise((resolve) => setTimeout(resolve, delay));
615
+ }
616
+ handle = await backend.acquireLock(entityId);
617
+ if (handle !== null) break;
618
+ }
619
+ if (handle === null) {
620
+ const lockPath = path.join(
621
+ repoRoot,
622
+ ".build-project",
623
+ "planning",
624
+ "coordination",
625
+ "locks",
626
+ `${entityId.replace(/[/\\]/g, "_")}.lock`
627
+ );
628
+ throw new Error(
629
+ `Could not acquire lock for entity ${entityId} after retries. Lock path: ${lockPath}. Another process may be writing to this entity.`
630
+ );
631
+ }
632
+ try {
633
+ return await fn();
634
+ } finally {
635
+ await backend.releaseLock(handle);
636
+ }
637
+ }
638
+ var warnedMalformedFindingFiles = /* @__PURE__ */ new Set();
639
+ var warnedMalformedIssueFiles = /* @__PURE__ */ new Set();
640
+ async function createFinding(repoRoot, options) {
641
+ return withIndexRegeneration(repoRoot, async () => {
642
+ const now = /* @__PURE__ */ new Date();
643
+ const nowISO = now.toISOString();
644
+ const fp = generateFingerprint(options.fingerprint);
645
+ const observation = createObservation(
646
+ options.reportedBy,
647
+ options.reporterConfidence,
648
+ options.severity,
649
+ options.codeLocations,
650
+ now
651
+ );
652
+ const ingest = evaluateIngest(
653
+ { fingerprint: fp, category: options.category, severity: options.severity },
654
+ options.suppressions ?? [],
655
+ now
656
+ );
657
+ const findingMeta = {
658
+ kind: "finding",
659
+ title: options.title,
660
+ status: ingest.status,
661
+ version: 1,
662
+ reportedBy: options.reportedBy,
663
+ reportedAt: nowISO,
664
+ observations: [observation],
665
+ reporterConfidence: options.reporterConfidence,
666
+ severity: options.severity,
667
+ category: options.category,
668
+ fingerprint: fp,
669
+ codeLocations: options.codeLocations,
670
+ validations: [],
671
+ firstSeenAt: nowISO,
672
+ lastSeenAt: nowISO,
673
+ occurrenceCount: 1,
674
+ requiresHumanReview: ingest.requiresHumanReview,
675
+ detectionRunId: options.detectionRunId,
676
+ traceId: options.traceId,
677
+ spanId: options.spanId,
678
+ createdAt: nowISO,
679
+ updatedAt: nowISO,
680
+ closedReason: ingest.closedReason,
681
+ closedBy: ingest.closedBy,
682
+ closedAt: ingest.closedAt
683
+ };
684
+ const result = await createWorkItemFile({
685
+ repoRoot,
686
+ bucket: "finding",
687
+ title: options.title,
688
+ description: options.body?.trim() || "",
689
+ metadata: stripUndefined(findingMeta)
690
+ });
691
+ const finding = { ...findingMeta, id: result.id };
692
+ return {
693
+ id: result.id,
694
+ filePath: result.path,
695
+ finding,
696
+ suppressed: ingest.status === "closed"
697
+ };
698
+ });
699
+ }
700
+ async function readFinding(repoRoot, findingId) {
701
+ const findingDir = getBucketPathByKind("finding", repoRoot);
702
+ const safeFindingId = assertSafePathComponent(findingId, "findingId");
703
+ const filePath = path.join(findingDir, `${safeFindingId}.md`);
704
+ let finding;
705
+ let body;
706
+ try {
707
+ ({ yaml: finding, body } = await parseMarkdownFile(filePath));
708
+ } catch (error) {
709
+ if (error.code === "ENOENT") {
710
+ throw new Error(`Finding not found: ${findingId}`);
711
+ }
712
+ throw error;
713
+ }
714
+ return { finding: normalizeFindingForRead(finding), body, filePath };
715
+ }
716
+ async function updateFinding(repoRoot, findingId, expectedVersion, updates, bodyOverride) {
717
+ return withIndexRegeneration(
718
+ repoRoot,
719
+ () => withEntityLock(repoRoot, findingId, async () => {
720
+ const { finding, body, filePath } = await readFinding(repoRoot, findingId);
721
+ if (finding.version !== expectedVersion) {
722
+ throw new StaleVersionError(finding.version, expectedVersion, findingId);
723
+ }
724
+ const updated = {
725
+ ...finding,
726
+ ...updates,
727
+ version: finding.version + 1,
728
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
729
+ };
730
+ const nextBody = typeof bodyOverride === "string" ? bodyOverride : body;
731
+ await writeMarkdownFile(
732
+ filePath,
733
+ stripUndefined(updated),
734
+ nextBody
735
+ );
736
+ return updated;
737
+ })
738
+ );
739
+ }
740
+ async function transitionFindingStatus(repoRoot, findingId, input) {
741
+ return withIndexRegeneration(
742
+ repoRoot,
743
+ () => withEntityLock(repoRoot, findingId, async () => {
744
+ const { finding, body, filePath } = await readFinding(repoRoot, findingId);
745
+ const updated = transitionFinding({ ...input, finding });
746
+ await writeMarkdownFile(
747
+ filePath,
748
+ stripUndefined(updated),
749
+ body
750
+ );
751
+ return updated;
752
+ })
753
+ );
754
+ }
755
+ async function listFindings(repoRoot, statusFilter, closedReasonFilter) {
756
+ const findingDir = getBucketPathByKind("finding", repoRoot);
757
+ const files = await listMarkdownFiles(findingDir);
758
+ const results = [];
759
+ for (const file of files) {
760
+ try {
761
+ const { yaml: finding } = await parseMarkdownFile(file);
762
+ if (statusFilter && finding.status !== statusFilter) continue;
763
+ if (closedReasonFilter && finding.closedReason !== closedReasonFilter) continue;
764
+ results.push({
765
+ id: finding.id,
766
+ title: finding.title,
767
+ status: finding.status,
768
+ severity: finding.severity,
769
+ category: finding.category,
770
+ version: finding.version,
771
+ closedReason: finding.closedReason
772
+ });
773
+ } catch (error) {
774
+ warnMalformedFile(repoRoot, file, "finding", error, warnedMalformedFindingFiles);
775
+ }
776
+ }
777
+ return results;
778
+ }
779
+ async function readIssue(repoRoot, issueId) {
780
+ const issueDir = getBucketPathByKind("issue", repoRoot);
781
+ const safeIssueId = assertSafePathComponent(issueId, "issueId");
782
+ const filePath = path.join(issueDir, `${safeIssueId}.md`);
783
+ let issue;
784
+ let body;
785
+ try {
786
+ ({ yaml: issue, body } = await parseMarkdownFile(filePath));
787
+ } catch (error) {
788
+ if (error.code === "ENOENT") {
789
+ throw new Error(`Issue not found: ${issueId}`);
790
+ }
791
+ throw error;
792
+ }
793
+ return { issue, body, filePath };
794
+ }
795
+ async function transitionIssueStatus(repoRoot, issueId, input) {
796
+ return withIndexRegeneration(
797
+ repoRoot,
798
+ () => withEntityLock(repoRoot, issueId, async () => {
799
+ const { issue, body, filePath } = await readIssue(repoRoot, issueId);
800
+ const updated = transitionIssue({ ...input, issue });
801
+ await writeMarkdownFile(
802
+ filePath,
803
+ stripUndefined(updated),
804
+ body
805
+ );
806
+ return updated;
807
+ })
808
+ );
809
+ }
810
+ async function listIssues(repoRoot, statusFilter) {
811
+ const issueDir = getBucketPathByKind("issue", repoRoot);
812
+ const files = await listMarkdownFiles(issueDir);
813
+ const results = [];
814
+ for (const file of files) {
815
+ try {
816
+ const { yaml: issue } = await parseMarkdownFile(file);
817
+ if (statusFilter && issue.status !== statusFilter) continue;
818
+ results.push({
819
+ id: issue.id,
820
+ title: issue.title,
821
+ status: issue.status,
822
+ severity: issue.severity,
823
+ category: issue.category,
824
+ version: issue.version,
825
+ claimed: isEffectivelyClaimed(issue),
826
+ findingIds: issue.findingIds ?? []
827
+ });
828
+ } catch (error) {
829
+ warnMalformedFile(repoRoot, file, "issue", error, warnedMalformedIssueFiles);
830
+ }
831
+ }
832
+ return results;
833
+ }
834
+ var FindingPublishConsentError = class extends Error {
835
+ constructor(findingId) {
836
+ super(
837
+ `Refusing to promote finding ${findingId}: promotion creates a TRACKED issue whose body is copied verbatim from this local-only finding (file paths, code snippets, scanner detail) and is then committed and pushed. Re-run with explicit publish consent (--yes-publish-issue) to cross the local\u2192published boundary.`
838
+ );
839
+ this.name = "FindingPublishConsentError";
840
+ }
841
+ };
842
+ async function promoteFindingToIssue(repoRoot, findingId, actor, options = {}) {
843
+ if (!options.publishIssue) {
844
+ throw new FindingPublishConsentError(findingId);
845
+ }
846
+ return withIndexRegeneration(
847
+ repoRoot,
848
+ () => withEntityLock(repoRoot, findingId, async () => {
849
+ const { finding, body, filePath } = await readFinding(repoRoot, findingId);
850
+ const now = /* @__PURE__ */ new Date();
851
+ const issueId = generateId(now);
852
+ const { updatedFinding, newIssue } = promoteFinding({
853
+ finding,
854
+ issueId,
855
+ actor,
856
+ expectedVersion: finding.version,
857
+ now
858
+ });
859
+ await writeMarkdownFile(
860
+ filePath,
861
+ stripUndefined(updatedFinding),
862
+ body
863
+ );
864
+ const issueDir = getBucketPathByKind("issue", repoRoot);
865
+ const issueFilePath = path.join(issueDir, `${issueId}.md`);
866
+ await writeMarkdownFile(
867
+ issueFilePath,
868
+ stripUndefined(newIssue),
869
+ body
870
+ );
871
+ return { finding: updatedFinding, issue: newIssue, issueFilePath };
872
+ })
873
+ );
874
+ }
875
+ async function renewEntityLease(repoRoot, entityId, actor, expectedVersion, leaseTtlMs) {
876
+ return withIndexRegeneration(
877
+ repoRoot,
878
+ () => withEntityLock(repoRoot, entityId, async () => {
879
+ const { issue, body, filePath } = await readIssue(repoRoot, entityId);
880
+ const updated = renewLease({
881
+ entity: issue,
882
+ actor,
883
+ expectedVersion,
884
+ leaseTtlMs
885
+ });
886
+ await writeMarkdownFile(
887
+ filePath,
888
+ stripUndefined(updated),
889
+ body
890
+ );
891
+ })
892
+ );
893
+ }
894
+ async function validateFinding(repoRoot, findingId, input, consensusConfig) {
895
+ return withIndexRegeneration(
896
+ repoRoot,
897
+ () => withEntityLock(repoRoot, findingId, async () => {
898
+ const { finding, body, filePath } = await readFinding(repoRoot, findingId);
899
+ const validation = createValidation(
900
+ input.validator,
901
+ input.verdict,
902
+ input.confidence,
903
+ input.reasoning
904
+ );
905
+ const updated = appendValidation({
906
+ finding,
907
+ validation,
908
+ expectedVersion: input.expectedVersion
909
+ });
910
+ await writeMarkdownFile(
911
+ filePath,
912
+ stripUndefined(updated),
913
+ body
914
+ );
915
+ const consensus = computeConsensus(updated, consensusConfig);
916
+ return { finding: updated, consensus };
917
+ })
918
+ );
919
+ }
920
+ async function getConsensus(repoRoot, findingId, consensusConfig) {
921
+ const { finding } = await readFinding(repoRoot, findingId);
922
+ return computeConsensus(finding, consensusConfig);
923
+ }
924
+ async function spawnTaskFromIssue(repoRoot, issueId, sprintId, actor, expectedVersion, taskOptions = {}) {
925
+ const { createTask } = await import("./task-manager-LHPBBRRE.js");
926
+ return withIndexRegeneration(
927
+ repoRoot,
928
+ () => withEntityLock(repoRoot, issueId, async () => {
929
+ const { issue, body, filePath } = await readIssue(repoRoot, issueId);
930
+ const now = /* @__PURE__ */ new Date();
931
+ if (issue.spawnedTask) {
932
+ throw new Error(`Issue ${issueId} already has spawned task: ${issue.spawnedTask}`);
933
+ }
934
+ if (issue.status !== "open" && issue.status !== "claimed") {
935
+ throw new Error(
936
+ `Cannot spawn task from issue in '${issue.status}' status (must be open or claimed)`
937
+ );
938
+ }
939
+ if (issue.status === "claimed") {
940
+ if (issue.claimedBy !== actor.actorId) {
941
+ throw new Error(
942
+ `Cannot spawn task from claimed issue ${issueId}: only claimant ${issue.claimedBy} can spawn`
943
+ );
944
+ }
945
+ if (!isEffectivelyClaimed(issue, now)) {
946
+ const expiredAt = issue.expiresAt ?? "unknown";
947
+ throw new Error(
948
+ `Cannot spawn task from claimed issue ${issueId}: lease expired at ${expiredAt}`
949
+ );
950
+ }
951
+ }
952
+ if (issue.version !== expectedVersion) {
953
+ throw new StaleVersionError(issue.version, expectedVersion, issueId);
954
+ }
955
+ const task = await createTask(
956
+ `[Issue] ${issue.title}`,
957
+ sprintId,
958
+ {
959
+ priority: taskOptions.priority,
960
+ assignee: taskOptions.assignee,
961
+ description: taskOptions.description || `Spawned from issue ${issueId} (${issue.category}/${issue.severity})`
962
+ },
963
+ repoRoot
964
+ );
965
+ const updated = {
966
+ ...issue,
967
+ spawnedTask: task.id,
968
+ spawnedTaskBy: actor,
969
+ spawnedTaskAt: now.toISOString(),
970
+ version: issue.version + 1,
971
+ updatedAt: now.toISOString()
972
+ };
973
+ await writeMarkdownFile(
974
+ filePath,
975
+ stripUndefined(updated),
976
+ body
977
+ );
978
+ return {
979
+ taskId: task.id,
980
+ issueId: issue.id,
981
+ issueVersion: updated.version
982
+ };
983
+ })
984
+ );
985
+ }
986
+ async function auditMalformedIssueFiles(repoRoot) {
987
+ const results = [];
988
+ const buckets = [
989
+ { kind: "finding", dir: getBucketPathByKind("finding", repoRoot) },
990
+ { kind: "issue", dir: getBucketPathByKind("issue", repoRoot) }
991
+ ];
992
+ for (const bucket of buckets) {
993
+ const files = await listMarkdownFiles(bucket.dir);
994
+ for (const file of files) {
995
+ try {
996
+ await parseMarkdownFile(file);
997
+ } catch (error) {
998
+ results.push({
999
+ bucket: bucket.kind,
1000
+ filePath: path.relative(repoRoot, file),
1001
+ error: error instanceof Error ? error.message : String(error)
1002
+ });
1003
+ }
1004
+ }
1005
+ }
1006
+ return results;
1007
+ }
1008
+ function stripUndefined(obj) {
1009
+ const result = {};
1010
+ for (const [key, value] of Object.entries(obj)) {
1011
+ if (value !== void 0) {
1012
+ result[key] = value;
1013
+ }
1014
+ }
1015
+ return result;
1016
+ }
1017
+ function normalizeFindingForRead(finding) {
1018
+ if (Array.isArray(finding.observations) && finding.observations.length > 0) {
1019
+ return finding;
1020
+ }
1021
+ return {
1022
+ ...finding,
1023
+ observations: getObservations(finding)
1024
+ };
1025
+ }
1026
+ function warnMalformedFile(repoRoot, filePath, bucket, error, warnedSet) {
1027
+ const relativePath = path.relative(repoRoot, filePath);
1028
+ if (warnedSet.has(relativePath)) return;
1029
+ warnedSet.add(relativePath);
1030
+ emitWarning(
1031
+ "CFG-002",
1032
+ {
1033
+ taskId: "issue-manager",
1034
+ subsystem: "planning",
1035
+ executionPhase: "execution"
1036
+ },
1037
+ {
1038
+ severity: "WARN" /* WARN */,
1039
+ metadata: {
1040
+ operation: "parse-planning-item",
1041
+ bucket,
1042
+ file: relativePath,
1043
+ error: error instanceof Error ? error.message : String(error)
1044
+ }
1045
+ }
1046
+ );
1047
+ }
1048
+
1049
+ // src/planning/issue-policy.ts
1050
+ import * as fs from "fs";
1051
+ import * as path2 from "path";
1052
+ import yaml from "js-yaml";
1053
+ var DEFAULT_ISSUE_POLICY = {
1054
+ consensus: {
1055
+ minValidations: 2,
1056
+ confirmedThreshold: 0.67,
1057
+ rejectedThreshold: 0.67,
1058
+ minAverageConfidence: 0.7
1059
+ },
1060
+ autoPromote: {
1061
+ enabled: true,
1062
+ minPromotionConfidence: 0.8,
1063
+ maxPromotesPerRun: 50,
1064
+ gatedCategories: ["security"],
1065
+ gatedSeverities: ["critical"]
1066
+ },
1067
+ ingest: {
1068
+ maxFindingsPerBatch: 500,
1069
+ maxOccurrencesBeforeReview: 10
1070
+ },
1071
+ severityPriority: {
1072
+ critical: "P0",
1073
+ high: "P1",
1074
+ medium: "P2",
1075
+ low: "P3"
1076
+ },
1077
+ scannerWeights: {}
1078
+ };
1079
+ function loadIssuePolicy(repoRoot = process.cwd()) {
1080
+ const configPath = path2.join(repoRoot, ".build-project", "config", "issue-policy.yaml");
1081
+ if (!fs.existsSync(configPath)) {
1082
+ return { ...DEFAULT_ISSUE_POLICY };
1083
+ }
1084
+ try {
1085
+ const raw = fs.readFileSync(configPath, "utf8");
1086
+ const parsed = yaml.load(raw);
1087
+ if (!parsed || typeof parsed !== "object") {
1088
+ return { ...DEFAULT_ISSUE_POLICY };
1089
+ }
1090
+ return mergePolicy(DEFAULT_ISSUE_POLICY, parsed);
1091
+ } catch {
1092
+ return { ...DEFAULT_ISSUE_POLICY };
1093
+ }
1094
+ }
1095
+ function mergePolicy(defaults, overrides) {
1096
+ return {
1097
+ consensus: {
1098
+ ...defaults.consensus,
1099
+ ...overrides.consensus ?? {}
1100
+ },
1101
+ autoPromote: {
1102
+ ...defaults.autoPromote,
1103
+ ...overrides.autoPromote ?? {}
1104
+ },
1105
+ ingest: {
1106
+ ...defaults.ingest,
1107
+ ...overrides.ingest ?? {}
1108
+ },
1109
+ severityPriority: {
1110
+ ...defaults.severityPriority,
1111
+ ...overrides.severityPriority ?? {}
1112
+ },
1113
+ scannerWeights: {
1114
+ ...defaults.scannerWeights,
1115
+ ...overrides.scannerWeights ?? {}
1116
+ }
1117
+ };
1118
+ }
1119
+ function isCategoryGated(category, policy = DEFAULT_ISSUE_POLICY) {
1120
+ return policy.autoPromote.gatedCategories.includes(category);
1121
+ }
1122
+ function isSeverityGated(severity, policy = DEFAULT_ISSUE_POLICY) {
1123
+ if (!severity) return false;
1124
+ return policy.autoPromote.gatedSeverities.includes(severity);
1125
+ }
1126
+ function severityToPriority(severity, policy = DEFAULT_ISSUE_POLICY) {
1127
+ if (!severity) return null;
1128
+ return policy.severityPriority[severity] ?? null;
1129
+ }
1130
+ function applyWeight(confidence, provider, policy = DEFAULT_ISSUE_POLICY) {
1131
+ if (!Number.isFinite(confidence)) {
1132
+ throw new Error(`Confidence must be a finite number, received: ${String(confidence)}`);
1133
+ }
1134
+ const rawWeight = policy.scannerWeights[provider];
1135
+ const weight = Number.isFinite(rawWeight) && rawWeight >= 0 ? rawWeight : 1;
1136
+ return Math.max(0, Math.min(1, confidence * weight));
1137
+ }
1138
+ function exceedsBatchBudget(candidateCount, policy = DEFAULT_ISSUE_POLICY) {
1139
+ return candidateCount > policy.ingest.maxFindingsPerBatch;
1140
+ }
1141
+
1142
+ // src/planning/tech-debt-manager.ts
1143
+ import * as fsSync from "fs";
1144
+ import * as fs2 from "fs/promises";
1145
+ import * as path3 from "path";
1146
+ import * as yaml2 from "js-yaml";
1147
+ var severityImpactDefaults = {
1148
+ critical: 9,
1149
+ high: 7,
1150
+ medium: 5,
1151
+ low: 3
1152
+ };
1153
+ var EFFORT_TO_HOURS = {
1154
+ low: 2,
1155
+ medium: 6,
1156
+ high: 12
1157
+ };
1158
+ var EFFORT_TO_AI_BASE_MINUTES = {
1159
+ low: 5,
1160
+ medium: 20,
1161
+ high: 90
1162
+ };
1163
+ var EFFORT_TO_COMPLEXITY = {
1164
+ low: 0.3,
1165
+ medium: 0.5,
1166
+ high: 0.7
1167
+ };
1168
+ function effortToNominalHours(effort) {
1169
+ return EFFORT_TO_HOURS[effort];
1170
+ }
1171
+ function effortToNominalComplexity(effort) {
1172
+ return EFFORT_TO_COMPLEXITY[effort];
1173
+ }
1174
+ function resolveDebtRuntimeEstimate(effort, explicitMinutes) {
1175
+ if (typeof explicitMinutes === "number" && Number.isFinite(explicitMinutes)) {
1176
+ if (explicitMinutes <= 0) return {};
1177
+ return {
1178
+ // Clamp to [1, 1440]: sub-minute values persist as a valid minute rather
1179
+ // than rounding to 0, and programmatic callers (createDebtItemAsync /
1180
+ // updateDebtItemAsync are exported) cannot persist values above the
1181
+ // shared ExpectedRuntimeMinutesSchema ceiling that the CLI enforces.
1182
+ expectedRuntimeMinutes: Math.min(1440, Math.max(1, Math.round(explicitMinutes))),
1183
+ runtimeEstimateProvenance: "explicit",
1184
+ runtimeEstimateConfidence: "medium"
1185
+ };
1186
+ }
1187
+ const estimate = estimateRuntime({
1188
+ baseExpectedRuntimeMs: EFFORT_TO_AI_BASE_MINUTES[effort] * 6e4
1189
+ });
1190
+ return {
1191
+ expectedRuntimeMinutes: Math.round(estimate.expectedRuntimeMs / 6e4),
1192
+ runtimeEstimateProvenance: estimate.provenance,
1193
+ runtimeEstimateConfidence: estimate.confidence
1194
+ };
1195
+ }
1196
+ function coerceDebtRuntimeEstimate(raw) {
1197
+ const result = {};
1198
+ const rawMinutes = raw.expectedRuntimeMinutes;
1199
+ const minutes = typeof rawMinutes === "number" ? rawMinutes : typeof rawMinutes === "string" && rawMinutes.trim() !== "" ? Number(rawMinutes) : void 0;
1200
+ if (typeof minutes === "number" && Number.isFinite(minutes) && minutes > 0) {
1201
+ result.expectedRuntimeMinutes = minutes;
1202
+ }
1203
+ const provenance = raw.runtimeEstimateProvenance;
1204
+ if (provenance === "heuristic" || provenance === "telemetry" || provenance === "blended" || provenance === "explicit") {
1205
+ result.runtimeEstimateProvenance = provenance;
1206
+ }
1207
+ const confidence = raw.runtimeEstimateConfidence;
1208
+ if (confidence === "low" || confidence === "medium" || confidence === "high") {
1209
+ result.runtimeEstimateConfidence = confidence;
1210
+ }
1211
+ return result;
1212
+ }
1213
+ var legacyImpactLabels = {
1214
+ critical: severityImpactDefaults.critical,
1215
+ high: severityImpactDefaults.high,
1216
+ medium: severityImpactDefaults.medium,
1217
+ low: severityImpactDefaults.low
1218
+ };
1219
+ function defaultImpactForSeverity(severity) {
1220
+ return severityImpactDefaults[severity ?? "medium"];
1221
+ }
1222
+ function coerceImpact(value, severity) {
1223
+ let parsed;
1224
+ if (typeof value === "number" && Number.isFinite(value)) {
1225
+ parsed = value;
1226
+ } else if (typeof value === "string") {
1227
+ const trimmed = value.trim().toLowerCase();
1228
+ const numericMatch = trimmed.match(/^(\d+(?:\.\d+)?)(?:\s*\/\s*10)?$/);
1229
+ if (numericMatch) {
1230
+ parsed = Number(numericMatch[1]);
1231
+ } else if (trimmed in legacyImpactLabels) {
1232
+ parsed = legacyImpactLabels[trimmed];
1233
+ }
1234
+ }
1235
+ const impact = parsed ?? defaultImpactForSeverity(severity);
1236
+ return Math.min(10, Math.max(1, Math.round(impact)));
1237
+ }
1238
+ function normalizeDebtItem(raw) {
1239
+ const severity = raw.severity ?? "medium";
1240
+ const effort = raw.effort ?? "medium";
1241
+ const normalized = {
1242
+ id: raw.id ?? "",
1243
+ kind: "tech-debt",
1244
+ title: raw.title ?? raw.id ?? "Untitled tech debt",
1245
+ domain: raw.domain ?? "architecture",
1246
+ severity,
1247
+ effort,
1248
+ impact: coerceImpact(raw.impact, severity),
1249
+ status: raw.status ?? "pending",
1250
+ estimatedComplexity: raw.estimatedComplexity ?? effortToNominalComplexity(effort),
1251
+ estimatedHours: raw.estimatedHours ?? effortToNominalHours(effort),
1252
+ // AI-era estimate: read-through only — legacy items round-trip byte-clean
1253
+ // with no fabricated AI fields (matches task-manager's honesty pattern).
1254
+ ...coerceDebtRuntimeEstimate(raw),
1255
+ rootCause: raw.rootCause ?? "To be documented",
1256
+ blocking: raw.blocking ?? severity === "critical",
1257
+ parallelizable: raw.parallelizable ?? severity !== "critical",
1258
+ executeBy: raw.executeBy,
1259
+ createdAt: raw.createdAt,
1260
+ updatedAt: raw.updatedAt,
1261
+ createdDate: raw.createdDate,
1262
+ targetCompleteDate: raw.targetCompleteDate,
1263
+ completedAt: raw.completedAt,
1264
+ archivedAt: raw.archivedAt
1265
+ };
1266
+ if (!normalized.createdAt && normalized.createdDate) {
1267
+ normalized.createdAt = `${normalized.createdDate}T00:00:00.000Z`;
1268
+ }
1269
+ return normalized;
1270
+ }
1271
+ function parseMarkdownContent(content, filePath) {
1272
+ content = normalizeMarkdownContent(content);
1273
+ const match = content.match(/^---\n([\s\S]+?)\n---\n([\s\S]*)$/);
1274
+ if (!match) {
1275
+ throw new Error(`Invalid markdown format in ${filePath}: missing YAML front matter`);
1276
+ }
1277
+ const rawMetadata = yaml2.load(match[1] ?? "", { schema: yaml2.JSON_SCHEMA });
1278
+ const body = (match[2] ?? "").trim();
1279
+ return { metadata: normalizeDebtItem(rawMetadata), body, raw: rawMetadata };
1280
+ }
1281
+ function patchedFrontmatter(raw, before, after) {
1282
+ const patched = { ...raw };
1283
+ for (const [key, value] of Object.entries(after)) {
1284
+ if (value !== before[key]) patched[key] = value;
1285
+ }
1286
+ for (const key of Object.keys(before)) {
1287
+ if (!(key in after)) delete patched[key];
1288
+ }
1289
+ return patched;
1290
+ }
1291
+ function buildDebtItem(title, severity, effort, options = {}) {
1292
+ const id = generateId(/* @__PURE__ */ new Date());
1293
+ const debtItem = {
1294
+ id,
1295
+ kind: "tech-debt",
1296
+ title,
1297
+ domain: options.domain || "architecture",
1298
+ severity,
1299
+ effort,
1300
+ impact: coerceImpact(options.impact, severity),
1301
+ status: "pending",
1302
+ // Advisory nominal derived from the explicit effort level (see EFFORT_TO_HOURS).
1303
+ estimatedComplexity: options.estimatedComplexity ?? effortToNominalComplexity(effort),
1304
+ estimatedHours: options.estimatedHours ?? effortToNominalHours(effort),
1305
+ // AI-era primary estimate (advisory, [B5]): explicit minutes win, else
1306
+ // effort-derived via the canonical estimator.
1307
+ ...resolveDebtRuntimeEstimate(effort, options.expectedRuntimeMinutes),
1308
+ rootCause: options.rootCause || "To be documented",
1309
+ blocking: options.blocking !== void 0 ? options.blocking : severity === "critical",
1310
+ parallelizable: options.parallelizable !== void 0 ? options.parallelizable : severity !== "critical",
1311
+ executeBy: options.executeBy,
1312
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1313
+ targetCompleteDate: options.targetCompleteDate
1314
+ };
1315
+ const body = `# ${title}
1316
+
1317
+ ## Problem
1318
+
1319
+ ${options.rootCause || "To be documented"}
1320
+
1321
+ ## Impact
1322
+
1323
+ - Severity: ${severity}
1324
+ - Estimated effort: ${effort}${debtItem.expectedRuntimeMinutes ? ` (~${debtItem.expectedRuntimeMinutes}m AI est)` : ` (${debtItem.estimatedHours}h)`}
1325
+ - Impact score: ${debtItem.impact}/10
1326
+ - Blocks production: ${debtItem.blocking ? "Yes" : "No"}
1327
+ - Can run in parallel: ${debtItem.parallelizable ? "Yes" : "No"}
1328
+
1329
+ ## Scheduling Recommendation
1330
+
1331
+ ${getSchedulingRecommendation(debtItem)}
1332
+
1333
+ ## Solution
1334
+
1335
+ To be documented when assigned.
1336
+
1337
+ ## Success Criteria
1338
+
1339
+ - [ ] Root cause addressed
1340
+ - [ ] Tests passing
1341
+ - [ ] Documentation updated
1342
+ - [ ] No regressions introduced
1343
+ `;
1344
+ return { debtItem, body };
1345
+ }
1346
+ function regenerateIndexesAfterCreate(basePath) {
1347
+ generateIndexes(basePath).catch((error) => {
1348
+ if (error?.code === "ENOENT") return;
1349
+ emitWarning(
1350
+ "CFG-002",
1351
+ {
1352
+ taskId: "tech-debt-manager",
1353
+ subsystem: "planning",
1354
+ executionPhase: "cleanup"
1355
+ },
1356
+ {
1357
+ severity: "INFO" /* INFO */,
1358
+ metadata: {
1359
+ error: error instanceof Error ? error.message : String(error),
1360
+ operation: "regenerate-indexes-after-create"
1361
+ }
1362
+ }
1363
+ );
1364
+ });
1365
+ }
1366
+ async function parseMarkdownFile2(filePath) {
1367
+ const content = await fs2.readFile(filePath, "utf8");
1368
+ return parseMarkdownContent(content, filePath);
1369
+ }
1370
+ async function getDebtItemAsync(itemId) {
1371
+ const basePath = getPlanningRoot();
1372
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1373
+ const filePath = path3.join(currentPath, `${itemId}.md`);
1374
+ try {
1375
+ await fs2.access(filePath);
1376
+ } catch {
1377
+ return null;
1378
+ }
1379
+ return parseMarkdownFile2(filePath);
1380
+ }
1381
+ async function writeMarkdownFile2(filePath, metadata, body) {
1382
+ const yamlStr = yaml2.dump(metadata, { lineWidth: -1 });
1383
+ const content = `---
1384
+ ${yamlStr}---
1385
+
1386
+ ${body}`;
1387
+ const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
1388
+ const handle = await fs2.open(tempPath, "w");
1389
+ try {
1390
+ await handle.writeFile(content, "utf8");
1391
+ await handle.sync();
1392
+ await handle.close();
1393
+ await fs2.rename(tempPath, filePath);
1394
+ } catch (error) {
1395
+ try {
1396
+ await handle.close();
1397
+ } catch {
1398
+ }
1399
+ try {
1400
+ await fs2.unlink(tempPath);
1401
+ } catch {
1402
+ }
1403
+ throw error;
1404
+ }
1405
+ }
1406
+ async function createDebtItemAsync(title, severity, effort, options = {}) {
1407
+ const basePath = getPlanningRoot();
1408
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1409
+ assertBucketWriteAvailable(basePath);
1410
+ await fs2.mkdir(currentPath, { recursive: true });
1411
+ const { debtItem, body } = buildDebtItem(title, severity, effort, options);
1412
+ const filePath = path3.join(currentPath, `${debtItem.id}.md`);
1413
+ await writeMarkdownFile2(filePath, debtItem, body);
1414
+ regenerateIndexesAfterCreate(basePath);
1415
+ return debtItem;
1416
+ }
1417
+ async function updateDebtItemAsync(itemId, fields) {
1418
+ const basePath = getPlanningRoot();
1419
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1420
+ const filePath = path3.join(currentPath, `${itemId}.md`);
1421
+ return withIndexRegeneration(basePath, async () => {
1422
+ const loaded = await getDebtItemAsync(itemId);
1423
+ if (!loaded) throw new Error(`Debt item not found: ${itemId}`);
1424
+ const { metadata: existing, body: existingBody } = loaded;
1425
+ const { yaml: rawFrontmatter } = await parseMarkdownFile(filePath);
1426
+ const rawUpdated = { ...rawFrontmatter };
1427
+ let changed = false;
1428
+ const applyScalar = (key, value) => {
1429
+ if (value === void 0) return;
1430
+ if (rawUpdated[key] !== value) {
1431
+ rawUpdated[key] = value;
1432
+ changed = true;
1433
+ }
1434
+ };
1435
+ applyScalar("title", fields.title);
1436
+ applyScalar("severity", fields.severity);
1437
+ applyScalar("effort", fields.effort);
1438
+ applyScalar("impact", fields.impact);
1439
+ applyScalar("blocking", fields.blocking);
1440
+ applyScalar("parallelizable", fields.parallelizable);
1441
+ applyScalar("domain", fields.domain);
1442
+ applyScalar("rootCause", fields.rootCause);
1443
+ applyScalar("executeBy", fields.executeBy);
1444
+ applyScalar("targetCompleteDate", fields.targetCompleteDate);
1445
+ applyScalar("estimatedHours", fields.estimatedHours);
1446
+ applyScalar("estimatedComplexity", fields.estimatedComplexity);
1447
+ if (fields.expectedRuntimeMinutes !== void 0) {
1448
+ const explicit = resolveDebtRuntimeEstimate(
1449
+ rawUpdated.effort ?? "medium",
1450
+ fields.expectedRuntimeMinutes
1451
+ );
1452
+ applyScalar("expectedRuntimeMinutes", explicit.expectedRuntimeMinutes);
1453
+ applyScalar("runtimeEstimateProvenance", explicit.runtimeEstimateProvenance);
1454
+ applyScalar("runtimeEstimateConfidence", explicit.runtimeEstimateConfidence);
1455
+ } else if (fields.effort !== void 0 && rawUpdated.runtimeEstimateProvenance !== "explicit" && rawUpdated.runtimeEstimateProvenance !== "telemetry" && rawUpdated.expectedRuntimeMinutes !== void 0) {
1456
+ const rederived = resolveDebtRuntimeEstimate(fields.effort);
1457
+ applyScalar("expectedRuntimeMinutes", rederived.expectedRuntimeMinutes);
1458
+ applyScalar("runtimeEstimateProvenance", rederived.runtimeEstimateProvenance);
1459
+ applyScalar("runtimeEstimateConfidence", rederived.runtimeEstimateConfidence);
1460
+ }
1461
+ if (typeof rawUpdated.expectedRuntimeMinutes === "string") {
1462
+ const repaired = Number(rawUpdated.expectedRuntimeMinutes);
1463
+ if (Number.isFinite(repaired)) {
1464
+ rawUpdated.expectedRuntimeMinutes = repaired;
1465
+ changed = true;
1466
+ }
1467
+ }
1468
+ let nextBody = existingBody;
1469
+ if (fields.body !== void 0 && fields.body !== existingBody) {
1470
+ nextBody = keepActivity(`Tech-debt item ${itemId}`, existingBody, fields.body);
1471
+ changed = true;
1472
+ }
1473
+ if (!changed) {
1474
+ return { item: existing, filePath, changed: false };
1475
+ }
1476
+ rawUpdated.id = itemId;
1477
+ rawUpdated.kind = "tech-debt";
1478
+ rawUpdated.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1479
+ const validation = validateDebtItem(rawUpdated);
1480
+ if (!validation.valid) {
1481
+ const detail = validation.errors.map((error) => `${error.field}: ${error.message}`).join("; ");
1482
+ throw new Error(`Invalid debt item after update (${itemId}): ${detail}`);
1483
+ }
1484
+ await writeMarkdownFile2(filePath, rawUpdated, nextBody);
1485
+ const { metadata: normalizedUpdated } = parseMarkdownContent(
1486
+ `---
1487
+ ${yaml2.dump(rawUpdated, { lineWidth: -1 })}---
1488
+ ${nextBody}`,
1489
+ filePath
1490
+ );
1491
+ return { item: normalizedUpdated, filePath, changed: true };
1492
+ });
1493
+ }
1494
+ function getSchedulingRecommendation(item) {
1495
+ if (item.severity === "critical" && item.blocking) {
1496
+ return "Execute immediately - halt sprint if necessary";
1497
+ }
1498
+ if (item.severity === "critical" && !item.blocking) {
1499
+ return "Execute in parallel with current sprint";
1500
+ }
1501
+ if (item.severity === "high" && item.blocking) {
1502
+ return "Add to current sprint - adjust capacity";
1503
+ }
1504
+ if (item.severity === "high" && !item.blocking) {
1505
+ return "Schedule for next sprint";
1506
+ }
1507
+ if (item.severity === "medium") {
1508
+ return "Opportunistic execution when capacity available";
1509
+ }
1510
+ return "Backlog for future sprints";
1511
+ }
1512
+ async function listByBlockingAsync() {
1513
+ const basePath = getPlanningRoot();
1514
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1515
+ const files = await listMarkdownFileNames(currentPath);
1516
+ const debtItems = [];
1517
+ for (const file of files) {
1518
+ const filePath = path3.join(currentPath, file);
1519
+ try {
1520
+ const { metadata } = await parseMarkdownFile2(filePath);
1521
+ if (metadata.blocking) {
1522
+ debtItems.push(metadata);
1523
+ }
1524
+ } catch (error) {
1525
+ warnDebtReadError(error, file, "list-blocking-debt");
1526
+ }
1527
+ }
1528
+ return sortBySeverityThenImpact(debtItems);
1529
+ }
1530
+ async function listByParallelizableAsync() {
1531
+ const basePath = getPlanningRoot();
1532
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1533
+ const files = await listMarkdownFileNames(currentPath);
1534
+ const debtItems = [];
1535
+ for (const file of files) {
1536
+ const filePath = path3.join(currentPath, file);
1537
+ try {
1538
+ const { metadata } = await parseMarkdownFile2(filePath);
1539
+ if (metadata.parallelizable) {
1540
+ debtItems.push(metadata);
1541
+ }
1542
+ } catch (error) {
1543
+ warnDebtReadError(error, file, "list-parallelizable-debt");
1544
+ }
1545
+ }
1546
+ return sortBySeverityThenHours(debtItems);
1547
+ }
1548
+ async function scheduleDebtAsync(itemId, when) {
1549
+ const basePath = getPlanningRoot();
1550
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1551
+ const filePath = path3.join(currentPath, `${itemId}.md`);
1552
+ try {
1553
+ await fs2.access(filePath);
1554
+ } catch {
1555
+ throw new Error(`Debt item not found: ${itemId}`);
1556
+ }
1557
+ return withIndexRegeneration(basePath, async () => {
1558
+ const { metadata, body, raw } = await parseMarkdownFile2(filePath);
1559
+ const before = { ...metadata };
1560
+ applyDebtSchedule(metadata, when);
1561
+ await writeMarkdownFile2(filePath, patchedFrontmatter(raw, before, metadata), body);
1562
+ return metadata;
1563
+ });
1564
+ }
1565
+ async function completeDebtAsync(itemId) {
1566
+ const basePath = getPlanningRoot();
1567
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1568
+ const bucket = getBucketByName("tech-debt", basePath);
1569
+ if (!bucket) {
1570
+ throw new Error("Bucket not configured: tech-debt");
1571
+ }
1572
+ const currentFile = path3.join(currentPath, `${itemId}.md`);
1573
+ try {
1574
+ await fs2.access(currentFile);
1575
+ } catch {
1576
+ throw new Error(`Debt item not found: ${itemId}`);
1577
+ }
1578
+ return withIndexRegeneration(basePath, async () => {
1579
+ const { metadata, body, raw } = await parseMarkdownFile2(currentFile);
1580
+ const before = { ...metadata };
1581
+ markDebtComplete(metadata);
1582
+ const archivedAt = metadata.archivedAt;
1583
+ const archivedFile = getArchivedFilePath(bucket, itemId, archivedAt, basePath);
1584
+ await fs2.mkdir(path3.dirname(archivedFile), { recursive: true });
1585
+ await writeMarkdownFile2(archivedFile, patchedFrontmatter(raw, before, metadata), body);
1586
+ await fs2.unlink(currentFile);
1587
+ return metadata;
1588
+ });
1589
+ }
1590
+ async function listAllDebtAsync(includeArchived = false, rootDir) {
1591
+ const basePath = rootDir ?? getPlanningRoot();
1592
+ const currentPath = getBucketPathByKind("tech-debt", basePath);
1593
+ const archivedPath = getBucketArchivePathByKind("tech-debt", basePath);
1594
+ const items = [];
1595
+ for (const file of await listMarkdownFileNames(currentPath)) {
1596
+ try {
1597
+ const { metadata } = await parseMarkdownFile2(path3.join(currentPath, file));
1598
+ items.push(metadata);
1599
+ } catch (error) {
1600
+ warnDebtReadError(error, file, "list-all-debt-current");
1601
+ }
1602
+ }
1603
+ if (includeArchived) {
1604
+ const files = await listMarkdownFilesRecursive2(archivedPath);
1605
+ for (const file of files) {
1606
+ if (path3.basename(file).toLowerCase() === "readme.md") {
1607
+ continue;
1608
+ }
1609
+ try {
1610
+ const { metadata } = await parseMarkdownFile2(file);
1611
+ items.push(metadata);
1612
+ } catch (error) {
1613
+ warnDebtReadError(error, path3.relative(basePath, file), "list-all-debt-archived");
1614
+ }
1615
+ }
1616
+ }
1617
+ return items;
1618
+ }
1619
+ async function listMarkdownFileNames(directory) {
1620
+ let entries;
1621
+ try {
1622
+ entries = await fs2.readdir(directory, { withFileTypes: true });
1623
+ } catch {
1624
+ return [];
1625
+ }
1626
+ return entries.filter(
1627
+ (entry) => entry.isFile() && entry.name.endsWith(".md") && entry.name.toLowerCase() !== "readme.md"
1628
+ ).map((entry) => entry.name);
1629
+ }
1630
+ async function listMarkdownFilesRecursive2(directory) {
1631
+ const results = [];
1632
+ let entries;
1633
+ try {
1634
+ entries = await fs2.readdir(directory, { withFileTypes: true });
1635
+ } catch {
1636
+ return results;
1637
+ }
1638
+ for (const entry of entries) {
1639
+ const fullPath = path3.join(directory, entry.name);
1640
+ if (entry.isDirectory()) {
1641
+ results.push(...await listMarkdownFilesRecursive2(fullPath));
1642
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
1643
+ results.push(fullPath);
1644
+ }
1645
+ }
1646
+ return results;
1647
+ }
1648
+ function sortBySeverityThenImpact(items) {
1649
+ return items.sort((a, b) => {
1650
+ const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
1651
+ const sevCompare = severityOrder[a.severity] - severityOrder[b.severity];
1652
+ return sevCompare !== 0 ? sevCompare : b.impact - a.impact;
1653
+ });
1654
+ }
1655
+ function sortBySeverityThenHours(items) {
1656
+ const tiebreakMinutes = (item) => item.expectedRuntimeMinutes ?? item.estimatedHours * 60;
1657
+ return items.sort((a, b) => {
1658
+ const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
1659
+ const sevCompare = severityOrder[a.severity] - severityOrder[b.severity];
1660
+ return sevCompare !== 0 ? sevCompare : tiebreakMinutes(a) - tiebreakMinutes(b);
1661
+ });
1662
+ }
1663
+ function applyDebtSchedule(metadata, when) {
1664
+ const now = /* @__PURE__ */ new Date();
1665
+ switch (when) {
1666
+ case "immediate":
1667
+ metadata.executeBy = now.toISOString().split("T")[0];
1668
+ metadata.status = "in-progress";
1669
+ break;
1670
+ case "current-sprint": {
1671
+ const currentSprintEnd = new Date(now);
1672
+ currentSprintEnd.setDate(currentSprintEnd.getDate() + 7);
1673
+ metadata.targetCompleteDate = currentSprintEnd.toISOString().split("T")[0];
1674
+ break;
1675
+ }
1676
+ case "next-sprint": {
1677
+ const nextSprintEnd = new Date(now);
1678
+ nextSprintEnd.setDate(nextSprintEnd.getDate() + 14);
1679
+ metadata.targetCompleteDate = nextSprintEnd.toISOString().split("T")[0];
1680
+ break;
1681
+ }
1682
+ case "backlog":
1683
+ delete metadata.executeBy;
1684
+ delete metadata.targetCompleteDate;
1685
+ break;
1686
+ }
1687
+ metadata.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1688
+ }
1689
+ function markDebtComplete(metadata) {
1690
+ metadata.status = "completed";
1691
+ metadata.completedAt = (/* @__PURE__ */ new Date()).toISOString();
1692
+ metadata.archivedAt = (/* @__PURE__ */ new Date()).toISOString();
1693
+ metadata.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1694
+ }
1695
+ function warnDebtReadError(error, file, operation) {
1696
+ emitWarning(
1697
+ "WS-002G",
1698
+ {
1699
+ taskId: "tech-debt-manager",
1700
+ subsystem: "planning",
1701
+ executionPhase: "execution"
1702
+ },
1703
+ {
1704
+ severity: "WARN" /* WARN */,
1705
+ skipConsole: true,
1706
+ metadata: {
1707
+ error: error instanceof Error ? error.message : String(error),
1708
+ file,
1709
+ operation
1710
+ }
1711
+ }
1712
+ );
1713
+ }
1714
+
1715
+ // src/core/read-models/next-duplicate-titles.ts
1716
+ function normalizeTitle(title) {
1717
+ return title.normalize("NFD").replace(/[\u0300-\u036f]/g, "").normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, "").replace(/\s+/g, " ").trim();
1718
+ }
1719
+ var STOP_WORDS = /* @__PURE__ */ new Set(["the", "and", "for", "with", "from", "that", "this", "then"]);
1720
+ var COMMON_VERBS = /* @__PURE__ */ new Set([
1721
+ "add",
1722
+ "fix",
1723
+ "implement",
1724
+ "update",
1725
+ "remove",
1726
+ "delete",
1727
+ "change",
1728
+ "support",
1729
+ "show",
1730
+ "list",
1731
+ "create",
1732
+ "enable",
1733
+ "disable",
1734
+ "allow",
1735
+ "ensure"
1736
+ ]);
1737
+ function areNearDuplicates(title1, title2) {
1738
+ const norm1 = normalizeTitle(title1);
1739
+ const norm2 = normalizeTitle(title2);
1740
+ if (norm1 === norm2) return true;
1741
+ const phrase1 = ` ${norm1} `;
1742
+ const phrase2 = ` ${norm2} `;
1743
+ if (phrase1.includes(phrase2) || phrase2.includes(phrase1)) {
1744
+ const words1 = norm1.split(" ");
1745
+ const words2 = norm2.split(" ");
1746
+ if (Math.min(words1.length, words2.length) >= 3) return true;
1747
+ }
1748
+ const tokens1 = norm1.split(" ").filter((t) => t.length > 2);
1749
+ const tokens2 = norm2.split(" ").filter((t) => t.length > 2);
1750
+ if (tokens1.length === 0 || tokens2.length === 0) return false;
1751
+ const filtered1 = tokens1.filter((t) => !STOP_WORDS.has(t) && !COMMON_VERBS.has(t));
1752
+ const filtered2 = tokens2.filter((t) => !STOP_WORDS.has(t) && !COMMON_VERBS.has(t));
1753
+ if (filtered1.length === 0 || filtered2.length === 0) return false;
1754
+ const set1 = new Set(filtered1);
1755
+ const set2 = new Set(filtered2);
1756
+ const intersection = [...set1].filter((t) => set2.has(t));
1757
+ const smallerSize = Math.min(set1.size, set2.size);
1758
+ const unionSize = (/* @__PURE__ */ new Set([...set1, ...set2])).size;
1759
+ if (smallerSize === 0) return false;
1760
+ const overlapRatio = intersection.length / smallerSize;
1761
+ const jaccardRatio = intersection.length / unionSize;
1762
+ if (smallerSize <= 2) {
1763
+ return overlapRatio >= 0.85 && jaccardRatio >= 0.5;
1764
+ }
1765
+ return overlapRatio >= 0.75 && jaccardRatio >= 0.4;
1766
+ }
1767
+
1768
+ // src/core/read-models/next.ts
1769
+ async function tryGetGitHeadSha(cwd) {
1770
+ try {
1771
+ const result = await execa("git", ["rev-parse", "HEAD"], { cwd });
1772
+ const sha = result.stdout.trim();
1773
+ return sha.length > 0 ? sha : void 0;
1774
+ } catch {
1775
+ return void 0;
1776
+ }
1777
+ }
1778
+ var GIT_DIFF_CACHE_TTL_MS = 5 * 60 * 1e3;
1779
+ var GIT_DIFF_CACHE_MAX_ENTRIES = 500;
1780
+ var gitDiffCache = /* @__PURE__ */ new Map();
1781
+ function pruneGitDiffCache(now) {
1782
+ for (const [key, value] of gitDiffCache.entries()) {
1783
+ if (now - value.cachedAt > GIT_DIFF_CACHE_TTL_MS) {
1784
+ gitDiffCache.delete(key);
1785
+ }
1786
+ }
1787
+ if (gitDiffCache.size <= GIT_DIFF_CACHE_MAX_ENTRIES) {
1788
+ return;
1789
+ }
1790
+ const entriesByAge = [...gitDiffCache.entries()].sort((a, b) => a[1].cachedAt - b[1].cachedAt);
1791
+ const overflowCount = gitDiffCache.size - GIT_DIFF_CACHE_MAX_ENTRIES;
1792
+ for (const [key] of entriesByAge.slice(0, overflowCount)) {
1793
+ gitDiffCache.delete(key);
1794
+ }
1795
+ }
1796
+ async function getChangedFiles(cwd, fromSha, toSha, files) {
1797
+ if (files.length === 0) return [];
1798
+ const sortedFiles = [...files].sort();
1799
+ const cacheKey = `${fromSha}..${toSha}:${sortedFiles.join(",")}`;
1800
+ const now = Date.now();
1801
+ pruneGitDiffCache(now);
1802
+ const cached = gitDiffCache.get(cacheKey);
1803
+ if (cached !== void 0 && now - cached.cachedAt <= GIT_DIFF_CACHE_TTL_MS) {
1804
+ return cached.changedFiles;
1805
+ }
1806
+ try {
1807
+ const result = await execa(
1808
+ "git",
1809
+ ["diff", "--name-only", `${fromSha}..${toSha}`, "--", ...files],
1810
+ {
1811
+ cwd,
1812
+ reject: false
1813
+ }
1814
+ );
1815
+ const changedFiles = result.exitCode === 0 ? result.stdout.split("\n").map((f) => f.trim()).filter((f) => f.length > 0) : [];
1816
+ gitDiffCache.set(cacheKey, { changedFiles, cachedAt: now });
1817
+ pruneGitDiffCache(now);
1818
+ return changedFiles;
1819
+ } catch {
1820
+ return [];
1821
+ }
1822
+ }
1823
+ async function getLinkedBacklogEligibility(rootDir) {
1824
+ const linkedCompletedIds = /* @__PURE__ */ new Set();
1825
+ const linkedBlockedIds = /* @__PURE__ */ new Set();
1826
+ const linkedUnsatisfiedDependencyIds = /* @__PURE__ */ new Set();
1827
+ try {
1828
+ const tasksDir = getBucketPathByKind("task", rootDir);
1829
+ const archiveDir = getBucketArchivePathByKind("task", rootDir);
1830
+ const taskStatuses = /* @__PURE__ */ new Map();
1831
+ const activeTasks = [];
1832
+ const taskFiles = await listMarkdownFiles(tasksDir);
1833
+ for (const file of taskFiles) {
1834
+ try {
1835
+ const { frontMatter } = await readMarkdownFile(file);
1836
+ const taskId = typeof frontMatter.id === "string" ? frontMatter.id : void 0;
1837
+ const status = normalizeTaskStatus(frontMatter.status);
1838
+ if (taskId) {
1839
+ taskStatuses.set(taskId, { status, archived: false });
1840
+ }
1841
+ if (taskId && typeof frontMatter.backlogItemId === "string" && frontMatter.backlogItemId.length > 0) {
1842
+ activeTasks.push({
1843
+ id: taskId,
1844
+ backlogItemId: frontMatter.backlogItemId,
1845
+ sprintId: typeof frontMatter.sprintId === "string" ? frontMatter.sprintId : void 0,
1846
+ status,
1847
+ dependencies: Array.isArray(frontMatter.dependencies) ? frontMatter.dependencies.filter((dep) => typeof dep === "string") : []
1848
+ });
1849
+ }
1850
+ } catch {
1851
+ }
1852
+ }
1853
+ const archivedTaskFiles = await listMarkdownFilesRecursive(archiveDir).catch(() => []);
1854
+ for (const file of archivedTaskFiles) {
1855
+ try {
1856
+ const { frontMatter } = await readMarkdownFile(file);
1857
+ const taskId = typeof frontMatter.id === "string" ? frontMatter.id : void 0;
1858
+ const status = normalizeTaskStatus(frontMatter.status);
1859
+ if (taskId && !taskStatuses.has(taskId)) {
1860
+ taskStatuses.set(taskId, { status, archived: true });
1861
+ }
1862
+ if (typeof frontMatter.backlogItemId === "string" && frontMatter.backlogItemId.length > 0 && (status === "done" || status === "review")) {
1863
+ linkedCompletedIds.add(frontMatter.backlogItemId);
1864
+ }
1865
+ } catch {
1866
+ }
1867
+ }
1868
+ const ledgers = /* @__PURE__ */ new Map();
1869
+ for (const task of activeTasks) {
1870
+ if (task.status === "done" || task.status === "review") {
1871
+ linkedCompletedIds.add(task.backlogItemId);
1872
+ continue;
1873
+ }
1874
+ if (task.status === "blocked") {
1875
+ linkedBlockedIds.add(task.backlogItemId);
1876
+ continue;
1877
+ }
1878
+ if (task.dependencies.length === 0) {
1879
+ continue;
1880
+ }
1881
+ if (task.sprintId && !ledgers.has(task.sprintId) && task.dependencies.some((id) => !taskStatuses.has(id))) {
1882
+ ledgers.set(
1883
+ task.sprintId,
1884
+ await loadSprintCompletedTaskIds(task.sprintId, rootDir).catch(() => /* @__PURE__ */ new Set())
1885
+ );
1886
+ }
1887
+ const completed = task.sprintId ? ledgers.get(task.sprintId) : void 0;
1888
+ const hasUnsatisfiedDependency = task.dependencies.some((dependencyId) => {
1889
+ const depStatus = taskStatuses.get(dependencyId);
1890
+ return !classifyTaskDependency(dependencyId, {
1891
+ task: depStatus ?? null,
1892
+ recordedComplete: completed?.has(dependencyId)
1893
+ }).satisfied;
1894
+ });
1895
+ if (hasUnsatisfiedDependency) {
1896
+ linkedUnsatisfiedDependencyIds.add(task.backlogItemId);
1897
+ }
1898
+ }
1899
+ } catch {
1900
+ }
1901
+ return {
1902
+ linkedCompletedIds,
1903
+ linkedBlockedIds,
1904
+ linkedUnsatisfiedDependencyIds
1905
+ };
1906
+ }
1907
+ async function getGraphBlockedBacklogItems(rootDir) {
1908
+ const blocked = /* @__PURE__ */ new Map();
1909
+ try {
1910
+ const context = await loadWorkGraphContext(rootDir);
1911
+ const isSatisfied = (blockerId) => {
1912
+ const blocker = context.itemsById.get(blockerId);
1913
+ if (!blocker) return true;
1914
+ const rawStatus = blocker.frontMatter.status;
1915
+ const status = typeof rawStatus === "string" ? rawStatus : "";
1916
+ return status === "done" || status === "archived" || status === "completed";
1917
+ };
1918
+ for (const [itemId, item] of context.itemsById) {
1919
+ if (item.frontMatter.kind !== "backlog") continue;
1920
+ const view = buildGraphBlockersView(context, itemId);
1921
+ if (!view || view.blockers.length === 0) continue;
1922
+ const unresolved = [];
1923
+ const seen = /* @__PURE__ */ new Set();
1924
+ for (const blocker of view.blockers) {
1925
+ if (seen.has(blocker.id)) continue;
1926
+ seen.add(blocker.id);
1927
+ if (!isSatisfied(blocker.id)) {
1928
+ unresolved.push({ id: blocker.id, title: blocker.title });
1929
+ }
1930
+ }
1931
+ if (unresolved.length > 0) {
1932
+ blocked.set(itemId, unresolved);
1933
+ }
1934
+ }
1935
+ } catch {
1936
+ }
1937
+ return blocked;
1938
+ }
1939
+ async function getArchivedBacklogTitles(rootDir) {
1940
+ const titles = /* @__PURE__ */ new Map();
1941
+ try {
1942
+ const archiveDir = getBucketArchivePathByKind("backlog", rootDir);
1943
+ const files = await listMarkdownFilesRecursive(archiveDir);
1944
+ for (const file of files) {
1945
+ try {
1946
+ const { frontMatter } = await readMarkdownFile(file);
1947
+ if (frontMatter.title && typeof frontMatter.title === "string") {
1948
+ const normalized = normalizeTitle(frontMatter.title);
1949
+ titles.set(normalized, {
1950
+ id: frontMatter.id,
1951
+ title: frontMatter.title
1952
+ });
1953
+ }
1954
+ } catch {
1955
+ }
1956
+ }
1957
+ } catch {
1958
+ }
1959
+ return titles;
1960
+ }
1961
+ function extractBodyPreview(body, maxChars = 300) {
1962
+ const withoutTitle = body.replace(/^\s*#[^\n]*\n?/, "").trim();
1963
+ if (withoutTitle.length === 0) return "";
1964
+ const lines = withoutTitle.split(/\r?\n/);
1965
+ while (lines.length > 0) {
1966
+ const firstLine = (lines[0] ?? "").trim();
1967
+ if (firstLine.length === 0 || /^#{1,6}\s+/.test(firstLine)) {
1968
+ lines.shift();
1969
+ continue;
1970
+ }
1971
+ break;
1972
+ }
1973
+ const stripped = lines.join("\n").trim();
1974
+ if (stripped.length === 0) return "";
1975
+ if (stripped.length <= maxChars) return stripped;
1976
+ const truncated = stripped.slice(0, maxChars);
1977
+ const lastSpace = truncated.lastIndexOf(" ");
1978
+ const cutPoint = lastSpace > maxChars * 0.5 ? lastSpace : maxChars;
1979
+ return `${truncated.slice(0, cutPoint)}...`;
1980
+ }
1981
+ function extractAcceptanceCriteria(body) {
1982
+ const lines = body.split(/\r?\n/);
1983
+ const criteria = [];
1984
+ let inAcceptanceCriteria = false;
1985
+ let inExampleBlock = false;
1986
+ for (const rawLine of lines) {
1987
+ const headingMatch = rawLine.match(/^\s{0,3}#{1,6}\s+(.+?)\s*$/);
1988
+ if (headingMatch) {
1989
+ const heading = headingMatch[1]?.replace(/:\s*$/, "").trim().toLowerCase();
1990
+ if (!inAcceptanceCriteria) {
1991
+ inAcceptanceCriteria = heading === "acceptance criteria";
1992
+ continue;
1993
+ }
1994
+ break;
1995
+ }
1996
+ if (!inAcceptanceCriteria) continue;
1997
+ const line = rawLine.trim();
1998
+ if (line.length === 0) continue;
1999
+ if (/^example\s*:?\s*$/i.test(line)) {
2000
+ inExampleBlock = true;
2001
+ continue;
2002
+ }
2003
+ if (inExampleBlock) continue;
2004
+ const bulletMatch = line.match(/^[-*]\s+(?:\[(?: |x|X)\]\s+)?(.+)$/);
2005
+ if (!bulletMatch) continue;
2006
+ const content = bulletMatch[1]?.trim() ?? "";
2007
+ if (content.length === 0) continue;
2008
+ if (content.includes("<<<") || content.includes(">>>")) continue;
2009
+ criteria.push(content);
2010
+ }
2011
+ return criteria;
2012
+ }
2013
+ async function queryNextItemsResult(options) {
2014
+ const unavailable = checkSharedBucketReadability(resolvePlanningContextForRoot(options.rootDir));
2015
+ return unavailable ?? planningReadOk(await collectNextItems(options));
2016
+ }
2017
+ async function queryNextItems(options) {
2018
+ return unwrapPlanningRead(await queryNextItemsResult(options));
2019
+ }
2020
+ async function collectNextItems(options) {
2021
+ const { rootDir } = options;
2022
+ const backlogDir = getBucketPathByKind("backlog", rootDir);
2023
+ const backlogDirRel = path4.relative(rootDir, backlogDir);
2024
+ const requestedKinds = options.kinds ?? [];
2025
+ const shouldQueryBacklog = requestedKinds.length === 0 || requestedKinds.includes("backlog");
2026
+ const backlogExists = shouldQueryBacklog ? await fs3.stat(backlogDir).then(() => true).catch(() => false) : false;
2027
+ if (!backlogExists && !options.includeFindings && requestedKinds.length === 0) {
2028
+ return [];
2029
+ }
2030
+ const backlogItems = backlogExists ? await listBacklogItems(backlogDir) : [];
2031
+ const inboxItems = backlogItems.filter((item) => item.status === "inbox");
2032
+ const reviewedItems = backlogItems.filter((item) => item.status === "reviewed");
2033
+ const linkedEligibility = backlogExists ? await getLinkedBacklogEligibility(rootDir) : {
2034
+ linkedCompletedIds: /* @__PURE__ */ new Set(),
2035
+ linkedBlockedIds: /* @__PURE__ */ new Set(),
2036
+ linkedUnsatisfiedDependencyIds: /* @__PURE__ */ new Set()
2037
+ };
2038
+ const graphBlockedItems = backlogExists ? await getGraphBlockedBacklogItems(rootDir) : /* @__PURE__ */ new Map();
2039
+ const archivedTitles = backlogExists ? await getArchivedBacklogTitles(rootDir) : /* @__PURE__ */ new Map();
2040
+ const activeProvenanceStatuses = /* @__PURE__ */ new Set([
2041
+ "pr-open",
2042
+ "archive-sync-pending",
2043
+ "delivered-local",
2044
+ "merged",
2045
+ "archived"
2046
+ ]);
2047
+ const provenanceSuppressedIds = /* @__PURE__ */ new Set();
2048
+ const blockedProvenanceReasons = /* @__PURE__ */ new Map();
2049
+ if (backlogExists) {
2050
+ const allCandidateIds = [...inboxItems, ...reviewedItems].map((item) => item.id);
2051
+ await Promise.all(
2052
+ allCandidateIds.map(async (id) => {
2053
+ try {
2054
+ const provenance = await loadBacklogExecutionProvenance(rootDir, id, {
2055
+ cleanupTerminalLocks: false
2056
+ });
2057
+ if (provenance?.status === "executing" && await isBacklogExecutionProvenanceActivelyExecuting(rootDir, provenance)) {
2058
+ provenanceSuppressedIds.add(id);
2059
+ } else if (provenance && activeProvenanceStatuses.has(provenance.status)) {
2060
+ provenanceSuppressedIds.add(id);
2061
+ } else if (provenance?.status === "blocked") {
2062
+ const blockedReason = provenance.errorMessage?.trim();
2063
+ if (blockedReason) {
2064
+ blockedProvenanceReasons.set(id, blockedReason);
2065
+ }
2066
+ }
2067
+ } catch {
2068
+ }
2069
+ })
2070
+ );
2071
+ }
2072
+ const candidates = [];
2073
+ let headSha;
2074
+ const ensureHeadSha = async () => {
2075
+ if (headSha) return headSha;
2076
+ headSha = await tryGetGitHeadSha(rootDir);
2077
+ return headSha;
2078
+ };
2079
+ const processItem = (item, statusLabel) => {
2080
+ if (linkedEligibility.linkedCompletedIds.has(item.id)) {
2081
+ return null;
2082
+ }
2083
+ if (linkedEligibility.linkedBlockedIds.has(item.id)) {
2084
+ return null;
2085
+ }
2086
+ if (linkedEligibility.linkedUnsatisfiedDependencyIds.has(item.id)) {
2087
+ return null;
2088
+ }
2089
+ const openBlockers = graphBlockedItems.get(item.id);
2090
+ if (openBlockers && openBlockers.length > 0 && !options.includeBlocked) {
2091
+ return null;
2092
+ }
2093
+ if (provenanceSuppressedIds.has(item.id)) {
2094
+ return null;
2095
+ }
2096
+ let isDuplicate = false;
2097
+ let duplicateOf;
2098
+ for (const [, archived] of archivedTitles) {
2099
+ if (areNearDuplicates(item.title, archived.title)) {
2100
+ isDuplicate = true;
2101
+ duplicateOf = archived.id;
2102
+ break;
2103
+ }
2104
+ }
2105
+ if (isDuplicate && !options.includeDuplicates) {
2106
+ return null;
2107
+ }
2108
+ const reviewedHeadSha = typeof item.reviewedHeadSha === "string" && item.reviewedHeadSha.length > 0 ? item.reviewedHeadSha : void 0;
2109
+ const reviewedAt = typeof item.reviewedAt === "string" && item.reviewedAt.length > 0 ? item.reviewedAt : void 0;
2110
+ const reviewedFiles = Array.isArray(item.reviewedFiles) && item.reviewedFiles.length > 0 ? item.reviewedFiles : void 0;
2111
+ const blockedReason = blockedProvenanceReasons.get(item.id);
2112
+ const needsRefinement = item.needsRefinement;
2113
+ return {
2114
+ id: item.id,
2115
+ kind: "backlog",
2116
+ title: item.title,
2117
+ priority: item.priority,
2118
+ status: item.status,
2119
+ filePath: path4.join(backlogDirRel, `${item.id}.md`),
2120
+ domain: item.domain ?? void 0,
2121
+ complexity: item.complexity ?? void 0,
2122
+ whyIncluded: `${statusLabel} backlog item${item.priority ? ` (${item.priority})` : ""}`,
2123
+ createdAt: item.createdAt ?? void 0,
2124
+ reviewedAt,
2125
+ reviewedHeadSha,
2126
+ reviewedFiles,
2127
+ isDuplicate,
2128
+ duplicateOf,
2129
+ blockedReason,
2130
+ blockedAnswerHint: blockedReason ? `build plan backlog execute ${item.id} --answer blockerId=value` : void 0,
2131
+ blockedByOpen: openBlockers && openBlockers.length > 0 ? openBlockers.map((b) => ({ id: b.id, title: b.title })) : void 0,
2132
+ needsRefinement
2133
+ };
2134
+ };
2135
+ for (const item of reviewedItems) {
2136
+ const candidate = processItem(item, "Reviewed");
2137
+ if (candidate) candidates.push(candidate);
2138
+ }
2139
+ for (const item of inboxItems) {
2140
+ const candidate = processItem(item, "Inbox");
2141
+ if (candidate) candidates.push(candidate);
2142
+ }
2143
+ if (options.includeFindings) {
2144
+ const policy = loadIssuePolicy(rootDir);
2145
+ try {
2146
+ const actionableFindings = await listFindings(rootDir, "open");
2147
+ const findingDir = getBucketPathByKind("finding", rootDir);
2148
+ const findingDirRel = path4.relative(rootDir, findingDir);
2149
+ for (const f of actionableFindings) {
2150
+ const priority = severityToPriority(f.severity, policy);
2151
+ candidates.push({
2152
+ id: f.id,
2153
+ kind: "finding",
2154
+ title: f.title,
2155
+ priority,
2156
+ status: f.status,
2157
+ filePath: path4.join(findingDirRel, `${f.id}.md`),
2158
+ whyIncluded: `${f.status} finding (${f.category}${f.severity ? `/${f.severity}` : ""})`
2159
+ });
2160
+ }
2161
+ } catch {
2162
+ }
2163
+ try {
2164
+ const actionableIssues = [
2165
+ ...await listIssues(rootDir, "open"),
2166
+ ...await listIssues(rootDir, "claimed")
2167
+ ];
2168
+ const issueDir = getBucketPathByKind("issue", rootDir);
2169
+ const issueDirRel = path4.relative(rootDir, issueDir);
2170
+ for (const issue of actionableIssues) {
2171
+ const priority = severityToPriority(issue.severity, policy);
2172
+ candidates.push({
2173
+ id: issue.id,
2174
+ kind: "issue",
2175
+ title: issue.title,
2176
+ priority,
2177
+ status: issue.status,
2178
+ filePath: path4.join(issueDirRel, `${issue.id}.md`),
2179
+ whyIncluded: `${issue.status} issue (${issue.category}/${issue.severity})`
2180
+ });
2181
+ }
2182
+ } catch {
2183
+ }
2184
+ }
2185
+ const includeDebt = requestedKinds.includes("debt");
2186
+ const includeParking = requestedKinds.includes("parking");
2187
+ if (includeDebt) {
2188
+ try {
2189
+ const debtDir = getBucketPathByKind("tech-debt", rootDir);
2190
+ const debtExists = await fs3.stat(debtDir).then(() => true).catch(() => false);
2191
+ if (debtExists) {
2192
+ const debtItems = await listAllDebtAsync(false, rootDir);
2193
+ const debtDirRel = path4.relative(rootDir, debtDir);
2194
+ for (const item of debtItems) {
2195
+ if (item.status === "completed") continue;
2196
+ candidates.push({
2197
+ id: item.id,
2198
+ kind: "debt",
2199
+ title: item.title,
2200
+ priority: null,
2201
+ status: item.status,
2202
+ filePath: path4.join(debtDirRel, `${item.id}.md`),
2203
+ domain: item.domain,
2204
+ complexity: item.estimatedComplexity,
2205
+ whyIncluded: `Tech debt (${item.severity}${item.blocking ? ", blocking" : ""})`,
2206
+ createdAt: item.createdAt ?? item.createdDate,
2207
+ severity: item.severity,
2208
+ blocking: item.blocking,
2209
+ effort: item.effort
2210
+ });
2211
+ }
2212
+ }
2213
+ } catch {
2214
+ }
2215
+ }
2216
+ if (includeParking) {
2217
+ try {
2218
+ const parkingDir = getBucketPathByKind("parking-lot", rootDir);
2219
+ const parkingExists = await fs3.stat(parkingDir).then(() => true).catch(() => false);
2220
+ if (parkingExists) {
2221
+ const parkingItems = await listActive(parkingDir);
2222
+ const parkingDirRel = path4.relative(rootDir, parkingDir);
2223
+ const now = /* @__PURE__ */ new Date();
2224
+ for (const item of parkingItems) {
2225
+ const isOverdue = typeof item.reconsiderDate === "string" && item.reconsiderDate.length > 0 ? new Date(item.reconsiderDate) <= now : false;
2226
+ candidates.push({
2227
+ id: item.id,
2228
+ kind: "parking",
2229
+ title: item.title,
2230
+ priority: null,
2231
+ status: item.status,
2232
+ filePath: path4.join(parkingDirRel, `${item.id}.md`),
2233
+ whyIncluded: `Parked item${isOverdue ? " (overdue for reconsideration)" : ""}`,
2234
+ createdAt: item.createdAt,
2235
+ deferralReason: item.deferralReason,
2236
+ reconsiderDate: item.reconsiderDate ?? null,
2237
+ isOverdue
2238
+ });
2239
+ }
2240
+ }
2241
+ } catch {
2242
+ }
2243
+ }
2244
+ const isCrossEntity = requestedKinds.length > 0;
2245
+ const priorityOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
2246
+ const debtSeverityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
2247
+ function crossEntityBucket(c) {
2248
+ if (c.kind === "backlog" || c.kind === "task" || c.kind === "finding" || c.kind === "issue") {
2249
+ const p = c.priority ? priorityOrder[c.priority] ?? 4 : 4;
2250
+ return p <= 1 ? 0 : 3;
2251
+ }
2252
+ if (c.kind === "debt") {
2253
+ const sev = c.severity ?? "low";
2254
+ if ((sev === "critical" || sev === "high") && c.blocking) return 1;
2255
+ if (sev === "high") return 2;
2256
+ return 4;
2257
+ }
2258
+ return 5;
2259
+ }
2260
+ candidates.sort((a, b) => {
2261
+ if (isCrossEntity) {
2262
+ const aBucket = crossEntityBucket(a);
2263
+ const bBucket = crossEntityBucket(b);
2264
+ if (aBucket !== bBucket) return aBucket - bBucket;
2265
+ if (aBucket === 5) {
2266
+ const aDate = a.reconsiderDate ?? "9999-12-31";
2267
+ const bDate = b.reconsiderDate ?? "9999-12-31";
2268
+ if (aDate !== bDate) return aDate.localeCompare(bDate);
2269
+ return a.id.localeCompare(b.id);
2270
+ }
2271
+ if (aBucket === 1 || aBucket === 2 || aBucket === 4) {
2272
+ const aSev = debtSeverityOrder[a.severity ?? "low"] ?? 3;
2273
+ const bSev = debtSeverityOrder[b.severity ?? "low"] ?? 3;
2274
+ if (aSev !== bSev) return aSev - bSev;
2275
+ return a.id.localeCompare(b.id);
2276
+ }
2277
+ }
2278
+ const aPriority = a.priority ? priorityOrder[a.priority] ?? 4 : 4;
2279
+ const bPriority = b.priority ? priorityOrder[b.priority] ?? 4 : 4;
2280
+ if (aPriority !== bPriority) return aPriority - bPriority;
2281
+ const statusOrder = { reviewed: 0, inbox: 1 };
2282
+ const aStatus = statusOrder[a.status] ?? 2;
2283
+ const bStatus = statusOrder[b.status] ?? 2;
2284
+ if (aStatus !== bStatus) return aStatus - bStatus;
2285
+ const aCreatedAt = a.createdAt ? Date.parse(a.createdAt) : Number.NaN;
2286
+ const bCreatedAt = b.createdAt ? Date.parse(b.createdAt) : Number.NaN;
2287
+ const aHasCreatedAt = Number.isFinite(aCreatedAt);
2288
+ const bHasCreatedAt = Number.isFinite(bCreatedAt);
2289
+ if (aHasCreatedAt && bHasCreatedAt && aCreatedAt !== bCreatedAt) {
2290
+ return aCreatedAt - bCreatedAt;
2291
+ }
2292
+ if (aHasCreatedAt !== bHasCreatedAt) {
2293
+ return aHasCreatedAt ? -1 : 1;
2294
+ }
2295
+ return a.id.localeCompare(b.id);
2296
+ });
2297
+ const limitedCandidates = options.limit ? candidates.slice(0, options.limit) : candidates;
2298
+ const candidatesWithSha = limitedCandidates.filter((c) => c.reviewedHeadSha);
2299
+ if (candidatesWithSha.length > 0) {
2300
+ const currentHead = await ensureHeadSha();
2301
+ if (currentHead) {
2302
+ for (const candidate of candidatesWithSha) {
2303
+ if (!candidate.reviewedHeadSha) continue;
2304
+ if (candidate.reviewedHeadSha === currentHead) {
2305
+ continue;
2306
+ }
2307
+ if (candidate.reviewedFiles && candidate.reviewedFiles.length > 0) {
2308
+ const changedFiles = await getChangedFiles(
2309
+ rootDir,
2310
+ candidate.reviewedHeadSha,
2311
+ currentHead,
2312
+ candidate.reviewedFiles
2313
+ );
2314
+ if (changedFiles.length > 0) {
2315
+ candidate.isStaleReview = true;
2316
+ candidate.staleReason = "files_changed";
2317
+ candidate.whyIncluded = `${candidate.whyIncluded} (needs re-review: ${changedFiles.length} file(s) changed)`;
2318
+ }
2319
+ } else {
2320
+ candidate.isStaleReview = true;
2321
+ candidate.staleReason = "head_changed";
2322
+ candidate.whyIncluded = `${candidate.whyIncluded} (needs re-review)`;
2323
+ }
2324
+ }
2325
+ }
2326
+ }
2327
+ if (options.context) {
2328
+ for (const candidate of limitedCandidates) {
2329
+ if (candidate.kind !== "backlog") continue;
2330
+ try {
2331
+ const item = await findBacklogItem(backlogDir, candidate.id);
2332
+ if (item?.body) {
2333
+ candidate.bodyPreview = extractBodyPreview(item.body);
2334
+ const criteria = extractAcceptanceCriteria(item.body);
2335
+ if (criteria.length > 0) {
2336
+ candidate.acceptanceCriteria = criteria;
2337
+ }
2338
+ }
2339
+ } catch {
2340
+ }
2341
+ }
2342
+ }
2343
+ return limitedCandidates;
2344
+ }
2345
+ function parseKindOption(raw) {
2346
+ if (!raw) return [];
2347
+ const validKinds = /* @__PURE__ */ new Set(["backlog", "debt", "parking", "all"]);
2348
+ const parts = raw.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
2349
+ const invalidKinds = parts.filter((kind) => !validKinds.has(kind));
2350
+ if (invalidKinds.length > 0) {
2351
+ throw new Error(`Unknown --kind value(s): ${invalidKinds.join(", ")}`);
2352
+ }
2353
+ if (parts.includes("all")) {
2354
+ return ["backlog", "debt", "parking"];
2355
+ }
2356
+ return [...new Set(parts)];
2357
+ }
2358
+
2359
+ export {
2360
+ normalizePath,
2361
+ generateFingerprint,
2362
+ findDuplicate,
2363
+ trackOccurrence,
2364
+ appendObservation,
2365
+ getObservations,
2366
+ computeAgreement,
2367
+ computeConsensus,
2368
+ createObservation,
2369
+ createFinding,
2370
+ readFinding,
2371
+ updateFinding,
2372
+ transitionFindingStatus,
2373
+ listFindings,
2374
+ readIssue,
2375
+ transitionIssueStatus,
2376
+ listIssues,
2377
+ promoteFindingToIssue,
2378
+ renewEntityLease,
2379
+ validateFinding,
2380
+ getConsensus,
2381
+ spawnTaskFromIssue,
2382
+ auditMalformedIssueFiles,
2383
+ loadIssuePolicy,
2384
+ isCategoryGated,
2385
+ isSeverityGated,
2386
+ applyWeight,
2387
+ exceedsBatchBudget,
2388
+ getDebtItemAsync,
2389
+ createDebtItemAsync,
2390
+ updateDebtItemAsync,
2391
+ listByBlockingAsync,
2392
+ listByParallelizableAsync,
2393
+ scheduleDebtAsync,
2394
+ completeDebtAsync,
2395
+ listAllDebtAsync,
2396
+ areNearDuplicates,
2397
+ extractBodyPreview,
2398
+ extractAcceptanceCriteria,
2399
+ queryNextItemsResult,
2400
+ queryNextItems,
2401
+ parseKindOption
2402
+ };
2403
+ //# sourceMappingURL=chunk-S6TAFQI5.js.map