@maycombhq/atticus 2.0.0-beta.26 → 2.0.0-beta.27.1

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 (325) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/{chunk-7JZONWAA.js → chunk-23OQZY5Z.js} +22 -18
  3. package/dist/{chunk-UTZMF5CV.js → chunk-23TTURB2.js} +1 -1
  4. package/dist/{chunk-YIOYKA4V.js → chunk-2AIOOA3U.js} +7 -7
  5. package/dist/chunk-2ANBMA74.js +107 -0
  6. package/dist/{chunk-ZYLGEWTC.js → chunk-2FORECYK.js} +78 -57
  7. package/dist/{chunk-D5H3RZNE.js → chunk-2J2GMERV.js} +16 -15
  8. package/dist/{chunk-ZDA72732.js → chunk-2MRYL45Z.js} +50 -9
  9. package/dist/{chunk-RBO4A7TC.js → chunk-2WPUSHB6.js} +15 -15
  10. package/dist/{chunk-2IO6XH37.js → chunk-3BQDBTQJ.js} +15 -15
  11. package/dist/{chunk-B3JHERXM.js → chunk-3CMGSQIA.js} +7 -5
  12. package/dist/{chunk-UFIQ5FWY.js → chunk-3M3MDBOG.js} +1 -1
  13. package/dist/chunk-3NGHSBVS.js +50 -0
  14. package/dist/{chunk-DHQXCP2X.js → chunk-3PBIZBWN.js} +1 -1
  15. package/dist/{chunk-CFK6CFXM.js → chunk-3PG6QOQF.js} +9 -9
  16. package/dist/chunk-3PN7KJBA.js +48 -0
  17. package/dist/{chunk-DARX3ATP.js → chunk-3TWERSTY.js} +11 -11
  18. package/dist/chunk-3XNE6XXF.js +211 -0
  19. package/dist/chunk-3YL2GZZH.js +55 -0
  20. package/dist/{chunk-ZGULQAPZ.js → chunk-44SWXDD7.js} +8 -5
  21. package/dist/{chunk-XI3GPYP4.js → chunk-44XGOSUU.js} +5 -5
  22. package/dist/{chunk-SAPX3PVK.js → chunk-4BK5EJ2C.js} +11 -11
  23. package/dist/{chunk-OH2OHNB5.js → chunk-4FLIW5PJ.js} +4 -4
  24. package/dist/{chunk-EUTZTJIO.js → chunk-4HMOOBIR.js} +19 -15
  25. package/dist/chunk-4NPWOUI2.js +514 -0
  26. package/dist/{chunk-RQM5Y3HJ.js → chunk-4UVTNHA6.js} +1 -1
  27. package/dist/{chunk-KVVNAUIG.js → chunk-4XK3HLOH.js} +1 -0
  28. package/dist/{chunk-ZQGFZJH5.js → chunk-523NRKHF.js} +4 -4
  29. package/dist/chunk-5A4FHGTI.js +34 -0
  30. package/dist/{chunk-SDHGFMES.js → chunk-5CIW5RMP.js} +3 -3
  31. package/dist/{chunk-GJSLO2E2.js → chunk-5GCCG3GJ.js} +11 -5
  32. package/dist/{chunk-LCRQPWTC.js → chunk-5KR2DHDW.js} +19 -18
  33. package/dist/{chunk-UIYPX2BA.js → chunk-5PAIR73N.js} +27 -26
  34. package/dist/{chunk-K35VNKJH.js → chunk-5YEUAZZE.js} +8 -8
  35. package/dist/{chunk-DB6TDJ4T.js → chunk-5YX7MJWW.js} +22 -21
  36. package/dist/{chunk-IH6BYFMH.js → chunk-5ZFLP2IK.js} +6 -6
  37. package/dist/chunk-66CMRGI2.js +44 -0
  38. package/dist/{chunk-YWQZ7CCW.js → chunk-6DHGNY3O.js} +18 -17
  39. package/dist/{chunk-WLA2JZ2K.js → chunk-6ESJWPR3.js} +8 -8
  40. package/dist/{chunk-2SCZZQNQ.js → chunk-6GX3OFEZ.js} +121 -15
  41. package/dist/{chunk-2HDNOUJU.js → chunk-6H62UHY5.js} +7065 -3456
  42. package/dist/{chunk-YYV276DM.js → chunk-6MSACVCY.js} +22 -21
  43. package/dist/{chunk-GXJ2PSDW.js → chunk-6OTGCKYH.js} +9 -9
  44. package/dist/{chunk-HSJKYDHI.js → chunk-6TXB2WR6.js} +5 -5
  45. package/dist/{chunk-KL7UHAOR.js → chunk-6VFR3DYS.js} +36 -21
  46. package/dist/{chunk-KS2IQYTZ.js → chunk-7BOGXFZ3.js} +11 -11
  47. package/dist/chunk-7GZ46N4V.js +37 -0
  48. package/dist/{chunk-KFJMQUSK.js → chunk-7HUCEHUK.js} +16 -15
  49. package/dist/{chunk-LY7DOYX2.js → chunk-7LOXUBRB.js} +53 -112
  50. package/dist/{chunk-NQDVD2YR.js → chunk-7SO6CGJH.js} +12 -12
  51. package/dist/{chunk-LZFKJ2BR.js → chunk-A3LVMCA5.js} +1 -1
  52. package/dist/{chunk-2XIIUXGX.js → chunk-A3QZZEJA.js} +16 -16
  53. package/dist/{chunk-PXDAGXQN.js → chunk-AHAEHBH5.js} +11 -11
  54. package/dist/{chunk-PFWP624T.js → chunk-AKZTCZ6F.js} +4 -4
  55. package/dist/{chunk-V5ZKGBYL.js → chunk-AOQG37K4.js} +8 -6
  56. package/dist/chunk-APYIIVBH.js +72 -0
  57. package/dist/{chunk-HV6PXXK7.js → chunk-AQLDQK2M.js} +3 -3
  58. package/dist/{chunk-YJBD5NDV.js → chunk-AXJCABA5.js} +6 -6
  59. package/dist/{chunk-CG6MG7SE.js → chunk-AZBP5DTU.js} +14 -14
  60. package/dist/chunk-B4WPO6FX.js +58 -0
  61. package/dist/{chunk-3GEAUW62.js → chunk-BSGOUHL6.js} +16 -15
  62. package/dist/{chunk-D4TW3PUO.js → chunk-BUBKKEUV.js} +5 -5
  63. package/dist/chunk-BV7WB32T.js +1068 -0
  64. package/dist/{chunk-I72PEROE.js → chunk-C5DY4R7R.js} +6 -6
  65. package/dist/chunk-CBFQO2F2.js +62 -0
  66. package/dist/{chunk-723OQZ3N.js → chunk-CHS5BJ34.js} +6 -6
  67. package/dist/{chunk-2FTHLB2H.js → chunk-CLM5Z3R5.js} +5 -5
  68. package/dist/{chunk-7AEB74KW.js → chunk-CPB4XMFI.js} +9 -9
  69. package/dist/{chunk-KZH5YV6J.js → chunk-CWJDZ5VP.js} +6 -6
  70. package/dist/chunk-CWKQRP6Y.js +56 -0
  71. package/dist/{chunk-PLSCWC2V.js → chunk-D3L5SO27.js} +5 -5
  72. package/dist/{chunk-OI32KTDM.js → chunk-D566V3T3.js} +13 -13
  73. package/dist/{chunk-JLTJAOO4.js → chunk-DDRTAEFZ.js} +50 -13
  74. package/dist/{chunk-TYN5SG5H.js → chunk-DGNTEKF6.js} +403 -148
  75. package/dist/{chunk-VUSYN4R4.js → chunk-DNDIT3LD.js} +8 -8
  76. package/dist/{chunk-IERXBWQU.js → chunk-DNKYWTVZ.js} +20 -19
  77. package/dist/{chunk-KJD4DLRZ.js → chunk-DS2OZXBN.js} +22 -21
  78. package/dist/{chunk-CSHJZFOE.js → chunk-DTW37FJ6.js} +91 -93
  79. package/dist/{chunk-KAWWXCPI.js → chunk-DVQCYF3V.js} +3 -3
  80. package/dist/{chunk-UZBLVNW6.js → chunk-DX7WEXYG.js} +38 -17
  81. package/dist/{chunk-PZFZPHCT.js → chunk-E7Q52EOO.js} +11 -11
  82. package/dist/{chunk-R2FUFBHW.js → chunk-EFDUC35B.js} +3 -3
  83. package/dist/chunk-EHT2KP5A.js +43 -0
  84. package/dist/{chunk-43OWNS5N.js → chunk-EHXEJFHD.js} +5 -5
  85. package/dist/{chunk-HQMLY2R6.js → chunk-ELJ5Q4J2.js} +2 -2
  86. package/dist/{chunk-BD7HBZLP.js → chunk-ELZGWEK4.js} +6 -6
  87. package/dist/{chunk-F4EGHECF.js → chunk-EM6DKBTJ.js} +3 -3
  88. package/dist/{chunk-PBDIVTFL.js → chunk-FADIWOA5.js} +3 -3
  89. package/dist/{chunk-IL7PVMUO.js → chunk-FBG3QHOL.js} +6 -6
  90. package/dist/{chunk-LHN5UCXD.js → chunk-FBNJZ3VH.js} +3 -3
  91. package/dist/chunk-FFIHRQ3O.js +67 -0
  92. package/dist/chunk-FT55WYNB.js +39 -0
  93. package/dist/{chunk-E5NHFHGC.js → chunk-FVT6LUOC.js} +7 -7
  94. package/dist/{chunk-KUEG2Y7M.js → chunk-FYRBBFIF.js} +8 -8
  95. package/dist/chunk-FZ2K3IXP.js +46 -0
  96. package/dist/{chunk-IBIIKUC7.js → chunk-G33UIUG3.js} +46 -20
  97. package/dist/chunk-G4TFQ4EG.js +60 -0
  98. package/dist/{chunk-2GT47PWU.js → chunk-GBJRFFDW.js} +5 -5
  99. package/dist/{chunk-BIKMME4S.js → chunk-GEHB2LMA.js} +28 -27
  100. package/dist/{chunk-NMURRF5F.js → chunk-GF6GBHFN.js} +13 -11
  101. package/dist/{chunk-6SIGGA37.js → chunk-GLNSLQSV.js} +26 -25
  102. package/dist/{chunk-BABRMZET.js → chunk-GZILYRGC.js} +3 -3
  103. package/dist/{chunk-5JGRF53S.js → chunk-GZSOZYEP.js} +3 -3
  104. package/dist/{chunk-Z33UNTHI.js → chunk-HBHPOKL2.js} +7 -7
  105. package/dist/{chunk-2JT4QV3Q.js → chunk-HDWVR5KD.js} +4 -4
  106. package/dist/{chunk-UJ5ZJS4B.js → chunk-HNU4AQXB.js} +22 -21
  107. package/dist/{chunk-IJN5PSDU.js → chunk-HOEZQRZU.js} +57 -27
  108. package/dist/{chunk-HWPX3T55.js → chunk-HPCGQAYH.js} +31 -24
  109. package/dist/{chunk-JJEXMHNZ.js → chunk-HUMM4S5I.js} +6 -6
  110. package/dist/{chunk-BIWNRS5I.js → chunk-I2NGDERG.js} +78 -47
  111. package/dist/{chunk-IGOE6KPG.js → chunk-I34CXV2C.js} +185 -11
  112. package/dist/{chunk-DOU52XFZ.js → chunk-I4P72R2F.js} +61 -28
  113. package/dist/{chunk-6U65YB54.js → chunk-I57IH5X6.js} +360 -271
  114. package/dist/{chunk-WYO4L4NU.js → chunk-I5X4WU7U.js} +6 -6
  115. package/dist/{chunk-DXLWZ3BJ.js → chunk-IDFUGYTS.js} +8 -8
  116. package/dist/{chunk-5A4RHEEL.js → chunk-INCFIDCB.js} +2 -2
  117. package/dist/{chunk-RTCZKKG7.js → chunk-IPMPLTEG.js} +3 -3
  118. package/dist/{chunk-QAFQLILX.js → chunk-IPSZDVLI.js} +12 -12
  119. package/dist/{chunk-ZFLBWL2G.js → chunk-J3ZUKQLV.js} +11 -3
  120. package/dist/chunk-J4L64TUA.js +58 -0
  121. package/dist/chunk-JA7AUBHU.js +51 -0
  122. package/dist/chunk-JD3QDLM2.js +50 -0
  123. package/dist/{chunk-4DHYXODN.js → chunk-JF2HM2IF.js} +4 -4
  124. package/dist/{chunk-XEWFVHOT.js → chunk-JGR4X2UA.js} +24 -23
  125. package/dist/chunk-JOG5O2ZH.js +185 -0
  126. package/dist/{chunk-ACY3U2RD.js → chunk-JRXFZB6J.js} +8 -8
  127. package/dist/{chunk-ZWMHL346.js → chunk-JWIAVNEC.js} +20 -19
  128. package/dist/{chunk-MQ6HP2TU.js → chunk-KMBI6IQD.js} +6 -6
  129. package/dist/chunk-KOITA526.js +42 -0
  130. package/dist/chunk-KZ5G3KEN.js +90 -0
  131. package/dist/{chunk-DPH4BS3F.js → chunk-L3KSU4QU.js} +17 -17
  132. package/dist/{chunk-4NWE2KY3.js → chunk-L4WFMAHI.js} +15 -14
  133. package/dist/{chunk-H7CSCA73.js → chunk-LAPVW2F6.js} +5 -5
  134. package/dist/{chunk-SZDOBIWE.js → chunk-LCQIRCOT.js} +55 -10
  135. package/dist/{chunk-ZLBUFK7L.js → chunk-LCWC6NDE.js} +7 -7
  136. package/dist/{chunk-ELR7DEQM.js → chunk-LH52QGNY.js} +34 -9
  137. package/dist/{chunk-WT6EXYEY.js → chunk-LJEEVZIH.js} +138 -22
  138. package/dist/{chunk-EVKDWJ5Y.js → chunk-LKLB5IJ7.js} +5 -5
  139. package/dist/{chunk-VIQHZA53.js → chunk-LP6BFBE5.js} +6 -6
  140. package/dist/{chunk-FIZ5LYL2.js → chunk-LQEMCF43.js} +16 -15
  141. package/dist/{chunk-RO6BE7ZS.js → chunk-LTVOQJKT.js} +7 -7
  142. package/dist/{chunk-C3TBDX7Y.js → chunk-M25UUEKC.js} +26 -25
  143. package/dist/{chunk-PXMV2LLY.js → chunk-M65AZ4ZE.js} +3 -5
  144. package/dist/chunk-MA44TMTL.js +190 -0
  145. package/dist/{chunk-EQMNMG6X.js → chunk-MA73J3E6.js} +13 -13
  146. package/dist/{chunk-P6EJNPFF.js → chunk-MBIJNU3D.js} +951 -409
  147. package/dist/chunk-MIKRDA2P.js +68 -0
  148. package/dist/{chunk-DJBXXYYA.js → chunk-MNOZDE6W.js} +15 -15
  149. package/dist/{chunk-QQAWI5LD.js → chunk-MP7W6OKP.js} +16 -15
  150. package/dist/chunk-MSNEGKI3.js +492 -0
  151. package/dist/{chunk-ZNYSBQIA.js → chunk-MUXYUIBV.js} +6 -6
  152. package/dist/{chunk-VJO7M34N.js → chunk-MZDHFWTN.js} +2 -2
  153. package/dist/{chunk-K3QKOVZN.js → chunk-N5DLB74D.js} +367 -71
  154. package/dist/{chunk-3D74UADA.js → chunk-NGSGJLKW.js} +2 -2
  155. package/dist/{chunk-3KP7OOJ4.js → chunk-NJ5IEZIG.js} +8 -8
  156. package/dist/chunk-NK6JCNJX.js +41 -0
  157. package/dist/{chunk-IYEET4VM.js → chunk-NNRQZUVW.js} +27 -26
  158. package/dist/{chunk-76AHTJVY.js → chunk-NNURP7VO.js} +15 -15
  159. package/dist/{chunk-GFFTVQ7R.js → chunk-NV5S63YK.js} +7 -7
  160. package/dist/{chunk-MKUBDKE2.js → chunk-NWAMUD7B.js} +29 -28
  161. package/dist/{chunk-CTJHEG6A.js → chunk-NWMFVPEP.js} +2 -0
  162. package/dist/{chunk-6EMJ4XFC.js → chunk-NWQ76YQ5.js} +31 -20
  163. package/dist/{chunk-H5BIVULF.js → chunk-O5BUMSB3.js} +10 -10
  164. package/dist/{chunk-IEIHVMM6.js → chunk-O6UC7ASJ.js} +5 -5
  165. package/dist/{chunk-Q3RKXK5Z.js → chunk-OBQL7GX4.js} +28 -27
  166. package/dist/{chunk-NCZS2BN2.js → chunk-OILAH2C7.js} +21 -20
  167. package/dist/{chunk-U3JXMY56.js → chunk-OOZKLLW7.js} +28 -25
  168. package/dist/{chunk-UAYU6K24.js → chunk-ORGB6645.js} +16 -15
  169. package/dist/{chunk-BGOAJFPB.js → chunk-OUALZ5RA.js} +1 -1
  170. package/dist/{chunk-6TZ4YRGJ.js → chunk-OUDGBJC2.js} +16 -9
  171. package/dist/{chunk-W4SMKUAK.js → chunk-OUGTAOGA.js} +2 -2
  172. package/dist/{chunk-7ZBYRMWK.js → chunk-OY2VC2IU.js} +26 -25
  173. package/dist/{chunk-GHST3KAB.js → chunk-OY6H7JX6.js} +5 -5
  174. package/dist/{chunk-KZ4I5M2X.js → chunk-P7H5WZH6.js} +37 -19
  175. package/dist/{chunk-ZA2PWNR3.js → chunk-PCIENCB7.js} +16 -15
  176. package/dist/{chunk-DXBXZNKV.js → chunk-PGAXZLNF.js} +21 -13
  177. package/dist/{chunk-UXVKFOMC.js → chunk-PPKH6ULR.js} +152 -20
  178. package/dist/{chunk-IP6ARMZU.js → chunk-PT77IUYQ.js} +58 -36
  179. package/dist/chunk-PVJZR4JB.js +653 -0
  180. package/dist/chunk-Q7EUPQEG.js +5 -0
  181. package/dist/{chunk-HNNMT5L2.js → chunk-Q7YDUGVZ.js} +1 -1
  182. package/dist/{chunk-MTIRNHRJ.js → chunk-QK3UFHFC.js} +1 -1
  183. package/dist/{chunk-VCXFMXMX.js → chunk-QLT3WYTD.js} +6 -6
  184. package/dist/{chunk-UWBPC5XH.js → chunk-QNXMVJMA.js} +8 -8
  185. package/dist/{chunk-XDLMQL5A.js → chunk-QPAANKUR.js} +7 -7
  186. package/dist/chunk-QQUAEM3U.js +57 -0
  187. package/dist/chunk-QU3ENIJV.js +52 -0
  188. package/dist/{chunk-TPKJD42W.js → chunk-QUFZDWPC.js} +8 -8
  189. package/dist/{chunk-DB3NWAU3.js → chunk-QXSYFB5L.js} +4 -4
  190. package/dist/{chunk-QXCGRQGO.js → chunk-QXXEOH3A.js} +18 -6
  191. package/dist/{chunk-QA4O2GGC.js → chunk-R4TUWD4C.js} +17 -1
  192. package/dist/{chunk-CNEOKSTO.js → chunk-R6KZWNZM.js} +34 -31
  193. package/dist/{chunk-CNT6T2JM.js → chunk-R7NPDUBL.js} +16 -15
  194. package/dist/{chunk-HVWPN2RY.js → chunk-R7VX5BSP.js} +16 -15
  195. package/dist/chunk-RCPWEZD7.js +47 -0
  196. package/dist/{chunk-FOOU5OJE.js → chunk-RDFRB26Z.js} +3 -3
  197. package/dist/{chunk-ISCX25D7.js → chunk-RTHQIGGY.js} +200 -56
  198. package/dist/{chunk-FYCN2Y5P.js → chunk-RX2SMQV3.js} +19 -18
  199. package/dist/{chunk-XIGVTH24.js → chunk-RZEYZOLW.js} +19 -19
  200. package/dist/{chunk-VTR4AC2U.js → chunk-RZYRUXSU.js} +4 -4
  201. package/dist/{chunk-YLXPJWNO.js → chunk-S5O57P5P.js} +17 -16
  202. package/dist/{chunk-CWLXVRFH.js → chunk-S6TLXRBR.js} +7 -7
  203. package/dist/{chunk-MCORC2LG.js → chunk-SF3HXNXR.js} +6 -6
  204. package/dist/{chunk-BSZII65X.js → chunk-SFCFL7Y5.js} +1 -1
  205. package/dist/chunk-SJ2Z3AWF.js +89 -0
  206. package/dist/{chunk-KFZ5IXEZ.js → chunk-SKVLJL2E.js} +28 -27
  207. package/dist/chunk-SMFFUFMN.js +1876 -0
  208. package/dist/{chunk-IDRCBMJF.js → chunk-SP5BWA5H.js} +32 -31
  209. package/dist/chunk-SRIU7L4Z.js +425 -0
  210. package/dist/{chunk-CUTMM4NY.js → chunk-SSYD4XIW.js} +154 -25
  211. package/dist/{chunk-UBEFT3MQ.js → chunk-TFN2N227.js} +6 -6
  212. package/dist/{chunk-YEHSJY6B.js → chunk-TLSL7OII.js} +13 -13
  213. package/dist/{chunk-B7KGNEFI.js → chunk-TM2WY65Q.js} +25 -24
  214. package/dist/{chunk-6P67IUET.js → chunk-TMETWJFO.js} +11 -11
  215. package/dist/{chunk-SRB54QGX.js → chunk-TMMGQBLO.js} +20 -19
  216. package/dist/{chunk-VGGSHDQU.js → chunk-TOSHT6NJ.js} +8 -8
  217. package/dist/{chunk-64LSDT3D.js → chunk-TPKDYSHO.js} +12 -12
  218. package/dist/{chunk-OXCHO2QS.js → chunk-TQISA4VW.js} +26 -23
  219. package/dist/{chunk-NVVEVP5O.js → chunk-TRSNIJNM.js} +7 -7
  220. package/dist/{chunk-TQG2DDWH.js → chunk-TUMHMISE.js} +22 -21
  221. package/dist/{chunk-WM4EMP7T.js → chunk-U36V664P.js} +283 -61
  222. package/dist/{chunk-5UIGGXA5.js → chunk-U4K34CXK.js} +21 -20
  223. package/dist/{chunk-3KIMLBGZ.js → chunk-UDM6HGF4.js} +6 -6
  224. package/dist/{chunk-NMCPIYTF.js → chunk-UDM7LXNJ.js} +7 -7
  225. package/dist/{chunk-ZFEOIYK5.js → chunk-UEUPEUZX.js} +3 -3
  226. package/dist/{chunk-RCLBIJRN.js → chunk-UGJSKAZ2.js} +6 -6
  227. package/dist/{chunk-DS5M2J2H.js → chunk-UMIZYX3U.js} +16 -15
  228. package/dist/{chunk-63572EFC.js → chunk-USYDJY63.js} +21 -19
  229. package/dist/{chunk-V5FT3MZG.js → chunk-UXETN43F.js} +8 -8
  230. package/dist/{chunk-LBBI5P5G.js → chunk-V6BP4XHZ.js} +25 -24
  231. package/dist/chunk-V7DGFWDB.js +55 -0
  232. package/dist/chunk-VGXE7XFO.js +35 -0
  233. package/dist/{chunk-IZIGZ7KY.js → chunk-VSED7FYC.js} +13 -8
  234. package/dist/{chunk-HVOE7ZW2.js → chunk-VTQ55N4O.js} +19 -18
  235. package/dist/{chunk-P6DM2EFI.js → chunk-VVLWEM2Y.js} +6 -6
  236. package/dist/{chunk-YXKCE5BA.js → chunk-VWCNMDMZ.js} +5 -5
  237. package/dist/{chunk-EY3OVHNC.js → chunk-VX5CORDG.js} +24 -23
  238. package/dist/{chunk-XT3ZW7C7.js → chunk-W4SWXJZQ.js} +19 -18
  239. package/dist/{chunk-BV2BZIUF.js → chunk-W5UMEIYG.js} +25 -24
  240. package/dist/{chunk-VPQUFIE7.js → chunk-W6OY2PMB.js} +10 -10
  241. package/dist/chunk-W7NNZFIL.js +52 -0
  242. package/dist/{chunk-6ZDAEUKB.js → chunk-WJWSB65O.js} +1602 -452
  243. package/dist/{chunk-IFQJ3YQE.js → chunk-WNPGLGCJ.js} +5 -5
  244. package/dist/{chunk-MM7JSMLW.js → chunk-WNRIL6JQ.js} +18 -17
  245. package/dist/{chunk-TLBPTUFU.js → chunk-WPZCSFND.js} +20 -19
  246. package/dist/chunk-WTGQJXRJ.js +55 -0
  247. package/dist/{chunk-BEEHCL5O.js → chunk-WTLFRINF.js} +37 -36
  248. package/dist/{chunk-XIJBQM45.js → chunk-X5B7KYPD.js} +507 -20
  249. package/dist/{chunk-GNFZ227W.js → chunk-XIIT4PVT.js} +3 -3
  250. package/dist/{chunk-EECFUQP3.js → chunk-XKWPEY4B.js} +184 -46
  251. package/dist/{chunk-GAJBMPWC.js → chunk-XRNMQZFC.js} +28 -9
  252. package/dist/{chunk-BIAQ6NQS.js → chunk-XRTECHVH.js} +7 -7
  253. package/dist/{chunk-I2EWY3MG.js → chunk-XZY4GTCX.js} +14 -9
  254. package/dist/{chunk-V3M4VFUB.js → chunk-Y6S7VCYN.js} +6 -6
  255. package/dist/{chunk-MY3LDBMR.js → chunk-YAPVAYZN.js} +3 -3
  256. package/dist/{chunk-WH3ZFLXT.js → chunk-YBAJ5SAR.js} +197 -124
  257. package/dist/{chunk-ET7SPOBA.js → chunk-YHS7TSQS.js} +8 -8
  258. package/dist/{chunk-RK5P2DWD.js → chunk-YIGSUTW2.js} +1329 -92
  259. package/dist/{chunk-ANFBBJEV.js → chunk-YPXBGNUV.js} +24 -22
  260. package/dist/{chunk-MZXDSAKW.js → chunk-YRHKEXTP.js} +11 -11
  261. package/dist/{chunk-CPE7HLIK.js → chunk-YTPND655.js} +18 -17
  262. package/dist/{chunk-LTOBNBJ6.js → chunk-YZUOOTC3.js} +27 -26
  263. package/dist/{chunk-F6GRBF5L.js → chunk-Z245SJ64.js} +25 -24
  264. package/dist/{chunk-NP3PG6OI.js → chunk-Z5CIRZNO.js} +157 -89
  265. package/dist/chunk-ZCARJ77R.js +56 -0
  266. package/dist/{chunk-DASVVML7.js → chunk-ZIAMPN7N.js} +6 -6
  267. package/dist/chunk-ZNZYMUBK.js +53 -0
  268. package/dist/{chunk-NECDBPFP.js → chunk-ZOAX7W5S.js} +11 -11
  269. package/dist/{chunk-7IWMRZRI.js → chunk-ZQZRNVNS.js} +83 -40
  270. package/dist/{chunk-PGDVJWCI.js → chunk-ZT6GPGZ4.js} +52 -37
  271. package/dist/{chunk-H26T2LQL.js → chunk-ZW3OEHLT.js} +29 -28
  272. package/dist/files.json +653 -549
  273. package/dist/fixtures/forge/expected/crosscheck.json +726 -0
  274. package/dist/fixtures/forge/slots/README.md +13 -0
  275. package/dist/fixtures/forge/slots/build.json +2686 -0
  276. package/dist/fixtures/forge/slots/crosscheck/forge-ledger.crosscheck.yaml +8 -0
  277. package/dist/fixtures/forge/slots/facts/forge-ledger.jsonl +17 -0
  278. package/dist/fixtures/forge/slots/facts/forge-ledger.meta.json +9 -0
  279. package/dist/fixtures/forge/slots/legacy/joins.json +113 -0
  280. package/dist/fixtures/forge/slots/readers/forge-events.json +306 -0
  281. package/dist/fixtures/forge/slots/readers/forge-gateway.json +238 -0
  282. package/dist/fixtures/forge/slots/readers/forge-infra.json +264 -0
  283. package/dist/fixtures/forge/slots/readers/forge-ledger.json +756 -0
  284. package/dist/fixtures/forge/slots/readers/forge-portal-bff.json +349 -0
  285. package/dist/fixtures/forge/slots/readers/forge-portal-ui.json +214 -0
  286. package/dist/fixtures/forge/slots/readers/forge-reports-job.json +258 -0
  287. package/dist/packages/sdk/npm/index.js +3788 -2939
  288. package/dist/packages/ui/dist/assets/{elk-api-BdXSPeBO.js → elk-api-CPE6PVL8.js} +2 -2
  289. package/dist/packages/ui/dist/assets/index-BYcVqj0l.js +65 -0
  290. package/dist/packages/ui/dist/assets/index-DF52Ejvz.css +1 -0
  291. package/dist/packages/ui/dist/index.html +2 -2
  292. package/package.json +5 -5
  293. package/dist/chunk-24OXGB3P.js +0 -82
  294. package/dist/chunk-3FFIDQQB.js +0 -42
  295. package/dist/chunk-4N5W7LYW.js +0 -41
  296. package/dist/chunk-7NVLGPER.js +0 -45
  297. package/dist/chunk-A6LGX56J.js +0 -52
  298. package/dist/chunk-AHACUPGL.js +0 -46
  299. package/dist/chunk-DG7KYZAL.js +0 -40
  300. package/dist/chunk-DWD6BKHG.js +0 -52
  301. package/dist/chunk-EEVSFGIU.js +0 -50
  302. package/dist/chunk-EN3N6LNU.js +0 -52
  303. package/dist/chunk-FWQDH5NK.js +0 -55
  304. package/dist/chunk-GHCFWIUW.js +0 -38
  305. package/dist/chunk-GSIJWDXH.js +0 -43
  306. package/dist/chunk-HCC5547C.js +0 -232
  307. package/dist/chunk-HLDUWEO7.js +0 -36
  308. package/dist/chunk-K2NQTROJ.js +0 -170
  309. package/dist/chunk-LH4WAJLC.js +0 -45
  310. package/dist/chunk-M5IQUWJR.js +0 -59
  311. package/dist/chunk-MEMEO7YO.js +0 -988
  312. package/dist/chunk-MGNO4Q6V.js +0 -51
  313. package/dist/chunk-MZ6GOFRF.js +0 -55
  314. package/dist/chunk-N2AW2DHF.js +0 -51
  315. package/dist/chunk-N35Y5HZO.js +0 -47
  316. package/dist/chunk-NHFMLMLN.js +0 -257
  317. package/dist/chunk-PR6Z5L7W.js +0 -67
  318. package/dist/chunk-STBJ6SVJ.js +0 -50
  319. package/dist/chunk-U3RGBYXE.js +0 -62
  320. package/dist/chunk-URZKIL37.js +0 -42
  321. package/dist/chunk-W7HNZDHB.js +0 -71
  322. package/dist/chunk-YYZWSVIS.js +0 -33
  323. package/dist/chunk-ZAMSF2DF.js +0 -54
  324. package/dist/packages/ui/dist/assets/index-DRSUhpFi.css +0 -1
  325. package/dist/packages/ui/dist/assets/index-RZe5iotJ.js +0 -63
@@ -4,23 +4,33 @@ 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
- answerAudit,
8
- auditLines,
9
- defaultAuditSeed,
10
- precisionOf,
11
- prepareAudit,
12
- writeAudit
13
- } from "./chunk-KZ4I5M2X.js";
7
+ uiComponentTypeRoutes
8
+ } from "./chunk-523NRKHF.js";
14
9
  import {
15
- uiCiteRoutes
16
- } from "./chunk-DB3NWAU3.js";
17
- import "./chunk-WLA2JZ2K.js";
10
+ changeProblems,
11
+ missingChangeWords
12
+ } from "./chunk-SJ2Z3AWF.js";
18
13
  import {
19
- uiComponentTypeRoutes
20
- } from "./chunk-ZQGFZJH5.js";
14
+ FORCE_STEPS,
15
+ appLines,
16
+ hasKeptResume,
17
+ mapRepoOf
18
+ } from "./chunk-JRXFZB6J.js";
19
+ import {
20
+ allRuns,
21
+ answerOf,
22
+ item,
23
+ listRuns,
24
+ partStates,
25
+ runTranscript
26
+ } from "./chunk-EFDUC35B.js";
27
+ import {
28
+ uiCiteRoutes
29
+ } from "./chunk-QXSYFB5L.js";
30
+ import "./chunk-6ESJWPR3.js";
21
31
  import {
22
32
  conformanceCommand
23
- } from "./chunk-3KIMLBGZ.js";
33
+ } from "./chunk-UDM6HGF4.js";
24
34
  import {
25
35
  outcomeList,
26
36
  outcomeRecord,
@@ -29,38 +39,29 @@ import {
29
39
  releaseNotesCommand,
30
40
  releasePlanCommand,
31
41
  releaseSecurityCommand
32
- } from "./chunk-SDHGFMES.js";
42
+ } from "./chunk-5CIW5RMP.js";
33
43
  import {
34
44
  historyEntry,
35
45
  listHistory
36
- } from "./chunk-GNFZ227W.js";
46
+ } from "./chunk-XIIT4PVT.js";
37
47
  import {
38
- FORCE_STEPS,
39
- appLines,
40
- hasKeptResume,
41
- mapRepoOf
42
- } from "./chunk-ACY3U2RD.js";
43
- import {
44
- allRuns,
45
- answerOf,
46
- item,
47
- listRuns,
48
- partStates,
49
- runTranscript
50
- } from "./chunk-R2FUFBHW.js";
51
- import {
52
- isHandoffStep
53
- } from "./chunk-4Q3NN7VF.js";
48
+ changeArchive,
49
+ changeHandoff,
50
+ changeNew,
51
+ changeReleasePrs,
52
+ changeSync,
53
+ syncAfterManualStep
54
+ } from "./chunk-TQISA4VW.js";
54
55
  import {
55
56
  executorsCheck,
56
57
  todoDone,
57
58
  todoRun,
58
59
  todoShow
59
- } from "./chunk-ZFLBWL2G.js";
60
+ } from "./chunk-J3ZUKQLV.js";
60
61
  import {
61
62
  inputsSha256,
62
63
  loadExecutors
63
- } from "./chunk-RTCZKKG7.js";
64
+ } from "./chunk-IPMPLTEG.js";
64
65
  import {
65
66
  isSandbox,
66
67
  learnCheck,
@@ -68,135 +69,132 @@ import {
68
69
  lessonsFor,
69
70
  readProgress,
70
71
  sandboxCreate
71
- } from "./chunk-KL7UHAOR.js";
72
+ } from "./chunk-6VFR3DYS.js";
72
73
  import {
73
74
  defencesScan,
74
75
  evalRun
75
- } from "./chunk-YIOYKA4V.js";
76
+ } from "./chunk-2AIOOA3U.js";
76
77
  import {
77
78
  listReports,
78
79
  readQuality
79
- } from "./chunk-EQMNMG6X.js";
80
+ } from "./chunk-MA73J3E6.js";
80
81
  import {
81
82
  estimateOf
82
- } from "./chunk-YJBD5NDV.js";
83
+ } from "./chunk-AXJCABA5.js";
83
84
  import {
84
85
  changeMapBody,
85
86
  changeMapOf,
86
87
  targetFlowsOf
87
- } from "./chunk-IEIHVMM6.js";
88
- import {
89
- changeArchive,
90
- changeHandoff,
91
- changeNew,
92
- changeReleasePrs,
93
- changeSync,
94
- syncAfterManualStep
95
- } from "./chunk-OXCHO2QS.js";
96
- import {
97
- boxesOf,
98
- candidatesOf,
99
- uiLinkRoutes
100
- } from "./chunk-2XIIUXGX.js";
101
- import {
102
- matchDone,
103
- quotesOf,
104
- readMatch,
105
- runMatch
106
- } from "./chunk-NQDVD2YR.js";
107
- import "./chunk-3KP7OOJ4.js";
88
+ } from "./chunk-O6UC7ASJ.js";
89
+ import "./chunk-6TXB2WR6.js";
108
90
  import {
109
91
  readServiceRequests
110
- } from "./chunk-DJBXXYYA.js";
111
- import {
112
- initiativeStatus,
113
- readView
114
- } from "./chunk-7JZONWAA.js";
92
+ } from "./chunk-MNOZDE6W.js";
115
93
  import {
116
94
  runDone,
117
95
  taskRun,
118
96
  taskRunNotWaiting
119
- } from "./chunk-CFK6CFXM.js";
97
+ } from "./chunk-3PG6QOQF.js";
120
98
  import {
121
- idFromUrl
122
- } from "./chunk-MQ6HP2TU.js";
123
- import {
124
- DecideError,
125
- correctDecision,
126
- decisionsView,
127
- undoBatch
128
- } from "./chunk-OI32KTDM.js";
129
- import "./chunk-DARX3ATP.js";
130
- import {
131
- copilotAcpAllowed
132
- } from "./chunk-DXBXZNKV.js";
133
- import "./chunk-DOU52XFZ.js";
134
- import "./chunk-BABRMZET.js";
135
- import {
136
- readRepos
137
- } from "./chunk-LHN5UCXD.js";
138
- import {
139
- filesUnder,
140
- memoByFiles,
141
- recheckNow,
142
- uiFactsRoutes
143
- } from "./chunk-ELR7DEQM.js";
144
- import {
145
- safeMessage,
146
- withFileLock
147
- } from "./chunk-BSZII65X.js";
148
- import "./chunk-BIWNRS5I.js";
149
- import {
150
- syncNextOf
151
- } from "./chunk-EHXDB3SA.js";
152
- import "./chunk-W4SMKUAK.js";
153
- import "./chunk-DXLWZ3BJ.js";
154
- import "./chunk-MY3LDBMR.js";
99
+ changeNextStep
100
+ } from "./chunk-2FORECYK.js";
155
101
  import {
156
102
  digestCommand
157
- } from "./chunk-BIAQ6NQS.js";
103
+ } from "./chunk-XRTECHVH.js";
158
104
  import {
159
105
  reconcileCommand
160
- } from "./chunk-4DHYXODN.js";
106
+ } from "./chunk-JF2HM2IF.js";
161
107
  import {
162
108
  sourcesAdd,
163
109
  sourcesSync
164
- } from "./chunk-VGGSHDQU.js";
110
+ } from "./chunk-TOSHT6NJ.js";
165
111
  import {
166
112
  INPUTS_SOURCE_ID
167
- } from "./chunk-F4EGHECF.js";
168
- import "./chunk-HSJKYDHI.js";
113
+ } from "./chunk-EM6DKBTJ.js";
114
+ import {
115
+ boxesOf,
116
+ candidatesOf,
117
+ uiLinkRoutes
118
+ } from "./chunk-A3QZZEJA.js";
169
119
  import {
120
+ DecideError,
121
+ correctDecision,
122
+ decisionsView,
123
+ undoBatch
124
+ } from "./chunk-D566V3T3.js";
125
+ import {
126
+ answerAudit,
127
+ auditLines,
128
+ defaultAuditSeed,
129
+ precisionOf,
130
+ prepareAudit,
131
+ writeAudit
132
+ } from "./chunk-P7H5WZH6.js";
133
+ import {
134
+ readNextState,
170
135
  uiOnboardingRoutes
171
- } from "./chunk-K2NQTROJ.js";
136
+ } from "./chunk-RTHQIGGY.js";
137
+ import "./chunk-DVQCYF3V.js";
138
+ import {
139
+ idFromUrl
140
+ } from "./chunk-KMBI6IQD.js";
172
141
  import "./chunk-X7XVMYIL.js";
173
- import "./chunk-2FTHLB2H.js";
142
+ import {
143
+ matchDone,
144
+ quotesOf,
145
+ readMatch,
146
+ runMatch
147
+ } from "./chunk-7SO6CGJH.js";
148
+ import "./chunk-3TWERSTY.js";
149
+ import "./chunk-NJ5IEZIG.js";
150
+ import {
151
+ copilotAcpAllowed
152
+ } from "./chunk-PGAXZLNF.js";
153
+ import "./chunk-I4P72R2F.js";
154
+ import "./chunk-CLM5Z3R5.js";
155
+ import "./chunk-GZILYRGC.js";
174
156
  import {
175
157
  answersMayHaveChanged,
176
158
  checkoutsStamp,
177
159
  keepAnswersWhileWatched,
178
160
  keptAnswer,
179
161
  uiTrustRoutes
180
- } from "./chunk-EUTZTJIO.js";
162
+ } from "./chunk-4HMOOBIR.js";
181
163
  import {
182
164
  contractCheckOf,
183
165
  estateJoinOnFile,
184
166
  stampOf
185
- } from "./chunk-RBO4A7TC.js";
186
- import "./chunk-ET7SPOBA.js";
187
- import "./chunk-BD7HBZLP.js";
167
+ } from "./chunk-2WPUSHB6.js";
168
+ import "./chunk-YHS7TSQS.js";
169
+ import {
170
+ readRepos
171
+ } from "./chunk-FBNJZ3VH.js";
172
+ import {
173
+ filesUnder,
174
+ memoByFiles,
175
+ recheckNow,
176
+ uiFactsRoutes
177
+ } from "./chunk-LH52QGNY.js";
178
+ import {
179
+ safeMessage,
180
+ withFileLock
181
+ } from "./chunk-SFCFL7Y5.js";
182
+ import "./chunk-I2NGDERG.js";
183
+ import {
184
+ syncNextOf
185
+ } from "./chunk-EHXDB3SA.js";
186
+ import "./chunk-OUGTAOGA.js";
187
+ import "./chunk-IDFUGYTS.js";
188
+ import "./chunk-YAPVAYZN.js";
188
189
  import {
189
190
  MACHINE_CHECKING,
190
191
  baselineCommand,
191
192
  setupSteps
192
- } from "./chunk-VUSYN4R4.js";
193
- import {
194
- doctorChecks
195
- } from "./chunk-XIGVTH24.js";
193
+ } from "./chunk-DNDIT3LD.js";
196
194
  import {
197
195
  readMe,
198
196
  writeMe
199
- } from "./chunk-VJO7M34N.js";
197
+ } from "./chunk-MZDHFWTN.js";
200
198
  import {
201
199
  buildTask,
202
200
  cancelTaskRunWait,
@@ -210,70 +208,68 @@ import {
210
208
  settleTaskPr,
211
209
  stopAllBuilds,
212
210
  taskRunOfRun
213
- } from "./chunk-LY7DOYX2.js";
214
- import "./chunk-V5FT3MZG.js";
215
- import "./chunk-P6DM2EFI.js";
211
+ } from "./chunk-7LOXUBRB.js";
212
+ import "./chunk-UXETN43F.js";
213
+ import "./chunk-VVLWEM2Y.js";
216
214
  import {
217
215
  checkoutOf
218
- } from "./chunk-XDLMQL5A.js";
219
- import "./chunk-PBDIVTFL.js";
216
+ } from "./chunk-QPAANKUR.js";
217
+ import "./chunk-FADIWOA5.js";
220
218
  import {
221
219
  intakeContext
222
- } from "./chunk-XI3GPYP4.js";
220
+ } from "./chunk-44XGOSUU.js";
221
+ import "./chunk-ELZGWEK4.js";
223
222
  import {
224
223
  scanCommand,
225
224
  scanSummaryLines
226
- } from "./chunk-EECFUQP3.js";
227
- import "./chunk-E5NHFHGC.js";
225
+ } from "./chunk-XKWPEY4B.js";
226
+ import "./chunk-FVT6LUOC.js";
228
227
  import {
229
228
  catalogRecords,
230
229
  openChanges,
231
230
  systemGuide
232
- } from "./chunk-FOOU5OJE.js";
231
+ } from "./chunk-RDFRB26Z.js";
232
+ import {
233
+ doctorChecks
234
+ } from "./chunk-RZEYZOLW.js";
233
235
  import {
234
236
  isMetarepo
235
237
  } from "./chunk-3G4YI4ZU.js";
236
- import "./chunk-WT6EXYEY.js";
237
- import "./chunk-2IO6XH37.js";
238
238
  import {
239
239
  workspaceOpen,
240
240
  workspaceSync
241
- } from "./chunk-HWPX3T55.js";
242
- import "./chunk-HNNMT5L2.js";
243
- import "./chunk-7AEB74KW.js";
241
+ } from "./chunk-HPCGQAYH.js";
242
+ import "./chunk-Q7YDUGVZ.js";
243
+ import "./chunk-CPB4XMFI.js";
244
244
  import {
245
245
  readChangeTasks,
246
246
  readStory,
247
247
  setTaskDone
248
- } from "./chunk-DPH4BS3F.js";
249
- import {
250
- ASSISTANT_FORMATS,
251
- readProbes,
252
- whatRunsWhere
253
- } from "./chunk-IBIIKUC7.js";
254
- import {
255
- critic,
256
- criticStats,
257
- findingAction
258
- } from "./chunk-KZH5YV6J.js";
259
- import "./chunk-H5BIVULF.js";
248
+ } from "./chunk-L3KSU4QU.js";
260
249
  import {
261
250
  planStories,
262
251
  snowDraft,
263
252
  snowSubmit
264
- } from "./chunk-IZIGZ7KY.js";
265
- import "./chunk-RQM5Y3HJ.js";
253
+ } from "./chunk-VSED7FYC.js";
254
+ import "./chunk-4UVTNHA6.js";
266
255
  import {
267
256
  ciArchiveGate
268
- } from "./chunk-JLTJAOO4.js";
257
+ } from "./chunk-DDRTAEFZ.js";
269
258
  import {
270
259
  traceMatrix
271
- } from "./chunk-SAPX3PVK.js";
260
+ } from "./chunk-4BK5EJ2C.js";
272
261
  import "./chunk-MUWDB4R4.js";
273
- import "./chunk-VOGCSYOI.js";
274
262
  import {
275
263
  archiveGate
276
- } from "./chunk-YEHSJY6B.js";
264
+ } from "./chunk-TLSL7OII.js";
265
+ import "./chunk-3XNE6XXF.js";
266
+ import "./chunk-LJEEVZIH.js";
267
+ import "./chunk-3BQDBTQJ.js";
268
+ import "./chunk-HOEZQRZU.js";
269
+ import {
270
+ initiativeStatus,
271
+ readView
272
+ } from "./chunk-23OQZY5Z.js";
277
273
  import {
278
274
  CORRECTIONS_FILE,
279
275
  FEATURE_FILE,
@@ -323,24 +319,46 @@ import {
323
319
  syncWorkItems,
324
320
  threadReplies,
325
321
  writeSketch
326
- } from "./chunk-CSHJZFOE.js";
322
+ } from "./chunk-DTW37FJ6.js";
327
323
  import {
328
324
  FeaturePlacement,
329
325
  STAGES,
330
326
  STAGE_PHASE,
331
327
  fieldNames,
332
328
  rerunOf
333
- } from "./chunk-5A4RHEEL.js";
329
+ } from "./chunk-INCFIDCB.js";
334
330
  import {
335
331
  HttpError,
336
332
  badRequest,
337
333
  conflict,
334
+ intParam,
338
335
  notFound,
339
336
  problem,
340
337
  requireConfirmation,
341
338
  startServer,
342
339
  strParam
343
- } from "./chunk-2SCZZQNQ.js";
340
+ } from "./chunk-6GX3OFEZ.js";
341
+ import {
342
+ addressRefusal,
343
+ asTheApp,
344
+ recordConfirmedAddress,
345
+ requireConfirmedModel,
346
+ servingTheApp,
347
+ whereKeyGoes
348
+ } from "./chunk-OY6H7JX6.js";
349
+ import "./chunk-4XK3HLOH.js";
350
+ import {
351
+ ASSISTANT_FORMATS,
352
+ readProbes,
353
+ whatRunsWhere
354
+ } from "./chunk-G33UIUG3.js";
355
+ import {
356
+ critic,
357
+ criticStats,
358
+ findingAction
359
+ } from "./chunk-CWJDZ5VP.js";
360
+ import "./chunk-O5BUMSB3.js";
361
+ import "./chunk-VOGCSYOI.js";
344
362
  import {
345
363
  layerRules,
346
364
  loadConstitution,
@@ -353,11 +371,12 @@ import {
353
371
  readStoryIndex,
354
372
  reviewedGates,
355
373
  roundsOf
356
- } from "./chunk-VIQHZA53.js";
374
+ } from "./chunk-LP6BFBE5.js";
357
375
  import {
358
376
  ChangeOwnersError,
359
377
  artifactFiles,
360
378
  artifactPhase,
379
+ artifactWritten,
361
380
  changeFolder,
362
381
  changeReport,
363
382
  changeSize,
@@ -366,6 +385,7 @@ import {
366
385
  handoffBranchPushed,
367
386
  liveHandoff,
368
387
  loadChangeContext,
388
+ personWrittenPlanning,
369
389
  pushHandoffBranch,
370
390
  readTaskDecision,
371
391
  recordTaskDecision,
@@ -373,30 +393,8 @@ import {
373
393
  setChangeOwners,
374
394
  unmergedTaskBranches,
375
395
  unmergedTaskWords
376
- } from "./chunk-WH3ZFLXT.js";
377
- import "./chunk-UTZMF5CV.js";
378
- import {
379
- fileStepStore,
380
- manualAdapter,
381
- stepOfProvisional
382
- } from "./chunk-6U65YB54.js";
383
- import "./chunk-SZDOBIWE.js";
384
- import {
385
- addressRefusal,
386
- asTheApp,
387
- recordConfirmedAddress,
388
- requireConfirmedModel,
389
- servingTheApp,
390
- whereKeyGoes
391
- } from "./chunk-GHST3KAB.js";
392
- import "./chunk-KVVNAUIG.js";
393
- import {
394
- COMMON_SETTINGS,
395
- PROVIDER_SETTINGS,
396
- defaultKeyStore,
397
- keyEnvFromEnvironment,
398
- looksLikeKey
399
- } from "./chunk-5JGRF53S.js";
396
+ } from "./chunk-YBAJ5SAR.js";
397
+ import "./chunk-23TTURB2.js";
400
398
  import {
401
399
  componentRenames,
402
400
  estateFacts,
@@ -406,16 +404,18 @@ import {
406
404
  joinReposOf,
407
405
  keepCatalogsInMemory,
408
406
  outsideProfileSystems,
407
+ promotedStates,
409
408
  readCatalog,
409
+ readCrossCheck,
410
410
  targetPicker
411
- } from "./chunk-2HDNOUJU.js";
411
+ } from "./chunk-6H62UHY5.js";
412
412
  import {
413
413
  NoSuchNode,
414
414
  buildEstate,
415
415
  focusView,
416
416
  nodeView,
417
417
  viewKey
418
- } from "./chunk-RK5P2DWD.js";
418
+ } from "./chunk-YIGSUTW2.js";
419
419
  import {
420
420
  OrgPackProposal,
421
421
  SNAPSHOT_FILE,
@@ -439,29 +439,42 @@ import {
439
439
  snapshotDates,
440
440
  snapshotSources,
441
441
  writeReview
442
- } from "./chunk-K3QKOVZN.js";
443
- import {
444
- readServiceRequestExports,
445
- readVendorSpec,
446
- readWorkItemExports
447
- } from "./chunk-QAFQLILX.js";
448
- import "./chunk-HQMLY2R6.js";
449
- import "./chunk-I2EWY3MG.js";
450
- import "./chunk-UFIQ5FWY.js";
451
- import "./chunk-MTIRNHRJ.js";
452
- import "./chunk-DHQXCP2X.js";
442
+ } from "./chunk-N5DLB74D.js";
443
+ import "./chunk-4NPWOUI2.js";
453
444
  import {
454
- batchSections,
455
- providerFactoryFor
456
- } from "./chunk-ZDA72732.js";
457
- import "./chunk-QA4O2GGC.js";
445
+ fileStepStore,
446
+ manualAdapter,
447
+ stepOfProvisional
448
+ } from "./chunk-I57IH5X6.js";
449
+ import "./chunk-LCQIRCOT.js";
458
450
  import {
459
451
  baseClonePath,
460
452
  changeWorktreesDir,
461
453
  cloneUrlKey,
462
454
  loadRepos,
463
455
  readChangeRepos
464
- } from "./chunk-XIJBQM45.js";
456
+ } from "./chunk-X5B7KYPD.js";
457
+ import {
458
+ COMMON_SETTINGS,
459
+ PROVIDER_SETTINGS,
460
+ defaultKeyStore,
461
+ keyEnvFromEnvironment,
462
+ looksLikeKey
463
+ } from "./chunk-GZSOZYEP.js";
464
+ import {
465
+ readServiceRequestExports,
466
+ readVendorSpec,
467
+ readWorkItemExports
468
+ } from "./chunk-IPSZDVLI.js";
469
+ import {
470
+ batchSections,
471
+ providerFactoryFor
472
+ } from "./chunk-2MRYL45Z.js";
473
+ import "./chunk-ELJ5Q4J2.js";
474
+ import "./chunk-XZY4GTCX.js";
475
+ import "./chunk-3M3MDBOG.js";
476
+ import "./chunk-QK3UFHFC.js";
477
+ import "./chunk-3PBIZBWN.js";
465
478
  import {
466
479
  ADAPTER_FIELDS,
467
480
  ADAPTER_KINDS,
@@ -499,6 +512,7 @@ import {
499
512
  factsDirOf,
500
513
  factsFileOf,
501
514
  factsRelOf,
515
+ headFromFiles,
502
516
  inEol,
503
517
  inputsDirOf,
504
518
  isAdopted,
@@ -533,19 +547,22 @@ import {
533
547
  specRepos,
534
548
  undeclareLink,
535
549
  writeOrgPackFile
536
- } from "./chunk-6ZDAEUKB.js";
550
+ } from "./chunk-WJWSB65O.js";
537
551
  import {
538
552
  FileChangedError,
539
553
  RUN_LOG_READ_MAX,
540
554
  createLog,
555
+ isMetarepoRoot,
556
+ onAtticusSignal,
541
557
  printToCurrent,
542
558
  readTerminalRunLines,
543
559
  readTerminalRuns,
560
+ redactText,
544
561
  runLogsDirOf,
545
562
  tailTerminalRunLines,
546
563
  writeFileAtomic,
547
564
  writeFileIfUnchanged
548
- } from "./chunk-MEMEO7YO.js";
565
+ } from "./chunk-SMFFUFMN.js";
549
566
  import {
550
567
  ASSISTANTS,
551
568
  ChangeArtifact,
@@ -566,18 +583,23 @@ import {
566
583
  decideOf,
567
584
  external_exports,
568
585
  gateRoundLimit,
586
+ hostMatches,
569
587
  joinConventions,
570
588
  knowledgeKindOf,
571
589
  loadOrgPack,
572
590
  pageStanding
573
- } from "./chunk-LZFKJ2BR.js";
591
+ } from "./chunk-A3LVMCA5.js";
574
592
  import {
575
593
  keptFilesMayHaveChanged,
576
594
  trustKeptFiles
577
- } from "./chunk-CTJHEG6A.js";
595
+ } from "./chunk-NWMFVPEP.js";
578
596
  import {
579
597
  require_dist
580
598
  } from "./chunk-BQGDB6ZL.js";
599
+ import "./chunk-R4TUWD4C.js";
600
+ import {
601
+ isHandoffStep
602
+ } from "./chunk-4Q3NN7VF.js";
581
603
  import {
582
604
  __toESM
583
605
  } from "./chunk-TV45EUGM.js";
@@ -609,11 +631,20 @@ function tracked(ctx, title, work, o = {}) {
609
631
  const jobs = ctx.jobs;
610
632
  if (!jobs || typeof jobs.track !== "function")
611
633
  return work();
612
- const opts = { title, ...o.meta ? { meta: o.meta } : {} };
634
+ const opts = {
635
+ title,
636
+ ...o.meta ? { meta: o.meta } : {},
637
+ // Beta.27 re-review: the run log is titled by the ids it names, never by `title`.
638
+ ...o.ids ? { log: { ids: o.ids } } : {}
639
+ };
613
640
  return ctx.jobs.track(o.kind ?? "work", (c) => work(c), opts);
614
641
  }
615
642
  function answerAsJob(ctx, title, work, o = {}) {
616
- const opts = { title, ...o.meta ? { meta: o.meta } : {} };
643
+ const opts = {
644
+ title,
645
+ ...o.meta ? { meta: o.meta } : {},
646
+ ...o.ids ? { log: { ids: o.ids } } : {}
647
+ };
617
648
  const job = ctx.jobs.start(o.kind ?? "work", async () => {
618
649
  try {
619
650
  const answer = await work();
@@ -648,7 +679,7 @@ async function trackedLocal(ctx, title, work, o = {}) {
648
679
  return tracked(ctx, title, (c) => {
649
680
  c?.progress(0, 1, title);
650
681
  return work(c);
651
- }, { kind: "local", ...o.meta ? { meta: o.meta } : {} });
682
+ }, { kind: "local", ...o.meta ? { meta: o.meta } : {}, ...o.ids ? { ids: o.ids } : {} });
652
683
  }
653
684
  var jobState = (j) => j.state === "queued" ? "running" : j.state;
654
685
  var PREPARED_MS = 15 * 60 * 1e3;
@@ -704,6 +735,8 @@ function readHandoffRuns(root, now) {
704
735
  return out.sort((a, b) => b.startedAt.localeCompare(a.startedAt)).slice(0, HANDOFF_MAX);
705
736
  }
706
737
  var handoffState = (s) => s === "validated" ? "done" : s === "failed" ? "failed" : s === "cancelled" ? "cancelled" : "waiting";
738
+ var APP_KINDS = new Set(api_exports.ActivityKind.options);
739
+ var appKind = (t) => t.startedBy === "app" && t.job && APP_KINDS.has(t.job.kind) ? t.job.kind : t.startedBy === "app" ? "work" : void 0;
707
740
  var newestFirst = (a, b) => b.startedAt.localeCompare(a.startedAt) || b.id.localeCompare(a.id);
708
741
  function newestKeepingRunning(entries, max) {
709
742
  const running = entries.filter((e) => e.state === "running");
@@ -714,6 +747,7 @@ function uiActivityRoutes(r, ctx, deps = {}) {
714
747
  const root = ctx.root;
715
748
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
716
749
  const readOpts = { ...deps.alive ? { alive: deps.alive } : {}, now };
750
+ const fromLog = (t) => !(t.startedBy === "app" && ctx.jobs.ownsRun?.(t.runId));
717
751
  const jobEntry = (j) => {
718
752
  const meta = ctx.jobs.metaOf(j.id) ?? {};
719
753
  const lines = ctx.jobs.linesOf(j.id);
@@ -744,16 +778,21 @@ function uiActivityRoutes(r, ctx, deps = {}) {
744
778
  lines: lines?.total ?? 0,
745
779
  from: lines?.from ?? 0,
746
780
  ...j.state === "running" ? { stop: `/api/jobs/${encodeURIComponent(j.id)}/cancel` } : {},
747
- ...meta.handoffRun ? { runId: meta.handoffRun } : {}
781
+ ...j.state === "running" && j.stopping ? { stopping: true } : {},
782
+ ...meta.handoffRun ? { runId: meta.handoffRun } : {},
783
+ // Beta.27 review: a job that ended by refusing (a scan's safety stop) wrote nothing.
784
+ ...j.state === "done" && j.result?.refused ? { outcome: "refused" } : {}
748
785
  };
749
786
  };
750
787
  const tails = /* @__PURE__ */ new Map();
751
788
  const terminalEntry = (t, total) => ({
752
789
  id: `${TERM}${t.runId}`,
753
- kind: "command",
790
+ // Beta.27 review: a job an earlier run of the app started, kept in the run log, by its kind;
791
+ // one still running when that app closed (or crashed) has `ended`.
792
+ kind: appKind(t) ?? "command",
754
793
  title: t.title,
755
794
  where: t.startedBy,
756
- state: t.stale ? "ended" : t.state,
795
+ state: t.stale || t.appClosed ? "ended" : t.state,
757
796
  startedAt: t.startedAt,
758
797
  ...t.finishedAt ? { finishedAt: t.finishedAt } : {},
759
798
  ...t.exitCode !== void 0 ? { exitCode: t.exitCode } : {},
@@ -773,13 +812,13 @@ function uiActivityRoutes(r, ctx, deps = {}) {
773
812
  const tick = () => {
774
813
  let runs;
775
814
  try {
776
- runs = readTerminalRuns(root, readOpts);
815
+ runs = readTerminalRuns(root, readOpts).filter(fromLog);
777
816
  } catch {
778
817
  return;
779
818
  }
780
819
  for (const t of runs) {
781
820
  const was = tails.get(t.runId);
782
- const state = t.stale ? "ended" : t.state;
821
+ const state = t.stale || t.appClosed ? "ended" : t.state;
783
822
  const { size, ino } = logStat(t.runId);
784
823
  if (was && !was.more && was.state === state && was.size === size && was.ino === ino)
785
824
  continue;
@@ -956,7 +995,7 @@ function uiActivityRoutes(r, ctx, deps = {}) {
956
995
  tick();
957
996
  const entries = [
958
997
  ...ctx.jobs.list().map(jobEntry),
959
- ...readTerminalRuns(root, readOpts).map((t) => terminalEntry(t)),
998
+ ...readTerminalRuns(root, readOpts).filter(fromLog).map((t) => terminalEntry(t)),
960
999
  ...handoffEntries()
961
1000
  ];
962
1001
  const kept = newestKeepingRunning(entries, MAX_ENTRIES);
@@ -969,7 +1008,7 @@ function uiActivityRoutes(r, ctx, deps = {}) {
969
1008
  const l2 = t ? readTerminalRunLines(root, runId, from) : void 0;
970
1009
  if (!t || !l2)
971
1010
  throw notFound(`There is no activity ${id}.`);
972
- return { id, ...l2, state: t.stale ? "ended" : t.state };
1011
+ return { id, ...l2, state: t.stale || t.appClosed ? "ended" : t.state };
973
1012
  }
974
1013
  if (RUN_DIR.test(id)) {
975
1014
  handoffCache = void 0;
@@ -1033,19 +1072,19 @@ async function changesWithWorktrees(root) {
1033
1072
  function uiStepRoutes(r, ctx, asJob) {
1034
1073
  const root = ctx.root;
1035
1074
  return r.add("POST", "/api/facts/apply-all", async () => {
1036
- const { verifyAllCommand } = await import("./chunk-7NVLGPER.js");
1075
+ const { verifyAllCommand } = await import("./chunk-3NGHSBVS.js");
1037
1076
  return asJob("Applying to every repo", () => captured((io) => verifyAllCommand(root, { write: true, verbose: false, json: false }, io)));
1038
1077
  }).add("POST", "/api/estate/join", async () => {
1039
- const { estateJoin } = await import("./chunk-DB6TDJ4T.js");
1078
+ const { estateJoin } = await import("./chunk-5YX7MJWW.js");
1040
1079
  return asJob("Joining the estate's flows", () => captured((io) => estateJoin(root, { json: false }, io)));
1041
1080
  }).add("POST", "/api/knowledge/sources/sync", async () => {
1042
- const { sourcesSync: sourcesSync2 } = await import("./chunk-CPE7HLIK.js");
1081
+ const { sourcesSync: sourcesSync2 } = await import("./chunk-YTPND655.js");
1043
1082
  return asJob("Syncing every wiki", () => captured((io) => sourcesSync2(root, io, { json: false })));
1044
1083
  }).add("POST", "/api/workspace/prune", async ({ body }) => {
1045
1084
  const change = body?.change;
1046
1085
  if (change !== void 0 && (typeof change !== "string" || !ID2.test(change)))
1047
1086
  throw badRequest("change is a change id, or left out for every change with worktrees.");
1048
- const { workspacePrune } = await import("./chunk-M5IQUWJR.js");
1087
+ const { workspacePrune } = await import("./chunk-G4TFQ4EG.js");
1049
1088
  return asJob(change ? `Cleaning up ${change}'s worktrees` : "Cleaning up worktrees", () => captured(async (io) => {
1050
1089
  const list = change ? [change] : await changesWithWorktrees(root);
1051
1090
  if (!list.length) {
@@ -1060,7 +1099,7 @@ function uiStepRoutes(r, ctx, asJob) {
1060
1099
  return code;
1061
1100
  }));
1062
1101
  }).add("GET", "/api/changes/{changeId}/tasks/{taskId}/context", async ({ params }) => {
1063
- const { taskContextCli } = await import("./chunk-7ZBYRMWK.js");
1102
+ const { taskContextCli } = await import("./chunk-OY2VC2IU.js");
1064
1103
  const lines = [];
1065
1104
  const errs = [];
1066
1105
  const code = await taskContextCli(root, params.changeId, params.taskId, { markdown: true }, { out: (l) => lines.push(l), err: (l) => errs.push(l) });
@@ -1071,13 +1110,244 @@ function uiStepRoutes(r, ctx, asJob) {
1071
1110
  const on = body?.on;
1072
1111
  if (typeof on !== "boolean")
1073
1112
  throw badRequest("on is true or false.");
1074
- const { setLocalRecording } = await import("./chunk-V3M4VFUB.js");
1113
+ const { setLocalRecording } = await import("./chunk-Y6S7VCYN.js");
1075
1114
  await setLocalRecording(root, on);
1076
1115
  ctx.events.publish({ type: "file.changed", path: ".atticus/me.yaml" });
1077
1116
  return { status: 200, body: { on } };
1078
1117
  });
1079
1118
  }
1080
1119
 
1120
+ // packages/cli/dist/ui-api-catalog.js
1121
+ var REPO = /^[a-z0-9][a-z0-9._-]{0,99}$/i;
1122
+ var PROMOTE_REFUSED = 3;
1123
+ function parse(schema, body) {
1124
+ const r = schema.safeParse(body ?? {});
1125
+ if (!r.success)
1126
+ throw badRequest("Some fields aren't right.", {
1127
+ errors: r.error.issues.map((i) => ({ path: i.path.join("."), message: i.message }))
1128
+ });
1129
+ return r.data;
1130
+ }
1131
+ async function headOf(root, repo) {
1132
+ try {
1133
+ return await headFromFiles(isAdopted(root) ? root : baseClonePath(root, repo));
1134
+ } catch {
1135
+ return void 0;
1136
+ }
1137
+ }
1138
+ function coalesced(work) {
1139
+ let running;
1140
+ let next;
1141
+ const start = () => {
1142
+ const p = work();
1143
+ running = p;
1144
+ const done = () => {
1145
+ if (running === p)
1146
+ running = void 0;
1147
+ };
1148
+ p.then(done, done);
1149
+ return p;
1150
+ };
1151
+ return () => {
1152
+ if (next)
1153
+ return next;
1154
+ if (!running)
1155
+ return start();
1156
+ const after = running.then(() => void 0, () => void 0);
1157
+ const n = after.then(() => {
1158
+ next = void 0;
1159
+ return start();
1160
+ });
1161
+ next = n;
1162
+ return n;
1163
+ };
1164
+ }
1165
+ function uiCatalogRoutes(r, ctx, asJob) {
1166
+ const root = ctx.root;
1167
+ const buildViewNow = coalesced(async () => (await import("./chunk-B4WPO6FX.js")).catalogBuildView(root));
1168
+ const repoOf2 = (params) => {
1169
+ const repo = params.repo ?? "";
1170
+ if (!REPO.test(repo))
1171
+ throw badRequest("repo is a repo id, as the manifests name it.");
1172
+ return repo;
1173
+ };
1174
+ return r.add("GET", "/api/crosscheck", async () => {
1175
+ const v = await readCrossCheck(root);
1176
+ const repos = await Promise.all(v.repos.map(async (x) => {
1177
+ const head = await headOf(root, x.repo);
1178
+ return { ...x, items: [], ...head ? { head } : {} };
1179
+ }));
1180
+ return { status: 200, body: api_exports.CrossCheckView.parse({ ...v, repos }) };
1181
+ }).add("GET", "/api/crosscheck/{repo}", async ({ params }) => {
1182
+ const repo = repoOf2(params);
1183
+ const v = await readCrossCheck(root, { repo });
1184
+ const one = v.repos[0];
1185
+ if (!one)
1186
+ throw notFound(`${repo} isn't a repo the manifests list.`);
1187
+ const head = await headOf(root, repo);
1188
+ const promoted = await promotedStates(root, repo, one.items.filter((i) => i.state === "readers-only").map((i) => i.key));
1189
+ const { readersValueSha } = await import("./chunk-JOG5O2ZH.js");
1190
+ const items = one.items.map((i) => {
1191
+ const p = i.state === "readers-only" ? promoted.get(i.key) : void 0;
1192
+ const sha5 = i.state === "readers-only" || i.state === "disagree" ? { readersSha256: readersValueSha(i.readers?.value) } : {};
1193
+ return { ...i, ...sha5, ...p ? { promoted: p } : {} };
1194
+ });
1195
+ return {
1196
+ status: 200,
1197
+ body: api_exports.RepoCrossCheck.parse({ ...one, items, ...head ? { head } : {} })
1198
+ };
1199
+ }).add("GET", "/api/crosscheck/{repo}/promote", async ({ params, query }) => {
1200
+ const repo = repoOf2(params);
1201
+ const key = (query.get("key") ?? "").trim();
1202
+ if (!key || key.length > 500)
1203
+ throw badRequest("key is the item's key, as the cross-check names it.");
1204
+ const v = await readCrossCheck(root, { repo });
1205
+ if (!v.repos[0])
1206
+ throw notFound(`${repo} isn't a repo the manifests list.`);
1207
+ const { planPromote } = await import("./chunk-MSNEGKI3.js");
1208
+ const { checkoutLineOf } = await import("./chunk-JOG5O2ZH.js");
1209
+ const { next: _next, ...plan } = await planPromote(root, repo, key, {
1210
+ lineOf: checkoutLineOf(root, repo)
1211
+ });
1212
+ void _next;
1213
+ return { status: 200, body: api_exports.CrossCheckPromoteView.parse(plan) };
1214
+ }).add("POST", "/api/crosscheck/{repo}/promote", async ({ params, body }) => {
1215
+ const repo = repoOf2(params);
1216
+ const b = parse(api_exports.CrossCheckPromoteRequest, body);
1217
+ const v = await readCrossCheck(root, { repo });
1218
+ if (!v.repos[0])
1219
+ throw notFound(`${repo} isn't a repo the manifests list.`);
1220
+ const { planPromote } = await import("./chunk-MSNEGKI3.js");
1221
+ const { catalogCrossCheck, checkoutLineOf } = await import("./chunk-JOG5O2ZH.js");
1222
+ const plan = await planPromote(root, repo, b.key, { lineOf: checkoutLineOf(root, repo) });
1223
+ if (!plan.can)
1224
+ throw conflict(`${b.key} can't be promoted now: ${plan.why}. Nothing written.`);
1225
+ if (plan.sha256 !== b.sha256)
1226
+ throw conflict(`The fact promoting ${b.key} writes isn't the one the page showed any more. Nothing written: look at it again.`);
1227
+ const { verifyCommand } = await import("./chunk-3NGHSBVS.js");
1228
+ return asJob(`Promote on ${repo}`, () => captured(async (io) => {
1229
+ const code = await catalogCrossCheck(root, { repo, promote: b.key, expect: b.sha256 }, io);
1230
+ if (code !== 0)
1231
+ return PROMOTE_REFUSED;
1232
+ return verifyCommand(root, repo, { write: false, verbose: false, json: false }, io);
1233
+ }));
1234
+ }).add("POST", "/api/crosscheck/{repo}/dismiss", async ({ params, body }) => {
1235
+ const repo = repoOf2(params);
1236
+ const b = parse(api_exports.CrossCheckDismissRequest, body);
1237
+ const v = await readCrossCheck(root, { repo });
1238
+ const one = v.repos[0];
1239
+ if (!one)
1240
+ throw notFound(`${repo} isn't a repo the manifests list.`);
1241
+ const { catalogCrossCheck, readersValueSha } = await import("./chunk-JOG5O2ZH.js");
1242
+ const item2 = one.items.find((i) => i.key === b.key);
1243
+ if (b.undo) {
1244
+ if (!item2?.dismissed)
1245
+ throw notFound(`${b.key} isn't dismissed on ${repo}.`);
1246
+ } else {
1247
+ if (!item2 || item2.state === "agree" || item2.state === "facts-only")
1248
+ throw notFound(`${b.key} isn't an item the readers found or disagree on, on ${repo}.`);
1249
+ if (b.sha256 === void 0)
1250
+ throw badRequest("sha256 is the item's readersSha256, as the page showed it.");
1251
+ if (readersValueSha(item2.readers?.value) !== b.sha256)
1252
+ throw conflict(`The readers say another value for ${b.key} than the page showed. Nothing written: look at it again.`);
1253
+ }
1254
+ return asJob(b.undo ? `List again on ${repo}` : `Dismiss on ${repo}`, () => captured((io) => catalogCrossCheck(root, {
1255
+ repo,
1256
+ ...b.undo ? { undismiss: b.key } : { dismiss: b.key, expect: b.sha256 }
1257
+ }, io)));
1258
+ }).add("GET", "/api/build", async () => {
1259
+ return { status: 200, body: api_exports.CatalogBuildView.parse(await buildViewNow()) };
1260
+ }).add("POST", "/api/build", async ({ body }) => {
1261
+ const b = parse(api_exports.CatalogBuildRequest, body);
1262
+ const counted = b.allowRemovals !== void 0 || b.discardEdits !== void 0;
1263
+ if (counted && b.plan === void 0)
1264
+ throw badRequest("plan is GET /api/build's pending.plan for the list being confirmed.");
1265
+ if (b.plan !== void 0) {
1266
+ const { catalogBuildView } = await import("./chunk-B4WPO6FX.js");
1267
+ if ((await catalogBuildView(root)).pending.plan !== b.plan)
1268
+ throw conflict("What the build would remove or discard isn't what the page listed any more. Nothing written: look at the list again.");
1269
+ }
1270
+ const { catalogBuild } = await import("./chunk-PVJZR4JB.js");
1271
+ const flags = [
1272
+ ...b.allowRemovals !== void 0 ? [`--allow-removals ${b.allowRemovals}`] : [],
1273
+ ...b.discardEdits !== void 0 ? [`--discard-edits ${b.discardEdits}`] : []
1274
+ ];
1275
+ return asJob(["atticus catalog build", ...flags].join(" "), () => captured((io) => catalogBuild(root, {
1276
+ ...b.allowRemovals !== void 0 ? { allowRemovals: b.allowRemovals } : {},
1277
+ ...b.discardEdits !== void 0 ? { discardEdits: b.discardEdits } : {},
1278
+ ...b.plan !== void 0 ? { plan: b.plan } : {}
1279
+ }, io)));
1280
+ }).add("POST", "/api/build/edits/curate", async ({ body }) => {
1281
+ const b = parse(api_exports.CatalogEditsRequest, body);
1282
+ const { catalogBuildView } = await import("./chunk-B4WPO6FX.js");
1283
+ const view3 = await catalogBuildView(root);
1284
+ const now = view3.pending.refused;
1285
+ const edits = now?.reasons.includes("hand-edits") ? now.edits ?? [] : [];
1286
+ if (edits.length !== b.count || view3.pending.plan !== b.plan)
1287
+ throw conflict(edits.length !== b.count ? `The page listed ${b.count} hand ${b.count === 1 ? "edit" : "edits"}; there ${edits.length === 1 ? "is" : "are"} ${edits.length} now. Nothing was made curated: look at the list again.` : "The hand edits aren't the ones the page listed any more. Nothing was made curated: look at the list again.");
1288
+ const { catalogBuild, catalogEdits } = await import("./chunk-PVJZR4JB.js");
1289
+ return asJob("Make the hand edits curated, then build", () => captured(async (io) => {
1290
+ const code = await catalogEdits(root, { curate: true, by: ctx.user, plan: b.plan }, io);
1291
+ return code === 0 ? catalogBuild(root, {}, io) : code;
1292
+ }));
1293
+ }).add("GET", "/api/build/undo", async ({ query }) => {
1294
+ const n = intParam(query, "n", 1, 1e6);
1295
+ const { catalogUndoView } = await import("./chunk-B4WPO6FX.js");
1296
+ return {
1297
+ status: 200,
1298
+ body: api_exports.CatalogUndoView.parse(await catalogUndoView(root, n))
1299
+ };
1300
+ }).add("POST", "/api/build/undo", async ({ body }) => {
1301
+ const b = parse(api_exports.CatalogUndoRequest, body);
1302
+ const { catalogUndoView } = await import("./chunk-B4WPO6FX.js");
1303
+ const v = await catalogUndoView(root, b.n);
1304
+ if (!v.plan)
1305
+ throw conflict(v.problem ?? `There are fewer than ${b.n} builds to undo here.`);
1306
+ if (v.plan.files.length !== b.files)
1307
+ throw conflict(`The page listed ${b.files} ${b.files === 1 ? "file" : "files"} to put back; taking back the ${b.n === 1 ? "latest build" : `${b.n} latest builds`} puts back ${v.plan.files.length} now. Nothing was undone: look at the list again.`);
1308
+ if (v.plan.hash !== b.plan)
1309
+ throw conflict("The builds to take back or their files aren't the ones the page listed any more. Nothing was undone: look at the list again.");
1310
+ const { catalogUndo } = await import("./chunk-PVJZR4JB.js");
1311
+ return asJob(`atticus catalog undo ${b.n} --yes`, () => captured((io) => catalogUndo(root, { n: b.n, yes: true, plan: b.plan }, io)));
1312
+ }).add("GET", "/api/build/prune", async () => {
1313
+ const { catalogPruneView } = await import("./chunk-B4WPO6FX.js");
1314
+ return {
1315
+ status: 200,
1316
+ body: api_exports.CatalogPruneView.parse(await catalogPruneView(root))
1317
+ };
1318
+ }).add("POST", "/api/build/prune", async ({ body }) => {
1319
+ const b = parse(api_exports.CatalogPruneRequest, body);
1320
+ const { catalogPruneView } = await import("./chunk-B4WPO6FX.js");
1321
+ const v = await catalogPruneView(root);
1322
+ if (v.files.length !== b.count)
1323
+ throw conflict(`The page listed ${b.count} ${b.count === 1 ? "file" : "files"} to remove; there ${v.files.length === 1 ? "is" : "are"} ${v.files.length} now. Nothing was removed: look at the list again.`);
1324
+ if (v.plan !== b.plan)
1325
+ throw conflict("The files to remove aren't the ones the page listed any more. Nothing was removed: look at the list again.");
1326
+ const { catalogPrune } = await import("./chunk-PVJZR4JB.js");
1327
+ return asJob("atticus catalog prune --yes", () => captured((io) => catalogPrune(root, { yes: true, plan: b.plan }, io)));
1328
+ }).add("GET", "/api/build/upgrade", async () => {
1329
+ const { catalogUpgradeView } = await import("./chunk-B4WPO6FX.js");
1330
+ return { status: 200, body: api_exports.CatalogUpgradeView.parse(await catalogUpgradeView(root)) };
1331
+ }).add("POST", "/api/build/upgrade", async ({ body }) => {
1332
+ const b = parse(api_exports.CatalogUpgradeRequest, body);
1333
+ const { catalogUpgradeView } = await import("./chunk-B4WPO6FX.js");
1334
+ const v = await catalogUpgradeView(root);
1335
+ if (!v.pending)
1336
+ throw conflict("Nothing to upgrade: catalog/sources is here already.");
1337
+ if (v.others.length)
1338
+ throw conflict(`Other upgrade steps wait first (${v.others.map((s) => s.summary).join("; ")}): run the upgrade (Run the upgrade, on Home or on Catalog builds) first, then look at this list again. Nothing written.`);
1339
+ const accept = v.acceptChanges;
1340
+ if (accept > 0 && b.acceptChanges !== accept)
1341
+ throw conflict(b.acceptChanges === void 0 ? `The first build gives ${accept} record ${accept === 1 ? "file" : "files"} differently: accept exactly ${accept === 1 ? "it" : "these"} with their count first. Nothing written.` : `The page accepted ${b.acceptChanges} ${b.acceptChanges === 1 ? "change" : "changes"}; the first build gives ${accept} record ${accept === 1 ? "file" : "files"} differently now. Nothing written: look at the list again.`);
1342
+ if (accept === 0 && b.acceptChanges !== void 0)
1343
+ throw conflict("The first build changes nothing now, so there is nothing to accept. Nothing written: look at the list again.");
1344
+ if (v.writes.length !== b.count || v.plan !== b.plan)
1345
+ throw conflict(`The page listed ${b.count} ${b.count === 1 ? "file" : "files"} to write; the upgrade writes ${v.writes.length === b.count ? "other files" : `${v.writes.length}`} now. Nothing written: look at the list again.`);
1346
+ const { upgradeCommand } = await import("./chunk-CWKQRP6Y.js");
1347
+ return asJob(accept ? `atticus upgrade --yes --accept-changes ${accept}` : "atticus upgrade --yes", () => captured((io) => upgradeCommand(root, { by: ctx.user, yes: true, ...accept ? { acceptChanges: accept } : {} }, io)));
1348
+ });
1349
+ }
1350
+
1081
1351
  // packages/cli/dist/ui-api.js
1082
1352
  import { createHash as createHash3 } from "node:crypto";
1083
1353
  import { existsSync } from "node:fs";
@@ -1144,7 +1414,7 @@ async function answerFile(root, s) {
1144
1414
  const inRun = join3(s.dir, out);
1145
1415
  if (s.run.request.outputIn === "run" || s.run.parts?.length)
1146
1416
  return inRun;
1147
- const { changesDirOf: changesDirOf2 } = await import("./chunk-UXVKFOMC.js");
1417
+ const { changesDirOf: changesDirOf2 } = await import("./chunk-PPKH6ULR.js");
1148
1418
  return join3(changesDirOf2(root), s.run.request.change, out);
1149
1419
  }
1150
1420
  async function dueRuns(root, o) {
@@ -1314,6 +1584,9 @@ async function run(f, o = {}) {
1314
1584
  });
1315
1585
  return { code, out, err };
1316
1586
  }
1587
+ function scanAppWords(text) {
1588
+ return text.replace(/clone it again with atticus workspace sync/g, "clone it again with Sync repos on Set up \u203A Repos (in a terminal: atticus workspace sync)").replace(/clone it with atticus workspace sync/g, "clone it with Sync repos on Set up \u203A Repos (in a terminal: atticus workspace sync)").replace(/Scan every repo \(atticus scan, after atticus workspace sync\)/g, "Sync repos, then Check with the built-in readers again (in a terminal: atticus workspace sync, then atticus scan)");
1589
+ }
1317
1590
  function refused(r) {
1318
1591
  const detail = (r.err.length ? r.err : r.out).join("\n") || "The command refused.";
1319
1592
  return r.code === 2 ? new HttpError(400, "The request isn't valid", detail) : new HttpError(422, "Atticus can't do that yet", detail, { lines: [...r.out, ...r.err] });
@@ -1342,7 +1615,7 @@ async function readChange(root, id) {
1342
1615
  try {
1343
1616
  return await changeStore(root).read(id);
1344
1617
  } catch {
1345
- throw notFound(`There is no change ${id}.`);
1618
+ throw notFound(await missingChangeWords(root, id));
1346
1619
  }
1347
1620
  }
1348
1621
  async function changeDetail(root, id) {
@@ -1394,7 +1667,7 @@ async function changeDetail(root, id) {
1394
1667
  state: c.state,
1395
1668
  // ADR 0191 (app-only audit): the repos it names and its target flows' ("Name its repos on its
1396
1669
  // brief" stayed after the stories named them; the brief has no repos).
1397
- repos: await (await import("./chunk-IP6ARMZU.js")).changeRepos(root, c),
1670
+ repos: await (await import("./chunk-PT77IUYQ.js")).changeRepos(root, c),
1398
1671
  openFindings: open,
1399
1672
  updatedAt: c.history.at(-1)?.at ?? c.createdAt,
1400
1673
  ...fast ? { fastPath: true } : {},
@@ -1548,7 +1821,7 @@ async function artifactPath(root, id, artifact, o = {}) {
1548
1821
  if (!a.success)
1549
1822
  throw badRequest(`${artifact} is not an artifact. Use one of ${ChangeArtifact.options.join(", ")}.`);
1550
1823
  const dir = join4(changesDirOf(root), id);
1551
- const files = await artifactFiles(dir, a.data);
1824
+ const files = o.listed ?? await artifactFiles(dir, a.data);
1552
1825
  if (o.file) {
1553
1826
  if (!files.includes(o.file))
1554
1827
  throw notFound(`${o.file} isn't one of change ${id}'s ${artifact} files.`);
@@ -1560,11 +1833,12 @@ async function artifactPath(root, id, artifact, o = {}) {
1560
1833
  throw notFound(`Change ${id} has no ${artifact} yet.`);
1561
1834
  return files[0];
1562
1835
  }
1836
+ var ARTIFACT_FILES_MAX = 200;
1563
1837
  function uiRoutes(r, ctx, deps = {}) {
1564
1838
  const { root, user, jobs } = ctx;
1565
1839
  const confirmed2 = (write, target, given) => requireConfirmation(ctx.confirmations, write, target, given);
1566
1840
  const readyView = async (change) => {
1567
- const { deployOrderOf } = await import("./chunk-BEEHCL5O.js");
1841
+ const { deployOrderOf } = await import("./chunk-WTLFRINF.js");
1568
1842
  const repoOrder = await deployOrderOf(root, change);
1569
1843
  const prStates = /* @__PURE__ */ new Map();
1570
1844
  for (const t of await taskViews(root, change, {
@@ -1586,6 +1860,17 @@ function uiRoutes(r, ctx, deps = {}) {
1586
1860
  ...deps.notify ? { notify: deps.notify } : {}
1587
1861
  };
1588
1862
  const localWhat = /* @__PURE__ */ new Map();
1863
+ const refusalStillListed = async (b, ofCommand) => {
1864
+ const counted = b.allowRemovals !== void 0 || b.discardEdits !== void 0;
1865
+ if (counted && b.plan === void 0)
1866
+ throw badRequest("plan is the refusal's plan (its job's result's refused.plan) for the list being confirmed.");
1867
+ if (b.plan === void 0)
1868
+ return;
1869
+ const { lastBuildOf } = await import("./chunk-B4WPO6FX.js");
1870
+ const last = await lastBuildOf(root);
1871
+ if (last?.outcome !== "refused" || !ofCommand(last.command) || last.refused?.plan !== b.plan)
1872
+ throw conflict("What the build would remove or discard isn't what the page listed any more. Nothing written: look at the list again.");
1873
+ };
1589
1874
  const asJob = (what, work) => {
1590
1875
  const busy = ctx.jobs.runningOf("local");
1591
1876
  if (busy)
@@ -1596,11 +1881,11 @@ function uiRoutes(r, ctx, deps = {}) {
1596
1881
  c.progress(1, 1, res.code === 0 ? "Done" : "Stopped");
1597
1882
  ctx.events.publish({ type: "file.changed", path: "." });
1598
1883
  const raw = [...res.out, ...res.err];
1599
- const { appLines: appLines2 } = await import("./chunk-PZFZPHCT.js");
1884
+ const { appLines: appLines2 } = await import("./chunk-E7Q52EOO.js");
1600
1885
  const lines = appLines2(raw);
1601
1886
  const next = res.code === 0 ? void 0 : syncNextOf(raw);
1602
1887
  return {
1603
- result: { code: res.code, lines, ...next ? { next } : {} },
1888
+ result: { ...res.extra, code: res.code, lines, ...next ? { next } : {} },
1604
1889
  errors: res.code === 0 ? [] : lines
1605
1890
  };
1606
1891
  }, { title: what });
@@ -1608,6 +1893,7 @@ function uiRoutes(r, ctx, deps = {}) {
1608
1893
  return { status: 202, body: { jobId: job.id } };
1609
1894
  };
1610
1895
  uiStepRoutes(r, ctx, asJob);
1896
+ uiCatalogRoutes(r, ctx, asJob);
1611
1897
  const doneRun = async (runId, by) => {
1612
1898
  const { before, onlyResume } = await doneMayStart(runId);
1613
1899
  try {
@@ -1627,7 +1913,7 @@ function uiRoutes(r, ctx, deps = {}) {
1627
1913
  };
1628
1914
  const doneMayStart = async (runId) => {
1629
1915
  const before = await findRun(root, runId);
1630
- const { hasKeptResume: hasKeptResume2 } = await import("./chunk-PZFZPHCT.js");
1916
+ const { hasKeptResume: hasKeptResume2 } = await import("./chunk-E7Q52EOO.js");
1631
1917
  const onlyResume = before.state === "validated" && await hasKeptResume2(root, runId);
1632
1918
  if (before.state === "validated" && !onlyResume || before.state === "cancelled")
1633
1919
  throw conflict(`Run ${runId} is already ${before.state}.`);
@@ -1649,17 +1935,17 @@ function uiRoutes(r, ctx, deps = {}) {
1649
1935
  }
1650
1936
  const after = await findRun(root, runId);
1651
1937
  ctx.events.publish({ type: "run.changed", runId: after.runId, state: after.state });
1652
- const { resumeAfterDone, appLines: appLines2 } = await import("./chunk-PZFZPHCT.js");
1938
+ const { resumeAfterDone, appLines: appLines2 } = await import("./chunk-E7Q52EOO.js");
1653
1939
  if (res.code !== 0)
1654
1940
  throw refused({ ...res, out: appLines2(res.out), err: appLines2(res.err) });
1655
1941
  const stepRunner = deps.runStep ?? (async (args) => {
1656
- const { main } = await import("./chunk-TYN5SG5H.js");
1942
+ const { main } = await import("./chunk-DGNTEKF6.js");
1657
1943
  const out = [];
1658
1944
  const err = [];
1659
1945
  const code = await main([...args, "--root", root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
1660
1946
  return { code, out, err };
1661
1947
  });
1662
- const { hasKeptResume: kept } = await import("./chunk-PZFZPHCT.js");
1948
+ const { hasKeptResume: kept } = await import("./chunk-E7Q52EOO.js");
1663
1949
  const resumed = !await kept(root, after.runId) ? void 0 : await trackedLocal(ctx, `Finishing the step: ${after.runId}`, () => resumeAfterDone(root, stepRunner, after.change, after.runId), { meta: { handoffRun: after.runId } }).catch((e) => ({ lines: [e.message] }));
1664
1950
  if (resumed)
1665
1951
  ctx.events.publish({ type: "file.changed", path: changesRelOf(root) });
@@ -1678,35 +1964,62 @@ function uiRoutes(r, ctx, deps = {}) {
1678
1964
  };
1679
1965
  };
1680
1966
  startAutoDone(ctx, (runId) => doneRun(runId, "app"), deps.autoDone ?? {});
1681
- return r.add("POST", "/api/facts/{repo}/apply", async ({ params }) => {
1682
- const { verifyCommand } = await import("./chunk-7NVLGPER.js");
1967
+ return r.add("POST", "/api/facts/{repo}/apply", async ({ params, body }) => {
1968
+ const { verifyCommand } = await import("./chunk-3NGHSBVS.js");
1969
+ const b = parseBody(api_exports.FactsApplyRequest, body);
1683
1970
  const repo = params.repo;
1684
1971
  if (!FACTS_REPO.test(repo))
1685
1972
  throw badRequest(`${JSON.stringify(repo)} isn't a repo name.`);
1686
1973
  if (!(await loadRepos(root)).some((x) => x.id === repo))
1687
1974
  throw notFound(`There is no repo ${repo} in this workspace.`);
1688
- return asJob(`Applying to ${repo}`, () => run((io) => verifyCommand(root, repo, { write: true, verbose: false, json: false }, io)));
1689
- }).add("GET", "/api/upgrade", async () => keptAnswer(root, "upgrade", async () => {
1690
- const { newerAtticusOf, upgradeCheck } = await import("./chunk-MGNO4Q6V.js");
1691
- const c = await upgradeCheck(root);
1692
- const stamp3 = c.stamp?.atticus ?? newerAtticusOf(c);
1693
- const body = {
1694
- atticus: c.atticus,
1695
- newer: c.newer,
1696
- ...stamp3 ? { stamp: stamp3 } : {},
1697
- pending: c.pending
1698
- };
1699
- return { status: 200, body };
1700
- })).add("POST", "/api/upgrade", async () => {
1701
- const { newerThan, newerWords, upgradeCheck, upgradeCommand } = await import("./chunk-MGNO4Q6V.js");
1975
+ await refusalStillListed(b, (c) => c === `atticus verify ${repo} --write`);
1976
+ return asJob(`Applying to ${repo}`, async () => {
1977
+ const { lastBuildOf } = await import("./chunk-B4WPO6FX.js");
1978
+ const before = JSON.stringify(await lastBuildOf(root) ?? null);
1979
+ const ran = await run((io) => verifyCommand(root, repo, {
1980
+ write: true,
1981
+ verbose: false,
1982
+ json: false,
1983
+ ...b.allowRemovals !== void 0 ? { allowRemovals: b.allowRemovals } : {},
1984
+ ...b.discardEdits !== void 0 ? { discardEdits: b.discardEdits } : {},
1985
+ ...b.plan !== void 0 ? { plan: b.plan } : {}
1986
+ }, io));
1987
+ if (ran.code === 0)
1988
+ return ran;
1989
+ const last = await lastBuildOf(root);
1990
+ return last?.outcome === "refused" && last.refused && JSON.stringify(last) !== before ? { ...ran, extra: { refused: last.refused } } : ran;
1991
+ });
1992
+ }).add("GET", "/api/upgrade", async () => {
1993
+ const r2 = await keptAnswer(root, "upgrade", async () => {
1994
+ const { newerAtticusOf, upgradeCheck } = await import("./chunk-CWKQRP6Y.js");
1995
+ const c = await upgradeCheck(root);
1996
+ const stamp3 = c.stamp?.atticus ?? newerAtticusOf(c);
1997
+ const body = {
1998
+ atticus: c.atticus,
1999
+ newer: c.newer,
2000
+ ...stamp3 ? { stamp: stamp3 } : {},
2001
+ pending: c.pending
2002
+ };
2003
+ return { status: 200, body };
2004
+ });
2005
+ const { upgradedPaths, UPGRADE_STAMP } = await import("./chunk-W7NNZFIL.js");
2006
+ const upgraded = upgradedPaths(root).filter((p) => p !== UPGRADE_STAMP);
2007
+ return { ...r2, body: { ...r2.body, upgraded } };
2008
+ }).add("POST", "/api/upgrade", async () => {
2009
+ const { newerThan, newerWords, upgradeCheck, upgradeCommand } = await import("./chunk-CWKQRP6Y.js");
1702
2010
  const c = await upgradeCheck(root);
1703
2011
  if (c.newer)
1704
2012
  throw conflict(newerWords(c));
1705
2013
  if (!c.pending.length && c.stamp && !newerThan(c.atticus, c.stamp.atticus))
1706
2014
  throw conflict(`Nothing to upgrade: up to date for Atticus ${c.atticus}.`);
1707
- return asJob("Upgrading the metarepo", () => run((io) => upgradeCommand(root, { by: user }, io)));
2015
+ return asJob("Upgrading the metarepo", async () => {
2016
+ const ran = await run((io) => upgradeCommand(root, { by: user }, io));
2017
+ const { upgradedPaths, UPGRADE_STAMP } = await import("./chunk-W7NNZFIL.js");
2018
+ const upgraded = upgradedPaths(root).filter((p) => p !== UPGRADE_STAMP);
2019
+ return { ...ran, extra: { upgraded } };
2020
+ });
1708
2021
  }).add("GET", "/api/propose", async ({ query }) => {
1709
- const { proposePlan, PROPOSE_SCOPES } = await import("./chunk-IJN5PSDU.js");
2022
+ const { proposePlan, PROPOSE_SCOPES } = await import("./chunk-W7NNZFIL.js");
1710
2023
  const scope = query.get("scope") ?? "";
1711
2024
  if (!PROPOSE_SCOPES.includes(scope))
1712
2025
  throw refused({
@@ -1729,7 +2042,7 @@ function uiRoutes(r, ctx, deps = {}) {
1729
2042
  }).add("POST", "/api/propose", async ({ body }) => {
1730
2043
  const b = parseBody(api_exports.ProposeRequest, body);
1731
2044
  confirmed2("propose", b.scope, b.confirmation);
1732
- const { proposeForReview } = await import("./chunk-IJN5PSDU.js");
2045
+ const { proposeForReview } = await import("./chunk-W7NNZFIL.js");
1733
2046
  return asJob("Proposing for review", () => run((io) => proposeForReview(root, {
1734
2047
  scope: b.scope,
1735
2048
  by: user,
@@ -1738,15 +2051,15 @@ function uiRoutes(r, ctx, deps = {}) {
1738
2051
  ...b.branch ? { branch: b.branch } : {}
1739
2052
  }, io)));
1740
2053
  }).add("POST", "/api/propose/bring-in", async () => {
1741
- const { bringInMerged } = await import("./chunk-IJN5PSDU.js");
2054
+ const { bringInMerged } = await import("./chunk-W7NNZFIL.js");
1742
2055
  return asJob("Bringing in what merged", () => run((io) => bringInMerged(root, io)));
1743
2056
  }).add("POST", "/api/propose/upstream", async ({ body }) => {
1744
2057
  const b = parseBody(api_exports.UpstreamRequest, body);
1745
- const { setUpstream } = await import("./chunk-IJN5PSDU.js");
2058
+ const { setUpstream } = await import("./chunk-W7NNZFIL.js");
1746
2059
  return asJob(`Setting the upstream to ${b.upstream}`, () => run((io) => setUpstream(root, b.upstream, io)));
1747
2060
  }).add("POST", "/api/changes/{changeId}/conformance", async ({ params }) => {
1748
2061
  await readChange(root, params.changeId);
1749
- const { changeConformCommand } = await import("./chunk-C3TBDX7Y.js");
2062
+ const { changeConformCommand } = await import("./chunk-M25UUEKC.js");
1750
2063
  return asJob(`Checking ${params.changeId}'s code against its design`, () => run((io) => changeConformCommand(root, params.changeId, { findingsAnswer: true }, io)));
1751
2064
  }).add("GET", "/api/change-types", async () => {
1752
2065
  const op = await loadOrgPack(orgPackDirOf(root));
@@ -1795,9 +2108,13 @@ function uiRoutes(r, ctx, deps = {}) {
1795
2108
  path: `${changesRelOf(root)}/${params.changeId}/change.yaml`
1796
2109
  });
1797
2110
  return { status: 200, body: await changeDetail(root, params.changeId) };
1798
- }).add("GET", "/api/changes/{changeId}/status", async ({ params }) => {
2111
+ }).add("GET", "/api/change-problems", async () => ({
2112
+ status: 200,
2113
+ body: api_exports.ChangeProblems.parse(await changeProblems(root))
2114
+ })).add("GET", "/api/changes/{changeId}/status", async ({ params }) => {
1799
2115
  await readChange(root, params.changeId);
1800
2116
  const rep = await changeReport(root, params.changeId);
2117
+ const said = await changeNextStep(root, params.changeId, rep, void 0, "page");
1801
2118
  return {
1802
2119
  status: 200,
1803
2120
  body: {
@@ -1805,7 +2122,9 @@ function uiRoutes(r, ctx, deps = {}) {
1805
2122
  ...rep.phase ? { phase: rep.phase } : {},
1806
2123
  ...rep.next ? { next: rep.next } : {},
1807
2124
  ...rep.progress ? { progress: rep.progress } : {},
1808
- nextStep: rep.nextStep,
2125
+ nextStep: said.nextStep,
2126
+ ...said.nextStepApp ? { nextStepApp: said.nextStepApp } : {},
2127
+ ...said.stepFirst ? { stepFirst: true } : {},
1809
2128
  risk: rep.risk,
1810
2129
  tests: rep.tests,
1811
2130
  ...rep.handoff ? {
@@ -1819,6 +2138,56 @@ function uiRoutes(r, ctx, deps = {}) {
1819
2138
  reasons: rep.reasons
1820
2139
  }
1821
2140
  };
2141
+ }).add("GET", "/api/changes/{changeId}/artifacts/{artifact}/files", async ({ params, query }) => {
2142
+ await readChange(root, params.changeId);
2143
+ const asked = [...new Set(query.getAll("file").filter(Boolean))];
2144
+ if (!asked.length)
2145
+ throw badRequest("Name the files: ?file=<path>&file=<path>, each from the change folder.");
2146
+ if (asked.length > ARTIFACT_FILES_MAX)
2147
+ throw badRequest(`At most ${ARTIFACT_FILES_MAX} files a call (${asked.length} asked).`);
2148
+ const art = ChangeArtifact.safeParse(params.artifact);
2149
+ if (!art.success)
2150
+ await artifactPath(root, params.changeId, params.artifact);
2151
+ const dir = join4(changesDirOf(root), params.changeId);
2152
+ const listed = art.success ? await artifactFiles(dir, art.data) : [];
2153
+ const files = [];
2154
+ const problems = /* @__PURE__ */ Object.create(null);
2155
+ const problem2 = (file, e) => {
2156
+ problems[file] = {
2157
+ status: e.status,
2158
+ title: e.title,
2159
+ ...e.detail ? { detail: e.detail } : {}
2160
+ };
2161
+ };
2162
+ for (const file of asked) {
2163
+ let rel;
2164
+ let content;
2165
+ try {
2166
+ rel = await artifactPath(root, params.changeId, params.artifact, {
2167
+ orNew: true,
2168
+ file,
2169
+ listed
2170
+ });
2171
+ content = await readFile2(join4(dir, rel), "utf8").catch((e) => {
2172
+ if (e.code === "ENOENT")
2173
+ throw notFound(`${file} isn't there any more: it was deleted or moved.`);
2174
+ return "";
2175
+ });
2176
+ } catch (e) {
2177
+ if (!(e instanceof HttpError))
2178
+ throw e;
2179
+ problem2(file, e);
2180
+ continue;
2181
+ }
2182
+ files.push({
2183
+ file,
2184
+ artifact: params.artifact,
2185
+ path: `${changesRelOf(root)}/${params.changeId}/${rel}`,
2186
+ content,
2187
+ sha256: sha2(content)
2188
+ });
2189
+ }
2190
+ return { status: 200, body: { files, problems } };
1822
2191
  }).add("GET", "/api/changes/{changeId}/artifacts/{artifact}", async ({ params, query }) => {
1823
2192
  await readChange(root, params.changeId);
1824
2193
  const rel = await artifactPath(root, params.changeId, params.artifact, {
@@ -1849,7 +2218,7 @@ function uiRoutes(r, ctx, deps = {}) {
1849
2218
  throw conflict(`${rel} changed since you opened it. Reload it, then make your edit again.`);
1850
2219
  await mkdir(dirname3(file), { recursive: true });
1851
2220
  await writeFileIfUnchanged(file, was, b.content);
1852
- const { recordPersonSave: recordPersonSave2 } = await import("./chunk-ANFBBJEV.js");
2221
+ const { recordPersonSave: recordPersonSave2 } = await import("./chunk-YPXBGNUV.js");
1853
2222
  await recordPersonSave2(join4(changesDirOf(root), params.changeId), params.changeId, {
1854
2223
  file: rel,
1855
2224
  who: user,
@@ -1989,7 +2358,7 @@ function uiRoutes(r, ctx, deps = {}) {
1989
2358
  left
1990
2359
  })
1991
2360
  };
1992
- }, { title: `Run the ready tasks of ${change}` });
2361
+ }, { title: `Run the ready tasks of ${change}`, log: { ids: [change] } });
1993
2362
  return { status: 202, body: api_exports.RunReadyAccepted.parse({ jobId: job.id, tasks }) };
1994
2363
  }).add("POST", "/api/changes/{changeId}/tasks/{taskId}/pr", async ({ params, body }) => {
1995
2364
  await readChange(root, params.changeId);
@@ -2147,7 +2516,7 @@ function uiRoutes(r, ctx, deps = {}) {
2147
2516
  const res = await run((io) => changeSync(root, params.changeId, { by: user, approve, ...b.repo ? { repo: b.repo } : {} }, io, changeDeps));
2148
2517
  if (res.code === 2)
2149
2518
  throw refused(res);
2150
- const { appLines: appLines2 } = await import("./chunk-PZFZPHCT.js");
2519
+ const { appLines: appLines2 } = await import("./chunk-E7Q52EOO.js");
2151
2520
  return {
2152
2521
  status: 200,
2153
2522
  body: {
@@ -2157,14 +2526,14 @@ function uiRoutes(r, ctx, deps = {}) {
2157
2526
  };
2158
2527
  }).add("GET", "/api/changes/{changeId}/inputs", async ({ params }) => {
2159
2528
  const c = await readChange(root, params.changeId);
2160
- const { readChangeInputs } = await import("./chunk-VPQUFIE7.js");
2529
+ const { readChangeInputs } = await import("./chunk-W6OY2PMB.js");
2161
2530
  return {
2162
2531
  status: 200,
2163
2532
  body: api_exports.ChangeInputList.parse(await readChangeInputs(join4(changesDirOf(root), c.id)))
2164
2533
  };
2165
2534
  }).add("GET", "/api/changes/{changeId}/prototypes", async ({ params }) => {
2166
2535
  const c = await readChange(root, params.changeId);
2167
- const { changePrototypes } = await import("./chunk-HVOE7ZW2.js");
2536
+ const { changePrototypes } = await import("./chunk-VTQ55N4O.js");
2168
2537
  return {
2169
2538
  status: 200,
2170
2539
  body: api_exports.ChangePrototypeList.parse(await changePrototypes(root, c.id))
@@ -2172,7 +2541,7 @@ function uiRoutes(r, ctx, deps = {}) {
2172
2541
  }).add("POST", "/api/changes/{changeId}/prototypes", async ({ params, body }) => {
2173
2542
  const c = await readChange(root, params.changeId);
2174
2543
  const b = parseBody(api_exports.ComparePrototypeRequest, body);
2175
- const { attachPrototype, changePrototypes } = await import("./chunk-HVOE7ZW2.js");
2544
+ const { attachPrototype, changePrototypes } = await import("./chunk-VTQ55N4O.js");
2176
2545
  const res = await run((io) => attachPrototype(root, c.id, b.repo, { by: user, ...deps.now ? { now: new Date(deps.now) } : {} }, io));
2177
2546
  if (res.code !== 0)
2178
2547
  throw refused(res);
@@ -2190,7 +2559,7 @@ function uiRoutes(r, ctx, deps = {}) {
2190
2559
  const bytes = new Uint8Array(Buffer.from(b.content, "base64"));
2191
2560
  if (bytes.length > MAX_ATTACH)
2192
2561
  throw new HttpError(413, "The file is too large", "Attach a file of 15 MB or less.");
2193
- const { attachFiles } = await import("./chunk-7ZBYRMWK.js");
2562
+ const { attachFiles } = await import("./chunk-OY2VC2IU.js");
2194
2563
  const r2 = await attachFiles(root, c.id, [{ name: b.name, bytes }], user);
2195
2564
  if (!r2.added.length)
2196
2565
  throw new HttpError(422, "Atticus can't attach that", r2.refused[0]?.why ?? "", {
@@ -2281,7 +2650,7 @@ function uiRoutes(r, ctx, deps = {}) {
2281
2650
  got = await once(next);
2282
2651
  }
2283
2652
  return got;
2284
- });
2653
+ }, { ids: [params.changeId] });
2285
2654
  if (res.code === 2)
2286
2655
  throw refused(res);
2287
2656
  ctx.events.publish({
@@ -2391,10 +2760,11 @@ function uiRoutes(r, ctx, deps = {}) {
2391
2760
  }
2392
2761
  const f = (await latestFindings(root, params.changeId)).find((x) => x.id === params.findingId);
2393
2762
  return { status: 200, body: f };
2394
- }).add("POST", "/api/scan", ({ body }) => {
2763
+ }).add("POST", "/api/scan", async ({ body }) => {
2395
2764
  const b = parseBody(api_exports.ScanRequest, body);
2396
2765
  if (jobs.runningOf("scan"))
2397
2766
  throw conflict("A scan is already running.");
2767
+ await refusalStillListed(b, (c) => c === "atticus scan" || c.startsWith("atticus scan "));
2398
2768
  const scanTitle = b.repos?.length ? `Scan ${b.repos.join(", ")}` : "Scan";
2399
2769
  const job = jobs.start("scan", async (c) => {
2400
2770
  c.progress(0, 1, "Checking with the built-in readers");
@@ -2405,7 +2775,11 @@ function uiRoutes(r, ctx, deps = {}) {
2405
2775
  json: true,
2406
2776
  // ADR 0123: another branch, scanned beside the baseline.
2407
2777
  ...b.ref ? { ref: b.ref } : {},
2408
- ...askFrom ? { askFrom } : {}
2778
+ ...askFrom ? { askFrom } : {},
2779
+ // ADR 0195 (CS3): the confirm step's counts, as the refusal listed them.
2780
+ ...b.allowRemovals !== void 0 ? { allowRemovals: b.allowRemovals } : {},
2781
+ ...b.discardEdits !== void 0 ? { discardEdits: b.discardEdits } : {},
2782
+ ...b.plan !== void 0 ? { plan: b.plan } : {}
2409
2783
  }, io), { jsonOut: true });
2410
2784
  c.progress(1, 1, "Scanned");
2411
2785
  const parsed = (() => {
@@ -2416,13 +2790,19 @@ function uiRoutes(r, ctx, deps = {}) {
2416
2790
  }
2417
2791
  })();
2418
2792
  for (const l of scanSummaryLines(parsed))
2419
- printToCurrent(l);
2793
+ printToCurrent(scanAppWords(l));
2420
2794
  const problems = parsed.problems?.length ?? 0;
2421
2795
  const refusal3 = parsed.refused;
2796
+ const sources = Array.isArray(parsed.sources) ? parsed.sources : [];
2422
2797
  if (refusal3)
2423
2798
  return {
2424
- result: { stats: parsed.stats, problems, written: false, refused: refusal3 },
2425
- errors: refusal3.message.split("\n")
2799
+ result: {
2800
+ stats: parsed.stats,
2801
+ problems,
2802
+ written: false,
2803
+ refused: { ...refusal3, message: scanAppWords(refusal3.message) },
2804
+ sources
2805
+ }
2426
2806
  };
2427
2807
  ctx.events.publish({
2428
2808
  type: "index.rebuilt",
@@ -2435,10 +2815,18 @@ function uiRoutes(r, ctx, deps = {}) {
2435
2815
  const questions = parsed.questions?.length ?? 0;
2436
2816
  printToCurrent(`The built-in readers added ${added} record${added === 1 ? "" : "s"}, changed ${changed} and removed ${removed}; ${questions} host question${questions === 1 ? " is" : "s are"} open.`);
2437
2817
  return {
2438
- result: { stats: parsed.stats, problems, added, changed, removed, questions },
2818
+ result: {
2819
+ stats: parsed.stats,
2820
+ problems,
2821
+ added,
2822
+ changed,
2823
+ removed,
2824
+ questions,
2825
+ sources
2826
+ },
2439
2827
  errors: res.code === 2 ? res.err : []
2440
2828
  };
2441
- }, { title: scanTitle });
2829
+ }, { title: scanTitle, log: { ids: b.repos ?? [] } });
2442
2830
  return { status: 202, body: { jobId: job.id } };
2443
2831
  }).add("POST", "/api/workspace/sync", ({ body }) => {
2444
2832
  const b = parseBody(api_exports.ScanRequest.pick({ repos: true }), body);
@@ -2447,32 +2835,42 @@ function uiRoutes(r, ctx, deps = {}) {
2447
2835
  throw conflict(`A sync is already running (${busy.id}): wait for it to finish.`);
2448
2836
  const job = jobs.start("sync", async (c) => {
2449
2837
  c.progress(0, 1, "Syncing base clones");
2450
- const res = await run((io) => workspaceSync(root, b.repos, io));
2838
+ const res = await run((io) => workspaceSync(root, b.repos, io, { signal: c.signal }));
2451
2839
  c.progress(1, 1, res.code === 0 ? "Synced" : "Stopped");
2452
2840
  const lines = [...res.out, ...res.err];
2841
+ if (c.cancelled)
2842
+ return { result: { code: res.code, lines } };
2453
2843
  return {
2454
2844
  result: { code: res.code, lines },
2455
2845
  errors: res.code === 0 ? [] : res.err.length ? res.err : lines
2456
2846
  };
2457
- }, { title: b.repos?.length ? `Sync ${b.repos.join(", ")}` : "Sync the base clones" });
2847
+ }, {
2848
+ title: b.repos?.length ? `Sync ${b.repos.join(", ")}` : "Sync the base clones",
2849
+ log: { ids: b.repos ?? [] }
2850
+ });
2458
2851
  return { status: 202, body: { jobId: job.id } };
2459
2852
  }).add("POST", "/api/reconcile", ({ body }) => {
2460
2853
  const b = parseBody(api_exports.ReconcileRequest, body);
2461
2854
  const busy = jobs.runningOf("reconcile");
2462
2855
  if (busy)
2463
2856
  throw conflict(`A reconcile is already running (${busy.id}): wait for it to finish.`);
2464
- const job = jobs.start("reconcile", async (c) => {
2465
- c.progress(0, 1, `Reconciling ${b.diagram}`);
2466
- const res = await run((io) => reconcileCommand(root, [b.diagram], { json: true }, io));
2467
- c.progress(1, 1, "Reconciled");
2468
- let result;
2469
- try {
2470
- result = JSON.parse(res.out.join("\n"));
2471
- } catch {
2472
- result = { lines: res.out };
2473
- }
2474
- return { result, errors: res.code === 2 ? res.err : [] };
2475
- }, { title: `Reconcile ${b.diagram}` });
2857
+ const job = jobs.start(
2858
+ "reconcile",
2859
+ async (c) => {
2860
+ c.progress(0, 1, `Reconciling ${b.diagram}`);
2861
+ const res = await run((io) => reconcileCommand(root, [b.diagram], { json: true }, io));
2862
+ c.progress(1, 1, "Reconciled");
2863
+ let result;
2864
+ try {
2865
+ result = JSON.parse(res.out.join("\n"));
2866
+ } catch {
2867
+ result = { lines: res.out };
2868
+ }
2869
+ return { result, errors: res.code === 2 ? res.err : [] };
2870
+ },
2871
+ // The diagram's name is the person's: in the run log, as an id only if it is one.
2872
+ { title: `Reconcile ${b.diagram}`, log: { ids: [b.diagram] } }
2873
+ );
2476
2874
  return { status: 202, body: { jobId: job.id } };
2477
2875
  });
2478
2876
  }
@@ -2532,7 +2930,7 @@ async function readChange2(root, id) {
2532
2930
  try {
2533
2931
  return await changeStore(root).read(id);
2534
2932
  } catch {
2535
- throw notFound(`There is no change ${id}.`);
2933
+ throw notFound(await missingChangeWords(root, id));
2536
2934
  }
2537
2935
  }
2538
2936
  async function openChanges2(root) {
@@ -2840,7 +3238,7 @@ function uiRunRoutes(r, ctx, deps = {}) {
2840
3238
  io,
2841
3239
  // the step's sync is said apart, as `synced`, below
2842
3240
  { ...deps.todo, sync: false }
2843
- )));
3241
+ )), { ids: [params.stepId] });
2844
3242
  if (res.code !== 0) {
2845
3243
  if (res.err.some((l) => /^There is no step/.test(l)))
2846
3244
  throw notFound(res.err.join("\n"));
@@ -2976,7 +3374,12 @@ function uiRunRoutes(r, ctx, deps = {}) {
2976
3374
  state: rep.state,
2977
3375
  ...rep.phase ? { phase: rep.phase } : {},
2978
3376
  ...rep.next ? { next: rep.next } : {},
2979
- nextStep: rep.nextStep,
3377
+ // Beta.27 review: the sentence At a glance says (changeNextStep).
3378
+ ...await changeNextStep(root, id, rep, void 0, "page").then((s) => ({
3379
+ nextStep: s.nextStep,
3380
+ ...s.nextStepApp ? { nextStepApp: s.nextStepApp } : {},
3381
+ ...s.stepFirst ? { stepFirst: true } : {}
3382
+ })),
2980
3383
  risk: rep.risk,
2981
3384
  blockers: rep.blockers,
2982
3385
  reasons: rep.reasons
@@ -3467,7 +3870,7 @@ function uiKnowRoutes(r, ctx, o = {}) {
3467
3870
  const args = build(arg);
3468
3871
  if (!args)
3469
3872
  throw badRequest(`The ${name} view needs an id: /api/view/${name}/<id>.`);
3470
- const { main } = await import("./chunk-TYN5SG5H.js");
3873
+ const { main } = await import("./chunk-DGNTEKF6.js");
3471
3874
  const out = [];
3472
3875
  const err = [];
3473
3876
  const code = await main([...args, "--json", "--root", ctx.root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
@@ -3497,7 +3900,7 @@ function uiKnowRoutes(r, ctx, o = {}) {
3497
3900
  return { status: 200, body: { code, data: body, problems: err } };
3498
3901
  };
3499
3902
  const text = async (args) => {
3500
- const { main } = await import("./chunk-TYN5SG5H.js");
3903
+ const { main } = await import("./chunk-DGNTEKF6.js");
3501
3904
  const out = [];
3502
3905
  const err = [];
3503
3906
  const code = await main([...args, "--root", ctx.root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
@@ -3515,7 +3918,7 @@ function uiKnowRoutes(r, ctx, o = {}) {
3515
3918
  throw badRequest("Some fields aren't right.", {
3516
3919
  errors: b.error.issues.map((i) => ({ path: i.path.join("."), message: i.message }))
3517
3920
  });
3518
- const { triageDecide } = await import("./chunk-QQAWI5LD.js");
3921
+ const { triageDecide } = await import("./chunk-MP7W6OKP.js");
3519
3922
  const out = [];
3520
3923
  const err = [];
3521
3924
  const code = await triageDecide(ctx.root, params.itemId, b.data.option, { by: ctx.user, ...b.data.reason ? { reason: b.data.reason } : {} }, { out: (l) => out.push(l), err: (l) => err.push(l) });
@@ -3642,7 +4045,7 @@ function refused3(r) {
3642
4045
  return r.code === 2 ? badRequest(detail) : new HttpError(422, "Atticus refused", detail);
3643
4046
  }
3644
4047
  function uiInitiativeRoutes(r, ctx) {
3645
- const commands = () => import("./chunk-XT3ZW7C7.js");
4048
+ const commands = () => import("./chunk-W4SWXJZQ.js");
3646
4049
  const changed = () => ctx.events.publish({ type: "file.changed", path: "catalog/curated" });
3647
4050
  return r.add("POST", "/api/initiatives", async ({ body }) => {
3648
4051
  const b = parseBody3(api_exports.NewInitiativeRequest, body);
@@ -3721,9 +4124,9 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3721
4124
  throw badRequest("role is product, architecture, analysis or delivery, or left out.");
3722
4125
  const onFile = await listQuestions(ctx.root);
3723
4126
  const every = { ...onFile, questions: onFile.questions.filter((q) => !q.finding) };
3724
- const { routeQuestions } = await import("./chunk-723OQZ3N.js");
4127
+ const { routeQuestions } = await import("./chunk-CHS5BJ34.js");
3725
4128
  const routedAll = await routeQuestions(ctx.root, every.questions, mine ? { mine: ctx.user } : {});
3726
- const { stageQuestions, roleWithStage, isChangeQuestion, countByRole, personsRoles } = await import("./chunk-2JT4QV3Q.js");
4129
+ const { stageQuestions, roleWithStage, isChangeQuestion, countByRole, personsRoles } = await import("./chunk-HDWVR5KD.js");
3727
4130
  const stages = await stageQuestions(ctx.root);
3728
4131
  const roleOf = (q) => roleWithStage(q, stages);
3729
4132
  for (const q of every.questions) {
@@ -3774,13 +4177,13 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3774
4177
  return { status: 200, body };
3775
4178
  };
3776
4179
  return r.add("GET", "/api/questions", async ({ query }) => keptAnswer(ctx.root, `questions?${query.toString()}&by=${ctx.user}`, () => questionsAnswer(query), () => checkoutsStamp(ctx.root))).add("GET", "/api/owner-questions", async () => keptAnswer(ctx.root, "owner-questions", async () => {
3777
- const { ownerQuestions } = await import("./chunk-CUTMM4NY.js");
4180
+ const { ownerQuestions } = await import("./chunk-SSYD4XIW.js");
3778
4181
  return { status: 200, body: await ownerQuestions(ctx.root, { now: now() }) };
3779
4182
  })).add("POST", "/api/owner-questions/{id}/answer", async ({ params, body }) => {
3780
4183
  const b = api_exports.OwnerAnswerRequest.safeParse(body ?? {});
3781
4184
  if (!b.success || !b.data.answer.trim())
3782
4185
  throw badRequest('Answer with { answer: "what the owner said" }.');
3783
- const { answerOwnerQuestion, OwnerQuestionError } = await import("./chunk-CUTMM4NY.js");
4186
+ const { answerOwnerQuestion, OwnerQuestionError } = await import("./chunk-SSYD4XIW.js");
3784
4187
  try {
3785
4188
  const r2 = await answerOwnerQuestion(ctx.root, params.id, b.data.answer, {
3786
4189
  by: ctx.user,
@@ -3805,13 +4208,13 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3805
4208
  throw notFound(`There is no question ${params.id}.`);
3806
4209
  if (q.askedBy.step !== TARGETS_STEP_ID && q.askedBy.step !== TOPICS_STEP_ID)
3807
4210
  throw new HttpError(422, "That question doesn't ask where a call goes or who owns a topic", `${q.id} isn't a targets or topics question, so it has no picker.`);
3808
- const { pickerOf } = await import("./chunk-HVWPN2RY.js");
4211
+ const { pickerOf } = await import("./chunk-R7VX5BSP.js");
3809
4212
  return { status: 200, body: { picks: await pickerOf(ctx.root) } };
3810
4213
  }).add("GET", "/api/questions/{id}/evidence", async ({ params }) => {
3811
4214
  const q = await readQuestion(ctx.root, params.id).catch(() => void 0);
3812
4215
  if (!q)
3813
4216
  throw notFound(`There is no question ${params.id}.`);
3814
- const { evidenceExcerpts } = await import("./chunk-CWLXVRFH.js");
4217
+ const { evidenceExcerpts } = await import("./chunk-S6TLXRBR.js");
3815
4218
  return {
3816
4219
  status: 200,
3817
4220
  body: {
@@ -3856,7 +4259,7 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3856
4259
  const q0 = await readQuestion(ctx.root, params.id).catch(() => void 0);
3857
4260
  if (!q0)
3858
4261
  throw notFound(`There is no question ${params.id}.`);
3859
- const { targetAnswerOf, offerLine } = await import("./chunk-HVWPN2RY.js");
4262
+ const { targetAnswerOf, offerLine } = await import("./chunk-R7VX5BSP.js");
3860
4263
  const t = await targetAnswerOf(ctx.root, q0, target, {
3861
4264
  ...addSystem ? { addSystem } : {},
3862
4265
  ...name ? { name } : {}
@@ -3935,6 +4338,8 @@ async function acrossRows(root, view3) {
3935
4338
  const rows = [];
3936
4339
  const op = view3 === "requests" ? await loadOrgPack(orgPackDirOf(root)) : void 0;
3937
4340
  const steps = view3 === "requests" ? await fileStepStore(root).list({ system: "service-desk" }).catch(() => []) : [];
4341
+ let stateP;
4342
+ const nextState = () => stateP ??= readNextState(root).catch(() => void 0);
3938
4343
  for (const c of changes) {
3939
4344
  const base = { change: c.id, changeTitle: c.title, changeState: c.state };
3940
4345
  const dir = changeFolder(root, c.id);
@@ -4011,12 +4416,15 @@ async function acrossRows(root, view3) {
4011
4416
  case "releases": {
4012
4417
  const rep = await changeReport(root, c.id);
4013
4418
  const h = liveHandoff(c);
4419
+ const said = await changeNextStep(root, c.id, rep, await nextState(), "page");
4014
4420
  rows.push({
4015
4421
  ...base,
4016
4422
  atRelease: AT_RELEASE.has(c.state),
4017
4423
  ...rep.phase ? { phase: rep.phase } : {},
4018
4424
  ...rep.next ? { next: rep.next } : {},
4019
- nextStep: rep.nextStep,
4425
+ nextStep: said.nextStep,
4426
+ ...said.nextStepApp ? { nextStepApp: said.nextStepApp } : {},
4427
+ ...said.stepFirst ? { stepFirst: true } : {},
4020
4428
  risk: rep.risk.level,
4021
4429
  blockers: rep.blockers.length,
4022
4430
  ...h ? { handoff: { phase: h.phase, pr: h.pr.url, state: h.state } } : {}
@@ -4484,7 +4892,7 @@ function uiSpecRoutes(r, ctx) {
4484
4892
  });
4485
4893
  r.add("GET", "/api/changes/{changeId}/conformance", async ({ params }) => {
4486
4894
  const change = idOf2(params.changeId, "change");
4487
- const { conformanceOf } = await import("./chunk-6SIGGA37.js");
4895
+ const { conformanceOf } = await import("./chunk-GLNSLQSV.js");
4488
4896
  const c = await conformanceOf(root, change);
4489
4897
  if (!c)
4490
4898
  throw notFound(`There is no change ${change}.`);
@@ -4499,7 +4907,7 @@ function uiSpecRoutes(r, ctx) {
4499
4907
  });
4500
4908
  r.add("GET", "/api/changes/{changeId}/impact", async ({ params }) => {
4501
4909
  const change = idOf2(params.changeId, "change");
4502
- const { changeImpactOf } = await import("./chunk-XEWFVHOT.js");
4910
+ const { changeImpactOf } = await import("./chunk-JGR4X2UA.js");
4503
4911
  const i = await changeImpactOf(root, change);
4504
4912
  if (!i)
4505
4913
  throw notFound(`There is no change ${change}.`);
@@ -4652,8 +5060,8 @@ function uiKnowledgeRoutes(r, ctx, deps = {}) {
4652
5060
  const slash = id.indexOf("/");
4653
5061
  return hash > 0 && slash > 0 && slash < hash ? { source: id.slice(0, slash), page: id.slice(slash + 1, hash) } : void 0;
4654
5062
  };
4655
- const { knowledgePages } = await import("./chunk-IP6ARMZU.js");
4656
- const { sectionOf } = await import("./chunk-NMURRF5F.js");
5063
+ const { knowledgePages } = await import("./chunk-PT77IUYQ.js");
5064
+ const { sectionOf } = await import("./chunk-GF6GBHFN.js");
4657
5065
  const pages = doc?.items.some((i) => i.id.includes("#")) ? await knowledgePages(root) : [];
4658
5066
  const records = doc?.items.length ? new Map((await readKnowledge(root, { cacheRoot: root })).items.map((r2) => [r2.id, r2])) : /* @__PURE__ */ new Map();
4659
5067
  const passageOf = (id) => {
@@ -4853,7 +5261,7 @@ function uiKnowledgeRoutes(r, ctx, deps = {}) {
4853
5261
  printToCurrent(l);
4854
5262
  }
4855
5263
  };
4856
- const code = await tracked(ctx, `Sync the wiki ${id}`, () => sourcesSync(root, io, { source: id, now: stamp(now()) }));
5264
+ const code = await tracked(ctx, `Sync the wiki ${id}`, () => sourcesSync(root, io, { source: id, now: stamp(now()) }), { ids: [id] });
4857
5265
  if (code === 2)
4858
5266
  throw new HttpError(422, "Atticus refused", c.problems.join("\n") || "Nothing to sync.");
4859
5267
  changed(`${knowledgeRelOf(root)}/snapshots/${id}`);
@@ -4944,7 +5352,7 @@ function uiKnowledgeRoutes(r, ctx, deps = {}) {
4944
5352
  if (source !== void 0)
4945
5353
  idOf3(source, "source");
4946
5354
  const ids = await snapshotSources(root);
4947
- const { inputsPassagePages, pastableArg } = await import("./chunk-IP6ARMZU.js");
5355
+ const { inputsPassagePages, pastableArg } = await import("./chunk-PT77IUYQ.js");
4948
5356
  const live = !ids.includes(INPUTS_SOURCE_ID) && (!source || source === INPUTS_SOURCE_ID) ? await inputsPassagePages(root) : [];
4949
5357
  if (source && !ids.includes(source) && !(source === INPUTS_SOURCE_ID && live.length))
4950
5358
  throw notFound(`${source} has no snapshot yet: atticus sources sync --source ${source}.`);
@@ -5159,7 +5567,7 @@ async function configuredModel(root) {
5159
5567
  function uiModelRunRoutes(r, ctx, deps = {}) {
5160
5568
  const root = ctx.root;
5161
5569
  const runStep = deps.runStep ?? (async (args) => {
5162
- const { main } = await import("./chunk-TYN5SG5H.js");
5570
+ const { main } = await import("./chunk-DGNTEKF6.js");
5163
5571
  const out = [];
5164
5572
  const err = [];
5165
5573
  const code = await main([...args, "--root", root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
@@ -5167,7 +5575,7 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5167
5575
  });
5168
5576
  return r.add("POST", "/api/runs/handoff", async ({ body }) => {
5169
5577
  const words = stepWords(body);
5170
- const { prepareStep } = await import("./chunk-PZFZPHCT.js");
5578
+ const { prepareStep } = await import("./chunk-E7Q52EOO.js");
5171
5579
  const { code, prepared } = await prepareStep(root, runStep, words);
5172
5580
  ctx.events.publish({ type: "file.changed", path: runsRelOf(root) });
5173
5581
  if (!prepared.runId && code !== 0) {
@@ -5185,6 +5593,8 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5185
5593
  const busy = ctx.jobs.runningOf("step");
5186
5594
  if (busy)
5187
5595
  throw conflict(`An AI step is running on this server (${busy.id}): wait for it to finish, or cancel it.`);
5596
+ const { commandTitleInputsOf } = await import("./chunk-DGNTEKF6.js");
5597
+ const log = { command: commandTitleInputsOf([...words, "--mode", "model"]) };
5188
5598
  const job = ctx.jobs.start("step", async (c) => {
5189
5599
  c.progress(0, 1, `Running atticus ${words.join(" ")} with ${model}`);
5190
5600
  const before = new Set((await listRuns(root, { limit: 1e5 })).map((x) => x.runId));
@@ -5202,7 +5612,7 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5202
5612
  let applied;
5203
5613
  if (code === 0 && repo) {
5204
5614
  c.progress(0, 1, `Applying to ${repo}`);
5205
- const v = await trackedLocal(ctx, `Applying to ${repo}`, () => runStep(["verify", repo, "--write"]));
5615
+ const v = await trackedLocal(ctx, `Applying to ${repo}`, () => runStep(["verify", repo, "--write"]), { ids: [repo] });
5206
5616
  raw.push(...v.out, ...v.err);
5207
5617
  errs.push(...v.err);
5208
5618
  code = v.code;
@@ -5224,7 +5634,7 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5224
5634
  },
5225
5635
  errors: code === 0 ? [] : errs.length ? appLines(errs) : []
5226
5636
  };
5227
- }, { title: `atticus ${words.join(" ")}` });
5637
+ }, { title: `atticus ${words.join(" ")}`, log });
5228
5638
  return { status: 202, body: { jobId: job.id, model } };
5229
5639
  }).add("GET", "/api/runs", async ({ query }) => {
5230
5640
  const change = query.get("change") ?? void 0;
@@ -5347,6 +5757,12 @@ var CopilotRun = class {
5347
5757
  delete v.progress.session;
5348
5758
  break;
5349
5759
  }
5760
+ case "repo.stopped": {
5761
+ const { type: _t, ...problem2 } = e;
5762
+ (v.problems ??= []).push(problem2);
5763
+ out.push(this.push("run", [`Stopped: ${e.message}`]));
5764
+ break;
5765
+ }
5350
5766
  case "verify":
5351
5767
  v.totals.kept += e.kept;
5352
5768
  v.totals.rejected += e.rejected;
@@ -5385,25 +5801,51 @@ var CopilotRun = class {
5385
5801
 
5386
5802
  // packages/cli/dist/ui-api-copilot-runs.js
5387
5803
  var defaultStarter = (root) => async (o, io, deps) => {
5388
- const { mapAllCommand } = await import("./chunk-WM4EMP7T.js");
5804
+ const { mapAllCommand } = await import("./chunk-U36V664P.js");
5389
5805
  return mapAllCommand(root, o, io, {
5390
5806
  ...deps,
5391
- makeAcp: async () => (await import("./chunk-A6LGX56J.js")).acpStepRunner(root)
5807
+ makeAcp: async () => (await import("./chunk-V7DGFWDB.js")).acpStepRunner(root)
5392
5808
  });
5393
5809
  };
5394
5810
  var TAIL = 200;
5395
5811
  var NOT_ALLOWED = "runtime.yaml doesn't allow copilot-acp here (schemaVersion 3, copilot-acp in modes.allowed and copilot in assistants.allowed), so the app can't start Copilot itself. Read through Copilot Chat instead: atticus map --all in a terminal gives each part to paste.";
5396
- async function allowedHere(root) {
5812
+ var defaultCheck = async (root) => (await import("./chunk-QXXEOH3A.js")).generateAssistantFiles(root, {
5813
+ check: true,
5814
+ assistants: ["copilot"]
5815
+ });
5816
+ async function allowedHere(root, check) {
5397
5817
  try {
5398
5818
  const op = await loadOrgPack(orgPackDirOf(root));
5399
5819
  const c = copilotAcpOf(op.runtime);
5400
- return { allowed: copilotAcpAllowed(op), ...c.model ? { model: c.model } : {} };
5820
+ const allowed = copilotAcpAllowed(op);
5821
+ if (!allowed)
5822
+ return { allowed, ...c.model ? { model: c.model } : {} };
5823
+ const { assistantFilesState, limitFor, limitToOffer } = await import("./chunk-U36V664P.js");
5824
+ const known = await limitFor(root, op, void 0).catch(() => void 0);
5825
+ const offer = known ? void 0 : await limitToOffer(root);
5826
+ const limit = known ? {
5827
+ known: true,
5828
+ tokens: known.limit,
5829
+ from: known.from === "probe" ? "probe" : "runtime.yaml"
5830
+ } : { known: false, ...offer ? { tokens: offer.tokens, from: offer.from } : {} };
5831
+ const files = await check(root).then((r) => {
5832
+ const { shared, ...s } = assistantFilesState(r.results);
5833
+ return shared.length ? { ...s, shared } : s;
5834
+ }).catch(() => void 0);
5835
+ return {
5836
+ allowed,
5837
+ ...c.model ? { model: c.model } : {},
5838
+ limit,
5839
+ ...files ? { assistantFiles: files } : {}
5840
+ };
5401
5841
  } catch {
5402
5842
  return { allowed: false };
5403
5843
  }
5404
5844
  }
5405
5845
  var optionsOf = (b) => ({
5406
5846
  mode: "copilot-acp",
5847
+ // beta.27: the limit the person gave in the dialog, as --max-tokens.
5848
+ ...b.maxTokens !== void 0 ? { maxTokens: b.maxTokens } : {},
5407
5849
  ...b.kind === "stale" ? { stale: true } : {},
5408
5850
  ...b.kind === "gaps" ? { gaps: true } : {},
5409
5851
  ...b.repos?.length ? { repos: b.repos } : {},
@@ -5412,6 +5854,7 @@ var optionsOf = (b) => ({
5412
5854
  });
5413
5855
  function uiCopilotRunRoutes(r, ctx, deps = {}) {
5414
5856
  const start = deps.start ?? defaultStarter(ctx.root);
5857
+ const check = deps.assistantFiles ?? defaultCheck;
5415
5858
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
5416
5859
  const flushMs = deps.flushMs ?? 100;
5417
5860
  let run5;
@@ -5443,7 +5886,7 @@ function uiCopilotRunRoutes(r, ctx, deps = {}) {
5443
5886
  };
5444
5887
  return r.add("GET", "/api/copilot-runs/current", async ({ query }) => {
5445
5888
  if (!allowed || Date.now() - allowed.at > 1e4)
5446
- allowed = { at: Date.now(), v: await allowedHere(ctx.root) };
5889
+ allowed = { at: Date.now(), v: await allowedHere(ctx.root, check) };
5447
5890
  const a = allowed.v;
5448
5891
  const tail = Math.min(Math.max(Number(query.get("tail") ?? TAIL) || TAIL, 0), TAB_LINES);
5449
5892
  const view3 = run5 ? {
@@ -5459,7 +5902,9 @@ function uiCopilotRunRoutes(r, ctx, deps = {}) {
5459
5902
  run: view3,
5460
5903
  allowed: a.allowed,
5461
5904
  ...a.allowed ? {} : { why: NOT_ALLOWED },
5462
- ...a.model ? { model: a.model } : {}
5905
+ ...a.model ? { model: a.model } : {},
5906
+ ...a.limit ? { limit: a.limit } : {},
5907
+ ...a.assistantFiles ? { assistantFiles: a.assistantFiles } : {}
5463
5908
  }
5464
5909
  };
5465
5910
  }).add("POST", "/api/copilot-runs", async ({ body }) => {
@@ -5480,14 +5925,27 @@ function uiCopilotRunRoutes(r, ctx, deps = {}) {
5480
5925
  starting = true;
5481
5926
  let a;
5482
5927
  try {
5483
- a = await allowedHere(ctx.root);
5928
+ a = await allowedHere(ctx.root, check);
5484
5929
  } finally {
5485
5930
  starting = false;
5486
5931
  }
5932
+ allowed = { at: Date.now(), v: a };
5487
5933
  if (!a.allowed)
5488
5934
  throw conflict(NOT_ALLOWED);
5935
+ if (a.limit && !a.limit.known && b.data.maxTokens === void 0) {
5936
+ throw new HttpError(400, "The model's limit is needed", "Atticus doesn't know your model's limit, and a part planned too big overflows the reader: give it in the dialog (Your model's limit, in tokens), the context window of the model Copilot uses. It is kept on this machine for the next run.", { code: "limit-unknown" });
5937
+ }
5938
+ if (a.assistantFiles?.edited.length) {
5939
+ const { assistantFilesEditedWords } = await import("./chunk-U36V664P.js");
5940
+ throw new HttpError(409, "Assistant files edited by hand", assistantFilesEditedWords(a.assistantFiles.edited), { code: "assistant-files-edited", files: a.assistantFiles.edited });
5941
+ }
5489
5942
  if (ctx.jobs.runningOf("step")?.state === "running")
5490
5943
  throw conflict("An AI step started on this server meanwhile: wait for it to finish.");
5944
+ if (b.data.maxTokens !== void 0) {
5945
+ const { saveLastLimit } = await import("./chunk-U36V664P.js");
5946
+ await saveLastLimit(ctx.root, b.data.maxTokens, now().getTime());
5947
+ allowed = void 0;
5948
+ }
5491
5949
  const runId = `copilot-run-${now().getTime().toString(36)}-${randomBytes(3).toString("hex")}-${++seq}`;
5492
5950
  const me = new CopilotRun({
5493
5951
  runId,
@@ -5659,7 +6117,7 @@ function uiLinkMatchRoutes(r, ctx, deps = {}) {
5659
6117
  if (me && done.error)
5660
6118
  me.error = done.error;
5661
6119
  return done.state === "failed" ? { errors: [done.error ?? "The session ended without an answer."] } : { result: { state: done.state } };
5662
- }, { title: `Match ${from} with ${view3.toName}` });
6120
+ }, { title: `Match ${from} with ${view3.toName}`, log: { ids: [from] } });
5663
6121
  running.set(key, { jobId: job.id });
5664
6122
  const files = await readMatch(ctx.root, view3);
5665
6123
  return {
@@ -5712,7 +6170,7 @@ function uiDecisionRoutes(r, ctx, deps = {}) {
5712
6170
  ctx.events.publish({ type: "file.changed", path });
5713
6171
  return { status: 200, body: out };
5714
6172
  }).add("GET", "/api/propose-answers", async () => {
5715
- const { openDecideRun, PROPOSE_CHANGE } = await import("./chunk-ZLBUFK7L.js");
6173
+ const { openDecideRun, PROPOSE_CHANGE } = await import("./chunk-LCWC6NDE.js");
5716
6174
  const run5 = await openDecideRun(ctx.root, PROPOSE_CHANGE);
5717
6175
  const body = run5 ? {
5718
6176
  state: "waiting",
@@ -5726,7 +6184,7 @@ function uiDecisionRoutes(r, ctx, deps = {}) {
5726
6184
  const op = await loadOrgPack(orgPackDirOf(ctx.root));
5727
6185
  if (op.runtime.ai === "off")
5728
6186
  throw conflict("runtime.yaml turns AI off here (ai: off): answer the questions yourself.");
5729
- const { startProposeHandoff } = await import("./chunk-A6LGX56J.js");
6187
+ const { startProposeHandoff } = await import("./chunk-V7DGFWDB.js");
5730
6188
  const h = await startProposeHandoff(ctx.root, { now: now() });
5731
6189
  const body = {
5732
6190
  state: "waiting",
@@ -5857,11 +6315,11 @@ git commit -m "${safeMessage(`${change}: drawn on the canvas`)}"`;
5857
6315
  }
5858
6316
 
5859
6317
  // packages/cli/dist/ui-api-owner.js
5860
- var REPO = /^[A-Za-z0-9._-]{1,200}$/;
6318
+ var REPO2 = /^[A-Za-z0-9._-]{1,200}$/;
5861
6319
  var TEAM = /^[a-z0-9][a-z0-9-]{0,62}$/;
5862
6320
  function uiOwnerRoutes(r, ctx) {
5863
6321
  const options = async (repo) => {
5864
- if (!REPO.test(repo))
6322
+ if (!REPO2.test(repo))
5865
6323
  throw badRequest(`${JSON.stringify(repo)} isn't a repo name.`);
5866
6324
  const op = await loadOrgPack(orgPackDirOf(ctx.root));
5867
6325
  const entry = estateRepos(op).find((x) => x.id === repo);
@@ -5959,7 +6417,7 @@ git commit -m "${safeMessage(`${repo}: ${[owner ? `owner ${owner}` : "", system
5959
6417
  // packages/cli/dist/ui-api-declared.js
5960
6418
  import { readFile as readFile8 } from "node:fs/promises";
5961
6419
  import { join as join11 } from "node:path";
5962
- var REPO2 = /^[A-Za-z0-9._-]{1,200}$/;
6420
+ var REPO3 = /^[A-Za-z0-9._-]{1,200}$/;
5963
6421
  var says = (c) => {
5964
6422
  const what = `${c.target.kind} ${c.target.value} (${c.target.file}:${c.target.line})`;
5965
6423
  if (c.action === "wrong")
@@ -6108,7 +6566,7 @@ git commit -m "${safeMessage(`profile: ${b.data.system}: a declaration undone`)}
6108
6566
  throw badRequest("Say repo=<repo> or system=<id>.");
6109
6567
  const items = [];
6110
6568
  if (repo) {
6111
- if (!REPO2.test(repo))
6569
+ if (!REPO3.test(repo))
6112
6570
  throw badRequest(`${JSON.stringify(repo)} isn't a repo name.`);
6113
6571
  const rel = `${factsRelOf(ctx.root)}/${repo}.corrections.jsonl`;
6114
6572
  const text = await readFile8(join11(factsDirOf(ctx.root), `${repo}.corrections.jsonl`), "utf8").catch(() => "");
@@ -6383,7 +6841,7 @@ function uiDocumentRoutes(r, ctx) {
6383
6841
  const root = ctx.root;
6384
6842
  const changed = (path) => ctx.events.publish({ type: "file.changed", path });
6385
6843
  return r.add("GET", "/api/knowledge/documents", async () => {
6386
- const { listDocuments } = await import("./chunk-KFJMQUSK.js");
6844
+ const { listDocuments } = await import("./chunk-7HUCEHUK.js");
6387
6845
  return { status: 200, body: api_exports.DocumentList.parse(await listDocuments(root)) };
6388
6846
  }).add("POST", "/api/knowledge/documents", async ({ body }) => {
6389
6847
  const b = api_exports.AttachFileRequest.safeParse(body ?? {});
@@ -6392,7 +6850,7 @@ function uiDocumentRoutes(r, ctx) {
6392
6850
  const bytes = new Uint8Array(Buffer.from(b.data.content, "base64"));
6393
6851
  if (bytes.length > MAX_FILE)
6394
6852
  throw new HttpError(413, "The file is too large", "Add a file of 15 MB or less.");
6395
- const { addToInbox } = await import("./chunk-QQAWI5LD.js");
6853
+ const { addToInbox } = await import("./chunk-MP7W6OKP.js");
6396
6854
  const res = await addToInbox(root, [{ name: b.data.name, bytes }]);
6397
6855
  if (!res.added.length)
6398
6856
  throw new HttpError(422, "Atticus can't add that", res.refused[0]?.why ?? "", {
@@ -6402,7 +6860,7 @@ function uiDocumentRoutes(r, ctx) {
6402
6860
  changed(a.path);
6403
6861
  return { status: 201, body: api_exports.AddDocumentResult.parse(res) };
6404
6862
  }, { maxBody: Math.ceil(MAX_FILE * 4 / 3) + 64 * 1024 }).add("POST", "/api/changes/{changeId}/inputs/{name}/promote", async ({ params }) => {
6405
- const { AttachError, promoteChangeInput } = await import("./chunk-7ZBYRMWK.js");
6863
+ const { AttachError, promoteChangeInput } = await import("./chunk-OY2VC2IU.js");
6406
6864
  try {
6407
6865
  const res = await promoteChangeInput(root, params.changeId, params.name);
6408
6866
  changed(res.path);
@@ -6419,13 +6877,13 @@ function uiDocumentRoutes(r, ctx) {
6419
6877
  function uiRepoRoutes(r, ctx) {
6420
6878
  const root = ctx.root;
6421
6879
  return r.add("GET", "/api/repos/branches", async () => {
6422
- const { repoBranches } = await import("./chunk-FIZ5LYL2.js");
6880
+ const { repoBranches } = await import("./chunk-LQEMCF43.js");
6423
6881
  return { status: 200, body: api_exports.RepoBranchesList.parse(await repoBranches(root)) };
6424
6882
  }).add("GET", "/api/repos/compare", async ({ query }) => {
6425
6883
  const branch = query.get("branch")?.trim() ?? "";
6426
6884
  if (!branch)
6427
6885
  throw badRequest("Say which branch: ?branch=<name>.");
6428
- const { compareBranch } = await import("./chunk-FIZ5LYL2.js");
6886
+ const { compareBranch } = await import("./chunk-LQEMCF43.js");
6429
6887
  const c = await compareBranch(root, branch);
6430
6888
  if (!c)
6431
6889
  throw notFound(`${branch} hasn't been scanned beside the baseline yet.`);
@@ -6434,7 +6892,7 @@ function uiRepoRoutes(r, ctx) {
6434
6892
  const b = api_exports.EditRepoBranchesRequest.safeParse(body ?? {});
6435
6893
  if (!b.success)
6436
6894
  throw badRequest("Send defaultBranch and branches as branch names.");
6437
- const { editRepoBranches, RepoEditError } = await import("./chunk-FIZ5LYL2.js");
6895
+ const { editRepoBranches, RepoEditError } = await import("./chunk-LQEMCF43.js");
6438
6896
  try {
6439
6897
  const file = await editRepoBranches(root, params.repoId, b.data);
6440
6898
  ctx.events.publish({ type: "file.changed", path: file });
@@ -6454,7 +6912,7 @@ function uiRepoRoutes(r, ctx) {
6454
6912
  const b = api_exports.EditRepoBuildRequest.safeParse(body ?? {});
6455
6913
  if (!b.success)
6456
6914
  throw badRequest('Send the build command as build ("" clears it), up to 500 characters.');
6457
- const { editRepoBuild, RepoEditError } = await import("./chunk-FIZ5LYL2.js");
6915
+ const { editRepoBuild, RepoEditError } = await import("./chunk-LQEMCF43.js");
6458
6916
  try {
6459
6917
  const r2 = await editRepoBuild(root, params.repoId, b.data);
6460
6918
  ctx.events.publish({ type: "file.changed", path: r2.file });
@@ -6475,7 +6933,7 @@ function uiRepoRoutes(r, ctx) {
6475
6933
  const b = api_exports.SetOrgPackOwnerRequest.safeParse(body ?? {});
6476
6934
  if (!b.success)
6477
6935
  throw badRequest("Send the owner as one handle: { owner }.");
6478
- const { setOrgPackOwner, OwnerEditError } = await import("./chunk-VTR4AC2U.js");
6936
+ const { setOrgPackOwner, OwnerEditError } = await import("./chunk-RZYRUXSU.js");
6479
6937
  try {
6480
6938
  const r2 = await setOrgPackOwner(root, b.data.owner, b.data.was);
6481
6939
  ctx.events.publish({ type: "file.changed", path: r2.file });
@@ -6496,7 +6954,7 @@ function uiRepoRoutes(r, ctx) {
6496
6954
  const b = api_exports.EditRepoDescriptionRequest.safeParse(body ?? {});
6497
6955
  if (!b.success)
6498
6956
  throw badRequest("Send what the repo is as text, or accept: true to confirm the draft, or reject: true to drop it.");
6499
- const { editRepoDescription, RepoEditError } = await import("./chunk-FIZ5LYL2.js");
6957
+ const { editRepoDescription, RepoEditError } = await import("./chunk-LQEMCF43.js");
6500
6958
  try {
6501
6959
  const r2 = await editRepoDescription(root, params.repoId, b.data);
6502
6960
  ctx.events.publish({ type: "file.changed", path: r2.file });
@@ -6525,19 +6983,21 @@ function changeIdOf(v) {
6525
6983
  function uiCockpitRoutes(r, ctx) {
6526
6984
  return r.add("GET", "/api/changes/{changeId}/cockpit", async ({ params }) => {
6527
6985
  const id = changeIdOf(params.changeId);
6528
- const { cockpit } = await import("./chunk-ZYLGEWTC.js");
6986
+ const { cockpit } = await import("./chunk-FFIHRQ3O.js");
6529
6987
  try {
6530
6988
  return await keptAnswer(ctx.root, `cockpit:${id}:${ctx.user}`, async () => ({
6531
6989
  status: 200,
6532
6990
  body: api_exports.ChangeCockpit.parse(await cockpit(ctx.root, id, { user: ctx.user }))
6533
6991
  }), () => checkoutsStamp(ctx.root));
6534
6992
  } catch (e) {
6535
- if (e instanceof Error && e.name === "ChangeFileError")
6536
- throw notFound(`There is no change ${params.changeId}.`);
6993
+ if (e instanceof Error && e.name === "ChangeFileError") {
6994
+ const { missingChangeWords: missingChangeWords2 } = await import("./chunk-VGXE7XFO.js");
6995
+ throw notFound(await missingChangeWords2(ctx.root, id));
6996
+ }
6537
6997
  throw e;
6538
6998
  }
6539
6999
  }).add("GET", "/api/past-changes", async ({ query }) => {
6540
- const { changeAboutText, similarChanges } = await import("./chunk-KUEG2Y7M.js");
7000
+ const { changeAboutText, similarChanges } = await import("./chunk-FYRBBFIF.js");
6541
7001
  const given = query.get("change");
6542
7002
  const change = given ? changeIdOf(given) : void 0;
6543
7003
  const text = change ? await changeAboutText(ctx.root, change) : query.get("text")?.trim();
@@ -6556,11 +7016,11 @@ function uiCockpitRoutes(r, ctx) {
6556
7016
  const b = api_exports.AttachPastChangeRequest.safeParse(body ?? {});
6557
7017
  if (!b.success)
6558
7018
  throw badRequest("Say which archived change: { like: <its folder or id> }.");
6559
- const { attachPastChange, findPastChange } = await import("./chunk-KUEG2Y7M.js");
7019
+ const { attachPastChange, findPastChange } = await import("./chunk-FYRBBFIF.js");
6560
7020
  const folder = await findPastChange(ctx.root, b.data.like);
6561
7021
  if (!folder)
6562
7022
  throw notFound(`There is no archived change ${b.data.like}.`);
6563
- const { AttachError } = await import("./chunk-7ZBYRMWK.js");
7023
+ const { AttachError } = await import("./chunk-OY2VC2IU.js");
6564
7024
  try {
6565
7025
  const name = await attachPastChange(ctx.root, params.changeId, folder, ctx.user);
6566
7026
  ctx.events.publish({ type: "file.changed", path: `inputs/${name}` });
@@ -6577,9 +7037,9 @@ function uiCockpitRoutes(r, ctx) {
6577
7037
  }
6578
7038
 
6579
7039
  // packages/cli/dist/ui-api-audit.js
6580
- var REPO3 = /^[a-z0-9][a-z0-9._-]{0,99}$/i;
7040
+ var REPO4 = /^[a-z0-9][a-z0-9._-]{0,99}$/i;
6581
7041
  var repoOf = (v) => {
6582
- if (!REPO3.test(v))
7042
+ if (!REPO4.test(v))
6583
7043
  throw badRequest(`${JSON.stringify(v)} isn't a repo name.`);
6584
7044
  return v;
6585
7045
  };
@@ -6690,6 +7150,8 @@ var OUTSIDE_ADD_SPEC = (id) => [
6690
7150
  "atticus intake list",
6691
7151
  "atticus triage"
6692
7152
  ];
7153
+ var OUTSIDE_ALIAS_CLASH = (name, host, repo) => `${host} is one of ${name}'s aliases in the profile, but ${repo} answers on it (repos.manifest.yaml lists it), so calls to it go to ${repo}, not to ${name}. If ${repo} is the gateway in front of ${name}, take ${host} out of ${name}'s aliases.`;
7154
+ var OUTSIDE_SPEC_HOST_CLASH = (name, host, repo, spec) => `${host} is a server in ${name}'s spec (${spec}), but repos.manifest.yaml lists it under ${repo}'s hosts, so calls to it go to ${repo}, not to ${name}. If ${repo} doesn't answer on ${host}, take it out of ${repo}'s hosts in repos.manifest.yaml.`;
6693
7155
  async function outsideView(root) {
6694
7156
  const quiet = { out: () => void 0, err: () => void 0 };
6695
7157
  const { op, records, inputs } = await intakeContext(root, quiet);
@@ -6740,8 +7202,22 @@ async function outsideView(root) {
6740
7202
  repos,
6741
7203
  vendors,
6742
7204
  targets: estate.targets,
6743
- ...joinConventions(op)
7205
+ ...joinConventions(op),
7206
+ // Beta.27: a service's call the join lands on a gateway's route reaches the system
7207
+ // through it (listed behind the route), never as a direct call.
7208
+ joined: joined.joins
6744
7209
  }) : { matches: [], gaps: [], asks: [] };
7210
+ const reaches = /* @__PURE__ */ new Map();
7211
+ for (const m of matched.matches) {
7212
+ const k = `${m.vendor}\0${m.call.repo}\0${m.call.fact}`;
7213
+ reaches.set(k, [.../* @__PURE__ */ new Set([...reaches.get(k) ?? [], m.operation])].sort());
7214
+ }
7215
+ const opsOf = (vendor, e) => {
7216
+ const ops = reaches.get(`${vendor}\0${e.repo}\0${e.fact}`) ?? [];
7217
+ return { operation: ops[0], ...ops.length > 1 ? { operations: ops } : {} };
7218
+ };
7219
+ const manifests = estateRepos(op);
7220
+ const clashes = (hosts) => hosts.flatMap((h) => manifests.filter((m) => [...m.hosts ?? [], ...(m.modules ?? []).flatMap((x) => x.hosts ?? [])].some((p) => hostMatches(p, h))).map((m) => ({ host: h, repo: m.id })));
6745
7221
  const contracts = await contractCheckOf(root).catch(() => void 0);
6746
7222
  const catalog = records.length ? records : (await readCatalog(join13(catalogDirOf(root), "generated"), { cacheRoot: root })).records;
6747
7223
  const ifaces = catalog.filter((r) => r.kind === "Interface");
@@ -6804,18 +7280,20 @@ async function outsideView(root) {
6804
7280
  }
6805
7281
  for (const g of [...matched.gaps, ...matched.asks].filter((x) => x.vendor === s.id))
6806
7282
  add(callOf(g.call), "spec");
7283
+ const once = /* @__PURE__ */ new Set();
6807
7284
  for (const m of matched.matches.filter((x) => x.vendor === s.id)) {
6808
- add({ ...callOf(m.call), operation: m.operation }, "spec");
7285
+ const k = `${m.call.repo}\0${m.call.fact}`;
7286
+ if (once.has(k))
7287
+ continue;
7288
+ once.add(k);
7289
+ const ops = opsOf(s.id, m.call);
7290
+ add({ ...callOf(m.call), ...ops }, "spec");
6809
7291
  if (m.direct || !m.route)
6810
7292
  continue;
6811
7293
  const route = m.route;
6812
7294
  for (const j of joined.joins)
6813
7295
  if (j.entry.repo === route.repo && j.entry.fact === route.fact)
6814
- add({
6815
- ...callOf(j.call),
6816
- operation: m.operation,
6817
- through: { repo: route.repo, at: route.at }
6818
- }, "spec");
7296
+ add({ ...callOf(j.call), ...ops, through: { repo: route.repo, at: route.at } }, "spec");
6819
7297
  }
6820
7298
  for (const m of sharedJoin.matches.filter((x) => x.system === s.id))
6821
7299
  add({
@@ -6830,6 +7308,11 @@ async function outsideView(root) {
6830
7308
  const lines = new Set(list.map((c) => `${c.repo}|${c.at}`));
6831
7309
  const named = [s.id, s.name, ...s.aliases].map((n) => n.toLowerCase());
6832
7310
  const questions = open.filter((q) => named.some((n) => q.question.toLowerCase().includes(n)) || q.options.some((o) => named.some((n) => o.label.toLowerCase().includes(n))) || q.evidence.some((e) => lines.has(`${q.repo}|${e}`))).map((q) => ({ id: q.id, repo: q.repo, question: q.question })).sort((a, b) => cmp(a.id, b.id));
7311
+ const aliasHosts = hostAliases(s.aliases);
7312
+ const notes = [
7313
+ ...clashes(aliasHosts).map((c) => OUTSIDE_ALIAS_CLASH(s.name, c.host, c.repo)),
7314
+ ...spec ? clashes(spec.hosts.filter((h) => !aliasHosts.some((a) => hostMatches(a, h)))).map((c) => OUTSIDE_SPEC_HOST_CLASH(s.name, c.host, c.repo, spec.path)) : []
7315
+ ];
6833
7316
  return {
6834
7317
  id: s.id,
6835
7318
  name: s.name,
@@ -6847,13 +7330,14 @@ async function outsideView(root) {
6847
7330
  method: o.method,
6848
7331
  path: o.fullPath,
6849
7332
  cite: o.cite,
6850
- calls: list.filter((c) => c.operation === o.id).length
7333
+ calls: list.filter((c) => c.operation === o.id || !!c.operations?.includes(o.id)).length
6851
7334
  }))
6852
7335
  }
6853
7336
  } : {},
6854
7337
  unmatched: matched.gaps.filter((g) => g.vendor === s.id).map((g) => ({ ...callOf(g.call), seen: ["spec"], message: g.message })),
6855
7338
  ambiguous: matched.asks.filter((a) => a.vendor === s.id).map((a) => ({ ...callOf(a.call), seen: ["spec"], candidates: a.candidates })),
6856
7339
  questions,
7340
+ ...notes.length ? { notes } : {},
6857
7341
  ...spec ? {} : { addSpec: OUTSIDE_ADD_SPEC(s.id) },
6858
7342
  ...contractsOf(s.id),
6859
7343
  ...map ? {
@@ -7528,11 +8012,19 @@ async function stageThreadView(root, change, stage) {
7528
8012
  items.sort((a, b) => a.at < b.at ? -1 : a.at > b.at ? 1 : 0);
7529
8013
  if (waiting)
7530
8014
  state = "waiting";
8015
+ const writtenElsewhere = stage === "proposal" && state === "not-started" && await artifactWritten(root, change, "proposal").catch(() => false);
8016
+ if (writtenElsewhere)
8017
+ state = "done";
8018
+ const byPerson = stage === "stories" && state === "not-started" ? await personWrittenPlanning(dir) : [];
8019
+ if (byPerson.length) {
8020
+ state = "done";
8021
+ replyWhy = `A person wrote ${change}'s planning files outside the app, so no assistant waits for a reply: draft the stories again to start one.`;
8022
+ }
7531
8023
  const open = items.filter((i) => i.kind === "finding" && i.view.finding.state === "open").length;
7532
8024
  const questions = items.filter((i) => i.kind === "question" && i.question.state === "open").length;
7533
8025
  const dropped = items.filter((i) => i.kind === "dropped").length;
7534
8026
  const waitingWho = waiting ? runs.find((s) => s.run.runId === waiting.runId && isLens(agentOf2(s))) ? "critic" : "drafter" : void 0;
7535
- const headline = state === "not-started" ? `The ${stage} stage hasn't started for this change. Start it: Atticus writes the prompt for your assistant.` : waiting ? waitingWho === "critic" ? "The critic's prompt below waits for your assistant. Paste it in; the app checks the answer as soon as the file is written." : "The prompt below waits for your assistant. Paste it in; the app checks the answer as soon as the file is written." : lastFailed ? "Your assistant's last answer didn't pass its checks: the problems are below. Tell the assistant, or fix the file and the app checks it again." : state === "questions" ? `The stage waits on ${questions === 1 ? "the question" : `${questions} questions`} below.` : state === "stopped" ? "The stage stopped: its assistant couldn't fix what was found. Fix the file it names, or tell the assistant." : state === "done" ? `The stage is done${open ? `, with ${open} open finding${open === 1 ? "" : "s"}` : ""}.` : "Ready for the next round: tell the assistant what to change, or start the round.";
8027
+ const headline = writtenElsewhere ? `The proposal is written (${rel}/proposal.md): it was written outside the app, so this conversation has nothing in it.` : byPerson.length ? `A person wrote ${byPerson.join(" and ").replace(/ and (?=.* and )/g, ", ")} outside the app, so the stories stage never ran and this conversation has nothing in it. The change goes on from them; to have the stage write them instead, draft the stories again (it replaces them).` : state === "not-started" ? `The ${stage} stage hasn't started for this change. Start it: Atticus writes the prompt for your assistant.` : waiting ? waitingWho === "critic" ? "The critic's prompt below waits for your assistant. Paste it in; the app checks the answer as soon as the file is written." : "The prompt below waits for your assistant. Paste it in; the app checks the answer as soon as the file is written." : lastFailed ? "Your assistant's last answer didn't pass its checks: the problems are below. Tell the assistant, or fix the file and the app checks it again." : state === "questions" ? `The stage waits on ${questions === 1 ? "the question" : `${questions} questions`} below.` : state === "stopped" ? "The stage stopped: its assistant couldn't fix what was found. Fix the file it names, or tell the assistant." : state === "done" ? `The stage is done${open ? `, with ${open} open finding${open === 1 ? "" : "s"}` : ""}.` : "Ready for the next round: tell the assistant what to change, or start the round.";
7536
8028
  if (dropped)
7537
8029
  items.push({
7538
8030
  kind: "note",
@@ -7547,6 +8039,7 @@ async function stageThreadView(root, change, stage) {
7547
8039
  items,
7548
8040
  ...waiting ? { waiting } : {},
7549
8041
  step: stageStep(stage, change),
8042
+ ...byPerson.length ? { byPerson } : {},
7550
8043
  reply: { open: replyOpen, ...replyWhy ? { why: replyWhy } : {} },
7551
8044
  problems
7552
8045
  };
@@ -7563,7 +8056,7 @@ function uiThreadRoutes(r, ctx, deps = {}) {
7563
8056
  if (!ID7.test(v))
7564
8057
  throw badRequest(`${JSON.stringify(v)} isn't a change id.`);
7565
8058
  if (!await stat8(join16(changeFolder(ctx.root, v), "change.yaml")).catch(() => void 0))
7566
- throw notFound(`There is no change ${v}.`);
8059
+ throw notFound(await missingChangeWords(ctx.root, v));
7567
8060
  return v;
7568
8061
  };
7569
8062
  const refused4 = (e) => {
@@ -7755,7 +8248,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7755
8248
  };
7756
8249
  return r.add("GET", "/api/setup/metarepo", async () => {
7757
8250
  const origin = await originOf(root);
7758
- const { metarepoIdFromUrl } = await import("./chunk-5UIGGXA5.js");
8251
+ const { metarepoIdFromUrl } = await import("./chunk-U4K34CXK.js");
7759
8252
  const folder = basename2(root);
7760
8253
  const body = {
7761
8254
  metarepo: isMetarepo(root),
@@ -7773,7 +8266,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7773
8266
  const b = parseBody4(api_exports.CreateMetarepoRequest, body);
7774
8267
  if (isMetarepo(root))
7775
8268
  throw conflict(`${root} is a metarepo already.`);
7776
- const { initCommand } = await import("./chunk-U3JXMY56.js");
8269
+ const { initCommand } = await import("./chunk-OOZKLLW7.js");
7777
8270
  const res = await run4((io) => initCommand(root, {
7778
8271
  name: b.name,
7779
8272
  platform: b.platform,
@@ -7798,10 +8291,11 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7798
8291
  if (!await stat9(dir).then((s) => s.isDirectory(), () => false))
7799
8292
  throw notFound(`There is no folder ${dir} on this machine.`);
7800
8293
  const open = deps.openFolder ?? (async (d) => {
7801
- const { startUi: startUi2 } = await import("./chunk-P6EJNPFF.js");
8294
+ const { startUi: startUi2 } = await import("./chunk-MBIJNU3D.js");
7802
8295
  const srv = await startUi2(d, {
7803
8296
  port: 0,
7804
8297
  user,
8298
+ runLog: true,
7805
8299
  ...ctx.version ? { version: ctx.version } : {}
7806
8300
  });
7807
8301
  ctx.onClose?.add(() => void srv.close());
@@ -7830,7 +8324,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7830
8324
  };
7831
8325
  return { status: 200, body: ask };
7832
8326
  }
7833
- const { reposDiscover, AdoptError } = await import("./chunk-5UIGGXA5.js");
8327
+ const { reposDiscover, AdoptError } = await import("./chunk-U4K34CXK.js");
7834
8328
  const found = await reposDiscover(root, { dir }, { dryRun: true, ...b.platform ? { platform: b.platform } : {} }).catch((e) => {
7835
8329
  if (e instanceof AdoptError)
7836
8330
  throw unprocessable2(e.message.replace(/ with --platform\b/g, " (choose the platform)"));
@@ -7847,7 +8341,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7847
8341
  detected: { signals: f.detection.signals, confidence: f.detection.confidence }
7848
8342
  }));
7849
8343
  } else {
7850
- const { cloneAt, typeOf } = await import("./chunk-RCLBIJRN.js");
8344
+ const { cloneAt, typeOf } = await import("./chunk-UGJSKAZ2.js");
7851
8345
  for (const given of pastedUrls(b.urls ?? "").slice(0, 500)) {
7852
8346
  const c = candidateOf(given);
7853
8347
  const clone = await cloneAt(c.url);
@@ -7918,13 +8412,13 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7918
8412
  const id = params.repoId;
7919
8413
  if (!(await loadRepos(root).catch(() => [])).some((x) => x.id === id))
7920
8414
  throw notFound(`There is no repo ${id} in any manifest.`);
7921
- const { repoFor } = await import("./chunk-DASVVML7.js");
8415
+ const { repoFor } = await import("./chunk-ZIAMPN7N.js");
7922
8416
  const repo = await repoFor(root, id);
7923
8417
  if (!repo)
7924
8418
  throw conflict(`${id} isn't cloned here yet, so there are no files to read its type from: clone it first (Sync on Onboarding, or atticus workspace sync).`);
7925
8419
  const op = await loadOrgPack(orgPackDirOf(root));
7926
8420
  if (op.repoTypes.length) {
7927
- const { repoTypeDetect } = await import("./chunk-GSIJWDXH.js");
8421
+ const { repoTypeDetect } = await import("./chunk-66CMRGI2.js");
7928
8422
  const res = await run4((io) => repoTypeDetect(root, id, { json: true }, io));
7929
8423
  if (res.code !== 0)
7930
8424
  throw unprocessable2([...res.err, ...res.out].join("\n"));
@@ -7938,7 +8432,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7938
8432
  };
7939
8433
  return { status: 200, body: body2 };
7940
8434
  }
7941
- const { typeOf } = await import("./chunk-RCLBIJRN.js");
8435
+ const { typeOf } = await import("./chunk-UGJSKAZ2.js");
7942
8436
  const t = await typeOf(repo.dir, void 0);
7943
8437
  const body = {
7944
8438
  repo: id,
@@ -8079,7 +8573,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
8079
8573
  const b = parseBody4(api_exports.SourceRequest, body);
8080
8574
  const file = join17(orgPackDirOf(root), "sources.yaml");
8081
8575
  const before = await readFile13(file, "utf8").catch(() => "");
8082
- const { sourcesAdd: sourcesAdd2 } = await import("./chunk-CPE7HLIK.js");
8576
+ const { sourcesAdd: sourcesAdd2 } = await import("./chunk-YTPND655.js");
8083
8577
  const res = await run4((io) => sourcesAdd2(root, b.type, b.location.trim(), io, {
8084
8578
  ...b.id ? { id: b.id } : {},
8085
8579
  ...b.path ? { path: b.path } : {},
@@ -8102,7 +8596,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
8102
8596
  };
8103
8597
  }
8104
8598
  const after = await readFile13(file, "utf8").catch(() => "");
8105
- const { changedLines: changedLines2, lfOnly: lfOnly2 } = await import("./chunk-UXVKFOMC.js");
8599
+ const { changedLines: changedLines2, lfOnly: lfOnly2 } = await import("./chunk-PPKH6ULR.js");
8106
8600
  changed(path);
8107
8601
  return {
8108
8602
  status: 200,
@@ -8126,8 +8620,9 @@ function changeIdOf2(v) {
8126
8620
  function uiRolesRoutes(r, ctx, deps = {}) {
8127
8621
  const root = ctx.root;
8128
8622
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
8623
+ const sending = /* @__PURE__ */ new Set();
8129
8624
  ctx.askKnowledge = async (q) => {
8130
- const { knowledgeAnswerOf } = await import("./chunk-IP6ARMZU.js");
8625
+ const { knowledgeAnswerOf } = await import("./chunk-PT77IUYQ.js");
8131
8626
  return api_exports.KnowledgeAnswerView.parse(await knowledgeAnswerOf(root, q));
8132
8627
  };
8133
8628
  const exists4 = async (id) => {
@@ -8188,7 +8683,7 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8188
8683
  const id = changeIdOf2(params.changeId);
8189
8684
  if (!await exists4(id))
8190
8685
  throw notFound(`There is no change ${id}.`);
8191
- const { ownerSuggestions } = await import("./chunk-IP6ARMZU.js");
8686
+ const { ownerSuggestions } = await import("./chunk-PT77IUYQ.js");
8192
8687
  return {
8193
8688
  status: 200,
8194
8689
  body: api_exports.OwnerSuggestionList.parse(await ownerSuggestions(root, id))
@@ -8245,7 +8740,9 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8245
8740
  throw new HttpError(422, "Atticus refused", e.message);
8246
8741
  });
8247
8742
  if (b.data.job)
8248
- return answerAsJob(ctx, `Putting work items in the tracker: ${id}`, answer);
8743
+ return answerAsJob(ctx, `Putting work items in the tracker: ${id}`, answer, {
8744
+ ids: [id]
8745
+ });
8249
8746
  return { status: 200, body: await answer() };
8250
8747
  }).add("GET", "/api/changes/{changeId}/stories/shape", async ({ params }) => {
8251
8748
  const id = changeIdOf2(params.changeId);
@@ -8298,13 +8795,13 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8298
8795
  const b = api_exports.SendOwnerAskRequest.safeParse(body ?? {});
8299
8796
  if (!b.success)
8300
8797
  throw badRequest("Send { confirmation? }.");
8301
- const { ownerQuestions } = await import("./chunk-CUTMM4NY.js");
8798
+ const { ownerQuestions } = await import("./chunk-SSYD4XIW.js");
8302
8799
  const list = await ownerQuestions(root, { now: now() });
8303
8800
  const q = list.questions.find((x) => x.id === params.id);
8304
8801
  if (!q)
8305
8802
  throw notFound(`There is no owner question ${params.id}.`);
8306
- const { notifierFor } = await import("./chunk-IP6ARMZU.js");
8307
- const n = await notifierFor(root, q.finding?.change, deps.notify);
8803
+ const { fallbackWords, notifierFor } = await import("./chunk-PT77IUYQ.js");
8804
+ const n = await notifierFor(root, q.finding?.change, deps.notify, deps.adapterFactories ? { factories: deps.adapterFactories } : {});
8308
8805
  const to = q.owner;
8309
8806
  if (!n.notify || n.kind === "none")
8310
8807
  return {
@@ -8315,50 +8812,81 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8315
8812
  why: "No notifications are set up here (runtime.yaml adapters.notify): copy the question and ask the owner, then record what they said."
8316
8813
  })
8317
8814
  };
8318
- if (n.kind === "live")
8319
- requireConfirmation(ctx.confirmations, "owner-ask", q.id, b.data.confirmation);
8320
- const team = (await readTeams(root)).teams.find((t) => t.id === to);
8321
- const mentions = team ? team.people.map((p) => p.replace(/^@/, "")) : [to.replace(/^@/, "")];
8322
- const channel = q.channel && q.channel !== "Atticus" ? q.channel : `@${to.replace(/^@/, "")}`;
8815
+ const { ownerAskRef, recordedSendAt, recordOwnerSend } = await import("./chunk-SSYD4XIW.js");
8816
+ if (sending.has(q.id))
8817
+ throw new HttpError(409, "Being sent", `${q.id} is being sent to ${to} now, from another tab or window: reload to see it sent.`, { code: "being-sent" });
8818
+ sending.add(q.id);
8323
8819
  try {
8324
- const sent = await n.notify.send({
8325
- channel,
8326
- title: `A question for ${team?.name ?? to}`,
8327
- body: `${q.question}
8820
+ const was = q.finding ? void 0 : await recordedSendAt(root, q.id);
8821
+ if (n.kind === "live" && !q.finding && b.data.again !== true) {
8822
+ if (was)
8823
+ throw new HttpError(409, "Already sent", `${q.id} was sent to ${to} at ${was} (catalog/curated/ownerquestion/${q.id}.yaml): choose Send again to send it once more.`, { code: "already-sent" });
8824
+ }
8825
+ if (n.kind === "live")
8826
+ requireConfirmation(ctx.confirmations, "owner-ask", q.id, b.data.confirmation);
8827
+ const team = (await readTeams(root)).teams.find((t) => t.id === to);
8828
+ const mentions = team ? team.people.map((p) => p.replace(/^@/, "")) : [to.replace(/^@/, "")];
8829
+ const channel = q.channel && q.channel !== "Atticus" ? q.channel : `@${to.replace(/^@/, "")}`;
8830
+ let sent;
8831
+ try {
8832
+ sent = await n.notify.send(
8833
+ {
8834
+ channel,
8835
+ title: `A question for ${team?.name ?? to}`,
8836
+ body: `${q.question}
8328
8837
 
8329
8838
  What it is for: ${q.neededFact}
8330
8839
 
8331
8840
  Answer it in Atticus (Questions \u203A Owner questions), or reply to ${ctx.user}.`,
8332
- mentions
8333
- }, { by: ctx.user.replace(/^@/, ""), at: stamp2(now()), ref: `owner-ask:${q.id}` });
8334
- return {
8335
- status: 200,
8336
- body: api_exports.SentOwnerAsk.parse({
8337
- state: n.kind === "manual" ? "step" : "sent",
8338
- to,
8339
- id: sent.id,
8340
- ...n.kind === "manual" ? {
8341
- why: "Notifications are manual here: sending it is a step for you (Home \u203A Manual steps)."
8342
- } : {}
8343
- })
8344
- };
8345
- } catch (e) {
8346
- if (e instanceof HttpError)
8347
- throw e;
8841
+ mentions
8842
+ },
8843
+ // A manual notifier keys its step on this ref: one step per question while it is
8844
+ // open (whoever sends it, whatever "reply to" says), a new one once it is closed.
8845
+ { by: ctx.user.replace(/^@/, ""), at: stamp2(now()), ref: ownerAskRef(q.id) }
8846
+ );
8847
+ } catch (e) {
8848
+ if (e instanceof HttpError)
8849
+ throw e;
8850
+ return {
8851
+ status: 200,
8852
+ body: api_exports.SentOwnerAsk.parse({
8853
+ state: "not-sent",
8854
+ to,
8855
+ why: `The notify adapter refused: ${e.message}`
8856
+ })
8857
+ };
8858
+ }
8859
+ const fell = n.fallback ?? (n.fallbacks[0] ? fallbackWords(n.fallbacks[0]) : void 0);
8860
+ if (n.kind === "manual" || fell)
8861
+ return {
8862
+ status: 200,
8863
+ body: api_exports.SentOwnerAsk.parse({
8864
+ state: "step",
8865
+ to,
8866
+ id: sent.id,
8867
+ why: fell ? `Not sent: ${fell}, so sending it is a step for you (Home \u203A Manual steps).` : "Notifications are manual here: sending it is a step for you (Home \u203A Manual steps)."
8868
+ })
8869
+ };
8870
+ const file = await recordOwnerSend(root, q.id, {
8871
+ by: ctx.user.replace(/^@/, ""),
8872
+ at: stamp2(now()),
8873
+ to,
8874
+ now: now()
8875
+ }).catch(() => void 0);
8876
+ if (file)
8877
+ ctx.events.publish({ type: "file.changed", path: file });
8348
8878
  return {
8349
8879
  status: 200,
8350
- body: api_exports.SentOwnerAsk.parse({
8351
- state: "not-sent",
8352
- to,
8353
- why: `The notify adapter refused: ${e.message}`
8354
- })
8880
+ body: api_exports.SentOwnerAsk.parse({ state: "sent", to, id: sent.id })
8355
8881
  };
8882
+ } finally {
8883
+ sending.delete(q.id);
8356
8884
  }
8357
8885
  }).add("GET", "/api/knowledge/passage", async ({ query }) => {
8358
8886
  const id = strParam(query, "id")?.trim();
8359
8887
  if (!id || id.length > 400 || /[\p{Cc}]/u.test(id))
8360
8888
  throw badRequest("Say which section: ?id=<source>/<page>#<heading>.");
8361
- const { passageOf } = await import("./chunk-IP6ARMZU.js");
8889
+ const { passageOf } = await import("./chunk-PT77IUYQ.js");
8362
8890
  const p = await passageOf(root, id);
8363
8891
  if (!p)
8364
8892
  throw notFound(`No page or section ${id} is in a snapshot or in inputs/.`);
@@ -8384,9 +8912,34 @@ function extendUiRoutes(r, ctx, deps = {}, o = {}) {
8384
8912
  return uiRolesRoutes(uiSetupRoutes(uiThreadRoutes(uiActivityRoutes(uiDecisionRoutes(all, ctx), ctx), ctx), ctx, deps.openFolder ? { openFolder: deps.openFolder } : {}), ctx, {
8385
8913
  ...deps.notify ? { notify: deps.notify } : {},
8386
8914
  ...deps.workTracker ? { workTracker: deps.workTracker } : {},
8915
+ ...deps.adapterFactories ? { adapterFactories: deps.adapterFactories } : {},
8387
8916
  ...deps.now ? { now: () => new Date(deps.now) } : {}
8388
8917
  });
8389
8918
  }
8919
+ function uiRequestLogger(root, err = (l) => process.stderr.write(`${l}
8920
+ `)) {
8921
+ const log = createLog(root);
8922
+ return (r) => {
8923
+ if (r.method !== "GET" && r.method !== "HEAD") {
8924
+ answersMayHaveChanged();
8925
+ keptFilesMayHaveChanged();
8926
+ }
8927
+ if (!isMetarepoRoot(root)) {
8928
+ if (r.error)
8929
+ err(redactText(`atticus ui: ${r.method} ${r.path} failed (${r.status}): ${r.error.message}`));
8930
+ else if (r.status >= 500)
8931
+ err(`atticus ui: ${r.method} ${r.path} answered ${r.status}`);
8932
+ return;
8933
+ }
8934
+ const fields = { method: r.method, path: r.path, status: r.status, ms: r.ms };
8935
+ if (r.error)
8936
+ log.error("request", r.error, fields);
8937
+ else if (r.status >= 500)
8938
+ log.warn("request", fields);
8939
+ else
8940
+ log.debug("request", fields);
8941
+ };
8942
+ }
8390
8943
  async function startUi(root, o = {}, deps = {}) {
8391
8944
  const srv = await startServer({
8392
8945
  root,
@@ -8395,25 +8948,11 @@ async function startUi(root, o = {}, deps = {}) {
8395
8948
  ...o.full ? { full: true } : {},
8396
8949
  ...o.token ? { token: o.token } : {},
8397
8950
  ...o.pageKey ? { pageKey: o.pageKey } : {},
8951
+ ...o.runLog ? { runLog: true } : {},
8398
8952
  staticDir: o.staticDir ?? uiDistDir(),
8399
8953
  ...o.user ? { user: o.user } : {},
8400
8954
  ...o.version ? { version: o.version } : {},
8401
- onRequest: (() => {
8402
- const log = createLog(root);
8403
- return (r) => {
8404
- if (r.method !== "GET" && r.method !== "HEAD") {
8405
- answersMayHaveChanged();
8406
- keptFilesMayHaveChanged();
8407
- }
8408
- const fields = { method: r.method, path: r.path, status: r.status, ms: r.ms };
8409
- if (r.error)
8410
- log.error("request", r.error, fields);
8411
- else if (r.status >= 500)
8412
- log.warn("request", fields);
8413
- else
8414
- log.debug("request", fields);
8415
- };
8416
- })(),
8955
+ onRequest: uiRequestLogger(root),
8417
8956
  extend: (r, ctx) => extendUiRoutes(r, ctx, deps, { warm: o.warm === true })
8418
8957
  });
8419
8958
  keepCatalogsInMemory(true);
@@ -8473,8 +9012,8 @@ function untilStopped(embedded, stdin = process.stdin, o = {}) {
8473
9012
  const stop = () => {
8474
9013
  if (watch)
8475
9014
  clearInterval(watch);
8476
- process.off("SIGINT", stop);
8477
- process.off("SIGTERM", stop);
9015
+ offInt();
9016
+ offTerm();
8478
9017
  if (embedded) {
8479
9018
  stdin.off("end", stop);
8480
9019
  stdin.off("close", stop);
@@ -8482,8 +9021,8 @@ function untilStopped(embedded, stdin = process.stdin, o = {}) {
8482
9021
  }
8483
9022
  resolve3();
8484
9023
  };
8485
- process.once("SIGINT", stop);
8486
- process.once("SIGTERM", stop);
9024
+ const offInt = onAtticusSignal("SIGINT", stop, { once: true });
9025
+ const offTerm = onAtticusSignal("SIGTERM", stop, { once: true });
8487
9026
  if (embedded) {
8488
9027
  stdin.once("end", stop);
8489
9028
  stdin.once("close", stop);
@@ -8513,6 +9052,8 @@ async function uiCommand(root, o, io) {
8513
9052
  ...given ? { token: given } : {},
8514
9053
  ...pageKey ? { pageKey } : {},
8515
9054
  warm: true,
9055
+ // Beta.27 review: the jobs it starts are kept in the run log, for after a restart.
9056
+ runLog: true,
8516
9057
  ...o.full ? { full: true } : {},
8517
9058
  ...o.port !== void 0 ? { port: o.port } : {},
8518
9059
  ...o.user ? { user: o.user } : {},
@@ -8544,5 +9085,6 @@ export {
8544
9085
  startUi,
8545
9086
  startedLines,
8546
9087
  uiCommand,
9088
+ uiRequestLogger,
8547
9089
  untilStopped
8548
9090
  };