@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,2659 @@
1
+ import {
2
+ CANDIDATE_ITEM_ID_PREFIX,
3
+ CANDIDATE_SEARCH_PRIORITY,
4
+ MAX_UNRESOLVED_LINES,
5
+ QUERY_SAFE_EVIDENCE_CLASSES,
6
+ SERVICE_DOC_DOMAINS,
7
+ STACK_BLOCK_MARKERS,
8
+ acceptDetectedReality,
9
+ acknowledgeConflicts,
10
+ candidateSetSignature,
11
+ ciAdvisoryMessage,
12
+ computeStackFingerprint,
13
+ createIntentContract,
14
+ detectStack,
15
+ fingerprintDigest,
16
+ forgetDriftRecord,
17
+ isCandidateQuerySafe,
18
+ isQuerySafeHostname,
19
+ isSafeStackIdentifier,
20
+ legacyDeclaredStackPath,
21
+ listPendingDrift,
22
+ migrateLegacyDeclaration,
23
+ parseIntentSpec,
24
+ readDriftRecord,
25
+ readIntentContract,
26
+ readStoredFingerprint,
27
+ recordDelivery,
28
+ recordDriftRecords,
29
+ removeIntentContract,
30
+ renderAcknowledgedSdkPair,
31
+ renderStackAgentsBlock,
32
+ resolveIntent,
33
+ resolvedStackDetection,
34
+ retireContract,
35
+ serviceSignalForToken,
36
+ writeIntentContract,
37
+ writeStoredFingerprint
38
+ } from "./chunk-VYI4DSZP.js";
39
+ import {
40
+ CONTEXT_DIR,
41
+ KNOWLEDGE_BLOCK_BEGIN,
42
+ KNOWLEDGE_BLOCK_END,
43
+ KitItemSchema,
44
+ PURPOSE_BLOCK_MARKERS,
45
+ createManifest,
46
+ knowledgeManifestPath,
47
+ readKnowledgeManifest,
48
+ resolveBuildVersion,
49
+ writeKnowledgeManifest
50
+ } from "./chunk-BQ3VAGXH.js";
51
+ import {
52
+ runAsk
53
+ } from "./chunk-YPDCLXNZ.js";
54
+ import {
55
+ FRAMEWORK_RULES
56
+ } from "./chunk-PFCXFO7A.js";
57
+ import {
58
+ atomicWriteJson,
59
+ atomicWriteJsonSync,
60
+ atomicWriteText,
61
+ atomicWriteTextSync
62
+ } from "./chunk-RFDVSI4N.js";
63
+ import {
64
+ isCiEnvironment
65
+ } from "./chunk-SKTFRFQ7.js";
66
+ import {
67
+ getDefaultPaths
68
+ } from "./chunk-56WPYDJH.js";
69
+ import {
70
+ getPackageRoot
71
+ } from "./chunk-STW7OFOA.js";
72
+
73
+ // src/utils/managed-block.ts
74
+ function upsertManagedBlock(existingContent, block, markers) {
75
+ const beginIndex = existingContent.indexOf(markers.begin);
76
+ const endIndex = existingContent.indexOf(markers.end);
77
+ if (beginIndex === -1 && endIndex === -1) {
78
+ if (existingContent.length === 0) return `${block}
79
+ `;
80
+ const separator = existingContent.endsWith("\n\n") ? "" : existingContent.endsWith("\n") ? "\n" : "\n\n";
81
+ return `${existingContent}${separator}${block}
82
+ `;
83
+ }
84
+ if (beginIndex === -1 || endIndex === -1 || endIndex < beginIndex) {
85
+ throw new Error(
86
+ `Document contains a malformed managed block (unpaired ${markers.begin} / ${markers.end} markers); refusing to modify it.`
87
+ );
88
+ }
89
+ const before = existingContent.slice(0, beginIndex);
90
+ const after = existingContent.slice(endIndex + markers.end.length);
91
+ return `${before}${block}${after}`;
92
+ }
93
+ function removeManagedBlock(existingContent, markers) {
94
+ const beginIndex = existingContent.indexOf(markers.begin);
95
+ const endIndex = existingContent.indexOf(markers.end);
96
+ if (beginIndex === -1 || endIndex === -1 || endIndex < beginIndex) {
97
+ return existingContent;
98
+ }
99
+ const before = existingContent.slice(0, beginIndex);
100
+ const after = existingContent.slice(endIndex + markers.end.length);
101
+ const trimmedBefore = before.endsWith("\n\n") ? before.slice(0, -1) : before;
102
+ return `${trimmedBefore}${after.startsWith("\n") ? after.slice(1) : after}`;
103
+ }
104
+
105
+ // src/core/knowledge/search.ts
106
+ import { z } from "zod";
107
+
108
+ // src/core/knowledge/framework-scope.ts
109
+ function frameworkScopeClause(detection) {
110
+ if (detection.frameworks.length === 0) {
111
+ return " No application framework was detected in this repository, so keep results framework-neutral: cover the language, its standard library and its standard tooling, and leave out any resource that exists only for a specific framework.";
112
+ }
113
+ return ` Framework-specific resources are limited to the detected framework(s): ${detection.frameworks.join(", ")}. Leave out resources that exist only for other frameworks.`;
114
+ }
115
+ function escapeRegExp(text) {
116
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
117
+ }
118
+ function buildEvidence() {
119
+ const evidence = /* @__PURE__ */ new Map();
120
+ for (const rule of FRAMEWORK_RULES) {
121
+ if (rule.dependencies === void 0) continue;
122
+ const entry = evidence.get(rule.label) ?? { patterns: [], hostLabels: [] };
123
+ for (const names of Object.values(rule.dependencies)) {
124
+ for (const raw of names ?? []) {
125
+ const name = raw.replace(/\*$/, "").replace(/:$/, "");
126
+ const slash = name.indexOf("/");
127
+ if (slash > 0) {
128
+ const owner = name.slice(0, slash);
129
+ entry.patterns.push(new RegExp(`(?<![a-z0-9._@-])${escapeRegExp(name)}(?![a-z0-9_-])`));
130
+ if (!owner.includes(".")) {
131
+ entry.patterns.push(new RegExp(`(?<![a-z0-9._-])${escapeRegExp(owner)}/`));
132
+ entry.hostLabels.push(owner.replace(/^@/, ""));
133
+ }
134
+ } else if (name.includes(".")) {
135
+ entry.patterns.push(new RegExp(`(?<![a-z0-9._-])${escapeRegExp(name)}(?![a-z0-9_-])`));
136
+ }
137
+ }
138
+ }
139
+ if (entry.patterns.length > 0) evidence.set(rule.label, entry);
140
+ }
141
+ return evidence;
142
+ }
143
+ var FRAMEWORK_EVIDENCE = buildEvidence();
144
+ function hostLabelsOf(url) {
145
+ try {
146
+ return new URL(url).hostname.toLowerCase().split(".");
147
+ } catch {
148
+ return [];
149
+ }
150
+ }
151
+ function namesUndetectedFramework(row, detection) {
152
+ const detected = new Set(detection.frameworks.map((framework) => framework.toLowerCase()));
153
+ const text = `${row.sourceUrl} ${row.installHint ?? ""}`.toLowerCase();
154
+ const hostLabels = hostLabelsOf(row.sourceUrl);
155
+ for (const [label, evidence] of FRAMEWORK_EVIDENCE) {
156
+ if (detected.has(label)) continue;
157
+ if (evidence.patterns.some((pattern) => pattern.test(text))) return true;
158
+ if (evidence.hostLabels.some((owner) => hostLabels.includes(owner))) return true;
159
+ }
160
+ return false;
161
+ }
162
+
163
+ // src/core/knowledge/search.ts
164
+ var DEFAULT_SEARCH_TIMEOUT_MS = 6e4;
165
+ var DEFAULT_MAX_QUERIES = 4;
166
+ var SourcePolicySchema = z.object({
167
+ allow: z.array(z.string().min(1)).default([]),
168
+ deny: z.array(z.string().min(1)).default([])
169
+ });
170
+ var OFFICIAL_DOC_DOMAINS = [
171
+ "apple.com",
172
+ "swift.org",
173
+ "developer.android.com",
174
+ "anthropic.com",
175
+ "modelcontextprotocol.io",
176
+ "nodejs.org",
177
+ "typescriptlang.org",
178
+ "react.dev",
179
+ "vuejs.org",
180
+ "angular.dev",
181
+ "svelte.dev",
182
+ "nextjs.org",
183
+ "python.org",
184
+ "go.dev",
185
+ "rust-lang.org",
186
+ "kotlinlang.org",
187
+ "dart.dev",
188
+ "flutter.dev",
189
+ "learn.microsoft.com",
190
+ // Curated external-service doc domains (service-signals.ts). Contributed here
191
+ // so a DETECTED service's docs carry `official` trust through the SAME gate —
192
+ // there is one trust system, not two.
193
+ ...SERVICE_DOC_DOMAINS
194
+ ];
195
+ var DEFAULT_SOURCE_POLICY = { allow: [], deny: [] };
196
+ function hostMatchesSuffix(host, suffix) {
197
+ const normalizedSuffix = suffix.toLowerCase().replace(/^\.+/, "");
198
+ return host === normalizedSuffix || host.endsWith(`.${normalizedSuffix}`);
199
+ }
200
+ function hostnameOf(url) {
201
+ try {
202
+ return new URL(url).hostname.toLowerCase();
203
+ } catch {
204
+ return void 0;
205
+ }
206
+ }
207
+ function isSourceAllowed(sourceUrl, policy) {
208
+ const host = hostnameOf(sourceUrl);
209
+ if (!host) return false;
210
+ if (policy.deny.some((suffix) => hostMatchesSuffix(host, suffix))) return false;
211
+ if (policy.allow.length === 0) return true;
212
+ return policy.allow.some((suffix) => hostMatchesSuffix(host, suffix));
213
+ }
214
+ function renderStackSummary(detection) {
215
+ const pairKeyed = /* @__PURE__ */ new Map();
216
+ for (const pair of detection.acknowledgedSdkPairs ?? []) {
217
+ pairKeyed.set(`${pair.platform}-${pair.sdkVersion}`, renderAcknowledgedSdkPair(pair));
218
+ pairKeyed.set(`${pair.platform}-${pair.deploymentVersion}`, "");
219
+ }
220
+ const sdkParts = [];
221
+ for (const target of detection.sdkTargets) {
222
+ if (pairKeyed.has(target)) {
223
+ const rendered = pairKeyed.get(target);
224
+ if (rendered) sdkParts.push(rendered);
225
+ continue;
226
+ }
227
+ sdkParts.push(target);
228
+ }
229
+ return [
230
+ detection.languages.filter((l) => l !== "unknown" && l !== "docs").join(", "),
231
+ detection.frameworks.join(", "),
232
+ sdkParts.join(", "),
233
+ (detection.tools ?? []).join(", "),
234
+ (detection.domains ?? []).join(", ")
235
+ ].filter((part) => part.length > 0).join("; ");
236
+ }
237
+ function buildSearchTasks(detection, maxQueries = DEFAULT_MAX_QUERIES, userGuidance) {
238
+ const stackSummary = renderStackSummary(detection);
239
+ if (!stackSummary) return [];
240
+ const guidance = userGuidance?.trim();
241
+ const querySuffix = frameworkScopeClause(detection) + (guidance ? ` The user gave this additional guidance about what they want: "${guidance}".` : "");
242
+ const tasks = [
243
+ {
244
+ id: "docs",
245
+ query: `Find the current best OFFICIAL documentation resources for coding agents working on this stack: ${stackSummary}. Prefer docs-as-markdown endpoints and official developer documentation MCP servers.${querySuffix}`
246
+ },
247
+ {
248
+ id: "mcp-skills",
249
+ query: `Find currently maintained MCP servers and official agent skills useful for a codebase using: ${stackSummary}. Include the exact install/registration command for each.${querySuffix}`
250
+ },
251
+ {
252
+ id: "rules",
253
+ query: `Find well-regarded community instruction/rule files (AGENTS.md snippets, cursor rules, agent guidelines) for: ${stackSummary}. Only include actively maintained sources.${querySuffix}`
254
+ },
255
+ {
256
+ id: "freshness",
257
+ query: `Find resources that cover APIs and SDK changes NEWER than typical LLM training data for: ${stackSummary} (release notes feeds, living changelogs, current API references).${querySuffix}`
258
+ }
259
+ ];
260
+ return tasks.slice(0, Math.max(0, maxQueries));
261
+ }
262
+ var CANDIDATE_QUERY_CHUNK_SIZE = 6;
263
+ var CANDIDATE_SEARCH_TASK_ID_PREFIX = "candidate-docs";
264
+ function evidenceClassPhrase(evidenceClass) {
265
+ switch (evidenceClass) {
266
+ case "env-template":
267
+ return "env key";
268
+ case "package":
269
+ return "package";
270
+ case "source":
271
+ return "source key";
272
+ case "script":
273
+ return "script key";
274
+ case "config":
275
+ return "config key";
276
+ case "hostname":
277
+ return "hostname";
278
+ }
279
+ }
280
+ function candidatePriorityRank(candidate) {
281
+ let best = CANDIDATE_SEARCH_PRIORITY.length;
282
+ for (const ev of candidate.evidence) {
283
+ const idx = CANDIDATE_SEARCH_PRIORITY.indexOf(ev.class);
284
+ if (idx !== -1 && idx < best) best = idx;
285
+ }
286
+ return best;
287
+ }
288
+ function renderCandidateEvidence(candidate) {
289
+ const seen = /* @__PURE__ */ new Set();
290
+ const hints = [];
291
+ const ordered = [...candidate.evidence].sort(
292
+ (a, b) => CANDIDATE_SEARCH_PRIORITY.indexOf(a.class) - CANDIDATE_SEARCH_PRIORITY.indexOf(b.class)
293
+ );
294
+ for (const ev of ordered) {
295
+ const querySafe = QUERY_SAFE_EVIDENCE_CLASSES.has(ev.class) || ev.class === "hostname" && isQuerySafeHostname(ev.matched.toLowerCase());
296
+ const hint = querySafe ? `${evidenceClassPhrase(ev.class)} ${ev.matched}` : evidenceClassPhrase(ev.class);
297
+ if (seen.has(hint)) continue;
298
+ seen.add(hint);
299
+ hints.push(hint);
300
+ }
301
+ const context = hints.length > 0 ? ` (${hints.join("; ")})` : "";
302
+ return `${candidate.token}${context}`;
303
+ }
304
+ function buildCandidateSearchTasks(candidates, maxQueries = DEFAULT_MAX_QUERIES, alreadyUsedQueries = 0) {
305
+ const remaining = Math.max(0, maxQueries - Math.max(0, alreadyUsedQueries));
306
+ const dispatchable = candidates.filter(isCandidateQuerySafe);
307
+ if (remaining === 0 || dispatchable.length === 0) {
308
+ return { tasks: [], coveredTokens: [] };
309
+ }
310
+ const ordered = [...dispatchable].sort(
311
+ (a, b) => candidatePriorityRank(a) - candidatePriorityRank(b)
312
+ );
313
+ const tasks = [];
314
+ const coveredTokens = [];
315
+ for (let chunkStart = 0; chunkStart < ordered.length; chunkStart += CANDIDATE_QUERY_CHUNK_SIZE) {
316
+ if (tasks.length >= remaining) break;
317
+ const chunk = ordered.slice(chunkStart, chunkStart + CANDIDATE_QUERY_CHUNK_SIZE);
318
+ const services = chunk.map(renderCandidateEvidence).join(", ");
319
+ tasks.push({
320
+ id: `${CANDIDATE_SEARCH_TASK_ID_PREFIX}:${chunk.map((c) => c.token).join("+")}`,
321
+ query: `The following external API services were detected in a codebase: ${services}. Find the OFFICIAL API documentation URL for each of these services; return one docs result per service.`
322
+ });
323
+ for (const c of chunk) coveredTokens.push(c.token);
324
+ }
325
+ return { tasks, coveredTokens };
326
+ }
327
+ async function dispatchCandidateSearch(tasks, options) {
328
+ if (tasks.length === 0) {
329
+ return { hits: [], allFailed: false, messages: [], queriesDispatched: 0 };
330
+ }
331
+ const timeoutMs = options.timeoutMs ?? DEFAULT_SEARCH_TIMEOUT_MS;
332
+ const policy = options.policy ?? DEFAULT_SOURCE_POLICY;
333
+ const messages = [];
334
+ const hitsByUrl = /* @__PURE__ */ new Map();
335
+ let failures = 0;
336
+ for (const task of tasks) {
337
+ let rows;
338
+ try {
339
+ rows = await withTimeout(
340
+ options.provider.search(task, { timeoutMs }),
341
+ timeoutMs,
342
+ `knowledge candidate search "${task.id}"`
343
+ );
344
+ } catch (error) {
345
+ failures += 1;
346
+ messages.push(
347
+ `Candidate search task "${task.id}" failed: ${error instanceof Error ? error.message : String(error)}`
348
+ );
349
+ continue;
350
+ }
351
+ for (const row of rows) {
352
+ const parsed = RawSearchResultSchema.safeParse(row);
353
+ if (!parsed.success) continue;
354
+ const raw = parsed.data;
355
+ if (raw.kind !== "docs") continue;
356
+ if (!isSourceAllowed(raw.sourceUrl, policy)) continue;
357
+ const host = hostnameOf(raw.sourceUrl);
358
+ if (!host) continue;
359
+ const dedupKey = slugForUrl(raw.sourceUrl);
360
+ if (hitsByUrl.has(dedupKey)) continue;
361
+ hitsByUrl.set(dedupKey, {
362
+ kind: raw.kind,
363
+ sourceUrl: raw.sourceUrl,
364
+ hostname: host,
365
+ trust: clampTrust(raw),
366
+ description: raw.description,
367
+ installHint: raw.installHint
368
+ });
369
+ }
370
+ }
371
+ return {
372
+ hits: Array.from(hitsByUrl.values()),
373
+ allFailed: failures === tasks.length,
374
+ messages,
375
+ queriesDispatched: tasks.length
376
+ };
377
+ }
378
+ var RawSearchResultSchema = z.object({
379
+ kind: z.enum(["mcp", "skill", "instructions", "docs"]),
380
+ sourceUrl: z.string().url(),
381
+ trust: z.enum(["official", "community", "third-party"]),
382
+ description: z.string().min(1),
383
+ installHint: z.string().min(1).optional()
384
+ });
385
+ var PROVIDER_RESPONSE_INSTRUCTIONS = [
386
+ "Respond with ONLY a JSON array (no prose, no code fence). Each element:",
387
+ '{"kind":"mcp"|"skill"|"instructions"|"docs","sourceUrl":"https://...","trust":"official"|"community"|"third-party","description":"one line","installHint":"exact command (optional)"}',
388
+ "Include at most 6 results. Only include resources you are confident currently exist.",
389
+ "Write each description as a neutral third-person line about the resource itself. Do not use first person, and do not add notes about what you checked or could not confirm; leave out a resource you cannot vouch for."
390
+ ].join("\n");
391
+ function extractJsonArray(text) {
392
+ const start = text.indexOf("[");
393
+ const end = text.lastIndexOf("]");
394
+ if (start === -1 || end <= start) return [];
395
+ try {
396
+ const parsed = JSON.parse(text.slice(start, end + 1));
397
+ return Array.isArray(parsed) ? parsed : [];
398
+ } catch {
399
+ return [];
400
+ }
401
+ }
402
+ function createAskSearchProvider(options) {
403
+ const ask = options.ask ?? runAsk;
404
+ return {
405
+ async search(task, { timeoutMs }) {
406
+ const result = await ask({
407
+ target: options.providerId,
408
+ question: `${task.query}
409
+
410
+ ${PROVIDER_RESPONSE_INSTRUCTIONS}`,
411
+ cwd: options.cwd,
412
+ timeoutMs
413
+ });
414
+ return extractJsonArray(result.answer);
415
+ }
416
+ };
417
+ }
418
+ var OFFLINE_FALLBACK_MESSAGE = "Knowledge search is unavailable (provider offline or unreachable). No recommendations were fetched; re-run when online, or add items manually.";
419
+ function withTimeout(promise, timeoutMs, label) {
420
+ return new Promise((resolvePromise, rejectPromise) => {
421
+ const timer = setTimeout(() => {
422
+ rejectPromise(new Error(`${label} timed out after ${timeoutMs}ms`));
423
+ }, timeoutMs);
424
+ promise.then(
425
+ (value) => {
426
+ clearTimeout(timer);
427
+ resolvePromise(value);
428
+ },
429
+ (error) => {
430
+ clearTimeout(timer);
431
+ rejectPromise(error);
432
+ }
433
+ );
434
+ });
435
+ }
436
+ function slugForUrl(url) {
437
+ const host = hostnameOf(url) ?? "unknown";
438
+ let pathname = "";
439
+ try {
440
+ pathname = new URL(url).pathname.replace(/\/+$/, "");
441
+ } catch {
442
+ }
443
+ return `${host}${pathname}`.toLowerCase();
444
+ }
445
+ function clampTrust(result) {
446
+ if (result.trust !== "official") return result.trust;
447
+ const host = hostnameOf(result.sourceUrl);
448
+ if (host && OFFICIAL_DOC_DOMAINS.some((suffix) => hostMatchesSuffix(host, suffix))) {
449
+ return "official";
450
+ }
451
+ return "community";
452
+ }
453
+ async function searchRecommendations(detection, options) {
454
+ const timeoutMs = options.timeoutMs ?? DEFAULT_SEARCH_TIMEOUT_MS;
455
+ const maxQueries = options.maxQueries ?? DEFAULT_MAX_QUERIES;
456
+ const policy = options.policy ?? DEFAULT_SOURCE_POLICY;
457
+ const tasks = buildSearchTasks(detection, maxQueries, options.userGuidance);
458
+ if (tasks.length === 0) {
459
+ return { status: "ok", items: [], messages: [], queriesDispatched: 0, failedTasks: 0 };
460
+ }
461
+ const messages = [];
462
+ const itemsById = /* @__PURE__ */ new Map();
463
+ let failures = 0;
464
+ for (const task of tasks) {
465
+ let rows;
466
+ try {
467
+ rows = await withTimeout(
468
+ options.provider.search(task, { timeoutMs }),
469
+ timeoutMs,
470
+ `knowledge search "${task.id}"`
471
+ );
472
+ } catch (error) {
473
+ failures += 1;
474
+ messages.push(
475
+ `Search task "${task.id}" failed: ${error instanceof Error ? error.message : String(error)}`
476
+ );
477
+ continue;
478
+ }
479
+ for (const row of rows) {
480
+ const parsed = RawSearchResultSchema.safeParse(row);
481
+ if (!parsed.success) continue;
482
+ const raw = parsed.data;
483
+ if (!isSourceAllowed(raw.sourceUrl, policy)) continue;
484
+ if (namesUndetectedFramework(raw, detection)) continue;
485
+ const trust = clampTrust(raw);
486
+ const id = `${raw.kind}:${slugForUrl(raw.sourceUrl)}`;
487
+ if (itemsById.has(id)) continue;
488
+ const candidate = KitItemSchema.safeParse({
489
+ id,
490
+ kind: raw.kind,
491
+ sourceUrl: raw.sourceUrl,
492
+ trust,
493
+ description: raw.description,
494
+ installHint: raw.installHint
495
+ });
496
+ if (candidate.success) itemsById.set(id, candidate.data);
497
+ }
498
+ }
499
+ if (failures === tasks.length) {
500
+ return {
501
+ status: "offline",
502
+ items: [],
503
+ messages: [OFFLINE_FALLBACK_MESSAGE, ...messages],
504
+ queriesDispatched: tasks.length,
505
+ failedTasks: tasks.length
506
+ };
507
+ }
508
+ return {
509
+ status: "ok",
510
+ items: Array.from(itemsById.values()),
511
+ messages,
512
+ queriesDispatched: tasks.length,
513
+ failedTasks: failures
514
+ };
515
+ }
516
+
517
+ // src/core/knowledge/apply.ts
518
+ import { lstatSync, readFileSync as readFileSync2 } from "fs";
519
+ import path2 from "path";
520
+
521
+ // src/core/knowledge/cache.ts
522
+ import { existsSync, readFileSync } from "fs";
523
+ import path from "path";
524
+ import { z as z2 } from "zod";
525
+ var DEFAULT_CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
526
+ var CACHE_DIR_NAME = "knowledge-cache";
527
+ var CacheEntrySchema = z2.object({
528
+ schemaVersion: z2.literal(1),
529
+ stackFingerprint: z2.string().min(1),
530
+ buildVersion: z2.string().min(1),
531
+ /** ISO timestamp the recommendations were fetched. */
532
+ fetchedAt: z2.string().min(1),
533
+ items: z2.array(KitItemSchema),
534
+ /** Human-facing notes captured with the fetch (partial-failure messages). */
535
+ messages: z2.array(z2.string()).default([]),
536
+ /**
537
+ * Exact-set signature of the service candidates present when this entry was
538
+ * cached ({@link candidateSetSignature}). Absent on legacy entries written
539
+ * before generalized service discovery — the offer layer treats a missing
540
+ * signature as a miss whenever the current detection has candidates (so a
541
+ * stale entry never hides newly discovered services). Never carries the
542
+ * unresolved-candidate list: an unresolved token is NOT a cacheable "no docs"
543
+ * answer, only the resolved candidate docs items are persisted (in `items`).
544
+ */
545
+ candidateSignature: z2.string().optional()
546
+ });
547
+ function resolveCacheDir(options) {
548
+ return options.cacheDir ?? path.join(getDefaultPaths().userConfigDir, CACHE_DIR_NAME);
549
+ }
550
+ function cacheKey(stackFingerprint, buildVersion) {
551
+ const safeVersion = buildVersion.replace(/[^A-Za-z0-9._-]/g, "_");
552
+ return `${stackFingerprint}-v${safeVersion}.json`;
553
+ }
554
+ function entryPath(options, fingerprint, version) {
555
+ return path.join(resolveCacheDir(options), cacheKey(fingerprint, version));
556
+ }
557
+ function readCachedRecommendations(stackFingerprint, options = {}) {
558
+ const buildVersion = resolveBuildVersion();
559
+ const filePath = entryPath(options, stackFingerprint, buildVersion);
560
+ if (!existsSync(filePath)) return void 0;
561
+ let parsed;
562
+ try {
563
+ parsed = JSON.parse(readFileSync(filePath, "utf8"));
564
+ } catch {
565
+ return void 0;
566
+ }
567
+ const result = CacheEntrySchema.safeParse(parsed);
568
+ if (!result.success) return void 0;
569
+ const entry = result.data;
570
+ if (entry.stackFingerprint !== stackFingerprint || entry.buildVersion !== buildVersion) {
571
+ return void 0;
572
+ }
573
+ const ttlMs = options.ttlMs ?? DEFAULT_CACHE_TTL_MS;
574
+ const now = (options.now?.() ?? /* @__PURE__ */ new Date()).getTime();
575
+ const fetchedAt = Date.parse(entry.fetchedAt);
576
+ if (!Number.isFinite(fetchedAt) || now - fetchedAt > ttlMs) return void 0;
577
+ return entry;
578
+ }
579
+ async function writeCachedRecommendations(stackFingerprint, items, messages = [], options = {}, candidateSignature) {
580
+ const buildVersion = resolveBuildVersion();
581
+ const entry = {
582
+ schemaVersion: 1,
583
+ stackFingerprint,
584
+ buildVersion,
585
+ fetchedAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
586
+ items,
587
+ messages,
588
+ // Only persisted when candidates existed at fetch time; a signature of ''
589
+ // (no candidates) is meaningful too (exact-set equality), so store it
590
+ // whenever the caller supplies one.
591
+ ...candidateSignature !== void 0 ? { candidateSignature } : {}
592
+ };
593
+ try {
594
+ await atomicWriteText(
595
+ entryPath(options, stackFingerprint, buildVersion),
596
+ JSON.stringify(entry, null, 2),
597
+ { ensureDir: true, trailingNewline: true }
598
+ );
599
+ } catch {
600
+ }
601
+ }
602
+ var LIBRARY_CACHE_DIR_NAME = "libraries";
603
+ var LibraryCacheEntrySchema = z2.object({
604
+ schemaVersion: z2.literal(1),
605
+ ecosystem: z2.string().min(1),
606
+ name: z2.string().min(1),
607
+ fetchedAt: z2.string().min(1),
608
+ item: KitItemSchema
609
+ });
610
+ function libraryEntryPath(options, ecosystem, name) {
611
+ const safe = name.replace(/[^a-z0-9.-]/g, (ch) => `%${ch.charCodeAt(0).toString(16)}`);
612
+ return path.join(resolveCacheDir(options), LIBRARY_CACHE_DIR_NAME, `${ecosystem}--${safe}.json`);
613
+ }
614
+ function readCachedLibraryDocs(ecosystem, name, options = {}) {
615
+ const filePath = libraryEntryPath(options, ecosystem, name);
616
+ if (!existsSync(filePath)) return void 0;
617
+ try {
618
+ const entry = LibraryCacheEntrySchema.parse(JSON.parse(readFileSync(filePath, "utf8")));
619
+ if (entry.ecosystem !== ecosystem || entry.name !== name) return void 0;
620
+ const now = (options.now?.() ?? /* @__PURE__ */ new Date()).getTime();
621
+ const fetchedAt = Date.parse(entry.fetchedAt);
622
+ if (!Number.isFinite(fetchedAt) || now - fetchedAt > (options.ttlMs ?? DEFAULT_CACHE_TTL_MS)) {
623
+ return void 0;
624
+ }
625
+ return entry.item;
626
+ } catch {
627
+ return void 0;
628
+ }
629
+ }
630
+ async function writeCachedLibraryDocs(ecosystem, name, item, options = {}) {
631
+ try {
632
+ await atomicWriteText(
633
+ libraryEntryPath(options, ecosystem, name),
634
+ JSON.stringify(
635
+ {
636
+ schemaVersion: 1,
637
+ ecosystem,
638
+ name,
639
+ fetchedAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
640
+ item
641
+ },
642
+ null,
643
+ 2
644
+ ),
645
+ { ensureDir: true, trailingNewline: true }
646
+ );
647
+ } catch {
648
+ }
649
+ }
650
+
651
+ // src/core/knowledge/candidate-matching.ts
652
+ function candidateTokenVariants(token) {
653
+ const lower = token.toLowerCase();
654
+ const variants = /* @__PURE__ */ new Set([
655
+ lower,
656
+ lower.replace(/_/g, "-"),
657
+ lower.replace(/-/g, "_"),
658
+ lower.replace(/[-_]/g, ""),
659
+ // Host-derived tokens hyphenate dots (data.sec.gov -> sec-gov); a docs hit
660
+ // on the ORIGINAL dotted domain (sec.gov) must still match (Codex P2).
661
+ lower.replace(/[-_]/g, ".")
662
+ ]);
663
+ return [...variants].filter((v) => v.length > 0);
664
+ }
665
+ function boundaryMatch(haystack, needle) {
666
+ let from = 0;
667
+ while (true) {
668
+ const at = haystack.indexOf(needle, from);
669
+ if (at === -1) return false;
670
+ const before = at === 0 ? "" : haystack[at - 1];
671
+ const afterIdx = at + needle.length;
672
+ const after = afterIdx >= haystack.length ? "" : haystack[afterIdx];
673
+ const isBoundary = (ch) => ch === "" || !/[a-z0-9]/.test(ch);
674
+ if (isBoundary(before) && isBoundary(after)) return true;
675
+ from = at + 1;
676
+ }
677
+ }
678
+ function hitMentionsToken(hit, token) {
679
+ const haystacks = [hit.hostname, hit.description.toLowerCase()];
680
+ return candidateTokenVariants(token).some((v) => haystacks.some((h) => boundaryMatch(h, v)));
681
+ }
682
+ function hitMatchesCandidate(hit, candidate) {
683
+ if (hitMentionsToken(hit, candidate.token)) return true;
684
+ const hitTail = registrableTail(hit.hostname);
685
+ if (!hitTail) return false;
686
+ return candidate.evidence.some(
687
+ (ev) => ev.class === "hostname" && registrableTail(ev.matched.toLowerCase()) === hitTail
688
+ );
689
+ }
690
+ var PUBLIC_SUFFIX_SECOND_LABELS = /* @__PURE__ */ new Set([
691
+ "co",
692
+ "com",
693
+ "org",
694
+ "net",
695
+ "gov",
696
+ "ac",
697
+ "edu"
698
+ ]);
699
+ function registrableTail(hostname) {
700
+ const labels = hostname.split(".").filter(Boolean);
701
+ if (labels.length < 2) return void 0;
702
+ const take = labels.length >= 3 && PUBLIC_SUFFIX_SECOND_LABELS.has(labels[labels.length - 2]) ? 3 : 2;
703
+ if (labels.length < take) return void 0;
704
+ return labels.slice(-take).join(".");
705
+ }
706
+
707
+ // src/core/knowledge/library-suggestions.ts
708
+ var LIBRARY_ITEM_ID_PREFIX = "docs:library:";
709
+ var REGISTRY_PHRASES = {
710
+ npm: "npm package",
711
+ pypi: "PyPI package",
712
+ go: "Go module",
713
+ cargo: "Rust crate",
714
+ maven: "Maven artifact",
715
+ nuget: "NuGet package",
716
+ rubygems: "Ruby gem",
717
+ packagist: "Composer package",
718
+ pub: "pub.dev package",
719
+ hex: "Hex package",
720
+ swiftpm: "Swift package"
721
+ };
722
+ function libraryToken(library) {
723
+ const tail = library.name.split(/[/:]/).pop() ?? library.name;
724
+ return tail.replace(/^@/, "");
725
+ }
726
+ function libraryNamespace(library) {
727
+ const segments = library.name.split("/");
728
+ let namespace;
729
+ if (library.ecosystem === "npm" && library.name.startsWith("@")) {
730
+ namespace = segments[0]?.slice(1);
731
+ } else if (library.ecosystem === "packagist" && segments.length === 2) {
732
+ namespace = segments[0];
733
+ } else if (library.ecosystem === "go" && segments.length >= 3) {
734
+ namespace = segments[segments.length - 2];
735
+ }
736
+ return namespace && namespace.length >= 2 ? namespace : void 0;
737
+ }
738
+ var COMMON_GROUP_PREFIXES = /* @__PURE__ */ new Set([
739
+ "com",
740
+ "org",
741
+ "io",
742
+ "net",
743
+ "edu",
744
+ "gov",
745
+ "dev",
746
+ "app",
747
+ "co",
748
+ "me",
749
+ "eu",
750
+ "uk",
751
+ "de"
752
+ ]);
753
+ function hitMatchesLibrary(hit, library) {
754
+ if (library.ecosystem === "maven") {
755
+ const group = library.name.split(":")[0] ?? "";
756
+ return hitMentionsToken(hit, library.name) || hitMentionsToken(hit, libraryToken(library)) && group.split(".").some((segment) => !COMMON_GROUP_PREFIXES.has(segment) && hitMentionsToken(hit, segment));
757
+ }
758
+ const namespace = libraryNamespace(library);
759
+ return hitMentionsToken(hit, libraryToken(library)) && (namespace === void 0 || hitMentionsToken(hit, namespace));
760
+ }
761
+ function libraryOwningHit(hit, covered) {
762
+ const matching = covered.filter((library) => hitMatchesLibrary(hit, library));
763
+ return matching.length === 1 ? matching[0] : void 0;
764
+ }
765
+ function libraryItemId(library) {
766
+ return `${LIBRARY_ITEM_ID_PREFIX}${library.ecosystem}:${library.name}`;
767
+ }
768
+ function buildLibrarySearchTasks(libraries, maxTasks) {
769
+ const tasks = [];
770
+ const covered = [];
771
+ for (let start = 0; start < libraries.length && tasks.length < maxTasks; ) {
772
+ const chunk = libraries.slice(start, start + CANDIDATE_QUERY_CHUNK_SIZE);
773
+ start += CANDIDATE_QUERY_CHUNK_SIZE;
774
+ const listed = chunk.map((lib) => `${lib.name} (${REGISTRY_PHRASES[lib.ecosystem]})`);
775
+ tasks.push({
776
+ id: `library-docs:${chunk.map((lib) => `${lib.ecosystem}/${lib.name}`).join("+")}`,
777
+ query: `The following public libraries are direct dependencies of a codebase: ${listed.join(", ")}. Find the OFFICIAL documentation URL for each of these libraries; return one docs result per library.`
778
+ });
779
+ covered.push(...chunk);
780
+ }
781
+ return { tasks, covered };
782
+ }
783
+ function itemForHit(library, hit) {
784
+ return {
785
+ id: libraryItemId(library),
786
+ kind: "docs",
787
+ sourceUrl: hit.sourceUrl,
788
+ trust: hit.trust,
789
+ description: `${library.name} \u2014 searched docs (${REGISTRY_PHRASES[library.ecosystem]} dependency)`
790
+ };
791
+ }
792
+ function uncachedLibraries(libraries, cache) {
793
+ return libraries.filter((lib) => !readCachedLibraryDocs(lib.ecosystem, lib.name, cache));
794
+ }
795
+ function libraryQueriesNeeded(detection, cache, isCi = isCiEnvironment) {
796
+ const libraries = detection.libraryCandidates ?? [];
797
+ if (libraries.length === 0 || isCi()) return 0;
798
+ return Math.ceil(uncachedLibraries(libraries, cache).length / CANDIDATE_QUERY_CHUNK_SIZE);
799
+ }
800
+ async function suggestLibraryDocs(options) {
801
+ const libraries = options.detection.libraryCandidates ?? [];
802
+ if (libraries.length === 0 || (options.isCi ?? isCiEnvironment)()) return [];
803
+ const taken = new Set(options.existingItems.map((item) => item.id));
804
+ const takenUrls = new Set(options.existingItems.map((item) => item.sourceUrl.toLowerCase()));
805
+ const accept = (item) => {
806
+ if (taken.has(item.id) || takenUrls.has(item.sourceUrl.toLowerCase())) return false;
807
+ taken.add(item.id);
808
+ takenUrls.add(item.sourceUrl.toLowerCase());
809
+ return true;
810
+ };
811
+ const offered = [];
812
+ const misses = uncachedLibraries(libraries, options.cache);
813
+ for (const library of libraries) {
814
+ const cached = readCachedLibraryDocs(library.ecosystem, library.name, options.cache);
815
+ if (cached && accept(cached)) offered.push(cached);
816
+ }
817
+ if (misses.length === 0 || !options.allowSearch || options.remainingQueries <= 0) {
818
+ return offered;
819
+ }
820
+ const { tasks, covered } = buildLibrarySearchTasks(misses, options.remainingQueries);
821
+ const search = await dispatchCandidateSearch(tasks, {
822
+ provider: options.provider,
823
+ timeoutMs: options.timeoutMs,
824
+ policy: options.policy ?? DEFAULT_SOURCE_POLICY
825
+ });
826
+ for (const library of covered) {
827
+ const hit = search.hits.find((candidate) => libraryOwningHit(candidate, covered) === library);
828
+ if (!hit) continue;
829
+ const item = itemForHit(library, hit);
830
+ await writeCachedLibraryDocs(library.ecosystem, library.name, item, options.cache);
831
+ if (accept(item)) offered.push(item);
832
+ }
833
+ return offered;
834
+ }
835
+
836
+ // src/core/knowledge/apply.ts
837
+ var DEGRADED_SEARCH_NOT_CACHED_MESSAGE = "Some search lanes failed or timed out; results were not cached and the next offer will search again.";
838
+ function curatedServiceItems(detection, policy) {
839
+ const items = [];
840
+ const seenTokens = /* @__PURE__ */ new Set();
841
+ for (const service of detection.detectedServices ?? []) {
842
+ if (service.confidence === "low") continue;
843
+ const signal = serviceSignalForToken(service.token);
844
+ if (!signal) continue;
845
+ if (!isSourceAllowed(signal.docsUrl, policy)) continue;
846
+ seenTokens.add(signal.token);
847
+ items.push({
848
+ id: `docs:service:${signal.token}`,
849
+ kind: "docs",
850
+ sourceUrl: signal.docsUrl,
851
+ trust: "official",
852
+ description: `${signal.description} (detected: ${service.evidence.join("+")})`
853
+ });
854
+ }
855
+ for (const candidate of serviceCandidatesOf(detection)) {
856
+ if (candidate.confidence !== "confirmed") continue;
857
+ if (seenTokens.has(candidate.token)) continue;
858
+ const signal = serviceSignalForToken(candidate.token);
859
+ if (!signal) continue;
860
+ if (!isSourceAllowed(signal.docsUrl, policy)) continue;
861
+ seenTokens.add(signal.token);
862
+ items.push({
863
+ id: `docs:service:${signal.token}`,
864
+ kind: "docs",
865
+ sourceUrl: signal.docsUrl,
866
+ trust: "official",
867
+ description: `${signal.description} (detected: ${candidateEvidenceClasses(candidate).join("+")})`
868
+ });
869
+ }
870
+ return items;
871
+ }
872
+ function normalizeUrlForDedup(url) {
873
+ try {
874
+ const parsed = new URL(url);
875
+ const pathname = parsed.pathname.replace(/\/+$/, "");
876
+ return `${parsed.protocol}//${parsed.host}${pathname}${parsed.search}`.toLowerCase();
877
+ } catch {
878
+ return url.trim().replace(/\/+$/, "").toLowerCase();
879
+ }
880
+ }
881
+ function mergeServiceItems(baseItems, serviceItems) {
882
+ if (serviceItems.length === 0) return baseItems;
883
+ const serviceUrls = new Set(serviceItems.map((item) => normalizeUrlForDedup(item.sourceUrl)));
884
+ const serviceIds = new Set(serviceItems.map((item) => item.id));
885
+ const merged = baseItems.filter(
886
+ (item) => !serviceIds.has(item.id) && !serviceUrls.has(normalizeUrlForDedup(item.sourceUrl))
887
+ );
888
+ return [...serviceItems, ...merged];
889
+ }
890
+ function serviceCandidatesOf(detection) {
891
+ return detection.serviceCandidates ?? [];
892
+ }
893
+ function candidateEvidenceClasses(candidate) {
894
+ const seen = /* @__PURE__ */ new Set();
895
+ const classes = [];
896
+ for (const ev of candidate.evidence) {
897
+ if (seen.has(ev.class)) continue;
898
+ seen.add(ev.class);
899
+ classes.push(ev.class);
900
+ }
901
+ return classes;
902
+ }
903
+ function candidateEvidenceStrings(candidate) {
904
+ const seen = /* @__PURE__ */ new Set();
905
+ const out = [];
906
+ for (const ev of candidate.evidence) {
907
+ const redact = ev.class === "source" || ev.class === "script";
908
+ const rendered = redact ? `${ev.class} key` : `${ev.class} ${ev.matched}`;
909
+ if (seen.has(rendered)) continue;
910
+ seen.add(rendered);
911
+ out.push(rendered);
912
+ }
913
+ return out;
914
+ }
915
+ function candidateResolvedByItems(token, items) {
916
+ const curatedId = `docs:service:${token}`;
917
+ const candidateId = `${CANDIDATE_ITEM_ID_PREFIX}${token}`;
918
+ if (items.some((item) => item.id === curatedId || item.id === candidateId)) return true;
919
+ const variants = candidateTokenVariants(token);
920
+ return items.some(
921
+ (item) => item.kind === "docs" && variants.some((v) => boundaryMatch(normalizeUrlForDedup(item.sourceUrl), v))
922
+ );
923
+ }
924
+ function unresolvedFrom(candidates, resolvingItems) {
925
+ const out = [];
926
+ for (const candidate of candidates) {
927
+ if (candidateResolvedByItems(candidate.token, resolvingItems)) continue;
928
+ out.push({ token: candidate.token, evidence: candidateEvidenceStrings(candidate) });
929
+ }
930
+ return out;
931
+ }
932
+ function attachCandidateHits(candidates, coveredTokens, hits, existingItems) {
933
+ const items = [];
934
+ const unresolved = [];
935
+ const seenIds = new Set(existingItems.map((item) => item.id));
936
+ const seenUrls = new Set(existingItems.map((item) => normalizeUrlForDedup(item.sourceUrl)));
937
+ for (const candidate of candidates) {
938
+ const token = candidate.token;
939
+ if (candidateResolvedByItems(token, existingItems)) continue;
940
+ const candidateItemId = `${CANDIDATE_ITEM_ID_PREFIX}${token}`;
941
+ if (seenIds.has(candidateItemId)) continue;
942
+ if (!coveredTokens.has(token)) {
943
+ unresolved.push({ token, evidence: candidateEvidenceStrings(candidate) });
944
+ continue;
945
+ }
946
+ const matching = hits.filter((hit) => hitMatchesCandidate(hit, candidate));
947
+ if (matching.length === 0) {
948
+ unresolved.push({ token, evidence: candidateEvidenceStrings(candidate) });
949
+ continue;
950
+ }
951
+ const pick = matching.find((hit) => !seenUrls.has(normalizeUrlForDedup(hit.sourceUrl)));
952
+ if (!pick) {
953
+ const resolvedByEmitted = candidateResolvedByItems(token, items);
954
+ if (!resolvedByEmitted) {
955
+ unresolved.push({ token, evidence: candidateEvidenceStrings(candidate) });
956
+ }
957
+ continue;
958
+ }
959
+ const item = {
960
+ id: candidateItemId,
961
+ kind: "docs",
962
+ sourceUrl: pick.sourceUrl,
963
+ trust: pick.trust,
964
+ description: `${token} \u2014 searched docs (detected via ${candidateEvidenceClasses(candidate).join(", ")})`
965
+ };
966
+ items.push(item);
967
+ seenIds.add(candidateItemId);
968
+ seenUrls.add(normalizeUrlForDedup(pick.sourceUrl));
969
+ }
970
+ return { items, unresolved };
971
+ }
972
+ function candidateSummaryMessage(candidateCount, unresolved) {
973
+ const resolved = candidateCount - unresolved.length;
974
+ let line = `Service discovery: ${resolved} resolved, ${unresolved.length} unresolved candidates.`;
975
+ if (unresolved.length > MAX_UNRESOLVED_LINES) {
976
+ const shown = unresolved.slice(0, MAX_UNRESOLVED_LINES).map((u) => u.token);
977
+ line += ` Unresolved: ${shown.join(", ")} +${unresolved.length - MAX_UNRESOLVED_LINES} more.`;
978
+ } else if (unresolved.length > 0) {
979
+ line += ` Unresolved: ${unresolved.map((u) => u.token).join(", ")}.`;
980
+ }
981
+ return line;
982
+ }
983
+ async function buildKitOffer(cwd, options) {
984
+ const detection = options.detection ?? detectStack(cwd);
985
+ const guidance = options.userGuidance?.trim() || void 0;
986
+ const policy = options.policy ?? DEFAULT_SOURCE_POLICY;
987
+ const maxQueries = options.maxQueries ?? DEFAULT_MAX_QUERIES;
988
+ const timeoutMs = options.timeoutMs ?? DEFAULT_SEARCH_TIMEOUT_MS;
989
+ const serviceItems = curatedServiceItems(detection, policy);
990
+ const candidates = serviceCandidatesOf(detection);
991
+ const currentSignature = candidateSetSignature(candidates);
992
+ const libraryOptions = {
993
+ detection,
994
+ provider: options.provider,
995
+ policy,
996
+ timeoutMs,
997
+ cache: options.cache,
998
+ remainingQueries: 0,
999
+ existingItems: [],
1000
+ allowSearch: false
1001
+ };
1002
+ if (!options.refresh && !guidance) {
1003
+ const cached = readCachedRecommendations(detection.fingerprint, options.cache);
1004
+ const signatureMatches = cached === void 0 ? false : cached.candidateSignature === void 0 ? candidates.length === 0 : cached.candidateSignature === currentSignature;
1005
+ if (cached && signatureMatches) {
1006
+ const stackItems2 = mergeServiceItems(cached.items, serviceItems);
1007
+ const unresolvedCandidates2 = unresolvedFrom(candidates, stackItems2);
1008
+ const items2 = [
1009
+ ...stackItems2,
1010
+ ...await suggestLibraryDocs({
1011
+ ...libraryOptions,
1012
+ allowSearch: false,
1013
+ existingItems: stackItems2
1014
+ })
1015
+ ];
1016
+ const messages2 = [
1017
+ `Recommendations from cache (fetched ${cached.fetchedAt}); use refresh to search again.`,
1018
+ ...cached.messages
1019
+ ];
1020
+ if (candidates.length > 0) {
1021
+ messages2.push(candidateSummaryMessage(candidates.length, unresolvedCandidates2));
1022
+ }
1023
+ return { detection, items: items2, source: "cache", offline: false, messages: messages2, unresolvedCandidates: unresolvedCandidates2 };
1024
+ }
1025
+ }
1026
+ const searchableCandidates = candidates.filter(
1027
+ (c) => c.confidence === "confirmed" && isCandidateQuerySafe(c) && !candidateResolvedByItems(c.token, serviceItems)
1028
+ );
1029
+ const candidateChunks = Math.ceil(searchableCandidates.length / CANDIDATE_QUERY_CHUNK_SIZE);
1030
+ const reservedForCandidates = maxQueries > 0 && candidateChunks > 0 ? Math.max(1, Math.min(Math.floor(maxQueries / 2), candidateChunks)) : 0;
1031
+ const reservedForLibraries = maxQueries > 1 ? Math.min(libraryQueriesNeeded(detection, options.cache), 1) : 0;
1032
+ const result = await searchRecommendations(detection, {
1033
+ provider: options.provider,
1034
+ timeoutMs,
1035
+ maxQueries: Math.max(
1036
+ maxQueries > 0 ? 1 : 0,
1037
+ maxQueries - reservedForCandidates - reservedForLibraries
1038
+ ),
1039
+ policy,
1040
+ userGuidance: guidance
1041
+ });
1042
+ if (result.status === "offline") {
1043
+ const unresolvedCandidates2 = unresolvedFrom(candidates, serviceItems);
1044
+ const offlineMessages = candidates.length > 0 ? [...result.messages, candidateSummaryMessage(candidates.length, unresolvedCandidates2)] : result.messages;
1045
+ if (serviceItems.length > 0) {
1046
+ return {
1047
+ detection,
1048
+ items: serviceItems,
1049
+ source: "search",
1050
+ offline: false,
1051
+ messages: offlineMessages,
1052
+ unresolvedCandidates: unresolvedCandidates2
1053
+ };
1054
+ }
1055
+ return {
1056
+ detection,
1057
+ items: [],
1058
+ source: "none",
1059
+ offline: true,
1060
+ messages: offlineMessages,
1061
+ unresolvedCandidates: unresolvedCandidates2
1062
+ };
1063
+ }
1064
+ const preResolvedItems = mergeServiceItems(result.items, serviceItems);
1065
+ const confirmedCandidates = candidates.filter(
1066
+ (c) => c.confidence === "confirmed" && !candidateResolvedByItems(c.token, preResolvedItems)
1067
+ );
1068
+ const { tasks: candidateTasks, coveredTokens } = buildCandidateSearchTasks(
1069
+ confirmedCandidates,
1070
+ maxQueries,
1071
+ result.queriesDispatched
1072
+ );
1073
+ const candidateSearch = await dispatchCandidateSearch(candidateTasks, {
1074
+ provider: options.provider,
1075
+ timeoutMs,
1076
+ policy
1077
+ });
1078
+ const baseItems = mergeServiceItems(result.items, serviceItems);
1079
+ const { items: candidateItems, unresolved: unresolvedCandidates } = attachCandidateHits(
1080
+ candidates,
1081
+ new Set(coveredTokens),
1082
+ candidateSearch.hits,
1083
+ baseItems
1084
+ );
1085
+ const stackItems = [...baseItems, ...candidateItems];
1086
+ const libraryItems = await suggestLibraryDocs({
1087
+ ...libraryOptions,
1088
+ allowSearch: !(candidateTasks.length > 0 && candidateSearch.allFailed),
1089
+ remainingQueries: maxQueries - result.queriesDispatched - candidateSearch.queriesDispatched,
1090
+ existingItems: stackItems
1091
+ });
1092
+ const items = [...stackItems, ...libraryItems];
1093
+ const messages = [...result.messages, ...candidateSearch.messages];
1094
+ if (candidates.length > 0) {
1095
+ messages.push(candidateSummaryMessage(candidates.length, unresolvedCandidates));
1096
+ }
1097
+ const candidateSearchDead = candidateTasks.length > 0 && candidateSearch.allFailed;
1098
+ if (candidateSearchDead && result.queriesDispatched === 0) {
1099
+ return {
1100
+ detection,
1101
+ items: mergeServiceItems([], serviceItems),
1102
+ source: serviceItems.length > 0 ? "search" : "none",
1103
+ offline: serviceItems.length === 0,
1104
+ messages,
1105
+ unresolvedCandidates
1106
+ };
1107
+ }
1108
+ const searchDegraded = result.failedTasks > 0 || candidateSearchDead;
1109
+ if (searchDegraded) {
1110
+ messages.push(DEGRADED_SEARCH_NOT_CACHED_MESSAGE);
1111
+ }
1112
+ if (!guidance && !searchDegraded) {
1113
+ const searchableTokens = new Set(
1114
+ candidates.filter((c) => c.confidence === "confirmed" && isCandidateQuerySafe(c)).map((c) => c.token)
1115
+ );
1116
+ const searchableUnresolved = unresolvedCandidates.filter(
1117
+ (u) => searchableTokens.has(u.token)
1118
+ ).length;
1119
+ const fullyCovered = !candidateSearchDead && searchableUnresolved === 0;
1120
+ await writeCachedRecommendations(
1121
+ detection.fingerprint,
1122
+ fullyCovered ? [...result.items, ...candidateItems] : result.items,
1123
+ result.messages,
1124
+ options.cache,
1125
+ fullyCovered ? currentSignature : void 0
1126
+ );
1127
+ }
1128
+ return {
1129
+ detection,
1130
+ items,
1131
+ source: "search",
1132
+ offline: false,
1133
+ messages,
1134
+ unresolvedCandidates
1135
+ };
1136
+ }
1137
+ var KNOWLEDGE_BLOCK_MARKERS = {
1138
+ begin: KNOWLEDGE_BLOCK_BEGIN,
1139
+ end: KNOWLEDGE_BLOCK_END
1140
+ };
1141
+ function safeHost(sourceUrl) {
1142
+ try {
1143
+ return new URL(sourceUrl).hostname;
1144
+ } catch {
1145
+ return "(invalid-url)";
1146
+ }
1147
+ }
1148
+ function renderKnowledgeBlock(items, updatedAt) {
1149
+ const lines = [
1150
+ KNOWLEDGE_BLOCK_BEGIN,
1151
+ "## Knowledge kit (managed by Build)",
1152
+ "",
1153
+ `Current stack resources accepted via \`build init\` (updated ${updatedAt}).`,
1154
+ "Do not edit inside this block \u2014 changes are overwritten on the next apply.",
1155
+ "Full source URLs live in .build-project/context/knowledge/manifest.json.",
1156
+ ""
1157
+ ];
1158
+ for (const item of items) {
1159
+ lines.push(
1160
+ `- [${item.trust}] ${item.kind}: ${safeHost(item.sourceUrl)} (${item.versionOrDate}, ${item.mode})`
1161
+ );
1162
+ }
1163
+ if (items.length === 0) {
1164
+ lines.push("- (no accepted items)");
1165
+ }
1166
+ lines.push(KNOWLEDGE_BLOCK_END);
1167
+ return lines.join("\n");
1168
+ }
1169
+ var PENDING_INTENT_MARKER = "A stack intent contract is declared for this repository";
1170
+ function renderPendingIntentBlock(dimensionCount) {
1171
+ const safeCount = Number.isFinite(dimensionCount) && dimensionCount > 0 ? Math.floor(dimensionCount) : 0;
1172
+ const dimensionsPhrase = safeCount === 1 ? "1 dimension" : `${safeCount} dimensions`;
1173
+ const lines = [
1174
+ KNOWLEDGE_BLOCK_BEGIN,
1175
+ "## Knowledge kit (managed by Build)",
1176
+ "",
1177
+ `${PENDING_INTENT_MARKER} (${dimensionsPhrase}), but no knowledge kit has been accepted yet.`,
1178
+ "Run `build init knowledge status` for details and `build init knowledge offer` to fetch curated resources.",
1179
+ "Do not edit inside this block \u2014 it is replaced automatically when a kit is accepted.",
1180
+ KNOWLEDGE_BLOCK_END
1181
+ ];
1182
+ return lines.join("\n");
1183
+ }
1184
+ function blockIsPendingIntent(existingContent) {
1185
+ const beginIndex = existingContent.indexOf(KNOWLEDGE_BLOCK_BEGIN);
1186
+ const endIndex = existingContent.indexOf(KNOWLEDGE_BLOCK_END);
1187
+ if (beginIndex === -1 || endIndex === -1 || endIndex < beginIndex) return false;
1188
+ const block = existingContent.slice(beginIndex, endIndex + KNOWLEDGE_BLOCK_END.length);
1189
+ return block.includes(PENDING_INTENT_MARKER);
1190
+ }
1191
+ function removeKnowledgeBlock(existingContent) {
1192
+ return removeManagedBlock(existingContent, KNOWLEDGE_BLOCK_MARKERS);
1193
+ }
1194
+ function upsertKnowledgeBlock(existingContent, block) {
1195
+ return upsertManagedBlock(existingContent, block, KNOWLEDGE_BLOCK_MARKERS);
1196
+ }
1197
+ function provenancePath(root, appliedAt) {
1198
+ const stamp = appliedAt.replace(/[:.]/g, "-");
1199
+ return path2.join(root, ".build-project", "provenance", `knowledge-apply-${stamp}.json`);
1200
+ }
1201
+ function trustNoteFor(item) {
1202
+ switch (item.trust) {
1203
+ case "official":
1204
+ return "Official vendor source.";
1205
+ case "community":
1206
+ return "Community-maintained source \u2014 review before installing.";
1207
+ default:
1208
+ return "THIRD-PARTY source \u2014 Build will not install this automatically; review the command and source before running it.";
1209
+ }
1210
+ }
1211
+ async function applyKit(offer, acceptedItemIds, options = {}) {
1212
+ const root = offer.detection.root;
1213
+ const now = options.now?.() ?? /* @__PURE__ */ new Date();
1214
+ const appliedAt = now.toISOString();
1215
+ const acceptedIds = new Set(acceptedItemIds);
1216
+ const unknownIds = acceptedItemIds.filter((id) => !offer.items.some((item) => item.id === id));
1217
+ if (unknownIds.length > 0) {
1218
+ throw new Error(`Accepted item ids not present in the offer: ${unknownIds.join(", ")}`);
1219
+ }
1220
+ const accepted = offer.items.filter((item) => acceptedIds.has(item.id)).map((item) => ({
1221
+ id: item.id,
1222
+ kind: item.kind,
1223
+ sourceUrl: item.sourceUrl,
1224
+ trust: item.trust,
1225
+ description: item.description,
1226
+ installHint: item.installHint,
1227
+ versionOrDate: appliedAt.slice(0, 10),
1228
+ mode: "online-ref"
1229
+ }));
1230
+ const prior = readKnowledgeManifest(root);
1231
+ let kitReplace;
1232
+ if (prior.status === "ok") {
1233
+ const priorIds = new Set(prior.manifest.items.map((item) => item.id));
1234
+ const newIds = new Set(accepted.map((item) => item.id));
1235
+ const isProperSubset = newIds.size < priorIds.size && [...newIds].every((id) => priorIds.has(id));
1236
+ if (isProperSubset) {
1237
+ kitReplace = {
1238
+ previousCount: priorIds.size,
1239
+ acceptedCount: newIds.size,
1240
+ droppedCount: priorIds.size - newIds.size
1241
+ };
1242
+ }
1243
+ }
1244
+ const agentsPath = path2.join(root, "AGENTS.md");
1245
+ let existing = "";
1246
+ try {
1247
+ const st = lstatSync(agentsPath);
1248
+ if (!st.isFile()) {
1249
+ throw new Error(
1250
+ "AGENTS.md is not a regular file (symlink or special); refusing to write through it."
1251
+ );
1252
+ }
1253
+ existing = readFileSync2(agentsPath, "utf8");
1254
+ } catch (error) {
1255
+ const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
1256
+ if (code !== "ENOENT") throw error;
1257
+ }
1258
+ const block = renderKnowledgeBlock(accepted, appliedAt.slice(0, 10));
1259
+ const updated = upsertKnowledgeBlock(existing, block);
1260
+ const filesTouched = [];
1261
+ if (updated !== existing) {
1262
+ await atomicWriteText(agentsPath, updated, { ensureDir: false });
1263
+ }
1264
+ filesTouched.push("AGENTS.md");
1265
+ const manifest = createManifest(offer.detection.fingerprint, accepted, now);
1266
+ await writeKnowledgeManifest(root, manifest);
1267
+ filesTouched.push(path2.relative(root, knowledgeManifestPath(root)));
1268
+ const installActions = offer.items.filter((item) => acceptedIds.has(item.id) && item.kind === "mcp" && item.installHint).map((item) => ({
1269
+ id: item.id,
1270
+ command: item.installHint,
1271
+ trustNote: trustNoteFor(item)
1272
+ }));
1273
+ const trustSummary = {};
1274
+ for (const item of accepted) {
1275
+ trustSummary[item.trust] = (trustSummary[item.trust] ?? 0) + 1;
1276
+ }
1277
+ const provenance = {
1278
+ kind: "knowledge-apply",
1279
+ schemaVersion: 1,
1280
+ appliedAt,
1281
+ buildVersion: resolveBuildVersion(),
1282
+ stackFingerprint: offer.detection.fingerprint,
1283
+ items: accepted.map((item) => ({
1284
+ id: item.id,
1285
+ kind: item.kind,
1286
+ sourceUrl: item.sourceUrl,
1287
+ trust: item.trust,
1288
+ versionOrDate: item.versionOrDate,
1289
+ mode: item.mode
1290
+ })),
1291
+ filesTouched: [...filesTouched],
1292
+ trustSummary
1293
+ };
1294
+ const provenanceFile = provenancePath(root, appliedAt);
1295
+ await atomicWriteText(provenanceFile, JSON.stringify(provenance, null, 2), {
1296
+ ensureDir: true,
1297
+ trailingNewline: true
1298
+ });
1299
+ filesTouched.push(path2.relative(root, provenanceFile));
1300
+ return {
1301
+ filesTouched,
1302
+ accepted,
1303
+ installActions,
1304
+ provenance,
1305
+ ...kitReplace ? { kitReplace } : {}
1306
+ };
1307
+ }
1308
+
1309
+ // src/core/knowledge/pending-notice.ts
1310
+ import { existsSync as existsSync2, readFileSync as readFileSync3, unlinkSync } from "fs";
1311
+ import path3 from "path";
1312
+ import { z as z3 } from "zod";
1313
+ var PENDING_OFFER_NOTICE_MESSAGE = "Knowledge kit: offer skipped (non-interactive session). Run build init knowledge offer for a headless offer, or re-run build init in a terminal.";
1314
+ var PendingOfferNoticeSchema = z3.object({
1315
+ schemaVersion: z3.literal(1),
1316
+ skippedAt: z3.string().min(1),
1317
+ cause: z3.union([z3.literal("non-interactive"), z3.literal("suppressed")]),
1318
+ message: z3.string().min(1)
1319
+ });
1320
+ function pendingOfferNoticePath(cwd) {
1321
+ return path3.join(cwd, ".build-project", "state", "knowledge", "pending-offer-notice.json");
1322
+ }
1323
+ function writePendingOfferNotice(cwd, cause) {
1324
+ const notice = {
1325
+ schemaVersion: 1,
1326
+ skippedAt: (/* @__PURE__ */ new Date()).toISOString(),
1327
+ cause,
1328
+ message: PENDING_OFFER_NOTICE_MESSAGE
1329
+ };
1330
+ try {
1331
+ atomicWriteJsonSync(pendingOfferNoticePath(cwd), notice);
1332
+ } catch {
1333
+ }
1334
+ }
1335
+ function readPendingOfferNotice(cwd) {
1336
+ const filePath = pendingOfferNoticePath(cwd);
1337
+ if (!existsSync2(filePath)) return void 0;
1338
+ try {
1339
+ const parsed = PendingOfferNoticeSchema.safeParse(JSON.parse(readFileSync3(filePath, "utf8")));
1340
+ if (!parsed.success) return void 0;
1341
+ return { ...parsed.data, message: PENDING_OFFER_NOTICE_MESSAGE };
1342
+ } catch {
1343
+ return void 0;
1344
+ }
1345
+ }
1346
+ function clearPendingOfferNotice(cwd) {
1347
+ try {
1348
+ unlinkSync(pendingOfferNoticePath(cwd));
1349
+ } catch {
1350
+ }
1351
+ }
1352
+
1353
+ // src/core/context/usage-block.ts
1354
+ import { readFileSync as readFileSync4 } from "fs";
1355
+ import path4 from "path";
1356
+ var USAGE_BLOCK_MARKERS = {
1357
+ begin: "<!-- build-usage:begin -->",
1358
+ end: "<!-- build-usage:end -->"
1359
+ };
1360
+ function sliceUsageBlock(template, markers = USAGE_BLOCK_MARKERS) {
1361
+ const begin = template.indexOf(markers.begin);
1362
+ const end = template.indexOf(markers.end);
1363
+ if (begin < 0 || end < begin) return void 0;
1364
+ return template.slice(begin, end + markers.end.length);
1365
+ }
1366
+ var WORK_TRACKING_MARKERS = {
1367
+ begin: "<!-- build-work-tracking:begin -->",
1368
+ end: "<!-- build-work-tracking:end -->"
1369
+ };
1370
+ function readPackagedUsageBlock(markers = USAGE_BLOCK_MARKERS) {
1371
+ try {
1372
+ const templatePath = path4.join(getPackageRoot(), "templates", "AGENTS.template.md");
1373
+ return sliceUsageBlock(readFileSync4(templatePath, "utf8"), markers);
1374
+ } catch {
1375
+ return void 0;
1376
+ }
1377
+ }
1378
+ var LEGACY_USAGE_HEADING = /^#{2,3} (?:Build Commands|Running Work Through Build)[ \t]*$/m;
1379
+ var LEGACY_USAGE_REASON = 'AGENTS.md already has an older Build guide without markers ("Build Commands", "Running Work Through Build"); delete those sections, then run build config context apply to install the current guide.';
1380
+ function hasLegacyUsageGuide(agentsContent) {
1381
+ return !agentsContent.includes(USAGE_BLOCK_MARKERS.begin) && LEGACY_USAGE_HEADING.test(agentsContent);
1382
+ }
1383
+ function upsertUsageBlock(agentsContent) {
1384
+ if (hasLegacyUsageGuide(agentsContent)) return agentsContent;
1385
+ const fragment = readPackagedUsageBlock();
1386
+ if (fragment === void 0) {
1387
+ throw new Error("Usage block missing from the packaged AGENTS template.");
1388
+ }
1389
+ return upsertManagedBlock(agentsContent, fragment, USAGE_BLOCK_MARKERS);
1390
+ }
1391
+ function installUsageBlockIfAbsent(agentsContent) {
1392
+ if (agentsContent.includes(USAGE_BLOCK_MARKERS.begin) || agentsContent.includes(USAGE_BLOCK_MARKERS.end)) {
1393
+ return agentsContent;
1394
+ }
1395
+ return upsertUsageBlock(agentsContent);
1396
+ }
1397
+
1398
+ // src/core/context/fabric.ts
1399
+ import { lstatSync as lstatSync3, readFileSync as readFileSync7 } from "fs";
1400
+ import path7 from "path";
1401
+
1402
+ // src/core/knowledge/actions.ts
1403
+ import { randomBytes } from "crypto";
1404
+ import { existsSync as existsSync3, lstatSync as lstatSync2, readdirSync, readFileSync as readFileSync5, unlinkSync as unlinkSync2 } from "fs";
1405
+ import path5 from "path";
1406
+ import { z as z4 } from "zod";
1407
+ var KNOWLEDGE_NEXT_ACTION_HINT = "Next: build init knowledge offer mints a review token; accept <token> all applies the kit.";
1408
+ var GRADUATION_ELIGIBLE_NO_MANIFEST_HINT = "Fully satisfied \u2014 run build init knowledge offer, then accept <token> all to apply the kit, then graduate <token> (or build init interactively).";
1409
+ var GRADUATION_ELIGIBLE_HINT = "Fully satisfied \u2014 run build init knowledge offer, then accept <token> all, then graduate <token> (or build init interactively).";
1410
+ function knowledgeStatus(cwd) {
1411
+ const detection = detectStack(cwd);
1412
+ const stored = readIntentContract(cwd);
1413
+ let contract;
1414
+ let effective = detection;
1415
+ if (stored.status === "absent") {
1416
+ contract = { status: "absent" };
1417
+ } else if (stored.status === "invalid") {
1418
+ contract = { status: "invalid", error: stored.error };
1419
+ } else if (stored.contract.status === "retired") {
1420
+ contract = {
1421
+ status: "ok",
1422
+ spec: stored.contract.spec,
1423
+ declaredAt: stored.contract.declaredAt,
1424
+ ...stored.contract.rationale ? { rationale: stored.contract.rationale } : {},
1425
+ contractStatus: "retired",
1426
+ dimensions: stored.contract.dimensions.map(describeDim),
1427
+ conflicts: [],
1428
+ graduationEligible: false
1429
+ };
1430
+ } else {
1431
+ const resolution = resolveIntent(detection, stored.contract);
1432
+ effective = resolution.effective;
1433
+ contract = {
1434
+ status: "ok",
1435
+ spec: stored.contract.spec,
1436
+ declaredAt: stored.contract.declaredAt,
1437
+ ...stored.contract.rationale ? { rationale: stored.contract.rationale } : {},
1438
+ contractStatus: resolution.contract.status,
1439
+ dimensions: resolution.contract.dimensions.map(describeDim),
1440
+ conflicts: resolution.conflicts.map((c) => ({
1441
+ token: c.dimension.token,
1442
+ detectedToken: c.detectedToken
1443
+ })),
1444
+ graduationEligible: isGraduationEligible(resolution)
1445
+ };
1446
+ }
1447
+ const manifestResult = readKnowledgeManifest(cwd);
1448
+ let manifest;
1449
+ if (manifestResult.status === "absent") {
1450
+ manifest = { status: "absent" };
1451
+ } else if (manifestResult.status === "invalid") {
1452
+ manifest = { status: "invalid", error: manifestResult.error };
1453
+ } else {
1454
+ manifest = {
1455
+ status: "ok",
1456
+ stackFingerprint: manifestResult.manifest.stackFingerprint,
1457
+ itemCount: manifestResult.manifest.items.length,
1458
+ updatedAt: manifestResult.manifest.updatedAt,
1459
+ drifted: manifestResult.manifest.stackFingerprint !== effective.fingerprint
1460
+ };
1461
+ }
1462
+ const liveNoManifest = contract.status === "ok" && contract.contractStatus !== "retired" && manifest.status === "absent";
1463
+ const graduationGuidance = contract.status === "ok" && contract.graduationEligible ? manifest.status === "absent" ? GRADUATION_ELIGIBLE_NO_MANIFEST_HINT : GRADUATION_ELIGIBLE_HINT : void 0;
1464
+ return {
1465
+ detection: {
1466
+ languages: detection.languages.filter((l) => l !== "unknown" && l !== "docs"),
1467
+ frameworks: detection.frameworks,
1468
+ sdkTargets: detection.sdkTargets,
1469
+ tools: detection.tools ?? [],
1470
+ domains: detection.domains ?? [],
1471
+ fingerprint: detection.fingerprint
1472
+ },
1473
+ contract,
1474
+ manifest,
1475
+ ...liveNoManifest ? { nextAction: KNOWLEDGE_NEXT_ACTION_HINT } : {},
1476
+ ...graduationGuidance ? { graduationGuidance } : {}
1477
+ };
1478
+ }
1479
+ function computeKnowledgeProjection(cwd, existingContent) {
1480
+ const manifestResult = readKnowledgeManifest(cwd);
1481
+ if (manifestResult.status === "ok") {
1482
+ const block = renderKnowledgeBlock(
1483
+ manifestResult.manifest.items,
1484
+ manifestResult.manifest.updatedAt.slice(0, 10)
1485
+ );
1486
+ return { kind: "upsert", block };
1487
+ }
1488
+ if (manifestResult.status === "invalid") {
1489
+ return { kind: "none" };
1490
+ }
1491
+ const stored = readIntentContract(cwd);
1492
+ const liveContract = stored.status === "ok" && stored.contract.status !== "retired" ? stored.contract : void 0;
1493
+ if (liveContract) {
1494
+ const resolved = resolveIntent(detectStack(cwd), liveContract).contract;
1495
+ const liveDimensions = resolved.dimensions.filter((d) => d.status !== "retired").length;
1496
+ return { kind: "upsert", block: renderPendingIntentBlock(liveDimensions) };
1497
+ }
1498
+ if (blockIsPendingIntent(existingContent)) {
1499
+ return { kind: "remove" };
1500
+ }
1501
+ return { kind: "none" };
1502
+ }
1503
+ function describeDim(dim) {
1504
+ return {
1505
+ token: dim.token,
1506
+ dimension: dim.dimension,
1507
+ status: dim.status,
1508
+ ...dim.conflict ? { conflict: dim.conflict } : {}
1509
+ };
1510
+ }
1511
+ function isGraduationEligible(resolution) {
1512
+ const hasSatisfiedDim = resolution.contract.dimensions.some((d) => d.status === "satisfied");
1513
+ return resolution.allSatisfied && (hasSatisfiedDim || resolution.allCovered);
1514
+ }
1515
+ function effectiveDetection(cwd) {
1516
+ migrateLegacyDeclaration(cwd);
1517
+ const detection = detectStack(cwd);
1518
+ const stored = readIntentContract(cwd);
1519
+ if (stored.status !== "ok" || stored.contract.status === "retired") {
1520
+ return detection;
1521
+ }
1522
+ return resolveIntent(detection, stored.contract).effective;
1523
+ }
1524
+ function syncPendingIntentBlock(cwd) {
1525
+ try {
1526
+ const agentsPath = path5.join(cwd, "AGENTS.md");
1527
+ if (!existsSync3(agentsPath) || !lstatSync2(agentsPath).isFile()) {
1528
+ return;
1529
+ }
1530
+ if (readKnowledgeManifest(cwd).status !== "absent") return;
1531
+ const stored = readIntentContract(cwd);
1532
+ const liveContract = stored.status === "ok" && stored.contract.status !== "retired" ? stored.contract : void 0;
1533
+ const existing = readFileSync5(agentsPath, "utf8");
1534
+ if (liveContract) {
1535
+ const resolved = resolveIntent(detectStack(cwd), liveContract).contract;
1536
+ const liveDimensions = resolved.dimensions.filter((d) => d.status !== "retired").length;
1537
+ const block = renderPendingIntentBlock(liveDimensions);
1538
+ const updated = upsertKnowledgeBlock(existing, block);
1539
+ if (updated !== existing) {
1540
+ atomicWriteTextSync(agentsPath, updated, { ensureDir: false });
1541
+ }
1542
+ return;
1543
+ }
1544
+ if (blockIsPendingIntent(existing)) {
1545
+ const updated = removeKnowledgeBlock(existing);
1546
+ if (updated !== existing) {
1547
+ atomicWriteTextSync(agentsPath, updated, { ensureDir: false });
1548
+ }
1549
+ }
1550
+ } catch {
1551
+ }
1552
+ }
1553
+ function declareIntent(cwd, spec, reason) {
1554
+ const parsed = parseIntentSpec(spec);
1555
+ if (!parsed.ok) {
1556
+ return { ok: false, error: parsed.error };
1557
+ }
1558
+ try {
1559
+ unlinkSync2(legacyDeclaredStackPath(cwd));
1560
+ } catch {
1561
+ }
1562
+ const candidate = createIntentContract(spec, parsed.tokens, { rationale: reason });
1563
+ const detection = detectStack(cwd);
1564
+ const probe = resolveIntent(detection, candidate);
1565
+ if (probe.allCovered) {
1566
+ removeIntentContract(cwd);
1567
+ syncPendingIntentBlock(cwd);
1568
+ return { ok: true, outcome: "covered", spec, conflicts: [] };
1569
+ }
1570
+ writeIntentContract(cwd, probe.contract);
1571
+ syncPendingIntentBlock(cwd);
1572
+ return {
1573
+ ok: true,
1574
+ outcome: "stored",
1575
+ spec,
1576
+ conflicts: probe.conflicts.map((c) => ({
1577
+ token: c.dimension.token,
1578
+ detectedToken: c.detectedToken
1579
+ }))
1580
+ };
1581
+ }
1582
+ function clearIntent(cwd) {
1583
+ const stored = readIntentContract(cwd);
1584
+ let cleared = false;
1585
+ if (stored.status !== "absent") {
1586
+ removeIntentContract(cwd);
1587
+ cleared = true;
1588
+ }
1589
+ try {
1590
+ unlinkSync2(legacyDeclaredStackPath(cwd));
1591
+ cleared = true;
1592
+ } catch {
1593
+ }
1594
+ syncPendingIntentBlock(cwd);
1595
+ return { cleared };
1596
+ }
1597
+ function resolveConflicts(cwd, choice) {
1598
+ const stored = readIntentContract(cwd);
1599
+ if (stored.status === "absent") {
1600
+ return { ok: false, error: "No stack intent contract to resolve conflicts on." };
1601
+ }
1602
+ if (stored.status === "invalid") {
1603
+ return {
1604
+ ok: false,
1605
+ error: `Stack intent contract is invalid (${stored.error}); re-declare or clear it first.`
1606
+ };
1607
+ }
1608
+ const resolution = resolveIntent(detectStack(cwd), stored.contract);
1609
+ const pending = resolution.conflicts.length;
1610
+ if (pending === 0) {
1611
+ return { ok: false, error: "No pending conflicts to resolve." };
1612
+ }
1613
+ const updated = choice === "keep" ? acknowledgeConflicts(resolution.contract) : acceptDetectedReality(resolution.contract);
1614
+ writeIntentContract(cwd, updated);
1615
+ syncPendingIntentBlock(cwd);
1616
+ return { ok: true, resolvedCount: pending, choice };
1617
+ }
1618
+ function pendingOffersDir(cwd) {
1619
+ return path5.join(cwd, ".build-project", "state", "knowledge", "pending-offers");
1620
+ }
1621
+ var PENDING_OFFER_TTL_MS = 60 * 60 * 1e3;
1622
+ var PendingOfferSchema = z4.object({
1623
+ schemaVersion: z4.literal(1),
1624
+ token: z4.string().min(1),
1625
+ /** Repo root the offer was built for (guards cross-repo token reuse). */
1626
+ root: z4.string().min(1),
1627
+ stackFingerprint: z4.string().min(1),
1628
+ guidance: z4.string().optional(),
1629
+ createdAt: z4.string().min(1),
1630
+ /** True when search was unavailable — an offline offer NEVER counts as a review. */
1631
+ offline: z4.boolean(),
1632
+ items: z4.array(KitItemSchema),
1633
+ messages: z4.array(z4.string()),
1634
+ /** Set by acceptOffer; a consumed offer still gates graduation until TTL. */
1635
+ consumedAt: z4.string().optional()
1636
+ });
1637
+ var TOKEN_PATTERN = /^[a-f0-9]{32}$/;
1638
+ function pendingOfferPath(cwd, token) {
1639
+ return path5.join(pendingOffersDir(cwd), `${token}.json`);
1640
+ }
1641
+ function readPendingOffer(cwd, token) {
1642
+ if (!TOKEN_PATTERN.test(token)) return void 0;
1643
+ const filePath = pendingOfferPath(cwd, token);
1644
+ if (!existsSync3(filePath)) return void 0;
1645
+ try {
1646
+ const parsed = PendingOfferSchema.safeParse(JSON.parse(readFileSync5(filePath, "utf8")));
1647
+ return parsed.success ? parsed.data : void 0;
1648
+ } catch {
1649
+ return void 0;
1650
+ }
1651
+ }
1652
+ function offerExpired(offer, now) {
1653
+ const created = Date.parse(offer.createdAt);
1654
+ return !Number.isFinite(created) || now.getTime() - created > PENDING_OFFER_TTL_MS;
1655
+ }
1656
+ function cleanupExpiredOffers(cwd, now) {
1657
+ const dir = pendingOffersDir(cwd);
1658
+ let entries;
1659
+ try {
1660
+ entries = readdirSync(dir);
1661
+ } catch {
1662
+ return;
1663
+ }
1664
+ for (const entry of entries) {
1665
+ if (!entry.endsWith(".json")) continue;
1666
+ const token = entry.slice(0, -".json".length);
1667
+ if (!TOKEN_PATTERN.test(token)) continue;
1668
+ const offer = readPendingOffer(cwd, token);
1669
+ if (!offer || offerExpired(offer, now)) {
1670
+ try {
1671
+ unlinkSync2(path5.join(dir, entry));
1672
+ } catch {
1673
+ }
1674
+ }
1675
+ }
1676
+ }
1677
+ async function createOffer(cwd, options) {
1678
+ const now = options.now?.() ?? /* @__PURE__ */ new Date();
1679
+ cleanupExpiredOffers(cwd, now);
1680
+ const offer = await buildKitOffer(cwd, {
1681
+ provider: options.provider,
1682
+ cache: options.cache,
1683
+ refresh: options.refresh,
1684
+ userGuidance: options.guidance,
1685
+ detection: effectiveDetection(cwd)
1686
+ });
1687
+ if (offer.offline) {
1688
+ return {
1689
+ offline: true,
1690
+ source: offer.source,
1691
+ items: [],
1692
+ messages: offer.messages,
1693
+ detectionFingerprint: offer.detection.fingerprint
1694
+ };
1695
+ }
1696
+ const token = randomBytes(16).toString("hex");
1697
+ const pending = {
1698
+ schemaVersion: 1,
1699
+ token,
1700
+ root: offer.detection.root,
1701
+ stackFingerprint: offer.detection.fingerprint,
1702
+ ...options.guidance ? { guidance: options.guidance } : {},
1703
+ createdAt: now.toISOString(),
1704
+ offline: false,
1705
+ items: offer.items,
1706
+ messages: offer.messages
1707
+ };
1708
+ await atomicWriteJson(pendingOfferPath(cwd, token), pending);
1709
+ clearPendingOfferNotice(cwd);
1710
+ return {
1711
+ token,
1712
+ offline: false,
1713
+ source: offer.source,
1714
+ items: offer.items,
1715
+ messages: offer.messages,
1716
+ detectionFingerprint: offer.detection.fingerprint
1717
+ };
1718
+ }
1719
+ async function acceptOffer(cwd, token, itemIds, options = {}) {
1720
+ const now = options.now?.() ?? /* @__PURE__ */ new Date();
1721
+ const pending = readPendingOffer(cwd, token);
1722
+ if (!pending) {
1723
+ return { ok: false, error: "Unknown or malformed offer token; run knowledge offer again." };
1724
+ }
1725
+ if (path5.resolve(pending.root) !== path5.resolve(cwd)) {
1726
+ return {
1727
+ ok: false,
1728
+ error: "Offer token was minted for a different repository root; run knowledge offer again."
1729
+ };
1730
+ }
1731
+ if (pending.consumedAt) {
1732
+ return { ok: false, error: "Offer already accepted; run knowledge offer again for a new one." };
1733
+ }
1734
+ if (offerExpired(pending, now)) {
1735
+ return { ok: false, error: "Offer expired; run knowledge offer again." };
1736
+ }
1737
+ const detection = effectiveDetection(cwd);
1738
+ if (detection.fingerprint !== pending.stackFingerprint) {
1739
+ return {
1740
+ ok: false,
1741
+ error: "The effective stack changed since the offer was created; run knowledge offer again."
1742
+ };
1743
+ }
1744
+ const acceptedIds = itemIds === "all" ? pending.items.map((item) => item.id) : itemIds;
1745
+ if (acceptedIds.length === 0) {
1746
+ if (itemIds === "all" && pending.items.length === 0) {
1747
+ await atomicWriteJson(pendingOfferPath(cwd, token), {
1748
+ ...pending,
1749
+ consumedAt: now.toISOString()
1750
+ });
1751
+ return {
1752
+ ok: true,
1753
+ applied: {
1754
+ filesTouched: [],
1755
+ accepted: [],
1756
+ installActions: [],
1757
+ provenance: {
1758
+ kind: "knowledge-apply",
1759
+ schemaVersion: 1,
1760
+ appliedAt: now.toISOString(),
1761
+ buildVersion: resolveBuildVersion(),
1762
+ stackFingerprint: pending.stackFingerprint,
1763
+ items: [],
1764
+ filesTouched: [],
1765
+ trustSummary: {}
1766
+ }
1767
+ }
1768
+ };
1769
+ }
1770
+ return { ok: false, error: "No items selected; pass item ids or all." };
1771
+ }
1772
+ const offer = {
1773
+ detection,
1774
+ items: pending.items,
1775
+ source: "cache",
1776
+ offline: false,
1777
+ messages: pending.messages
1778
+ };
1779
+ let applied;
1780
+ try {
1781
+ applied = await applyKit(offer, acceptedIds, { now: () => now });
1782
+ } catch (error) {
1783
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
1784
+ }
1785
+ await atomicWriteJson(pendingOfferPath(cwd, token), {
1786
+ ...pending,
1787
+ consumedAt: now.toISOString()
1788
+ });
1789
+ return { ok: true, applied };
1790
+ }
1791
+ async function graduateIntent(cwd, token, options = {}) {
1792
+ const now = options.now?.() ?? /* @__PURE__ */ new Date();
1793
+ const pending = readPendingOffer(cwd, token);
1794
+ if (!pending || pending.offline) {
1795
+ return {
1796
+ ok: false,
1797
+ error: "Graduation requires a token from a successful knowledge offer that has been accepted; run knowledge offer, then accept, then graduate."
1798
+ };
1799
+ }
1800
+ if (path5.resolve(pending.root) !== path5.resolve(cwd)) {
1801
+ return {
1802
+ ok: false,
1803
+ error: "Offer token was minted for a different repository root; run knowledge offer again."
1804
+ };
1805
+ }
1806
+ if (offerExpired(pending, now)) {
1807
+ return { ok: false, error: "Offer token expired; run knowledge offer again." };
1808
+ }
1809
+ migrateLegacyDeclaration(cwd);
1810
+ const stored = readIntentContract(cwd);
1811
+ if (stored.status === "absent") {
1812
+ return { ok: false, error: "No stack intent contract to graduate." };
1813
+ }
1814
+ if (stored.status === "invalid") {
1815
+ return {
1816
+ ok: false,
1817
+ error: `Stack intent contract is invalid (${stored.error}); re-declare or clear it first.`
1818
+ };
1819
+ }
1820
+ if (stored.contract.status === "retired") {
1821
+ return { ok: false, error: "Stack intent contract is already retired." };
1822
+ }
1823
+ const detection = detectStack(cwd);
1824
+ const resolution = resolveIntent(detection, stored.contract, { now: () => now });
1825
+ if (resolution.effective.fingerprint !== pending.stackFingerprint) {
1826
+ return {
1827
+ ok: false,
1828
+ error: "The effective stack changed since the offer was created; run knowledge offer again before graduating."
1829
+ };
1830
+ }
1831
+ if (!isGraduationEligible(resolution)) {
1832
+ const unsatisfied = resolution.contract.dimensions.filter(
1833
+ (d) => d.status !== "satisfied" && d.status !== "retired" && !(d.status === "conflict" && d.conflict?.acknowledged === true)
1834
+ ).map((d) => d.token);
1835
+ return {
1836
+ ok: false,
1837
+ error: `Stack intent "${stored.contract.spec}" is not fully satisfied yet (pending: ${unsatisfied.join(", ") || "evidence of detection catch-up"}).`
1838
+ };
1839
+ }
1840
+ if (!pending.consumedAt) {
1841
+ return {
1842
+ ok: false,
1843
+ error: "Graduation requires the offer to be accepted first; run build init knowledge accept <token> all, then graduate."
1844
+ };
1845
+ }
1846
+ const manifestResult = readKnowledgeManifest(cwd);
1847
+ if (pending.items.length > 0) {
1848
+ if (manifestResult.status === "absent") {
1849
+ return {
1850
+ ok: false,
1851
+ error: "Graduation requires an accepted knowledge kit (manifest missing); run build init knowledge accept <token> all, then graduate."
1852
+ };
1853
+ }
1854
+ if (manifestResult.status === "invalid") {
1855
+ return {
1856
+ ok: false,
1857
+ error: `Knowledge manifest is invalid (${manifestResult.error}); re-run build init knowledge accept before graduating.`
1858
+ };
1859
+ }
1860
+ }
1861
+ let manifestReconfirmed = false;
1862
+ const effectiveFingerprint = resolution.effective.fingerprint;
1863
+ if (manifestResult.status === "ok" && manifestResult.manifest.stackFingerprint !== effectiveFingerprint) {
1864
+ const reconfirmed = {
1865
+ ...manifestResult.manifest,
1866
+ stackFingerprint: effectiveFingerprint,
1867
+ updatedAt: now.toISOString()
1868
+ };
1869
+ await writeKnowledgeManifest(cwd, reconfirmed);
1870
+ manifestReconfirmed = true;
1871
+ }
1872
+ writeIntentContract(cwd, retireContract(resolution.contract, { now: () => now }));
1873
+ try {
1874
+ unlinkSync2(pendingOfferPath(cwd, token));
1875
+ } catch {
1876
+ }
1877
+ syncPendingIntentBlock(cwd);
1878
+ return { ok: true, spec: stored.contract.spec, manifestReconfirmed };
1879
+ }
1880
+
1881
+ // src/core/context/service/render-service-block.ts
1882
+ var SERVICE_BLOCK_MARKERS = {
1883
+ begin: "<!-- build-context-service:begin -->",
1884
+ end: "<!-- build-context-service:end -->"
1885
+ };
1886
+ var KNOWN_MANAGED_BLOCK_MARKERS = [
1887
+ SERVICE_BLOCK_MARKERS.begin,
1888
+ SERVICE_BLOCK_MARKERS.end,
1889
+ STACK_BLOCK_MARKERS.begin,
1890
+ STACK_BLOCK_MARKERS.end,
1891
+ PURPOSE_BLOCK_MARKERS.begin,
1892
+ PURPOSE_BLOCK_MARKERS.end,
1893
+ KNOWLEDGE_BLOCK_BEGIN,
1894
+ KNOWLEDGE_BLOCK_END,
1895
+ USAGE_BLOCK_MARKERS.begin,
1896
+ USAGE_BLOCK_MARKERS.end
1897
+ ];
1898
+ function fragmentEmbedsManagedMarker(fragment, ownMarkers) {
1899
+ let interior = fragment;
1900
+ if (interior.startsWith(ownMarkers.begin)) {
1901
+ interior = interior.slice(ownMarkers.begin.length);
1902
+ }
1903
+ if (interior.endsWith(ownMarkers.end)) {
1904
+ interior = interior.slice(0, interior.length - ownMarkers.end.length);
1905
+ }
1906
+ return KNOWN_MANAGED_BLOCK_MARKERS.some((marker) => interior.includes(marker));
1907
+ }
1908
+ function renderServiceContextBlock(entries) {
1909
+ const lines = ["## Service context (managed by Build)", ""];
1910
+ const inlined = entries.filter((entry) => entry.inline);
1911
+ if (inlined.length === 0) {
1912
+ lines.push("No inlined service context entries.");
1913
+ } else {
1914
+ for (const entry of inlined) {
1915
+ lines.push(`### ${entry.title}`);
1916
+ lines.push(`Source: ${entry.source} (captured ${entry.capturedAt})`);
1917
+ lines.push("");
1918
+ lines.push(entry.body.replace(/\s+$/, ""));
1919
+ lines.push("");
1920
+ }
1921
+ }
1922
+ lines.push(
1923
+ "Do not edit inside this block \u2014 it is regenerated by `build config context apply`. Entries live in .build-project/context/service/."
1924
+ );
1925
+ return lines.join("\n");
1926
+ }
1927
+ function renderServiceBlockFragment(entries) {
1928
+ const content = renderServiceContextBlock(entries);
1929
+ if (KNOWN_MANAGED_BLOCK_MARKERS.some((marker) => content.includes(marker))) {
1930
+ throw new Error(
1931
+ "Service block content contains a managed-block marker string; refusing to render a self-corrupting block."
1932
+ );
1933
+ }
1934
+ return [SERVICE_BLOCK_MARKERS.begin, content, SERVICE_BLOCK_MARKERS.end].join("\n");
1935
+ }
1936
+
1937
+ // src/core/context/service/store.ts
1938
+ import { randomBytes as randomBytes2 } from "crypto";
1939
+ import { existsSync as existsSync4, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
1940
+ import { link, mkdir, unlink, writeFile } from "fs/promises";
1941
+ import path6 from "path";
1942
+ import * as YAML from "yaml";
1943
+
1944
+ // src/core/context/service/schema.ts
1945
+ import { z as z5 } from "zod";
1946
+ var ServiceEntryFrontmatterSchema = z5.object({
1947
+ /**
1948
+ * Slug id; MUST equal the filename stem AND satisfy the finite-grammar
1949
+ * identifier — the same grammar the id is derived under. A hand-edited entry
1950
+ * whose id is prose (e.g. `ignore previous instructions`) fails here and is
1951
+ * skipped, so it can never be surfaced or inlined.
1952
+ */
1953
+ id: z5.string().min(1).refine(isSafeStackIdentifier, {
1954
+ message: "id must be a finite-grammar-safe identifier"
1955
+ }),
1956
+ /** Human title of the entry. */
1957
+ title: z5.string().min(1),
1958
+ /** Free-text reference to the origin (URL, path, or title). */
1959
+ source: z5.string().min(1),
1960
+ /** ISO datetime the entry was captured (auto-set on add). */
1961
+ capturedAt: z5.string().datetime(),
1962
+ /** Optional free-text author note (from `--by`); NOT a git identity. */
1963
+ capturedBy: z5.string().min(1).optional(),
1964
+ /** Builder's destination choice: when true, the body is projected into AGENTS.md. */
1965
+ inline: z5.boolean()
1966
+ });
1967
+
1968
+ // src/core/context/service/store.ts
1969
+ var SERVICE_DIR = path6.join(CONTEXT_DIR, "service");
1970
+ function serviceDir(root) {
1971
+ return path6.join(root, SERVICE_DIR);
1972
+ }
1973
+ function serviceEntryPath(root, id) {
1974
+ return path6.join(serviceDir(root), `${id}.md`);
1975
+ }
1976
+ function slugifyTitle(title) {
1977
+ return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64).replace(/-+$/g, "");
1978
+ }
1979
+ function shortHash(seed) {
1980
+ let h = 0;
1981
+ for (let i = 0; i < seed.length; i++) {
1982
+ h = h * 31 + seed.charCodeAt(i) >>> 0;
1983
+ }
1984
+ return h.toString(36).slice(0, 8);
1985
+ }
1986
+ function deriveEntryId(title, existingIds) {
1987
+ let base = slugifyTitle(title);
1988
+ if (!isSafeStackIdentifier(base)) {
1989
+ base = `service-${shortHash(title)}`;
1990
+ }
1991
+ if (!existingIds.has(base)) return base;
1992
+ for (let n = 2; ; n++) {
1993
+ const suffix = `-${n}`;
1994
+ const candidate = `${base.slice(0, 64 - suffix.length)}${suffix}`;
1995
+ if (isSafeStackIdentifier(candidate) && !existingIds.has(candidate)) return candidate;
1996
+ }
1997
+ }
1998
+ function occupiedEntryIds(root) {
1999
+ const dir = serviceDir(root);
2000
+ if (!existsSync4(dir)) return /* @__PURE__ */ new Set();
2001
+ try {
2002
+ return new Set(
2003
+ readdirSync2(dir).filter((f) => f.toLowerCase().endsWith(".md")).map((f) => f.slice(0, -".md".length).toLowerCase())
2004
+ );
2005
+ } catch {
2006
+ return /* @__PURE__ */ new Set();
2007
+ }
2008
+ }
2009
+ function parseEntryFile(content) {
2010
+ const normalized = content.replace(/\r\n/g, "\n");
2011
+ const lines = normalized.split("\n");
2012
+ if (lines[0]?.trim() !== "---") return void 0;
2013
+ let closingLine = -1;
2014
+ for (let i = 1; i < lines.length; i++) {
2015
+ if (lines[i]?.trim() === "---") {
2016
+ closingLine = i;
2017
+ break;
2018
+ }
2019
+ }
2020
+ if (closingLine === -1) return void 0;
2021
+ const yamlText = lines.slice(1, closingLine).join("\n");
2022
+ const body = lines.slice(closingLine + 1).join("\n");
2023
+ let frontmatter;
2024
+ try {
2025
+ frontmatter = YAML.parse(yamlText);
2026
+ } catch {
2027
+ return void 0;
2028
+ }
2029
+ return { frontmatter, body };
2030
+ }
2031
+ function listServiceEntries(root, options = {}) {
2032
+ const dir = serviceDir(root);
2033
+ let files;
2034
+ try {
2035
+ files = readdirSync2(dir).filter((f) => f.endsWith(".md"));
2036
+ } catch (error) {
2037
+ if (options.requireComplete && error.code !== "ENOENT") throw error;
2038
+ return [];
2039
+ }
2040
+ const entries = [];
2041
+ for (const file of files.sort()) {
2042
+ try {
2043
+ const raw = readFileSync6(path6.join(dir, file), "utf8");
2044
+ const parsed = parseEntryFile(raw);
2045
+ if (!parsed) throw new Error(`Invalid service entry: ${file}`);
2046
+ const result = ServiceEntryFrontmatterSchema.safeParse(parsed.frontmatter);
2047
+ if (!result.success) throw new Error(`Invalid service entry: ${file}`);
2048
+ const frontmatter = result.data;
2049
+ if (file.slice(0, -".md".length) !== frontmatter.id)
2050
+ throw new Error(`Service entry ID mismatch: ${file}`);
2051
+ entries.push({ ...frontmatter, body: parsed.body });
2052
+ } catch (error) {
2053
+ if (options.requireComplete) throw error;
2054
+ }
2055
+ }
2056
+ return entries;
2057
+ }
2058
+ function serializeEntry(entry) {
2059
+ const { body, ...frontmatter } = entry;
2060
+ const ordered = {
2061
+ id: frontmatter.id,
2062
+ title: frontmatter.title,
2063
+ source: frontmatter.source,
2064
+ capturedAt: frontmatter.capturedAt,
2065
+ ...frontmatter.capturedBy !== void 0 ? { capturedBy: frontmatter.capturedBy } : {},
2066
+ inline: frontmatter.inline
2067
+ };
2068
+ const yamlText = YAML.stringify(ordered, { lineWidth: 0 }).trimEnd();
2069
+ return `---
2070
+ ${yamlText}
2071
+ ---
2072
+ ${body}`;
2073
+ }
2074
+ async function addServiceEntry(root, input) {
2075
+ const now = input.now ?? (() => /* @__PURE__ */ new Date());
2076
+ const id = deriveEntryId(input.title, occupiedEntryIds(root));
2077
+ const frontmatter = ServiceEntryFrontmatterSchema.parse({
2078
+ id,
2079
+ title: input.title,
2080
+ source: input.source,
2081
+ capturedAt: now().toISOString(),
2082
+ ...input.capturedBy !== void 0 ? { capturedBy: input.capturedBy } : {},
2083
+ inline: input.inline
2084
+ });
2085
+ const entry = { ...frontmatter, body: input.body };
2086
+ const targetEntryPath = serviceEntryPath(root, id);
2087
+ const payload = `${serializeEntry(entry)}
2088
+ `;
2089
+ const dir = path6.dirname(targetEntryPath);
2090
+ await mkdir(dir, { recursive: true });
2091
+ const tempPath = path6.join(dir, `.tmp.${process.pid}.${randomBytes2(8).toString("hex")}`);
2092
+ try {
2093
+ await writeFile(tempPath, payload, { encoding: "utf8", flag: "wx" });
2094
+ try {
2095
+ await link(tempPath, targetEntryPath);
2096
+ } catch (error) {
2097
+ if (error.code === "EEXIST") {
2098
+ throw new Error(
2099
+ `Refusing to overwrite an existing service entry file at ${path6.basename(targetEntryPath)}.`
2100
+ );
2101
+ }
2102
+ throw error;
2103
+ }
2104
+ } finally {
2105
+ await unlink(tempPath).catch(() => {
2106
+ });
2107
+ }
2108
+ return { entry, entryPath: targetEntryPath };
2109
+ }
2110
+
2111
+ // src/core/context/fabric.ts
2112
+ var STACK_BLOCK_MARKERS2 = {
2113
+ begin: STACK_BLOCK_MARKERS.begin,
2114
+ end: STACK_BLOCK_MARKERS.end
2115
+ };
2116
+ var KNOWLEDGE_BLOCK_MARKERS2 = {
2117
+ begin: KNOWLEDGE_BLOCK_BEGIN,
2118
+ end: KNOWLEDGE_BLOCK_END
2119
+ };
2120
+ function classifyAgentsFile(root) {
2121
+ try {
2122
+ return lstatSync3(path7.join(root, "AGENTS.md")).isFile() ? "regular" : "non-regular";
2123
+ } catch {
2124
+ return "missing";
2125
+ }
2126
+ }
2127
+ var AGENTS_UNAVAILABLE_REASONS = {
2128
+ missing: "AGENTS.md is missing; run `build init` to create it. Build never creates AGENTS.md here.",
2129
+ "non-regular": "AGENTS.md is not a regular file (directory or symlink); Build will not write through it.",
2130
+ unreadable: "AGENTS.md could not be read; check its permissions."
2131
+ };
2132
+ function readAgents(root) {
2133
+ const kind = classifyAgentsFile(root);
2134
+ if (kind !== "regular") return { kind: "unavailable", cause: kind };
2135
+ try {
2136
+ return { kind: "ok", content: readFileSync7(path7.join(root, "AGENTS.md"), "utf8") };
2137
+ } catch {
2138
+ return { kind: "unavailable", cause: "unreadable" };
2139
+ }
2140
+ }
2141
+ function expectedFragment(root, block, existingContent) {
2142
+ if (block === "stack") {
2143
+ const detection = resolvedStackDetection(root);
2144
+ const fragment = [
2145
+ STACK_BLOCK_MARKERS2.begin,
2146
+ renderStackAgentsBlock(detection),
2147
+ STACK_BLOCK_MARKERS2.end
2148
+ ].join("\n");
2149
+ return { present: true, fragment };
2150
+ }
2151
+ if (block === "knowledge") {
2152
+ const projection = computeKnowledgeProjection(root, existingContent);
2153
+ if (projection.kind === "upsert") return { present: true, fragment: projection.block };
2154
+ if (projection.kind === "remove") return { present: false };
2155
+ return knowledgeManifestIsInvalid(root) ? { present: "unrenderable" } : { present: false };
2156
+ }
2157
+ if (block === "usage") {
2158
+ const fragment = readPackagedUsageBlock();
2159
+ return fragment === void 0 ? { present: "unrenderable" } : { present: true, fragment };
2160
+ }
2161
+ let entries;
2162
+ try {
2163
+ entries = listServiceEntries(root, { requireComplete: true });
2164
+ } catch {
2165
+ return { present: "unrenderable" };
2166
+ }
2167
+ try {
2168
+ const inlined = entries.filter((e) => e.inline);
2169
+ if (inlined.length === 0) return { present: false };
2170
+ return { present: true, fragment: renderServiceBlockFragment(entries) };
2171
+ } catch {
2172
+ return { present: "error" };
2173
+ }
2174
+ }
2175
+ function knowledgeManifestIsInvalid(root) {
2176
+ return readKnowledgeManifest(root).status === "invalid";
2177
+ }
2178
+ function readOnDiskFragment(content, markers) {
2179
+ const beginIndex = content.indexOf(markers.begin);
2180
+ const endIndex = content.indexOf(markers.end);
2181
+ if (beginIndex === -1 && endIndex === -1) return { state: "absent" };
2182
+ if (beginIndex === -1 || endIndex === -1 || endIndex < beginIndex) return { state: "malformed" };
2183
+ return { state: "present", fragment: content.slice(beginIndex, endIndex + markers.end.length) };
2184
+ }
2185
+ function markersFor(block) {
2186
+ if (block === "stack") return STACK_BLOCK_MARKERS2;
2187
+ if (block === "knowledge") return KNOWLEDGE_BLOCK_MARKERS2;
2188
+ if (block === "usage") return USAGE_BLOCK_MARKERS;
2189
+ return { begin: SERVICE_BLOCK_MARKERS.begin, end: SERVICE_BLOCK_MARKERS.end };
2190
+ }
2191
+ var BLOCK_ORDER = ["stack", "knowledge", "service", "usage"];
2192
+ var MALFORMED_MARKER_REASON = "managed-block markers are unpaired or out of order; left untouched.";
2193
+ var MARKER_IN_FRAGMENT_REASON = "rendered content contains a managed-block marker string; left untouched.";
2194
+ var KNOWLEDGE_UNREADABLE_REASON = "knowledge manifest is present but unreadable; block left as-is (repair the manifest).";
2195
+ var UNRENDERABLE_REASONS = {
2196
+ stack: KNOWLEDGE_UNREADABLE_REASON,
2197
+ knowledge: KNOWLEDGE_UNREADABLE_REASON,
2198
+ service: "Stored service context is unreadable or invalid; existing guidance is preserved.",
2199
+ usage: "The packaged usage guide is unreadable; existing guidance is preserved."
2200
+ };
2201
+ function computeContextPlan(root, agents) {
2202
+ if (agents.kind === "unavailable") {
2203
+ return BLOCK_ORDER.map((block) => ({
2204
+ block,
2205
+ status: "agents-unavailable",
2206
+ action: "skip",
2207
+ reason: AGENTS_UNAVAILABLE_REASONS[agents.cause]
2208
+ }));
2209
+ }
2210
+ return BLOCK_ORDER.map((block) => {
2211
+ const markers = markersFor(block);
2212
+ const onDisk = readOnDiskFragment(agents.content, markers);
2213
+ if (onDisk.state === "malformed") {
2214
+ return {
2215
+ block,
2216
+ status: "markers-malformed",
2217
+ action: "skip",
2218
+ reason: MALFORMED_MARKER_REASON
2219
+ };
2220
+ }
2221
+ const expected = expectedFragment(root, block, agents.content);
2222
+ if (expected.present === "error") {
2223
+ return {
2224
+ block,
2225
+ status: "markers-malformed",
2226
+ action: "skip",
2227
+ reason: MARKER_IN_FRAGMENT_REASON
2228
+ };
2229
+ }
2230
+ if (expected.present === "unrenderable") {
2231
+ return onDisk.state === "present" ? {
2232
+ block,
2233
+ status: "needs-attention",
2234
+ action: "nothing",
2235
+ reason: UNRENDERABLE_REASONS[block]
2236
+ } : { block, status: "not-applicable", action: "nothing" };
2237
+ }
2238
+ if (expected.present === false) {
2239
+ return onDisk.state === "present" ? { block, status: "stale", action: "remove" } : { block, status: "not-applicable", action: "nothing" };
2240
+ }
2241
+ if (fragmentEmbedsManagedMarker(expected.fragment, markers)) {
2242
+ return {
2243
+ block,
2244
+ status: "markers-malformed",
2245
+ action: "skip",
2246
+ reason: MARKER_IN_FRAGMENT_REASON
2247
+ };
2248
+ }
2249
+ if (onDisk.state === "absent") {
2250
+ if (block === "usage" && hasLegacyUsageGuide(agents.content)) {
2251
+ return { block, status: "needs-attention", action: "skip", reason: LEGACY_USAGE_REASON };
2252
+ }
2253
+ return {
2254
+ block,
2255
+ status: block === "usage" ? "not-installed" : "stale",
2256
+ action: "upsert",
2257
+ fragment: expected.fragment
2258
+ };
2259
+ }
2260
+ return onDisk.fragment === expected.fragment ? { block, status: "in-sync", action: "nothing", fragment: expected.fragment } : { block, status: "stale", action: "upsert", fragment: expected.fragment };
2261
+ });
2262
+ }
2263
+ var KNOWLEDGE_POINTER = "knowledge: manage with `build init knowledge ...`";
2264
+ function buildContextView(root) {
2265
+ const agents = readAgents(root);
2266
+ const status = knowledgeStatus(root);
2267
+ const entries = listServiceEntries(root);
2268
+ const detection = resolvedStackDetection(root);
2269
+ const contractStatus = status.contract.status === "ok" ? status.contract.contractStatus : status.contract.status;
2270
+ return {
2271
+ stack: {
2272
+ // Match init/apply exactly, including detection outcome tokens.
2273
+ languages: detection.languages,
2274
+ frameworks: detection.frameworks,
2275
+ sdkTargets: detection.sdkTargets,
2276
+ tools: detection.tools ?? [],
2277
+ domains: detection.domains ?? []
2278
+ },
2279
+ knowledge: {
2280
+ contractStatus,
2281
+ manifestStatus: status.manifest.status,
2282
+ itemCount: status.manifest.status === "ok" ? status.manifest.itemCount : 0
2283
+ },
2284
+ service: {
2285
+ count: entries.length,
2286
+ inlineCount: entries.filter((e) => e.inline).length,
2287
+ entries: entries.map((e) => ({ id: e.id, title: e.title, inline: e.inline }))
2288
+ },
2289
+ // Render the SAME plan apply executes, so view and apply never disagree.
2290
+ blocks: computeContextPlan(root, agents).map(
2291
+ (plan) => ({
2292
+ block: plan.block,
2293
+ status: plan.status,
2294
+ ...plan.reason ? { reason: plan.reason } : {}
2295
+ })
2296
+ ),
2297
+ agentsAvailable: agents.kind === "ok",
2298
+ knowledgePointer: KNOWLEDGE_POINTER
2299
+ };
2300
+ }
2301
+ function listStaleManagedBlocks(root) {
2302
+ const agents = readAgents(root);
2303
+ if (agents.kind !== "ok") return [];
2304
+ return computeContextPlan(root, agents).filter(
2305
+ (plan) => plan.status === "stale" && readOnDiskFragment(agents.content, markersFor(plan.block)).state === "present"
2306
+ ).map((plan) => plan.block);
2307
+ }
2308
+ async function applyContext(root, options = {}) {
2309
+ const agents = readAgents(root);
2310
+ const plan = computeContextPlan(root, agents).filter(
2311
+ (step) => step.block !== "usage" || options.includeUsage !== false
2312
+ );
2313
+ if (agents.kind === "unavailable") {
2314
+ return {
2315
+ agentsUnavailable: true,
2316
+ wrote: false,
2317
+ outcomes: plan.map((p) => ({
2318
+ block: p.block,
2319
+ result: "skipped",
2320
+ reason: p.reason ?? "AGENTS.md is absent or not a regular file."
2321
+ }))
2322
+ };
2323
+ }
2324
+ let working = agents.content;
2325
+ const outcomes = [];
2326
+ for (const step of plan) {
2327
+ const markers = markersFor(step.block);
2328
+ switch (step.action) {
2329
+ case "skip":
2330
+ outcomes.push({
2331
+ block: step.block,
2332
+ result: "skipped",
2333
+ reason: step.reason ?? MALFORMED_MARKER_REASON
2334
+ });
2335
+ break;
2336
+ case "nothing":
2337
+ outcomes.push({
2338
+ block: step.block,
2339
+ result: step.status === "in-sync" ? "already-in-sync" : "nothing-to-project"
2340
+ });
2341
+ break;
2342
+ case "remove": {
2343
+ const next = removeManagedBlock(working, markers);
2344
+ if (next !== working) {
2345
+ working = next;
2346
+ outcomes.push({ block: step.block, result: "updated" });
2347
+ } else {
2348
+ outcomes.push({ block: step.block, result: "nothing-to-project" });
2349
+ }
2350
+ break;
2351
+ }
2352
+ case "upsert": {
2353
+ try {
2354
+ const next = upsertManagedBlock(working, step.fragment, markers);
2355
+ if (next === working) {
2356
+ outcomes.push({ block: step.block, result: "already-in-sync" });
2357
+ } else {
2358
+ working = next;
2359
+ outcomes.push({ block: step.block, result: "updated" });
2360
+ }
2361
+ } catch {
2362
+ outcomes.push({
2363
+ block: step.block,
2364
+ result: "skipped",
2365
+ reason: MALFORMED_MARKER_REASON
2366
+ });
2367
+ }
2368
+ break;
2369
+ }
2370
+ }
2371
+ }
2372
+ const wrote = working !== agents.content;
2373
+ if (wrote) {
2374
+ await atomicWriteText(path7.join(root, "AGENTS.md"), working, { trailingNewline: false });
2375
+ }
2376
+ return { agentsUnavailable: false, wrote, outcomes };
2377
+ }
2378
+
2379
+ // src/core/init-drift/nudge.ts
2380
+ var CONTEXT_BLOCKS_APPLY_COMMAND = "build config context apply";
2381
+ function diffSets(before, after) {
2382
+ const beforeSet = new Set(before);
2383
+ const afterSet = new Set(after);
2384
+ return {
2385
+ added: after.filter((item) => !beforeSet.has(item)),
2386
+ removed: before.filter((item) => !afterSet.has(item))
2387
+ };
2388
+ }
2389
+ function newManifests(stored, current) {
2390
+ return Object.keys(current.manifests).filter((name) => stored.manifests[name] !== true);
2391
+ }
2392
+ function detectDrift(stored, current) {
2393
+ const detectedAtMs = 0;
2394
+ const records = [];
2395
+ const appearedManifests = newManifests(stored, current);
2396
+ const languages = diffSets(stored.languages, current.languages);
2397
+ for (const language of languages.added) {
2398
+ records.push({
2399
+ key: `language:${language}`,
2400
+ kind: "language-added",
2401
+ subject: language,
2402
+ change: "added",
2403
+ evidence: appearedManifests,
2404
+ detectedAtMs
2405
+ });
2406
+ }
2407
+ for (const language of languages.removed) {
2408
+ records.push({
2409
+ key: `language:${language}`,
2410
+ kind: "language-removed",
2411
+ subject: language,
2412
+ change: "removed",
2413
+ evidence: [],
2414
+ detectedAtMs
2415
+ });
2416
+ }
2417
+ const frameworks = diffSets(stored.frameworks, current.frameworks);
2418
+ for (const framework of frameworks.added) {
2419
+ records.push({
2420
+ key: `framework:${framework}`,
2421
+ kind: "framework-changed",
2422
+ subject: framework,
2423
+ change: "added",
2424
+ evidence: appearedManifests,
2425
+ detectedAtMs
2426
+ });
2427
+ }
2428
+ for (const framework of frameworks.removed) {
2429
+ records.push({
2430
+ key: `framework:${framework}`,
2431
+ kind: "framework-changed",
2432
+ subject: framework,
2433
+ change: "removed",
2434
+ evidence: [],
2435
+ detectedAtMs
2436
+ });
2437
+ }
2438
+ const explained = new Set(records.flatMap((record) => record.evidence));
2439
+ for (const manifest of appearedManifests) {
2440
+ if (explained.has(manifest)) continue;
2441
+ records.push({
2442
+ key: `manifest:${manifest}`,
2443
+ kind: "manifest-appeared",
2444
+ subject: manifest,
2445
+ change: "added",
2446
+ evidence: [manifest],
2447
+ detectedAtMs
2448
+ });
2449
+ }
2450
+ return records;
2451
+ }
2452
+ function checkDrift(cwd, options = {}) {
2453
+ const now = options.now ?? Date.now;
2454
+ const current = computeStackFingerprint(cwd);
2455
+ const currentDigest = fingerprintDigest(current);
2456
+ const stored = readStoredFingerprint(cwd);
2457
+ if (stored === void 0) {
2458
+ writeStoredFingerprint(cwd, current, options);
2459
+ return {
2460
+ hadBaseline: false,
2461
+ newDrift: [],
2462
+ pending: listPendingDrift(cwd, options),
2463
+ currentDigest
2464
+ };
2465
+ }
2466
+ if (stored.digest === currentDigest) {
2467
+ return {
2468
+ hadBaseline: true,
2469
+ newDrift: [],
2470
+ pending: listPendingDrift(cwd, options),
2471
+ currentDigest
2472
+ };
2473
+ }
2474
+ const nowMs = now();
2475
+ const newDrift = detectDrift(stored.fingerprint, current).map((record) => ({
2476
+ ...record,
2477
+ detectedAtMs: nowMs
2478
+ }));
2479
+ if (newDrift.length > 0) {
2480
+ recordDriftRecords(cwd, newDrift, options);
2481
+ }
2482
+ writeStoredFingerprint(cwd, current, options);
2483
+ return {
2484
+ hadBaseline: true,
2485
+ newDrift,
2486
+ pending: listPendingDrift(cwd, options),
2487
+ currentDigest
2488
+ };
2489
+ }
2490
+ var LANGUAGE_LABELS = {
2491
+ python: { label: "Python", artifacts: "recommend Python docs/resources for coding agents" },
2492
+ go: { label: "Go", artifacts: "recommend Go docs/resources for coding agents" },
2493
+ rust: { label: "Rust", artifacts: "recommend Rust docs/resources for coding agents" },
2494
+ swift: { label: "Swift", artifacts: "recommend Swift/Apple docs/resources for coding agents" },
2495
+ typescript: {
2496
+ label: "TypeScript",
2497
+ artifacts: "recommend TypeScript docs/resources for coding agents"
2498
+ },
2499
+ javascript: {
2500
+ label: "JavaScript",
2501
+ artifacts: "recommend JavaScript docs/resources for coding agents"
2502
+ },
2503
+ node: { label: "Node.js", artifacts: "recommend Node.js docs/resources for coding agents" },
2504
+ java: { label: "Java", artifacts: "recommend Java docs/resources for coding agents" },
2505
+ kotlin: { label: "Kotlin", artifacts: "recommend Kotlin docs/resources for coding agents" },
2506
+ ruby: { label: "Ruby", artifacts: "recommend Ruby docs/resources for coding agents" },
2507
+ php: { label: "PHP", artifacts: "recommend PHP docs/resources for coding agents" },
2508
+ dart: { label: "Dart", artifacts: "recommend Dart/Flutter docs/resources for coding agents" },
2509
+ dotnet: { label: ".NET", artifacts: "recommend .NET docs/resources for coding agents" },
2510
+ c: { label: "C", artifacts: "recommend C docs/resources for coding agents" },
2511
+ cpp: { label: "C++", artifacts: "recommend C++ docs/resources for coding agents" }
2512
+ };
2513
+ function languageLabel(subject) {
2514
+ return LANGUAGE_LABELS[subject] ?? {
2515
+ label: subject,
2516
+ artifacts: `recommend ${subject} docs/resources for coding agents`
2517
+ };
2518
+ }
2519
+ function evidenceSuffix(record) {
2520
+ if (record.evidence.length === 0) return "";
2521
+ return ` (${record.evidence.join(", ")} added)`;
2522
+ }
2523
+ function composeNudgeMessage(record) {
2524
+ const previewPromise = "Run 'build init' when ready \u2014 it will show you exactly what it proposes before changing anything.";
2525
+ switch (record.kind) {
2526
+ case "ci-setup":
2527
+ return ciAdvisoryMessage(record.subject);
2528
+ case "context-blocks-stale":
2529
+ return `Notice: Managed context blocks in AGENTS.md are out of date (${record.subject}). Run '${CONTEXT_BLOCKS_APPLY_COMMAND}' to refresh them; nothing is written until you do.`;
2530
+ case "language-added": {
2531
+ const { label, artifacts } = languageLabel(record.subject);
2532
+ return `Notice: New since last check: ${label}${evidenceSuffix(record)}. Build can update the agent instructions (AGENTS.md) and ${artifacts}. ` + previewPromise;
2533
+ }
2534
+ case "language-removed": {
2535
+ const { label } = languageLabel(record.subject);
2536
+ return `Notice: Changed since last check: ${label} no longer detected in this repo. Build can update the agent instructions (AGENTS.md) and retire stale ${label} guidance for coding agents. ` + previewPromise;
2537
+ }
2538
+ case "framework-changed": {
2539
+ const direction = record.change === "added" ? "added" : "removed";
2540
+ return `Notice: Changed since last check: ${record.subject} toolchain signal ${direction}${evidenceSuffix(record)}. Build can update the agent instructions (AGENTS.md) and adjust the recommended docs/resources for coding agents. ` + previewPromise;
2541
+ }
2542
+ case "manifest-appeared":
2543
+ return `Notice: New since last check: ${record.subject} appeared. Build can update the agent instructions (AGENTS.md) and recommend docs/resources matching the new stack surface. ` + previewPromise;
2544
+ }
2545
+ }
2546
+
2547
+ // src/core/init-drift/render.ts
2548
+ function shouldSuppressNudges(policy, options = {}) {
2549
+ if (policy.json || policy.quiet) return true;
2550
+ if (isCiEnvironment(options.env ?? process.env)) return true;
2551
+ const stderrIsTty = options.stderrIsTty ?? Boolean(process.stderr.isTTY);
2552
+ return !stderrIsTty;
2553
+ }
2554
+ function formatAge(ageMs) {
2555
+ const days = Math.floor(ageMs / (24 * 60 * 60 * 1e3));
2556
+ if (days >= 2) return `${days} days`;
2557
+ if (days === 1) return "1 day";
2558
+ const hours = Math.floor(ageMs / (60 * 60 * 1e3));
2559
+ if (hours >= 1) return hours === 1 ? "1 hour" : `${hours} hours`;
2560
+ return "less than an hour";
2561
+ }
2562
+ function defaultWriteLine(line) {
2563
+ process.stderr.write(`${line}
2564
+ `);
2565
+ }
2566
+ function renderPendingNudges(cwd, streamPolicy, options = {}) {
2567
+ const pending = listPendingDrift(cwd, options).filter(
2568
+ (record) => options.includeRecord?.(record) ?? true
2569
+ );
2570
+ if (shouldSuppressNudges(streamPolicy, options)) {
2571
+ return { rendered: false, deliveredKeys: [], pendingCount: pending.length };
2572
+ }
2573
+ if (pending.length === 0) {
2574
+ return { rendered: false, deliveredKeys: [], pendingCount: 0 };
2575
+ }
2576
+ const writeLine = options.writeLine ?? defaultWriteLine;
2577
+ for (const record of pending) {
2578
+ const message = composeNudgeMessage(record);
2579
+ const suffix = options.includeAge === true ? ` (not yet reviewed, ${formatAge(record.ageMs)})` : "";
2580
+ writeLine(`${message}${suffix}`);
2581
+ }
2582
+ const deliveredKeys = pending.map((record) => record.key);
2583
+ if (!options.readOnly) recordDelivery(cwd, deliveredKeys, options);
2584
+ return {
2585
+ rendered: true,
2586
+ deliveredKeys: options.readOnly ? [] : deliveredKeys,
2587
+ pendingCount: options.readOnly ? pending.length : 0
2588
+ };
2589
+ }
2590
+ function listPendingNudges(cwd, options = {}) {
2591
+ return listPendingDrift(cwd, options);
2592
+ }
2593
+
2594
+ // src/core/init-drift/context-blocks.ts
2595
+ var CONTEXT_BLOCKS_DRIFT_KEY = "context-blocks";
2596
+ function syncContextBlocksDrift(cwd, options = {}) {
2597
+ const stale = listStaleManagedBlocks(cwd);
2598
+ const prior = readDriftRecord(cwd, CONTEXT_BLOCKS_DRIFT_KEY);
2599
+ if (stale.length === 0) {
2600
+ if (prior) forgetDriftRecord(cwd, CONTEXT_BLOCKS_DRIFT_KEY);
2601
+ return;
2602
+ }
2603
+ const subject = stale.join(", ");
2604
+ if (prior?.record.subject === subject) return;
2605
+ const now = options.now ?? Date.now;
2606
+ recordDriftRecords(
2607
+ cwd,
2608
+ [
2609
+ {
2610
+ key: CONTEXT_BLOCKS_DRIFT_KEY,
2611
+ kind: "context-blocks-stale",
2612
+ subject,
2613
+ change: "added",
2614
+ evidence: [],
2615
+ detectedAtMs: Math.max(now(), (prior?.record.detectedAtMs ?? 0) + 1)
2616
+ }
2617
+ ],
2618
+ options
2619
+ );
2620
+ }
2621
+
2622
+ export {
2623
+ upsertManagedBlock,
2624
+ removeManagedBlock,
2625
+ createAskSearchProvider,
2626
+ buildKitOffer,
2627
+ renderPendingIntentBlock,
2628
+ blockIsPendingIntent,
2629
+ removeKnowledgeBlock,
2630
+ upsertKnowledgeBlock,
2631
+ applyKit,
2632
+ PENDING_OFFER_NOTICE_MESSAGE,
2633
+ writePendingOfferNotice,
2634
+ readPendingOfferNotice,
2635
+ clearPendingOfferNotice,
2636
+ knowledgeStatus,
2637
+ declareIntent,
2638
+ clearIntent,
2639
+ resolveConflicts,
2640
+ createOffer,
2641
+ acceptOffer,
2642
+ graduateIntent,
2643
+ WORK_TRACKING_MARKERS,
2644
+ readPackagedUsageBlock,
2645
+ installUsageBlockIfAbsent,
2646
+ listServiceEntries,
2647
+ addServiceEntry,
2648
+ classifyAgentsFile,
2649
+ buildContextView,
2650
+ listStaleManagedBlocks,
2651
+ applyContext,
2652
+ syncContextBlocksDrift,
2653
+ CONTEXT_BLOCKS_APPLY_COMMAND,
2654
+ checkDrift,
2655
+ shouldSuppressNudges,
2656
+ renderPendingNudges,
2657
+ listPendingNudges
2658
+ };
2659
+ //# sourceMappingURL=chunk-KZWGBUIO.js.map