@maycombhq/atticus 2.0.0-beta.25 → 2.0.0-beta.27

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 (326) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/chunk-22A2K555.js +653 -0
  3. package/dist/{chunk-UTZMF5CV.js → chunk-23TTURB2.js} +1 -1
  4. package/dist/{chunk-F36DIKJ3.js → chunk-2666BPJE.js} +19 -19
  5. package/dist/{chunk-E2OP6JNF.js → chunk-2ALBHI4Q.js} +28 -27
  6. package/dist/chunk-2ANBMA74.js +107 -0
  7. package/dist/{chunk-S7UQFI4B.js → chunk-2HCW6HXK.js} +27 -26
  8. package/dist/{chunk-HV3KPEFH.js → chunk-2ISR6MWD.js} +15 -15
  9. package/dist/{chunk-QQD25YNF.js → chunk-2MRYL45Z.js} +50 -9
  10. package/dist/{chunk-KN4UQJ7R.js → chunk-3GNUHLAN.js} +4 -4
  11. package/dist/chunk-3GURU22K.js +44 -0
  12. package/dist/{chunk-4U3JLIRC.js → chunk-3M3MDBOG.js} +1 -1
  13. package/dist/{chunk-DJ4C5ELF.js → chunk-3PBIZBWN.js} +1 -1
  14. package/dist/{chunk-XUCHGEF5.js → chunk-3PWXVBCB.js} +83 -40
  15. package/dist/chunk-3W2QX6TT.js +58 -0
  16. package/dist/{chunk-CPFAWYVC.js → chunk-3Z7ATALI.js} +5 -5
  17. package/dist/{chunk-ZGULQAPZ.js → chunk-44SWXDD7.js} +8 -5
  18. package/dist/{chunk-LGE6H4UP.js → chunk-46N5O5H7.js} +5 -5
  19. package/dist/{chunk-SRLUADSY.js → chunk-4D4DNTFE.js} +4 -4
  20. package/dist/{chunk-DMQJDHXG.js → chunk-4EAT7HOX.js} +7 -5
  21. package/dist/{chunk-DPZD7WVX.js → chunk-4FLIW5PJ.js} +4 -4
  22. package/dist/{chunk-SGTAQNOP.js → chunk-4LWA5VMJ.js} +52 -37
  23. package/dist/{chunk-D45K3XKK.js → chunk-4ODVHNA6.js} +18 -17
  24. package/dist/{chunk-7QZDGM5V.js → chunk-4POSAXNC.js} +6 -6
  25. package/dist/{chunk-A3J75BO2.js → chunk-4PQ4KDOA.js} +16 -15
  26. package/dist/{chunk-2Y5FJQSF.js → chunk-4UVTNHA6.js} +1 -1
  27. package/dist/{chunk-KVVNAUIG.js → chunk-4XK3HLOH.js} +1 -0
  28. package/dist/{chunk-V7T6URII.js → chunk-523NRKHF.js} +4 -4
  29. package/dist/{chunk-7EAH2MFY.js → chunk-5GCCG3GJ.js} +11 -5
  30. package/dist/{chunk-7U6PBBXG.js → chunk-5XW6RUDV.js} +8 -8
  31. package/dist/{chunk-Y3J365UC.js → chunk-5YEUAZZE.js} +8 -8
  32. package/dist/{chunk-JWLABUXL.js → chunk-62LD7CSY.js} +13 -13
  33. package/dist/{chunk-LOJGNSPA.js → chunk-67Y2J55V.js} +22 -21
  34. package/dist/{chunk-UCKG6UE7.js → chunk-6DSZ4CL7.js} +37 -22
  35. package/dist/{chunk-FNP4M4VL.js → chunk-6G67LSBG.js} +283 -61
  36. package/dist/{chunk-5GLGLWAJ.js → chunk-6OEB4FTC.js} +20 -19
  37. package/dist/{chunk-5RKN5QIX.js → chunk-6OTGCKYH.js} +9 -9
  38. package/dist/{chunk-UI7ID4HG.js → chunk-6XLCMDIP.js} +13 -13
  39. package/dist/chunk-76DZJTU7.js +190 -0
  40. package/dist/chunk-7764GVJK.js +37 -0
  41. package/dist/{chunk-TKCNJJ2S.js → chunk-7BOGXFZ3.js} +11 -11
  42. package/dist/{chunk-Q52KWTG5.js → chunk-7CVHKNAF.js} +16 -15
  43. package/dist/{chunk-XF5UMMQL.js → chunk-7FEIS3KV.js} +25 -24
  44. package/dist/{chunk-UTYL4XVA.js → chunk-7GXM45T5.js} +26 -23
  45. package/dist/{chunk-4PW5SRKJ.js → chunk-7YMAMNMT.js} +17 -16
  46. package/dist/chunk-7YWS47SE.js +56 -0
  47. package/dist/{chunk-LZFKJ2BR.js → chunk-A3LVMCA5.js} +1 -1
  48. package/dist/{chunk-7YFUNWFM.js → chunk-A7ZJKLFC.js} +11 -11
  49. package/dist/chunk-AANQC5QP.js +47 -0
  50. package/dist/{chunk-LP5QGTCR.js → chunk-AIQLTDC3.js} +3 -3
  51. package/dist/{chunk-EPXYFJTY.js → chunk-AKZTCZ6F.js} +4 -4
  52. package/dist/{chunk-5267F4BS.js → chunk-ALCSTVWQ.js} +3 -3
  53. package/dist/{chunk-NMBHFSJQ.js → chunk-ALUHO7SE.js} +26 -25
  54. package/dist/{chunk-3WO7ASU7.js → chunk-AMZ4XMES.js} +8 -8
  55. package/dist/{chunk-JKEUPSCE.js → chunk-AOQG37K4.js} +8 -6
  56. package/dist/{chunk-3NA2VE45.js → chunk-ARXZTHEI.js} +16 -15
  57. package/dist/{chunk-W2W7YCFL.js → chunk-AS4CTARY.js} +16 -15
  58. package/dist/{chunk-7AKJ2XTW.js → chunk-AVUPW23W.js} +18 -17
  59. package/dist/{chunk-CMUJSPP4.js → chunk-B56FCIEJ.js} +12 -12
  60. package/dist/{chunk-K3OIBTCV.js → chunk-BABATPOZ.js} +18 -17
  61. package/dist/{chunk-VAZYNF6I.js → chunk-BIOKDLLX.js} +21 -19
  62. package/dist/{chunk-23QHP4JJ.js → chunk-BUBKKEUV.js} +5 -5
  63. package/dist/{chunk-N3OEBQTA.js → chunk-CDC6VECU.js} +3 -3
  64. package/dist/chunk-CHEFUNZ4.js +425 -0
  65. package/dist/{chunk-MM7YWUBB.js → chunk-CIFR3DPV.js} +6 -6
  66. package/dist/{chunk-JCKKAELC.js → chunk-CLBVKD4P.js} +16 -15
  67. package/dist/{chunk-HHZEXF7V.js → chunk-CLM5Z3R5.js} +5 -5
  68. package/dist/{chunk-M7XNX5IC.js → chunk-CLYV5MB6.js} +9 -9
  69. package/dist/{chunk-SHWHRCMU.js → chunk-CRYIBCGP.js} +37 -19
  70. package/dist/{chunk-6576X5BJ.js → chunk-D3L5SO27.js} +5 -5
  71. package/dist/chunk-DAZM2INZ.js +34 -0
  72. package/dist/{chunk-VBJHIRKV.js → chunk-DF4BXBB2.js} +6 -6
  73. package/dist/{chunk-U4HZ5CXL.js → chunk-E7Q52EOO.js} +11 -11
  74. package/dist/{chunk-MZTU5L6S.js → chunk-EFDUC35B.js} +3 -3
  75. package/dist/{chunk-GIOOA2ZO.js → chunk-EHXEJFHD.js} +5 -5
  76. package/dist/{chunk-M6HI36T3.js → chunk-ELJ5Q4J2.js} +2 -2
  77. package/dist/{chunk-MJAIBPI5.js → chunk-EM6DKBTJ.js} +3 -3
  78. package/dist/{chunk-YGS2YVF2.js → chunk-EMC46SU4.js} +38 -17
  79. package/dist/{chunk-CB6H7MH2.js → chunk-EQEDIWFQ.js} +25 -24
  80. package/dist/chunk-EW574EZI.js +57 -0
  81. package/dist/{chunk-JJEPU4VS.js → chunk-EYINWNXL.js} +5 -5
  82. package/dist/{chunk-MJOIMGS4.js → chunk-EYVYHYCA.js} +8 -8
  83. package/dist/{chunk-WGOQZ4PQ.js → chunk-F66542M6.js} +34 -9
  84. package/dist/{chunk-EUCATH2U.js → chunk-F74OMLNU.js} +6 -6
  85. package/dist/{chunk-G5P7F6RQ.js → chunk-FADIWOA5.js} +3 -3
  86. package/dist/{chunk-JMOZ6K5A.js → chunk-FC3ZVD3O.js} +3 -3
  87. package/dist/{chunk-XXJSGCDO.js → chunk-FG65LXED.js} +8 -8
  88. package/dist/{chunk-5WZV37WS.js → chunk-FKAUBC4Y.js} +8 -8
  89. package/dist/{chunk-WA644MUQ.js → chunk-FM3EEDS2.js} +15 -15
  90. package/dist/{chunk-XZQBFF65.js → chunk-FS4E7F6O.js} +403 -148
  91. package/dist/{chunk-Q6UYUCNS.js → chunk-FSYJPYLE.js} +16 -15
  92. package/dist/{chunk-H7GAPNGQ.js → chunk-G33UIUG3.js} +46 -20
  93. package/dist/{chunk-OEUTV6EL.js → chunk-G3F4BYML.js} +15 -14
  94. package/dist/{chunk-7UYRN4ON.js → chunk-GBJRFFDW.js} +5 -5
  95. package/dist/{chunk-7HW2CMIN.js → chunk-GF6GBHFN.js} +13 -11
  96. package/dist/{chunk-DCPI3ETH.js → chunk-GLHOUT5E.js} +26 -25
  97. package/dist/{chunk-VOBG7BLB.js → chunk-GM6GXO2A.js} +20 -19
  98. package/dist/{chunk-KJPKIU2R.js → chunk-GSJ2RXE7.js} +29 -28
  99. package/dist/{chunk-HU7VXMFV.js → chunk-GT72FDER.js} +6 -6
  100. package/dist/{chunk-SBNBVUOF.js → chunk-GW6ZH77P.js} +37 -36
  101. package/dist/{chunk-6WYOJCB4.js → chunk-GZILYRGC.js} +3 -3
  102. package/dist/{chunk-4SS5ZK47.js → chunk-GZSOZYEP.js} +3 -3
  103. package/dist/{chunk-N6SSI6XO.js → chunk-H25QNDKK.js} +58 -36
  104. package/dist/{chunk-DYVUNT4O.js → chunk-H3RKW4RF.js} +7 -7
  105. package/dist/chunk-H7M7ZH6H.js +52 -0
  106. package/dist/chunk-H7NRWSMP.js +55 -0
  107. package/dist/{chunk-KW4DIXUL.js → chunk-HDWVR5KD.js} +4 -4
  108. package/dist/{chunk-HR34F2AJ.js → chunk-HG24EF5S.js} +16 -15
  109. package/dist/chunk-HPNYSY5M.js +1068 -0
  110. package/dist/{chunk-3VC2XJ53.js → chunk-HUMM4S5I.js} +6 -6
  111. package/dist/{chunk-K373N5U6.js → chunk-HVPS2YCW.js} +11 -11
  112. package/dist/{chunk-IGOE6KPG.js → chunk-I34CXV2C.js} +185 -11
  113. package/dist/{chunk-U7YZ3IRI.js → chunk-I57IH5X6.js} +360 -271
  114. package/dist/{chunk-P56N3NPT.js → chunk-I5X4WU7U.js} +6 -6
  115. package/dist/chunk-IAVVJ34R.js +55 -0
  116. package/dist/chunk-IBJE2E2S.js +51 -0
  117. package/dist/{chunk-EXCXNDTQ.js → chunk-IF3X6FMO.js} +1 -1
  118. package/dist/{chunk-GAVEIYKH.js → chunk-IJHJIL6T.js} +154 -25
  119. package/dist/chunk-IM435QAM.js +72 -0
  120. package/dist/{chunk-7NLYSTEK.js → chunk-IMBJ7WAO.js} +6 -6
  121. package/dist/{chunk-EM7F6XEU.js → chunk-INCFIDCB.js} +2 -2
  122. package/dist/{chunk-AYWJMHSX.js → chunk-IPMPLTEG.js} +3 -3
  123. package/dist/{chunk-PGKCRK77.js → chunk-IPSZDVLI.js} +12 -12
  124. package/dist/{chunk-IMTAHDME.js → chunk-IX2EOYOU.js} +50 -13
  125. package/dist/{chunk-QE444DZ2.js → chunk-IXNMGPF7.js} +61 -28
  126. package/dist/{chunk-NL6GIEJU.js → chunk-J6GO3K7G.js} +19 -18
  127. package/dist/chunk-JBLM6IUA.js +42 -0
  128. package/dist/{chunk-IWQEZFVV.js → chunk-JL2VOYSL.js} +91 -93
  129. package/dist/{chunk-K77ILFUQ.js → chunk-JRXFZB6J.js} +8 -8
  130. package/dist/{chunk-UR6JGVX2.js → chunk-JTOLBS7R.js} +988 -410
  131. package/dist/{chunk-GD6FXN6R.js → chunk-K73BHPTQ.js} +19 -18
  132. package/dist/{chunk-PYVFLITV.js → chunk-KF7KVUNJ.js} +5 -5
  133. package/dist/{chunk-F4WKGX7K.js → chunk-KKUCBKJE.js} +20 -19
  134. package/dist/{chunk-U7F6E5M3.js → chunk-KLFFHBWG.js} +27 -26
  135. package/dist/{chunk-ROVOAF2O.js → chunk-KMYB2XO7.js} +21 -13
  136. package/dist/chunk-KNYQUWFN.js +52 -0
  137. package/dist/{chunk-KFDOL2Y4.js → chunk-KOAJPMU2.js} +31 -20
  138. package/dist/chunk-KRTSE73S.js +55 -0
  139. package/dist/{chunk-IW3QMW3X.js → chunk-L3AM5YRP.js} +28 -9
  140. package/dist/{chunk-334N6EI2.js → chunk-LCIIFAID.js} +22 -21
  141. package/dist/{chunk-DLNQ3HUM.js → chunk-LCQIRCOT.js} +55 -10
  142. package/dist/{chunk-QFOJ3UPU.js → chunk-LFHBAWIM.js} +13 -13
  143. package/dist/chunk-LIHEMWIT.js +39 -0
  144. package/dist/{chunk-T5QYYB5L.js → chunk-LJLYWILK.js} +14 -14
  145. package/dist/{chunk-E7PR4WMM.js → chunk-LNJKDS5C.js} +26 -25
  146. package/dist/{chunk-HHZ2ZKUD.js → chunk-LTHY7E2P.js} +16 -15
  147. package/dist/{chunk-4WIVTPGE.js → chunk-LTVOQJKT.js} +7 -7
  148. package/dist/{chunk-TIOYZDRB.js → chunk-LZO3JABE.js} +6 -6
  149. package/dist/{chunk-PXMV2LLY.js → chunk-M65AZ4ZE.js} +3 -5
  150. package/dist/chunk-MPNTEWNY.js +492 -0
  151. package/dist/chunk-MQGQ3AWK.js +58 -0
  152. package/dist/{chunk-NQLTWGF4.js → chunk-MUXYUIBV.js} +6 -6
  153. package/dist/{chunk-5R3FRI6H.js → chunk-MWRRJDXQ.js} +34 -31
  154. package/dist/{chunk-XY6FVBBV.js → chunk-MZDHFWTN.js} +2 -2
  155. package/dist/chunk-N2XCT5OX.js +68 -0
  156. package/dist/{chunk-C5LX54QK.js → chunk-N3JGYAMD.js} +15 -15
  157. package/dist/{chunk-RL7PETU6.js → chunk-N5DLB74D.js} +367 -71
  158. package/dist/{chunk-MJMEF7SD.js → chunk-NC3Q7RIB.js} +10 -10
  159. package/dist/{chunk-4GWQVT2C.js → chunk-NCNLX4DL.js} +19 -18
  160. package/dist/{chunk-3D74UADA.js → chunk-NGSGJLKW.js} +2 -2
  161. package/dist/{chunk-OOU4N2JQ.js → chunk-NN7K2LLN.js} +25 -24
  162. package/dist/{chunk-ELNIQYLR.js → chunk-NNURP7VO.js} +15 -15
  163. package/dist/chunk-NSQB24WR.js +56 -0
  164. package/dist/{chunk-MWOPED6I.js → chunk-NV5S63YK.js} +7 -7
  165. package/dist/{chunk-CTJHEG6A.js → chunk-NWMFVPEP.js} +2 -0
  166. package/dist/{chunk-7E3G5NCH.js → chunk-NYT6QGZA.js} +22 -18
  167. package/dist/chunk-OB2DAIJX.js +62 -0
  168. package/dist/{chunk-YAUMNRCB.js → chunk-OC3OXDTG.js} +13 -8
  169. package/dist/{chunk-DAHKLVHU.js → chunk-OD6RNYMQ.js} +16 -16
  170. package/dist/{chunk-7FUQAT2R.js → chunk-OFYBRMRG.js} +6 -6
  171. package/dist/chunk-OGTELPDN.js +43 -0
  172. package/dist/{chunk-BS52P2CM.js → chunk-OQ7SBQ2Z.js} +7 -7
  173. package/dist/{chunk-OMSH46JK.js → chunk-OUDGBJC2.js} +16 -9
  174. package/dist/{chunk-USH4VU5D.js → chunk-OUGTAOGA.js} +2 -2
  175. package/dist/chunk-OWP5FCYM.js +60 -0
  176. package/dist/{chunk-YEGGQG5E.js → chunk-P36PTWBM.js} +8 -8
  177. package/dist/{chunk-IKRM64KR.js → chunk-P6Y2J2QY.js} +12 -12
  178. package/dist/{chunk-P4QTTCVK.js → chunk-PDJL2HO5.js} +24 -22
  179. package/dist/{chunk-WDJGJ3HV.js → chunk-PPKH6ULR.js} +152 -20
  180. package/dist/{chunk-5OVSDV77.js → chunk-Q4PFF2ZE.js} +8 -8
  181. package/dist/chunk-Q7EUPQEG.js +5 -0
  182. package/dist/{chunk-YRKAJ42V.js → chunk-QC6GSNIK.js} +7074 -3456
  183. package/dist/chunk-QCRQNYGI.js +211 -0
  184. package/dist/chunk-QDF533AW.js +90 -0
  185. package/dist/chunk-QDGNDNBG.js +50 -0
  186. package/dist/{chunk-2ULVUSIP.js → chunk-QGMD3PYL.js} +31 -24
  187. package/dist/{chunk-QEP4HTJE.js → chunk-QLT3WYTD.js} +6 -6
  188. package/dist/{chunk-GX67TNFA.js → chunk-QNDMAKQS.js} +11 -3
  189. package/dist/{chunk-XM3JE4QY.js → chunk-QNXMVJMA.js} +8 -8
  190. package/dist/{chunk-XP5DF5MC.js → chunk-QPAANKUR.js} +13 -12
  191. package/dist/{chunk-SD3PGZSR.js → chunk-QS4VX3HZ.js} +1 -1
  192. package/dist/{chunk-ZD64ZR64.js → chunk-QSM4K6LI.js} +7 -7
  193. package/dist/{chunk-Z4N7BKLN.js → chunk-QUFZDWPC.js} +8 -8
  194. package/dist/{chunk-ELNLHU7Y.js → chunk-QXXEOH3A.js} +18 -6
  195. package/dist/{chunk-QA4O2GGC.js → chunk-R4TUWD4C.js} +17 -1
  196. package/dist/{chunk-TAIYQDIV.js → chunk-ROI64BAI.js} +22 -21
  197. package/dist/{chunk-NMGFXT4S.js → chunk-RPVL3RTX.js} +19 -18
  198. package/dist/{chunk-62FMA437.js → chunk-RUNHVUCW.js} +16 -15
  199. package/dist/{chunk-I2M7MXSV.js → chunk-RWYPLODE.js} +9 -9
  200. package/dist/{chunk-5K6ZKHZR.js → chunk-RZYRUXSU.js} +4 -4
  201. package/dist/{chunk-TVFADTAT.js → chunk-S6TLXRBR.js} +7 -7
  202. package/dist/{chunk-PCZ4C2V7.js → chunk-SCOP3J6X.js} +7 -7
  203. package/dist/{chunk-JXLUHMTC.js → chunk-SCP24MJX.js} +24 -23
  204. package/dist/{chunk-R6HJ4SDB.js → chunk-SF3HXNXR.js} +6 -6
  205. package/dist/{chunk-7F4GZ7U2.js → chunk-SFCFL7Y5.js} +1 -1
  206. package/dist/{chunk-5RDKQOY3.js → chunk-SHFY73RI.js} +53 -112
  207. package/dist/{chunk-H75SPCAW.js → chunk-SHIARIEZ.js} +20 -19
  208. package/dist/chunk-SMFFUFMN.js +1876 -0
  209. package/dist/{chunk-JQGWP3SC.js → chunk-SVOGRJO6.js} +197 -124
  210. package/dist/chunk-SVZAAOHJ.js +46 -0
  211. package/dist/{chunk-BJDVI5W6.js → chunk-SZOU32VF.js} +21 -20
  212. package/dist/{chunk-MXPKXCGP.js → chunk-T2MN24LZ.js} +1 -1
  213. package/dist/{chunk-A3AADMM2.js → chunk-TD5WWJLN.js} +6 -6
  214. package/dist/{chunk-SXF66YNZ.js → chunk-TFN2N227.js} +6 -6
  215. package/dist/{chunk-RSA5JJMN.js → chunk-TFXNOQEU.js} +28 -27
  216. package/dist/{chunk-BEDZNT62.js → chunk-TMETWJFO.js} +11 -11
  217. package/dist/chunk-TNSAIISO.js +50 -0
  218. package/dist/{chunk-IDTVBZQI.js → chunk-TRJO2I4S.js} +3 -3
  219. package/dist/{chunk-IFDCCCEN.js → chunk-TRSNIJNM.js} +7 -7
  220. package/dist/{chunk-GDGE7ZHC.js → chunk-U3Z2QZE3.js} +6 -6
  221. package/dist/{chunk-GVOQJPKA.js → chunk-U7L3ORPK.js} +22 -21
  222. package/dist/{chunk-5UJ7C7IH.js → chunk-UDM6HGF4.js} +6 -6
  223. package/dist/{chunk-Z3KEX7ON.js → chunk-UDM7LXNJ.js} +7 -7
  224. package/dist/chunk-UDTO3U6E.js +35 -0
  225. package/dist/{chunk-UVKJVTKX.js → chunk-UEUPEUZX.js} +3 -3
  226. package/dist/chunk-UWBODTY7.js +514 -0
  227. package/dist/{chunk-KGT5RIGE.js → chunk-UYYYQTPD.js} +84 -51
  228. package/dist/{chunk-LKRMVWXB.js → chunk-V34N6JAN.js} +32 -31
  229. package/dist/{chunk-RX56MZLX.js → chunk-V3Y5P7OS.js} +24 -23
  230. package/dist/chunk-V6MLVGTP.js +89 -0
  231. package/dist/chunk-VC2XHC7P.js +424 -0
  232. package/dist/{chunk-MM5OAVSW.js → chunk-VCYE4MUD.js} +29 -28
  233. package/dist/{chunk-AGAFNUYZ.js → chunk-VN2VJ6BV.js} +19 -15
  234. package/dist/{chunk-DBVQEPZB.js → chunk-VVLWEM2Y.js} +6 -6
  235. package/dist/{chunk-F56DNMDD.js → chunk-VWCNMDMZ.js} +5 -5
  236. package/dist/{chunk-LNGFTPU7.js → chunk-W2A4NHQD.js} +25 -24
  237. package/dist/{chunk-LQD3R6NZ.js → chunk-W6OY2PMB.js} +10 -10
  238. package/dist/{chunk-IP6TSICI.js → chunk-WC6DHBVG.js} +16 -15
  239. package/dist/{chunk-MELS6T5J.js → chunk-WCA3WIGG.js} +5 -5
  240. package/dist/{chunk-GLISHJ4G.js → chunk-WJWSB65O.js} +1602 -452
  241. package/dist/{chunk-77REYYY5.js → chunk-WNPGLGCJ.js} +5 -5
  242. package/dist/chunk-WTOVWEY3.js +67 -0
  243. package/dist/{chunk-WS7KBKP4.js → chunk-X5B7KYPD.js} +507 -20
  244. package/dist/{chunk-O6DJMDBR.js → chunk-X73WLHSN.js} +7 -7
  245. package/dist/{chunk-YGNQUFVZ.js → chunk-XIIT4PVT.js} +3 -3
  246. package/dist/{chunk-5P4PNGPL.js → chunk-XLTT5QCX.js} +28 -25
  247. package/dist/{chunk-NPZ4KXIV.js → chunk-XMIS25ZJ.js} +21 -20
  248. package/dist/{chunk-NB664KWQ.js → chunk-XPDQ4T6G.js} +27 -26
  249. package/dist/{chunk-EAGSM3XY.js → chunk-XRWUYOX3.js} +138 -22
  250. package/dist/{chunk-2VN4TLGI.js → chunk-XZY4GTCX.js} +14 -9
  251. package/dist/{chunk-QSKY7FE3.js → chunk-Y2TVTI4P.js} +121 -15
  252. package/dist/{chunk-XVQQ3BQS.js → chunk-Y2U4CSCA.js} +28 -27
  253. package/dist/chunk-Y2U63JKE.js +41 -0
  254. package/dist/{chunk-UJ535VWR.js → chunk-Y6S7VCYN.js} +6 -6
  255. package/dist/{chunk-SEBBJQWK.js → chunk-YAPMGK7E.js} +11 -11
  256. package/dist/{chunk-CNF7D3A7.js → chunk-YAPVAYZN.js} +3 -3
  257. package/dist/{chunk-B2U4AOZ5.js → chunk-YCBDNWX3.js} +78 -57
  258. package/dist/{chunk-CGVRLQAY.js → chunk-YIGSUTW2.js} +1329 -92
  259. package/dist/{chunk-J65TN6QU.js → chunk-YJTBE6AJ.js} +5 -5
  260. package/dist/chunk-YQ3IXQIH.js +185 -0
  261. package/dist/{chunk-ZJQ64T6M.js → chunk-YRHKEXTP.js} +11 -11
  262. package/dist/{chunk-MN2XDLDM.js → chunk-YSSFS3YC.js} +17 -17
  263. package/dist/{chunk-BPDS7KUR.js → chunk-YXG2VQJJ.js} +200 -56
  264. package/dist/{chunk-XC5ZDFW7.js → chunk-Z4GLFTEH.js} +8 -8
  265. package/dist/{chunk-7X3WLAKP.js → chunk-Z65FWO6A.js} +157 -89
  266. package/dist/{chunk-OW53P52N.js → chunk-ZDG637ZT.js} +22 -21
  267. package/dist/{chunk-BIQNPWGX.js → chunk-ZIAMPN7N.js} +6 -6
  268. package/dist/chunk-ZIIBQHCX.js +53 -0
  269. package/dist/{chunk-RFQW7XT3.js → chunk-ZJJMYPGZ.js} +57 -27
  270. package/dist/{chunk-Y6KPWRZJ.js → chunk-ZOAX7W5S.js} +11 -11
  271. package/dist/chunk-ZSSR5GGB.js +48 -0
  272. package/dist/files.json +655 -551
  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 +3859 -2939
  288. package/dist/packages/ui/dist/assets/{elk-api-ts8TigYQ.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-2RABF6RT.js +0 -36
  295. package/dist/chunk-5CPZIWIN.js +0 -38
  296. package/dist/chunk-7YSMZEO3.js +0 -55
  297. package/dist/chunk-AENMOZMM.js +0 -42
  298. package/dist/chunk-BDKYHCGI.js +0 -71
  299. package/dist/chunk-BMMTWRWE.js +0 -50
  300. package/dist/chunk-CQRFCWQV.js +0 -45
  301. package/dist/chunk-CVWKS6GO.js +0 -50
  302. package/dist/chunk-D2CGJ7RR.js +0 -46
  303. package/dist/chunk-D7QIZLWB.js +0 -38
  304. package/dist/chunk-DM3H4V2G.js +0 -62
  305. package/dist/chunk-EJGUEUXG.js +0 -51
  306. package/dist/chunk-ELKTDXV3.js +0 -67
  307. package/dist/chunk-EP7ZBZLT.js +0 -170
  308. package/dist/chunk-EXGXCVWC.js +0 -52
  309. package/dist/chunk-FJS2FZFZ.js +0 -41
  310. package/dist/chunk-G3ZFEHCX.js +0 -925
  311. package/dist/chunk-GAU2IFIC.js +0 -33
  312. package/dist/chunk-GPOL5H3B.js +0 -55
  313. package/dist/chunk-HD72AL3L.js +0 -43
  314. package/dist/chunk-K4C2DWOZ.js +0 -232
  315. package/dist/chunk-KY3BUZYI.js +0 -54
  316. package/dist/chunk-LMNCRSER.js +0 -257
  317. package/dist/chunk-LPXH2DA4.js +0 -40
  318. package/dist/chunk-MLUHBVCI.js +0 -45
  319. package/dist/chunk-ONB7M2AF.js +0 -52
  320. package/dist/chunk-QBK33722.js +0 -51
  321. package/dist/chunk-S7I7SLZN.js +0 -59
  322. package/dist/chunk-UCQB6NKS.js +0 -192
  323. package/dist/chunk-UKMA5JFE.js +0 -52
  324. package/dist/chunk-X7QLAUNS.js +0 -47
  325. package/dist/packages/ui/dist/assets/index-CIfmX7DJ.css +0 -1
  326. package/dist/packages/ui/dist/assets/index-DNtpSfZS.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-SHWHRCMU.js";
7
+ uiComponentTypeRoutes
8
+ } from "./chunk-523NRKHF.js";
14
9
  import {
15
- uiCiteRoutes
16
- } from "./chunk-KN4UQJ7R.js";
17
- import "./chunk-5OVSDV77.js";
10
+ changeProblems,
11
+ missingChangeWords
12
+ } from "./chunk-V6MLVGTP.js";
18
13
  import {
19
- uiComponentTypeRoutes
20
- } from "./chunk-V7T6URII.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-3GNUHLAN.js";
30
+ import "./chunk-Q4PFF2ZE.js";
21
31
  import {
22
32
  conformanceCommand
23
- } from "./chunk-5UJ7C7IH.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-IDTVBZQI.js";
42
+ } from "./chunk-TRJO2I4S.js";
33
43
  import {
34
44
  historyEntry,
35
45
  listHistory
36
- } from "./chunk-YGNQUFVZ.js";
46
+ } from "./chunk-XIIT4PVT.js";
37
47
  import {
38
- FORCE_STEPS,
39
- appLines,
40
- hasKeptResume,
41
- mapRepoOf
42
- } from "./chunk-K77ILFUQ.js";
43
- import {
44
- allRuns,
45
- answerOf,
46
- item,
47
- listRuns,
48
- partStates,
49
- runTranscript
50
- } from "./chunk-MZTU5L6S.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-7GXM45T5.js";
54
55
  import {
55
56
  executorsCheck,
56
57
  todoDone,
57
58
  todoRun,
58
59
  todoShow
59
- } from "./chunk-GX67TNFA.js";
60
+ } from "./chunk-QNDMAKQS.js";
60
61
  import {
61
62
  inputsSha256,
62
63
  loadExecutors
63
- } from "./chunk-AYWJMHSX.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-UCKG6UE7.js";
72
+ } from "./chunk-6DSZ4CL7.js";
72
73
  import {
73
74
  defencesScan,
74
75
  evalRun
75
- } from "./chunk-ZD64ZR64.js";
76
+ } from "./chunk-QSM4K6LI.js";
76
77
  import {
77
78
  listReports,
78
79
  readQuality
79
- } from "./chunk-UI7ID4HG.js";
80
+ } from "./chunk-6XLCMDIP.js";
80
81
  import {
81
82
  estimateOf
82
- } from "./chunk-HU7VXMFV.js";
83
+ } from "./chunk-GT72FDER.js";
83
84
  import {
84
85
  changeMapBody,
85
86
  changeMapOf,
86
87
  targetFlowsOf
87
- } from "./chunk-LGE6H4UP.js";
88
- import {
89
- changeArchive,
90
- changeHandoff,
91
- changeNew,
92
- changeReleasePrs,
93
- changeSync,
94
- syncAfterManualStep
95
- } from "./chunk-UTYL4XVA.js";
96
- import {
97
- boxesOf,
98
- candidatesOf,
99
- uiLinkRoutes
100
- } from "./chunk-DAHKLVHU.js";
101
- import {
102
- matchDone,
103
- quotesOf,
104
- readMatch,
105
- runMatch
106
- } from "./chunk-CMUJSPP4.js";
107
- import "./chunk-3WO7ASU7.js";
88
+ } from "./chunk-46N5O5H7.js";
89
+ import "./chunk-EYINWNXL.js";
108
90
  import {
109
91
  readServiceRequests
110
- } from "./chunk-HV3KPEFH.js";
111
- import {
112
- initiativeStatus,
113
- readView
114
- } from "./chunk-7E3G5NCH.js";
92
+ } from "./chunk-2ISR6MWD.js";
115
93
  import {
116
94
  runDone,
117
95
  taskRun,
118
96
  taskRunNotWaiting
119
- } from "./chunk-M7XNX5IC.js";
120
- import {
121
- idFromUrl
122
- } from "./chunk-7NLYSTEK.js";
123
- import {
124
- DecideError,
125
- correctDecision,
126
- decisionsView,
127
- undoBatch
128
- } from "./chunk-QFOJ3UPU.js";
129
- import "./chunk-K373N5U6.js";
130
- import {
131
- copilotAcpAllowed
132
- } from "./chunk-ROVOAF2O.js";
133
- import "./chunk-QE444DZ2.js";
134
- import "./chunk-6WYOJCB4.js";
135
- import {
136
- readRepos
137
- } from "./chunk-JMOZ6K5A.js";
138
- import {
139
- filesUnder,
140
- memoByFiles,
141
- recheckNow,
142
- uiFactsRoutes
143
- } from "./chunk-WGOQZ4PQ.js";
144
- import {
145
- safeMessage,
146
- withFileLock
147
- } from "./chunk-7F4GZ7U2.js";
148
- import "./chunk-KGT5RIGE.js";
97
+ } from "./chunk-CLYV5MB6.js";
149
98
  import {
150
- syncNextOf
151
- } from "./chunk-EHXDB3SA.js";
152
- import "./chunk-USH4VU5D.js";
153
- import "./chunk-XXJSGCDO.js";
154
- import "./chunk-CNF7D3A7.js";
99
+ changeNextStep
100
+ } from "./chunk-YCBDNWX3.js";
155
101
  import {
156
102
  digestCommand
157
- } from "./chunk-DYVUNT4O.js";
103
+ } from "./chunk-H3RKW4RF.js";
158
104
  import {
159
105
  reconcileCommand
160
- } from "./chunk-SRLUADSY.js";
106
+ } from "./chunk-4D4DNTFE.js";
161
107
  import {
162
108
  sourcesAdd,
163
109
  sourcesSync
164
- } from "./chunk-7U6PBBXG.js";
110
+ } from "./chunk-5XW6RUDV.js";
165
111
  import {
166
112
  INPUTS_SOURCE_ID
167
- } from "./chunk-MJAIBPI5.js";
168
- import "./chunk-JJEPU4VS.js";
113
+ } from "./chunk-EM6DKBTJ.js";
114
+ import {
115
+ boxesOf,
116
+ candidatesOf,
117
+ uiLinkRoutes
118
+ } from "./chunk-OD6RNYMQ.js";
119
+ import {
120
+ DecideError,
121
+ correctDecision,
122
+ decisionsView,
123
+ undoBatch
124
+ } from "./chunk-LFHBAWIM.js";
125
+ import {
126
+ answerAudit,
127
+ auditLines,
128
+ defaultAuditSeed,
129
+ precisionOf,
130
+ prepareAudit,
131
+ writeAudit
132
+ } from "./chunk-CRYIBCGP.js";
169
133
  import {
134
+ readNextState,
170
135
  uiOnboardingRoutes
171
- } from "./chunk-EP7ZBZLT.js";
136
+ } from "./chunk-YXG2VQJJ.js";
137
+ import "./chunk-ALCSTVWQ.js";
138
+ import {
139
+ idFromUrl
140
+ } from "./chunk-IMBJ7WAO.js";
172
141
  import "./chunk-X7XVMYIL.js";
173
- import "./chunk-HHZEXF7V.js";
142
+ import {
143
+ matchDone,
144
+ quotesOf,
145
+ readMatch,
146
+ runMatch
147
+ } from "./chunk-B56FCIEJ.js";
148
+ import "./chunk-HVPS2YCW.js";
149
+ import "./chunk-AMZ4XMES.js";
150
+ import {
151
+ copilotAcpAllowed
152
+ } from "./chunk-KMYB2XO7.js";
153
+ import "./chunk-IXNMGPF7.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-AGAFNUYZ.js";
162
+ } from "./chunk-VN2VJ6BV.js";
181
163
  import {
182
164
  contractCheckOf,
183
165
  estateJoinOnFile,
184
166
  stampOf
185
- } from "./chunk-WA644MUQ.js";
186
- import "./chunk-YEGGQG5E.js";
187
- import "./chunk-TIOYZDRB.js";
167
+ } from "./chunk-FM3EEDS2.js";
168
+ import "./chunk-P36PTWBM.js";
169
+ import {
170
+ readRepos
171
+ } from "./chunk-FC3ZVD3O.js";
172
+ import {
173
+ filesUnder,
174
+ memoByFiles,
175
+ recheckNow,
176
+ uiFactsRoutes
177
+ } from "./chunk-F66542M6.js";
178
+ import {
179
+ safeMessage,
180
+ withFileLock
181
+ } from "./chunk-SFCFL7Y5.js";
182
+ import "./chunk-UYYYQTPD.js";
183
+ import {
184
+ syncNextOf
185
+ } from "./chunk-EHXDB3SA.js";
186
+ import "./chunk-OUGTAOGA.js";
187
+ import "./chunk-FG65LXED.js";
188
+ import "./chunk-YAPVAYZN.js";
188
189
  import {
189
190
  MACHINE_CHECKING,
190
191
  baselineCommand,
191
192
  setupSteps
192
- } from "./chunk-XC5ZDFW7.js";
193
- import {
194
- doctorChecks
195
- } from "./chunk-F36DIKJ3.js";
193
+ } from "./chunk-Z4GLFTEH.js";
196
194
  import {
197
195
  readMe,
198
196
  writeMe
199
- } from "./chunk-XY6FVBBV.js";
197
+ } from "./chunk-MZDHFWTN.js";
200
198
  import {
201
199
  buildTask,
202
200
  cancelTaskRunWait,
@@ -210,69 +208,68 @@ import {
210
208
  settleTaskPr,
211
209
  stopAllBuilds,
212
210
  taskRunOfRun
213
- } from "./chunk-5RDKQOY3.js";
214
- import "./chunk-5WZV37WS.js";
215
- import "./chunk-DBVQEPZB.js";
211
+ } from "./chunk-SHFY73RI.js";
212
+ import "./chunk-FKAUBC4Y.js";
213
+ import "./chunk-VVLWEM2Y.js";
216
214
  import {
217
215
  checkoutOf
218
- } from "./chunk-XP5DF5MC.js";
219
- import "./chunk-G5P7F6RQ.js";
216
+ } from "./chunk-QPAANKUR.js";
217
+ import "./chunk-FADIWOA5.js";
220
218
  import {
221
219
  intakeContext
222
- } from "./chunk-J65TN6QU.js";
220
+ } from "./chunk-YJTBE6AJ.js";
221
+ import "./chunk-LZO3JABE.js";
223
222
  import {
224
- scanCommand
225
- } from "./chunk-UCQB6NKS.js";
226
- import "./chunk-BS52P2CM.js";
223
+ scanCommand,
224
+ scanSummaryLines
225
+ } from "./chunk-VC2XHC7P.js";
226
+ import "./chunk-OQ7SBQ2Z.js";
227
227
  import {
228
228
  catalogRecords,
229
229
  openChanges,
230
230
  systemGuide
231
- } from "./chunk-N3OEBQTA.js";
231
+ } from "./chunk-CDC6VECU.js";
232
+ import {
233
+ doctorChecks
234
+ } from "./chunk-2666BPJE.js";
232
235
  import {
233
236
  isMetarepo
234
237
  } from "./chunk-3G4YI4ZU.js";
235
- import "./chunk-EAGSM3XY.js";
236
- import "./chunk-C5LX54QK.js";
237
238
  import {
238
239
  workspaceOpen,
239
240
  workspaceSync
240
- } from "./chunk-2ULVUSIP.js";
241
- import "./chunk-EXCXNDTQ.js";
242
- import "./chunk-I2M7MXSV.js";
241
+ } from "./chunk-QGMD3PYL.js";
242
+ import "./chunk-IF3X6FMO.js";
243
+ import "./chunk-RWYPLODE.js";
243
244
  import {
244
245
  readChangeTasks,
245
246
  readStory,
246
247
  setTaskDone
247
- } from "./chunk-MN2XDLDM.js";
248
- import {
249
- ASSISTANT_FORMATS,
250
- readProbes,
251
- whatRunsWhere
252
- } from "./chunk-H7GAPNGQ.js";
253
- import {
254
- critic,
255
- criticStats,
256
- findingAction
257
- } from "./chunk-A3AADMM2.js";
258
- import "./chunk-MJMEF7SD.js";
248
+ } from "./chunk-YSSFS3YC.js";
259
249
  import {
260
250
  planStories,
261
251
  snowDraft,
262
252
  snowSubmit
263
- } from "./chunk-YAUMNRCB.js";
264
- import "./chunk-2Y5FJQSF.js";
253
+ } from "./chunk-OC3OXDTG.js";
254
+ import "./chunk-4UVTNHA6.js";
265
255
  import {
266
256
  ciArchiveGate
267
- } from "./chunk-IMTAHDME.js";
257
+ } from "./chunk-IX2EOYOU.js";
268
258
  import {
269
259
  traceMatrix
270
- } from "./chunk-SEBBJQWK.js";
260
+ } from "./chunk-YAPMGK7E.js";
271
261
  import "./chunk-MUWDB4R4.js";
272
- import "./chunk-VOGCSYOI.js";
273
262
  import {
274
263
  archiveGate
275
- } from "./chunk-JWLABUXL.js";
264
+ } from "./chunk-62LD7CSY.js";
265
+ import "./chunk-QCRQNYGI.js";
266
+ import "./chunk-XRWUYOX3.js";
267
+ import "./chunk-N3JGYAMD.js";
268
+ import "./chunk-ZJJMYPGZ.js";
269
+ import {
270
+ initiativeStatus,
271
+ readView
272
+ } from "./chunk-NYT6QGZA.js";
276
273
  import {
277
274
  CORRECTIONS_FILE,
278
275
  FEATURE_FILE,
@@ -322,24 +319,46 @@ import {
322
319
  syncWorkItems,
323
320
  threadReplies,
324
321
  writeSketch
325
- } from "./chunk-IWQEZFVV.js";
322
+ } from "./chunk-JL2VOYSL.js";
326
323
  import {
327
324
  FeaturePlacement,
328
325
  STAGES,
329
326
  STAGE_PHASE,
330
327
  fieldNames,
331
328
  rerunOf
332
- } from "./chunk-EM7F6XEU.js";
329
+ } from "./chunk-INCFIDCB.js";
333
330
  import {
334
331
  HttpError,
335
332
  badRequest,
336
333
  conflict,
334
+ intParam,
337
335
  notFound,
338
336
  problem,
339
337
  requireConfirmation,
340
338
  startServer,
341
339
  strParam
342
- } from "./chunk-QSKY7FE3.js";
340
+ } from "./chunk-Y2TVTI4P.js";
341
+ import {
342
+ addressRefusal,
343
+ asTheApp,
344
+ recordConfirmedAddress,
345
+ requireConfirmedModel,
346
+ servingTheApp,
347
+ whereKeyGoes
348
+ } from "./chunk-WCA3WIGG.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-TD5WWJLN.js";
360
+ import "./chunk-NC3Q7RIB.js";
361
+ import "./chunk-VOGCSYOI.js";
343
362
  import {
344
363
  layerRules,
345
364
  loadConstitution,
@@ -352,11 +371,12 @@ import {
352
371
  readStoryIndex,
353
372
  reviewedGates,
354
373
  roundsOf
355
- } from "./chunk-GDGE7ZHC.js";
374
+ } from "./chunk-U3Z2QZE3.js";
356
375
  import {
357
376
  ChangeOwnersError,
358
377
  artifactFiles,
359
378
  artifactPhase,
379
+ artifactWritten,
360
380
  changeFolder,
361
381
  changeReport,
362
382
  changeSize,
@@ -365,6 +385,7 @@ import {
365
385
  handoffBranchPushed,
366
386
  liveHandoff,
367
387
  loadChangeContext,
388
+ personWrittenPlanning,
368
389
  pushHandoffBranch,
369
390
  readTaskDecision,
370
391
  recordTaskDecision,
@@ -372,30 +393,8 @@ import {
372
393
  setChangeOwners,
373
394
  unmergedTaskBranches,
374
395
  unmergedTaskWords
375
- } from "./chunk-JQGWP3SC.js";
376
- import "./chunk-UTZMF5CV.js";
377
- import {
378
- fileStepStore,
379
- manualAdapter,
380
- stepOfProvisional
381
- } from "./chunk-U7YZ3IRI.js";
382
- import "./chunk-DLNQ3HUM.js";
383
- import {
384
- addressRefusal,
385
- asTheApp,
386
- recordConfirmedAddress,
387
- requireConfirmedModel,
388
- servingTheApp,
389
- whereKeyGoes
390
- } from "./chunk-MELS6T5J.js";
391
- import "./chunk-KVVNAUIG.js";
392
- import {
393
- COMMON_SETTINGS,
394
- PROVIDER_SETTINGS,
395
- defaultKeyStore,
396
- keyEnvFromEnvironment,
397
- looksLikeKey
398
- } from "./chunk-4SS5ZK47.js";
396
+ } from "./chunk-SVOGRJO6.js";
397
+ import "./chunk-23TTURB2.js";
399
398
  import {
400
399
  componentRenames,
401
400
  estateFacts,
@@ -405,16 +404,18 @@ import {
405
404
  joinReposOf,
406
405
  keepCatalogsInMemory,
407
406
  outsideProfileSystems,
407
+ promotedStates,
408
408
  readCatalog,
409
+ readCrossCheck,
409
410
  targetPicker
410
- } from "./chunk-YRKAJ42V.js";
411
+ } from "./chunk-QC6GSNIK.js";
411
412
  import {
412
413
  NoSuchNode,
413
414
  buildEstate,
414
415
  focusView,
415
416
  nodeView,
416
417
  viewKey
417
- } from "./chunk-CGVRLQAY.js";
418
+ } from "./chunk-YIGSUTW2.js";
418
419
  import {
419
420
  OrgPackProposal,
420
421
  SNAPSHOT_FILE,
@@ -438,29 +439,42 @@ import {
438
439
  snapshotDates,
439
440
  snapshotSources,
440
441
  writeReview
441
- } from "./chunk-RL7PETU6.js";
442
- import {
443
- readServiceRequestExports,
444
- readVendorSpec,
445
- readWorkItemExports
446
- } from "./chunk-PGKCRK77.js";
447
- import "./chunk-M6HI36T3.js";
448
- import "./chunk-2VN4TLGI.js";
449
- import "./chunk-4U3JLIRC.js";
450
- import "./chunk-MXPKXCGP.js";
451
- import "./chunk-DJ4C5ELF.js";
442
+ } from "./chunk-N5DLB74D.js";
443
+ import "./chunk-UWBODTY7.js";
452
444
  import {
453
- batchSections,
454
- providerFactoryFor
455
- } from "./chunk-QQD25YNF.js";
456
- import "./chunk-QA4O2GGC.js";
445
+ fileStepStore,
446
+ manualAdapter,
447
+ stepOfProvisional
448
+ } from "./chunk-I57IH5X6.js";
449
+ import "./chunk-LCQIRCOT.js";
457
450
  import {
458
451
  baseClonePath,
459
452
  changeWorktreesDir,
460
453
  cloneUrlKey,
461
454
  loadRepos,
462
455
  readChangeRepos
463
- } from "./chunk-WS7KBKP4.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-T2MN24LZ.js";
477
+ import "./chunk-3PBIZBWN.js";
464
478
  import {
465
479
  ADAPTER_FIELDS,
466
480
  ADAPTER_KINDS,
@@ -498,6 +512,7 @@ import {
498
512
  factsDirOf,
499
513
  factsFileOf,
500
514
  factsRelOf,
515
+ headFromFiles,
501
516
  inEol,
502
517
  inputsDirOf,
503
518
  isAdopted,
@@ -532,19 +547,22 @@ import {
532
547
  specRepos,
533
548
  undeclareLink,
534
549
  writeOrgPackFile
535
- } from "./chunk-GLISHJ4G.js";
550
+ } from "./chunk-WJWSB65O.js";
536
551
  import {
537
552
  FileChangedError,
538
553
  RUN_LOG_READ_MAX,
539
554
  createLog,
555
+ isMetarepoRoot,
556
+ onAtticusSignal,
540
557
  printToCurrent,
541
558
  readTerminalRunLines,
542
559
  readTerminalRuns,
560
+ redactText,
543
561
  runLogsDirOf,
544
562
  tailTerminalRunLines,
545
563
  writeFileAtomic,
546
564
  writeFileIfUnchanged
547
- } from "./chunk-G3ZFEHCX.js";
565
+ } from "./chunk-SMFFUFMN.js";
548
566
  import {
549
567
  ASSISTANTS,
550
568
  ChangeArtifact,
@@ -565,18 +583,23 @@ import {
565
583
  decideOf,
566
584
  external_exports,
567
585
  gateRoundLimit,
586
+ hostMatches,
568
587
  joinConventions,
569
588
  knowledgeKindOf,
570
589
  loadOrgPack,
571
590
  pageStanding
572
- } from "./chunk-LZFKJ2BR.js";
591
+ } from "./chunk-A3LVMCA5.js";
573
592
  import {
574
593
  keptFilesMayHaveChanged,
575
594
  trustKeptFiles
576
- } from "./chunk-CTJHEG6A.js";
595
+ } from "./chunk-NWMFVPEP.js";
577
596
  import {
578
597
  require_dist
579
598
  } from "./chunk-BQGDB6ZL.js";
599
+ import "./chunk-R4TUWD4C.js";
600
+ import {
601
+ isHandoffStep
602
+ } from "./chunk-4Q3NN7VF.js";
580
603
  import {
581
604
  __toESM
582
605
  } from "./chunk-TV45EUGM.js";
@@ -608,11 +631,20 @@ function tracked(ctx, title, work, o = {}) {
608
631
  const jobs = ctx.jobs;
609
632
  if (!jobs || typeof jobs.track !== "function")
610
633
  return work();
611
- 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
+ };
612
640
  return ctx.jobs.track(o.kind ?? "work", (c) => work(c), opts);
613
641
  }
614
642
  function answerAsJob(ctx, title, work, o = {}) {
615
- 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
+ };
616
648
  const job = ctx.jobs.start(o.kind ?? "work", async () => {
617
649
  try {
618
650
  const answer = await work();
@@ -647,9 +679,16 @@ async function trackedLocal(ctx, title, work, o = {}) {
647
679
  return tracked(ctx, title, (c) => {
648
680
  c?.progress(0, 1, title);
649
681
  return work(c);
650
- }, { kind: "local", ...o.meta ? { meta: o.meta } : {} });
682
+ }, { kind: "local", ...o.meta ? { meta: o.meta } : {}, ...o.ids ? { ids: o.ids } : {} });
651
683
  }
652
684
  var jobState = (j) => j.state === "queued" ? "running" : j.state;
685
+ var PREPARED_MS = 15 * 60 * 1e3;
686
+ var WHERE_WORDS = {
687
+ terminal: "in a terminal",
688
+ vscode: "in VS Code",
689
+ intellij: "in IntelliJ",
690
+ copilot: "in a Copilot session"
691
+ };
653
692
  function readHandoffRuns(root, now) {
654
693
  const out = [];
655
694
  let changes;
@@ -696,6 +735,8 @@ function readHandoffRuns(root, now) {
696
735
  return out.sort((a, b) => b.startedAt.localeCompare(a.startedAt)).slice(0, HANDOFF_MAX);
697
736
  }
698
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;
699
740
  var newestFirst = (a, b) => b.startedAt.localeCompare(a.startedAt) || b.id.localeCompare(a.id);
700
741
  function newestKeepingRunning(entries, max) {
701
742
  const running = entries.filter((e) => e.state === "running");
@@ -706,6 +747,7 @@ function uiActivityRoutes(r, ctx, deps = {}) {
706
747
  const root = ctx.root;
707
748
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
708
749
  const readOpts = { ...deps.alive ? { alive: deps.alive } : {}, now };
750
+ const fromLog = (t) => !(t.startedBy === "app" && ctx.jobs.ownsRun?.(t.runId));
709
751
  const jobEntry = (j) => {
710
752
  const meta = ctx.jobs.metaOf(j.id) ?? {};
711
753
  const lines = ctx.jobs.linesOf(j.id);
@@ -736,16 +778,21 @@ function uiActivityRoutes(r, ctx, deps = {}) {
736
778
  lines: lines?.total ?? 0,
737
779
  from: lines?.from ?? 0,
738
780
  ...j.state === "running" ? { stop: `/api/jobs/${encodeURIComponent(j.id)}/cancel` } : {},
739
- ...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" } : {}
740
785
  };
741
786
  };
742
787
  const tails = /* @__PURE__ */ new Map();
743
788
  const terminalEntry = (t, total) => ({
744
789
  id: `${TERM}${t.runId}`,
745
- 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",
746
793
  title: t.title,
747
794
  where: t.startedBy,
748
- state: t.stale ? "ended" : t.state,
795
+ state: t.stale || t.appClosed ? "ended" : t.state,
749
796
  startedAt: t.startedAt,
750
797
  ...t.finishedAt ? { finishedAt: t.finishedAt } : {},
751
798
  ...t.exitCode !== void 0 ? { exitCode: t.exitCode } : {},
@@ -765,13 +812,13 @@ function uiActivityRoutes(r, ctx, deps = {}) {
765
812
  const tick = () => {
766
813
  let runs;
767
814
  try {
768
- runs = readTerminalRuns(root, readOpts);
815
+ runs = readTerminalRuns(root, readOpts).filter(fromLog);
769
816
  } catch {
770
817
  return;
771
818
  }
772
819
  for (const t of runs) {
773
820
  const was = tails.get(t.runId);
774
- const state = t.stale ? "ended" : t.state;
821
+ const state = t.stale || t.appClosed ? "ended" : t.state;
775
822
  const { size, ino } = logStat(t.runId);
776
823
  if (was && !was.more && was.state === state && was.size === size && was.ino === ino)
777
824
  continue;
@@ -854,10 +901,29 @@ function uiActivityRoutes(r, ctx, deps = {}) {
854
901
  handoffCache = { at: t, runs: readHandoffRuns(root, now().getTime()) };
855
902
  return handoffCache.runs;
856
903
  };
904
+ const preparedBy = (h) => {
905
+ const at = Date.parse(h.startedAt);
906
+ let best;
907
+ for (const t of readTerminalRuns(root, readOpts)) {
908
+ if (t.command[0] === "handoff" || !t.command.slice(1).includes(h.change))
909
+ continue;
910
+ const s = Date.parse(t.startedAt);
911
+ if (!(s <= at && at - s <= PREPARED_MS))
912
+ continue;
913
+ if (!best || t.startedAt > best.startedAt)
914
+ best = t;
915
+ }
916
+ return best;
917
+ };
857
918
  const handoffLines = (h) => {
858
919
  const shape = [handoffState(h.state)];
859
920
  const prompt = `${runsRelOf(root)}/${h.change}/${h.runId}/prompt.md`;
860
921
  const out = [];
922
+ const by = preparedBy(h);
923
+ if (by) {
924
+ shape.push(`prepared ${by.runId}`);
925
+ out.push(`Prepared by ${by.title}, ${WHERE_WORDS[by.startedBy] ?? `in ${by.startedBy}`}.`);
926
+ }
861
927
  if (handoffState(h.state) === "waiting") {
862
928
  out.push(`Waiting for your assistant${h.agent ? ` (${h.agent})` : ""} on ${h.change}.`, `The prompt: ${prompt}`, "Give it to your assistant (Copilot Chat, Claude Code): copy it from Set up \u203A Model runs, or open the file.", h.output ? `When the answer is in ${h.output}, press Done on its run, or run: atticus handoff done ${h.runId}` : `When the answer is written, press Done on its run, or run: atticus handoff done ${h.runId}`);
863
929
  } else {
@@ -929,7 +995,7 @@ function uiActivityRoutes(r, ctx, deps = {}) {
929
995
  tick();
930
996
  const entries = [
931
997
  ...ctx.jobs.list().map(jobEntry),
932
- ...readTerminalRuns(root, readOpts).map((t) => terminalEntry(t)),
998
+ ...readTerminalRuns(root, readOpts).filter(fromLog).map((t) => terminalEntry(t)),
933
999
  ...handoffEntries()
934
1000
  ];
935
1001
  const kept = newestKeepingRunning(entries, MAX_ENTRIES);
@@ -942,7 +1008,7 @@ function uiActivityRoutes(r, ctx, deps = {}) {
942
1008
  const l2 = t ? readTerminalRunLines(root, runId, from) : void 0;
943
1009
  if (!t || !l2)
944
1010
  throw notFound(`There is no activity ${id}.`);
945
- return { id, ...l2, state: t.stale ? "ended" : t.state };
1011
+ return { id, ...l2, state: t.stale || t.appClosed ? "ended" : t.state };
946
1012
  }
947
1013
  if (RUN_DIR.test(id)) {
948
1014
  handoffCache = void 0;
@@ -1006,19 +1072,19 @@ async function changesWithWorktrees(root) {
1006
1072
  function uiStepRoutes(r, ctx, asJob) {
1007
1073
  const root = ctx.root;
1008
1074
  return r.add("POST", "/api/facts/apply-all", async () => {
1009
- const { verifyAllCommand } = await import("./chunk-CQRFCWQV.js");
1075
+ const { verifyAllCommand } = await import("./chunk-QDGNDNBG.js");
1010
1076
  return asJob("Applying to every repo", () => captured((io) => verifyAllCommand(root, { write: true, verbose: false, json: false }, io)));
1011
1077
  }).add("POST", "/api/estate/join", async () => {
1012
- const { estateJoin } = await import("./chunk-LOJGNSPA.js");
1078
+ const { estateJoin } = await import("./chunk-67Y2J55V.js");
1013
1079
  return asJob("Joining the estate's flows", () => captured((io) => estateJoin(root, { json: false }, io)));
1014
1080
  }).add("POST", "/api/knowledge/sources/sync", async () => {
1015
- const { sourcesSync: sourcesSync2 } = await import("./chunk-K3OIBTCV.js");
1081
+ const { sourcesSync: sourcesSync2 } = await import("./chunk-BABATPOZ.js");
1016
1082
  return asJob("Syncing every wiki", () => captured((io) => sourcesSync2(root, io, { json: false })));
1017
1083
  }).add("POST", "/api/workspace/prune", async ({ body }) => {
1018
1084
  const change = body?.change;
1019
1085
  if (change !== void 0 && (typeof change !== "string" || !ID2.test(change)))
1020
1086
  throw badRequest("change is a change id, or left out for every change with worktrees.");
1021
- const { workspacePrune } = await import("./chunk-S7I7SLZN.js");
1087
+ const { workspacePrune } = await import("./chunk-OWP5FCYM.js");
1022
1088
  return asJob(change ? `Cleaning up ${change}'s worktrees` : "Cleaning up worktrees", () => captured(async (io) => {
1023
1089
  const list = change ? [change] : await changesWithWorktrees(root);
1024
1090
  if (!list.length) {
@@ -1033,7 +1099,7 @@ function uiStepRoutes(r, ctx, asJob) {
1033
1099
  return code;
1034
1100
  }));
1035
1101
  }).add("GET", "/api/changes/{changeId}/tasks/{taskId}/context", async ({ params }) => {
1036
- const { taskContextCli } = await import("./chunk-NMBHFSJQ.js");
1102
+ const { taskContextCli } = await import("./chunk-ALUHO7SE.js");
1037
1103
  const lines = [];
1038
1104
  const errs = [];
1039
1105
  const code = await taskContextCli(root, params.changeId, params.taskId, { markdown: true }, { out: (l) => lines.push(l), err: (l) => errs.push(l) });
@@ -1044,13 +1110,244 @@ function uiStepRoutes(r, ctx, asJob) {
1044
1110
  const on = body?.on;
1045
1111
  if (typeof on !== "boolean")
1046
1112
  throw badRequest("on is true or false.");
1047
- const { setLocalRecording } = await import("./chunk-UJ535VWR.js");
1113
+ const { setLocalRecording } = await import("./chunk-Y6S7VCYN.js");
1048
1114
  await setLocalRecording(root, on);
1049
1115
  ctx.events.publish({ type: "file.changed", path: ".atticus/me.yaml" });
1050
1116
  return { status: 200, body: { on } };
1051
1117
  });
1052
1118
  }
1053
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-3W2QX6TT.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-YQ3IXQIH.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-MPNTEWNY.js");
1208
+ const { checkoutLineOf } = await import("./chunk-YQ3IXQIH.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-MPNTEWNY.js");
1221
+ const { catalogCrossCheck, checkoutLineOf } = await import("./chunk-YQ3IXQIH.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-QDGNDNBG.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-YQ3IXQIH.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-3W2QX6TT.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-22A2K555.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-3W2QX6TT.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-22A2K555.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-3W2QX6TT.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-3W2QX6TT.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-22A2K555.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-3W2QX6TT.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-3W2QX6TT.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-22A2K555.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-3W2QX6TT.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-3W2QX6TT.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-NSQB24WR.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
+
1054
1351
  // packages/cli/dist/ui-api.js
1055
1352
  import { createHash as createHash3 } from "node:crypto";
1056
1353
  import { existsSync } from "node:fs";
@@ -1117,7 +1414,7 @@ async function answerFile(root, s) {
1117
1414
  const inRun = join3(s.dir, out);
1118
1415
  if (s.run.request.outputIn === "run" || s.run.parts?.length)
1119
1416
  return inRun;
1120
- const { changesDirOf: changesDirOf2 } = await import("./chunk-WDJGJ3HV.js");
1417
+ const { changesDirOf: changesDirOf2 } = await import("./chunk-PPKH6ULR.js");
1121
1418
  return join3(changesDirOf2(root), s.run.request.change, out);
1122
1419
  }
1123
1420
  async function dueRuns(root, o) {
@@ -1271,13 +1568,14 @@ var TASK_ERRORS = /* @__PURE__ */ new Set([
1271
1568
  "GitError",
1272
1569
  "RuntimeError"
1273
1570
  ]);
1274
- async function run(f) {
1571
+ async function run(f, o = {}) {
1275
1572
  const out = [];
1276
1573
  const err = [];
1277
1574
  const code = await f({
1278
1575
  out: (l) => {
1279
1576
  out.push(l);
1280
- printToCurrent(l);
1577
+ if (!o.jsonOut)
1578
+ printToCurrent(l);
1281
1579
  },
1282
1580
  err: (l) => {
1283
1581
  err.push(l);
@@ -1286,6 +1584,9 @@ async function run(f) {
1286
1584
  });
1287
1585
  return { code, out, err };
1288
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
+ }
1289
1590
  function refused(r) {
1290
1591
  const detail = (r.err.length ? r.err : r.out).join("\n") || "The command refused.";
1291
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] });
@@ -1314,7 +1615,7 @@ async function readChange(root, id) {
1314
1615
  try {
1315
1616
  return await changeStore(root).read(id);
1316
1617
  } catch {
1317
- throw notFound(`There is no change ${id}.`);
1618
+ throw notFound(await missingChangeWords(root, id));
1318
1619
  }
1319
1620
  }
1320
1621
  async function changeDetail(root, id) {
@@ -1366,7 +1667,7 @@ async function changeDetail(root, id) {
1366
1667
  state: c.state,
1367
1668
  // ADR 0191 (app-only audit): the repos it names and its target flows' ("Name its repos on its
1368
1669
  // brief" stayed after the stories named them; the brief has no repos).
1369
- repos: await (await import("./chunk-N6SSI6XO.js")).changeRepos(root, c),
1670
+ repos: await (await import("./chunk-H25QNDKK.js")).changeRepos(root, c),
1370
1671
  openFindings: open,
1371
1672
  updatedAt: c.history.at(-1)?.at ?? c.createdAt,
1372
1673
  ...fast ? { fastPath: true } : {},
@@ -1520,7 +1821,7 @@ async function artifactPath(root, id, artifact, o = {}) {
1520
1821
  if (!a.success)
1521
1822
  throw badRequest(`${artifact} is not an artifact. Use one of ${ChangeArtifact.options.join(", ")}.`);
1522
1823
  const dir = join4(changesDirOf(root), id);
1523
- const files = await artifactFiles(dir, a.data);
1824
+ const files = o.listed ?? await artifactFiles(dir, a.data);
1524
1825
  if (o.file) {
1525
1826
  if (!files.includes(o.file))
1526
1827
  throw notFound(`${o.file} isn't one of change ${id}'s ${artifact} files.`);
@@ -1532,11 +1833,12 @@ async function artifactPath(root, id, artifact, o = {}) {
1532
1833
  throw notFound(`Change ${id} has no ${artifact} yet.`);
1533
1834
  return files[0];
1534
1835
  }
1836
+ var ARTIFACT_FILES_MAX = 200;
1535
1837
  function uiRoutes(r, ctx, deps = {}) {
1536
1838
  const { root, user, jobs } = ctx;
1537
1839
  const confirmed2 = (write, target, given) => requireConfirmation(ctx.confirmations, write, target, given);
1538
1840
  const readyView = async (change) => {
1539
- const { deployOrderOf } = await import("./chunk-SBNBVUOF.js");
1841
+ const { deployOrderOf } = await import("./chunk-GW6ZH77P.js");
1540
1842
  const repoOrder = await deployOrderOf(root, change);
1541
1843
  const prStates = /* @__PURE__ */ new Map();
1542
1844
  for (const t of await taskViews(root, change, {
@@ -1558,6 +1860,17 @@ function uiRoutes(r, ctx, deps = {}) {
1558
1860
  ...deps.notify ? { notify: deps.notify } : {}
1559
1861
  };
1560
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-3W2QX6TT.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
+ };
1561
1874
  const asJob = (what, work) => {
1562
1875
  const busy = ctx.jobs.runningOf("local");
1563
1876
  if (busy)
@@ -1568,11 +1881,11 @@ function uiRoutes(r, ctx, deps = {}) {
1568
1881
  c.progress(1, 1, res.code === 0 ? "Done" : "Stopped");
1569
1882
  ctx.events.publish({ type: "file.changed", path: "." });
1570
1883
  const raw = [...res.out, ...res.err];
1571
- const { appLines: appLines2 } = await import("./chunk-U4HZ5CXL.js");
1884
+ const { appLines: appLines2 } = await import("./chunk-E7Q52EOO.js");
1572
1885
  const lines = appLines2(raw);
1573
1886
  const next = res.code === 0 ? void 0 : syncNextOf(raw);
1574
1887
  return {
1575
- result: { code: res.code, lines, ...next ? { next } : {} },
1888
+ result: { ...res.extra, code: res.code, lines, ...next ? { next } : {} },
1576
1889
  errors: res.code === 0 ? [] : lines
1577
1890
  };
1578
1891
  }, { title: what });
@@ -1580,6 +1893,7 @@ function uiRoutes(r, ctx, deps = {}) {
1580
1893
  return { status: 202, body: { jobId: job.id } };
1581
1894
  };
1582
1895
  uiStepRoutes(r, ctx, asJob);
1896
+ uiCatalogRoutes(r, ctx, asJob);
1583
1897
  const doneRun = async (runId, by) => {
1584
1898
  const { before, onlyResume } = await doneMayStart(runId);
1585
1899
  try {
@@ -1599,7 +1913,7 @@ function uiRoutes(r, ctx, deps = {}) {
1599
1913
  };
1600
1914
  const doneMayStart = async (runId) => {
1601
1915
  const before = await findRun(root, runId);
1602
- const { hasKeptResume: hasKeptResume2 } = await import("./chunk-U4HZ5CXL.js");
1916
+ const { hasKeptResume: hasKeptResume2 } = await import("./chunk-E7Q52EOO.js");
1603
1917
  const onlyResume = before.state === "validated" && await hasKeptResume2(root, runId);
1604
1918
  if (before.state === "validated" && !onlyResume || before.state === "cancelled")
1605
1919
  throw conflict(`Run ${runId} is already ${before.state}.`);
@@ -1621,17 +1935,17 @@ function uiRoutes(r, ctx, deps = {}) {
1621
1935
  }
1622
1936
  const after = await findRun(root, runId);
1623
1937
  ctx.events.publish({ type: "run.changed", runId: after.runId, state: after.state });
1624
- const { resumeAfterDone, appLines: appLines2 } = await import("./chunk-U4HZ5CXL.js");
1938
+ const { resumeAfterDone, appLines: appLines2 } = await import("./chunk-E7Q52EOO.js");
1625
1939
  if (res.code !== 0)
1626
1940
  throw refused({ ...res, out: appLines2(res.out), err: appLines2(res.err) });
1627
1941
  const stepRunner = deps.runStep ?? (async (args) => {
1628
- const { main } = await import("./chunk-XZQBFF65.js");
1942
+ const { main } = await import("./chunk-FS4E7F6O.js");
1629
1943
  const out = [];
1630
1944
  const err = [];
1631
1945
  const code = await main([...args, "--root", root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
1632
1946
  return { code, out, err };
1633
1947
  });
1634
- const { hasKeptResume: kept } = await import("./chunk-U4HZ5CXL.js");
1948
+ const { hasKeptResume: kept } = await import("./chunk-E7Q52EOO.js");
1635
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] }));
1636
1950
  if (resumed)
1637
1951
  ctx.events.publish({ type: "file.changed", path: changesRelOf(root) });
@@ -1650,35 +1964,62 @@ function uiRoutes(r, ctx, deps = {}) {
1650
1964
  };
1651
1965
  };
1652
1966
  startAutoDone(ctx, (runId) => doneRun(runId, "app"), deps.autoDone ?? {});
1653
- return r.add("POST", "/api/facts/{repo}/apply", async ({ params }) => {
1654
- const { verifyCommand } = await import("./chunk-CQRFCWQV.js");
1967
+ return r.add("POST", "/api/facts/{repo}/apply", async ({ params, body }) => {
1968
+ const { verifyCommand } = await import("./chunk-QDGNDNBG.js");
1969
+ const b = parseBody(api_exports.FactsApplyRequest, body);
1655
1970
  const repo = params.repo;
1656
1971
  if (!FACTS_REPO.test(repo))
1657
1972
  throw badRequest(`${JSON.stringify(repo)} isn't a repo name.`);
1658
1973
  if (!(await loadRepos(root)).some((x) => x.id === repo))
1659
1974
  throw notFound(`There is no repo ${repo} in this workspace.`);
1660
- return asJob(`Applying to ${repo}`, () => run((io) => verifyCommand(root, repo, { write: true, verbose: false, json: false }, io)));
1661
- }).add("GET", "/api/upgrade", async () => keptAnswer(root, "upgrade", async () => {
1662
- const { newerAtticusOf, upgradeCheck } = await import("./chunk-QBK33722.js");
1663
- const c = await upgradeCheck(root);
1664
- const stamp3 = c.stamp?.atticus ?? newerAtticusOf(c);
1665
- const body = {
1666
- atticus: c.atticus,
1667
- newer: c.newer,
1668
- ...stamp3 ? { stamp: stamp3 } : {},
1669
- pending: c.pending
1670
- };
1671
- return { status: 200, body };
1672
- })).add("POST", "/api/upgrade", async () => {
1673
- const { newerThan, newerWords, upgradeCheck, upgradeCommand } = await import("./chunk-QBK33722.js");
1975
+ await refusalStillListed(b, (c) => c === `atticus verify ${repo} --write`);
1976
+ return asJob(`Applying to ${repo}`, async () => {
1977
+ const { lastBuildOf } = await import("./chunk-3W2QX6TT.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-NSQB24WR.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-KNYQUWFN.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-NSQB24WR.js");
1674
2010
  const c = await upgradeCheck(root);
1675
2011
  if (c.newer)
1676
2012
  throw conflict(newerWords(c));
1677
2013
  if (!c.pending.length && c.stamp && !newerThan(c.atticus, c.stamp.atticus))
1678
2014
  throw conflict(`Nothing to upgrade: up to date for Atticus ${c.atticus}.`);
1679
- 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-KNYQUWFN.js");
2018
+ const upgraded = upgradedPaths(root).filter((p) => p !== UPGRADE_STAMP);
2019
+ return { ...ran, extra: { upgraded } };
2020
+ });
1680
2021
  }).add("GET", "/api/propose", async ({ query }) => {
1681
- const { proposePlan, PROPOSE_SCOPES } = await import("./chunk-RFQW7XT3.js");
2022
+ const { proposePlan, PROPOSE_SCOPES } = await import("./chunk-KNYQUWFN.js");
1682
2023
  const scope = query.get("scope") ?? "";
1683
2024
  if (!PROPOSE_SCOPES.includes(scope))
1684
2025
  throw refused({
@@ -1701,7 +2042,7 @@ function uiRoutes(r, ctx, deps = {}) {
1701
2042
  }).add("POST", "/api/propose", async ({ body }) => {
1702
2043
  const b = parseBody(api_exports.ProposeRequest, body);
1703
2044
  confirmed2("propose", b.scope, b.confirmation);
1704
- const { proposeForReview } = await import("./chunk-RFQW7XT3.js");
2045
+ const { proposeForReview } = await import("./chunk-KNYQUWFN.js");
1705
2046
  return asJob("Proposing for review", () => run((io) => proposeForReview(root, {
1706
2047
  scope: b.scope,
1707
2048
  by: user,
@@ -1710,15 +2051,15 @@ function uiRoutes(r, ctx, deps = {}) {
1710
2051
  ...b.branch ? { branch: b.branch } : {}
1711
2052
  }, io)));
1712
2053
  }).add("POST", "/api/propose/bring-in", async () => {
1713
- const { bringInMerged } = await import("./chunk-RFQW7XT3.js");
2054
+ const { bringInMerged } = await import("./chunk-KNYQUWFN.js");
1714
2055
  return asJob("Bringing in what merged", () => run((io) => bringInMerged(root, io)));
1715
2056
  }).add("POST", "/api/propose/upstream", async ({ body }) => {
1716
2057
  const b = parseBody(api_exports.UpstreamRequest, body);
1717
- const { setUpstream } = await import("./chunk-RFQW7XT3.js");
2058
+ const { setUpstream } = await import("./chunk-KNYQUWFN.js");
1718
2059
  return asJob(`Setting the upstream to ${b.upstream}`, () => run((io) => setUpstream(root, b.upstream, io)));
1719
2060
  }).add("POST", "/api/changes/{changeId}/conformance", async ({ params }) => {
1720
2061
  await readChange(root, params.changeId);
1721
- const { changeConformCommand } = await import("./chunk-DCPI3ETH.js");
2062
+ const { changeConformCommand } = await import("./chunk-GLHOUT5E.js");
1722
2063
  return asJob(`Checking ${params.changeId}'s code against its design`, () => run((io) => changeConformCommand(root, params.changeId, { findingsAnswer: true }, io)));
1723
2064
  }).add("GET", "/api/change-types", async () => {
1724
2065
  const op = await loadOrgPack(orgPackDirOf(root));
@@ -1767,9 +2108,13 @@ function uiRoutes(r, ctx, deps = {}) {
1767
2108
  path: `${changesRelOf(root)}/${params.changeId}/change.yaml`
1768
2109
  });
1769
2110
  return { status: 200, body: await changeDetail(root, params.changeId) };
1770
- }).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 }) => {
1771
2115
  await readChange(root, params.changeId);
1772
2116
  const rep = await changeReport(root, params.changeId);
2117
+ const said = await changeNextStep(root, params.changeId, rep, void 0, "page");
1773
2118
  return {
1774
2119
  status: 200,
1775
2120
  body: {
@@ -1777,7 +2122,9 @@ function uiRoutes(r, ctx, deps = {}) {
1777
2122
  ...rep.phase ? { phase: rep.phase } : {},
1778
2123
  ...rep.next ? { next: rep.next } : {},
1779
2124
  ...rep.progress ? { progress: rep.progress } : {},
1780
- nextStep: rep.nextStep,
2125
+ nextStep: said.nextStep,
2126
+ ...said.nextStepApp ? { nextStepApp: said.nextStepApp } : {},
2127
+ ...said.stepFirst ? { stepFirst: true } : {},
1781
2128
  risk: rep.risk,
1782
2129
  tests: rep.tests,
1783
2130
  ...rep.handoff ? {
@@ -1791,6 +2138,56 @@ function uiRoutes(r, ctx, deps = {}) {
1791
2138
  reasons: rep.reasons
1792
2139
  }
1793
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 } };
1794
2191
  }).add("GET", "/api/changes/{changeId}/artifacts/{artifact}", async ({ params, query }) => {
1795
2192
  await readChange(root, params.changeId);
1796
2193
  const rel = await artifactPath(root, params.changeId, params.artifact, {
@@ -1821,7 +2218,7 @@ function uiRoutes(r, ctx, deps = {}) {
1821
2218
  throw conflict(`${rel} changed since you opened it. Reload it, then make your edit again.`);
1822
2219
  await mkdir(dirname3(file), { recursive: true });
1823
2220
  await writeFileIfUnchanged(file, was, b.content);
1824
- const { recordPersonSave: recordPersonSave2 } = await import("./chunk-P4QTTCVK.js");
2221
+ const { recordPersonSave: recordPersonSave2 } = await import("./chunk-PDJL2HO5.js");
1825
2222
  await recordPersonSave2(join4(changesDirOf(root), params.changeId), params.changeId, {
1826
2223
  file: rel,
1827
2224
  who: user,
@@ -1961,7 +2358,7 @@ function uiRoutes(r, ctx, deps = {}) {
1961
2358
  left
1962
2359
  })
1963
2360
  };
1964
- }, { title: `Run the ready tasks of ${change}` });
2361
+ }, { title: `Run the ready tasks of ${change}`, log: { ids: [change] } });
1965
2362
  return { status: 202, body: api_exports.RunReadyAccepted.parse({ jobId: job.id, tasks }) };
1966
2363
  }).add("POST", "/api/changes/{changeId}/tasks/{taskId}/pr", async ({ params, body }) => {
1967
2364
  await readChange(root, params.changeId);
@@ -2119,7 +2516,7 @@ function uiRoutes(r, ctx, deps = {}) {
2119
2516
  const res = await run((io) => changeSync(root, params.changeId, { by: user, approve, ...b.repo ? { repo: b.repo } : {} }, io, changeDeps));
2120
2517
  if (res.code === 2)
2121
2518
  throw refused(res);
2122
- const { appLines: appLines2 } = await import("./chunk-U4HZ5CXL.js");
2519
+ const { appLines: appLines2 } = await import("./chunk-E7Q52EOO.js");
2123
2520
  return {
2124
2521
  status: 200,
2125
2522
  body: {
@@ -2129,14 +2526,14 @@ function uiRoutes(r, ctx, deps = {}) {
2129
2526
  };
2130
2527
  }).add("GET", "/api/changes/{changeId}/inputs", async ({ params }) => {
2131
2528
  const c = await readChange(root, params.changeId);
2132
- const { readChangeInputs } = await import("./chunk-LQD3R6NZ.js");
2529
+ const { readChangeInputs } = await import("./chunk-W6OY2PMB.js");
2133
2530
  return {
2134
2531
  status: 200,
2135
2532
  body: api_exports.ChangeInputList.parse(await readChangeInputs(join4(changesDirOf(root), c.id)))
2136
2533
  };
2137
2534
  }).add("GET", "/api/changes/{changeId}/prototypes", async ({ params }) => {
2138
2535
  const c = await readChange(root, params.changeId);
2139
- const { changePrototypes } = await import("./chunk-4GWQVT2C.js");
2536
+ const { changePrototypes } = await import("./chunk-NCNLX4DL.js");
2140
2537
  return {
2141
2538
  status: 200,
2142
2539
  body: api_exports.ChangePrototypeList.parse(await changePrototypes(root, c.id))
@@ -2144,7 +2541,7 @@ function uiRoutes(r, ctx, deps = {}) {
2144
2541
  }).add("POST", "/api/changes/{changeId}/prototypes", async ({ params, body }) => {
2145
2542
  const c = await readChange(root, params.changeId);
2146
2543
  const b = parseBody(api_exports.ComparePrototypeRequest, body);
2147
- const { attachPrototype, changePrototypes } = await import("./chunk-4GWQVT2C.js");
2544
+ const { attachPrototype, changePrototypes } = await import("./chunk-NCNLX4DL.js");
2148
2545
  const res = await run((io) => attachPrototype(root, c.id, b.repo, { by: user, ...deps.now ? { now: new Date(deps.now) } : {} }, io));
2149
2546
  if (res.code !== 0)
2150
2547
  throw refused(res);
@@ -2162,7 +2559,7 @@ function uiRoutes(r, ctx, deps = {}) {
2162
2559
  const bytes = new Uint8Array(Buffer.from(b.content, "base64"));
2163
2560
  if (bytes.length > MAX_ATTACH)
2164
2561
  throw new HttpError(413, "The file is too large", "Attach a file of 15 MB or less.");
2165
- const { attachFiles } = await import("./chunk-NMBHFSJQ.js");
2562
+ const { attachFiles } = await import("./chunk-ALUHO7SE.js");
2166
2563
  const r2 = await attachFiles(root, c.id, [{ name: b.name, bytes }], user);
2167
2564
  if (!r2.added.length)
2168
2565
  throw new HttpError(422, "Atticus can't attach that", r2.refused[0]?.why ?? "", {
@@ -2253,7 +2650,7 @@ function uiRoutes(r, ctx, deps = {}) {
2253
2650
  got = await once(next);
2254
2651
  }
2255
2652
  return got;
2256
- });
2653
+ }, { ids: [params.changeId] });
2257
2654
  if (res.code === 2)
2258
2655
  throw refused(res);
2259
2656
  ctx.events.publish({
@@ -2363,10 +2760,11 @@ function uiRoutes(r, ctx, deps = {}) {
2363
2760
  }
2364
2761
  const f = (await latestFindings(root, params.changeId)).find((x) => x.id === params.findingId);
2365
2762
  return { status: 200, body: f };
2366
- }).add("POST", "/api/scan", ({ body }) => {
2763
+ }).add("POST", "/api/scan", async ({ body }) => {
2367
2764
  const b = parseBody(api_exports.ScanRequest, body);
2368
2765
  if (jobs.runningOf("scan"))
2369
2766
  throw conflict("A scan is already running.");
2767
+ await refusalStillListed(b, (c) => c === "atticus scan" || c.startsWith("atticus scan "));
2370
2768
  const scanTitle = b.repos?.length ? `Scan ${b.repos.join(", ")}` : "Scan";
2371
2769
  const job = jobs.start("scan", async (c) => {
2372
2770
  c.progress(0, 1, "Checking with the built-in readers");
@@ -2377,8 +2775,12 @@ function uiRoutes(r, ctx, deps = {}) {
2377
2775
  json: true,
2378
2776
  // ADR 0123: another branch, scanned beside the baseline.
2379
2777
  ...b.ref ? { ref: b.ref } : {},
2380
- ...askFrom ? { askFrom } : {}
2381
- }, io));
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 } : {}
2783
+ }, io), { jsonOut: true });
2382
2784
  c.progress(1, 1, "Scanned");
2383
2785
  const parsed = (() => {
2384
2786
  try {
@@ -2387,7 +2789,21 @@ function uiRoutes(r, ctx, deps = {}) {
2387
2789
  return {};
2388
2790
  }
2389
2791
  })();
2792
+ for (const l of scanSummaryLines(parsed))
2793
+ printToCurrent(scanAppWords(l));
2390
2794
  const problems = parsed.problems?.length ?? 0;
2795
+ const refusal3 = parsed.refused;
2796
+ const sources = Array.isArray(parsed.sources) ? parsed.sources : [];
2797
+ if (refusal3)
2798
+ return {
2799
+ result: {
2800
+ stats: parsed.stats,
2801
+ problems,
2802
+ written: false,
2803
+ refused: { ...refusal3, message: scanAppWords(refusal3.message) },
2804
+ sources
2805
+ }
2806
+ };
2391
2807
  ctx.events.publish({
2392
2808
  type: "index.rebuilt",
2393
2809
  records: Number(parsed.stats?.records ?? 0)
@@ -2399,10 +2815,18 @@ function uiRoutes(r, ctx, deps = {}) {
2399
2815
  const questions = parsed.questions?.length ?? 0;
2400
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.`);
2401
2817
  return {
2402
- 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
+ },
2403
2827
  errors: res.code === 2 ? res.err : []
2404
2828
  };
2405
- }, { title: scanTitle });
2829
+ }, { title: scanTitle, log: { ids: b.repos ?? [] } });
2406
2830
  return { status: 202, body: { jobId: job.id } };
2407
2831
  }).add("POST", "/api/workspace/sync", ({ body }) => {
2408
2832
  const b = parseBody(api_exports.ScanRequest.pick({ repos: true }), body);
@@ -2411,32 +2835,42 @@ function uiRoutes(r, ctx, deps = {}) {
2411
2835
  throw conflict(`A sync is already running (${busy.id}): wait for it to finish.`);
2412
2836
  const job = jobs.start("sync", async (c) => {
2413
2837
  c.progress(0, 1, "Syncing base clones");
2414
- const res = await run((io) => workspaceSync(root, b.repos, io));
2838
+ const res = await run((io) => workspaceSync(root, b.repos, io, { signal: c.signal }));
2415
2839
  c.progress(1, 1, res.code === 0 ? "Synced" : "Stopped");
2416
2840
  const lines = [...res.out, ...res.err];
2841
+ if (c.cancelled)
2842
+ return { result: { code: res.code, lines } };
2417
2843
  return {
2418
2844
  result: { code: res.code, lines },
2419
2845
  errors: res.code === 0 ? [] : res.err.length ? res.err : lines
2420
2846
  };
2421
- }, { 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
+ });
2422
2851
  return { status: 202, body: { jobId: job.id } };
2423
2852
  }).add("POST", "/api/reconcile", ({ body }) => {
2424
2853
  const b = parseBody(api_exports.ReconcileRequest, body);
2425
2854
  const busy = jobs.runningOf("reconcile");
2426
2855
  if (busy)
2427
2856
  throw conflict(`A reconcile is already running (${busy.id}): wait for it to finish.`);
2428
- const job = jobs.start("reconcile", async (c) => {
2429
- c.progress(0, 1, `Reconciling ${b.diagram}`);
2430
- const res = await run((io) => reconcileCommand(root, [b.diagram], { json: true }, io));
2431
- c.progress(1, 1, "Reconciled");
2432
- let result;
2433
- try {
2434
- result = JSON.parse(res.out.join("\n"));
2435
- } catch {
2436
- result = { lines: res.out };
2437
- }
2438
- return { result, errors: res.code === 2 ? res.err : [] };
2439
- }, { 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
+ );
2440
2874
  return { status: 202, body: { jobId: job.id } };
2441
2875
  });
2442
2876
  }
@@ -2496,7 +2930,7 @@ async function readChange2(root, id) {
2496
2930
  try {
2497
2931
  return await changeStore(root).read(id);
2498
2932
  } catch {
2499
- throw notFound(`There is no change ${id}.`);
2933
+ throw notFound(await missingChangeWords(root, id));
2500
2934
  }
2501
2935
  }
2502
2936
  async function openChanges2(root) {
@@ -2804,7 +3238,7 @@ function uiRunRoutes(r, ctx, deps = {}) {
2804
3238
  io,
2805
3239
  // the step's sync is said apart, as `synced`, below
2806
3240
  { ...deps.todo, sync: false }
2807
- )));
3241
+ )), { ids: [params.stepId] });
2808
3242
  if (res.code !== 0) {
2809
3243
  if (res.err.some((l) => /^There is no step/.test(l)))
2810
3244
  throw notFound(res.err.join("\n"));
@@ -2940,7 +3374,12 @@ function uiRunRoutes(r, ctx, deps = {}) {
2940
3374
  state: rep.state,
2941
3375
  ...rep.phase ? { phase: rep.phase } : {},
2942
3376
  ...rep.next ? { next: rep.next } : {},
2943
- 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
+ })),
2944
3383
  risk: rep.risk,
2945
3384
  blockers: rep.blockers,
2946
3385
  reasons: rep.reasons
@@ -3431,7 +3870,7 @@ function uiKnowRoutes(r, ctx, o = {}) {
3431
3870
  const args = build(arg);
3432
3871
  if (!args)
3433
3872
  throw badRequest(`The ${name} view needs an id: /api/view/${name}/<id>.`);
3434
- const { main } = await import("./chunk-XZQBFF65.js");
3873
+ const { main } = await import("./chunk-FS4E7F6O.js");
3435
3874
  const out = [];
3436
3875
  const err = [];
3437
3876
  const code = await main([...args, "--json", "--root", ctx.root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
@@ -3461,7 +3900,7 @@ function uiKnowRoutes(r, ctx, o = {}) {
3461
3900
  return { status: 200, body: { code, data: body, problems: err } };
3462
3901
  };
3463
3902
  const text = async (args) => {
3464
- const { main } = await import("./chunk-XZQBFF65.js");
3903
+ const { main } = await import("./chunk-FS4E7F6O.js");
3465
3904
  const out = [];
3466
3905
  const err = [];
3467
3906
  const code = await main([...args, "--root", ctx.root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
@@ -3479,7 +3918,7 @@ function uiKnowRoutes(r, ctx, o = {}) {
3479
3918
  throw badRequest("Some fields aren't right.", {
3480
3919
  errors: b.error.issues.map((i) => ({ path: i.path.join("."), message: i.message }))
3481
3920
  });
3482
- const { triageDecide } = await import("./chunk-62FMA437.js");
3921
+ const { triageDecide } = await import("./chunk-RUNHVUCW.js");
3483
3922
  const out = [];
3484
3923
  const err = [];
3485
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) });
@@ -3606,7 +4045,7 @@ function refused3(r) {
3606
4045
  return r.code === 2 ? badRequest(detail) : new HttpError(422, "Atticus refused", detail);
3607
4046
  }
3608
4047
  function uiInitiativeRoutes(r, ctx) {
3609
- const commands = () => import("./chunk-NL6GIEJU.js");
4048
+ const commands = () => import("./chunk-J6GO3K7G.js");
3610
4049
  const changed = () => ctx.events.publish({ type: "file.changed", path: "catalog/curated" });
3611
4050
  return r.add("POST", "/api/initiatives", async ({ body }) => {
3612
4051
  const b = parseBody3(api_exports.NewInitiativeRequest, body);
@@ -3685,9 +4124,9 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3685
4124
  throw badRequest("role is product, architecture, analysis or delivery, or left out.");
3686
4125
  const onFile = await listQuestions(ctx.root);
3687
4126
  const every = { ...onFile, questions: onFile.questions.filter((q) => !q.finding) };
3688
- const { routeQuestions } = await import("./chunk-7FUQAT2R.js");
4127
+ const { routeQuestions } = await import("./chunk-OFYBRMRG.js");
3689
4128
  const routedAll = await routeQuestions(ctx.root, every.questions, mine ? { mine: ctx.user } : {});
3690
- const { stageQuestions, roleWithStage, isChangeQuestion, countByRole, personsRoles } = await import("./chunk-KW4DIXUL.js");
4129
+ const { stageQuestions, roleWithStage, isChangeQuestion, countByRole, personsRoles } = await import("./chunk-HDWVR5KD.js");
3691
4130
  const stages = await stageQuestions(ctx.root);
3692
4131
  const roleOf = (q) => roleWithStage(q, stages);
3693
4132
  for (const q of every.questions) {
@@ -3738,13 +4177,13 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3738
4177
  return { status: 200, body };
3739
4178
  };
3740
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 () => {
3741
- const { ownerQuestions } = await import("./chunk-GAVEIYKH.js");
4180
+ const { ownerQuestions } = await import("./chunk-IJHJIL6T.js");
3742
4181
  return { status: 200, body: await ownerQuestions(ctx.root, { now: now() }) };
3743
4182
  })).add("POST", "/api/owner-questions/{id}/answer", async ({ params, body }) => {
3744
4183
  const b = api_exports.OwnerAnswerRequest.safeParse(body ?? {});
3745
4184
  if (!b.success || !b.data.answer.trim())
3746
4185
  throw badRequest('Answer with { answer: "what the owner said" }.');
3747
- const { answerOwnerQuestion, OwnerQuestionError } = await import("./chunk-GAVEIYKH.js");
4186
+ const { answerOwnerQuestion, OwnerQuestionError } = await import("./chunk-IJHJIL6T.js");
3748
4187
  try {
3749
4188
  const r2 = await answerOwnerQuestion(ctx.root, params.id, b.data.answer, {
3750
4189
  by: ctx.user,
@@ -3769,13 +4208,13 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3769
4208
  throw notFound(`There is no question ${params.id}.`);
3770
4209
  if (q.askedBy.step !== TARGETS_STEP_ID && q.askedBy.step !== TOPICS_STEP_ID)
3771
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.`);
3772
- const { pickerOf } = await import("./chunk-Q6UYUCNS.js");
4211
+ const { pickerOf } = await import("./chunk-FSYJPYLE.js");
3773
4212
  return { status: 200, body: { picks: await pickerOf(ctx.root) } };
3774
4213
  }).add("GET", "/api/questions/{id}/evidence", async ({ params }) => {
3775
4214
  const q = await readQuestion(ctx.root, params.id).catch(() => void 0);
3776
4215
  if (!q)
3777
4216
  throw notFound(`There is no question ${params.id}.`);
3778
- const { evidenceExcerpts } = await import("./chunk-TVFADTAT.js");
4217
+ const { evidenceExcerpts } = await import("./chunk-S6TLXRBR.js");
3779
4218
  return {
3780
4219
  status: 200,
3781
4220
  body: {
@@ -3820,7 +4259,7 @@ function uiQuestionRoutes(r, ctx, deps = {}) {
3820
4259
  const q0 = await readQuestion(ctx.root, params.id).catch(() => void 0);
3821
4260
  if (!q0)
3822
4261
  throw notFound(`There is no question ${params.id}.`);
3823
- const { targetAnswerOf, offerLine } = await import("./chunk-Q6UYUCNS.js");
4262
+ const { targetAnswerOf, offerLine } = await import("./chunk-FSYJPYLE.js");
3824
4263
  const t = await targetAnswerOf(ctx.root, q0, target, {
3825
4264
  ...addSystem ? { addSystem } : {},
3826
4265
  ...name ? { name } : {}
@@ -3899,6 +4338,8 @@ async function acrossRows(root, view3) {
3899
4338
  const rows = [];
3900
4339
  const op = view3 === "requests" ? await loadOrgPack(orgPackDirOf(root)) : void 0;
3901
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);
3902
4343
  for (const c of changes) {
3903
4344
  const base = { change: c.id, changeTitle: c.title, changeState: c.state };
3904
4345
  const dir = changeFolder(root, c.id);
@@ -3975,12 +4416,15 @@ async function acrossRows(root, view3) {
3975
4416
  case "releases": {
3976
4417
  const rep = await changeReport(root, c.id);
3977
4418
  const h = liveHandoff(c);
4419
+ const said = await changeNextStep(root, c.id, rep, await nextState(), "page");
3978
4420
  rows.push({
3979
4421
  ...base,
3980
4422
  atRelease: AT_RELEASE.has(c.state),
3981
4423
  ...rep.phase ? { phase: rep.phase } : {},
3982
4424
  ...rep.next ? { next: rep.next } : {},
3983
- nextStep: rep.nextStep,
4425
+ nextStep: said.nextStep,
4426
+ ...said.nextStepApp ? { nextStepApp: said.nextStepApp } : {},
4427
+ ...said.stepFirst ? { stepFirst: true } : {},
3984
4428
  risk: rep.risk.level,
3985
4429
  blockers: rep.blockers.length,
3986
4430
  ...h ? { handoff: { phase: h.phase, pr: h.pr.url, state: h.state } } : {}
@@ -4448,7 +4892,7 @@ function uiSpecRoutes(r, ctx) {
4448
4892
  });
4449
4893
  r.add("GET", "/api/changes/{changeId}/conformance", async ({ params }) => {
4450
4894
  const change = idOf2(params.changeId, "change");
4451
- const { conformanceOf } = await import("./chunk-E7PR4WMM.js");
4895
+ const { conformanceOf } = await import("./chunk-LNJKDS5C.js");
4452
4896
  const c = await conformanceOf(root, change);
4453
4897
  if (!c)
4454
4898
  throw notFound(`There is no change ${change}.`);
@@ -4463,7 +4907,7 @@ function uiSpecRoutes(r, ctx) {
4463
4907
  });
4464
4908
  r.add("GET", "/api/changes/{changeId}/impact", async ({ params }) => {
4465
4909
  const change = idOf2(params.changeId, "change");
4466
- const { changeImpactOf } = await import("./chunk-JXLUHMTC.js");
4910
+ const { changeImpactOf } = await import("./chunk-SCP24MJX.js");
4467
4911
  const i = await changeImpactOf(root, change);
4468
4912
  if (!i)
4469
4913
  throw notFound(`There is no change ${change}.`);
@@ -4616,8 +5060,8 @@ function uiKnowledgeRoutes(r, ctx, deps = {}) {
4616
5060
  const slash = id.indexOf("/");
4617
5061
  return hash > 0 && slash > 0 && slash < hash ? { source: id.slice(0, slash), page: id.slice(slash + 1, hash) } : void 0;
4618
5062
  };
4619
- const { knowledgePages } = await import("./chunk-N6SSI6XO.js");
4620
- const { sectionOf } = await import("./chunk-7HW2CMIN.js");
5063
+ const { knowledgePages } = await import("./chunk-H25QNDKK.js");
5064
+ const { sectionOf } = await import("./chunk-GF6GBHFN.js");
4621
5065
  const pages = doc?.items.some((i) => i.id.includes("#")) ? await knowledgePages(root) : [];
4622
5066
  const records = doc?.items.length ? new Map((await readKnowledge(root, { cacheRoot: root })).items.map((r2) => [r2.id, r2])) : /* @__PURE__ */ new Map();
4623
5067
  const passageOf = (id) => {
@@ -4817,7 +5261,7 @@ function uiKnowledgeRoutes(r, ctx, deps = {}) {
4817
5261
  printToCurrent(l);
4818
5262
  }
4819
5263
  };
4820
- 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] });
4821
5265
  if (code === 2)
4822
5266
  throw new HttpError(422, "Atticus refused", c.problems.join("\n") || "Nothing to sync.");
4823
5267
  changed(`${knowledgeRelOf(root)}/snapshots/${id}`);
@@ -4908,7 +5352,7 @@ function uiKnowledgeRoutes(r, ctx, deps = {}) {
4908
5352
  if (source !== void 0)
4909
5353
  idOf3(source, "source");
4910
5354
  const ids = await snapshotSources(root);
4911
- const { inputsPassagePages, pastableArg } = await import("./chunk-N6SSI6XO.js");
5355
+ const { inputsPassagePages, pastableArg } = await import("./chunk-H25QNDKK.js");
4912
5356
  const live = !ids.includes(INPUTS_SOURCE_ID) && (!source || source === INPUTS_SOURCE_ID) ? await inputsPassagePages(root) : [];
4913
5357
  if (source && !ids.includes(source) && !(source === INPUTS_SOURCE_ID && live.length))
4914
5358
  throw notFound(`${source} has no snapshot yet: atticus sources sync --source ${source}.`);
@@ -5123,7 +5567,7 @@ async function configuredModel(root) {
5123
5567
  function uiModelRunRoutes(r, ctx, deps = {}) {
5124
5568
  const root = ctx.root;
5125
5569
  const runStep = deps.runStep ?? (async (args) => {
5126
- const { main } = await import("./chunk-XZQBFF65.js");
5570
+ const { main } = await import("./chunk-FS4E7F6O.js");
5127
5571
  const out = [];
5128
5572
  const err = [];
5129
5573
  const code = await main([...args, "--root", root], { out: (l) => out.push(l), err: (l) => err.push(l) }, { quiet: true });
@@ -5131,7 +5575,7 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5131
5575
  });
5132
5576
  return r.add("POST", "/api/runs/handoff", async ({ body }) => {
5133
5577
  const words = stepWords(body);
5134
- const { prepareStep } = await import("./chunk-U4HZ5CXL.js");
5578
+ const { prepareStep } = await import("./chunk-E7Q52EOO.js");
5135
5579
  const { code, prepared } = await prepareStep(root, runStep, words);
5136
5580
  ctx.events.publish({ type: "file.changed", path: runsRelOf(root) });
5137
5581
  if (!prepared.runId && code !== 0) {
@@ -5149,6 +5593,8 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5149
5593
  const busy = ctx.jobs.runningOf("step");
5150
5594
  if (busy)
5151
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-FS4E7F6O.js");
5597
+ const log = { command: commandTitleInputsOf([...words, "--mode", "model"]) };
5152
5598
  const job = ctx.jobs.start("step", async (c) => {
5153
5599
  c.progress(0, 1, `Running atticus ${words.join(" ")} with ${model}`);
5154
5600
  const before = new Set((await listRuns(root, { limit: 1e5 })).map((x) => x.runId));
@@ -5166,7 +5612,7 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5166
5612
  let applied;
5167
5613
  if (code === 0 && repo) {
5168
5614
  c.progress(0, 1, `Applying to ${repo}`);
5169
- 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] });
5170
5616
  raw.push(...v.out, ...v.err);
5171
5617
  errs.push(...v.err);
5172
5618
  code = v.code;
@@ -5188,7 +5634,7 @@ function uiModelRunRoutes(r, ctx, deps = {}) {
5188
5634
  },
5189
5635
  errors: code === 0 ? [] : errs.length ? appLines(errs) : []
5190
5636
  };
5191
- }, { title: `atticus ${words.join(" ")}` });
5637
+ }, { title: `atticus ${words.join(" ")}`, log });
5192
5638
  return { status: 202, body: { jobId: job.id, model } };
5193
5639
  }).add("GET", "/api/runs", async ({ query }) => {
5194
5640
  const change = query.get("change") ?? void 0;
@@ -5311,6 +5757,12 @@ var CopilotRun = class {
5311
5757
  delete v.progress.session;
5312
5758
  break;
5313
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
+ }
5314
5766
  case "verify":
5315
5767
  v.totals.kept += e.kept;
5316
5768
  v.totals.rejected += e.rejected;
@@ -5349,25 +5801,51 @@ var CopilotRun = class {
5349
5801
 
5350
5802
  // packages/cli/dist/ui-api-copilot-runs.js
5351
5803
  var defaultStarter = (root) => async (o, io, deps) => {
5352
- const { mapAllCommand } = await import("./chunk-FNP4M4VL.js");
5804
+ const { mapAllCommand } = await import("./chunk-6G67LSBG.js");
5353
5805
  return mapAllCommand(root, o, io, {
5354
5806
  ...deps,
5355
- makeAcp: async () => (await import("./chunk-EXGXCVWC.js")).acpStepRunner(root)
5807
+ makeAcp: async () => (await import("./chunk-IAVVJ34R.js")).acpStepRunner(root)
5356
5808
  });
5357
5809
  };
5358
5810
  var TAIL = 200;
5359
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.";
5360
- 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) {
5361
5817
  try {
5362
5818
  const op = await loadOrgPack(orgPackDirOf(root));
5363
5819
  const c = copilotAcpOf(op.runtime);
5364
- 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-6G67LSBG.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
+ };
5365
5841
  } catch {
5366
5842
  return { allowed: false };
5367
5843
  }
5368
5844
  }
5369
5845
  var optionsOf = (b) => ({
5370
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 } : {},
5371
5849
  ...b.kind === "stale" ? { stale: true } : {},
5372
5850
  ...b.kind === "gaps" ? { gaps: true } : {},
5373
5851
  ...b.repos?.length ? { repos: b.repos } : {},
@@ -5376,6 +5854,7 @@ var optionsOf = (b) => ({
5376
5854
  });
5377
5855
  function uiCopilotRunRoutes(r, ctx, deps = {}) {
5378
5856
  const start = deps.start ?? defaultStarter(ctx.root);
5857
+ const check = deps.assistantFiles ?? defaultCheck;
5379
5858
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
5380
5859
  const flushMs = deps.flushMs ?? 100;
5381
5860
  let run5;
@@ -5407,7 +5886,7 @@ function uiCopilotRunRoutes(r, ctx, deps = {}) {
5407
5886
  };
5408
5887
  return r.add("GET", "/api/copilot-runs/current", async ({ query }) => {
5409
5888
  if (!allowed || Date.now() - allowed.at > 1e4)
5410
- allowed = { at: Date.now(), v: await allowedHere(ctx.root) };
5889
+ allowed = { at: Date.now(), v: await allowedHere(ctx.root, check) };
5411
5890
  const a = allowed.v;
5412
5891
  const tail = Math.min(Math.max(Number(query.get("tail") ?? TAIL) || TAIL, 0), TAB_LINES);
5413
5892
  const view3 = run5 ? {
@@ -5423,7 +5902,9 @@ function uiCopilotRunRoutes(r, ctx, deps = {}) {
5423
5902
  run: view3,
5424
5903
  allowed: a.allowed,
5425
5904
  ...a.allowed ? {} : { why: NOT_ALLOWED },
5426
- ...a.model ? { model: a.model } : {}
5905
+ ...a.model ? { model: a.model } : {},
5906
+ ...a.limit ? { limit: a.limit } : {},
5907
+ ...a.assistantFiles ? { assistantFiles: a.assistantFiles } : {}
5427
5908
  }
5428
5909
  };
5429
5910
  }).add("POST", "/api/copilot-runs", async ({ body }) => {
@@ -5444,14 +5925,27 @@ function uiCopilotRunRoutes(r, ctx, deps = {}) {
5444
5925
  starting = true;
5445
5926
  let a;
5446
5927
  try {
5447
- a = await allowedHere(ctx.root);
5928
+ a = await allowedHere(ctx.root, check);
5448
5929
  } finally {
5449
5930
  starting = false;
5450
5931
  }
5932
+ allowed = { at: Date.now(), v: a };
5451
5933
  if (!a.allowed)
5452
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-6G67LSBG.js");
5940
+ throw new HttpError(409, "Assistant files edited by hand", assistantFilesEditedWords(a.assistantFiles.edited), { code: "assistant-files-edited", files: a.assistantFiles.edited });
5941
+ }
5453
5942
  if (ctx.jobs.runningOf("step")?.state === "running")
5454
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-6G67LSBG.js");
5946
+ await saveLastLimit(ctx.root, b.data.maxTokens, now().getTime());
5947
+ allowed = void 0;
5948
+ }
5455
5949
  const runId = `copilot-run-${now().getTime().toString(36)}-${randomBytes(3).toString("hex")}-${++seq}`;
5456
5950
  const me = new CopilotRun({
5457
5951
  runId,
@@ -5623,7 +6117,7 @@ function uiLinkMatchRoutes(r, ctx, deps = {}) {
5623
6117
  if (me && done.error)
5624
6118
  me.error = done.error;
5625
6119
  return done.state === "failed" ? { errors: [done.error ?? "The session ended without an answer."] } : { result: { state: done.state } };
5626
- }, { title: `Match ${from} with ${view3.toName}` });
6120
+ }, { title: `Match ${from} with ${view3.toName}`, log: { ids: [from] } });
5627
6121
  running.set(key, { jobId: job.id });
5628
6122
  const files = await readMatch(ctx.root, view3);
5629
6123
  return {
@@ -5676,7 +6170,7 @@ function uiDecisionRoutes(r, ctx, deps = {}) {
5676
6170
  ctx.events.publish({ type: "file.changed", path });
5677
6171
  return { status: 200, body: out };
5678
6172
  }).add("GET", "/api/propose-answers", async () => {
5679
- const { openDecideRun, PROPOSE_CHANGE } = await import("./chunk-O6DJMDBR.js");
6173
+ const { openDecideRun, PROPOSE_CHANGE } = await import("./chunk-X73WLHSN.js");
5680
6174
  const run5 = await openDecideRun(ctx.root, PROPOSE_CHANGE);
5681
6175
  const body = run5 ? {
5682
6176
  state: "waiting",
@@ -5690,7 +6184,7 @@ function uiDecisionRoutes(r, ctx, deps = {}) {
5690
6184
  const op = await loadOrgPack(orgPackDirOf(ctx.root));
5691
6185
  if (op.runtime.ai === "off")
5692
6186
  throw conflict("runtime.yaml turns AI off here (ai: off): answer the questions yourself.");
5693
- const { startProposeHandoff } = await import("./chunk-EXGXCVWC.js");
6187
+ const { startProposeHandoff } = await import("./chunk-IAVVJ34R.js");
5694
6188
  const h = await startProposeHandoff(ctx.root, { now: now() });
5695
6189
  const body = {
5696
6190
  state: "waiting",
@@ -5821,11 +6315,11 @@ git commit -m "${safeMessage(`${change}: drawn on the canvas`)}"`;
5821
6315
  }
5822
6316
 
5823
6317
  // packages/cli/dist/ui-api-owner.js
5824
- var REPO = /^[A-Za-z0-9._-]{1,200}$/;
6318
+ var REPO2 = /^[A-Za-z0-9._-]{1,200}$/;
5825
6319
  var TEAM = /^[a-z0-9][a-z0-9-]{0,62}$/;
5826
6320
  function uiOwnerRoutes(r, ctx) {
5827
6321
  const options = async (repo) => {
5828
- if (!REPO.test(repo))
6322
+ if (!REPO2.test(repo))
5829
6323
  throw badRequest(`${JSON.stringify(repo)} isn't a repo name.`);
5830
6324
  const op = await loadOrgPack(orgPackDirOf(ctx.root));
5831
6325
  const entry = estateRepos(op).find((x) => x.id === repo);
@@ -5923,7 +6417,7 @@ git commit -m "${safeMessage(`${repo}: ${[owner ? `owner ${owner}` : "", system
5923
6417
  // packages/cli/dist/ui-api-declared.js
5924
6418
  import { readFile as readFile8 } from "node:fs/promises";
5925
6419
  import { join as join11 } from "node:path";
5926
- var REPO2 = /^[A-Za-z0-9._-]{1,200}$/;
6420
+ var REPO3 = /^[A-Za-z0-9._-]{1,200}$/;
5927
6421
  var says = (c) => {
5928
6422
  const what = `${c.target.kind} ${c.target.value} (${c.target.file}:${c.target.line})`;
5929
6423
  if (c.action === "wrong")
@@ -6072,7 +6566,7 @@ git commit -m "${safeMessage(`profile: ${b.data.system}: a declaration undone`)}
6072
6566
  throw badRequest("Say repo=<repo> or system=<id>.");
6073
6567
  const items = [];
6074
6568
  if (repo) {
6075
- if (!REPO2.test(repo))
6569
+ if (!REPO3.test(repo))
6076
6570
  throw badRequest(`${JSON.stringify(repo)} isn't a repo name.`);
6077
6571
  const rel = `${factsRelOf(ctx.root)}/${repo}.corrections.jsonl`;
6078
6572
  const text = await readFile8(join11(factsDirOf(ctx.root), `${repo}.corrections.jsonl`), "utf8").catch(() => "");
@@ -6347,7 +6841,7 @@ function uiDocumentRoutes(r, ctx) {
6347
6841
  const root = ctx.root;
6348
6842
  const changed = (path) => ctx.events.publish({ type: "file.changed", path });
6349
6843
  return r.add("GET", "/api/knowledge/documents", async () => {
6350
- const { listDocuments } = await import("./chunk-W2W7YCFL.js");
6844
+ const { listDocuments } = await import("./chunk-AS4CTARY.js");
6351
6845
  return { status: 200, body: api_exports.DocumentList.parse(await listDocuments(root)) };
6352
6846
  }).add("POST", "/api/knowledge/documents", async ({ body }) => {
6353
6847
  const b = api_exports.AttachFileRequest.safeParse(body ?? {});
@@ -6356,7 +6850,7 @@ function uiDocumentRoutes(r, ctx) {
6356
6850
  const bytes = new Uint8Array(Buffer.from(b.data.content, "base64"));
6357
6851
  if (bytes.length > MAX_FILE)
6358
6852
  throw new HttpError(413, "The file is too large", "Add a file of 15 MB or less.");
6359
- const { addToInbox } = await import("./chunk-62FMA437.js");
6853
+ const { addToInbox } = await import("./chunk-RUNHVUCW.js");
6360
6854
  const res = await addToInbox(root, [{ name: b.data.name, bytes }]);
6361
6855
  if (!res.added.length)
6362
6856
  throw new HttpError(422, "Atticus can't add that", res.refused[0]?.why ?? "", {
@@ -6366,7 +6860,7 @@ function uiDocumentRoutes(r, ctx) {
6366
6860
  changed(a.path);
6367
6861
  return { status: 201, body: api_exports.AddDocumentResult.parse(res) };
6368
6862
  }, { maxBody: Math.ceil(MAX_FILE * 4 / 3) + 64 * 1024 }).add("POST", "/api/changes/{changeId}/inputs/{name}/promote", async ({ params }) => {
6369
- const { AttachError, promoteChangeInput } = await import("./chunk-NMBHFSJQ.js");
6863
+ const { AttachError, promoteChangeInput } = await import("./chunk-ALUHO7SE.js");
6370
6864
  try {
6371
6865
  const res = await promoteChangeInput(root, params.changeId, params.name);
6372
6866
  changed(res.path);
@@ -6383,13 +6877,13 @@ function uiDocumentRoutes(r, ctx) {
6383
6877
  function uiRepoRoutes(r, ctx) {
6384
6878
  const root = ctx.root;
6385
6879
  return r.add("GET", "/api/repos/branches", async () => {
6386
- const { repoBranches } = await import("./chunk-IP6TSICI.js");
6880
+ const { repoBranches } = await import("./chunk-WC6DHBVG.js");
6387
6881
  return { status: 200, body: api_exports.RepoBranchesList.parse(await repoBranches(root)) };
6388
6882
  }).add("GET", "/api/repos/compare", async ({ query }) => {
6389
6883
  const branch = query.get("branch")?.trim() ?? "";
6390
6884
  if (!branch)
6391
6885
  throw badRequest("Say which branch: ?branch=<name>.");
6392
- const { compareBranch } = await import("./chunk-IP6TSICI.js");
6886
+ const { compareBranch } = await import("./chunk-WC6DHBVG.js");
6393
6887
  const c = await compareBranch(root, branch);
6394
6888
  if (!c)
6395
6889
  throw notFound(`${branch} hasn't been scanned beside the baseline yet.`);
@@ -6398,7 +6892,7 @@ function uiRepoRoutes(r, ctx) {
6398
6892
  const b = api_exports.EditRepoBranchesRequest.safeParse(body ?? {});
6399
6893
  if (!b.success)
6400
6894
  throw badRequest("Send defaultBranch and branches as branch names.");
6401
- const { editRepoBranches, RepoEditError } = await import("./chunk-IP6TSICI.js");
6895
+ const { editRepoBranches, RepoEditError } = await import("./chunk-WC6DHBVG.js");
6402
6896
  try {
6403
6897
  const file = await editRepoBranches(root, params.repoId, b.data);
6404
6898
  ctx.events.publish({ type: "file.changed", path: file });
@@ -6418,7 +6912,7 @@ function uiRepoRoutes(r, ctx) {
6418
6912
  const b = api_exports.EditRepoBuildRequest.safeParse(body ?? {});
6419
6913
  if (!b.success)
6420
6914
  throw badRequest('Send the build command as build ("" clears it), up to 500 characters.');
6421
- const { editRepoBuild, RepoEditError } = await import("./chunk-IP6TSICI.js");
6915
+ const { editRepoBuild, RepoEditError } = await import("./chunk-WC6DHBVG.js");
6422
6916
  try {
6423
6917
  const r2 = await editRepoBuild(root, params.repoId, b.data);
6424
6918
  ctx.events.publish({ type: "file.changed", path: r2.file });
@@ -6439,7 +6933,7 @@ function uiRepoRoutes(r, ctx) {
6439
6933
  const b = api_exports.SetOrgPackOwnerRequest.safeParse(body ?? {});
6440
6934
  if (!b.success)
6441
6935
  throw badRequest("Send the owner as one handle: { owner }.");
6442
- const { setOrgPackOwner, OwnerEditError } = await import("./chunk-5K6ZKHZR.js");
6936
+ const { setOrgPackOwner, OwnerEditError } = await import("./chunk-RZYRUXSU.js");
6443
6937
  try {
6444
6938
  const r2 = await setOrgPackOwner(root, b.data.owner, b.data.was);
6445
6939
  ctx.events.publish({ type: "file.changed", path: r2.file });
@@ -6460,7 +6954,7 @@ function uiRepoRoutes(r, ctx) {
6460
6954
  const b = api_exports.EditRepoDescriptionRequest.safeParse(body ?? {});
6461
6955
  if (!b.success)
6462
6956
  throw badRequest("Send what the repo is as text, or accept: true to confirm the draft, or reject: true to drop it.");
6463
- const { editRepoDescription, RepoEditError } = await import("./chunk-IP6TSICI.js");
6957
+ const { editRepoDescription, RepoEditError } = await import("./chunk-WC6DHBVG.js");
6464
6958
  try {
6465
6959
  const r2 = await editRepoDescription(root, params.repoId, b.data);
6466
6960
  ctx.events.publish({ type: "file.changed", path: r2.file });
@@ -6489,19 +6983,21 @@ function changeIdOf(v) {
6489
6983
  function uiCockpitRoutes(r, ctx) {
6490
6984
  return r.add("GET", "/api/changes/{changeId}/cockpit", async ({ params }) => {
6491
6985
  const id = changeIdOf(params.changeId);
6492
- const { cockpit } = await import("./chunk-B2U4AOZ5.js");
6986
+ const { cockpit } = await import("./chunk-WTOVWEY3.js");
6493
6987
  try {
6494
6988
  return await keptAnswer(ctx.root, `cockpit:${id}:${ctx.user}`, async () => ({
6495
6989
  status: 200,
6496
6990
  body: api_exports.ChangeCockpit.parse(await cockpit(ctx.root, id, { user: ctx.user }))
6497
6991
  }), () => checkoutsStamp(ctx.root));
6498
6992
  } catch (e) {
6499
- if (e instanceof Error && e.name === "ChangeFileError")
6500
- throw notFound(`There is no change ${params.changeId}.`);
6993
+ if (e instanceof Error && e.name === "ChangeFileError") {
6994
+ const { missingChangeWords: missingChangeWords2 } = await import("./chunk-UDTO3U6E.js");
6995
+ throw notFound(await missingChangeWords2(ctx.root, id));
6996
+ }
6501
6997
  throw e;
6502
6998
  }
6503
6999
  }).add("GET", "/api/past-changes", async ({ query }) => {
6504
- const { changeAboutText, similarChanges } = await import("./chunk-MJOIMGS4.js");
7000
+ const { changeAboutText, similarChanges } = await import("./chunk-EYVYHYCA.js");
6505
7001
  const given = query.get("change");
6506
7002
  const change = given ? changeIdOf(given) : void 0;
6507
7003
  const text = change ? await changeAboutText(ctx.root, change) : query.get("text")?.trim();
@@ -6520,11 +7016,11 @@ function uiCockpitRoutes(r, ctx) {
6520
7016
  const b = api_exports.AttachPastChangeRequest.safeParse(body ?? {});
6521
7017
  if (!b.success)
6522
7018
  throw badRequest("Say which archived change: { like: <its folder or id> }.");
6523
- const { attachPastChange, findPastChange } = await import("./chunk-MJOIMGS4.js");
7019
+ const { attachPastChange, findPastChange } = await import("./chunk-EYVYHYCA.js");
6524
7020
  const folder = await findPastChange(ctx.root, b.data.like);
6525
7021
  if (!folder)
6526
7022
  throw notFound(`There is no archived change ${b.data.like}.`);
6527
- const { AttachError } = await import("./chunk-NMBHFSJQ.js");
7023
+ const { AttachError } = await import("./chunk-ALUHO7SE.js");
6528
7024
  try {
6529
7025
  const name = await attachPastChange(ctx.root, params.changeId, folder, ctx.user);
6530
7026
  ctx.events.publish({ type: "file.changed", path: `inputs/${name}` });
@@ -6541,9 +7037,9 @@ function uiCockpitRoutes(r, ctx) {
6541
7037
  }
6542
7038
 
6543
7039
  // packages/cli/dist/ui-api-audit.js
6544
- var REPO3 = /^[a-z0-9][a-z0-9._-]{0,99}$/i;
7040
+ var REPO4 = /^[a-z0-9][a-z0-9._-]{0,99}$/i;
6545
7041
  var repoOf = (v) => {
6546
- if (!REPO3.test(v))
7042
+ if (!REPO4.test(v))
6547
7043
  throw badRequest(`${JSON.stringify(v)} isn't a repo name.`);
6548
7044
  return v;
6549
7045
  };
@@ -6654,6 +7150,8 @@ var OUTSIDE_ADD_SPEC = (id) => [
6654
7150
  "atticus intake list",
6655
7151
  "atticus triage"
6656
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.`;
6657
7155
  async function outsideView(root) {
6658
7156
  const quiet = { out: () => void 0, err: () => void 0 };
6659
7157
  const { op, records, inputs } = await intakeContext(root, quiet);
@@ -6704,8 +7202,22 @@ async function outsideView(root) {
6704
7202
  repos,
6705
7203
  vendors,
6706
7204
  targets: estate.targets,
6707
- ...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
6708
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 })));
6709
7221
  const contracts = await contractCheckOf(root).catch(() => void 0);
6710
7222
  const catalog = records.length ? records : (await readCatalog(join13(catalogDirOf(root), "generated"), { cacheRoot: root })).records;
6711
7223
  const ifaces = catalog.filter((r) => r.kind === "Interface");
@@ -6768,18 +7280,20 @@ async function outsideView(root) {
6768
7280
  }
6769
7281
  for (const g of [...matched.gaps, ...matched.asks].filter((x) => x.vendor === s.id))
6770
7282
  add(callOf(g.call), "spec");
7283
+ const once = /* @__PURE__ */ new Set();
6771
7284
  for (const m of matched.matches.filter((x) => x.vendor === s.id)) {
6772
- 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");
6773
7291
  if (m.direct || !m.route)
6774
7292
  continue;
6775
7293
  const route = m.route;
6776
7294
  for (const j of joined.joins)
6777
7295
  if (j.entry.repo === route.repo && j.entry.fact === route.fact)
6778
- add({
6779
- ...callOf(j.call),
6780
- operation: m.operation,
6781
- through: { repo: route.repo, at: route.at }
6782
- }, "spec");
7296
+ add({ ...callOf(j.call), ...ops, through: { repo: route.repo, at: route.at } }, "spec");
6783
7297
  }
6784
7298
  for (const m of sharedJoin.matches.filter((x) => x.system === s.id))
6785
7299
  add({
@@ -6794,6 +7308,11 @@ async function outsideView(root) {
6794
7308
  const lines = new Set(list.map((c) => `${c.repo}|${c.at}`));
6795
7309
  const named = [s.id, s.name, ...s.aliases].map((n) => n.toLowerCase());
6796
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
+ ];
6797
7316
  return {
6798
7317
  id: s.id,
6799
7318
  name: s.name,
@@ -6811,13 +7330,14 @@ async function outsideView(root) {
6811
7330
  method: o.method,
6812
7331
  path: o.fullPath,
6813
7332
  cite: o.cite,
6814
- calls: list.filter((c) => c.operation === o.id).length
7333
+ calls: list.filter((c) => c.operation === o.id || !!c.operations?.includes(o.id)).length
6815
7334
  }))
6816
7335
  }
6817
7336
  } : {},
6818
7337
  unmatched: matched.gaps.filter((g) => g.vendor === s.id).map((g) => ({ ...callOf(g.call), seen: ["spec"], message: g.message })),
6819
7338
  ambiguous: matched.asks.filter((a) => a.vendor === s.id).map((a) => ({ ...callOf(a.call), seen: ["spec"], candidates: a.candidates })),
6820
7339
  questions,
7340
+ ...notes.length ? { notes } : {},
6821
7341
  ...spec ? {} : { addSpec: OUTSIDE_ADD_SPEC(s.id) },
6822
7342
  ...contractsOf(s.id),
6823
7343
  ...map ? {
@@ -7492,11 +8012,19 @@ async function stageThreadView(root, change, stage) {
7492
8012
  items.sort((a, b) => a.at < b.at ? -1 : a.at > b.at ? 1 : 0);
7493
8013
  if (waiting)
7494
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
+ }
7495
8023
  const open = items.filter((i) => i.kind === "finding" && i.view.finding.state === "open").length;
7496
8024
  const questions = items.filter((i) => i.kind === "question" && i.question.state === "open").length;
7497
8025
  const dropped = items.filter((i) => i.kind === "dropped").length;
7498
8026
  const waitingWho = waiting ? runs.find((s) => s.run.runId === waiting.runId && isLens(agentOf2(s))) ? "critic" : "drafter" : void 0;
7499
- 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.";
7500
8028
  if (dropped)
7501
8029
  items.push({
7502
8030
  kind: "note",
@@ -7511,6 +8039,7 @@ async function stageThreadView(root, change, stage) {
7511
8039
  items,
7512
8040
  ...waiting ? { waiting } : {},
7513
8041
  step: stageStep(stage, change),
8042
+ ...byPerson.length ? { byPerson } : {},
7514
8043
  reply: { open: replyOpen, ...replyWhy ? { why: replyWhy } : {} },
7515
8044
  problems
7516
8045
  };
@@ -7527,7 +8056,7 @@ function uiThreadRoutes(r, ctx, deps = {}) {
7527
8056
  if (!ID7.test(v))
7528
8057
  throw badRequest(`${JSON.stringify(v)} isn't a change id.`);
7529
8058
  if (!await stat8(join16(changeFolder(ctx.root, v), "change.yaml")).catch(() => void 0))
7530
- throw notFound(`There is no change ${v}.`);
8059
+ throw notFound(await missingChangeWords(ctx.root, v));
7531
8060
  return v;
7532
8061
  };
7533
8062
  const refused4 = (e) => {
@@ -7719,7 +8248,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7719
8248
  };
7720
8249
  return r.add("GET", "/api/setup/metarepo", async () => {
7721
8250
  const origin = await originOf(root);
7722
- const { metarepoIdFromUrl } = await import("./chunk-NPZ4KXIV.js");
8251
+ const { metarepoIdFromUrl } = await import("./chunk-XMIS25ZJ.js");
7723
8252
  const folder = basename2(root);
7724
8253
  const body = {
7725
8254
  metarepo: isMetarepo(root),
@@ -7737,7 +8266,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7737
8266
  const b = parseBody4(api_exports.CreateMetarepoRequest, body);
7738
8267
  if (isMetarepo(root))
7739
8268
  throw conflict(`${root} is a metarepo already.`);
7740
- const { initCommand } = await import("./chunk-5P4PNGPL.js");
8269
+ const { initCommand } = await import("./chunk-XLTT5QCX.js");
7741
8270
  const res = await run4((io) => initCommand(root, {
7742
8271
  name: b.name,
7743
8272
  platform: b.platform,
@@ -7762,10 +8291,11 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7762
8291
  if (!await stat9(dir).then((s) => s.isDirectory(), () => false))
7763
8292
  throw notFound(`There is no folder ${dir} on this machine.`);
7764
8293
  const open = deps.openFolder ?? (async (d) => {
7765
- const { startUi: startUi2 } = await import("./chunk-UR6JGVX2.js");
8294
+ const { startUi: startUi2 } = await import("./chunk-JTOLBS7R.js");
7766
8295
  const srv = await startUi2(d, {
7767
8296
  port: 0,
7768
8297
  user,
8298
+ runLog: true,
7769
8299
  ...ctx.version ? { version: ctx.version } : {}
7770
8300
  });
7771
8301
  ctx.onClose?.add(() => void srv.close());
@@ -7794,7 +8324,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7794
8324
  };
7795
8325
  return { status: 200, body: ask };
7796
8326
  }
7797
- const { reposDiscover, AdoptError } = await import("./chunk-NPZ4KXIV.js");
8327
+ const { reposDiscover, AdoptError } = await import("./chunk-XMIS25ZJ.js");
7798
8328
  const found = await reposDiscover(root, { dir }, { dryRun: true, ...b.platform ? { platform: b.platform } : {} }).catch((e) => {
7799
8329
  if (e instanceof AdoptError)
7800
8330
  throw unprocessable2(e.message.replace(/ with --platform\b/g, " (choose the platform)"));
@@ -7811,7 +8341,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7811
8341
  detected: { signals: f.detection.signals, confidence: f.detection.confidence }
7812
8342
  }));
7813
8343
  } else {
7814
- const { cloneAt, typeOf } = await import("./chunk-EUCATH2U.js");
8344
+ const { cloneAt, typeOf } = await import("./chunk-F74OMLNU.js");
7815
8345
  for (const given of pastedUrls(b.urls ?? "").slice(0, 500)) {
7816
8346
  const c = candidateOf(given);
7817
8347
  const clone = await cloneAt(c.url);
@@ -7882,13 +8412,13 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7882
8412
  const id = params.repoId;
7883
8413
  if (!(await loadRepos(root).catch(() => [])).some((x) => x.id === id))
7884
8414
  throw notFound(`There is no repo ${id} in any manifest.`);
7885
- const { repoFor } = await import("./chunk-BIQNPWGX.js");
8415
+ const { repoFor } = await import("./chunk-ZIAMPN7N.js");
7886
8416
  const repo = await repoFor(root, id);
7887
8417
  if (!repo)
7888
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).`);
7889
8419
  const op = await loadOrgPack(orgPackDirOf(root));
7890
8420
  if (op.repoTypes.length) {
7891
- const { repoTypeDetect } = await import("./chunk-HD72AL3L.js");
8421
+ const { repoTypeDetect } = await import("./chunk-3GURU22K.js");
7892
8422
  const res = await run4((io) => repoTypeDetect(root, id, { json: true }, io));
7893
8423
  if (res.code !== 0)
7894
8424
  throw unprocessable2([...res.err, ...res.out].join("\n"));
@@ -7902,7 +8432,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
7902
8432
  };
7903
8433
  return { status: 200, body: body2 };
7904
8434
  }
7905
- const { typeOf } = await import("./chunk-EUCATH2U.js");
8435
+ const { typeOf } = await import("./chunk-F74OMLNU.js");
7906
8436
  const t = await typeOf(repo.dir, void 0);
7907
8437
  const body = {
7908
8438
  repo: id,
@@ -8043,7 +8573,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
8043
8573
  const b = parseBody4(api_exports.SourceRequest, body);
8044
8574
  const file = join17(orgPackDirOf(root), "sources.yaml");
8045
8575
  const before = await readFile13(file, "utf8").catch(() => "");
8046
- const { sourcesAdd: sourcesAdd2 } = await import("./chunk-K3OIBTCV.js");
8576
+ const { sourcesAdd: sourcesAdd2 } = await import("./chunk-BABATPOZ.js");
8047
8577
  const res = await run4((io) => sourcesAdd2(root, b.type, b.location.trim(), io, {
8048
8578
  ...b.id ? { id: b.id } : {},
8049
8579
  ...b.path ? { path: b.path } : {},
@@ -8066,7 +8596,7 @@ function uiSetupRoutes(r, ctx, deps = {}) {
8066
8596
  };
8067
8597
  }
8068
8598
  const after = await readFile13(file, "utf8").catch(() => "");
8069
- const { changedLines: changedLines2, lfOnly: lfOnly2 } = await import("./chunk-WDJGJ3HV.js");
8599
+ const { changedLines: changedLines2, lfOnly: lfOnly2 } = await import("./chunk-PPKH6ULR.js");
8070
8600
  changed(path);
8071
8601
  return {
8072
8602
  status: 200,
@@ -8090,8 +8620,9 @@ function changeIdOf2(v) {
8090
8620
  function uiRolesRoutes(r, ctx, deps = {}) {
8091
8621
  const root = ctx.root;
8092
8622
  const now = deps.now ?? (() => /* @__PURE__ */ new Date());
8623
+ const sending = /* @__PURE__ */ new Set();
8093
8624
  ctx.askKnowledge = async (q) => {
8094
- const { knowledgeAnswerOf } = await import("./chunk-N6SSI6XO.js");
8625
+ const { knowledgeAnswerOf } = await import("./chunk-H25QNDKK.js");
8095
8626
  return api_exports.KnowledgeAnswerView.parse(await knowledgeAnswerOf(root, q));
8096
8627
  };
8097
8628
  const exists4 = async (id) => {
@@ -8152,7 +8683,7 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8152
8683
  const id = changeIdOf2(params.changeId);
8153
8684
  if (!await exists4(id))
8154
8685
  throw notFound(`There is no change ${id}.`);
8155
- const { ownerSuggestions } = await import("./chunk-N6SSI6XO.js");
8686
+ const { ownerSuggestions } = await import("./chunk-H25QNDKK.js");
8156
8687
  return {
8157
8688
  status: 200,
8158
8689
  body: api_exports.OwnerSuggestionList.parse(await ownerSuggestions(root, id))
@@ -8209,7 +8740,9 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8209
8740
  throw new HttpError(422, "Atticus refused", e.message);
8210
8741
  });
8211
8742
  if (b.data.job)
8212
- 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
+ });
8213
8746
  return { status: 200, body: await answer() };
8214
8747
  }).add("GET", "/api/changes/{changeId}/stories/shape", async ({ params }) => {
8215
8748
  const id = changeIdOf2(params.changeId);
@@ -8262,13 +8795,13 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8262
8795
  const b = api_exports.SendOwnerAskRequest.safeParse(body ?? {});
8263
8796
  if (!b.success)
8264
8797
  throw badRequest("Send { confirmation? }.");
8265
- const { ownerQuestions } = await import("./chunk-GAVEIYKH.js");
8798
+ const { ownerQuestions } = await import("./chunk-IJHJIL6T.js");
8266
8799
  const list = await ownerQuestions(root, { now: now() });
8267
8800
  const q = list.questions.find((x) => x.id === params.id);
8268
8801
  if (!q)
8269
8802
  throw notFound(`There is no owner question ${params.id}.`);
8270
- const { notifierFor } = await import("./chunk-N6SSI6XO.js");
8271
- const n = await notifierFor(root, q.finding?.change, deps.notify);
8803
+ const { fallbackWords, notifierFor } = await import("./chunk-H25QNDKK.js");
8804
+ const n = await notifierFor(root, q.finding?.change, deps.notify, deps.adapterFactories ? { factories: deps.adapterFactories } : {});
8272
8805
  const to = q.owner;
8273
8806
  if (!n.notify || n.kind === "none")
8274
8807
  return {
@@ -8279,50 +8812,81 @@ function uiRolesRoutes(r, ctx, deps = {}) {
8279
8812
  why: "No notifications are set up here (runtime.yaml adapters.notify): copy the question and ask the owner, then record what they said."
8280
8813
  })
8281
8814
  };
8282
- if (n.kind === "live")
8283
- requireConfirmation(ctx.confirmations, "owner-ask", q.id, b.data.confirmation);
8284
- const team = (await readTeams(root)).teams.find((t) => t.id === to);
8285
- const mentions = team ? team.people.map((p) => p.replace(/^@/, "")) : [to.replace(/^@/, "")];
8286
- const channel = q.channel && q.channel !== "Atticus" ? q.channel : `@${to.replace(/^@/, "")}`;
8815
+ const { ownerAskRef, recordedSendAt, recordOwnerSend } = await import("./chunk-IJHJIL6T.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);
8287
8819
  try {
8288
- const sent = await n.notify.send({
8289
- channel,
8290
- title: `A question for ${team?.name ?? to}`,
8291
- 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}
8292
8837
 
8293
8838
  What it is for: ${q.neededFact}
8294
8839
 
8295
8840
  Answer it in Atticus (Questions \u203A Owner questions), or reply to ${ctx.user}.`,
8296
- mentions
8297
- }, { by: ctx.user.replace(/^@/, ""), at: stamp2(now()), ref: `owner-ask:${q.id}` });
8298
- return {
8299
- status: 200,
8300
- body: api_exports.SentOwnerAsk.parse({
8301
- state: n.kind === "manual" ? "step" : "sent",
8302
- to,
8303
- id: sent.id,
8304
- ...n.kind === "manual" ? {
8305
- why: "Notifications are manual here: sending it is a step for you (Home \u203A Manual steps)."
8306
- } : {}
8307
- })
8308
- };
8309
- } catch (e) {
8310
- if (e instanceof HttpError)
8311
- 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 });
8312
8878
  return {
8313
8879
  status: 200,
8314
- body: api_exports.SentOwnerAsk.parse({
8315
- state: "not-sent",
8316
- to,
8317
- why: `The notify adapter refused: ${e.message}`
8318
- })
8880
+ body: api_exports.SentOwnerAsk.parse({ state: "sent", to, id: sent.id })
8319
8881
  };
8882
+ } finally {
8883
+ sending.delete(q.id);
8320
8884
  }
8321
8885
  }).add("GET", "/api/knowledge/passage", async ({ query }) => {
8322
8886
  const id = strParam(query, "id")?.trim();
8323
8887
  if (!id || id.length > 400 || /[\p{Cc}]/u.test(id))
8324
8888
  throw badRequest("Say which section: ?id=<source>/<page>#<heading>.");
8325
- const { passageOf } = await import("./chunk-N6SSI6XO.js");
8889
+ const { passageOf } = await import("./chunk-H25QNDKK.js");
8326
8890
  const p = await passageOf(root, id);
8327
8891
  if (!p)
8328
8892
  throw notFound(`No page or section ${id} is in a snapshot or in inputs/.`);
@@ -8348,9 +8912,34 @@ function extendUiRoutes(r, ctx, deps = {}, o = {}) {
8348
8912
  return uiRolesRoutes(uiSetupRoutes(uiThreadRoutes(uiActivityRoutes(uiDecisionRoutes(all, ctx), ctx), ctx), ctx, deps.openFolder ? { openFolder: deps.openFolder } : {}), ctx, {
8349
8913
  ...deps.notify ? { notify: deps.notify } : {},
8350
8914
  ...deps.workTracker ? { workTracker: deps.workTracker } : {},
8915
+ ...deps.adapterFactories ? { adapterFactories: deps.adapterFactories } : {},
8351
8916
  ...deps.now ? { now: () => new Date(deps.now) } : {}
8352
8917
  });
8353
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
+ }
8354
8943
  async function startUi(root, o = {}, deps = {}) {
8355
8944
  const srv = await startServer({
8356
8945
  root,
@@ -8359,25 +8948,11 @@ async function startUi(root, o = {}, deps = {}) {
8359
8948
  ...o.full ? { full: true } : {},
8360
8949
  ...o.token ? { token: o.token } : {},
8361
8950
  ...o.pageKey ? { pageKey: o.pageKey } : {},
8951
+ ...o.runLog ? { runLog: true } : {},
8362
8952
  staticDir: o.staticDir ?? uiDistDir(),
8363
8953
  ...o.user ? { user: o.user } : {},
8364
8954
  ...o.version ? { version: o.version } : {},
8365
- onRequest: (() => {
8366
- const log = createLog(root);
8367
- return (r) => {
8368
- if (r.method !== "GET" && r.method !== "HEAD") {
8369
- answersMayHaveChanged();
8370
- keptFilesMayHaveChanged();
8371
- }
8372
- const fields = { method: r.method, path: r.path, status: r.status, ms: r.ms };
8373
- if (r.error)
8374
- log.error("request", r.error, fields);
8375
- else if (r.status >= 500)
8376
- log.warn("request", fields);
8377
- else
8378
- log.debug("request", fields);
8379
- };
8380
- })(),
8955
+ onRequest: uiRequestLogger(root),
8381
8956
  extend: (r, ctx) => extendUiRoutes(r, ctx, deps, { warm: o.warm === true })
8382
8957
  });
8383
8958
  keepCatalogsInMemory(true);
@@ -8437,8 +9012,8 @@ function untilStopped(embedded, stdin = process.stdin, o = {}) {
8437
9012
  const stop = () => {
8438
9013
  if (watch)
8439
9014
  clearInterval(watch);
8440
- process.off("SIGINT", stop);
8441
- process.off("SIGTERM", stop);
9015
+ offInt();
9016
+ offTerm();
8442
9017
  if (embedded) {
8443
9018
  stdin.off("end", stop);
8444
9019
  stdin.off("close", stop);
@@ -8446,8 +9021,8 @@ function untilStopped(embedded, stdin = process.stdin, o = {}) {
8446
9021
  }
8447
9022
  resolve3();
8448
9023
  };
8449
- process.once("SIGINT", stop);
8450
- process.once("SIGTERM", stop);
9024
+ const offInt = onAtticusSignal("SIGINT", stop, { once: true });
9025
+ const offTerm = onAtticusSignal("SIGTERM", stop, { once: true });
8451
9026
  if (embedded) {
8452
9027
  stdin.once("end", stop);
8453
9028
  stdin.once("close", stop);
@@ -8477,6 +9052,8 @@ async function uiCommand(root, o, io) {
8477
9052
  ...given ? { token: given } : {},
8478
9053
  ...pageKey ? { pageKey } : {},
8479
9054
  warm: true,
9055
+ // Beta.27 review: the jobs it starts are kept in the run log, for after a restart.
9056
+ runLog: true,
8480
9057
  ...o.full ? { full: true } : {},
8481
9058
  ...o.port !== void 0 ? { port: o.port } : {},
8482
9059
  ...o.user ? { user: o.user } : {},
@@ -8508,5 +9085,6 @@ export {
8508
9085
  startUi,
8509
9086
  startedLines,
8510
9087
  uiCommand,
9088
+ uiRequestLogger,
8511
9089
  untilStopped
8512
9090
  };