@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,2479 @@
1
+ import {
2
+ findLabRun,
3
+ findLatestLabRun
4
+ } from "./chunk-FT7SGLXT.js";
5
+ import {
6
+ UNIFIED_COST_METRIC_SOURCE_SAMPLES
7
+ } from "./chunk-J5HM6V5P.js";
8
+ import {
9
+ renderJsonError,
10
+ renderJsonResult
11
+ } from "./chunk-5YDE3Q62.js";
12
+ import {
13
+ BooleanFlagSchema,
14
+ FilePathSchema,
15
+ ModelNameSchema,
16
+ PositiveIntegerSchema,
17
+ createSafeErrorMessage,
18
+ formatValidationErrors,
19
+ validateCommandOptions
20
+ } from "./chunk-I7SCBHJN.js";
21
+ import {
22
+ ensurePendingInvocationCostEnrichment,
23
+ formatCostProjectionNotice,
24
+ fromVisibilitySummary,
25
+ listInvocationProviderIdsSince,
26
+ projectCostVisibility,
27
+ summarizeInvocationCostVisibility
28
+ } from "./chunk-Q64IR2Z2.js";
29
+ import {
30
+ parseDuration
31
+ } from "./chunk-2VLJUXJU.js";
32
+ import {
33
+ checkAndWarnLabContext
34
+ } from "./chunk-C3KCMAJP.js";
35
+ import {
36
+ ValidationError
37
+ } from "./chunk-RRC5BL7B.js";
38
+ import {
39
+ emitWarning
40
+ } from "./chunk-7VRJHTGZ.js";
41
+
42
+ // src/cli/commands/cost.ts
43
+ import fs from "fs";
44
+ import path from "path";
45
+ import chalk3 from "chalk";
46
+ import { Command, InvalidArgumentError } from "commander";
47
+ import { z as z2 } from "zod";
48
+
49
+ // src/cost-tracking/pricing-verifier.ts
50
+ function isExpectedFreeZeroCostModel(model) {
51
+ if (!model) return false;
52
+ return /:free(?:$|[:/])/i.test(model) || model.toLowerCase().endsWith(":free");
53
+ }
54
+ function isExpectedFreeZeroCostWarning(warning) {
55
+ if (warning.type !== "zero_cost") return false;
56
+ if (warning.details?.expectedFreeCatalog === true) return true;
57
+ return isExpectedFreeZeroCostModel(warning.model);
58
+ }
59
+ var PricingVerifier = class {
60
+ calculator;
61
+ logger;
62
+ config;
63
+ costHistory = /* @__PURE__ */ new Map();
64
+ constructor(calculator, logger, config) {
65
+ this.calculator = calculator;
66
+ this.logger = logger;
67
+ this.config = {
68
+ maxAgeDays: 30,
69
+ enableFreshnessChecks: true,
70
+ enableAnomalyDetection: true,
71
+ anomalyThresholdPercent: 50,
72
+ ...config
73
+ };
74
+ }
75
+ /**
76
+ * Resolve the pricing data version from the dynamic pricing manifest.
77
+ * Returns 'unknown' when no manifest is available or it carries no registry version.
78
+ */
79
+ resolvePricingVersion() {
80
+ try {
81
+ const manifest = this.calculator.getDynamicPricingManifest?.() ?? null;
82
+ const registryVersion = manifest?.registryVersion;
83
+ if (typeof registryVersion !== "string" || registryVersion.length === 0) {
84
+ return "unknown";
85
+ }
86
+ return registryVersion;
87
+ } catch {
88
+ return "unknown";
89
+ }
90
+ }
91
+ /**
92
+ * Verify pricing configuration for a specific provider
93
+ */
94
+ async verifyProvider(provider) {
95
+ const warnings = [];
96
+ const errors = [];
97
+ try {
98
+ this.calculator.ensurePricingLoadedSync();
99
+ const models = this.calculator.getAvailableModels(provider);
100
+ if (models.length === 0) {
101
+ const availability = this.getProviderPricingAvailability(provider);
102
+ if (isAdvisoryMissingPricing(availability)) {
103
+ warnings.push({
104
+ type: "pricing_unavailable",
105
+ severity: "medium",
106
+ message: `Provider "${provider}" has a model catalog but no per-token pricing because billing is ${availability.billingMode}`,
107
+ provider,
108
+ details: { availability }
109
+ });
110
+ return {
111
+ valid: true,
112
+ warnings,
113
+ errors,
114
+ metadata: {
115
+ version: this.resolvePricingVersion(),
116
+ providersChecked: [provider],
117
+ modelsChecked: 0
118
+ }
119
+ };
120
+ }
121
+ errors.push({
122
+ type: "missing_pricing",
123
+ message: `No models found for provider "${provider}"`,
124
+ provider
125
+ });
126
+ return {
127
+ valid: false,
128
+ warnings,
129
+ errors,
130
+ metadata: {
131
+ version: this.resolvePricingVersion(),
132
+ providersChecked: [provider],
133
+ modelsChecked: 0
134
+ }
135
+ };
136
+ }
137
+ for (const model of models) {
138
+ const modelWarnings = this.verifyModelPricing(provider, model);
139
+ warnings.push(...modelWarnings);
140
+ }
141
+ if (this.config.enableFreshnessChecks) {
142
+ const freshnessWarnings = this.checkPricingFreshness(provider);
143
+ warnings.push(...freshnessWarnings);
144
+ }
145
+ const freshness = resolveProviderFreshness(
146
+ this.calculator.getDynamicPricingManifest?.() ?? null,
147
+ provider
148
+ );
149
+ const ageDays = freshness.lastUpdated !== void 0 ? (Date.now() - new Date(freshness.lastUpdated).getTime()) / (1e3 * 60 * 60 * 24) : void 0;
150
+ const metadata = {
151
+ version: this.resolvePricingVersion(),
152
+ providersChecked: [provider],
153
+ modelsChecked: models.length
154
+ };
155
+ if (freshness.lastUpdated !== void 0) {
156
+ metadata.lastUpdated = new Date(freshness.lastUpdated).toISOString();
157
+ }
158
+ if (ageDays !== void 0 && Number.isFinite(ageDays)) {
159
+ metadata.ageDays = Math.round(ageDays);
160
+ }
161
+ this.logger.logCostEvent("pricing_verification_complete", {
162
+ provider,
163
+ modelsChecked: models.length,
164
+ warningsCount: warnings.length,
165
+ errorsCount: errors.length
166
+ });
167
+ return {
168
+ valid: errors.length === 0,
169
+ warnings,
170
+ errors,
171
+ metadata
172
+ };
173
+ } catch (error) {
174
+ const message = error instanceof Error ? error.message : String(error);
175
+ errors.push({
176
+ type: "invalid_pricing",
177
+ message: `Pricing verification failed: ${message}`,
178
+ provider
179
+ });
180
+ return {
181
+ valid: false,
182
+ warnings,
183
+ errors,
184
+ metadata: {
185
+ version: this.resolvePricingVersion(),
186
+ providersChecked: [provider],
187
+ modelsChecked: 0
188
+ }
189
+ };
190
+ }
191
+ }
192
+ /**
193
+ * Verify pricing for a specific model
194
+ */
195
+ verifyModelPricing(provider, model) {
196
+ const warnings = [];
197
+ try {
198
+ const pricing = this.getModelPricingSafe(provider, model);
199
+ if (!pricing) {
200
+ warnings.push({
201
+ type: "missing_model",
202
+ severity: "high",
203
+ message: `No pricing found for model "${model}"`,
204
+ provider,
205
+ model
206
+ });
207
+ return warnings;
208
+ }
209
+ if (pricing.inputTokens === 0 && pricing.outputTokens === 0 && pricing.billingMode === "metered" && !isIncludedPlanPricing(pricing)) {
210
+ const expectedFreeCatalog = isExpectedFreeZeroCostModel(model);
211
+ warnings.push({
212
+ type: "zero_cost",
213
+ severity: expectedFreeCatalog ? "low" : "high",
214
+ message: expectedFreeCatalog ? `Model "${model}" is a :free catalog entry with $0+$0 token prices` : `Model "${model}" has zero cost for input and output tokens`,
215
+ provider,
216
+ model,
217
+ details: { pricing, expectedFreeCatalog }
218
+ });
219
+ }
220
+ const typicalMaxInputCost = 100;
221
+ const typicalMaxOutputCost = 500;
222
+ if (pricing.inputTokens > typicalMaxInputCost || pricing.outputTokens > typicalMaxOutputCost) {
223
+ warnings.push({
224
+ type: "high_cost_variance",
225
+ severity: "medium",
226
+ message: `Model "${model}" has unusually high token costs`,
227
+ provider,
228
+ model,
229
+ details: {
230
+ inputTokens: pricing.inputTokens,
231
+ outputTokens: pricing.outputTokens,
232
+ thresholds: { typicalMaxInputCost, typicalMaxOutputCost }
233
+ }
234
+ });
235
+ }
236
+ } catch (error) {
237
+ const message = error instanceof Error ? error.message : String(error);
238
+ warnings.push({
239
+ type: "missing_model",
240
+ severity: "high",
241
+ message: `Failed to verify pricing for "${model}": ${message}`,
242
+ provider,
243
+ model
244
+ });
245
+ }
246
+ return warnings;
247
+ }
248
+ /**
249
+ * Check if pricing data is fresh (not stale)
250
+ */
251
+ checkPricingFreshness(provider) {
252
+ const warnings = [];
253
+ const manifest = this.calculator.getDynamicPricingManifest?.();
254
+ if (!manifest) {
255
+ return warnings;
256
+ }
257
+ const providerFreshness = resolveProviderFreshness(manifest, provider);
258
+ const timestamp = providerFreshness.lastSuccessfulFetch ?? providerFreshness.lastUpdated;
259
+ if (!timestamp) {
260
+ return warnings;
261
+ }
262
+ const updatedDate = new Date(timestamp);
263
+ if (Number.isNaN(updatedDate.getTime())) {
264
+ return warnings;
265
+ }
266
+ const ageDays = (Date.now() - updatedDate.getTime()) / (1e3 * 60 * 60 * 24);
267
+ if (providerFreshness.stale || ageDays > this.config.maxAgeDays) {
268
+ warnings.push({
269
+ type: "stale_data",
270
+ severity: providerFreshness.stale ? "high" : "medium",
271
+ message: providerFreshness.stale ? `Pricing data for "${provider}" is using stale fallback data from ${Math.round(ageDays)} days ago` : `Pricing data for "${provider}" is ${Math.round(ageDays)} days old`,
272
+ provider,
273
+ details: {
274
+ ageDays: Math.round(ageDays),
275
+ maxAgeDays: this.config.maxAgeDays,
276
+ stale: providerFreshness.stale,
277
+ failureReason: providerFreshness.failureReason
278
+ }
279
+ });
280
+ }
281
+ return warnings;
282
+ }
283
+ /**
284
+ * Detect cost calculation anomalies
285
+ */
286
+ detectAnomaly(provider, model, actualCost) {
287
+ if (!this.config.enableAnomalyDetection) {
288
+ return null;
289
+ }
290
+ const historyKey = `${provider}:${model}`;
291
+ const history = this.costHistory.get(historyKey) || [];
292
+ if (history.length < 5) {
293
+ history.push(actualCost);
294
+ this.costHistory.set(historyKey, history);
295
+ return null;
296
+ }
297
+ const mean = history.reduce((sum, cost) => sum + cost, 0) / history.length;
298
+ if (mean === 0) {
299
+ history.push(actualCost);
300
+ this.costHistory.set(historyKey, history);
301
+ return null;
302
+ }
303
+ const threshold = mean * (this.config.anomalyThresholdPercent / 100);
304
+ const expectedRange = {
305
+ min: mean - threshold,
306
+ max: mean + threshold
307
+ };
308
+ if (actualCost < expectedRange.min || actualCost > expectedRange.max) {
309
+ const deviationPercent = Math.abs(actualCost - mean) / mean * 100;
310
+ const alert = {
311
+ provider,
312
+ model,
313
+ expectedCostRange: expectedRange,
314
+ actualCost,
315
+ deviationPercent,
316
+ severity: deviationPercent > this.config.anomalyThresholdPercent * 2 ? "critical" : "warning",
317
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
318
+ };
319
+ this.logger.logCostEvent("cost_anomaly_detected", {
320
+ provider,
321
+ model,
322
+ actualCost,
323
+ expectedMin: expectedRange.min,
324
+ expectedMax: expectedRange.max,
325
+ deviationPercent,
326
+ severity: alert.severity
327
+ });
328
+ return alert;
329
+ }
330
+ history.push(actualCost);
331
+ if (history.length > 20) {
332
+ history.shift();
333
+ }
334
+ this.costHistory.set(historyKey, history);
335
+ return null;
336
+ }
337
+ /**
338
+ * Safe method to get model pricing without throwing
339
+ */
340
+ getModelPricingSafe(provider, model) {
341
+ try {
342
+ const calculator = this.calculator;
343
+ if (typeof calculator.getModelPricingWithFallback === "function") {
344
+ return calculator.getModelPricingWithFallback(provider, model);
345
+ }
346
+ return null;
347
+ } catch {
348
+ return null;
349
+ }
350
+ }
351
+ getProviderPricingAvailability(provider) {
352
+ const calculator = this.calculator;
353
+ if (typeof calculator.getProviderPricingAvailability !== "function") {
354
+ return null;
355
+ }
356
+ try {
357
+ return calculator.getProviderPricingAvailability(
358
+ provider
359
+ );
360
+ } catch {
361
+ return null;
362
+ }
363
+ }
364
+ /**
365
+ * Reset cost history (useful for testing or manual reset)
366
+ */
367
+ resetHistory() {
368
+ this.costHistory.clear();
369
+ this.logger.logCostEvent("pricing_verifier_history_reset", {
370
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
371
+ });
372
+ }
373
+ };
374
+ function isIncludedPlanPricing(pricing) {
375
+ const explicitIncluded = pricing.billingSource === "included_plan" || pricing.pricingSource === "subscription_included";
376
+ if (explicitIncluded) {
377
+ return true;
378
+ }
379
+ const hasExplicitProvenance = pricing.billingSource !== void 0 || pricing.pricingSource !== void 0 && pricing.pricingSource !== "yaml" && pricing.pricingSource !== "dynamic";
380
+ if (hasExplicitProvenance) {
381
+ return false;
382
+ }
383
+ return hasIncludedPlanNote(pricing.pricingNotes);
384
+ }
385
+ function isAdvisoryMissingPricing(availability) {
386
+ if (!availability?.hasModelCatalog || availability.hasTokenPricing) {
387
+ return false;
388
+ }
389
+ return availability.billingMode === "flat_rate" || availability.billingMode === "non_metered";
390
+ }
391
+ function hasIncludedPlanNote(note) {
392
+ if (!note) {
393
+ return false;
394
+ }
395
+ const normalized = note.toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
396
+ return /\bincluded\s+(with|in|under)\b.{0,80}\b(plan|subscription|license|seat)\b/.test(normalized) || /\bincluded\s+as\s+part\s+of\b.{0,80}\b(plan|subscription|license|seat)\b/.test(normalized) || /\b(plan|subscription)\s+included\b/.test(normalized);
397
+ }
398
+ function resolveProviderFreshness(manifest, provider) {
399
+ if (!manifest) {
400
+ return { stale: false };
401
+ }
402
+ const providerLower = provider.toLowerCase();
403
+ const providerEntry = manifest.providers.find(
404
+ (entry) => entry.providerId === provider || entry.providerId.toLowerCase() === providerLower
405
+ );
406
+ if (!providerEntry) {
407
+ return {
408
+ lastUpdated: manifest.generatedAt,
409
+ stale: false
410
+ };
411
+ }
412
+ return {
413
+ lastUpdated: providerEntry.lastUpdated,
414
+ lastSuccessfulFetch: providerEntry.lastSuccessfulFetch,
415
+ stale: providerEntry.stale,
416
+ failureReason: providerEntry.failureReason
417
+ };
418
+ }
419
+
420
+ // src/cost-tracking/stored-usage.ts
421
+ function storedUsageToUsageData(usage) {
422
+ return {
423
+ inputTokens: usage.inputTokens,
424
+ outputTokens: usage.outputTokens,
425
+ cacheReadTokens: usage.cacheReadTokens,
426
+ cacheWriteTokens: usage.cacheWriteTokens,
427
+ cacheWriteLongTokens: usage.cacheWriteLongTokens,
428
+ cacheReadTokensIncludedInInput: usage.cacheReadTokensIncludedInInput,
429
+ granularity: usage.granularity,
430
+ speedTier: usage.requestedServiceTier,
431
+ speedBreakdown: usage.observedSpeed,
432
+ requestEvidence: usage.requestEvidence,
433
+ tools: usage.toolCalls?.map((tool) => ({ name: tool.name, requests: tool.requests })) ?? [],
434
+ executionTimeMinutes: usage.executionTimeMs === void 0 ? void 0 : usage.executionTimeMs / 6e4
435
+ };
436
+ }
437
+
438
+ // src/cli/formatters/currency.ts
439
+ var formatterCache = /* @__PURE__ */ new Map();
440
+ function getFormatter(currency) {
441
+ const normalized = currency.toUpperCase();
442
+ let formatter = formatterCache.get(normalized);
443
+ if (!formatter) {
444
+ try {
445
+ formatter = new Intl.NumberFormat("en-US", {
446
+ style: "currency",
447
+ currency: normalized,
448
+ minimumFractionDigits: 2,
449
+ maximumFractionDigits: 2
450
+ });
451
+ } catch {
452
+ formatter = new Intl.NumberFormat("en-US", {
453
+ minimumFractionDigits: 2,
454
+ maximumFractionDigits: 2
455
+ });
456
+ }
457
+ formatterCache.set(normalized, formatter);
458
+ }
459
+ return formatter;
460
+ }
461
+ var subcentFormatterCache = /* @__PURE__ */ new Map();
462
+ function getSubcentFormatter(currency) {
463
+ const normalized = currency.toUpperCase();
464
+ let formatter = subcentFormatterCache.get(normalized);
465
+ if (!formatter) {
466
+ try {
467
+ formatter = new Intl.NumberFormat("en-US", {
468
+ style: "currency",
469
+ currency: normalized,
470
+ minimumFractionDigits: 4,
471
+ maximumFractionDigits: 4
472
+ });
473
+ } catch {
474
+ formatter = new Intl.NumberFormat("en-US", {
475
+ minimumFractionDigits: 4,
476
+ maximumFractionDigits: 4
477
+ });
478
+ }
479
+ subcentFormatterCache.set(normalized, formatter);
480
+ }
481
+ return formatter;
482
+ }
483
+ function formatCurrency(amount, currency = "USD") {
484
+ const formatter = getFormatter(currency);
485
+ return formatter.format(amount);
486
+ }
487
+ function formatCostDisplay(amount, currency = "USD") {
488
+ if (amount !== 0 && Math.abs(amount) < 0.01) {
489
+ return getSubcentFormatter(currency).format(amount);
490
+ }
491
+ return getFormatter(currency).format(amount);
492
+ }
493
+ function formatCurrencyDelta(amount, currency = "USD") {
494
+ const formatted = formatCurrency(Math.abs(amount), currency);
495
+ if (amount > 0) {
496
+ return `+${formatted}`;
497
+ }
498
+ if (amount < 0) {
499
+ return `-${formatted}`;
500
+ }
501
+ return formatted;
502
+ }
503
+
504
+ // src/cli/formatters/tokens.ts
505
+ var numberFormatter = new Intl.NumberFormat("en-US");
506
+ function formatTokenCount(tokens) {
507
+ return `${numberFormatter.format(tokens)} tokens`;
508
+ }
509
+
510
+ // src/cli/commands/cost-cache-tokens.ts
511
+ import chalk from "chalk";
512
+ import { z } from "zod";
513
+ var OptionalTokenCountSchema = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional();
514
+ function cacheTokenEstimates(options) {
515
+ return {
516
+ ...options.cacheRead === void 0 ? {} : { cacheRead: options.cacheRead },
517
+ ...options.cacheWrite === void 0 ? {} : { cacheWrite: options.cacheWrite }
518
+ };
519
+ }
520
+ function printCacheTokenLines(options) {
521
+ if (options.cacheRead !== void 0) {
522
+ console.log(`${chalk.gray("Cache Read Tokens")}: ${formatTokenCount(options.cacheRead)}`);
523
+ }
524
+ if (options.cacheWrite !== void 0) {
525
+ console.log(`${chalk.gray("Cache Write Tokens")}: ${formatTokenCount(options.cacheWrite)}`);
526
+ }
527
+ }
528
+
529
+ // src/cli/commands/cost-daily-days.ts
530
+ function totalCostByDay(rows) {
531
+ const days = /* @__PURE__ */ new Map();
532
+ for (const row of rows) {
533
+ const prior = days.get(row.date);
534
+ days.set(
535
+ row.date,
536
+ row.totalCost === null || prior === null ? null : (prior ?? 0) + row.totalCost
537
+ );
538
+ }
539
+ return [...days].map(([date, cost]) => ({ date, cost }));
540
+ }
541
+ function costExtremeDays(days) {
542
+ const priced = days.filter((day) => day.cost !== null).sort((a, b) => b.cost - a.cost);
543
+ const highest = priced[0];
544
+ const lowest = priced.at(-1);
545
+ return highest && lowest && highest.cost > lowest.cost ? { highest, lowest } : void 0;
546
+ }
547
+
548
+ // src/cli/commands/cost-swarm.ts
549
+ import chalk2 from "chalk";
550
+ function buildSwarmCostBreakdown(rows) {
551
+ const totalCents = rows.reduce((sum, row) => sum + row.totalCostCents, 0);
552
+ return {
553
+ totalCostUsd: totalCents / 100,
554
+ roles: rows.map((row) => ({
555
+ agentRole: row.agentRole,
556
+ tasks: row.totalInvocations,
557
+ pricedTasks: row.pricedInvocations,
558
+ costUsd: row.totalCostCents / 100,
559
+ percentage: totalCents > 0 ? row.totalCostCents / totalCents * 100 : 0,
560
+ avgCostPerPricedTaskUsd: row.pricedInvocations > 0 ? row.totalCostCents / row.pricedInvocations / 100 : null,
561
+ tokensIn: row.totalTokensIn,
562
+ tokensOut: row.totalTokensOut
563
+ }))
564
+ };
565
+ }
566
+ function printSwarmCostBreakdown(breakdown, windowLabel) {
567
+ if (breakdown.roles.length === 0) {
568
+ console.log(chalk2.gray(`
569
+ No swarm executions found in the last ${windowLabel}`));
570
+ return;
571
+ }
572
+ console.log(chalk2.bold.cyan(`
573
+ Swarm Cost Breakdown (last ${windowLabel})
574
+ `));
575
+ for (const role of breakdown.roles) {
576
+ const unpriced = role.tasks - role.pricedTasks;
577
+ const taskNote = unpriced > 0 ? `${role.tasks} tasks, ${unpriced} unpriced` : `${role.tasks} tasks`;
578
+ console.log(
579
+ `${chalk2.bold(role.agentRole.padEnd(15))} ${formatCurrency(role.costUsd)} (${role.percentage.toFixed(1)}%) [${taskNote}]`
580
+ );
581
+ const avg = role.avgCostPerPricedTaskUsd === null ? "" : `, avg per priced task ${formatCurrency(role.avgCostPerPricedTaskUsd)}`;
582
+ console.log(
583
+ `${chalk2.gray(" tokens")}: ${formatTokenCount(role.tokensIn)} in, ${formatTokenCount(role.tokensOut)} out${avg}`
584
+ );
585
+ }
586
+ console.log(chalk2.gray("\nTip: Use role-specific providers to optimize costs per domain"));
587
+ }
588
+
589
+ // src/cli/commands/cost.ts
590
+ function writeCostOutput(value) {
591
+ console.log(value);
592
+ }
593
+ function logCostEmptyStateHint(modelInvocationsDb, startTimestampMs, attempt) {
594
+ const projection = projectCostVisibility(modelInvocationsDb, startTimestampMs, attempt);
595
+ const notice = formatCostProjectionNotice(projection);
596
+ if (notice) {
597
+ writeCostOutput(chalk3.gray(notice));
598
+ }
599
+ }
600
+ function formatDailyAggregationCost(value) {
601
+ return value === null ? "incomplete" : formatCostDisplay(value);
602
+ }
603
+ function sumCompleteDailyCosts(rows) {
604
+ let total = 0;
605
+ for (const row of rows) {
606
+ if (row.totalCost === null) {
607
+ return null;
608
+ }
609
+ total += row.totalCost;
610
+ }
611
+ return total;
612
+ }
613
+ var ToolUsageSchema = z2.object({
614
+ name: z2.string().min(1, "Tool name cannot be empty").max(100, "Tool name too long").regex(/^[a-zA-Z0-9._-]+$/, "Invalid tool name format"),
615
+ estimatedRequests: PositiveIntegerSchema
616
+ });
617
+ var StatusOptionsSchema = z2.object({
618
+ json: BooleanFlagSchema.optional(),
619
+ swarm: BooleanFlagSchema.optional(),
620
+ days: z2.string().regex(/^\d+$/, "Days must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(7),
621
+ outputFile: FilePathSchema.optional(),
622
+ since: z2.string().regex(/^\d+[mhdw]$/, "--since must match pattern like 7d or 24h").optional(),
623
+ lab: z2.union([z2.string(), z2.boolean()]).optional(),
624
+ labId: z2.string().optional(),
625
+ runId: z2.string().optional(),
626
+ verbose: BooleanFlagSchema.optional()
627
+ }).strict().superRefine((data, ctx) => {
628
+ if (data.lab && (data.labId || data.runId)) {
629
+ ctx.addIssue({
630
+ code: z2.ZodIssueCode.custom,
631
+ message: "--lab cannot be combined with --lab-id/--run-id"
632
+ });
633
+ }
634
+ if (data.labId && !data.runId) {
635
+ ctx.addIssue({ code: z2.ZodIssueCode.custom, message: "--lab-id requires --run-id" });
636
+ }
637
+ if (data.runId && !data.labId) {
638
+ ctx.addIssue({ code: z2.ZodIssueCode.custom, message: "--run-id requires --lab-id" });
639
+ }
640
+ });
641
+ var PredictOptionsSchema = z2.object({
642
+ input: PositiveIntegerSchema,
643
+ output: PositiveIntegerSchema,
644
+ cacheRead: OptionalTokenCountSchema,
645
+ cacheWrite: OptionalTokenCountSchema,
646
+ tool: z2.array(ToolUsageSchema).optional(),
647
+ json: BooleanFlagSchema.optional()
648
+ }).strict();
649
+ var CompareOptionsSchema = z2.object({
650
+ input: PositiveIntegerSchema,
651
+ output: PositiveIntegerSchema,
652
+ cacheRead: OptionalTokenCountSchema,
653
+ cacheWrite: OptionalTokenCountSchema,
654
+ json: BooleanFlagSchema.optional()
655
+ }).strict();
656
+ var DailyOptionsSchema = z2.object({
657
+ days: z2.string().regex(/^\d+$/, "Days must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(7),
658
+ start: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Start date must be in YYYY-MM-DD format").optional(),
659
+ end: z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "End date must be in YYYY-MM-DD format").optional(),
660
+ group: z2.enum(["date", "provider", "model"]).optional().default("date"),
661
+ json: BooleanFlagSchema.optional()
662
+ }).strict().refine((data) => {
663
+ if (data.start && data.end) {
664
+ const start = new Date(data.start);
665
+ const end = new Date(data.end);
666
+ return start <= end;
667
+ }
668
+ return true;
669
+ }, "Start date cannot be after end date");
670
+ var ForecastOptionsSchema = z2.object({
671
+ days: z2.string().regex(/^\d+$/, "Days must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(7),
672
+ horizon: z2.string().regex(/^\d+$/, "Horizon must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(7),
673
+ json: BooleanFlagSchema.optional()
674
+ }).strict();
675
+ var HistoryOptionsSchema = z2.object({
676
+ task: z2.string().min(1).max(100).optional(),
677
+ competition: z2.string().min(1).max(100).optional(),
678
+ recalculate: z2.union([
679
+ z2.enum(["current", "snapshot"]),
680
+ z2.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format")
681
+ ]).optional(),
682
+ days: z2.string().regex(/^\d+$/, "Days must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(7),
683
+ json: BooleanFlagSchema.optional()
684
+ }).strict();
685
+ var TasksOptionsSchema = z2.object({
686
+ days: z2.string().regex(/^\d+$/, "Days must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(7),
687
+ top: z2.string().regex(/^\d+$/, "Top must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(10),
688
+ json: BooleanFlagSchema.optional()
689
+ }).strict();
690
+ var TokensOptionsSchema = z2.object({
691
+ days: z2.string().regex(/^\d+$/, "Days must be a positive integer").transform(Number).pipe(PositiveIntegerSchema).optional().default(7),
692
+ provider: z2.string().min(1).max(100).optional(),
693
+ model: ModelNameSchema.optional(),
694
+ json: BooleanFlagSchema.optional()
695
+ }).strict();
696
+ var ComparePricingOptionsSchema = z2.object({
697
+ json: BooleanFlagSchema.optional()
698
+ }).strict();
699
+ function mergePersistedCostMetrics(metrics, recentExecutions, windowStartMs, now = Date.now()) {
700
+ if (recentExecutions.length === 0) {
701
+ return metrics;
702
+ }
703
+ const sourceSamples = metrics[UNIFIED_COST_METRIC_SOURCE_SAMPLES] ?? [];
704
+ const remainingSourceSamples = sourceSamples.map((sample) => ({
705
+ ...sample,
706
+ // Use sub-cent precision (6 dp) to match the stored CostSnapshot.totalCostCents,
707
+ // which is stored at that precision. Whole-cent rounding here caused
708
+ // sub-cent invocations (< 0.5 cent) to produce totalCostCents=0 in the
709
+ // deduplication key, mismatching the persisted record and double-counting them.
710
+ totalCostCents: Math.round(sample.totalCost * 100 * 1e6) / 1e6
711
+ }));
712
+ const nonOverlappingExecutions = recentExecutions.filter((execution) => {
713
+ const executionCostCents = execution.costSnapshot.totalCostCents;
714
+ const exactExecutionIdIndex = remainingSourceSamples.findIndex(
715
+ (sample) => sample.executionId && sample.executionId === execution.executionId
716
+ );
717
+ if (exactExecutionIdIndex >= 0) {
718
+ remainingSourceSamples.splice(exactExecutionIdIndex, 1);
719
+ return false;
720
+ }
721
+ const matchingSampleIndex = remainingSourceSamples.findIndex(
722
+ (sample) => sample.provider === execution.provider && sample.model === execution.model && sample.totalCostCents === executionCostCents && Math.abs(sample.timestamp - execution.timestamp.getTime()) <= 2e3
723
+ );
724
+ if (matchingSampleIndex >= 0) {
725
+ remainingSourceSamples.splice(matchingSampleIndex, 1);
726
+ return false;
727
+ }
728
+ return true;
729
+ });
730
+ if (nonOverlappingExecutions.length === 0) {
731
+ return metrics;
732
+ }
733
+ const dayWindow = now - 24 * 60 * 60 * 1e3;
734
+ const monthWindow = now - 30 * 24 * 60 * 60 * 1e3;
735
+ const persistedDailyCost = nonOverlappingExecutions.filter((execution) => execution.timestamp.getTime() >= dayWindow).reduce((sum, execution) => sum + execution.costSnapshot.totalCostCents / 100, 0);
736
+ const persistedMonthlyCost = nonOverlappingExecutions.filter((execution) => execution.timestamp.getTime() >= monthWindow).reduce((sum, execution) => sum + execution.costSnapshot.totalCostCents / 100, 0);
737
+ const windowExecutions = nonOverlappingExecutions.filter(
738
+ (execution) => execution.timestamp.getTime() >= windowStartMs
739
+ );
740
+ const persistedWindowCost = windowExecutions.reduce(
741
+ (sum, execution) => sum + execution.costSnapshot.totalCostCents / 100,
742
+ 0
743
+ );
744
+ const byProviderModel = /* @__PURE__ */ new Map();
745
+ for (const execution of windowExecutions) {
746
+ const key = `${execution.provider}::${execution.model}`;
747
+ const current = byProviderModel.get(key);
748
+ const cost = execution.costSnapshot.totalCostCents / 100;
749
+ if (current) {
750
+ current.cost += cost;
751
+ } else {
752
+ byProviderModel.set(key, {
753
+ provider: execution.provider,
754
+ model: execution.model,
755
+ cost
756
+ });
757
+ }
758
+ }
759
+ const top = [...byProviderModel.values()].sort((a, b) => b.cost - a.cost)[0];
760
+ const dailyCost = metrics.dailyCost + persistedDailyCost;
761
+ const monthlyCost = metrics.monthlyCost + persistedMonthlyCost;
762
+ const sessionCost = metrics.sessionCost + persistedWindowCost;
763
+ return {
764
+ ...metrics,
765
+ sessionCost,
766
+ dailyCost,
767
+ monthlyCost,
768
+ topCostProvider: top ? {
769
+ provider: top.provider,
770
+ model: top.model,
771
+ cost: top.cost,
772
+ percentage: sessionCost > 0 ? top.cost / sessionCost * 100 : 0
773
+ } : metrics.topCostProvider,
774
+ costTrend: metrics.costTrend.length > 0 ? metrics.costTrend : windowExecutions.slice(-10).map((execution) => execution.costSnapshot.totalCostCents / 100)
775
+ };
776
+ }
777
+ async function verifyPricingForStatus(costCalculator, telemetry, scopeToProviders) {
778
+ const calculatorWithProviders = costCalculator;
779
+ if (typeof calculatorWithProviders.getAvailableProviders !== "function") {
780
+ return { valid: true, providersChecked: [], warnings: [], errors: [] };
781
+ }
782
+ try {
783
+ const providers = calculatorWithProviders.getAvailableProviders().filter((provider) => !scopeToProviders || scopeToProviders.includes(provider.toLowerCase()));
784
+ const verifier = new PricingVerifier(costCalculator, telemetry);
785
+ const results = await Promise.all(
786
+ providers.map((provider) => verifier.verifyProvider(provider))
787
+ );
788
+ return {
789
+ valid: results.every((result) => result.valid),
790
+ providersChecked: providers,
791
+ warnings: results.flatMap((result) => result.warnings),
792
+ errors: results.flatMap((result) => result.errors)
793
+ };
794
+ } catch (error) {
795
+ return {
796
+ valid: false,
797
+ providersChecked: [],
798
+ warnings: [],
799
+ errors: [
800
+ {
801
+ type: "calculation_error",
802
+ message: error instanceof Error ? error.message : String(error),
803
+ provider: "all"
804
+ }
805
+ ]
806
+ };
807
+ }
808
+ }
809
+ function resolveCostLabRun(options) {
810
+ if (options.lab) {
811
+ const selector = typeof options.lab === "string" ? options.lab.trim().toLowerCase() : options.lab === true ? "latest" : null;
812
+ if (!selector || selector === "latest") {
813
+ const latest = findLatestLabRun();
814
+ if (!latest) {
815
+ throw new Error(
816
+ "No lab runs found. Start a lab run with `build run competition --lab` before querying cost status."
817
+ );
818
+ }
819
+ return latest;
820
+ }
821
+ throw new Error("Unsupported --lab value. Supported value: latest.");
822
+ }
823
+ if (options.labId && options.runId) {
824
+ const run = findLabRun(options.labId, options.runId);
825
+ if (!run) {
826
+ throw new Error(`Lab run not found: ${options.labId}/${options.runId}`);
827
+ }
828
+ return run;
829
+ }
830
+ return null;
831
+ }
832
+ function listJsonlFiles(dir) {
833
+ let entries;
834
+ try {
835
+ entries = fs.readdirSync(dir, { withFileTypes: true });
836
+ } catch {
837
+ return [];
838
+ }
839
+ const files = [];
840
+ for (const entry of entries) {
841
+ const filePath = path.join(dir, entry.name);
842
+ if (entry.isDirectory()) {
843
+ files.push(...listJsonlFiles(filePath));
844
+ } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
845
+ files.push(filePath);
846
+ }
847
+ }
848
+ return files;
849
+ }
850
+ function readLabCostSummary(run, startTimeMs) {
851
+ const executions = [];
852
+ for (const filePath of listJsonlFiles(path.join(run.runPath, "logs"))) {
853
+ let contents;
854
+ try {
855
+ contents = fs.readFileSync(filePath, "utf8");
856
+ } catch {
857
+ continue;
858
+ }
859
+ for (const line of contents.split(/\n/)) {
860
+ if (!line.trim()) continue;
861
+ let record;
862
+ try {
863
+ record = JSON.parse(line);
864
+ } catch {
865
+ continue;
866
+ }
867
+ if (record.event !== "model_invocation") continue;
868
+ const timestamp = typeof record.timestamp === "string" ? Date.parse(record.timestamp) : typeof record.timestamp === "number" ? record.timestamp : Number.NaN;
869
+ if (!Number.isFinite(timestamp) || timestamp < startTimeMs) continue;
870
+ const totalCost = typeof record.totalCost === "number" ? record.totalCost : 0;
871
+ if (!Number.isFinite(totalCost)) continue;
872
+ executions.push({
873
+ timestamp: new Date(timestamp),
874
+ provider: typeof record.provider === "string" ? record.provider : "unknown",
875
+ model: typeof record.model === "string" ? record.model : "unknown",
876
+ totalCost
877
+ });
878
+ }
879
+ }
880
+ return { run, executions };
881
+ }
882
+ function mergeLabCostMetrics(metrics, summary, periodExecutions = summary.executions, now = Date.now()) {
883
+ const dayWindow = now - 24 * 60 * 60 * 1e3;
884
+ const monthWindow = now - 30 * 24 * 60 * 60 * 1e3;
885
+ const sessionCost = summary.executions.reduce((sum, execution) => sum + execution.totalCost, 0);
886
+ const dailyCost = periodExecutions.filter((execution) => execution.timestamp.getTime() >= dayWindow).reduce((sum, execution) => sum + execution.totalCost, 0);
887
+ const monthlyCost = periodExecutions.filter((execution) => execution.timestamp.getTime() >= monthWindow).reduce((sum, execution) => sum + execution.totalCost, 0);
888
+ const byProviderModel = /* @__PURE__ */ new Map();
889
+ for (const execution of summary.executions) {
890
+ const key = `${execution.provider}::${execution.model}`;
891
+ const current = byProviderModel.get(key);
892
+ if (current) {
893
+ current.cost += execution.totalCost;
894
+ } else {
895
+ byProviderModel.set(key, {
896
+ provider: execution.provider,
897
+ model: execution.model,
898
+ cost: execution.totalCost
899
+ });
900
+ }
901
+ }
902
+ const top = [...byProviderModel.values()].sort((a, b) => b.cost - a.cost)[0];
903
+ return {
904
+ ...metrics,
905
+ sessionCost,
906
+ dailyCost,
907
+ monthlyCost,
908
+ topCostProvider: top ? {
909
+ provider: top.provider,
910
+ model: top.model,
911
+ cost: top.cost,
912
+ percentage: sessionCost > 0 ? top.cost / sessionCost * 100 : 0
913
+ } : {
914
+ provider: "none",
915
+ model: "none",
916
+ cost: 0,
917
+ percentage: 0
918
+ },
919
+ costTrend: summary.executions.slice(-10).map((execution) => execution.totalCost)
920
+ };
921
+ }
922
+ function parseNonNegativeInteger(value) {
923
+ const parsed = Number.parseInt(value, 10);
924
+ if (!Number.isFinite(parsed) || parsed < 0) {
925
+ throw new InvalidArgumentError("Value must be a non-negative integer");
926
+ }
927
+ return parsed;
928
+ }
929
+ function collectRawToolUsage(value, previous = []) {
930
+ return [...previous, value];
931
+ }
932
+ function parseWholeNonNegativeInteger(value, message) {
933
+ if (!/^\d+$/.test(value)) {
934
+ throw new InvalidArgumentError(message);
935
+ }
936
+ return Number(value);
937
+ }
938
+ function parsePredictTokenOption(value) {
939
+ return parseWholeNonNegativeInteger(value, "Value must be a non-negative integer");
940
+ }
941
+ function parseOptionalPredictTokenOption(value) {
942
+ return value === void 0 ? void 0 : parsePredictTokenOption(value);
943
+ }
944
+ function parsePredictToolUsageEntry(value) {
945
+ const [name, requests] = value.split(":");
946
+ if (!name || !requests) {
947
+ throw new InvalidArgumentError("Tool usage must be formatted as name:requests");
948
+ }
949
+ const parsed = parseWholeNonNegativeInteger(
950
+ requests,
951
+ "Tool requests must be a non-negative integer"
952
+ );
953
+ return { name, estimatedRequests: parsed };
954
+ }
955
+ function toPredictJsonError(error) {
956
+ if (error instanceof InvalidArgumentError) {
957
+ return new ValidationError(error.message);
958
+ }
959
+ if (error instanceof z2.ZodError) {
960
+ return new ValidationError(formatValidationErrors(error));
961
+ }
962
+ if (error instanceof Error && error.message.startsWith("Invalid command options")) {
963
+ return new ValidationError(error.message);
964
+ }
965
+ return error;
966
+ }
967
+ function toToolUsage(estimates) {
968
+ return estimates.map((estimate) => ({
969
+ name: estimate.name,
970
+ requests: estimate.estimatedRequests
971
+ }));
972
+ }
973
+ function printCostBreakdown(label, breakdown) {
974
+ console.log(chalk3.bold.cyan(`
975
+ ${label}
976
+ `));
977
+ console.log(`${chalk3.gray("Provider")}: ${breakdown.provider}`);
978
+ console.log(`${chalk3.gray("Model")}: ${breakdown.model}`);
979
+ if (isPricingUnavailable(breakdown)) {
980
+ console.log(`${chalk3.gray("Total Cost")}: unavailable`);
981
+ console.log(`${chalk3.gray("Breakdown")}: unavailable`);
982
+ } else {
983
+ const total = breakdown.totalCostAmount.status === "available" ? breakdown.totalCostAmount.amount : breakdown.totalCost;
984
+ console.log(`${chalk3.gray("Total Cost")}: ${formatCurrency(total, breakdown.currency)}`);
985
+ console.log(
986
+ `${chalk3.gray("Breakdown")}: input ${formatCurrency(breakdown.inputCost, breakdown.currency)} | output ${formatCurrency(breakdown.outputCost, breakdown.currency)} | cache ${formatCurrency(breakdown.cacheCost, breakdown.currency)} | tools ${formatCurrency(breakdown.toolCosts, breakdown.currency)} | infra ${formatCurrency(breakdown.infrastructureCost, breakdown.currency)}`
987
+ );
988
+ }
989
+ console.log(`${chalk3.gray("Pricing Version")}: ${breakdown.pricingVersion}`);
990
+ if (isPricingUnavailable(breakdown)) {
991
+ console.log(chalk3.yellow(`${chalk3.gray("Pricing Status")}: unavailable`));
992
+ if (breakdown.pricingError) {
993
+ console.log(chalk3.yellow(`${chalk3.gray("Pricing Error")}: ${breakdown.pricingError}`));
994
+ }
995
+ return;
996
+ }
997
+ if (breakdown.billingMode !== "metered") {
998
+ const modeDescription = breakdown.billingMode === "non_metered" ? "non-metered" : breakdown.billingMode.replace(/_/g, " ");
999
+ console.log(
1000
+ chalk3.yellow(
1001
+ `Note: ${breakdown.provider}/${breakdown.model} is tracked as ${modeDescription}. Per-token cost fields are shown as $0 because billing is handled via seat or flat-rate licensing.`
1002
+ )
1003
+ );
1004
+ }
1005
+ }
1006
+ function isPricingUnavailable(breakdown) {
1007
+ return breakdown.pricingStatus === "unavailable" || breakdown.totalCostAmount.status !== "available";
1008
+ }
1009
+ function availableBreakdownUsd(breakdown) {
1010
+ return breakdown.totalCostAmount.status === "available" ? breakdown.totalCostAmount.amount : null;
1011
+ }
1012
+ function createCostCommand(deps) {
1013
+ const cost = new Command("cost");
1014
+ cost.alias("$");
1015
+ cost.description(
1016
+ "Cost tracking, forecasting, and comparison utilities\n\nExamples:\n build telemetry cost status\n build telemetry cost predict cursor auto --input 1000 --output 500\n build telemetry cost compare cursor:auto cursor:auto --input 1000 --output 500"
1017
+ );
1018
+ cost.command("status").description(
1019
+ "Show current real-time cost tracking metrics\n\nExamples:\n build telemetry cost status\n build telemetry cost status --swarm --days 14"
1020
+ ).option("--json", "(OPTIONAL) Output metrics as JSON").option("-v, --verbose", "(OPTIONAL) Include all pricing warnings, even for unused providers").option(
1021
+ "--swarm",
1022
+ "(OPTIONAL) Show cost breakdown by agent role (for swarm executions)\n Example: --swarm"
1023
+ ).option(
1024
+ "--days <days>",
1025
+ "(OPTIONAL) Number of days to look back for swarm costs (default: 7)\n Example: --days 14",
1026
+ "7"
1027
+ ).option(
1028
+ "--since <window>",
1029
+ "(OPTIONAL) Filter cost data to a time window (e.g. 7d, 24h, 30m, 1w)\n Example: --since 7d"
1030
+ ).option(
1031
+ "--output-file <path>",
1032
+ "(OPTIONAL) Save the cost report as JSON to the specified file path\n Example: --output-file cost-report.json"
1033
+ ).option("--lab [selector]", "(OPTIONAL) Use lab cost data (value: latest)").option("--lab-id <labId>", "(OPTIONAL) Specify lab ID (requires --run-id)").option("--run-id <runId>", "(OPTIONAL) Specify run ID (requires --lab-id)").action(async (options) => {
1034
+ const validatedOptions = validateCommandOptions(StatusOptionsSchema, options);
1035
+ const costTracker = await deps.costTracker;
1036
+ const telemetry = await deps.telemetry;
1037
+ const modelInvocationsDb = await deps.modelInvocationsDb;
1038
+ const costCalculator = await deps.costCalculator;
1039
+ if (telemetry.databaseModule && !validatedOptions.json) {
1040
+ telemetry.databaseModule.printDbBanner();
1041
+ }
1042
+ if (!validatedOptions.json) {
1043
+ checkAndWarnLabContext();
1044
+ }
1045
+ if (!costTracker) {
1046
+ console.error(chalk3.red("Cost tracker not available"));
1047
+ process.exit(1);
1048
+ }
1049
+ let startTime;
1050
+ let windowLabel;
1051
+ if (validatedOptions.since) {
1052
+ const parsedMs = parseDuration(validatedOptions.since);
1053
+ startTime = Date.now() - (parsedMs ?? 7 * 24 * 60 * 60 * 1e3);
1054
+ windowLabel = validatedOptions.since;
1055
+ } else {
1056
+ const daysBack = validatedOptions.days ?? 7;
1057
+ startTime = Date.now() - daysBack * 24 * 60 * 60 * 1e3;
1058
+ windowLabel = `${daysBack} days`;
1059
+ }
1060
+ const labRun = resolveCostLabRun({
1061
+ lab: validatedOptions.lab,
1062
+ labId: validatedOptions.labId,
1063
+ runId: validatedOptions.runId
1064
+ });
1065
+ const enrichmentAttempt = await ensurePendingInvocationCostEnrichment(modelInvocationsDb);
1066
+ const metricsStart = Math.min(startTime, Date.now() - 30 * 24 * 60 * 60 * 1e3);
1067
+ const inWindow = (e) => e.timestamp.getTime() >= startTime;
1068
+ const labPeriod = labRun ? readLabCostSummary(labRun, metricsStart) : null;
1069
+ const labCostSummary = labPeriod && {
1070
+ run: labPeriod.run,
1071
+ executions: labPeriod.executions.filter(inWindow)
1072
+ };
1073
+ const metricsExecutions = labCostSummary ? [] : modelInvocationsDb.getExecutionCostsSince(metricsStart);
1074
+ const recentExecutions = metricsExecutions.filter(inWindow);
1075
+ const metrics = labCostSummary ? mergeLabCostMetrics(
1076
+ costTracker.getCurrentMetrics(),
1077
+ labCostSummary,
1078
+ labPeriod?.executions
1079
+ ) : mergePersistedCostMetrics(costTracker.getCurrentMetrics(), metricsExecutions, startTime);
1080
+ const windowProviders = labCostSummary ? labCostSummary.executions.map((execution) => execution.provider.toLowerCase()) : listInvocationProviderIdsSince(modelInvocationsDb, startTime);
1081
+ const pricingVerification = await verifyPricingForStatus(
1082
+ costCalculator,
1083
+ telemetry,
1084
+ validatedOptions.verbose ? void 0 : windowProviders
1085
+ );
1086
+ const invocationVisibility = labCostSummary ? {
1087
+ rawInvocationCount: labCostSummary.executions.length,
1088
+ enrichedInvocationCount: labCostSummary.executions.length,
1089
+ pendingEnrichmentCount: 0,
1090
+ // Lab summaries are read from JSONL rows that already carry cost;
1091
+ // there is no unpriced enrichment state to report for them.
1092
+ unpricedInvocationCount: 0,
1093
+ visibility: labCostSummary.executions.length > 0 ? "enriched" : "no_invocations",
1094
+ hint: labCostSummary.executions.length > 0 ? void 0 : "No lab model invocations recorded in this window."
1095
+ } : summarizeInvocationCostVisibility(modelInvocationsDb, startTime);
1096
+ const costProjection = fromVisibilitySummary(
1097
+ invocationVisibility,
1098
+ labCostSummary ? void 0 : enrichmentAttempt
1099
+ );
1100
+ const pricingWarningsForView = validatedOptions.verbose ? pricingVerification.warnings : pricingVerification.warnings.filter((warning) => !isExpectedFreeZeroCostWarning(warning));
1101
+ const pricingVerificationForView = {
1102
+ ...pricingVerification,
1103
+ warnings: pricingWarningsForView
1104
+ };
1105
+ const swarmBreakdown = validatedOptions.swarm ? buildSwarmCostBreakdown(modelInvocationsDb.getRoleCostBreakdown(startTime)) : void 0;
1106
+ const statusPayload = {
1107
+ ...metrics,
1108
+ ...swarmBreakdown ? { swarmBreakdown } : {},
1109
+ pricingVerification: pricingVerificationForView,
1110
+ invocationVisibility,
1111
+ costProjection,
1112
+ labContext: labCostSummary ? {
1113
+ labId: labCostSummary.run.labId,
1114
+ runId: labCostSummary.run.runId,
1115
+ source: "lab-jsonl"
1116
+ } : null
1117
+ };
1118
+ telemetry.logCostEvent("cli_cost_status_viewed", {
1119
+ sessionCost: metrics.sessionCost,
1120
+ dailyCost: metrics.dailyCost,
1121
+ monthlyCost: metrics.monthlyCost,
1122
+ alertCount: metrics.activeAlerts.length,
1123
+ optimizationCount: metrics.availableOptimizations.length,
1124
+ pricingWarningCount: pricingVerification.warnings.length,
1125
+ pricingErrorCount: pricingVerification.errors.length,
1126
+ swarmView: validatedOptions.swarm ?? false,
1127
+ rawInvocationCount: invocationVisibility.rawInvocationCount,
1128
+ enrichedInvocationCount: invocationVisibility.enrichedInvocationCount,
1129
+ pendingEnrichmentCount: invocationVisibility.pendingEnrichmentCount,
1130
+ unpricedInvocationCount: invocationVisibility.unpricedInvocationCount,
1131
+ visibility: invocationVisibility.visibility,
1132
+ labId: labCostSummary?.run.labId ?? null,
1133
+ runId: labCostSummary?.run.runId ?? null
1134
+ });
1135
+ if (validatedOptions.outputFile) {
1136
+ const { writeFile } = await import("fs/promises");
1137
+ try {
1138
+ await writeFile(
1139
+ validatedOptions.outputFile,
1140
+ JSON.stringify(statusPayload, null, 2),
1141
+ "utf8"
1142
+ );
1143
+ } catch (err) {
1144
+ console.error(
1145
+ chalk3.red(
1146
+ `Failed to write output file: ${err instanceof Error ? err.message : String(err)}`
1147
+ )
1148
+ );
1149
+ process.exitCode = 1;
1150
+ return;
1151
+ }
1152
+ }
1153
+ if (validatedOptions.json) {
1154
+ console.log(JSON.stringify(statusPayload, null, 2));
1155
+ return;
1156
+ }
1157
+ console.log(chalk3.bold.cyan("\nCost: Cost Tracking Status\n"));
1158
+ if (labCostSummary) {
1159
+ console.log(
1160
+ `${chalk3.gray("Lab Run")}: ${labCostSummary.run.labId}/${labCostSummary.run.runId}`
1161
+ );
1162
+ }
1163
+ console.log(`${chalk3.gray("Session Cost")}: ${formatCurrency(metrics.sessionCost)}`);
1164
+ console.log(`${chalk3.gray("Daily Cost")}: ${formatCurrency(metrics.dailyCost)}`);
1165
+ console.log(`${chalk3.gray("Monthly Cost")}: ${formatCurrency(metrics.monthlyCost)}`);
1166
+ console.log(`${chalk3.gray("Cost / Minute")}: ${formatCurrency(metrics.costPerMinute)}`);
1167
+ const top = metrics.topCostProvider;
1168
+ console.log(
1169
+ `${chalk3.gray("Top Contributor")}: ${top.provider}/${top.model} (${formatCurrency(top.cost)} | ${top.percentage.toFixed(1)}%)`
1170
+ );
1171
+ if (metrics.costTrend.length > 0) {
1172
+ const trend = metrics.costTrend.map((value) => formatCurrency(value)).join(chalk3.gray(" -> "));
1173
+ console.log(`${chalk3.gray("Recent Trend")}: ${trend}`);
1174
+ } else {
1175
+ const trendNote = invocationVisibility.rawInvocationCount > 0 ? "No priced executions in this window" : "No executions recorded";
1176
+ console.log(`${chalk3.gray("Recent Trend")}: ${chalk3.gray(trendNote)}`);
1177
+ }
1178
+ if (metrics.sessionCost === 0 || costProjection.state !== "enriched" || costProjection.unpricedInvocationCount > 0) {
1179
+ const projectionNotice = formatCostProjectionNotice(costProjection);
1180
+ if (projectionNotice) {
1181
+ console.log(chalk3.gray(projectionNotice));
1182
+ }
1183
+ }
1184
+ if (modelInvocationsDb.hasNonMeteredBilling()) {
1185
+ console.log(
1186
+ chalk3.gray(
1187
+ "Info: Seat-licensed providers (e.g., Copilot CLI) are tracked for usage but excluded from per-token totals."
1188
+ )
1189
+ );
1190
+ }
1191
+ if (recentExecutions.length > 0) {
1192
+ const snapshotCost = recentExecutions.reduce(
1193
+ (sum, exec) => sum + exec.costSnapshot.totalCostCents,
1194
+ 0
1195
+ );
1196
+ let recalculatedCost = 0;
1197
+ for (const exec of recentExecutions) {
1198
+ const newCost = modelInvocationsDb.recalculateCost(
1199
+ exec.executionId,
1200
+ (provider, model, usage) => {
1201
+ try {
1202
+ const breakdown = costCalculator.calculateCost(
1203
+ provider,
1204
+ model,
1205
+ storedUsageToUsageData(usage)
1206
+ );
1207
+ const availableUsd = availableBreakdownUsd(breakdown);
1208
+ if (availableUsd === null) {
1209
+ return exec.costSnapshot.totalCostCents;
1210
+ }
1211
+ return availableUsd * 100;
1212
+ } catch {
1213
+ return exec.costSnapshot.totalCostCents;
1214
+ }
1215
+ }
1216
+ );
1217
+ recalculatedCost += newCost ?? exec.costSnapshot.totalCostCents;
1218
+ }
1219
+ console.log(chalk3.bold.cyan("\nCost: Cost Basis Comparison\n"));
1220
+ console.log(
1221
+ `${chalk3.gray("Historical (snapshot)")}: ${formatCurrency(snapshotCost / 100)}`
1222
+ );
1223
+ console.log(`${chalk3.gray("Current pricing")}: ${formatCurrency(recalculatedCost / 100)}`);
1224
+ if (Math.abs(recalculatedCost - snapshotCost) > 0.01) {
1225
+ const delta = recalculatedCost - snapshotCost;
1226
+ const pct = snapshotCost === 0 ? "percentage unavailable: zero historical cost" : `${(delta / snapshotCost * 100).toFixed(1)}%`;
1227
+ const direction = delta > 0 ? "up" : "down";
1228
+ const color = delta > 0 ? chalk3.red : chalk3.green;
1229
+ console.log(
1230
+ `${chalk3.gray("Price change")}: ${color(`${direction} ${formatCurrency(Math.abs(delta) / 100)} (${pct})`)}`
1231
+ );
1232
+ } else {
1233
+ console.log(`${chalk3.gray("Price change")}: ${chalk3.gray("No change")}`);
1234
+ }
1235
+ }
1236
+ if (swarmBreakdown) {
1237
+ printSwarmCostBreakdown(swarmBreakdown, windowLabel);
1238
+ }
1239
+ if (metrics.activeAlerts.length > 0) {
1240
+ console.log(chalk3.bold.yellow("\nWarning: Internal Cost Heuristics"));
1241
+ metrics.activeAlerts.forEach((alert) => {
1242
+ console.log(
1243
+ `${alert.severity.toUpperCase()} | ${alert.type} | ${alert.message} (${formatCurrency(alert.currentCost)} / ${formatCurrency(alert.threshold)})`
1244
+ );
1245
+ });
1246
+ } else {
1247
+ console.log(chalk3.gray("\nNo internal cost heuristic alerts"));
1248
+ }
1249
+ if (pricingVerificationForView.warnings.length > 0 || pricingVerification.errors.length > 0) {
1250
+ console.log(chalk3.bold.yellow("\nWarning: Pricing Data"));
1251
+ for (const warning of pricingVerificationForView.warnings) {
1252
+ const provider = warning.provider ? `${warning.provider}: ` : "";
1253
+ console.log(`${warning.severity.toUpperCase()} | ${provider}${warning.message}`);
1254
+ }
1255
+ for (const error of pricingVerification.errors) {
1256
+ console.log(`ERROR | ${error.provider}: ${error.message}`);
1257
+ }
1258
+ }
1259
+ if (metrics.availableOptimizations.length > 0) {
1260
+ console.log(chalk3.bold.green("\nTip: Optimization Suggestions"));
1261
+ metrics.availableOptimizations.forEach((suggestion) => {
1262
+ console.log(
1263
+ `${suggestion.title} | saves ${formatCurrency(suggestion.estimatedSavings)} (${suggestion.estimatedSavingsPercent.toFixed(1)}%) | confidence ${(suggestion.confidence * 100).toFixed(0)}%`
1264
+ );
1265
+ });
1266
+ }
1267
+ });
1268
+ cost.command("predict").description(
1269
+ "Predict execution cost for a provider/model pair\n\nExamples:\n build telemetry cost predict cursor auto --input 1000 --output 500\n build telemetry cost predict claude sonnet --input 2000 --output 1000 --tool search:5"
1270
+ ).argument("<provider>", "(REQUIRED) Provider identifier (e.g. anthropic)").argument("<model>", "(REQUIRED) Model name or alias (e.g. auto)").requiredOption(
1271
+ "--input <tokens>",
1272
+ "(REQUIRED) Estimated input tokens\n Example: --input 1000"
1273
+ ).requiredOption(
1274
+ "--output <tokens>",
1275
+ "(REQUIRED) Estimated output tokens\n Example: --output 500"
1276
+ ).option(
1277
+ "--cache-read <tokens>",
1278
+ "(OPTIONAL) Estimated cache-read tokens, priced on top of --input\n Example: --cache-read 20000"
1279
+ ).option(
1280
+ "--cache-write <tokens>",
1281
+ "(OPTIONAL) Estimated cache-write tokens, priced at the cache-write rate\n Example: --cache-write 5000"
1282
+ ).option(
1283
+ "--tool <usage>",
1284
+ "(OPTIONAL) Tool usage in name:requests format (repeatable)\n Example: --tool search:5",
1285
+ collectRawToolUsage,
1286
+ []
1287
+ ).option("--json", "(OPTIONAL) Output breakdown as JSON").action(async (provider, model, options) => {
1288
+ const jsonMode = Boolean(options.json);
1289
+ try {
1290
+ const parsedInput = parsePredictTokenOption(options.input);
1291
+ const parsedOutput = parsePredictTokenOption(options.output);
1292
+ const parsedCacheRead = parseOptionalPredictTokenOption(options.cacheRead);
1293
+ const parsedCacheWrite = parseOptionalPredictTokenOption(options.cacheWrite);
1294
+ const parsedTools = (options.tool ?? []).map(parsePredictToolUsageEntry);
1295
+ const costCalculator = await deps.costCalculator;
1296
+ const telemetry = await deps.telemetry;
1297
+ const validatedProvider = z2.string().min(1, "Provider cannot be empty").max(100, "Provider name too long").regex(/^[a-zA-Z0-9._-]+$/, "Invalid provider name format").parse(provider);
1298
+ const validatedModel = ModelNameSchema.parse(model);
1299
+ const validatedOptions = validateCommandOptions(PredictOptionsSchema, {
1300
+ input: parsedInput,
1301
+ output: parsedOutput,
1302
+ cacheRead: parsedCacheRead,
1303
+ cacheWrite: parsedCacheWrite,
1304
+ tool: parsedTools.length > 0 ? parsedTools : void 0,
1305
+ json: options.json
1306
+ });
1307
+ await deps.ensurePricingLoaded();
1308
+ const tools = validatedOptions.tool ? toToolUsage(validatedOptions.tool) : [];
1309
+ const breakdown = costCalculator.predictCost(validatedProvider, validatedModel, {
1310
+ input: validatedOptions.input,
1311
+ output: validatedOptions.output,
1312
+ ...cacheTokenEstimates(validatedOptions),
1313
+ tools: tools.map((tool) => ({
1314
+ name: tool.name,
1315
+ estimatedRequests: tool.requests
1316
+ }))
1317
+ });
1318
+ telemetry.logCostEvent("cli_cost_predict", {
1319
+ provider: validatedProvider,
1320
+ model: validatedModel,
1321
+ inputTokens: validatedOptions.input,
1322
+ outputTokens: validatedOptions.output,
1323
+ cacheReadTokens: validatedOptions.cacheRead,
1324
+ cacheWriteTokens: validatedOptions.cacheWrite,
1325
+ tools: tools.length,
1326
+ totalCost: availableBreakdownUsd(breakdown),
1327
+ costStatus: breakdown.totalCostAmount.status,
1328
+ currency: breakdown.currency,
1329
+ pricingStatus: breakdown.pricingStatus
1330
+ });
1331
+ if (validatedOptions.json) {
1332
+ renderJsonResult(breakdown);
1333
+ return;
1334
+ }
1335
+ printCostBreakdown("Predictive: Cost Prediction", breakdown);
1336
+ console.log(`${chalk3.gray("Input Tokens")}: ${formatTokenCount(validatedOptions.input)}`);
1337
+ console.log(`${chalk3.gray("Output Tokens")}: ${formatTokenCount(validatedOptions.output)}`);
1338
+ printCacheTokenLines(validatedOptions);
1339
+ if (tools.length > 0) {
1340
+ const toolSummary = tools.map((tool) => `${tool.name} \xD7 ${tool.requests}`).join(chalk3.gray(", "));
1341
+ console.log(`${chalk3.gray("Tools")}: ${toolSummary}`);
1342
+ }
1343
+ } catch (error) {
1344
+ if (jsonMode) {
1345
+ renderJsonError(toPredictJsonError(error));
1346
+ process.exitCode = 1;
1347
+ return;
1348
+ }
1349
+ throw error;
1350
+ }
1351
+ });
1352
+ cost.command("compare").description(
1353
+ "Compare predicted costs across multiple provider/model pairs\n\nExamples:\n build telemetry cost compare cursor:auto cursor:auto --input 1000 --output 500\n build telemetry cost compare cursor:auto cursor:auto --input 2000 --output 1000 --json"
1354
+ ).argument(
1355
+ "[providerModels...]",
1356
+ "(REQUIRED) Provider/model pairs (format provider:model, at least 2 required)"
1357
+ ).requiredOption(
1358
+ "--input <tokens>",
1359
+ "(REQUIRED) Estimated input tokens\n Example: --input 1000",
1360
+ parseNonNegativeInteger
1361
+ ).requiredOption(
1362
+ "--output <tokens>",
1363
+ "(REQUIRED) Estimated output tokens\n Example: --output 500",
1364
+ parseNonNegativeInteger
1365
+ ).option(
1366
+ "--cache-read <tokens>",
1367
+ "(OPTIONAL) Estimated cache-read tokens\n Example: --cache-read 20000"
1368
+ ).option(
1369
+ "--cache-write <tokens>",
1370
+ "(OPTIONAL) Estimated cache-write tokens\n Example: --cache-write 5000"
1371
+ ).option("--json", "(OPTIONAL) Output comparison as JSON").action(async (providerModels, options) => {
1372
+ try {
1373
+ const costCalculator = await deps.costCalculator;
1374
+ const telemetry = await deps.telemetry;
1375
+ if (!Array.isArray(providerModels) || providerModels.length < 2) {
1376
+ throw new InvalidArgumentError("Provide at least two provider:model pairs to compare");
1377
+ }
1378
+ const validatedOptions = validateCommandOptions(CompareOptionsSchema, {
1379
+ ...options,
1380
+ cacheRead: parseOptionalPredictTokenOption(options.cacheRead),
1381
+ cacheWrite: parseOptionalPredictTokenOption(options.cacheWrite)
1382
+ });
1383
+ const ProviderModelPairSchema = z2.string().regex(/^[a-zA-Z0-9._-]+:[a-zA-Z0-9._\-/]+$/, "Invalid provider:model format").refine((value) => {
1384
+ const parts = value.split(":");
1385
+ return parts.length === 2 && (parts[0]?.length ?? 0) > 0 && (parts[1]?.length ?? 0) > 0;
1386
+ }, "Provider:model must have both provider and model specified");
1387
+ const validatedPairs = providerModels.map((pair) => ProviderModelPairSchema.parse(pair));
1388
+ await deps.ensurePricingLoaded();
1389
+ const breakdowns = validatedPairs.map((entry) => {
1390
+ const [provider, model] = entry.split(":");
1391
+ if (!provider || !model) {
1392
+ throw new InvalidArgumentError(
1393
+ `Invalid provider:model pair '${entry}'. Expected format provider:model`
1394
+ );
1395
+ }
1396
+ return costCalculator.predictCost(provider, model, {
1397
+ input: validatedOptions.input,
1398
+ output: validatedOptions.output,
1399
+ ...cacheTokenEstimates(validatedOptions)
1400
+ });
1401
+ });
1402
+ const pricedBreakdowns = breakdowns.filter((breakdown) => !isPricingUnavailable(breakdown));
1403
+ const cheapestModel = pricedBreakdowns.reduce((min, current) => {
1404
+ if (!min) return current;
1405
+ const minUsd = availableBreakdownUsd(min) ?? Number.POSITIVE_INFINITY;
1406
+ const currentUsd = availableBreakdownUsd(current) ?? Number.POSITIVE_INFINITY;
1407
+ return currentUsd < minUsd ? current : min;
1408
+ }, void 0);
1409
+ telemetry.logCostEvent("cli_cost_compare", {
1410
+ comparisons: validatedPairs.length,
1411
+ inputTokens: validatedOptions.input,
1412
+ outputTokens: validatedOptions.output,
1413
+ cacheReadTokens: validatedOptions.cacheRead,
1414
+ cacheWriteTokens: validatedOptions.cacheWrite,
1415
+ cheapest: cheapestModel?.model ?? null,
1416
+ unavailableComparisons: breakdowns.length - pricedBreakdowns.length
1417
+ });
1418
+ if (validatedOptions.json) {
1419
+ console.log(JSON.stringify(breakdowns, null, 2));
1420
+ return;
1421
+ }
1422
+ console.log(chalk3.bold.cyan("\nCost Comparison\n"));
1423
+ const unavailableBreakdowns = breakdowns.filter(isPricingUnavailable);
1424
+ const sorted = [
1425
+ ...pricedBreakdowns.sort((a, b) => {
1426
+ const aUsd = availableBreakdownUsd(a) ?? Number.POSITIVE_INFINITY;
1427
+ const bUsd = availableBreakdownUsd(b) ?? Number.POSITIVE_INFINITY;
1428
+ return aUsd - bUsd;
1429
+ }),
1430
+ ...unavailableBreakdowns
1431
+ ];
1432
+ if (sorted.length === 0) {
1433
+ console.log(chalk3.red("No breakdowns available"));
1434
+ return;
1435
+ }
1436
+ const cheapest = pricedBreakdowns[0];
1437
+ const cheapestUsd = cheapest && cheapest.totalCostAmount.status === "available" ? cheapest.totalCostAmount.amount : null;
1438
+ sorted.forEach((breakdown, index) => {
1439
+ const totalAmount = breakdown.totalCostAmount;
1440
+ const isUnavailable = breakdown.pricingStatus === "unavailable" || totalAmount.status !== "available";
1441
+ const isCheapest = !isUnavailable && breakdown === cheapest;
1442
+ const rankLabel = `${index + 1}. ${breakdown.provider}/${breakdown.model}`;
1443
+ console.log(isCheapest ? chalk3.green(rankLabel) : rankLabel);
1444
+ if (breakdown.pricingStatus === "unavailable" || totalAmount.status !== "available") {
1445
+ console.log(" total unavailable");
1446
+ if (breakdown.pricingError) {
1447
+ console.log(` pricing unavailable: ${breakdown.pricingError}`);
1448
+ }
1449
+ return;
1450
+ }
1451
+ const totalUsd = totalAmount.amount;
1452
+ if (cheapestUsd === null) {
1453
+ console.log(` total ${formatCurrency(totalUsd, breakdown.currency)}`);
1454
+ return;
1455
+ }
1456
+ console.log(
1457
+ ` total ${formatCurrency(totalUsd, breakdown.currency)} (${formatCurrencyDelta(totalUsd - cheapestUsd, breakdown.currency)})`
1458
+ );
1459
+ console.log(
1460
+ ` input ${formatCurrency(breakdown.inputCost, breakdown.currency)} | output ${formatCurrency(breakdown.outputCost, breakdown.currency)}`
1461
+ );
1462
+ if (breakdown.toolCosts > 0 || breakdown.cacheCost > 0 || breakdown.infrastructureCost > 0) {
1463
+ console.log(
1464
+ ` cache ${formatCurrency(breakdown.cacheCost, breakdown.currency)} | tools ${formatCurrency(breakdown.toolCosts, breakdown.currency)} | infra ${formatCurrency(breakdown.infrastructureCost, breakdown.currency)}`
1465
+ );
1466
+ }
1467
+ });
1468
+ } catch (error) {
1469
+ if (options.json) {
1470
+ console.log(
1471
+ JSON.stringify(
1472
+ {
1473
+ error: "cost_comparison_failed",
1474
+ message: createSafeErrorMessage(error, "cost compare")
1475
+ },
1476
+ null,
1477
+ 2
1478
+ )
1479
+ );
1480
+ process.exitCode = 1;
1481
+ return;
1482
+ }
1483
+ throw error;
1484
+ }
1485
+ });
1486
+ cost.command("daily").description(
1487
+ "Generate and display daily cost reports\n\nExamples:\n build telemetry cost daily\n build telemetry cost daily --days 14 --group provider\n build telemetry cost daily --start 2024-01-01 --end 2024-01-31"
1488
+ ).option(
1489
+ "--days <days>",
1490
+ "(OPTIONAL) Number of recent days to include (default: 7)\n Example: --days 14",
1491
+ "7"
1492
+ ).option(
1493
+ "--start <date>",
1494
+ "(OPTIONAL) Start date in YYYY-MM-DD format (overrides --days)\n Example: --start 2024-01-01"
1495
+ ).option(
1496
+ "--end <date>",
1497
+ "(OPTIONAL) End date in YYYY-MM-DD format (default: today)\n Example: --end 2024-01-31"
1498
+ ).option(
1499
+ "--group <grouping>",
1500
+ "(OPTIONAL) Group results by date, provider, or model (default: date)\n Example: --group provider",
1501
+ "date"
1502
+ ).option("--json", "(OPTIONAL) Output report as JSON").action(async (options) => {
1503
+ const modelInvocationsDb = await deps.modelInvocationsDb;
1504
+ const telemetry = await deps.telemetry;
1505
+ if (!modelInvocationsDb) {
1506
+ console.log(chalk3.yellow("Daily cost reports require a telemetry database."));
1507
+ console.log(chalk3.gray("Ensure cost tracking is enabled and try again."));
1508
+ return;
1509
+ }
1510
+ const validatedOptions = validateCommandOptions(DailyOptionsSchema, options);
1511
+ const today = /* @__PURE__ */ new Date();
1512
+ const endDate = validatedOptions.end ? new Date(validatedOptions.end) : today;
1513
+ let startDate;
1514
+ if (validatedOptions.start) {
1515
+ startDate = new Date(validatedOptions.start);
1516
+ if (Number.isNaN(startDate.getTime())) {
1517
+ throw new InvalidArgumentError(
1518
+ `Invalid --start date: ${validatedOptions.start}. Use YYYY-MM-DD format.`
1519
+ );
1520
+ }
1521
+ } else {
1522
+ const daysBack = validatedOptions.days ?? 7;
1523
+ startDate = new Date(endDate);
1524
+ startDate.setDate(startDate.getDate() - daysBack + 1);
1525
+ }
1526
+ if (Number.isNaN(endDate.getTime())) {
1527
+ throw new InvalidArgumentError(
1528
+ `Invalid --end date: ${validatedOptions.end}. Use YYYY-MM-DD format.`
1529
+ );
1530
+ }
1531
+ if (startDate > endDate) {
1532
+ throw new InvalidArgumentError(
1533
+ "Invalid date range: --start date cannot be after --end date."
1534
+ );
1535
+ }
1536
+ const startDateStr = startDate.toISOString().split("T")[0];
1537
+ const endDateStr = endDate.toISOString().split("T")[0];
1538
+ const dailyResult = modelInvocationsDb.getDailyCostAggregations(
1539
+ startDateStr,
1540
+ endDateStr,
1541
+ validatedOptions.group
1542
+ );
1543
+ const dailyData = dailyResult.rows;
1544
+ if (dailyResult.status === "error") {
1545
+ process.exitCode = 1;
1546
+ if (validatedOptions.json) {
1547
+ writeCostOutput(
1548
+ JSON.stringify(
1549
+ {
1550
+ status: "error",
1551
+ error: dailyResult.error ?? "daily cost aggregation failed",
1552
+ detail: dailyResult.detail,
1553
+ period: {
1554
+ start: startDateStr,
1555
+ end: endDateStr,
1556
+ days: 0
1557
+ },
1558
+ grouping: validatedOptions.group,
1559
+ data: []
1560
+ },
1561
+ null,
1562
+ 2
1563
+ )
1564
+ );
1565
+ return;
1566
+ }
1567
+ writeCostOutput(
1568
+ chalk3.yellow(
1569
+ `Error: Daily cost aggregation failed${dailyResult.error ? `: ${dailyResult.error}` : "."}`
1570
+ )
1571
+ );
1572
+ return;
1573
+ }
1574
+ if (dailyData.length === 0) {
1575
+ if (validatedOptions.json) {
1576
+ console.log(
1577
+ JSON.stringify(
1578
+ {
1579
+ status: "complete",
1580
+ period: {
1581
+ start: startDateStr,
1582
+ end: endDateStr,
1583
+ days: 0
1584
+ },
1585
+ summary: {
1586
+ totalCost: 0,
1587
+ totalExecutions: 0,
1588
+ pricedExecutions: 0,
1589
+ totalTokensIn: 0,
1590
+ totalTokensOut: 0,
1591
+ avgDailyCost: 0
1592
+ },
1593
+ grouping: validatedOptions.group,
1594
+ data: []
1595
+ },
1596
+ null,
1597
+ 2
1598
+ )
1599
+ );
1600
+ return;
1601
+ }
1602
+ console.log(chalk3.yellow("No cost data found for the specified period."));
1603
+ console.log(chalk3.gray(`Query range: ${startDateStr} to ${endDateStr}`));
1604
+ logCostEmptyStateHint(modelInvocationsDb, startDate.getTime());
1605
+ return;
1606
+ }
1607
+ const totalExecutions = dailyResult.executionCount;
1608
+ const pricedExecutions = dailyResult.pricedCount;
1609
+ const totalTokensIn = dailyData.reduce((sum, day) => sum + day.totalTokensIn, 0);
1610
+ const totalTokensOut = dailyData.reduce((sum, day) => sum + day.totalTokensOut, 0);
1611
+ const totalCost = dailyResult.status === "complete" ? sumCompleteDailyCosts(dailyData) : null;
1612
+ const dayTotals = totalCostByDay(dailyData);
1613
+ const avgDailyCost = totalCost !== null && dayTotals.length > 0 ? totalCost / dayTotals.length : null;
1614
+ telemetry.logCostEvent("cli_cost_daily_viewed", {
1615
+ startDate: startDateStr ?? null,
1616
+ endDate: endDateStr ?? null,
1617
+ grouping: validatedOptions.group,
1618
+ recordCount: dailyData.length,
1619
+ status: dailyResult.status,
1620
+ totalCost,
1621
+ totalExecutions,
1622
+ pricedExecutions
1623
+ });
1624
+ if (validatedOptions.json) {
1625
+ const summary = dailyResult.status === "complete" && totalCost !== null && avgDailyCost !== null ? {
1626
+ totalCost,
1627
+ totalExecutions,
1628
+ pricedExecutions,
1629
+ totalTokensIn,
1630
+ totalTokensOut,
1631
+ avgDailyCost
1632
+ } : {
1633
+ totalExecutions,
1634
+ pricedExecutions,
1635
+ totalTokensIn,
1636
+ totalTokensOut
1637
+ };
1638
+ console.log(
1639
+ JSON.stringify(
1640
+ {
1641
+ status: dailyResult.status,
1642
+ ...dailyResult.detail ? { detail: dailyResult.detail } : {},
1643
+ period: {
1644
+ start: startDateStr,
1645
+ end: endDateStr,
1646
+ days: dayTotals.length
1647
+ },
1648
+ summary,
1649
+ grouping: validatedOptions.group,
1650
+ data: dailyData
1651
+ },
1652
+ null,
1653
+ 2
1654
+ )
1655
+ );
1656
+ return;
1657
+ }
1658
+ console.log(chalk3.bold.cyan("\nDaily Cost Report\n"));
1659
+ console.log(
1660
+ `${chalk3.gray("Period")}: ${startDateStr} to ${endDateStr} (${dayTotals.length} ${dayTotals.length === 1 ? "day" : "days"} with data)`
1661
+ );
1662
+ console.log(`${chalk3.gray("Grouping")}: ${validatedOptions.group}`);
1663
+ if (dailyResult.status === "incomplete") {
1664
+ writeCostOutput(
1665
+ chalk3.yellow(
1666
+ `Evidence: incomplete (${pricedExecutions} of ${totalExecutions} invocations priced)`
1667
+ )
1668
+ );
1669
+ writeCostOutput(
1670
+ chalk3.gray("Totals and averages omitted until all invocations are priced.")
1671
+ );
1672
+ }
1673
+ console.log(chalk3.bold("\nSummary"));
1674
+ if (totalCost !== null && avgDailyCost !== null) {
1675
+ console.log(`${chalk3.gray("Total Cost")}: ${formatCostDisplay(totalCost)}`);
1676
+ console.log(`${chalk3.gray("Avg Daily Cost")}: ${formatCostDisplay(avgDailyCost)}`);
1677
+ } else {
1678
+ writeCostOutput(`${chalk3.gray("Total Cost")}: incomplete`);
1679
+ writeCostOutput(`${chalk3.gray("Avg Daily Cost")}: incomplete`);
1680
+ }
1681
+ console.log(`${chalk3.gray("Total Executions")}: ${totalExecutions.toLocaleString()}`);
1682
+ if (dailyResult.status === "incomplete") {
1683
+ writeCostOutput(`${chalk3.gray("Priced Executions")}: ${pricedExecutions.toLocaleString()}`);
1684
+ }
1685
+ console.log(
1686
+ `${chalk3.gray("Total Tokens")}: ${formatTokenCount(totalTokensIn + totalTokensOut)}`
1687
+ );
1688
+ const extremeDays = dailyResult.status === "complete" ? costExtremeDays(dayTotals) : void 0;
1689
+ if (extremeDays) {
1690
+ console.log(
1691
+ `${chalk3.gray("Highest Cost Day")}: ${extremeDays.highest.date} (${formatCostDisplay(extremeDays.highest.cost)})`
1692
+ );
1693
+ console.log(
1694
+ `${chalk3.gray("Lowest Cost Day")}: ${extremeDays.lowest.date} (${formatCostDisplay(extremeDays.lowest.cost)})`
1695
+ );
1696
+ }
1697
+ console.log(chalk3.bold("\nDetailed Breakdown\n"));
1698
+ if (validatedOptions.group === "date") {
1699
+ console.log(
1700
+ `${chalk3.bold("Date".padEnd(12))} ${chalk3.bold("Cost".padEnd(12))} ${chalk3.bold("Executions".padEnd(12))} ${chalk3.bold("Tokens".padEnd(12))} ${chalk3.bold("Avg Cost")}`
1701
+ );
1702
+ console.log(chalk3.gray("-".repeat(60)));
1703
+ dailyData.forEach((day) => {
1704
+ const totalTokens = day.totalTokensIn + day.totalTokensOut;
1705
+ console.log(
1706
+ `${day.date.padEnd(12)} ${formatDailyAggregationCost(day.totalCost).padEnd(12)} ${day.executionCount.toLocaleString().padEnd(12)} ${formatTokenCount(totalTokens).padEnd(12)} ${formatDailyAggregationCost(day.avgCostPerExecution)}`
1707
+ );
1708
+ });
1709
+ } else if (validatedOptions.group === "provider") {
1710
+ const providerGroups = /* @__PURE__ */ new Map();
1711
+ dailyData.forEach((item) => {
1712
+ if (!item.provider) return;
1713
+ if (!providerGroups.has(item.provider)) {
1714
+ providerGroups.set(item.provider, []);
1715
+ }
1716
+ providerGroups.get(item.provider)?.push(item);
1717
+ });
1718
+ console.log(
1719
+ `${chalk3.bold("Provider".padEnd(20))} ${chalk3.bold("Total Cost".padEnd(12))} ${chalk3.bold("Executions".padEnd(12))} ${chalk3.bold("Tokens".padEnd(12))} ${chalk3.bold("Avg Cost")}`
1720
+ );
1721
+ console.log(chalk3.gray("-".repeat(70)));
1722
+ providerGroups.forEach((items, provider) => {
1723
+ const providerCost = sumCompleteDailyCosts(items);
1724
+ const providerExecutions = items.reduce((sum, item) => sum + item.executionCount, 0);
1725
+ const providerTokens = items.reduce(
1726
+ (sum, item) => sum + item.totalTokensIn + item.totalTokensOut,
1727
+ 0
1728
+ );
1729
+ const avgCost = providerCost !== null && providerExecutions > 0 ? providerCost / providerExecutions : null;
1730
+ console.log(
1731
+ `${provider.padEnd(20)} ${formatDailyAggregationCost(providerCost).padEnd(12)} ${providerExecutions.toLocaleString().padEnd(12)} ${formatTokenCount(providerTokens).padEnd(12)} ${formatDailyAggregationCost(avgCost)}`
1732
+ );
1733
+ });
1734
+ } else if (validatedOptions.group === "model") {
1735
+ const modelGroups = /* @__PURE__ */ new Map();
1736
+ dailyData.forEach((item) => {
1737
+ if (!item.model) return;
1738
+ if (!modelGroups.has(item.model)) {
1739
+ modelGroups.set(item.model, []);
1740
+ }
1741
+ modelGroups.get(item.model)?.push(item);
1742
+ });
1743
+ console.log(
1744
+ `${chalk3.bold("Model".padEnd(25))} ${chalk3.bold("Total Cost".padEnd(12))} ${chalk3.bold("Executions".padEnd(12))} ${chalk3.bold("Tokens".padEnd(12))} ${chalk3.bold("Avg Cost")}`
1745
+ );
1746
+ console.log(chalk3.gray("-".repeat(75)));
1747
+ modelGroups.forEach((items, model) => {
1748
+ const modelCost = sumCompleteDailyCosts(items);
1749
+ const modelExecutions = items.reduce((sum, item) => sum + item.executionCount, 0);
1750
+ const modelTokens = items.reduce(
1751
+ (sum, item) => sum + item.totalTokensIn + item.totalTokensOut,
1752
+ 0
1753
+ );
1754
+ const avgCost = modelCost !== null && modelExecutions > 0 ? modelCost / modelExecutions : null;
1755
+ console.log(
1756
+ `${model.padEnd(25)} ${formatDailyAggregationCost(modelCost).padEnd(12)} ${modelExecutions.toLocaleString().padEnd(12)} ${formatTokenCount(modelTokens).padEnd(12)} ${formatDailyAggregationCost(avgCost)}`
1757
+ );
1758
+ });
1759
+ }
1760
+ console.log(
1761
+ chalk3.gray("\nTip: Use --group provider or --group model to see different breakdowns")
1762
+ );
1763
+ });
1764
+ cost.command("history").description(
1765
+ "Show cost history with optional recalculation\n\nExamples:\n build telemetry cost history --task task-123\n build telemetry cost history --competition comp-456 --recalculate current\n build telemetry cost history --days 30 --recalculate 2024-01-01"
1766
+ ).option("--task <taskId>", "(OPTIONAL) Show costs for specific task").option("--competition <competitionId>", "(OPTIONAL) Show costs for specific competition").option(
1767
+ "--recalculate <mode>",
1768
+ "(OPTIONAL) Recalculation mode: current | snapshot | YYYY-MM-DD\n Example: --recalculate current"
1769
+ ).option(
1770
+ "--days <days>",
1771
+ "(OPTIONAL) Number of recent days (default: 7)\n Example: --days 14",
1772
+ "7"
1773
+ ).option("--json", "(OPTIONAL) Output as JSON").action(async (options) => {
1774
+ const modelInvocationsDb = await deps.modelInvocationsDb;
1775
+ const costCalculator = await deps.costCalculator;
1776
+ const telemetry = await deps.telemetry;
1777
+ const validatedOptions = validateCommandOptions(HistoryOptionsSchema, options);
1778
+ let executions = [];
1779
+ if (validatedOptions.task) {
1780
+ const taskExecutions = modelInvocationsDb.getTaskExecutionCosts(validatedOptions.task);
1781
+ executions = taskExecutions.map((exec) => ({
1782
+ executionId: exec.executionId,
1783
+ provider: exec.provider,
1784
+ model: exec.model,
1785
+ snapshotCost: exec.costSnapshot.totalCostCents,
1786
+ currentCost: exec.costSnapshot.totalCostCents,
1787
+ timestamp: exec.timestamp
1788
+ }));
1789
+ } else if (validatedOptions.competition) {
1790
+ const competitionExecutions = modelInvocationsDb.getCompetitionExecutionCosts(
1791
+ validatedOptions.competition
1792
+ );
1793
+ executions = competitionExecutions.map((exec) => ({
1794
+ executionId: exec.executionId,
1795
+ provider: exec.provider,
1796
+ model: exec.model,
1797
+ snapshotCost: exec.costSnapshot.totalCostCents,
1798
+ currentCost: exec.costSnapshot.totalCostCents,
1799
+ timestamp: exec.timestamp
1800
+ }));
1801
+ } else {
1802
+ const daysBack = validatedOptions.days ?? 7;
1803
+ const startTime = Date.now() - daysBack * 24 * 60 * 60 * 1e3;
1804
+ const allExecutions = modelInvocationsDb.getExecutionCostsSince(startTime);
1805
+ executions = allExecutions.map((exec) => ({
1806
+ executionId: exec.executionId,
1807
+ provider: exec.provider,
1808
+ model: exec.model,
1809
+ snapshotCost: exec.costSnapshot.totalCostCents,
1810
+ currentCost: exec.costSnapshot.totalCostCents,
1811
+ timestamp: exec.timestamp
1812
+ }));
1813
+ }
1814
+ if (validatedOptions.recalculate === "current") {
1815
+ for (const exec of executions) {
1816
+ const newCost = modelInvocationsDb.recalculateCost(
1817
+ exec.executionId,
1818
+ (provider, model, usage) => {
1819
+ try {
1820
+ const breakdown = costCalculator.calculateCost(
1821
+ provider,
1822
+ model,
1823
+ storedUsageToUsageData(usage)
1824
+ );
1825
+ const availableUsd = availableBreakdownUsd(breakdown);
1826
+ if (availableUsd === null) {
1827
+ return exec.snapshotCost;
1828
+ }
1829
+ return availableUsd * 100;
1830
+ } catch (error) {
1831
+ emitWarning(
1832
+ "PR-003",
1833
+ {
1834
+ taskId: validatedOptions.task || "cost-history",
1835
+ subsystem: "cost-tracking",
1836
+ executionPhase: "execution"
1837
+ },
1838
+ {
1839
+ severity: "WARN" /* WARN */,
1840
+ metadata: {
1841
+ executionId: exec.executionId,
1842
+ error: error instanceof Error ? error.message : String(error),
1843
+ operation: "recalculateCost"
1844
+ }
1845
+ }
1846
+ );
1847
+ return exec.snapshotCost;
1848
+ }
1849
+ }
1850
+ );
1851
+ exec.currentCost = newCost ?? exec.snapshotCost;
1852
+ }
1853
+ }
1854
+ telemetry.logCostEvent("cli_cost_history_viewed", {
1855
+ taskId: validatedOptions.task ?? null,
1856
+ competitionId: validatedOptions.competition ?? null,
1857
+ recalculateMode: validatedOptions.recalculate ?? "snapshot",
1858
+ executionCount: executions.length
1859
+ });
1860
+ if (validatedOptions.json) {
1861
+ console.log(
1862
+ JSON.stringify(
1863
+ {
1864
+ executions: executions.map((e) => ({
1865
+ executionId: e.executionId,
1866
+ provider: e.provider,
1867
+ model: e.model,
1868
+ snapshotCost: e.snapshotCost / 100,
1869
+ currentCost: e.currentCost / 100,
1870
+ delta: (e.currentCost - e.snapshotCost) / 100,
1871
+ deltaPercent: e.snapshotCost > 0 ? (e.currentCost - e.snapshotCost) / e.snapshotCost * 100 : 0,
1872
+ timestamp: e.timestamp.toISOString()
1873
+ })),
1874
+ summary: {
1875
+ totalSnapshot: executions.reduce((sum, e) => sum + e.snapshotCost, 0) / 100,
1876
+ totalCurrent: executions.reduce((sum, e) => sum + e.currentCost, 0) / 100
1877
+ }
1878
+ },
1879
+ null,
1880
+ 2
1881
+ )
1882
+ );
1883
+ return;
1884
+ }
1885
+ console.log(chalk3.bold.cyan("\nCost History\n"));
1886
+ if (executions.length === 0) {
1887
+ console.log(chalk3.yellow("No execution history found."));
1888
+ if (!validatedOptions.task && !validatedOptions.competition) {
1889
+ const daysBack = validatedOptions.days ?? 7;
1890
+ const startTime = Date.now() - daysBack * 24 * 60 * 60 * 1e3;
1891
+ logCostEmptyStateHint(modelInvocationsDb, startTime);
1892
+ }
1893
+ return;
1894
+ }
1895
+ console.log(
1896
+ `${chalk3.bold("Execution".padEnd(30))} ${chalk3.bold("Snapshot".padEnd(12))} ${chalk3.bold("Current".padEnd(12))} ${chalk3.bold("Delta")}`
1897
+ );
1898
+ console.log(chalk3.gray("-".repeat(70)));
1899
+ executions.forEach((exec) => {
1900
+ const delta = exec.currentCost - exec.snapshotCost;
1901
+ const deltaPercent = exec.snapshotCost > 0 ? (delta / exec.snapshotCost * 100).toFixed(1) : "0.0";
1902
+ const direction = delta > 0 ? "up" : delta < 0 ? "down" : "flat";
1903
+ const color = delta > 0 ? chalk3.red : delta < 0 ? chalk3.green : chalk3.gray;
1904
+ const label = `${exec.executionId.substring(0, 8)}... (${exec.provider}/${exec.model})`;
1905
+ console.log(
1906
+ `${label.padEnd(30)} ${formatCurrency(exec.snapshotCost / 100).padEnd(12)} ${formatCurrency(exec.currentCost / 100).padEnd(12)} ` + color(`${direction} ${deltaPercent}%`)
1907
+ );
1908
+ });
1909
+ const totalSnapshot = executions.reduce((sum, e) => sum + e.snapshotCost, 0);
1910
+ const totalCurrent = executions.reduce((sum, e) => sum + e.currentCost, 0);
1911
+ const totalDelta = totalCurrent - totalSnapshot;
1912
+ console.log(chalk3.gray("-".repeat(70)));
1913
+ console.log(`${chalk3.bold("Total (Snapshot)")}: ${formatCurrency(totalSnapshot / 100)}`);
1914
+ console.log(`${chalk3.bold("Total (Current)")}: ${formatCurrency(totalCurrent / 100)}`);
1915
+ if (Math.abs(totalDelta) > 0.01) {
1916
+ const color = totalDelta > 0 ? chalk3.red : chalk3.green;
1917
+ console.log(
1918
+ `${chalk3.bold("Savings/Cost")}: ${color(formatCurrency(Math.abs(totalDelta) / 100))}`
1919
+ );
1920
+ }
1921
+ console.log(
1922
+ chalk3.gray(
1923
+ "\nTip: Token usage unchanged - cost difference due to pricing updates or recalculation mode"
1924
+ )
1925
+ );
1926
+ });
1927
+ cost.command("tasks").description(
1928
+ "Show cost breakdown by task\n\nExamples:\n build telemetry cost tasks\n build telemetry cost tasks --days 30 --top 20\n build telemetry cost tasks --json"
1929
+ ).option(
1930
+ "--days <days>",
1931
+ "(OPTIONAL) Number of recent days (default: 7)\n Example: --days 30",
1932
+ "7"
1933
+ ).option(
1934
+ "--top <n>",
1935
+ "(OPTIONAL) Show top N most expensive tasks (default: 10)\n Example: --top 20",
1936
+ "10"
1937
+ ).option("--json", "(OPTIONAL) Output as JSON").action(async (options) => {
1938
+ const telemetry = await deps.telemetry;
1939
+ const validatedOptions = validateCommandOptions(TasksOptionsSchema, options);
1940
+ const modelInvocationsDb = await deps.modelInvocationsDb;
1941
+ const startTime = Date.now() - (validatedOptions.days ?? 7) * 24 * 60 * 60 * 1e3;
1942
+ const executions = modelInvocationsDb.getExecutionCostsSince(startTime);
1943
+ const taskSummaries = /* @__PURE__ */ new Map();
1944
+ for (const execution of executions) {
1945
+ const taskId = execution.taskId ?? execution.competitionId ?? "unattributed";
1946
+ const existing = taskSummaries.get(taskId);
1947
+ if (existing) {
1948
+ existing.executionCount += 1;
1949
+ existing.totalCostCents += execution.costSnapshot.totalCostCents;
1950
+ existing.providers.add(execution.provider);
1951
+ if (execution.timestamp > existing.lastExecutionAt) {
1952
+ existing.lastExecutionAt = execution.timestamp;
1953
+ }
1954
+ continue;
1955
+ }
1956
+ taskSummaries.set(taskId, {
1957
+ taskId,
1958
+ executionCount: 1,
1959
+ totalCostCents: execution.costSnapshot.totalCostCents,
1960
+ providers: /* @__PURE__ */ new Set([execution.provider]),
1961
+ lastExecutionAt: execution.timestamp
1962
+ });
1963
+ }
1964
+ const rows = [...taskSummaries.values()].sort((a, b) => b.totalCostCents - a.totalCostCents).slice(0, validatedOptions.top ?? 10);
1965
+ if (validatedOptions.json) {
1966
+ console.log(
1967
+ JSON.stringify(
1968
+ {
1969
+ tasks: rows.map((row) => ({
1970
+ taskId: row.taskId,
1971
+ executionCount: row.executionCount,
1972
+ totalCost: row.totalCostCents / 100,
1973
+ providers: [...row.providers].sort(),
1974
+ lastExecutionAt: row.lastExecutionAt.toISOString()
1975
+ })),
1976
+ summary: {
1977
+ windowDays: validatedOptions.days ?? 7,
1978
+ totalTasks: taskSummaries.size,
1979
+ totalExecutions: executions.length
1980
+ }
1981
+ },
1982
+ null,
1983
+ 2
1984
+ )
1985
+ );
1986
+ return;
1987
+ }
1988
+ console.log(chalk3.bold.cyan("\nTask Cost Breakdown\n"));
1989
+ if (rows.length === 0) {
1990
+ console.log(chalk3.yellow("No task cost data found for the requested window."));
1991
+ logCostEmptyStateHint(modelInvocationsDb, startTime);
1992
+ return;
1993
+ }
1994
+ console.log(
1995
+ `${chalk3.bold("Task".padEnd(34))} ${chalk3.bold("Cost".padEnd(12))} ${chalk3.bold("Execs".padEnd(7))} ${chalk3.bold("Providers")}`
1996
+ );
1997
+ console.log(chalk3.gray("-".repeat(74)));
1998
+ for (const row of rows) {
1999
+ const label = row.taskId.length > 32 ? `${row.taskId.slice(0, 29)}...` : row.taskId.padEnd(32);
2000
+ console.log(
2001
+ `${label.padEnd(34)} ${formatCurrency(row.totalCostCents / 100).padEnd(12)} ${String(row.executionCount).padEnd(7)} ${[...row.providers].sort().join(", ")}`
2002
+ );
2003
+ }
2004
+ telemetry.logCostEvent("cli_cost_tasks_viewed", {
2005
+ days: validatedOptions.days ?? 7,
2006
+ top: validatedOptions.top ?? 10,
2007
+ taskCount: taskSummaries.size,
2008
+ executionCount: executions.length
2009
+ });
2010
+ });
2011
+ cost.command("tokens").description(
2012
+ "Show token usage trends over time\n\nExamples:\n build telemetry cost tokens\n build telemetry cost tokens --days 30 --provider anthropic\n build telemetry cost tokens --provider cursor --model auto"
2013
+ ).option(
2014
+ "--days <days>",
2015
+ "(OPTIONAL) Number of recent days (default: 7)\n Example: --days 30",
2016
+ "7"
2017
+ ).option(
2018
+ "--provider <provider>",
2019
+ "(OPTIONAL) Filter by provider\n Example: --provider anthropic"
2020
+ ).option("--model <model>", "(OPTIONAL) Filter by model\n Example: --model auto").option("--json", "(OPTIONAL) Output as JSON").action(async (options) => {
2021
+ const modelInvocationsDb = await deps.modelInvocationsDb;
2022
+ const telemetry = await deps.telemetry;
2023
+ const validatedOptions = validateCommandOptions(TokensOptionsSchema, options);
2024
+ const daysBack = validatedOptions.days ?? 7;
2025
+ const endDate = /* @__PURE__ */ new Date();
2026
+ const startDate = new Date(endDate);
2027
+ startDate.setDate(startDate.getDate() - daysBack + 1);
2028
+ const startDateStr = startDate.toISOString().split("T")[0];
2029
+ const endDateStr = endDate.toISOString().split("T")[0];
2030
+ const dailyResult = modelInvocationsDb.getDailyCostAggregations(
2031
+ startDateStr,
2032
+ endDateStr,
2033
+ "date"
2034
+ );
2035
+ if (dailyResult.status === "error") {
2036
+ process.exitCode = 1;
2037
+ if (validatedOptions.json) {
2038
+ writeCostOutput(
2039
+ JSON.stringify(
2040
+ {
2041
+ status: "error",
2042
+ error: dailyResult.error ?? "daily cost aggregation failed",
2043
+ detail: dailyResult.detail,
2044
+ period: {
2045
+ start: startDateStr,
2046
+ end: endDateStr,
2047
+ days: daysBack
2048
+ },
2049
+ data: []
2050
+ },
2051
+ null,
2052
+ 2
2053
+ )
2054
+ );
2055
+ return;
2056
+ }
2057
+ writeCostOutput(
2058
+ chalk3.yellow(
2059
+ `Error: Token trends unavailable${dailyResult.error ? `: ${dailyResult.error}` : "."}`
2060
+ )
2061
+ );
2062
+ return;
2063
+ }
2064
+ const filteredData = dailyResult.rows.filter((day) => {
2065
+ if (validatedOptions.provider && day.provider !== validatedOptions.provider) {
2066
+ return false;
2067
+ }
2068
+ if (validatedOptions.model && day.model !== validatedOptions.model) {
2069
+ return false;
2070
+ }
2071
+ return true;
2072
+ });
2073
+ telemetry.logCostEvent("cli_cost_tokens_viewed", {
2074
+ days: daysBack,
2075
+ provider: validatedOptions.provider ?? null,
2076
+ model: validatedOptions.model ?? null,
2077
+ recordCount: filteredData.length,
2078
+ status: dailyResult.status
2079
+ });
2080
+ if (validatedOptions.json) {
2081
+ console.log(
2082
+ JSON.stringify(
2083
+ {
2084
+ status: dailyResult.status,
2085
+ period: {
2086
+ start: startDateStr,
2087
+ end: endDateStr,
2088
+ days: daysBack
2089
+ },
2090
+ filters: {
2091
+ provider: validatedOptions.provider ?? null,
2092
+ model: validatedOptions.model ?? null
2093
+ },
2094
+ data: filteredData.map((day) => ({
2095
+ date: day.date,
2096
+ totalTokensIn: day.totalTokensIn,
2097
+ totalTokensOut: day.totalTokensOut,
2098
+ totalTokens: day.totalTokensIn + day.totalTokensOut,
2099
+ executionCount: day.executionCount,
2100
+ avgTokensPerExecution: day.executionCount > 0 ? (day.totalTokensIn + day.totalTokensOut) / day.executionCount : 0
2101
+ }))
2102
+ },
2103
+ null,
2104
+ 2
2105
+ )
2106
+ );
2107
+ return;
2108
+ }
2109
+ console.log(chalk3.bold.cyan("\nToken Usage Trends\n"));
2110
+ if (filteredData.length === 0) {
2111
+ console.log(chalk3.yellow("No token usage data found for the specified period."));
2112
+ const startTimeMs = Date.now() - daysBack * 24 * 60 * 60 * 1e3;
2113
+ logCostEmptyStateHint(modelInvocationsDb, startTimeMs);
2114
+ return;
2115
+ }
2116
+ console.log(`${chalk3.gray("Period")}: ${startDateStr} to ${endDateStr} (${daysBack} days)`);
2117
+ if (validatedOptions.provider) {
2118
+ console.log(`${chalk3.gray("Provider")}: ${validatedOptions.provider}`);
2119
+ }
2120
+ if (validatedOptions.model) {
2121
+ console.log(`${chalk3.gray("Model")}: ${validatedOptions.model}`);
2122
+ }
2123
+ console.log(
2124
+ `
2125
+ ${chalk3.bold("Date".padEnd(12))} ${chalk3.bold("Input".padEnd(12))} ${chalk3.bold("Output".padEnd(12))} ${chalk3.bold("Total".padEnd(12))} ${chalk3.bold("Execs")}`
2126
+ );
2127
+ console.log(chalk3.gray("-".repeat(65)));
2128
+ filteredData.forEach((day) => {
2129
+ const totalTokens = day.totalTokensIn + day.totalTokensOut;
2130
+ console.log(
2131
+ `${day.date.padEnd(12)} ${formatTokenCount(day.totalTokensIn).padEnd(12)} ${formatTokenCount(day.totalTokensOut).padEnd(12)} ${formatTokenCount(totalTokens).padEnd(12)} ${day.executionCount.toLocaleString()}`
2132
+ );
2133
+ });
2134
+ const totalIn = filteredData.reduce((sum, day) => sum + day.totalTokensIn, 0);
2135
+ const totalOut = filteredData.reduce((sum, day) => sum + day.totalTokensOut, 0);
2136
+ const totalExecs = filteredData.reduce((sum, day) => sum + day.executionCount, 0);
2137
+ console.log(chalk3.gray("-".repeat(65)));
2138
+ console.log(`${chalk3.bold("Total Input")}: ${formatTokenCount(totalIn)}`);
2139
+ console.log(`${chalk3.bold("Total Output")}: ${formatTokenCount(totalOut)}`);
2140
+ console.log(`${chalk3.bold("Total Tokens")}: ${formatTokenCount(totalIn + totalOut)}`);
2141
+ console.log(`${chalk3.bold("Total Executions")}: ${totalExecs.toLocaleString()}`);
2142
+ console.log(
2143
+ chalk3.gray(
2144
+ "\nTip: Token usage is independent of cost - use `build telemetry cost daily` for cost analysis"
2145
+ )
2146
+ );
2147
+ });
2148
+ cost.command("compare-pricing").description(
2149
+ "Compare recorded snapshot cost against current pricing\n\nExamples:\n build telemetry cost compare-pricing inv_123456\n build telemetry cost compare-pricing inv_123456 --json"
2150
+ ).argument("<executionId>", "(REQUIRED) Execution ID to analyze").option("--json", "(OPTIONAL) Output as JSON").action(async (executionId, options) => {
2151
+ const modelInvocationsDb = await deps.modelInvocationsDb;
2152
+ const costCalculator = await deps.costCalculator;
2153
+ const telemetry = await deps.telemetry;
2154
+ const validatedOptions = validateCommandOptions(ComparePricingOptionsSchema, options);
2155
+ const execution = modelInvocationsDb.getExecutionCost(executionId);
2156
+ if (!execution) {
2157
+ if (validatedOptions.json) {
2158
+ console.log(
2159
+ JSON.stringify(
2160
+ {
2161
+ error: "execution_not_found",
2162
+ message: `Execution not found: ${executionId}`,
2163
+ executionId
2164
+ },
2165
+ null,
2166
+ 2
2167
+ )
2168
+ );
2169
+ process.exitCode = 1;
2170
+ return;
2171
+ }
2172
+ console.error(chalk3.red(`Execution not found: ${executionId}`));
2173
+ process.exitCode = 1;
2174
+ return;
2175
+ }
2176
+ const currentCost = modelInvocationsDb.recalculateCost(
2177
+ executionId,
2178
+ (provider, model, usage) => {
2179
+ try {
2180
+ const breakdown = costCalculator.calculateCost(
2181
+ provider,
2182
+ model,
2183
+ storedUsageToUsageData(usage)
2184
+ );
2185
+ const availableUsd = availableBreakdownUsd(breakdown);
2186
+ if (availableUsd === null) {
2187
+ return execution.costSnapshot.totalCostCents;
2188
+ }
2189
+ return availableUsd * 100;
2190
+ } catch (error) {
2191
+ emitWarning(
2192
+ "PR-003",
2193
+ {
2194
+ taskId: executionId,
2195
+ subsystem: "cost-tracking",
2196
+ executionPhase: "execution"
2197
+ },
2198
+ {
2199
+ severity: "WARN" /* WARN */,
2200
+ metadata: {
2201
+ executionId,
2202
+ error: error instanceof Error ? error.message : String(error),
2203
+ operation: "recalculateCostComparePricing"
2204
+ }
2205
+ }
2206
+ );
2207
+ return execution.costSnapshot.totalCostCents;
2208
+ }
2209
+ }
2210
+ );
2211
+ telemetry.logCostEvent("cli_cost_compare_pricing_viewed", {
2212
+ executionId,
2213
+ snapshotCost: execution.costSnapshot.totalCostCents,
2214
+ currentCost: currentCost ?? execution.costSnapshot.totalCostCents
2215
+ });
2216
+ if (validatedOptions.json) {
2217
+ console.log(
2218
+ JSON.stringify(
2219
+ {
2220
+ executionId,
2221
+ provider: execution.provider,
2222
+ model: execution.model,
2223
+ usage: execution.usage,
2224
+ comparisons: {
2225
+ snapshot: {
2226
+ version: execution.pricingVersion,
2227
+ costCents: execution.costSnapshot.totalCostCents
2228
+ },
2229
+ current: {
2230
+ version: "current",
2231
+ costCents: currentCost ?? execution.costSnapshot.totalCostCents
2232
+ }
2233
+ }
2234
+ },
2235
+ null,
2236
+ 2
2237
+ )
2238
+ );
2239
+ return;
2240
+ }
2241
+ console.log(chalk3.bold.cyan("\nPricing Comparison\n"));
2242
+ console.log(`${chalk3.gray("Execution ID")}: ${executionId}`);
2243
+ console.log(`${chalk3.gray("Provider/Model")}: ${execution.provider}/${execution.model}`);
2244
+ console.log(
2245
+ `${chalk3.gray("Tokens")}: ${formatTokenCount(execution.usage.inputTokens)} in, ${formatTokenCount(execution.usage.outputTokens)} out`
2246
+ );
2247
+ console.log(chalk3.bold("\nCost Comparison\n"));
2248
+ console.log(
2249
+ `${chalk3.bold("Version".padEnd(20))} ${chalk3.bold("Cost".padEnd(12))} ${chalk3.bold("\u0394 from snapshot")}`
2250
+ );
2251
+ console.log(chalk3.gray("-".repeat(50)));
2252
+ const snapshotCost = execution.costSnapshot.totalCostCents;
2253
+ console.log(
2254
+ `${"Snapshot".padEnd(20)} ${formatCurrency(snapshotCost / 100).padEnd(12)} ${chalk3.gray("(baseline)")}`
2255
+ );
2256
+ if (currentCost !== null) {
2257
+ const delta = currentCost - snapshotCost;
2258
+ const deltaPercent = snapshotCost > 0 ? (delta / snapshotCost * 100).toFixed(1) : "0.0";
2259
+ const direction = delta > 0 ? "up" : delta < 0 ? "down" : "flat";
2260
+ const color = delta > 0 ? chalk3.red : delta < 0 ? chalk3.green : chalk3.gray;
2261
+ console.log(
2262
+ `${"Current".padEnd(20)} ${formatCurrency(currentCost / 100).padEnd(12)} ` + color(`${direction} ${deltaPercent}%`)
2263
+ );
2264
+ }
2265
+ console.log(
2266
+ chalk3.gray(
2267
+ "\nTip: Pricing versions reflect changes in provider pricing over time. Snapshot cost preserves historical accuracy."
2268
+ )
2269
+ );
2270
+ });
2271
+ cost.command("forecast").description(
2272
+ "Project future costs based on historical burn rate\n\nExamples:\n build telemetry cost forecast\n build telemetry cost forecast --days 14 --horizon 14\n build telemetry cost forecast --json"
2273
+ ).option(
2274
+ "--days <days>",
2275
+ "(OPTIONAL) Historical lookback window in days (default: 7)\n Example: --days 14",
2276
+ "7"
2277
+ ).option(
2278
+ "--horizon <days>",
2279
+ "(OPTIONAL) Number of future days to project (default: 7)\n Example: --horizon 14",
2280
+ "7"
2281
+ ).option("--json", "(OPTIONAL) Output forecast as JSON").action(async (options) => {
2282
+ const modelInvocationsDb = await deps.modelInvocationsDb;
2283
+ const telemetry = await deps.telemetry;
2284
+ if (!modelInvocationsDb) {
2285
+ console.log(chalk3.yellow("Cost forecasting requires a telemetry database."));
2286
+ console.log(chalk3.gray("Ensure cost tracking is enabled and try again."));
2287
+ return;
2288
+ }
2289
+ const validatedOptions = validateCommandOptions(ForecastOptionsSchema, options);
2290
+ const today = /* @__PURE__ */ new Date();
2291
+ const endDate = today;
2292
+ const daysBack = validatedOptions.days ?? 7;
2293
+ const startDate = new Date(endDate);
2294
+ startDate.setDate(startDate.getDate() - daysBack + 1);
2295
+ const startDateStr = startDate.toISOString().split("T")[0];
2296
+ const endDateStr = endDate.toISOString().split("T")[0];
2297
+ const dailyResult = modelInvocationsDb.getDailyCostAggregations(
2298
+ startDateStr,
2299
+ endDateStr,
2300
+ "date"
2301
+ );
2302
+ const dailyData = dailyResult.rows;
2303
+ const horizonDays = validatedOptions.horizon ?? 7;
2304
+ if (dailyResult.status === "error" || dailyResult.status === "incomplete") {
2305
+ const reason = dailyResult.status === "error" ? dailyResult.error ?? "daily cost aggregation failed" : dailyResult.detail ?? `incomplete cost evidence (${dailyResult.pricedCount}/${dailyResult.executionCount} priced)`;
2306
+ if (dailyResult.status === "error") {
2307
+ process.exitCode = 1;
2308
+ }
2309
+ if (validatedOptions.json) {
2310
+ writeCostOutput(
2311
+ JSON.stringify(
2312
+ {
2313
+ status: dailyResult.status,
2314
+ period: {
2315
+ start: startDateStr,
2316
+ end: endDateStr,
2317
+ days: dailyData.length
2318
+ },
2319
+ evidence: {
2320
+ executionCount: dailyResult.executionCount,
2321
+ pricedCount: dailyResult.pricedCount
2322
+ },
2323
+ message: dailyResult.status === "error" ? `Cost forecast unavailable: ${reason}` : `Cost forecast requires complete daily cost evidence. ${reason}`,
2324
+ ...dailyResult.status === "error" ? { error: reason } : { detail: reason }
2325
+ },
2326
+ null,
2327
+ 2
2328
+ )
2329
+ );
2330
+ return;
2331
+ }
2332
+ writeCostOutput(
2333
+ chalk3.yellow(
2334
+ dailyResult.status === "error" ? `Error: Cost forecast unavailable: ${reason}` : `Cost forecast unavailable: incomplete cost evidence (${dailyResult.pricedCount} of ${dailyResult.executionCount} priced).`
2335
+ )
2336
+ );
2337
+ writeCostOutput(
2338
+ chalk3.gray("Burn rate and projections are omitted until evidence is complete.")
2339
+ );
2340
+ return;
2341
+ }
2342
+ if (dailyData.length === 0) {
2343
+ if (validatedOptions.json) {
2344
+ console.log(
2345
+ JSON.stringify(
2346
+ {
2347
+ status: "complete",
2348
+ period: {
2349
+ start: startDateStr,
2350
+ end: endDateStr,
2351
+ days: 0
2352
+ },
2353
+ burnRate: {
2354
+ avgDailyCost: 0,
2355
+ trendSlope: 0
2356
+ },
2357
+ forecast: {
2358
+ horizonDays,
2359
+ dailyProjections: [],
2360
+ totalProjectedCost: 0
2361
+ }
2362
+ },
2363
+ null,
2364
+ 2
2365
+ )
2366
+ );
2367
+ return;
2368
+ }
2369
+ console.log(chalk3.yellow("No historical cost data found for the specified period."));
2370
+ return;
2371
+ }
2372
+ const totalCostSum = sumCompleteDailyCosts(dailyData);
2373
+ if (totalCostSum === null) {
2374
+ if (validatedOptions.json) {
2375
+ writeCostOutput(
2376
+ JSON.stringify(
2377
+ {
2378
+ status: "incomplete",
2379
+ period: {
2380
+ start: startDateStr,
2381
+ end: endDateStr,
2382
+ days: dailyData.length
2383
+ },
2384
+ message: "Cost forecast requires complete daily cost evidence."
2385
+ },
2386
+ null,
2387
+ 2
2388
+ )
2389
+ );
2390
+ return;
2391
+ }
2392
+ writeCostOutput(chalk3.yellow("Cost forecast unavailable: incomplete cost evidence."));
2393
+ return;
2394
+ }
2395
+ const avgDailyCost = totalCostSum / Math.max(dailyData.length, 1);
2396
+ const n = dailyData.length;
2397
+ let sumI = 0;
2398
+ let sumCost = 0;
2399
+ let sumICost = 0;
2400
+ let sumI2 = 0;
2401
+ for (let i = 0; i < n; i++) {
2402
+ const cost2 = dailyData[i]?.totalCost ?? 0;
2403
+ sumI += i;
2404
+ sumCost += cost2;
2405
+ sumICost += i * cost2;
2406
+ sumI2 += i * i;
2407
+ }
2408
+ const slopeDenominator = n * sumI2 - sumI * sumI;
2409
+ const slope = slopeDenominator !== 0 ? (n * sumICost - sumI * sumCost) / slopeDenominator : 0;
2410
+ const dailyProjections = [];
2411
+ for (let d = 0; d < horizonDays; d++) {
2412
+ const projDate = new Date(today);
2413
+ projDate.setDate(projDate.getDate() + d + 1);
2414
+ const projDateStr = projDate.toISOString().split("T")[0] ?? "";
2415
+ dailyProjections.push({
2416
+ date: projDateStr,
2417
+ projectedCost: Math.max(0, avgDailyCost)
2418
+ });
2419
+ }
2420
+ const totalProjectedCost = dailyProjections.reduce((sum, p) => sum + p.projectedCost, 0);
2421
+ telemetry.logCostEvent("cli_cost_forecast_viewed", {
2422
+ days: validatedOptions.days,
2423
+ horizon: validatedOptions.horizon,
2424
+ status: "complete",
2425
+ avgDailyCost,
2426
+ totalProjectedCost,
2427
+ trendSlope: slope
2428
+ });
2429
+ if (validatedOptions.json) {
2430
+ console.log(
2431
+ JSON.stringify(
2432
+ {
2433
+ status: "complete",
2434
+ period: {
2435
+ start: startDateStr,
2436
+ end: endDateStr,
2437
+ days: dailyData.length
2438
+ },
2439
+ burnRate: {
2440
+ avgDailyCost,
2441
+ trendSlope: slope
2442
+ },
2443
+ forecast: {
2444
+ horizonDays,
2445
+ dailyProjections,
2446
+ totalProjectedCost
2447
+ }
2448
+ },
2449
+ null,
2450
+ 2
2451
+ )
2452
+ );
2453
+ return;
2454
+ }
2455
+ const trendDirection = Math.abs(slope) < 1e-3 ? "stable" : slope > 0 ? "increasing" : "decreasing";
2456
+ console.log(chalk3.bold.cyan(`
2457
+ Cost Forecast (next ${horizonDays} days)
2458
+ `));
2459
+ console.log(
2460
+ `${chalk3.gray("Period analyzed")}: ${startDateStr} to ${endDateStr} (${dailyData.length} days)`
2461
+ );
2462
+ console.log(`${chalk3.gray("Avg daily burn rate")}: ${formatCurrency(avgDailyCost)}`);
2463
+ console.log(`${chalk3.gray("Trend")}: ${trendDirection}`);
2464
+ console.log(`
2465
+ ${chalk3.bold("Date".padEnd(12))} ${chalk3.bold("Projected Cost")}`);
2466
+ console.log(chalk3.gray("-".repeat(30)));
2467
+ dailyProjections.forEach((proj) => {
2468
+ console.log(`${proj.date.padEnd(12)} ${formatCurrency(proj.projectedCost)}`);
2469
+ });
2470
+ console.log(chalk3.gray("-".repeat(30)));
2471
+ console.log(`${chalk3.bold("Total projected")}: ${formatCurrency(totalProjectedCost)}`);
2472
+ });
2473
+ return cost;
2474
+ }
2475
+
2476
+ export {
2477
+ createCostCommand
2478
+ };
2479
+ //# sourceMappingURL=chunk-3HHWQR3N.js.map