@maycombhq/atticus 2.0.0-beta.2 → 2.0.0-beta.22

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 (284) hide show
  1. package/dist/bin.js +8 -4
  2. package/dist/chunk-23XVSEV5.js +49 -0
  3. package/dist/{chunk-ZDPAS56H.js → chunk-24OXGB3P.js} +8 -2
  4. package/dist/{chunk-7EOBHUMC.js → chunk-24XLDU72.js} +4 -3
  5. package/dist/{chunk-CR3MTH32.js → chunk-2F4CYZKJ.js} +86 -11
  6. package/dist/{chunk-6IU67AEK.js → chunk-2GF7OLF3.js} +23 -15
  7. package/dist/chunk-2IIMFOPM.js +41 -0
  8. package/dist/chunk-2LGRMVCA.js +617 -0
  9. package/dist/{chunk-XPCM366L.js → chunk-2MMCFP5C.js} +10 -8
  10. package/dist/{chunk-JBTK5OP2.js → chunk-2Q56PQPS.js} +6 -4
  11. package/dist/{chunk-Z6LF7HQN.js → chunk-2Q5EDGEO.js} +7 -5
  12. package/dist/{chunk-3USYZGRF.js → chunk-2RLKFUUL.js} +38 -27
  13. package/dist/chunk-2SKB4O2E.js +59 -0
  14. package/dist/{chunk-SP2I63OO.js → chunk-34S2WGOB.js} +87 -4
  15. package/dist/{chunk-GQ4N4WKF.js → chunk-3NFFJL5D.js} +33 -27
  16. package/dist/{chunk-SJRGMG6A.js → chunk-3NWDLGG6.js} +28 -25
  17. package/dist/{chunk-4WBVUHXN.js → chunk-3RM4UK6W.js} +20 -18
  18. package/dist/chunk-42SIDKEU.js +583 -0
  19. package/dist/{chunk-GLUX4EEP.js → chunk-4EURQWQD.js} +20 -15
  20. package/dist/chunk-4U276ICE.js +39 -0
  21. package/dist/{chunk-ZMFPW66A.js → chunk-53T4O55J.js} +4 -3
  22. package/dist/{chunk-6J5OKA4Y.js → chunk-57TDNMI3.js} +17 -15
  23. package/dist/chunk-5BD2KYLE.js +57 -0
  24. package/dist/{chunk-7EFILTCI.js → chunk-5F7GFN2F.js} +28 -0
  25. package/dist/chunk-5NMKONLP.js +95 -0
  26. package/dist/{chunk-7ZUIMTOU.js → chunk-5SJZW52K.js} +26 -24
  27. package/dist/{chunk-4RS5KZQD.js → chunk-63YRMR6J.js} +6 -5
  28. package/dist/chunk-66PPNOON.js +62 -0
  29. package/dist/chunk-6H3Z5JHH.js +64 -0
  30. package/dist/{chunk-CEXSU4S6.js → chunk-6MUGR4LS.js} +775 -89
  31. package/dist/{chunk-QSXK2RGH.js → chunk-6OJQOPUN.js} +5 -3
  32. package/dist/{chunk-MVZVGYXH.js → chunk-6PPOWY5E.js} +84 -14
  33. package/dist/{chunk-7EKXJZ2Y.js → chunk-6ZGLAACW.js} +299 -38
  34. package/dist/chunk-6ZJ5A7AF.js +222 -0
  35. package/dist/{chunk-L24C55VN.js → chunk-745DAZ4L.js} +142 -30
  36. package/dist/{chunk-Q4D5X7QB.js → chunk-7ASNL4Q4.js} +46 -24
  37. package/dist/chunk-7BR7IPOH.js +35 -0
  38. package/dist/{chunk-7WD63HU2.js → chunk-7DOR27HL.js} +6 -6
  39. package/dist/chunk-7FTTA3HD.js +341 -0
  40. package/dist/{chunk-OLQJTJJU.js → chunk-7GJS6DNX.js} +12 -3
  41. package/dist/{chunk-7JUKDRSZ.js → chunk-7IGKHZ4Z.js} +347 -226
  42. package/dist/{chunk-G2B4ZQGH.js → chunk-7IOWA5D5.js} +11 -6
  43. package/dist/{chunk-EBEW3XXQ.js → chunk-7JITZFJC.js} +7 -5
  44. package/dist/chunk-7MJSQTL5.js +174 -0
  45. package/dist/{chunk-I4JRCD6M.js → chunk-7UOMVMFG.js} +25 -17
  46. package/dist/{chunk-YY6ZQQBP.js → chunk-AFWUDXEM.js} +19 -7
  47. package/dist/chunk-AFZ3QA6W.js +47 -0
  48. package/dist/chunk-AJQ72EBM.js +420 -0
  49. package/dist/chunk-AJYXNTNZ.js +317 -0
  50. package/dist/chunk-AVTBS4OW.js +49 -0
  51. package/dist/{chunk-FHH4I4ZV.js → chunk-BDKC6H5P.js} +12 -6
  52. package/dist/{chunk-IPKHE5D6.js → chunk-BEVTIBRH.js} +1526 -875
  53. package/dist/chunk-BHT7QK4G.js +162 -0
  54. package/dist/{chunk-6JUBZBMW.js → chunk-BIGDQDHD.js} +6 -4
  55. package/dist/{chunk-2BFCZ3RK.js → chunk-BO4KX37X.js} +20 -18
  56. package/dist/chunk-BPK5P77O.js +115 -0
  57. package/dist/chunk-BQ4SQQC6.js +59 -0
  58. package/dist/chunk-BQGDB6ZL.js +7342 -0
  59. package/dist/{chunk-2ANOROX3.js → chunk-BTGPE6CR.js} +11 -9
  60. package/dist/chunk-BTY3HZBO.js +93 -0
  61. package/dist/{chunk-DPZHZQKE.js → chunk-BXYMYEJ4.js} +44 -10
  62. package/dist/{chunk-2RMYG36Q.js → chunk-C3RY6KU6.js} +309 -346
  63. package/dist/chunk-C4R4JLHE.js +40 -0
  64. package/dist/chunk-CADWLE2T.js +18 -0
  65. package/dist/chunk-CBGGOQWU.js +82 -0
  66. package/dist/chunk-CMDXGQTS.js +47 -0
  67. package/dist/{chunk-MC3H7736.js → chunk-CQDGOPGH.js} +58 -18
  68. package/dist/{chunk-HFQCFSJR.js → chunk-CX4RZ2KS.js} +4 -3
  69. package/dist/{chunk-PAMPPUR6.js → chunk-CXJ6FUKN.js} +1852 -207
  70. package/dist/{chunk-ABWHYWNI.js → chunk-D73UEXYW.js} +3 -3
  71. package/dist/chunk-DCZWQLYT.js +1205 -0
  72. package/dist/chunk-DLOBCJL6.js +48 -0
  73. package/dist/{chunk-4BN53TG3.js → chunk-DOBQKHIF.js} +31 -23
  74. package/dist/chunk-E3ISYXO3.js +423 -0
  75. package/dist/{chunk-7SW2QWLU.js → chunk-E6ZIEVOI.js} +16 -13
  76. package/dist/chunk-EBL2R3YG.js +43 -0
  77. package/dist/{chunk-AIOQPLA5.js → chunk-EGQRREQH.js} +41 -15
  78. package/dist/chunk-EHA7RMZ3.js +58 -0
  79. package/dist/{chunk-M766ZJ6W.js → chunk-EIPTLPFC.js} +38 -27
  80. package/dist/chunk-EMRIQUND.js +517 -0
  81. package/dist/{chunk-DFBCSHVT.js → chunk-EPCJQQWD.js} +6 -4
  82. package/dist/{chunk-RZPYKDWS.js → chunk-F3P7N7SF.js} +1 -1
  83. package/dist/{chunk-R77KLRB3.js → chunk-FFLNS6VP.js} +21 -18
  84. package/dist/chunk-FFTRTL6R.js +26 -0
  85. package/dist/{chunk-IHMLFRVV.js → chunk-FPJPLKDW.js} +62 -16
  86. package/dist/{chunk-JCZIKA4C.js → chunk-FSMSFDLD.js} +5 -4
  87. package/dist/{chunk-AVJDSJ2F.js → chunk-FUJM6RTF.js} +8 -7
  88. package/dist/chunk-FZOJFH7Q.js +132 -0
  89. package/dist/{chunk-QRAOANID.js → chunk-G6X77UJZ.js} +23 -21
  90. package/dist/{chunk-3ALD2W2A.js → chunk-GCWRWSU7.js} +10 -4
  91. package/dist/chunk-GIW4ZVDB.js +39 -0
  92. package/dist/{chunk-B2WLAWNJ.js → chunk-GUX3PTYM.js} +3 -3
  93. package/dist/{chunk-DPUYDDQG.js → chunk-GZY6RUZ6.js} +25 -3
  94. package/dist/chunk-H4VO6WG3.js +10 -0
  95. package/dist/{chunk-MMOSZPWJ.js → chunk-H5HBGNXU.js} +5 -4
  96. package/dist/chunk-H7KM7LZE.js +229 -0
  97. package/dist/{chunk-AA6YULYB.js → chunk-HNM2YQT2.js} +7 -7
  98. package/dist/{chunk-3C7EYRFZ.js → chunk-HYU5VLGA.js} +1 -1
  99. package/dist/{chunk-XY3P7JW7.js → chunk-IDKCWSM5.js} +1032 -172
  100. package/dist/chunk-IFKEI4SA.js +237 -0
  101. package/dist/{chunk-F7HYOUFF.js → chunk-IGOE6KPG.js} +67 -22
  102. package/dist/{chunk-TDD55CJH.js → chunk-IH2XURVQ.js} +6 -5
  103. package/dist/chunk-INQHESFB.js +38 -0
  104. package/dist/chunk-IP74LCOQ.js +57 -0
  105. package/dist/chunk-IPHHDDC6.js +45 -0
  106. package/dist/{chunk-T6AIP7H5.js → chunk-ISUAAMGS.js} +110 -153
  107. package/dist/{chunk-A7UPUQFY.js → chunk-IUPG3UKI.js} +624 -319
  108. package/dist/{chunk-L6SGQIR3.js → chunk-IVBOQAGB.js} +7 -3
  109. package/dist/{chunk-27NKUS3X.js → chunk-J2JAKCIW.js} +2205 -796
  110. package/dist/{chunk-V2YTAIQO.js → chunk-J3IOLXWM.js} +24 -7
  111. package/dist/chunk-JA5FI3QV.js +142 -0
  112. package/dist/chunk-JAVI7JSP.js +49 -0
  113. package/dist/{chunk-HLJAXMM4.js → chunk-JB5LINEM.js} +6 -2
  114. package/dist/{chunk-2VHF7OXM.js → chunk-JENSEMXF.js} +1 -1
  115. package/dist/{chunk-6BVONWJ7.js → chunk-JJF6HALY.js} +4 -3
  116. package/dist/chunk-JLUCKAEL.js +38 -0
  117. package/dist/chunk-JRBFANFE.js +221 -0
  118. package/dist/{chunk-R6XF6UR3.js → chunk-KDNTAPLX.js} +4 -4
  119. package/dist/chunk-KFAVQZSX.js +33 -0
  120. package/dist/chunk-KJXD4PNL.js +50 -0
  121. package/dist/chunk-KN5BXMWN.js +44 -0
  122. package/dist/{chunk-PCVDV3UZ.js → chunk-KQGURXFU.js} +9 -7
  123. package/dist/{chunk-WY6PP6AA.js → chunk-KXITGYLF.js} +40 -6
  124. package/dist/{chunk-66YVAGGM.js → chunk-L27SV425.js} +22 -20
  125. package/dist/{chunk-NE2W3OO7.js → chunk-LDLL7LB3.js} +24 -22
  126. package/dist/chunk-LFGTYX5U.js +379 -0
  127. package/dist/{chunk-EYWIDJFU.js → chunk-LGBMTVNT.js} +7 -5
  128. package/dist/{chunk-Q5AMFEWD.js → chunk-LGFL54FP.js} +3 -2
  129. package/dist/{chunk-6TACQN3N.js → chunk-LJXMYKZJ.js} +7 -5
  130. package/dist/{chunk-BKVWTZ6A.js → chunk-LKOR5UET.js} +29 -26
  131. package/dist/chunk-LNBQOP7D.js +294 -0
  132. package/dist/{chunk-O3WI5KWW.js → chunk-LO6P2VYG.js} +2 -2
  133. package/dist/chunk-LQJPN536.js +122 -0
  134. package/dist/{chunk-YEDDOYSC.js → chunk-LYBNHMVZ.js} +29 -5
  135. package/dist/{chunk-A3GY6SOA.js → chunk-LZ7NUC62.js} +20 -18
  136. package/dist/chunk-M32BLWDH.js +37 -0
  137. package/dist/{chunk-VYDBJ73M.js → chunk-M3NANSDZ.js} +17 -15
  138. package/dist/chunk-MFHL5URL.js +31 -0
  139. package/dist/chunk-MFR5OPBD.js +109 -0
  140. package/dist/{chunk-DE76JROX.js → chunk-MG4ZL5RW.js} +32 -20
  141. package/dist/{chunk-N7IXEHK3.js → chunk-MO6P2JZH.js} +10 -8
  142. package/dist/{chunk-65NYPGRC.js → chunk-MUWDB4R4.js} +1 -1
  143. package/dist/chunk-MZCGSXVR.js +34 -0
  144. package/dist/{chunk-MGYZM27B.js → chunk-N3XIYPU3.js} +51 -23
  145. package/dist/chunk-NDCF4R6S.js +172 -0
  146. package/dist/{chunk-DHPACDG7.js → chunk-NR2UJWOC.js} +10 -8
  147. package/dist/chunk-NXJ5URP6.js +51 -0
  148. package/dist/{chunk-UNM6ZOKP.js → chunk-NY2XSR5K.js} +147 -18
  149. package/dist/{chunk-5GDRCDQB.js → chunk-O45HFTFS.js} +3 -2
  150. package/dist/{chunk-ONLS5QA5.js → chunk-O4GXGGBX.js} +14 -12
  151. package/dist/chunk-O5PXQR67.js +249 -0
  152. package/dist/{chunk-PRPPGYZG.js → chunk-O66DM6DJ.js} +6 -4
  153. package/dist/{chunk-KEM4SDDP.js → chunk-O7FDLW7L.js} +11 -8
  154. package/dist/{chunk-T2UYZSCQ.js → chunk-O7XLYEFA.js} +169 -29
  155. package/dist/{chunk-FITWGOJ2.js → chunk-OHNCWBKF.js} +4 -4
  156. package/dist/{chunk-652QWTLZ.js → chunk-OHVTTOPS.js} +3 -3
  157. package/dist/chunk-OMI6FPPN.js +43 -0
  158. package/dist/chunk-ONUPY3H6.js +53 -0
  159. package/dist/chunk-OTLDSZDV.js +69 -0
  160. package/dist/chunk-OUBGGKDU.js +22 -0
  161. package/dist/chunk-OWNCM4ZN.js +330 -0
  162. package/dist/{chunk-YISXLPHN.js → chunk-P2V7QW4D.js} +235 -35
  163. package/dist/{chunk-CNUKCS2T.js → chunk-P32RUW3B.js} +1632 -93
  164. package/dist/{chunk-BWZ77RQT.js → chunk-PAQ2AS5E.js} +1 -1
  165. package/dist/{chunk-ZMAINWBW.js → chunk-PBPBMP2B.js} +4 -3
  166. package/dist/{chunk-ZVM6AKKM.js → chunk-PJSJPMJI.js} +3 -3
  167. package/dist/{chunk-EFHQ3TWP.js → chunk-PKBHS4AA.js} +233 -56
  168. package/dist/{chunk-GT4I4ZWM.js → chunk-PMUAJGLI.js} +20 -16
  169. package/dist/chunk-PPD7HTDP.js +152 -0
  170. package/dist/chunk-PSOFBQWB.js +42 -0
  171. package/dist/{chunk-S2A7YC3Q.js → chunk-Q2TECDIT.js} +10694 -8896
  172. package/dist/chunk-Q4K5WB2W.js +42 -0
  173. package/dist/{chunk-UGLN7QHV.js → chunk-Q6DFNVRJ.js} +14 -12
  174. package/dist/chunk-QA4O2GGC.js +265 -0
  175. package/dist/chunk-QAXW2N3B.js +1216 -0
  176. package/dist/chunk-QBNWF5ZU.js +19 -0
  177. package/dist/chunk-QFWA2DPH.js +224 -0
  178. package/dist/{chunk-23W7VWKR.js → chunk-QKUJMING.js} +1363 -114
  179. package/dist/{chunk-NXFPS2LR.js → chunk-R44CYFPV.js} +16 -13
  180. package/dist/{chunk-CKSITVS4.js → chunk-R7NYHMUU.js} +2687 -786
  181. package/dist/chunk-REWWDVQB.js +162 -0
  182. package/dist/{chunk-JMSCMUCA.js → chunk-RGERPOIV.js} +145 -21
  183. package/dist/{chunk-6JCPI55B.js → chunk-RLDGWLQ7.js} +49 -7
  184. package/dist/chunk-RUGXBPWI.js +384 -0
  185. package/dist/{chunk-CPA6HPVR.js → chunk-RXPJMEOW.js} +18 -12
  186. package/dist/{chunk-3HI6Z55Y.js → chunk-S4PMJU6H.js} +339 -43
  187. package/dist/chunk-S5LSDXV4.js +40 -0
  188. package/dist/chunk-S7FCV7S5.js +51 -0
  189. package/dist/{chunk-5GGOLAKC.js → chunk-SDKLKB6I.js} +28 -26
  190. package/dist/chunk-SFSPGFCV.js +62 -0
  191. package/dist/{chunk-ZNCEKR4J.js → chunk-SFUP7TTO.js} +12 -8
  192. package/dist/{chunk-64EQYWCA.js → chunk-SLXZOMA6.js} +69 -19
  193. package/dist/chunk-SQV37XO2.js +273 -0
  194. package/dist/{chunk-K65BJIMT.js → chunk-SU74NDMQ.js} +19 -17
  195. package/dist/chunk-SYV5LHML.js +165 -0
  196. package/dist/chunk-T4YPZIQN.js +36 -0
  197. package/dist/chunk-T6DQR5TV.js +323 -0
  198. package/dist/{chunk-JIITQXFB.js → chunk-THDMSZ3R.js} +3075 -802
  199. package/dist/{chunk-JGZCG5VM.js → chunk-TNR75OXT.js} +7 -7
  200. package/dist/{chunk-D3PO4DOZ.js → chunk-TUULXQRW.js} +174 -15
  201. package/dist/chunk-TYQBFTBR.js +516 -0
  202. package/dist/chunk-U76OWS3Q.js +49 -0
  203. package/dist/{chunk-YYQN46FY.js → chunk-UCROWG2D.js} +27 -24
  204. package/dist/{chunk-6M5NK3K3.js → chunk-UF4AZOZB.js} +50 -10
  205. package/dist/chunk-UF4GLFBX.js +345 -0
  206. package/dist/{chunk-OT2O76OS.js → chunk-UGUP3ZM6.js} +240 -39
  207. package/dist/chunk-UNAGJYET.js +45 -0
  208. package/dist/{chunk-5WG5YP4T.js → chunk-UOR2DTHH.js} +16 -14
  209. package/dist/{chunk-S3QNRWYR.js → chunk-UPOY4YSQ.js} +14 -12
  210. package/dist/{chunk-EPTBZ3GP.js → chunk-UPS2DGFC.js} +1 -1
  211. package/dist/{chunk-4AK7IBVP.js → chunk-UUU4CLJG.js} +4 -2
  212. package/dist/{chunk-W3BQAZ3Q.js → chunk-UWMJKX5U.js} +14 -12
  213. package/dist/{chunk-QZSX3F7C.js → chunk-UWOJLHFT.js} +27 -23
  214. package/dist/chunk-VBTP56CE.js +535 -0
  215. package/dist/chunk-VCTWPLAO.js +211 -0
  216. package/dist/chunk-VNU26RCO.js +1215 -0
  217. package/dist/{chunk-CSZ4C5N6.js → chunk-VTZMAJ3W.js} +93 -10
  218. package/dist/{chunk-TXLH6WHQ.js → chunk-VW62D6QE.js} +14 -12
  219. package/dist/{chunk-CAQZUNOH.js → chunk-VY72R2XZ.js} +610 -3
  220. package/dist/{chunk-2DIQQJCB.js → chunk-VZALIKIF.js} +18 -15
  221. package/dist/{chunk-TYAID7B7.js → chunk-W62H2XSO.js} +25 -23
  222. package/dist/{chunk-HVUPKCGJ.js → chunk-W7VWI2YH.js} +9 -6
  223. package/dist/{chunk-TANFV3MZ.js → chunk-WERM6KPJ.js} +7 -4
  224. package/dist/{chunk-BOHJZTEQ.js → chunk-WF7B67YE.js} +208 -87
  225. package/dist/{chunk-7FBGJFEE.js → chunk-WG5U3F5V.js} +14 -12
  226. package/dist/{chunk-4NDAAFQT.js → chunk-WJF2CS6M.js} +8 -5
  227. package/dist/{chunk-XAKWMCXI.js → chunk-WKUJ3KPV.js} +4 -4
  228. package/dist/chunk-WMTRHUI5.js +103 -0
  229. package/dist/chunk-WNKPRSGI.js +36 -0
  230. package/dist/chunk-WXFLMQSR.js +223 -0
  231. package/dist/{chunk-RRTKKSLQ.js → chunk-X3WY6MN3.js} +8 -6
  232. package/dist/{chunk-ZCJDOK2S.js → chunk-X4CXA2IL.js} +47 -23
  233. package/dist/{chunk-UBBC2XSG.js → chunk-X5F3Q5LV.js} +560 -105
  234. package/dist/{chunk-C6EKFH7J.js → chunk-XD75VZIH.js} +9 -7
  235. package/dist/chunk-XERYFDB5.js +297 -0
  236. package/dist/chunk-XI2LCCYQ.js +420 -0
  237. package/dist/chunk-Y2EQNWKV.js +933 -0
  238. package/dist/{chunk-LR3R6Z2A.js → chunk-YHCMZC2J.js} +7 -7
  239. package/dist/chunk-YYY3AZFE.js +122 -0
  240. package/dist/{chunk-GDLULHTC.js → chunk-Z5IA3WDR.js} +19 -31
  241. package/dist/{chunk-T6XQL73F.js → chunk-ZFFYNRIO.js} +63 -23
  242. package/dist/{chunk-EDS2L2LD.js → chunk-ZFL7NY4F.js} +56 -27
  243. package/dist/{chunk-YMZ3TNYB.js → chunk-ZGULQAPZ.js} +7 -4
  244. package/dist/{chunk-4SKZDI62.js → chunk-ZIUFM5HT.js} +3 -1
  245. package/dist/{chunk-DKJA76CJ.js → chunk-ZJFRMSJT.js} +15 -13
  246. package/dist/chunk-ZJXLNDH4.js +239 -0
  247. package/dist/chunk-ZQ3ON2VQ.js +252 -0
  248. package/dist/{chunk-HITVBIJS.js → chunk-ZQ7SKESZ.js} +150 -415
  249. package/dist/{chunk-6QSERWXH.js → chunk-ZQXZ2SES.js} +24 -21
  250. package/dist/chunk-ZX57KSEQ.js +39 -0
  251. package/dist/{chunk-I3E7CX4H.js → chunk-ZZK56BLP.js} +5 -3
  252. package/dist/files.json +664 -368
  253. package/dist/packages/naysayer/constitution/constitution.yaml +19 -0
  254. package/dist/packages/sdk/npm/index.js +6194 -2542
  255. package/dist/packages/ui/dist/assets/{elk-api-tma0MCuh.js → elk-api-CIf-0gz5.js} +2 -2
  256. package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +47 -0
  257. package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +1 -0
  258. package/dist/packages/ui/dist/index.html +3 -2
  259. package/package.json +5 -5
  260. package/dist/chunk-2BF2EYJV.js +0 -174
  261. package/dist/chunk-42EVSKME.js +0 -37
  262. package/dist/chunk-4BKGMUIK.js +0 -53
  263. package/dist/chunk-5KLGBXG5.js +0 -48
  264. package/dist/chunk-6BNC6EQ4.js +0 -41
  265. package/dist/chunk-6D2CQ5II.js +0 -41
  266. package/dist/chunk-7AVHLZGD.js +0 -45
  267. package/dist/chunk-D46WUV3T.js +0 -33
  268. package/dist/chunk-E36QOJMD.js +0 -47
  269. package/dist/chunk-FQXYPF7E.js +0 -147
  270. package/dist/chunk-GBRFVT63.js +0 -45
  271. package/dist/chunk-ICY36XCH.js +0 -34
  272. package/dist/chunk-J4K3KVLD.js +0 -131
  273. package/dist/chunk-JZU3H6UQ.js +0 -54
  274. package/dist/chunk-NN2ZQEB4.js +0 -38
  275. package/dist/chunk-PCOCACY3.js +0 -385
  276. package/dist/chunk-RTEYOSJY.js +0 -29
  277. package/dist/chunk-RUVFXE2L.js +0 -666
  278. package/dist/chunk-RVH5SUW5.js +0 -69
  279. package/dist/chunk-VN3DP4LQ.js +0 -43
  280. package/dist/chunk-W5BVQF44.js +0 -36
  281. package/dist/chunk-WVPJSRRJ.js +0 -52
  282. package/dist/chunk-XPTOBS2D.js +0 -48
  283. package/dist/packages/ui/dist/assets/index-B54fm9FQ.js +0 -29
  284. package/dist/packages/ui/dist/assets/index-DD_hufQz.css +0 -1
@@ -4,30 +4,27 @@ var require = __atticusCreateRequire(import.meta.url);
4
4
  var __atticusUrl = (p) => new URL("./" + p, import.meta.url).href;
5
5
  var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
6
6
  import {
7
- catalogRecords
8
- } from "./chunk-B2WLAWNJ.js";
7
+ QueryError,
8
+ askLookup,
9
+ graph,
10
+ impact,
11
+ openIndex,
12
+ translate
13
+ } from "./chunk-ISUAAMGS.js";
9
14
  import {
10
15
  readRound,
11
16
  reviewedGates,
12
17
  roundsOf
13
- } from "./chunk-3HI6Z55Y.js";
18
+ } from "./chunk-S4PMJU6H.js";
14
19
  import {
15
20
  changeFolder,
16
21
  changeStore
17
- } from "./chunk-XY3P7JW7.js";
18
- import {
19
- QueryError,
20
- askLookup,
21
- graph,
22
- impact,
23
- openIndex,
24
- translate
25
- } from "./chunk-T6AIP7H5.js";
22
+ } from "./chunk-IDKCWSM5.js";
26
23
  import {
27
24
  baseClonePath,
28
25
  gitUser,
29
26
  loadRepos
30
- } from "./chunk-EFHQ3TWP.js";
27
+ } from "./chunk-PKBHS4AA.js";
31
28
  import {
32
29
  API_VERSION,
33
30
  DEFAULT_PORT,
@@ -35,8 +32,8 @@ import {
35
32
  RECORD_KINDS,
36
33
  RecordId,
37
34
  Severity,
35
+ api_exports,
38
36
  catalogDirOf,
39
- changesDirOf,
40
37
  factsDirOf,
41
38
  fastPathOf,
42
39
  inputsDirOf,
@@ -48,23 +45,14 @@ import {
48
45
  proposalsDirOf,
49
46
  questionOfLens,
50
47
  questionsDirOf,
51
- readRepoSpec,
52
- require_dist,
53
48
  runsDirOf,
54
- specRepos,
55
49
  specsDirOf,
56
50
  withSignal
57
- } from "./chunk-S2A7YC3Q.js";
51
+ } from "./chunk-Q2TECDIT.js";
58
52
  import {
53
+ FileChangedError,
59
54
  SCHEMA_VERSION
60
- } from "./chunk-D3PO4DOZ.js";
61
- import {
62
- __toESM
63
- } from "./chunk-TV45EUGM.js";
64
-
65
- // packages/cli/dist/ui-api-cites.js
66
- import { readdir, readFile as readFile3, stat as stat3 } from "node:fs/promises";
67
- import { isAbsolute, join as join4, relative as relative2, sep as sep3 } from "node:path";
55
+ } from "./chunk-TUULXQRW.js";
68
56
 
69
57
  // packages/server/dist/http.js
70
58
  var HttpError = class extends Error {
@@ -148,6 +136,115 @@ function intParam(q, name, min, max) {
148
136
  }
149
137
  var strParam = (q, name) => q.get(name) || void 0;
150
138
 
139
+ // packages/server/dist/server.js
140
+ import { randomBytes as randomBytes2 } from "node:crypto";
141
+ import { createServer } from "node:http";
142
+
143
+ // packages/server/dist/jobs.js
144
+ var JobManager = class {
145
+ publish;
146
+ now;
147
+ jobs = /* @__PURE__ */ new Map();
148
+ cancelledIds = /* @__PURE__ */ new Set();
149
+ aborts = /* @__PURE__ */ new Map();
150
+ seq = 0;
151
+ /** Round 41: every running job of a kind, in start order (a later one never hides an earlier). */
152
+ running = /* @__PURE__ */ new Map();
153
+ constructor(publish, now = () => /* @__PURE__ */ new Date()) {
154
+ this.publish = publish;
155
+ this.now = now;
156
+ }
157
+ /**
158
+ * A running job of a kind, if any: the earliest still running (one scan at a time: a second
159
+ * ask gets 409).
160
+ */
161
+ runningOf(kind) {
162
+ for (const id of this.running.get(kind) ?? []) {
163
+ const j = this.jobs.get(id);
164
+ if (j?.state === "running")
165
+ return j;
166
+ }
167
+ return void 0;
168
+ }
169
+ get(id) {
170
+ return this.jobs.get(id);
171
+ }
172
+ start(kind, work) {
173
+ const id = `job-${++this.seq}`;
174
+ const job = {
175
+ id,
176
+ kind,
177
+ state: "running",
178
+ progress: { done: 0, total: 0, message: "Starting" },
179
+ startedAt: this.now().toISOString(),
180
+ errors: []
181
+ };
182
+ this.jobs.set(id, job);
183
+ const ofKind = this.running.get(kind) ?? /* @__PURE__ */ new Set();
184
+ ofKind.add(id);
185
+ this.running.set(kind, ofKind);
186
+ const abort = new AbortController();
187
+ this.aborts.set(id, abort);
188
+ const cancelled = this.cancelledIds;
189
+ const control = {
190
+ progress: (done, total, message) => {
191
+ job.progress = { done, total, message };
192
+ this.publish({ type: "job.progress", jobId: id, done, total, message });
193
+ },
194
+ get cancelled() {
195
+ return cancelled.has(id);
196
+ }
197
+ };
198
+ void (async () => {
199
+ try {
200
+ const out = await withSignal(abort.signal, () => work(control));
201
+ if (out?.result)
202
+ job.result = out.result;
203
+ if (out?.errors?.length)
204
+ job.errors.push(...out.errors);
205
+ job.state = this.cancelledIds.has(id) ? "cancelled" : job.errors.length ? "failed" : "done";
206
+ } catch (e) {
207
+ if (this.cancelledIds.has(id))
208
+ job.state = "cancelled";
209
+ else {
210
+ job.errors.push(e instanceof Error ? e.message : String(e));
211
+ job.state = "failed";
212
+ }
213
+ }
214
+ this.aborts.delete(id);
215
+ job.finishedAt = this.now().toISOString();
216
+ ofKind.delete(id);
217
+ if (!ofKind.size && this.running.get(kind) === ofKind)
218
+ this.running.delete(kind);
219
+ this.publish({ type: "job.done", jobId: id, state: job.state });
220
+ })();
221
+ return job;
222
+ }
223
+ /** Ask a running job to stop; false when it already finished. */
224
+ cancel(id) {
225
+ const j = this.jobs.get(id);
226
+ if (!j || j.state !== "running")
227
+ return false;
228
+ this.cancelledIds.add(id);
229
+ this.aborts.get(id)?.abort();
230
+ return true;
231
+ }
232
+ /** Wait for a job to finish (tests and the CLI). */
233
+ async settle(id, timeoutMs = 6e4) {
234
+ const start = Date.now();
235
+ for (; ; ) {
236
+ const j = this.jobs.get(id);
237
+ if (!j)
238
+ throw new Error(`No job ${id}`);
239
+ if (j.state !== "running" && j.state !== "queued")
240
+ return j;
241
+ if (Date.now() - start > timeoutMs)
242
+ throw new Error(`Job ${id} did not finish`);
243
+ await new Promise((r) => setTimeout(r, 20));
244
+ }
245
+ }
246
+ };
247
+
151
248
  // packages/server/dist/routes.js
152
249
  import { readFile, stat } from "node:fs/promises";
153
250
  import { join } from "node:path";
@@ -232,6 +329,7 @@ function apiRoutes(r, ctx) {
232
329
  ...strParam(query, "status") ? { status: strParam(query, "status") } : {},
233
330
  ...strParam(query, "system") ? { system: strParam(query, "system") } : {},
234
331
  ...strParam(query, "q") ? { q: strParam(query, "q") } : {},
332
+ ...strParam(query, "confidence") ? { confidence: strParam(query, "confidence") } : {},
235
333
  ...strParam(query, "cursor") ? { cursor: strParam(query, "cursor") } : {},
236
334
  ...limit !== void 0 ? { limit } : {}
237
335
  };
@@ -289,7 +387,20 @@ function apiRoutes(r, ctx) {
289
387
  return { status: 200, body: await withIndex(root, (ix) => graph(ix, o)) };
290
388
  }).add("GET", "/api/impact/{id}", async ({ params, query }) => {
291
389
  const depth = intParam(query, "depth", 1, 10);
292
- const res = await withIndex(root, (ix) => impact(ix, params.id, depth));
390
+ const res = await withIndex(root, (ix) => {
391
+ const r2 = impact(ix, params.id, depth);
392
+ if (!r2)
393
+ return void 0;
394
+ return {
395
+ ...r2,
396
+ affected: r2.affected.map((a) => {
397
+ const rec = ix.find(a.id)[0];
398
+ const ai = (rec?.evidence ?? []).find((e) => e.source === "ai");
399
+ const flagged = Array.isArray(rec?.flags) && rec.flags.includes("joined-by-ai");
400
+ return flagged || ai ? { ...a, byAi: true, ...ai?.run ? { run: ai.run } : {} } : a;
401
+ })
402
+ };
403
+ });
293
404
  if (!res)
294
405
  throw notFound(`There is no record ${params.id} in the catalog.`);
295
406
  return { status: 200, body: res };
@@ -380,6 +491,8 @@ function apiRoutes(r, ctx) {
380
491
  return { status: 200, body };
381
492
  }).add("GET", "/api/findings", async ({ query }) => {
382
493
  const change = strParam(query, "change");
494
+ if (change !== void 0 && !RecordId.safeParse(change).success)
495
+ throw badRequest(`${change} isn't a change id.`);
383
496
  const gate = strParam(query, "gate");
384
497
  const state = strParam(query, "state");
385
498
  const lens = enumParam(query, "lens", Lens.options);
@@ -393,6 +506,8 @@ function apiRoutes(r, ctx) {
393
506
  body.push(f);
394
507
  return { status: 200, body };
395
508
  }).add("GET", "/api/findings/{changeId}/{findingId}", async ({ params }) => {
509
+ if (!RecordId.safeParse(params.changeId).success)
510
+ throw badRequest(`${params.changeId} isn't a change id.`);
396
511
  const f = (await latestFindings(root, params.changeId)).find((x) => x.id === params.findingId);
397
512
  if (!f)
398
513
  throw notFound(`Change ${params.changeId} has no finding ${params.findingId}.`);
@@ -435,107 +550,9 @@ function apiRoutes(r, ctx) {
435
550
  });
436
551
  }
437
552
 
438
- // packages/server/dist/server.js
439
- import { randomBytes, timingSafeEqual } from "node:crypto";
440
- import { createServer } from "node:http";
441
-
442
- // packages/server/dist/jobs.js
443
- var JobManager = class {
444
- publish;
445
- now;
446
- jobs = /* @__PURE__ */ new Map();
447
- cancelledIds = /* @__PURE__ */ new Set();
448
- aborts = /* @__PURE__ */ new Map();
449
- seq = 0;
450
- running = /* @__PURE__ */ new Map();
451
- constructor(publish, now = () => /* @__PURE__ */ new Date()) {
452
- this.publish = publish;
453
- this.now = now;
454
- }
455
- /** The running job of a kind, if any (one scan at a time: a second asks gets 409). */
456
- runningOf(kind) {
457
- const id = this.running.get(kind);
458
- return id ? this.jobs.get(id) : void 0;
459
- }
460
- get(id) {
461
- return this.jobs.get(id);
462
- }
463
- start(kind, work) {
464
- const id = `job-${++this.seq}`;
465
- const job = {
466
- id,
467
- kind,
468
- state: "running",
469
- progress: { done: 0, total: 0, message: "Starting" },
470
- startedAt: this.now().toISOString(),
471
- errors: []
472
- };
473
- this.jobs.set(id, job);
474
- this.running.set(kind, id);
475
- const abort = new AbortController();
476
- this.aborts.set(id, abort);
477
- const cancelled = this.cancelledIds;
478
- const control = {
479
- progress: (done, total, message) => {
480
- job.progress = { done, total, message };
481
- this.publish({ type: "job.progress", jobId: id, done, total, message });
482
- },
483
- get cancelled() {
484
- return cancelled.has(id);
485
- }
486
- };
487
- void (async () => {
488
- try {
489
- const out = await withSignal(abort.signal, () => work(control));
490
- if (out?.result)
491
- job.result = out.result;
492
- if (out?.errors?.length)
493
- job.errors.push(...out.errors);
494
- job.state = this.cancelledIds.has(id) ? "cancelled" : job.errors.length ? "failed" : "done";
495
- } catch (e) {
496
- if (this.cancelledIds.has(id))
497
- job.state = "cancelled";
498
- else {
499
- job.errors.push(e instanceof Error ? e.message : String(e));
500
- job.state = "failed";
501
- }
502
- }
503
- this.aborts.delete(id);
504
- job.finishedAt = this.now().toISOString();
505
- if (this.running.get(kind) === id)
506
- this.running.delete(kind);
507
- this.publish({ type: "job.done", jobId: id, state: job.state });
508
- })();
509
- return job;
510
- }
511
- /** Ask a running job to stop; false when it already finished. */
512
- cancel(id) {
513
- const j = this.jobs.get(id);
514
- if (!j || j.state !== "running")
515
- return false;
516
- this.cancelledIds.add(id);
517
- this.aborts.get(id)?.abort();
518
- return true;
519
- }
520
- /** Wait for a job to finish (tests and the CLI). */
521
- async settle(id, timeoutMs = 6e4) {
522
- const start = Date.now();
523
- for (; ; ) {
524
- const j = this.jobs.get(id);
525
- if (!j)
526
- throw new Error(`No job ${id}`);
527
- if (j.state !== "running" && j.state !== "queued")
528
- return j;
529
- if (Date.now() - start > timeoutMs)
530
- throw new Error(`Job ${id} did not finish`);
531
- await new Promise((r) => setTimeout(r, 20));
532
- }
533
- }
534
- };
535
-
536
553
  // packages/server/dist/static.js
537
554
  import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
538
- import { extname, join as join2, normalize, sep } from "node:path";
555
+ import { extname, join as join2, normalize, resolve, sep } from "node:path";
539
556
  var TYPES = {
540
557
  ".html": "text/html; charset=utf-8",
541
558
  ".js": "text/javascript; charset=utf-8",
@@ -564,7 +581,8 @@ function appCsp(port, embed) {
564
581
  ].join("; ");
565
582
  }
566
583
  var escapeAttr = (s) => s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
567
- async function staticFile(dir, path, token) {
584
+ async function staticFile(givenDir, path, token, pageKey) {
585
+ const dir = resolve(givenDir);
568
586
  let rel;
569
587
  try {
570
588
  rel = decodeURIComponent(path);
@@ -583,7 +601,12 @@ async function staticFile(dir, path, token) {
583
601
  const ext = extname(target).toLowerCase();
584
602
  const type = TYPES[ext] ?? "application/octet-stream";
585
603
  if (ext === ".html") {
586
- const html = (await readFile2(target, "utf8")).replace(/<meta name="atticus-token" content="[^"]*"\s*\/?>/, `<meta name="atticus-token" content="${escapeAttr(token)}" />`);
604
+ const tokenMeta = `<meta name="atticus-token" content="${escapeAttr(token)}" />`;
605
+ const keyMeta = pageKey === void 0 ? "" : `<meta name="atticus-page-key" content="${escapeAttr(pageKey)}" />`;
606
+ let html = (await readFile2(target, "utf8")).replace(/<meta name="atticus-token" content="[^"]*"\s*\/?>/, () => tokenMeta);
607
+ if (keyMeta)
608
+ html = /<meta name="atticus-page-key" content="[^"]*"\s*\/?>/.test(html) ? html.replace(/<meta name="atticus-page-key" content="[^"]*"\s*\/?>/, () => keyMeta) : html.replace(tokenMeta, () => `${tokenMeta}
609
+ ${keyMeta}`);
587
610
  return { status: 200, type, body: html, cache: "no-store" };
588
611
  }
589
612
  return {
@@ -595,6 +618,91 @@ async function staticFile(dir, path, token) {
595
618
  };
596
619
  }
597
620
 
621
+ // packages/server/dist/confirm.js
622
+ import { randomBytes, timingSafeEqual } from "node:crypto";
623
+ var CONFIRM_TTL_MS = 12e4;
624
+ var MAX_OPEN = 256;
625
+ var Confirmations = class {
626
+ now;
627
+ open = /* @__PURE__ */ new Map();
628
+ constructor(now = () => Date.now()) {
629
+ this.now = now;
630
+ }
631
+ issue(write, target) {
632
+ const t = this.now();
633
+ for (const [k, v] of this.open)
634
+ if (v.until < t)
635
+ this.open.delete(k);
636
+ while (this.open.size >= MAX_OPEN)
637
+ this.open.delete(this.open.keys().next().value);
638
+ const confirmation = randomBytes(32).toString("base64url");
639
+ const until = t + CONFIRM_TTL_MS;
640
+ this.open.set(confirmation, { write, target, until });
641
+ return { confirmation, write, target, expiresAt: new Date(until).toISOString() };
642
+ }
643
+ /**
644
+ * Whether `given` confirms this write of this target now. It is spent whatever the answer, so a
645
+ * confirmation is never tried twice: a replay, another target or another write is refused.
646
+ */
647
+ take(write, target, given) {
648
+ if (typeof given !== "string" || !given)
649
+ return false;
650
+ const c = this.open.get(given);
651
+ if (!c)
652
+ return false;
653
+ this.open.delete(given);
654
+ return c.write === write && c.target === target && this.now() <= c.until;
655
+ }
656
+ };
657
+ function sameSecret(a, b) {
658
+ const x = Buffer.from(a);
659
+ const y = Buffer.from(b);
660
+ return x.length === y.length && timingSafeEqual(x, y);
661
+ }
662
+ var WITHOUT_THE_APP = {
663
+ handoff: {
664
+ what: "Raising a hand-off opens a PR",
665
+ cli: "atticus change handoff <change> --approve"
666
+ },
667
+ "release-prs": {
668
+ what: "Raising the release PRs pushes the change branch and opens PRs",
669
+ cli: "atticus change release-prs <change> --approve"
670
+ },
671
+ merge: { what: "Merging a ready PR", cli: "atticus change sync <change> --approve" },
672
+ "task-pr": {
673
+ what: "Raising a task's PR pushes its branch and opens a PR",
674
+ cli: "atticus task run <change> <task> --level pr --approve"
675
+ },
676
+ "digest-send": {
677
+ what: "Sending the digest posts a message",
678
+ cli: "atticus digest --send"
679
+ },
680
+ propose: {
681
+ what: "Propose for review pushes a branch and opens a PR",
682
+ cli: "git commit, push and open the PR yourself"
683
+ },
684
+ "step-run": {
685
+ what: "Running a step with a team's tool acts on their systems",
686
+ cli: "atticus todo run <step> --with <executor> --approve <you> --inputs <sha-256>"
687
+ },
688
+ "ai-model": {
689
+ what: "Changing where runtime.yaml sends the model's key (its provider, keyEnv or address)",
690
+ cli: "edit runtime.yaml yourself and propose it for review"
691
+ },
692
+ "ai-test": {
693
+ what: "Testing model settings that aren't committed sends the key to them",
694
+ cli: "commit runtime.yaml first, or run the step from the command line"
695
+ }
696
+ };
697
+ function needsConfirmation(write) {
698
+ const w = WITHOUT_THE_APP[write];
699
+ return new HttpError(403, "This needs a person's confirmation", `${w.what}, which a person confirms: click it in the Atticus app, or run ${w.cli} in a terminal. The session token alone (atticus ui --show-token, for assistants and scripts) never approves a write to a shared system (ADR 0186).`, { confirm: write });
700
+ }
701
+ function requireConfirmation(c, write, target, given) {
702
+ if (!c.take(write, target, given))
703
+ throw needsConfirmation(write);
704
+ }
705
+
598
706
  // packages/server/dist/watch.js
599
707
  import { statSync, watch } from "node:fs";
600
708
  import { join as join3, relative, sep as sep2 } from "node:path";
@@ -613,6 +721,14 @@ function watchMetarepo(o) {
613
721
  const delay = o.delayMs ?? 300;
614
722
  const maxPaths = o.maxPaths ?? 50;
615
723
  const watchers = /* @__PURE__ */ new Map();
724
+ const inodes = /* @__PURE__ */ new Map();
725
+ const inodeOf = (d) => {
726
+ try {
727
+ return statSync(d).ino;
728
+ } catch {
729
+ return void 0;
730
+ }
731
+ };
616
732
  const problems = [];
617
733
  const pending = /* @__PURE__ */ new Set();
618
734
  let timer;
@@ -673,21 +789,39 @@ function watchMetarepo(o) {
673
789
  note(name ? join3(dir, String(name)) : dir);
674
790
  });
675
791
  w.on("error", (e) => {
676
- problems.push(`${posix(relative(root, dir)) || "."}: ${e.message}`);
677
792
  w.close();
793
+ if (watchers.get(dir) !== w)
794
+ return;
795
+ problems.push(`${posix(relative(root, dir)) || "."}: ${e.message}`);
678
796
  watchers.delete(dir);
797
+ inodes.delete(dir);
679
798
  });
680
799
  watchers.set(dir, w);
800
+ const ino = inodeOf(dir);
801
+ if (ino !== void 0)
802
+ inodes.set(dir, ino);
803
+ const label = `${posix(relative(root, dir)) || "."}: `;
804
+ for (let i = problems.length - 1; i >= 0; i--)
805
+ if (problems[i].startsWith(label))
806
+ problems.splice(i, 1);
681
807
  } catch (e) {
682
808
  problems.push(`${posix(relative(root, dir)) || "."}: ${e.message}`);
683
809
  }
684
810
  };
685
811
  const attach = () => {
812
+ for (const [d, w] of watchers) {
813
+ const ino = inodeOf(d);
814
+ if (ino === void 0 || inodes.has(d) && inodes.get(d) !== ino) {
815
+ w.close();
816
+ watchers.delete(d);
817
+ inodes.delete(d);
818
+ }
819
+ }
820
+ follow(root, false);
821
+ follow(join3(root, ".atticus"), false);
686
822
  for (const d of folders())
687
823
  follow(d, true);
688
824
  };
689
- follow(root, false);
690
- follow(join3(root, ".atticus"), false);
691
825
  attach();
692
826
  return {
693
827
  get following() {
@@ -707,6 +841,8 @@ function watchMetarepo(o) {
707
841
 
708
842
  // packages/server/dist/ws.js
709
843
  import { createHash } from "node:crypto";
844
+ var MAX_CLIENT_FRAME = 64 * 1024;
845
+ var MAX_CLIENT_BUFFER = 256 * 1024;
710
846
  var GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
711
847
  function acceptKey(key) {
712
848
  return createHash("sha1").update(key + GUID).digest("base64");
@@ -758,8 +894,14 @@ var Socket = class {
758
894
  this.closed = true;
759
895
  this.onClose(this);
760
896
  }
761
- /** Client frames are masked; only control frames matter to us. */
897
+ /**
898
+ * Client frames are masked; only control frames matter to us. The page sends nothing but pings
899
+ * and a close, so a frame over MAX_CLIENT_FRAME, a buffer over MAX_CLIENT_BUFFER or an unmasked
900
+ * frame (RFC 6455 5.1) closes the connection rather than growing memory.
901
+ */
762
902
  read(d) {
903
+ if (this.buf.length + d.length > MAX_CLIENT_BUFFER)
904
+ return this.close();
763
905
  this.buf = Buffer.concat([this.buf, d]);
764
906
  while (this.buf.length >= 2) {
765
907
  const opcode = this.buf[0] & 15;
@@ -777,15 +919,15 @@ var Socket = class {
777
919
  len = Number(this.buf.readBigUInt64BE(2));
778
920
  off = 10;
779
921
  }
922
+ if (!masked || len > MAX_CLIENT_FRAME)
923
+ return this.close();
780
924
  const maskOff = off;
781
- if (masked)
782
- off += 4;
925
+ off += 4;
783
926
  if (this.buf.length < off + len)
784
927
  return;
785
928
  const payload = Buffer.from(this.buf.subarray(off, off + len));
786
- if (masked)
787
- for (let i = 0; i < payload.length; i++)
788
- payload[i] ^= this.buf[maskOff + i % 4];
929
+ for (let i = 0; i < payload.length; i++)
930
+ payload[i] ^= this.buf[maskOff + i % 4];
789
931
  this.buf = this.buf.subarray(off + len);
790
932
  if (opcode === 8)
791
933
  return this.close();
@@ -842,11 +984,8 @@ var EventHub = class {
842
984
  }
843
985
  };
844
986
  var MAX_BODY = 4 * 1024 * 1024;
845
- function sameToken(a, b) {
846
- const x = Buffer.from(a);
847
- const y = Buffer.from(b);
848
- return x.length === y.length && timingSafeEqual(x, y);
849
- }
987
+ var sameToken = sameSecret;
988
+ var STRONG = /^[A-Za-z0-9_-]{32,}$/;
850
989
  async function readBody(req, max = MAX_BODY) {
851
990
  const chunks = [];
852
991
  let size = 0;
@@ -888,9 +1027,11 @@ async function startServer(o) {
888
1027
  const host = o.host ?? "127.0.0.1";
889
1028
  if (host !== "127.0.0.1")
890
1029
  throw new Error(`Atticus only listens on 127.0.0.1 (asked for ${host}).`);
891
- const token = o.token && /^[A-Za-z0-9_-]{32,}$/.test(o.token) ? o.token : randomBytes(32).toString("base64url");
1030
+ const token = o.token && STRONG.test(o.token) ? o.token : randomBytes2(32).toString("base64url");
1031
+ const pageKey = o.pageKey && STRONG.test(o.pageKey) && o.pageKey !== token ? o.pageKey : randomBytes2(32).toString("base64url");
892
1032
  const events = new EventHub();
893
1033
  const jobs = new JobManager((e) => events.publish(e));
1034
+ const confirmations = new Confirmations();
894
1035
  const person = o.user ? { handle: o.user, source: "given" } : await gitUser(o.root);
895
1036
  const ctx = {
896
1037
  root: o.root,
@@ -899,9 +1040,17 @@ async function startServer(o) {
899
1040
  version: o.version ?? "0.0.0",
900
1041
  full: o.full === true,
901
1042
  events,
902
- jobs
1043
+ jobs,
1044
+ confirmations
903
1045
  };
904
- const router = apiRoutes(new Router(), ctx).add("GET", "/api/jobs/{jobId}", ({ params }) => {
1046
+ const router = apiRoutes(new Router(), ctx).add("POST", "/api/confirmations", ({ body }) => {
1047
+ const b = api_exports.ConfirmationRequest.safeParse(body ?? {});
1048
+ if (!b.success)
1049
+ throw badRequest(`Say which write and what for: { write: ${api_exports.CONFIRMED_WRITES.join(" | ")}, target }.`);
1050
+ if (!b.data.pageKey || !sameSecret(b.data.pageKey, pageKey))
1051
+ throw new HttpError(403, "Only the Atticus app asks for a confirmation", "A write to a shared system is a person's: they click it in the Atticus app, or run its command with --approve in a terminal. The session token alone (atticus ui --show-token) can't confirm one (ADR 0186).");
1052
+ return { status: 201, body: confirmations.issue(b.data.write, b.data.target) };
1053
+ }).add("GET", "/api/jobs/{jobId}", ({ params }) => {
905
1054
  const j = jobs.get(params.jobId);
906
1055
  if (!j)
907
1056
  throw notFound(`There is no job ${params.jobId}.`);
@@ -947,7 +1096,7 @@ async function startServer(o) {
947
1096
  throw new HttpError(403, "Requests must be addressed to this server");
948
1097
  if (!o.staticDir || req.method !== "GET" && req.method !== "HEAD")
949
1098
  throw new HttpError(404, "Not found", `Nothing is served at ${url.pathname}.`);
950
- const f = await staticFile(o.staticDir, url.pathname, token);
1099
+ const f = await staticFile(o.staticDir, url.pathname, token, pageKey);
951
1100
  const { "X-Frame-Options": deny, ...rest } = HARDENING;
952
1101
  res.writeHead(f.status, {
953
1102
  ...o.embed ? rest : { ...rest, "X-Frame-Options": deny },
@@ -976,14 +1125,18 @@ async function startServer(o) {
976
1125
  send(res, out.status, out.body);
977
1126
  done(out.status);
978
1127
  } catch (e) {
979
- const err = e instanceof HttpError ? e : new HttpError(500, "Something went wrong", e instanceof Error ? e.message : String(e));
1128
+ const err = e instanceof HttpError ? e : e instanceof FileChangedError ? new HttpError(409, "The file changed meanwhile", e.message) : (
1129
+ // The message stays in the log (onRequest gets the error): an fs error names the
1130
+ // metarepo's absolute path, which the page has no use for.
1131
+ new HttpError(500, "Something went wrong", "The app's log (.atticus/logs/atticus.log) has the details.")
1132
+ );
980
1133
  send(res, err.status, problem(err), "application/problem+json");
981
1134
  done(err.status, err.status >= 500 && e instanceof Error ? e : void 0);
982
1135
  }
983
1136
  });
984
1137
  server.on("upgrade", (req, sock) => {
985
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
986
1138
  try {
1139
+ const url = new URL(req.url ?? "/", "http://127.0.0.1");
987
1140
  if (url.pathname !== "/api/events")
988
1141
  throw new HttpError(404, "Not found");
989
1142
  guard(req, url, true);
@@ -999,9 +1152,9 @@ Connection: close\r
999
1152
  if (s)
1000
1153
  events.add(s);
1001
1154
  });
1002
- await new Promise((resolve, reject) => {
1155
+ await new Promise((resolve2, reject) => {
1003
1156
  server.once("error", reject);
1004
- server.listen(o.port ?? DEFAULT_PORT, host, () => resolve());
1157
+ server.listen(o.port ?? DEFAULT_PORT, host, () => resolve2());
1005
1158
  });
1006
1159
  port = server.address().port;
1007
1160
  const watcher = o.watch === false ? void 0 : watchMetarepo({ root: o.root, publish: (e) => events.publish(e) });
@@ -1009,219 +1162,29 @@ Connection: close\r
1009
1162
  url: `http://127.0.0.1:${port}`,
1010
1163
  port,
1011
1164
  token,
1165
+ pageKey,
1166
+ confirmations,
1012
1167
  events,
1013
1168
  jobs,
1014
1169
  person,
1015
1170
  get following() {
1016
1171
  return watcher?.following ?? [];
1017
1172
  },
1018
- close: () => new Promise((resolve) => {
1173
+ close: () => new Promise((resolve2) => {
1019
1174
  watcher?.close();
1020
1175
  events.closeAll();
1021
1176
  server.closeAllConnections?.();
1022
- server.close(() => resolve());
1177
+ server.close(() => resolve2());
1023
1178
  })
1024
1179
  };
1025
1180
  }
1026
1181
 
1027
- // packages/cli/dist/ui-api-cites.js
1028
- var import_yaml = __toESM(require_dist(), 1);
1029
- async function fingerprint(dirs) {
1030
- let count = 0;
1031
- let newest = 0;
1032
- const walk = async (d) => {
1033
- const entries = await readdir(d, { withFileTypes: true }).catch(() => []);
1034
- for (const e of entries) {
1035
- const p = join4(d, e.name);
1036
- if (e.isDirectory())
1037
- await walk(p);
1038
- else {
1039
- count++;
1040
- const s = await stat3(p).catch(() => void 0);
1041
- if (s && s.mtimeMs > newest)
1042
- newest = s.mtimeMs;
1043
- }
1044
- }
1045
- };
1046
- for (const d of dirs)
1047
- await walk(d);
1048
- return `${count}:${newest}`;
1049
- }
1050
- async function build(root) {
1051
- const index = /* @__PURE__ */ new Map();
1052
- const lineOf = (repo, path, line) => {
1053
- const files = index.get(repo) ?? /* @__PURE__ */ new Map();
1054
- index.set(repo, files);
1055
- const lines = files.get(path) ?? /* @__PURE__ */ new Map();
1056
- files.set(path, lines);
1057
- const l = lines.get(line) ?? { line, flows: [], records: [] };
1058
- lines.set(line, l);
1059
- return l;
1060
- };
1061
- for (const specRepo of await specRepos(root))
1062
- for (const f of (await readRepoSpec(root, specRepo, { cacheRoot: root })).flows) {
1063
- const parts = [
1064
- { step: 0, kind: f.trigger.kind, evidence: f.trigger.evidence },
1065
- ...f.steps.map((s, i) => ({
1066
- step: i + 1,
1067
- kind: s.kind,
1068
- ...s.confirmedBy ? { confirmedBy: s.confirmedBy } : {},
1069
- evidence: s.evidence
1070
- }))
1071
- ];
1072
- for (const part of parts)
1073
- for (const e of part.evidence) {
1074
- if (!e.path || e.line === void 0)
1075
- continue;
1076
- const l = lineOf(e.repo ?? specRepo, e.path, e.line);
1077
- if (l.flows.some((x) => x.flow === f.id && x.step === part.step))
1078
- continue;
1079
- l.flows.push({
1080
- repo: specRepo,
1081
- flow: f.id,
1082
- name: f.name,
1083
- step: part.step,
1084
- kind: part.kind,
1085
- ...part.confirmedBy ? { confirmedBy: part.confirmedBy } : {}
1086
- });
1087
- }
1088
- }
1089
- for (const r of await catalogRecords(root)) {
1090
- const name = r.name;
1091
- for (const e of r.evidence) {
1092
- if (!e.repo || !e.path || e.line === void 0)
1093
- continue;
1094
- const l = lineOf(e.repo, e.path, e.line);
1095
- if (l.records.some((x) => x.kind === r.kind && x.id === r.id))
1096
- continue;
1097
- l.records.push({
1098
- kind: r.kind,
1099
- id: r.id,
1100
- ...typeof name === "string" && name !== r.id ? { name } : {},
1101
- source: e.source
1102
- });
1103
- }
1104
- }
1105
- return index;
1106
- }
1107
- var DONE = /* @__PURE__ */ new Set(["released", "archived", "post-release-review"]);
1108
- async function inFlight(root) {
1109
- const out = /* @__PURE__ */ new Map();
1110
- const dir = changesDirOf(root);
1111
- for (const e of await readdir(dir, { withFileTypes: true }).catch(() => [])) {
1112
- if (!e.isDirectory() || e.name === "archive")
1113
- continue;
1114
- const yaml = await readFile3(join4(dir, e.name, "change.yaml"), "utf8").catch(() => "");
1115
- const state = (() => {
1116
- try {
1117
- return (0, import_yaml.parse)(yaml)?.state;
1118
- } catch {
1119
- return void 0;
1120
- }
1121
- })();
1122
- if (!yaml || typeof state === "string" && DONE.has(state))
1123
- continue;
1124
- for (const f of await readdir(join4(dir, e.name, "target-flows")).catch(() => []))
1125
- if (f.endsWith(".yaml")) {
1126
- const flow = f.slice(0, -".yaml".length);
1127
- out.set(flow, [...out.get(flow) ?? [], e.name]);
1128
- }
1129
- }
1130
- return out;
1131
- }
1132
- async function citeList(root, index, repo, path) {
1133
- const lines = [...index.get(repo)?.get(path)?.values() ?? []].sort((a, b) => a.line - b.line);
1134
- const flying = await inFlight(root);
1135
- const shown = lines.map((l) => ({
1136
- ...l,
1137
- flows: [...l.flows].sort((a, b) => a.flow.localeCompare(b.flow) || a.step - b.step).map((f) => flying.get(f.flow)?.length ? { ...f, changes: flying.get(f.flow) } : f)
1138
- }));
1139
- return { repo, path, lines: shown };
1140
- }
1141
- function fileInRepo(root, file) {
1142
- const rel = relative2(root, file);
1143
- if (!rel || rel.startsWith("..") || isAbsolute(rel))
1144
- return void 0;
1145
- const parts = rel.split(sep3);
1146
- if (parts[0] !== "workspace")
1147
- return { path: parts.join("/") };
1148
- const at = parts[1] === ".worktrees" ? 3 : parts[1] === ".branches" ? 2 : 1;
1149
- const repo = parts[at];
1150
- const rest = parts.slice(parts[1] === ".branches" ? 4 : at + 1);
1151
- if (!repo || !rest.length || !RecordId.safeParse(repo).success)
1152
- return void 0;
1153
- return { repo, path: rest.join("/") };
1154
- }
1155
- async function citesCli(root, o, io) {
1156
- let repo = o.repo;
1157
- let path = o.path;
1158
- const index = await build(root);
1159
- if (o.file) {
1160
- const at = fileInRepo(root, o.file);
1161
- if (!at) {
1162
- io.err(`${o.file} isn't in this metarepo or a repo's checkout in its workspace.`);
1163
- return 1;
1164
- }
1165
- path = at.path;
1166
- repo = at.repo ?? [...index.keys()].find((r) => index.get(r).has(at.path)) ?? void 0;
1167
- if (!repo) {
1168
- if (o.json)
1169
- io.out(JSON.stringify({ repo: "", path, lines: [] }, null, 2));
1170
- else
1171
- io.out(`Nothing in the specs or the catalog cites ${path}.`);
1172
- return 0;
1173
- }
1174
- }
1175
- if (!repo || !path || !RecordId.safeParse(repo).success) {
1176
- io.err("Say which file: atticus cites --repo <repo> --path <its path in the repo>, or --file <path on disk>.");
1177
- return 2;
1178
- }
1179
- const v = await citeList(root, index, repo, path);
1180
- if (o.json) {
1181
- io.out(JSON.stringify(v, null, 2));
1182
- return 0;
1183
- }
1184
- if (!v.lines.length) {
1185
- io.out(`Nothing in the specs or the catalog cites ${repo}/${path}.`);
1186
- return 0;
1187
- }
1188
- for (const l of v.lines) {
1189
- const flows = l.flows.map((f) => `${f.name} (step ${f.step})${f.changes?.length ? `, changed by ${f.changes.join(", ")}` : ""}`);
1190
- const records = l.records.map((r) => `${r.kind} ${r.name ?? r.id}`);
1191
- io.out(`Line ${l.line}: ${[...flows, ...records].join("; ")}`);
1192
- }
1193
- return 0;
1194
- }
1195
- function uiCiteRoutes(r, ctx) {
1196
- const root = ctx.root;
1197
- let cached;
1198
- const indexNow = async () => {
1199
- const print = await fingerprint([specsDirOf(root), catalogDirOf(root)]);
1200
- if (cached?.print !== print)
1201
- cached = { print, index: build(root) };
1202
- return cached.index;
1203
- };
1204
- void indexNow().catch(() => void 0);
1205
- r.add("GET", "/api/cites", async ({ query }) => {
1206
- const repo = query.get("repo");
1207
- const path = query.get("path");
1208
- if (!repo || !RecordId.safeParse(repo).success)
1209
- throw badRequest("Say which repo: ?repo=<the repo's id>.");
1210
- if (!path)
1211
- throw badRequest("Say which file: ?path=<its path in the repo>.");
1212
- return { status: 200, body: await citeList(root, await indexNow(), repo, path) };
1213
- });
1214
- return r;
1215
- }
1216
-
1217
1182
  export {
1218
1183
  HttpError,
1219
1184
  badRequest,
1220
1185
  notFound,
1221
1186
  conflict,
1222
1187
  strParam,
1223
- startServer,
1224
- fileInRepo,
1225
- citesCli,
1226
- uiCiteRoutes
1188
+ requireConfirmation,
1189
+ startServer
1227
1190
  };