@maycombhq/atticus 2.0.0-beta.21 → 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 (280) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/{chunk-TJH2EUAZ.js → chunk-23XVSEV5.js} +20 -18
  3. package/dist/{chunk-BXBCMGIQ.js → chunk-24OXGB3P.js} +1 -1
  4. package/dist/{chunk-DCWN3HFV.js → chunk-24XLDU72.js} +4 -3
  5. package/dist/{chunk-Q46QDDMF.js → chunk-2F4CYZKJ.js} +14 -9
  6. package/dist/{chunk-75ASLHBT.js → chunk-2GF7OLF3.js} +17 -15
  7. package/dist/chunk-2IIMFOPM.js +41 -0
  8. package/dist/{chunk-JRVNXLZP.js → chunk-2LGRMVCA.js} +14 -12
  9. package/dist/{chunk-62DLJSLV.js → chunk-2MMCFP5C.js} +10 -8
  10. package/dist/{chunk-UF4UHCIG.js → chunk-2Q56PQPS.js} +6 -4
  11. package/dist/{chunk-5TDRBOAV.js → chunk-2Q5EDGEO.js} +7 -5
  12. package/dist/{chunk-NYOABJNK.js → chunk-2RLKFUUL.js} +26 -24
  13. package/dist/chunk-2SKB4O2E.js +59 -0
  14. package/dist/{chunk-GCS3FZOB.js → chunk-34S2WGOB.js} +13 -4
  15. package/dist/{chunk-7AB6OWTV.js → chunk-3NFFJL5D.js} +31 -25
  16. package/dist/{chunk-GC2VK3JT.js → chunk-3NWDLGG6.js} +28 -25
  17. package/dist/{chunk-FLVZFTLQ.js → chunk-3RM4UK6W.js} +20 -18
  18. package/dist/{chunk-CNU5Q2D5.js → chunk-42SIDKEU.js} +37 -29
  19. package/dist/{chunk-K6JB6XTX.js → chunk-4EURQWQD.js} +20 -15
  20. package/dist/{chunk-OMPENNWY.js → chunk-4U276ICE.js} +1 -1
  21. package/dist/{chunk-JAABT3DA.js → chunk-53T4O55J.js} +4 -3
  22. package/dist/{chunk-YTTNTQOX.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-KYZMRSPS.js → chunk-5NMKONLP.js} +5 -3
  26. package/dist/{chunk-5CMPVC3N.js → chunk-5SJZW52K.js} +25 -23
  27. package/dist/{chunk-YAH5IQAL.js → chunk-63YRMR6J.js} +6 -5
  28. package/dist/{chunk-GUYL7RMK.js → chunk-66PPNOON.js} +27 -25
  29. package/dist/chunk-6H3Z5JHH.js +64 -0
  30. package/dist/{chunk-Y6K3CJBU.js → chunk-6MUGR4LS.js} +75 -27
  31. package/dist/{chunk-DDJPM5YX.js → chunk-6OJQOPUN.js} +5 -3
  32. package/dist/{chunk-2V2ZPQQU.js → chunk-6PPOWY5E.js} +9 -7
  33. package/dist/{chunk-YO2PKTXT.js → chunk-6ZGLAACW.js} +5 -3
  34. package/dist/{chunk-LIJJCBQI.js → chunk-6ZJ5A7AF.js} +15 -16
  35. package/dist/{chunk-64AADMTW.js → chunk-745DAZ4L.js} +50 -12
  36. package/dist/{chunk-VYOCPTUB.js → chunk-7ASNL4Q4.js} +17 -15
  37. package/dist/{chunk-XEQCQO66.js → chunk-7BR7IPOH.js} +10 -8
  38. package/dist/{chunk-X2CUXTWU.js → chunk-7DOR27HL.js} +6 -6
  39. package/dist/{chunk-G6IQYM25.js → chunk-7FTTA3HD.js} +8 -6
  40. package/dist/{chunk-FAJDKNSD.js → chunk-7GJS6DNX.js} +8 -3
  41. package/dist/{chunk-4KNOJC6J.js → chunk-7IGKHZ4Z.js} +55 -13
  42. package/dist/{chunk-3WON4G3M.js → chunk-7IOWA5D5.js} +11 -6
  43. package/dist/{chunk-PNQLCRSS.js → chunk-7JITZFJC.js} +7 -5
  44. package/dist/{chunk-2D7PWSOK.js → chunk-7MJSQTL5.js} +22 -20
  45. package/dist/{chunk-AE4P57KK.js → chunk-7UOMVMFG.js} +17 -15
  46. package/dist/{chunk-GK4PYVEC.js → chunk-AFWUDXEM.js} +10 -8
  47. package/dist/chunk-AFZ3QA6W.js +47 -0
  48. package/dist/{chunk-7FUIVIBG.js → chunk-AJQ72EBM.js} +13 -8
  49. package/dist/{chunk-QOOEYDNJ.js → chunk-AJYXNTNZ.js} +6 -6
  50. package/dist/chunk-AVTBS4OW.js +49 -0
  51. package/dist/{chunk-WFU77T3A.js → chunk-BDKC6H5P.js} +5 -5
  52. package/dist/{chunk-3AQ2R5NL.js → chunk-BEVTIBRH.js} +9 -7
  53. package/dist/{chunk-J5AAZ6OJ.js → chunk-BHT7QK4G.js} +5 -4
  54. package/dist/{chunk-UFE36WJH.js → chunk-BIGDQDHD.js} +6 -4
  55. package/dist/{chunk-WNTIOBOG.js → chunk-BO4KX37X.js} +20 -18
  56. package/dist/{chunk-455SYIIE.js → chunk-BPK5P77O.js} +5 -3
  57. package/dist/{chunk-OZJ3JLYI.js → chunk-BQ4SQQC6.js} +10 -9
  58. package/dist/chunk-BQGDB6ZL.js +7342 -0
  59. package/dist/{chunk-EZIN5E5B.js → chunk-BTGPE6CR.js} +11 -9
  60. package/dist/{chunk-265LWMOA.js → chunk-BTY3HZBO.js} +18 -16
  61. package/dist/{chunk-TW3KOSQK.js → chunk-BXYMYEJ4.js} +7 -6
  62. package/dist/{chunk-HK3VOHIE.js → chunk-C3RY6KU6.js} +119 -18
  63. package/dist/chunk-C4R4JLHE.js +40 -0
  64. package/dist/{chunk-Z3QFH7YG.js → chunk-CADWLE2T.js} +5 -4
  65. package/dist/{chunk-J2O4LFVI.js → chunk-CBGGOQWU.js} +6 -4
  66. package/dist/chunk-CMDXGQTS.js +47 -0
  67. package/dist/{chunk-TWQRPM76.js → chunk-CQDGOPGH.js} +23 -16
  68. package/dist/{chunk-5PV7S2ZP.js → chunk-CX4RZ2KS.js} +4 -3
  69. package/dist/{chunk-JYMIB5XY.js → chunk-CXJ6FUKN.js} +164 -44
  70. package/dist/{chunk-D57MFJPP.js → chunk-D73UEXYW.js} +3 -3
  71. package/dist/{chunk-UYLBRRFK.js → chunk-DCZWQLYT.js} +125 -26
  72. package/dist/chunk-DLOBCJL6.js +48 -0
  73. package/dist/{chunk-IFHDV6KQ.js → chunk-DOBQKHIF.js} +23 -23
  74. package/dist/{chunk-QJCJOMW3.js → chunk-E3ISYXO3.js} +19 -21
  75. package/dist/{chunk-VAMHOHUU.js → chunk-E6ZIEVOI.js} +16 -13
  76. package/dist/{chunk-EFCQSMXB.js → chunk-EBL2R3YG.js} +10 -4
  77. package/dist/{chunk-HGHRSF3E.js → chunk-EGQRREQH.js} +25 -17
  78. package/dist/{chunk-3J5I7ZOU.js → chunk-EHA7RMZ3.js} +4 -4
  79. package/dist/{chunk-7CZHUZBL.js → chunk-EIPTLPFC.js} +38 -27
  80. package/dist/{chunk-UZACEG2C.js → chunk-EMRIQUND.js} +17 -15
  81. package/dist/{chunk-RALY3E5U.js → chunk-EPCJQQWD.js} +6 -4
  82. package/dist/{chunk-VUVGX5L2.js → chunk-F3P7N7SF.js} +1 -1
  83. package/dist/{chunk-RA33EYS4.js → chunk-FFLNS6VP.js} +19 -17
  84. package/dist/{chunk-OPQZISG3.js → chunk-FFTRTL6R.js} +5 -4
  85. package/dist/{chunk-DUPZPDCJ.js → chunk-FPJPLKDW.js} +18 -14
  86. package/dist/{chunk-2HH3UCZM.js → chunk-FSMSFDLD.js} +5 -4
  87. package/dist/{chunk-AHW3RY3X.js → chunk-FUJM6RTF.js} +8 -7
  88. package/dist/{chunk-2UCRFXFZ.js → chunk-FZOJFH7Q.js} +13 -11
  89. package/dist/{chunk-BVWWPBKD.js → chunk-G6X77UJZ.js} +20 -18
  90. package/dist/{chunk-BPPU3PW7.js → chunk-GCWRWSU7.js} +10 -4
  91. package/dist/chunk-GIW4ZVDB.js +39 -0
  92. package/dist/{chunk-FY3QIRTL.js → chunk-GUX3PTYM.js} +3 -3
  93. package/dist/{chunk-BA2HUMDN.js → chunk-GZY6RUZ6.js} +2 -2
  94. package/dist/chunk-H4VO6WG3.js +10 -0
  95. package/dist/{chunk-UEVZZZU2.js → chunk-H5HBGNXU.js} +5 -4
  96. package/dist/{chunk-GS76RXQE.js → chunk-H7KM7LZE.js} +15 -12
  97. package/dist/{chunk-I2A3Z5AK.js → chunk-HNM2YQT2.js} +4 -4
  98. package/dist/{chunk-3UTYPHN3.js → chunk-HYU5VLGA.js} +1 -1
  99. package/dist/{chunk-HSZMPH5T.js → chunk-IDKCWSM5.js} +225 -50
  100. package/dist/{chunk-BXZ4PKIT.js → chunk-IFKEI4SA.js} +15 -11
  101. package/dist/{chunk-XG4WJHLQ.js → chunk-IGOE6KPG.js} +49 -20
  102. package/dist/{chunk-GNWAOVFQ.js → chunk-IH2XURVQ.js} +5 -5
  103. package/dist/{chunk-YIGBJNH4.js → chunk-INQHESFB.js} +5 -4
  104. package/dist/chunk-IP74LCOQ.js +57 -0
  105. package/dist/chunk-IPHHDDC6.js +45 -0
  106. package/dist/{chunk-5WERBKLE.js → chunk-ISUAAMGS.js} +42 -221
  107. package/dist/{chunk-7FHNFCHK.js → chunk-IUPG3UKI.js} +154 -368
  108. package/dist/{chunk-HWD4JPU7.js → chunk-IVBOQAGB.js} +4 -2
  109. package/dist/{chunk-4SLBCEPD.js → chunk-J2JAKCIW.js} +88 -57
  110. package/dist/{chunk-G5YJBNDZ.js → chunk-J3IOLXWM.js} +8 -6
  111. package/dist/{chunk-FQ6WH6PB.js → chunk-JA5FI3QV.js} +6 -4
  112. package/dist/chunk-JAVI7JSP.js +49 -0
  113. package/dist/{chunk-ZFQMMU5Y.js → chunk-JB5LINEM.js} +6 -2
  114. package/dist/{chunk-LQH4P45K.js → chunk-JENSEMXF.js} +1 -1
  115. package/dist/{chunk-M6D2U3YM.js → chunk-JJF6HALY.js} +4 -3
  116. package/dist/chunk-JLUCKAEL.js +38 -0
  117. package/dist/{chunk-M4H2UG4R.js → chunk-JRBFANFE.js} +19 -16
  118. package/dist/{chunk-YZDZOEV4.js → chunk-KDNTAPLX.js} +3 -3
  119. package/dist/{chunk-IFFRGC3N.js → chunk-KFAVQZSX.js} +14 -12
  120. package/dist/chunk-KJXD4PNL.js +50 -0
  121. package/dist/chunk-KN5BXMWN.js +44 -0
  122. package/dist/{chunk-HXXP2NTE.js → chunk-KQGURXFU.js} +9 -7
  123. package/dist/{chunk-PQH56YF6.js → chunk-KXITGYLF.js} +6 -4
  124. package/dist/{chunk-MMZUN7ZO.js → chunk-L27SV425.js} +22 -20
  125. package/dist/{chunk-XQ3YZ4QW.js → chunk-LDLL7LB3.js} +24 -22
  126. package/dist/{chunk-6DQYZU2W.js → chunk-LFGTYX5U.js} +15 -15
  127. package/dist/{chunk-4D62IZII.js → chunk-LGBMTVNT.js} +7 -5
  128. package/dist/{chunk-YKTE2RU3.js → chunk-LGFL54FP.js} +3 -2
  129. package/dist/{chunk-GDZB57IU.js → chunk-LJXMYKZJ.js} +7 -5
  130. package/dist/{chunk-YJ3TBOTK.js → chunk-LKOR5UET.js} +29 -26
  131. package/dist/{chunk-WIWTJMMR.js → chunk-LNBQOP7D.js} +23 -21
  132. package/dist/{chunk-TGVVUKTG.js → chunk-LO6P2VYG.js} +2 -2
  133. package/dist/{chunk-HE3HRDNZ.js → chunk-LQJPN536.js} +2 -2
  134. package/dist/{chunk-PRW3HXM3.js → chunk-LYBNHMVZ.js} +29 -5
  135. package/dist/{chunk-75ZOZFGH.js → chunk-LZ7NUC62.js} +20 -18
  136. package/dist/chunk-M32BLWDH.js +37 -0
  137. package/dist/{chunk-QKMRFNMA.js → chunk-M3NANSDZ.js} +17 -15
  138. package/dist/chunk-MFHL5URL.js +31 -0
  139. package/dist/{chunk-TYD6I4CZ.js → chunk-MFR5OPBD.js} +6 -6
  140. package/dist/{chunk-LIRVU3HW.js → chunk-MG4ZL5RW.js} +32 -20
  141. package/dist/{chunk-ICHDSWEY.js → chunk-MO6P2JZH.js} +10 -8
  142. package/dist/{chunk-3LZ6P5EP.js → chunk-MUWDB4R4.js} +1 -1
  143. package/dist/{chunk-E57AOFYN.js → chunk-MZCGSXVR.js} +15 -13
  144. package/dist/{chunk-77O633L5.js → chunk-N3XIYPU3.js} +14 -12
  145. package/dist/{chunk-CG6CULP6.js → chunk-NDCF4R6S.js} +7 -5
  146. package/dist/{chunk-JS6WMC3J.js → chunk-NR2UJWOC.js} +10 -8
  147. package/dist/chunk-NXJ5URP6.js +51 -0
  148. package/dist/{chunk-NTAVOWYD.js → chunk-NY2XSR5K.js} +20 -18
  149. package/dist/{chunk-PUEWDYGP.js → chunk-O45HFTFS.js} +3 -2
  150. package/dist/{chunk-URIKUID7.js → chunk-O4GXGGBX.js} +14 -12
  151. package/dist/{chunk-C7CEK3KW.js → chunk-O5PXQR67.js} +7 -5
  152. package/dist/{chunk-E2VXBSIR.js → chunk-O66DM6DJ.js} +6 -4
  153. package/dist/{chunk-P2VBXX7N.js → chunk-O7FDLW7L.js} +11 -9
  154. package/dist/{chunk-COYN3UAN.js → chunk-O7XLYEFA.js} +59 -22
  155. package/dist/{chunk-5QUOPNLN.js → chunk-OHNCWBKF.js} +4 -4
  156. package/dist/{chunk-AZDITBCT.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-L4CESDPB.js → chunk-OUBGGKDU.js} +1 -1
  161. package/dist/{chunk-4FOAYLI4.js → chunk-OWNCM4ZN.js} +9 -7
  162. package/dist/{chunk-4B6BT75O.js → chunk-P2V7QW4D.js} +81 -24
  163. package/dist/{chunk-QHJJMZLX.js → chunk-P32RUW3B.js} +167 -92
  164. package/dist/{chunk-F6H2RJ3N.js → chunk-PAQ2AS5E.js} +1 -1
  165. package/dist/{chunk-ZLS6PU2O.js → chunk-PBPBMP2B.js} +4 -3
  166. package/dist/{chunk-ZOSD4FXV.js → chunk-PJSJPMJI.js} +3 -3
  167. package/dist/{chunk-XOL3GFW2.js → chunk-PKBHS4AA.js} +68 -31
  168. package/dist/{chunk-ZZFHLRQW.js → chunk-PMUAJGLI.js} +18 -16
  169. package/dist/{chunk-SH27FYPF.js → chunk-PPD7HTDP.js} +20 -18
  170. package/dist/chunk-PSOFBQWB.js +42 -0
  171. package/dist/{chunk-PAINMSID.js → chunk-Q2TECDIT.js} +987 -7619
  172. package/dist/{chunk-LU4MQVAL.js → chunk-Q4K5WB2W.js} +11 -10
  173. package/dist/{chunk-ECLXZWAG.js → chunk-Q6DFNVRJ.js} +14 -12
  174. package/dist/chunk-QA4O2GGC.js +265 -0
  175. package/dist/{chunk-4WXRPQDE.js → chunk-QAXW2N3B.js} +182 -33
  176. package/dist/{chunk-WCEF7H6L.js → chunk-QFWA2DPH.js} +8 -5
  177. package/dist/{chunk-CPK7QSBG.js → chunk-QKUJMING.js} +8 -6
  178. package/dist/{chunk-LEBR5NHW.js → chunk-R44CYFPV.js} +18 -15
  179. package/dist/{chunk-BEPCKDCP.js → chunk-R7NYHMUU.js} +153 -84
  180. package/dist/{chunk-G6X4YL4D.js → chunk-REWWDVQB.js} +5 -4
  181. package/dist/{chunk-LN77DXBM.js → chunk-RGERPOIV.js} +10 -10
  182. package/dist/{chunk-UDXWIPCB.js → chunk-RLDGWLQ7.js} +9 -7
  183. package/dist/chunk-RUGXBPWI.js +384 -0
  184. package/dist/{chunk-FYBF5MB2.js → chunk-RXPJMEOW.js} +13 -11
  185. package/dist/{chunk-K332XW7K.js → chunk-S4PMJU6H.js} +20 -9
  186. package/dist/{chunk-THN26IEF.js → chunk-S7FCV7S5.js} +4 -1
  187. package/dist/{chunk-OV57AHCG.js → chunk-SDKLKB6I.js} +26 -24
  188. package/dist/{chunk-O4IKAIZ2.js → chunk-SFSPGFCV.js} +28 -22
  189. package/dist/{chunk-TQ4TG57V.js → chunk-SFUP7TTO.js} +4 -4
  190. package/dist/{chunk-YBOVNMHC.js → chunk-SLXZOMA6.js} +29 -16
  191. package/dist/{chunk-LWDNKE4X.js → chunk-SQV37XO2.js} +6 -6
  192. package/dist/{chunk-67BP7HXL.js → chunk-SU74NDMQ.js} +19 -17
  193. package/dist/{chunk-JKIGL3XQ.js → chunk-SYV5LHML.js} +36 -33
  194. package/dist/chunk-T4YPZIQN.js +36 -0
  195. package/dist/{chunk-GX74YWR7.js → chunk-T6DQR5TV.js} +16 -14
  196. package/dist/{chunk-LNWEWYCM.js → chunk-THDMSZ3R.js} +345 -253
  197. package/dist/{chunk-NCB6656Z.js → chunk-TNR75OXT.js} +7 -7
  198. package/dist/{chunk-ODMBPDDV.js → chunk-TUULXQRW.js} +124 -2
  199. package/dist/{chunk-MD7KUEJ3.js → chunk-TYQBFTBR.js} +9 -7
  200. package/dist/chunk-U76OWS3Q.js +49 -0
  201. package/dist/{chunk-GSGIZ2OO.js → chunk-UCROWG2D.js} +27 -24
  202. package/dist/{chunk-PTQ3ZALZ.js → chunk-UF4AZOZB.js} +14 -12
  203. package/dist/{chunk-QE527XRY.js → chunk-UF4GLFBX.js} +26 -23
  204. package/dist/{chunk-YWAKDNMH.js → chunk-UGUP3ZM6.js} +70 -19
  205. package/dist/{chunk-3G6S7LAA.js → chunk-UNAGJYET.js} +14 -12
  206. package/dist/{chunk-EDZ45WIR.js → chunk-UOR2DTHH.js} +16 -14
  207. package/dist/{chunk-42EPP7OB.js → chunk-UPOY4YSQ.js} +14 -12
  208. package/dist/{chunk-API5TOUB.js → chunk-UPS2DGFC.js} +1 -1
  209. package/dist/{chunk-D2WSW4GU.js → chunk-UUU4CLJG.js} +4 -2
  210. package/dist/{chunk-ZKYRDV7A.js → chunk-UWMJKX5U.js} +14 -12
  211. package/dist/{chunk-HS4BGB4G.js → chunk-UWOJLHFT.js} +25 -23
  212. package/dist/{chunk-OKUB6RJA.js → chunk-VBTP56CE.js} +8 -6
  213. package/dist/{chunk-3SSTNB4E.js → chunk-VCTWPLAO.js} +34 -14
  214. package/dist/{chunk-YF5DZCPN.js → chunk-VNU26RCO.js} +37 -34
  215. package/dist/{chunk-AOCWFA7T.js → chunk-VTZMAJ3W.js} +8 -8
  216. package/dist/{chunk-ZQLRCA2V.js → chunk-VW62D6QE.js} +10 -8
  217. package/dist/{chunk-WAZEXEJH.js → chunk-VY72R2XZ.js} +45 -2
  218. package/dist/{chunk-WEOMJHPV.js → chunk-VZALIKIF.js} +18 -15
  219. package/dist/{chunk-TSM6T6GQ.js → chunk-W62H2XSO.js} +25 -23
  220. package/dist/{chunk-BC6KKZ67.js → chunk-W7VWI2YH.js} +9 -6
  221. package/dist/{chunk-LO3BLMVG.js → chunk-WERM6KPJ.js} +7 -4
  222. package/dist/{chunk-36RY7ZXM.js → chunk-WF7B67YE.js} +88 -26
  223. package/dist/{chunk-TQTRWENN.js → chunk-WG5U3F5V.js} +14 -12
  224. package/dist/{chunk-NRQ65LTQ.js → chunk-WJF2CS6M.js} +6 -5
  225. package/dist/{chunk-FVMPFCDS.js → chunk-WKUJ3KPV.js} +4 -4
  226. package/dist/{chunk-BA3U7ALS.js → chunk-WMTRHUI5.js} +26 -22
  227. package/dist/chunk-WNKPRSGI.js +36 -0
  228. package/dist/{chunk-GIFMBCTW.js → chunk-WXFLMQSR.js} +10 -8
  229. package/dist/{chunk-JYTIHTIK.js → chunk-X3WY6MN3.js} +4 -4
  230. package/dist/{chunk-S2RY3BOD.js → chunk-X4CXA2IL.js} +31 -21
  231. package/dist/{chunk-26Z7OGQW.js → chunk-X5F3Q5LV.js} +60 -30
  232. package/dist/{chunk-4CLK2RJO.js → chunk-XD75VZIH.js} +6 -4
  233. package/dist/{chunk-KDAHXQIE.js → chunk-XERYFDB5.js} +37 -34
  234. package/dist/{chunk-U3NBK4EU.js → chunk-XI2LCCYQ.js} +8 -8
  235. package/dist/{chunk-MZGRDONP.js → chunk-Y2EQNWKV.js} +55 -38
  236. package/dist/{chunk-A2G72UI4.js → chunk-YHCMZC2J.js} +7 -7
  237. package/dist/{chunk-4TKVU2I2.js → chunk-YYY3AZFE.js} +2 -2
  238. package/dist/{chunk-2HTEMYTB.js → chunk-Z5IA3WDR.js} +17 -15
  239. package/dist/{chunk-FRHD22WM.js → chunk-ZFFYNRIO.js} +25 -23
  240. package/dist/{chunk-6EXDI5GI.js → chunk-ZFL7NY4F.js} +43 -40
  241. package/dist/{chunk-4PYC2UGC.js → chunk-ZGULQAPZ.js} +7 -4
  242. package/dist/{chunk-4SKZDI62.js → chunk-ZIUFM5HT.js} +3 -1
  243. package/dist/{chunk-CNPY4NTZ.js → chunk-ZJFRMSJT.js} +15 -13
  244. package/dist/{chunk-Q26LDIUV.js → chunk-ZJXLNDH4.js} +18 -15
  245. package/dist/{chunk-LPV6T362.js → chunk-ZQ3ON2VQ.js} +8 -6
  246. package/dist/{chunk-ZX7235KR.js → chunk-ZQ7SKESZ.js} +44 -383
  247. package/dist/{chunk-7QPCGTPS.js → chunk-ZQXZ2SES.js} +24 -21
  248. package/dist/{chunk-4CYTJ5TZ.js → chunk-ZX57KSEQ.js} +4 -3
  249. package/dist/{chunk-37WE3LS2.js → chunk-ZZK56BLP.js} +5 -3
  250. package/dist/files.json +533 -509
  251. package/dist/packages/sdk/npm/index.js +448 -67
  252. package/dist/packages/ui/dist/assets/{elk-api-CowTnhEJ.js → elk-api-CIf-0gz5.js} +2 -2
  253. package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +47 -0
  254. package/dist/packages/ui/dist/index.html +2 -1
  255. package/package.json +4 -4
  256. package/dist/chunk-26WBY34Y.js +0 -37
  257. package/dist/chunk-3TD6S4TC.js +0 -49
  258. package/dist/chunk-5G7ILBUG.js +0 -66
  259. package/dist/chunk-6FNAKCET.js +0 -38
  260. package/dist/chunk-AM6FP6JW.js +0 -43
  261. package/dist/chunk-CFH3QH26.js +0 -29
  262. package/dist/chunk-CLD4RVTA.js +0 -45
  263. package/dist/chunk-D5KV5PSK.js +0 -45
  264. package/dist/chunk-D5MASS4I.js +0 -48
  265. package/dist/chunk-DN4A2Q2O.js +0 -57
  266. package/dist/chunk-FGAGWYZB.js +0 -47
  267. package/dist/chunk-JITJP64K.js +0 -34
  268. package/dist/chunk-JRXHON4E.js +0 -41
  269. package/dist/chunk-JU4QNJSR.js +0 -62
  270. package/dist/chunk-N3RUGTGV.js +0 -39
  271. package/dist/chunk-PKJAV25S.js +0 -43
  272. package/dist/chunk-PRTBPXYA.js +0 -50
  273. package/dist/chunk-PRZ7KMWL.js +0 -42
  274. package/dist/chunk-QSIDVFB7.js +0 -45
  275. package/dist/chunk-SB5GRUFM.js +0 -54
  276. package/dist/chunk-T74WQQGS.js +0 -40
  277. package/dist/chunk-X7EMBM5X.js +0 -34
  278. package/dist/chunk-Z6VLC5X4.js +0 -36
  279. package/dist/chunk-ZPDDEVQX.js +0 -47
  280. package/dist/packages/ui/dist/assets/index-z2wv0d5d.js +0 -47
@@ -1667,13 +1667,41 @@ function normalizePath(input) {
1667
1667
  const trimmed = input.trim();
1668
1668
  if (trimmed === "")
1669
1669
  return "";
1670
- const withoutQuery = trimmed.split(/[?#]/, 1)[0] ?? "";
1670
+ const withoutQuery = stripParamConstraints(trimmed).split(/[?#]/, 1)[0] ?? "";
1671
1671
  const isPath = withoutQuery.startsWith("/") || withoutQuery.includes("/");
1672
1672
  if (!isPath)
1673
1673
  return withoutQuery;
1674
1674
  const segments = withoutQuery.split("/").filter((s) => s.length > 0).map((s) => /^(\{[^}]*\}|:[^/]+|<[^>]+>|\$\{[^}]*\})$/.test(s) ? "{}" : s);
1675
1675
  return "/" + segments.join("/");
1676
1676
  }
1677
+ function stripParamConstraints(path) {
1678
+ let out = "";
1679
+ let i = 0;
1680
+ while (i < path.length) {
1681
+ const ch = path[i];
1682
+ if (ch !== "{") {
1683
+ out += ch;
1684
+ i++;
1685
+ continue;
1686
+ }
1687
+ let depth = 0;
1688
+ let j = i;
1689
+ for (; j < path.length; j++) {
1690
+ if (path[j] === "{")
1691
+ depth++;
1692
+ else if (path[j] === "}" && --depth === 0)
1693
+ break;
1694
+ }
1695
+ if (j >= path.length) {
1696
+ out += path.slice(i);
1697
+ break;
1698
+ }
1699
+ const inner = path.slice(i + 1, j);
1700
+ out += "{" + (/^[^:?=]*/.exec(inner)?.[0] ?? "") + "}";
1701
+ i = j + 1;
1702
+ }
1703
+ return out;
1704
+ }
1677
1705
  function interfaceId(from, to, method, path) {
1678
1706
  const key = [from, to, (method ?? "").toUpperCase(), normalizePath(path)].join("|");
1679
1707
  return "if-" + createHash("sha256").update(key, "utf8").digest("hex").slice(0, 16);
@@ -1769,6 +1797,17 @@ function flowIssues(f) {
1769
1797
  return issues;
1770
1798
  }
1771
1799
  function parseRecord(input) {
1800
+ const v = input?.schemaVersion;
1801
+ if (typeof v === "number" && Number.isInteger(v) && v > SCHEMA_VERSION)
1802
+ return {
1803
+ ok: false,
1804
+ issues: [
1805
+ {
1806
+ path: "schemaVersion",
1807
+ message: `written by a newer Atticus (record version ${v}); install it to read this record`
1808
+ }
1809
+ ]
1810
+ };
1772
1811
  const result = CatalogRecord.safeParse(input);
1773
1812
  if (!result.success) {
1774
1813
  return {
@@ -2771,6 +2810,27 @@ var IntegrationPattern = z11.strictObject({
2771
2810
  version: Semver,
2772
2811
  status: z11.enum(["confirmed", "to-review", "deprecated"])
2773
2812
  });
2813
+ function gitRefProblem(ref2) {
2814
+ if (!ref2)
2815
+ return "it is empty";
2816
+ if (ref2.startsWith("-"))
2817
+ return "it starts with -";
2818
+ if (/[\x00-\x20\x7f]/.test(ref2))
2819
+ return "it has a space or a control character";
2820
+ if (/[~^:?*[\\]/.test(ref2))
2821
+ return "it has one of ~ ^ : ? * [ \\";
2822
+ if (ref2.includes(".."))
2823
+ return "it has ..";
2824
+ if (ref2.includes("@{") || ref2 === "@")
2825
+ return "it is @ or has @{";
2826
+ if (ref2.startsWith("/") || ref2.endsWith("/") || ref2.includes("//"))
2827
+ return "it starts or ends with /, or has //";
2828
+ if (ref2.endsWith("."))
2829
+ return "it ends with .";
2830
+ if (ref2.split("/").some((c) => c.startsWith(".") || c.endsWith(".lock")))
2831
+ return "a part of it starts with . or ends with .lock";
2832
+ return void 0;
2833
+ }
2774
2834
  var RelPath = z11.string().min(1).refine((p2) => !p2.startsWith("/") && !/^[A-Za-z]:/.test(p2) && !p2.includes("\\") && !p2.split("/").includes(".."), "a relative path inside the metarepo");
2775
2835
  var SourceTags = z11.strictObject({
2776
2836
  kinds: z11.array(RecordId).default([]),
@@ -2849,7 +2909,11 @@ var Sources = z11.strictObject({
2849
2909
  /** What the source is about (ADR 0083), to guide the knowledge scan and filter items. */
2850
2910
  tags: SourceTags.optional(),
2851
2911
  /** A git wiki's branch or tag; default its default branch. A name git takes as a ref, never as an option. */
2852
- ref: z11.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._/-]*$/, "a branch or tag name").optional(),
2912
+ ref: z11.string().max(200).superRefine((r, ctx) => {
2913
+ const why = gitRefProblem(r);
2914
+ if (why)
2915
+ ctx.addIssue({ code: "custom", message: `a branch or tag name: ${why}` });
2916
+ }).optional(),
2853
2917
  /** The folder of a git wiki its pages are in; default the whole repository. */
2854
2918
  path: RelPath.optional(),
2855
2919
  /** A git wiki is cloned into local state (clone), or kept as a submodule of the metarepo under knowledge/repos/. */
@@ -2941,10 +3005,11 @@ var AdapterSettings = z11.record(z11.string(), z11.union([z11.string(), z11.numb
2941
3005
  }
2942
3006
  }
2943
3007
  });
2944
- var adapter = (types, o = {}) => z11.strictObject({
2945
- type: z11.enum([...types, "mock", ...o.manual === false ? [] : ["manual"]]),
2946
- settings: AdapterSettings.default({})
2947
- });
3008
+ var adapter = (types, o = {}) => {
3009
+ const type = z11.enum([...types, "mock", ...o.manual === false ? [] : ["manual"]]);
3010
+ const full = z11.strictObject({ type, settings: AdapterSettings.default({}) });
3011
+ return z11.union([type.transform((t) => ({ type: t, settings: {} })), full]);
3012
+ };
2948
3013
  var BuildEngine = z11.enum(["speckit", "atticus"]);
2949
3014
  var Autonomy = z11.enum(["plan-only", "draft", "draft-and-pr"]);
2950
3015
  var RetrievalSettings = z11.strictObject({
@@ -3336,6 +3401,9 @@ var Profile = z11.strictObject({
3336
3401
  });
3337
3402
  });
3338
3403
 
3404
+ // packages/core/dist/metarepo.js
3405
+ var LAYOUT_PATH = Sources.shape.layout.unwrap().shape.catalog.unwrap().optional();
3406
+
3339
3407
  // packages/core/dist/roles-migrate.js
3340
3408
  import { isMap, parseDocument } from "yaml";
3341
3409
 
@@ -3745,6 +3813,13 @@ var AuditFile = z17.strictObject({
3745
3813
  items: z17.array(AuditItem)
3746
3814
  });
3747
3815
 
3816
+ // packages/core/dist/cite.js
3817
+ var SECRET_WORDS = "(?:password|passwd|pwd|secret|token|api[-_]?key|access[-_]?key|private[-_]?key|credentials?)";
3818
+ var KEY_LITERAL = new RegExp(`((?:^|[^A-Za-z0-9_.$-])[A-Za-z0-9_.$-]*?${SECRET_WORDS}["'\`]?\\]?(?:\\s*:\\s*[A-Za-z_][\\w.<>?\\[\\]]*(?=\\s*=))?\\s*(?::=|=>|=(?!=)|:(?!:))\\s*)(["'\`])((?:(?!\\2)[^\\\\]|\\\\.)+)\\2`, "i");
3819
+ var SETTER_LITERAL = new RegExp(`(\\b(?:set|with)[A-Za-z0-9_]*?${SECRET_WORDS}\\s*\\(\\s*)(["'\`])((?:(?!\\2)[^\\\\]|\\\\.)+)\\2`, "i");
3820
+ var KEY_BARE = new RegExp(`((?:\\bexport\\s+|--|[?&;])[A-Za-z0-9_.-]*?${SECRET_WORDS}\\s*=\\s*)([^\\s&;"'\`]+)`, "gi");
3821
+ var SECRET_IDENT = new RegExp(`[A-Za-z0-9_]*${SECRET_WORDS}[A-Za-z0-9_]*`, "i");
3822
+
3748
3823
  // packages/core/dist/json-schema.js
3749
3824
  import { z as z27 } from "zod";
3750
3825
 
@@ -7205,13 +7280,42 @@ var ProposePlanView = z30.object({
7205
7280
  */
7206
7281
  applyFirst: z30.array(z30.string()).optional()
7207
7282
  });
7283
+ var CONFIRMED_WRITES = [
7284
+ "handoff",
7285
+ "release-prs",
7286
+ "merge",
7287
+ "task-pr",
7288
+ "digest-send",
7289
+ "propose",
7290
+ "step-run",
7291
+ "ai-model",
7292
+ "ai-test"
7293
+ ];
7294
+ var ConfirmedWrite = z30.enum(CONFIRMED_WRITES);
7295
+ var Confirmation = z30.string().regex(/^[A-Za-z0-9_-]{16,128}$/, "a confirmation");
7296
+ var ConfirmationRequest = z30.strictObject({
7297
+ write: ConfirmedWrite,
7298
+ /** What the write is for: the change, `<change>/<task>`, the step, the scope, `me` or `model`. */
7299
+ target: z30.string().min(1).max(400),
7300
+ /** The page's own key, from its <meta name="atticus-page-key">; never printed. */
7301
+ pageKey: z30.string().max(200).optional()
7302
+ });
7303
+ var ConfirmationView = z30.object({
7304
+ confirmation: Confirmation,
7305
+ write: ConfirmedWrite,
7306
+ target: z30.string(),
7307
+ expiresAt: z30.string()
7308
+ });
7309
+ var ConfirmedRequest = z30.strictObject({ confirmation: Confirmation.optional() });
7208
7310
  var ProposeRequest = z30.strictObject({
7209
7311
  scope: ProposeScope,
7210
7312
  /** Exactly the files the person saw listed; one that changed back since is left out. */
7211
7313
  files: z30.array(z30.string().min(1)).min(1),
7212
7314
  title: z30.string().max(200).optional(),
7213
7315
  /** The branch GET's plan showed, so the PR is on the branch the person saw. */
7214
- branch: z30.string().max(200).optional()
7316
+ branch: z30.string().max(200).optional(),
7317
+ /** 3.0.0 (ADR 0186): the person's confirmation from the app (`propose`, the scope). */
7318
+ confirmation: Confirmation.optional()
7215
7319
  });
7216
7320
  var LinesView = z30.object({
7217
7321
  code: z30.number().int().optional(),
@@ -7446,10 +7550,15 @@ var FindingActionRequest = z30.strictObject({
7446
7550
  var OpenWorkspaceRequest = z30.strictObject({ repos: z30.array(RecordId).min(1) });
7447
7551
  var HandoffRequest = z30.strictObject({
7448
7552
  phase: Phase.optional(),
7449
- repo: z30.string().optional()
7553
+ repo: z30.string().optional(),
7554
+ /** 3.0.0 (ADR 0186): the person's confirmation from the app (`handoff`, the change). */
7555
+ confirmation: Confirmation.optional()
7450
7556
  });
7451
- var SyncRequest = z30.strictObject({ repo: z30.string().optional() });
7452
- var ReleasePrsRequest = z30.strictObject({});
7557
+ var SyncRequest = z30.strictObject({
7558
+ repo: z30.string().optional(),
7559
+ confirmation: Confirmation.optional()
7560
+ });
7561
+ var ReleasePrsRequest = z30.strictObject({ confirmation: Confirmation.optional() });
7453
7562
  var TaskDoneRequest = z30.strictObject({ done: z30.boolean() });
7454
7563
  var CHANGE_OWNER_ROLES = [
7455
7564
  "product-owner",
@@ -7507,7 +7616,9 @@ var StepRunRequest = z30.strictObject({
7507
7616
  with: z30.string().min(1),
7508
7617
  inputsSha256: z30.string().regex(/^[0-9a-f]{64}$/, "the sha-256 the preview showed"),
7509
7618
  fillOnly: z30.boolean().optional(),
7510
- change: z30.string().optional()
7619
+ change: z30.string().optional(),
7620
+ /** 3.0.0 (ADR 0186): the person's confirmation from the app (`step-run`, the step). */
7621
+ confirmation: Confirmation.optional()
7511
7622
  });
7512
7623
  var ArchiveRequest = z30.strictObject({ rescan: z30.boolean().optional() });
7513
7624
  var DraftRequestsRequest = z30.strictObject({ force: z30.boolean().optional() });
@@ -7550,7 +7661,10 @@ var SaveNotifyRequest = z30.strictObject({
7550
7661
  digest: z30.enum(["off", "daily", "weekly"]),
7551
7662
  channel: z30.string().trim().min(1).optional()
7552
7663
  });
7553
- var SendDigestRequest = z30.strictObject({ send: z30.boolean().default(false) });
7664
+ var SendDigestRequest = z30.strictObject({
7665
+ send: z30.boolean().default(false),
7666
+ confirmation: Confirmation.optional()
7667
+ });
7554
7668
  var TriageDecideRequest = z30.strictObject({
7555
7669
  option: z30.number().int().min(1),
7556
7670
  reason: z30.string().trim().min(1).optional()
@@ -7586,7 +7700,8 @@ var QuestionList = z30.object({
7586
7700
  problems: z30.array(z30.object({ file: z30.string(), message: z30.string() })),
7587
7701
  /**
7588
7702
  * 2.51.0: every question on file by state, whatever `state` or `mine` the list asked for, so a
7589
- * page shows its counts from the one request.
7703
+ * page shows its counts from the one request. With `change` they are that change's; with `role`
7704
+ * that role's, as the list is (`byRole` stays every role's).
7590
7705
  */
7591
7706
  counts: z30.object({
7592
7707
  open: z30.number().int(),
@@ -8592,6 +8707,16 @@ var OPS = {
8592
8707
  ok: { status: 200, schema: "Health", description: "OK" }
8593
8708
  }
8594
8709
  },
8710
+ "/api/confirmations": {
8711
+ post: {
8712
+ id: "confirmWrite",
8713
+ summary: "3.0.0 (ADR 0186): the app's page asks, on the person's click, for a confirmation of one write to a shared system (a hand-off, the release PRs, a merge, a task's PR, sending the digest, Propose for review, a step run with a team's tool, where the model's key goes, a Test of uncommitted model settings). It needs the page key the server puts in the page and never prints, so the session token alone gets 403; the confirmation is for that write and target, used once, and expires after two minutes",
8714
+ tag: "system",
8715
+ body: ConfirmationRequest,
8716
+ ok: { status: 201, schema: "ConfirmationView", description: "The confirmation" },
8717
+ errors: [400, 403]
8718
+ }
8719
+ },
8595
8720
  "/api/me": {
8596
8721
  get: {
8597
8722
  id: "getMe",
@@ -8627,7 +8752,7 @@ var OPS = {
8627
8752
  "/api/me/digest": {
8628
8753
  post: {
8629
8754
  id: "sendDigest",
8630
- summary: "What waits on the person; with send, posted through the notify adapter as their approval",
8755
+ summary: "What waits on the person; with send, posted through the notify adapter as their approval. 3.0.0 (ADR 0186): send needs the person's confirmation (`digest-send`, `me`), else 403",
8631
8756
  tag: "system",
8632
8757
  body: SendDigestRequest,
8633
8758
  ok: {
@@ -8635,7 +8760,7 @@ var OPS = {
8635
8760
  schema: { type: "object", required: ["title", "body", "lines"] },
8636
8761
  description: "The digest, with sent or notSent"
8637
8762
  },
8638
- errors: [400]
8763
+ errors: [400, 403]
8639
8764
  }
8640
8765
  },
8641
8766
  "/api/across": {
@@ -9422,10 +9547,11 @@ var OPS = {
9422
9547
  "/api/workspace/sync": {
9423
9548
  post: {
9424
9549
  id: "syncWorkspace",
9425
- summary: "Clone or update base clones",
9550
+ summary: "Clone or update base clones. 3.0.0 (review round 48): 409 while a sync runs on this server",
9426
9551
  tag: "workspace",
9427
9552
  body: ScanRequest.pick({ repos: true }),
9428
- ok: { status: 202, schema: "JobAccepted", description: "Job started" }
9553
+ ok: { status: 202, schema: "JobAccepted", description: "Job started" },
9554
+ errors: [409]
9429
9555
  }
9430
9556
  },
9431
9557
  "/api/scan": {
@@ -9441,11 +9567,11 @@ var OPS = {
9441
9567
  "/api/reconcile": {
9442
9568
  post: {
9443
9569
  id: "startReconcile",
9444
- summary: "Check a diagram against the catalog",
9570
+ summary: "Check a diagram against the catalog. 3.0.0 (review round 48): 409 while a reconcile runs on this server",
9445
9571
  tag: "scans",
9446
9572
  body: ReconcileRequest,
9447
9573
  ok: { status: 202, schema: "JobAccepted", description: "Job started" },
9448
- errors: [404]
9574
+ errors: [404, 409]
9449
9575
  }
9450
9576
  },
9451
9577
  "/api/jobs/{jobId}": {
@@ -9513,7 +9639,7 @@ var OPS = {
9513
9639
  },
9514
9640
  post: {
9515
9641
  id: "proposeForReview",
9516
- summary: "2.65.0 (ADR 0183): on the person's yes, commit exactly those files to the branch, push it and open the PR; a person merges",
9642
+ summary: "2.65.0 (ADR 0183): on the person's yes, commit exactly those files to the branch, push it and open the PR; a person merges. 3.0.0 (ADR 0186): needs the person's confirmation (`propose`, the scope), else 403",
9517
9643
  tag: "workspace",
9518
9644
  body: ProposeRequest,
9519
9645
  ok: {
@@ -9522,7 +9648,7 @@ var OPS = {
9522
9648
  description: "Started: its job's result is the code and the lines"
9523
9649
  },
9524
9650
  // 2.68.0: 409 while another local step (Apply, Propose, Bring in) runs.
9525
- errors: [400, 409]
9651
+ errors: [400, 403, 409]
9526
9652
  }
9527
9653
  },
9528
9654
  "/api/owner-questions": {
@@ -9604,7 +9730,7 @@ var OPS = {
9604
9730
  "/api/changes/{changeId}/release-prs": {
9605
9731
  post: {
9606
9732
  id: "raiseReleasePrs",
9607
- summary: "Raise one release PR per code repo from change/<id> into its default branch, as the signed-in person (ADR 0184)",
9733
+ summary: "Raise one release PR per code repo from change/<id> into its default branch, as the signed-in person (ADR 0184). 3.0.0 (ADR 0186): needs the person's confirmation (`release-prs`, the change), else 403",
9608
9734
  tag: "changes",
9609
9735
  params: [p("changeId")],
9610
9736
  body: ReleasePrsRequest,
@@ -9613,18 +9739,18 @@ var OPS = {
9613
9739
  schema: "LinesView",
9614
9740
  description: "Raised: what each repo's release PR said"
9615
9741
  },
9616
- errors: [400, 404, 422]
9742
+ errors: [400, 403, 404, 422]
9617
9743
  }
9618
9744
  },
9619
9745
  "/api/changes/{changeId}/sync": {
9620
9746
  post: {
9621
9747
  id: "syncChange",
9622
- summary: "Refresh the change from its hand-off PR and advance it when merged (ADR 0043)",
9748
+ summary: "Refresh the change from its hand-off PR and advance it when merged (ADR 0043). 3.0.0 (ADR 0186): merges a ready PR only with the person's confirmation (`merge`, the change); without one it only reads, and a confirmation that isn't valid is 403",
9623
9749
  tag: "changes",
9624
9750
  params: [p("changeId")],
9625
9751
  body: SyncRequest,
9626
9752
  ok: { status: 200, schema: "ChangeDetail", description: "OK" },
9627
- errors: [400, 404, 422]
9753
+ errors: [400, 403, 404, 422]
9628
9754
  }
9629
9755
  },
9630
9756
  "/api/changes/{changeId}/artifacts/{artifact}": {
@@ -9667,9 +9793,10 @@ var OPS = {
9667
9793
  "/api/changes/{changeId}/tasks/{taskId}/pr": {
9668
9794
  post: {
9669
9795
  id: "raiseTaskPr",
9670
- summary: "2.69.0 (sixth UX walk): on the person's yes, push a drafted task's branch and open its PR into the change branch",
9796
+ summary: "2.69.0 (sixth UX walk): on the person's yes, push a drafted task's branch and open its PR into the change branch. 3.0.0 (ADR 0186): needs the person's confirmation (`task-pr`, `<change>/<task>`), else 403",
9671
9797
  tag: "changes",
9672
9798
  params: [p("changeId"), p("taskId")],
9799
+ body: ConfirmedRequest,
9673
9800
  ok: { status: 201, schema: "Task", description: "The task, its PR raised" },
9674
9801
  errors: [403, 404, 409, 422]
9675
9802
  }
@@ -9720,7 +9847,7 @@ var OPS = {
9720
9847
  "/api/changes/{changeId}/handoff": {
9721
9848
  post: {
9722
9849
  id: "handOff",
9723
- summary: "Open the phase's hand-off PR after its gate passes",
9850
+ summary: "Open the phase's hand-off PR after its gate passes. 3.0.0 (ADR 0186): needs the person's confirmation (`handoff`, the change), else 403",
9724
9851
  tag: "changes",
9725
9852
  params: [p("changeId")],
9726
9853
  body: HandoffRequest,
@@ -10223,12 +10350,12 @@ var OPS = {
10223
10350
  },
10224
10351
  post: {
10225
10352
  id: "runStep",
10226
- summary: "Run a step with a team's own tool; the shown inputs' sha-256 is the approval",
10353
+ summary: "Run a step with a team's own tool on the shown inputs (their sha-256). 3.0.0 (ADR 0186): needs the person's confirmation (`step-run`, the step), else 403",
10227
10354
  tag: "release",
10228
10355
  params: [p("stepId")],
10229
10356
  body: StepRunRequest,
10230
10357
  ok: { status: 200, schema: { type: "object" }, description: "OK" },
10231
- errors: [400, 404, 422]
10358
+ errors: [400, 403, 404, 422]
10232
10359
  }
10233
10360
  },
10234
10361
  "/api/release": {
@@ -10391,11 +10518,11 @@ var OPS = {
10391
10518
  },
10392
10519
  put: {
10393
10520
  id: "putAiSettings",
10394
- summary: "Write the AI settings to runtime.yaml: checked against the Runtime schema, keeping what it doesn't change; refuses anything that looks like a key. 2.84.0: takes decide (ADR 0181: links, questions, minPrecision), lifting a version 3 file to 4",
10521
+ summary: "Write the AI settings to runtime.yaml: checked against the Runtime schema, keeping what it doesn't change; refuses anything that looks like a key. 2.84.0: takes decide (ADR 0181: links, questions, minPrecision), lifting a version 3 file to 4. 3.0.0 (ADR 0186): keyEnv is a variable starting ATTICUS_, one of the model providers' own key names (the list is in the model-providers package) or a name kept in this machine's credential store (422 otherwise); a change of the provider, keyEnv or an address needs the person's confirmation (`ai-model`, `model`) as `confirmation`, else 403",
10395
10522
  tag: "run",
10396
10523
  body: z30.record(z30.string(), z30.unknown()),
10397
10524
  ok: { status: 200, schema: { type: "object" }, description: "OK" },
10398
- errors: [409, 422]
10525
+ errors: [403, 409, 422]
10399
10526
  }
10400
10527
  },
10401
10528
  "/api/component-types": {
@@ -10419,10 +10546,11 @@ var OPS = {
10419
10546
  "/api/settings/ai/test": {
10420
10547
  post: {
10421
10548
  id: "testAiProvider",
10422
- summary: "Ask the configured model provider one short question with nothing of the estate in it, and say whether it answered",
10549
+ summary: "Ask the configured model provider one short question with nothing of the estate in it, and say whether it answered. 3.0.0 (ADR 0186): when runtime.yaml's model settings differ from the committed ones (HEAD), it needs the person's confirmation (`ai-test`, `model`), else 403",
10423
10550
  tag: "run",
10551
+ body: ConfirmedRequest,
10424
10552
  ok: { status: 200, schema: { type: "object" }, description: "OK" },
10425
- errors: [409]
10553
+ errors: [403, 409]
10426
10554
  }
10427
10555
  },
10428
10556
  "/api/settings/executors/check": {
@@ -10891,6 +11019,254 @@ import { isMap as isMap8, parseDocument as parseDocument8 } from "yaml";
10891
11019
  // packages/core/dist/runtime-migrate.js
10892
11020
  import { isMap as isMap9, parseDocument as parseDocument9 } from "yaml";
10893
11021
 
11022
+ // packages/core/dist/glob.js
11023
+ var notSlash = (c) => c !== "/";
11024
+ var anyChar = (c) => !/[\n\r\u2028\u2029]/.test(c);
11025
+ var Builder = class {
11026
+ states = [];
11027
+ add(s) {
11028
+ this.states.push(s);
11029
+ return this.states.length - 1;
11030
+ }
11031
+ /** `c*` looping on a test, then on to next. */
11032
+ loop(test, next) {
11033
+ const split = this.add({ kind: "split", outs: [] });
11034
+ const ch = this.add({ kind: "char", test, out: split });
11035
+ this.states[split].outs.push(ch, next);
11036
+ return split;
11037
+ }
11038
+ /** `(?:.*\/)?` then next: any folders, or none. */
11039
+ folders(next) {
11040
+ const slash = this.add({ kind: "char", test: (c) => c === "/", out: next });
11041
+ return this.add({ kind: "split", outs: [this.loop(anyChar, slash), next] });
11042
+ }
11043
+ };
11044
+ function tidy(glob) {
11045
+ return glob.trim().replace(/\\/g, "/").replace(/^\.\//, "");
11046
+ }
11047
+ function compile(b, g, next) {
11048
+ const pieces = [];
11049
+ for (let i = 0; i < g.length; i++) {
11050
+ const ch = g[i];
11051
+ if (ch === "*") {
11052
+ if (g[i + 1] === "*") {
11053
+ const slash = g[i + 2] === "/";
11054
+ pieces.push(slash ? (n) => b.folders(n) : (n) => b.loop(anyChar, n));
11055
+ i += slash ? 2 : 1;
11056
+ } else
11057
+ pieces.push((n) => b.loop(notSlash, n));
11058
+ } else if (ch === "?")
11059
+ pieces.push((n) => b.add({ kind: "char", test: notSlash, out: n }));
11060
+ else if (ch === "[") {
11061
+ const end = g.indexOf("]", i + 2);
11062
+ if (end < 0)
11063
+ pieces.push(lit("["));
11064
+ else {
11065
+ const body = g.slice(i + 1, end).replace(/^!/, "^").replace(/\\/g, "\\\\");
11066
+ const re = new RegExp(`^[${body}]$`);
11067
+ pieces.push((n) => b.add({ kind: "char", test: (c) => re.test(c), out: n }));
11068
+ i = end;
11069
+ }
11070
+ } else if (ch === "{") {
11071
+ const end = g.indexOf("}", i);
11072
+ if (end < 0)
11073
+ pieces.push(lit("{"));
11074
+ else {
11075
+ const parts = g.slice(i + 1, end).split(",").map((p2) => {
11076
+ let t = tidy(p2);
11077
+ if (t.startsWith("/"))
11078
+ t = t.slice(1);
11079
+ return t;
11080
+ });
11081
+ const probe = new Builder();
11082
+ for (const p2 of parts)
11083
+ compile(probe, p2, probe.add({ kind: "match" }));
11084
+ pieces.push((n) => b.add({ kind: "split", outs: parts.map((p2) => compile(b, p2, n)) }));
11085
+ i = end;
11086
+ }
11087
+ } else
11088
+ pieces.push(lit(ch));
11089
+ }
11090
+ let at = next;
11091
+ for (let k = pieces.length - 1; k >= 0; k--)
11092
+ at = pieces[k](at);
11093
+ return at;
11094
+ function lit(c) {
11095
+ return (n) => b.add({ kind: "char", test: (x) => x === c, out: n });
11096
+ }
11097
+ }
11098
+ function globMatcher(glob, anyDepth = !glob.replace(/\/$/, "").includes("/")) {
11099
+ let g = tidy(glob);
11100
+ if (g.startsWith("/")) {
11101
+ g = g.slice(1);
11102
+ anyDepth = false;
11103
+ }
11104
+ const b = new Builder();
11105
+ const end = b.add({ kind: "match" });
11106
+ let start = compile(b, g, end);
11107
+ if (anyDepth)
11108
+ start = b.folders(start);
11109
+ const states = b.states;
11110
+ const close = (set, s) => {
11111
+ const stack = [s];
11112
+ while (stack.length) {
11113
+ const at = stack.pop();
11114
+ if (set.has(at))
11115
+ continue;
11116
+ set.add(at);
11117
+ const st = states[at];
11118
+ if (st.kind === "split")
11119
+ for (const o of st.outs)
11120
+ stack.push(o);
11121
+ }
11122
+ };
11123
+ return {
11124
+ test(path) {
11125
+ let live = /* @__PURE__ */ new Set();
11126
+ close(live, start);
11127
+ for (let i = 0; i < path.length; i++) {
11128
+ const c = path[i];
11129
+ const next = /* @__PURE__ */ new Set();
11130
+ for (const s of live) {
11131
+ const st = states[s];
11132
+ if (st.kind === "char" && st.test(c))
11133
+ close(next, st.out);
11134
+ }
11135
+ if (!next.size)
11136
+ return false;
11137
+ live = next;
11138
+ }
11139
+ return live.has(end);
11140
+ }
11141
+ };
11142
+ }
11143
+
11144
+ // packages/core/dist/repo-files.js
11145
+ import { readdir, readFile } from "node:fs/promises";
11146
+ import { join } from "node:path";
11147
+ var LATIN1_HIGH = (
11148
+ // windows-1252's 0x80-0x9F; the five it leaves undefined keep their C1 code point
11149
+ "\u20AC\x81\u201A\u0192\u201E\u2026\u2020\u2021\u02C6\u2030\u0160\u2039\u0152\x8D\u017D\x8F\x90\u2018\u2019\u201C\u201D\u2022\u2013\u2014\u02DC\u2122\u0161\u203A\u0153\x9D\u017E\u0178"
11150
+ );
11151
+ var utf8 = new TextDecoder("utf-8", { fatal: true });
11152
+ function windows1252(bytes) {
11153
+ let out = "";
11154
+ for (let i = 0; i < bytes.length; i += 8192) {
11155
+ const chunk = bytes.subarray(i, i + 8192);
11156
+ const codes = new Array(chunk.length);
11157
+ for (let j = 0; j < chunk.length; j++) {
11158
+ const b = chunk[j];
11159
+ codes[j] = b >= 128 && b <= 159 ? LATIN1_HIGH.charCodeAt(b - 128) : b;
11160
+ }
11161
+ out += String.fromCharCode(...codes);
11162
+ }
11163
+ return out;
11164
+ }
11165
+ function utf16(bytes, bigEndian) {
11166
+ const n = bytes.length - bytes.length % 2;
11167
+ const b = Buffer.from(bytes.buffer, bytes.byteOffset, n);
11168
+ if (!bigEndian)
11169
+ return b.toString("utf16le");
11170
+ const swapped = Buffer.from(b);
11171
+ swapped.swap16();
11172
+ return swapped.toString("utf16le");
11173
+ }
11174
+ function decodeText(bytes) {
11175
+ if (bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 254)
11176
+ return utf16(bytes.subarray(2), false);
11177
+ if (bytes.length >= 2 && bytes[0] === 254 && bytes[1] === 255)
11178
+ return utf16(bytes.subarray(2), true);
11179
+ const body = bytes.length >= 3 && bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191 ? bytes.subarray(3) : bytes;
11180
+ try {
11181
+ return utf8.decode(body);
11182
+ } catch {
11183
+ return windows1252(body);
11184
+ }
11185
+ }
11186
+ function ignoreRules(text3, base) {
11187
+ const out = [];
11188
+ for (let line of text3.split(/\r?\n/)) {
11189
+ line = line.replace(/(?<!\\)\s+$/, "");
11190
+ if (!line || line.startsWith("#"))
11191
+ continue;
11192
+ let negate = false;
11193
+ if (line.startsWith("!")) {
11194
+ negate = true;
11195
+ line = line.slice(1);
11196
+ } else if (line.startsWith("\\!") || line.startsWith("\\#"))
11197
+ line = line.slice(1);
11198
+ const dirOnly = line.endsWith("/");
11199
+ if (dirOnly)
11200
+ line = line.slice(0, -1);
11201
+ if (!line)
11202
+ continue;
11203
+ const anchored = line.includes("/");
11204
+ try {
11205
+ out.push({ base, re: globMatcher(line.replace(/^\//, ""), !anchored), negate, dirOnly });
11206
+ } catch {
11207
+ }
11208
+ }
11209
+ return out;
11210
+ }
11211
+ function ignoredBy(rules, path, isDir) {
11212
+ let out = false;
11213
+ for (const r of rules) {
11214
+ if (r.dirOnly && !isDir)
11215
+ continue;
11216
+ if (r.base && !path.startsWith(`${r.base}/`))
11217
+ continue;
11218
+ const rel = r.base ? path.slice(r.base.length + 1) : path;
11219
+ if (r.re.test(rel))
11220
+ out = !r.negate;
11221
+ }
11222
+ return out;
11223
+ }
11224
+ var byName = (a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
11225
+ function folder(entries, rel, inherited, gitignore) {
11226
+ const rules = gitignore === void 0 ? inherited : [...inherited, ...ignoreRules(gitignore, rel)];
11227
+ const names = entries.map((e) => e.name);
11228
+ const kept = entries.filter((e) => !e.isSymbolicLink() && e.name !== ".git").sort(byName).map((e) => ({ e, path: rel ? `${rel}/${e.name}` : e.name }));
11229
+ return { rules, names, kept };
11230
+ }
11231
+ var hasGitignore = (entries) => entries.some((e) => e.name === ".gitignore" && e.isFile());
11232
+ async function walkRepo(root, visit, o = {}) {
11233
+ const max = o.max ?? Number.POSITIVE_INFINITY;
11234
+ let files = 0;
11235
+ let cut = false;
11236
+ const go = async (rel, above, inherited) => {
11237
+ const dir = rel ? join(root, ...rel.split("/")) : root;
11238
+ let entries;
11239
+ try {
11240
+ entries = await readdir(dir, { withFileTypes: true });
11241
+ } catch {
11242
+ return true;
11243
+ }
11244
+ const text3 = hasGitignore(entries) ? await readFile(join(dir, ".gitignore")).then(decodeText, () => void 0) : void 0;
11245
+ const { rules, names, kept } = folder(entries, rel, inherited, text3);
11246
+ for (const { e, path } of kept) {
11247
+ if (e.isDirectory()) {
11248
+ if (ignoredBy(rules, path, true) || o.skipFolder?.(above, e.name, names))
11249
+ continue;
11250
+ if (!await go(path, [...above, e.name], rules))
11251
+ return false;
11252
+ } else if (e.isFile()) {
11253
+ if (ignoredBy(rules, path, false))
11254
+ continue;
11255
+ if (files >= max) {
11256
+ cut = true;
11257
+ return false;
11258
+ }
11259
+ files++;
11260
+ if (await visit(path) === false)
11261
+ return false;
11262
+ }
11263
+ }
11264
+ return true;
11265
+ };
11266
+ await go("", [], []);
11267
+ return { files, cut };
11268
+ }
11269
+
10894
11270
  // packages/core/dist/log.js
10895
11271
  var LOG_MAX_BYTES = 5 * 1024 * 1024;
10896
11272
 
@@ -10918,7 +11294,8 @@ var BatchLink = z31.strictObject({
10918
11294
  var BatchQuestion = z31.strictObject({
10919
11295
  kind: z31.literal("question"),
10920
11296
  id: QuestionId,
10921
- before: QuestionAnswer.optional()
11297
+ before: QuestionAnswer.optional(),
11298
+ proposal: z31.string().min(1).max(65536).optional()
10922
11299
  });
10923
11300
  var BatchItem = z31.discriminatedUnion("kind", [BatchLink, BatchQuestion]);
10924
11301
  var DecisionBatch = z31.strictObject({
@@ -11354,8 +11731,20 @@ function globToRegExp(glob) {
11354
11731
  }
11355
11732
 
11356
11733
  // packages/sdk/dist/fs-repo.js
11357
- import { lstat, readdir, readFile, realpath, stat } from "node:fs/promises";
11358
- import { join, relative, resolve, sep } from "node:path";
11734
+ import { lstat, readFile as readFile2, realpath, stat } from "node:fs/promises";
11735
+ import { join as join2, resolve, sep } from "node:path";
11736
+
11737
+ // packages/sdk/dist/listing.js
11738
+ var LISTING = /* @__PURE__ */ Symbol.for("@maycombhq/sdk.listing");
11739
+ function listingOf(repo) {
11740
+ const v = repo[LISTING];
11741
+ return typeof v === "string" ? v : "";
11742
+ }
11743
+ function setListing(repo, listing) {
11744
+ Object.defineProperty(repo, LISTING, { value: listing, enumerable: false, configurable: true });
11745
+ }
11746
+
11747
+ // packages/sdk/dist/fs-repo.js
11359
11748
  var DEFAULT_IGNORES = [
11360
11749
  ".git",
11361
11750
  "node_modules",
@@ -11388,24 +11777,12 @@ function fsRepo(name, dir, commit, options = {}) {
11388
11777
  let cache;
11389
11778
  const sizes = /* @__PURE__ */ new Map();
11390
11779
  const skipped = /* @__PURE__ */ new Map();
11391
- async function walk(abs, out) {
11392
- const entries = await readdir(abs, { withFileTypes: true });
11393
- for (const e of entries) {
11394
- if (e.isSymbolicLink())
11395
- continue;
11396
- const full = join(abs, e.name);
11397
- if (e.isDirectory()) {
11398
- if (!ignore.has(e.name))
11399
- await walk(full, out);
11400
- } else if (e.isFile()) {
11401
- out.push(relative(root, full).split(sep).join("/"));
11402
- }
11403
- }
11404
- }
11405
11780
  async function allFiles() {
11406
11781
  if (!cache) {
11407
11782
  const out = [];
11408
- await walk(root, out);
11783
+ await walkRepo(root, async (p2) => void out.push(p2), {
11784
+ skipFolder: (_above, name2) => ignore.has(name2)
11785
+ });
11409
11786
  cache = out.sort();
11410
11787
  }
11411
11788
  return cache;
@@ -11414,7 +11791,7 @@ function fsRepo(name, dir, commit, options = {}) {
11414
11791
  if (path.startsWith("/") || /^[A-Za-z]:/.test(path) || path.includes("\\") || path.split("/").includes("..")) {
11415
11792
  throw new RepoReadError(`path must be repo-relative with forward slashes: ${path}`, path);
11416
11793
  }
11417
- const abs = join(root, ...path.split("/"));
11794
+ const abs = join2(root, ...path.split("/"));
11418
11795
  const info = await lstat(abs).catch(() => void 0);
11419
11796
  if (info?.isSymbolicLink())
11420
11797
  throw new RepoReadError(`symbolic links are not read: ${path}`, path);
@@ -11429,7 +11806,7 @@ function fsRepo(name, dir, commit, options = {}) {
11429
11806
  throw new RepoReadError(`file is larger than ${maxBytes} bytes: ${path}`, path);
11430
11807
  return abs;
11431
11808
  }
11432
- return {
11809
+ const handle = {
11433
11810
  name,
11434
11811
  commit,
11435
11812
  async *listFiles(globs) {
@@ -11438,7 +11815,7 @@ function fsRepo(name, dir, commit, options = {}) {
11438
11815
  if (!matchers.some((m) => m.test(p2)))
11439
11816
  continue;
11440
11817
  if (!sizes.has(p2))
11441
- sizes.set(p2, (await stat(join(root, ...p2.split("/"))).catch(() => void 0))?.size ?? 0);
11818
+ sizes.set(p2, (await stat(join2(root, ...p2.split("/"))).catch(() => void 0))?.size ?? 0);
11442
11819
  const bytes = sizes.get(p2);
11443
11820
  if (bytes > maxBytes) {
11444
11821
  skipped.set(p2, bytes);
@@ -11452,16 +11829,17 @@ function fsRepo(name, dir, commit, options = {}) {
11452
11829
  return [...skipped].sort(([a], [b]) => a < b ? -1 : 1).map(([path, bytes]) => ({ path, bytes }));
11453
11830
  },
11454
11831
  async readText(path) {
11455
- const text3 = await readFile(await safePath(path), "utf8");
11456
- return text3.charCodeAt(0) === 65279 ? text3.slice(1) : text3;
11832
+ return decodeText(await readFile2(await safePath(path)));
11457
11833
  }
11458
11834
  };
11835
+ setListing(handle, JSON.stringify({ ignore: [...ignore].sort(), maxFileBytes: maxBytes, gitignore: true }));
11836
+ return handle;
11459
11837
  }
11460
11838
 
11461
11839
  // packages/sdk/dist/cache.js
11462
11840
  import { createHash as createHash3 } from "node:crypto";
11463
- import { mkdir, readdir as readdir2, readFile as readFile2, rename, rm, writeFile } from "node:fs/promises";
11464
- import { join as join2 } from "node:path";
11841
+ import { mkdir, readdir as readdir2, readFile as readFile3, rename, rm, writeFile } from "node:fs/promises";
11842
+ import { join as join3 } from "node:path";
11465
11843
  var sha256 = (s) => createHash3("sha256").update(s).digest("hex");
11466
11844
  function cacheKeyHash(key) {
11467
11845
  return sha256(JSON.stringify([
@@ -11500,7 +11878,7 @@ function fsScanCache(dir) {
11500
11878
  const h = cacheKeyHash(key);
11501
11879
  return {
11502
11880
  h,
11503
- path: join2(dir, key.repo, key.commit, `${key.extractor}@${key.version}.${h.slice(0, 16)}.json`)
11881
+ path: join3(dir, key.repo, key.commit, `${key.extractor}@${key.version}.${h.slice(0, 16)}.json`)
11504
11882
  };
11505
11883
  };
11506
11884
  return {
@@ -11508,7 +11886,7 @@ function fsScanCache(dir) {
11508
11886
  const { h, path } = fileFor(key);
11509
11887
  let file;
11510
11888
  try {
11511
- file = JSON.parse(await readFile2(path, "utf8"));
11889
+ file = JSON.parse(await readFile3(path, "utf8"));
11512
11890
  } catch {
11513
11891
  return void 0;
11514
11892
  }
@@ -11534,7 +11912,7 @@ function fsScanCache(dir) {
11534
11912
  checksum: sha256(JSON.stringify(value)),
11535
11913
  value
11536
11914
  };
11537
- await mkdir(join2(path, ".."), { recursive: true });
11915
+ await mkdir(join3(path, ".."), { recursive: true });
11538
11916
  const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
11539
11917
  await writeFile(tmp, JSON.stringify(file), "utf8");
11540
11918
  await rename(tmp, path);
@@ -11546,13 +11924,13 @@ function fsScanCache(dir) {
11546
11924
  let removed = 0;
11547
11925
  let commits;
11548
11926
  try {
11549
- commits = await readdir2(join2(dir, repo));
11927
+ commits = await readdir2(join3(dir, repo));
11550
11928
  } catch {
11551
11929
  return 0;
11552
11930
  }
11553
11931
  for (const c of commits) {
11554
11932
  if (!keep.has(c)) {
11555
- await rm(join2(dir, repo, c), { recursive: true, force: true });
11933
+ await rm(join3(dir, repo, c), { recursive: true, force: true });
11556
11934
  removed++;
11557
11935
  }
11558
11936
  }
@@ -11657,7 +12035,10 @@ async function scanWith(options) {
11657
12035
  options.configFor?.(extractor) ?? "",
11658
12036
  JSON.stringify(options.repoInfo ?? {}),
11659
12037
  // A changed framework model means a different reading of the same code.
11660
- options.frameworks?.length ? JSON.stringify(options.frameworks) : ""
12038
+ options.frameworks?.length ? JSON.stringify(options.frameworks) : "",
12039
+ // Review round 49: the same commit listed another way (scan-settings exclusions, the
12040
+ // folders left out, the size limit) gives the extractor other files.
12041
+ listingOf(repo)
11661
12042
  ].join("|")
11662
12043
  };
11663
12044
  try {
@@ -11746,8 +12127,8 @@ async function scanWith(options) {
11746
12127
 
11747
12128
  // packages/sdk/dist/sandbox.js
11748
12129
  import { createHash as createHash4 } from "node:crypto";
11749
- import { readFile as readFile3 } from "node:fs/promises";
11750
- import { join as join3 } from "node:path";
12130
+ import { readFile as readFile4 } from "node:fs/promises";
12131
+ import { join as join4 } from "node:path";
11751
12132
  import { Worker } from "node:worker_threads";
11752
12133
  var PLUGIN_EXTRACTOR_PREFIX = "plugin-";
11753
12134
  var MAX_RECORDS = 1e5;
@@ -11759,7 +12140,7 @@ async function readPinnedEntry(dir, manifest) {
11759
12140
  return { ok: false, message: "isn't pinned: run atticus plugin pin once it is reviewed" };
11760
12141
  let source;
11761
12142
  try {
11762
- source = await readFile3(join3(dir, ...manifest.entry.split("/")), "utf8");
12143
+ source = await readFile4(join4(dir, ...manifest.entry.split("/")), "utf8");
11763
12144
  } catch (e) {
11764
12145
  return { ok: false, message: `can't read ${manifest.entry}: ${e.message}` };
11765
12146
  }