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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/dist/bin.js +8 -4
  2. package/dist/chunk-23XVSEV5.js +49 -0
  3. package/dist/{chunk-ZDPAS56H.js → chunk-24OXGB3P.js} +8 -2
  4. package/dist/{chunk-7EOBHUMC.js → chunk-24XLDU72.js} +4 -3
  5. package/dist/{chunk-CR3MTH32.js → chunk-2F4CYZKJ.js} +86 -11
  6. package/dist/{chunk-6IU67AEK.js → chunk-2GF7OLF3.js} +23 -15
  7. package/dist/chunk-2IIMFOPM.js +41 -0
  8. package/dist/chunk-2LGRMVCA.js +617 -0
  9. package/dist/{chunk-XPCM366L.js → chunk-2MMCFP5C.js} +10 -8
  10. package/dist/{chunk-JBTK5OP2.js → chunk-2Q56PQPS.js} +6 -4
  11. package/dist/{chunk-Z6LF7HQN.js → chunk-2Q5EDGEO.js} +7 -5
  12. package/dist/{chunk-3USYZGRF.js → chunk-2RLKFUUL.js} +38 -27
  13. package/dist/chunk-2SKB4O2E.js +59 -0
  14. package/dist/{chunk-SP2I63OO.js → chunk-34S2WGOB.js} +87 -4
  15. package/dist/{chunk-GQ4N4WKF.js → chunk-3NFFJL5D.js} +33 -27
  16. package/dist/{chunk-SJRGMG6A.js → chunk-3NWDLGG6.js} +28 -25
  17. package/dist/{chunk-4WBVUHXN.js → chunk-3RM4UK6W.js} +20 -18
  18. package/dist/chunk-42SIDKEU.js +583 -0
  19. package/dist/{chunk-GLUX4EEP.js → chunk-4EURQWQD.js} +20 -15
  20. package/dist/chunk-4U276ICE.js +39 -0
  21. package/dist/{chunk-ZMFPW66A.js → chunk-53T4O55J.js} +4 -3
  22. package/dist/{chunk-6J5OKA4Y.js → chunk-57TDNMI3.js} +17 -15
  23. package/dist/chunk-5BD2KYLE.js +57 -0
  24. package/dist/{chunk-7EFILTCI.js → chunk-5F7GFN2F.js} +28 -0
  25. package/dist/chunk-5NMKONLP.js +95 -0
  26. package/dist/{chunk-7ZUIMTOU.js → chunk-5SJZW52K.js} +26 -24
  27. package/dist/{chunk-4RS5KZQD.js → chunk-63YRMR6J.js} +6 -5
  28. package/dist/chunk-66PPNOON.js +62 -0
  29. package/dist/chunk-6H3Z5JHH.js +64 -0
  30. package/dist/{chunk-CEXSU4S6.js → chunk-6MUGR4LS.js} +775 -89
  31. package/dist/{chunk-QSXK2RGH.js → chunk-6OJQOPUN.js} +5 -3
  32. package/dist/{chunk-MVZVGYXH.js → chunk-6PPOWY5E.js} +84 -14
  33. package/dist/{chunk-7EKXJZ2Y.js → chunk-6ZGLAACW.js} +299 -38
  34. package/dist/chunk-6ZJ5A7AF.js +222 -0
  35. package/dist/{chunk-L24C55VN.js → chunk-745DAZ4L.js} +142 -30
  36. package/dist/{chunk-Q4D5X7QB.js → chunk-7ASNL4Q4.js} +46 -24
  37. package/dist/chunk-7BR7IPOH.js +35 -0
  38. package/dist/{chunk-7WD63HU2.js → chunk-7DOR27HL.js} +6 -6
  39. package/dist/chunk-7FTTA3HD.js +341 -0
  40. package/dist/{chunk-OLQJTJJU.js → chunk-7GJS6DNX.js} +12 -3
  41. package/dist/{chunk-7JUKDRSZ.js → chunk-7IGKHZ4Z.js} +347 -226
  42. package/dist/{chunk-G2B4ZQGH.js → chunk-7IOWA5D5.js} +11 -6
  43. package/dist/{chunk-EBEW3XXQ.js → chunk-7JITZFJC.js} +7 -5
  44. package/dist/chunk-7MJSQTL5.js +174 -0
  45. package/dist/{chunk-I4JRCD6M.js → chunk-7UOMVMFG.js} +25 -17
  46. package/dist/{chunk-YY6ZQQBP.js → chunk-AFWUDXEM.js} +19 -7
  47. package/dist/chunk-AFZ3QA6W.js +47 -0
  48. package/dist/chunk-AJQ72EBM.js +420 -0
  49. package/dist/chunk-AJYXNTNZ.js +317 -0
  50. package/dist/chunk-AVTBS4OW.js +49 -0
  51. package/dist/{chunk-FHH4I4ZV.js → chunk-BDKC6H5P.js} +12 -6
  52. package/dist/{chunk-IPKHE5D6.js → chunk-BEVTIBRH.js} +1526 -875
  53. package/dist/chunk-BHT7QK4G.js +162 -0
  54. package/dist/{chunk-6JUBZBMW.js → chunk-BIGDQDHD.js} +6 -4
  55. package/dist/{chunk-2BFCZ3RK.js → chunk-BO4KX37X.js} +20 -18
  56. package/dist/chunk-BPK5P77O.js +115 -0
  57. package/dist/chunk-BQ4SQQC6.js +59 -0
  58. package/dist/chunk-BQGDB6ZL.js +7342 -0
  59. package/dist/{chunk-2ANOROX3.js → chunk-BTGPE6CR.js} +11 -9
  60. package/dist/chunk-BTY3HZBO.js +93 -0
  61. package/dist/{chunk-DPZHZQKE.js → chunk-BXYMYEJ4.js} +44 -10
  62. package/dist/{chunk-2RMYG36Q.js → chunk-C3RY6KU6.js} +309 -346
  63. package/dist/chunk-C4R4JLHE.js +40 -0
  64. package/dist/chunk-CADWLE2T.js +18 -0
  65. package/dist/chunk-CBGGOQWU.js +82 -0
  66. package/dist/chunk-CMDXGQTS.js +47 -0
  67. package/dist/{chunk-MC3H7736.js → chunk-CQDGOPGH.js} +58 -18
  68. package/dist/{chunk-HFQCFSJR.js → chunk-CX4RZ2KS.js} +4 -3
  69. package/dist/{chunk-PAMPPUR6.js → chunk-CXJ6FUKN.js} +1852 -207
  70. package/dist/{chunk-ABWHYWNI.js → chunk-D73UEXYW.js} +3 -3
  71. package/dist/chunk-DCZWQLYT.js +1205 -0
  72. package/dist/chunk-DLOBCJL6.js +48 -0
  73. package/dist/{chunk-4BN53TG3.js → chunk-DOBQKHIF.js} +31 -23
  74. package/dist/chunk-E3ISYXO3.js +423 -0
  75. package/dist/{chunk-7SW2QWLU.js → chunk-E6ZIEVOI.js} +16 -13
  76. package/dist/chunk-EBL2R3YG.js +43 -0
  77. package/dist/{chunk-AIOQPLA5.js → chunk-EGQRREQH.js} +41 -15
  78. package/dist/chunk-EHA7RMZ3.js +58 -0
  79. package/dist/{chunk-M766ZJ6W.js → chunk-EIPTLPFC.js} +38 -27
  80. package/dist/chunk-EMRIQUND.js +517 -0
  81. package/dist/{chunk-DFBCSHVT.js → chunk-EPCJQQWD.js} +6 -4
  82. package/dist/{chunk-RZPYKDWS.js → chunk-F3P7N7SF.js} +1 -1
  83. package/dist/{chunk-R77KLRB3.js → chunk-FFLNS6VP.js} +21 -18
  84. package/dist/chunk-FFTRTL6R.js +26 -0
  85. package/dist/{chunk-IHMLFRVV.js → chunk-FPJPLKDW.js} +62 -16
  86. package/dist/{chunk-JCZIKA4C.js → chunk-FSMSFDLD.js} +5 -4
  87. package/dist/{chunk-AVJDSJ2F.js → chunk-FUJM6RTF.js} +8 -7
  88. package/dist/chunk-FZOJFH7Q.js +132 -0
  89. package/dist/{chunk-QRAOANID.js → chunk-G6X77UJZ.js} +23 -21
  90. package/dist/{chunk-3ALD2W2A.js → chunk-GCWRWSU7.js} +10 -4
  91. package/dist/chunk-GIW4ZVDB.js +39 -0
  92. package/dist/{chunk-B2WLAWNJ.js → chunk-GUX3PTYM.js} +3 -3
  93. package/dist/{chunk-DPUYDDQG.js → chunk-GZY6RUZ6.js} +25 -3
  94. package/dist/chunk-H4VO6WG3.js +10 -0
  95. package/dist/{chunk-MMOSZPWJ.js → chunk-H5HBGNXU.js} +5 -4
  96. package/dist/chunk-H7KM7LZE.js +229 -0
  97. package/dist/{chunk-AA6YULYB.js → chunk-HNM2YQT2.js} +7 -7
  98. package/dist/{chunk-3C7EYRFZ.js → chunk-HYU5VLGA.js} +1 -1
  99. package/dist/{chunk-XY3P7JW7.js → chunk-IDKCWSM5.js} +1032 -172
  100. package/dist/chunk-IFKEI4SA.js +237 -0
  101. package/dist/{chunk-F7HYOUFF.js → chunk-IGOE6KPG.js} +67 -22
  102. package/dist/{chunk-TDD55CJH.js → chunk-IH2XURVQ.js} +6 -5
  103. package/dist/chunk-INQHESFB.js +38 -0
  104. package/dist/chunk-IP74LCOQ.js +57 -0
  105. package/dist/chunk-IPHHDDC6.js +45 -0
  106. package/dist/{chunk-T6AIP7H5.js → chunk-ISUAAMGS.js} +110 -153
  107. package/dist/{chunk-A7UPUQFY.js → chunk-IUPG3UKI.js} +624 -319
  108. package/dist/{chunk-L6SGQIR3.js → chunk-IVBOQAGB.js} +7 -3
  109. package/dist/{chunk-27NKUS3X.js → chunk-J2JAKCIW.js} +2205 -796
  110. package/dist/{chunk-V2YTAIQO.js → chunk-J3IOLXWM.js} +24 -7
  111. package/dist/chunk-JA5FI3QV.js +142 -0
  112. package/dist/chunk-JAVI7JSP.js +49 -0
  113. package/dist/{chunk-HLJAXMM4.js → chunk-JB5LINEM.js} +6 -2
  114. package/dist/{chunk-2VHF7OXM.js → chunk-JENSEMXF.js} +1 -1
  115. package/dist/{chunk-6BVONWJ7.js → chunk-JJF6HALY.js} +4 -3
  116. package/dist/chunk-JLUCKAEL.js +38 -0
  117. package/dist/chunk-JRBFANFE.js +221 -0
  118. package/dist/{chunk-R6XF6UR3.js → chunk-KDNTAPLX.js} +4 -4
  119. package/dist/chunk-KFAVQZSX.js +33 -0
  120. package/dist/chunk-KJXD4PNL.js +50 -0
  121. package/dist/chunk-KN5BXMWN.js +44 -0
  122. package/dist/{chunk-PCVDV3UZ.js → chunk-KQGURXFU.js} +9 -7
  123. package/dist/{chunk-WY6PP6AA.js → chunk-KXITGYLF.js} +40 -6
  124. package/dist/{chunk-66YVAGGM.js → chunk-L27SV425.js} +22 -20
  125. package/dist/{chunk-NE2W3OO7.js → chunk-LDLL7LB3.js} +24 -22
  126. package/dist/chunk-LFGTYX5U.js +379 -0
  127. package/dist/{chunk-EYWIDJFU.js → chunk-LGBMTVNT.js} +7 -5
  128. package/dist/{chunk-Q5AMFEWD.js → chunk-LGFL54FP.js} +3 -2
  129. package/dist/{chunk-6TACQN3N.js → chunk-LJXMYKZJ.js} +7 -5
  130. package/dist/{chunk-BKVWTZ6A.js → chunk-LKOR5UET.js} +29 -26
  131. package/dist/chunk-LNBQOP7D.js +294 -0
  132. package/dist/{chunk-O3WI5KWW.js → chunk-LO6P2VYG.js} +2 -2
  133. package/dist/chunk-LQJPN536.js +122 -0
  134. package/dist/{chunk-YEDDOYSC.js → chunk-LYBNHMVZ.js} +29 -5
  135. package/dist/{chunk-A3GY6SOA.js → chunk-LZ7NUC62.js} +20 -18
  136. package/dist/chunk-M32BLWDH.js +37 -0
  137. package/dist/{chunk-VYDBJ73M.js → chunk-M3NANSDZ.js} +17 -15
  138. package/dist/chunk-MFHL5URL.js +31 -0
  139. package/dist/chunk-MFR5OPBD.js +109 -0
  140. package/dist/{chunk-DE76JROX.js → chunk-MG4ZL5RW.js} +32 -20
  141. package/dist/{chunk-N7IXEHK3.js → chunk-MO6P2JZH.js} +10 -8
  142. package/dist/{chunk-65NYPGRC.js → chunk-MUWDB4R4.js} +1 -1
  143. package/dist/chunk-MZCGSXVR.js +34 -0
  144. package/dist/{chunk-MGYZM27B.js → chunk-N3XIYPU3.js} +51 -23
  145. package/dist/chunk-NDCF4R6S.js +172 -0
  146. package/dist/{chunk-DHPACDG7.js → chunk-NR2UJWOC.js} +10 -8
  147. package/dist/chunk-NXJ5URP6.js +51 -0
  148. package/dist/{chunk-UNM6ZOKP.js → chunk-NY2XSR5K.js} +147 -18
  149. package/dist/{chunk-5GDRCDQB.js → chunk-O45HFTFS.js} +3 -2
  150. package/dist/{chunk-ONLS5QA5.js → chunk-O4GXGGBX.js} +14 -12
  151. package/dist/chunk-O5PXQR67.js +249 -0
  152. package/dist/{chunk-PRPPGYZG.js → chunk-O66DM6DJ.js} +6 -4
  153. package/dist/{chunk-KEM4SDDP.js → chunk-O7FDLW7L.js} +11 -8
  154. package/dist/{chunk-T2UYZSCQ.js → chunk-O7XLYEFA.js} +169 -29
  155. package/dist/{chunk-FITWGOJ2.js → chunk-OHNCWBKF.js} +4 -4
  156. package/dist/{chunk-652QWTLZ.js → chunk-OHVTTOPS.js} +3 -3
  157. package/dist/chunk-OMI6FPPN.js +43 -0
  158. package/dist/chunk-ONUPY3H6.js +53 -0
  159. package/dist/chunk-OTLDSZDV.js +69 -0
  160. package/dist/chunk-OUBGGKDU.js +22 -0
  161. package/dist/chunk-OWNCM4ZN.js +330 -0
  162. package/dist/{chunk-YISXLPHN.js → chunk-P2V7QW4D.js} +235 -35
  163. package/dist/{chunk-CNUKCS2T.js → chunk-P32RUW3B.js} +1632 -93
  164. package/dist/{chunk-BWZ77RQT.js → chunk-PAQ2AS5E.js} +1 -1
  165. package/dist/{chunk-ZMAINWBW.js → chunk-PBPBMP2B.js} +4 -3
  166. package/dist/{chunk-ZVM6AKKM.js → chunk-PJSJPMJI.js} +3 -3
  167. package/dist/{chunk-EFHQ3TWP.js → chunk-PKBHS4AA.js} +233 -56
  168. package/dist/{chunk-GT4I4ZWM.js → chunk-PMUAJGLI.js} +20 -16
  169. package/dist/chunk-PPD7HTDP.js +152 -0
  170. package/dist/chunk-PSOFBQWB.js +42 -0
  171. package/dist/{chunk-S2A7YC3Q.js → chunk-Q2TECDIT.js} +10694 -8896
  172. package/dist/chunk-Q4K5WB2W.js +42 -0
  173. package/dist/{chunk-UGLN7QHV.js → chunk-Q6DFNVRJ.js} +14 -12
  174. package/dist/chunk-QA4O2GGC.js +265 -0
  175. package/dist/chunk-QAXW2N3B.js +1216 -0
  176. package/dist/chunk-QBNWF5ZU.js +19 -0
  177. package/dist/chunk-QFWA2DPH.js +224 -0
  178. package/dist/{chunk-23W7VWKR.js → chunk-QKUJMING.js} +1363 -114
  179. package/dist/{chunk-NXFPS2LR.js → chunk-R44CYFPV.js} +16 -13
  180. package/dist/{chunk-CKSITVS4.js → chunk-R7NYHMUU.js} +2687 -786
  181. package/dist/chunk-REWWDVQB.js +162 -0
  182. package/dist/{chunk-JMSCMUCA.js → chunk-RGERPOIV.js} +145 -21
  183. package/dist/{chunk-6JCPI55B.js → chunk-RLDGWLQ7.js} +49 -7
  184. package/dist/chunk-RUGXBPWI.js +384 -0
  185. package/dist/{chunk-CPA6HPVR.js → chunk-RXPJMEOW.js} +18 -12
  186. package/dist/{chunk-3HI6Z55Y.js → chunk-S4PMJU6H.js} +339 -43
  187. package/dist/chunk-S5LSDXV4.js +40 -0
  188. package/dist/chunk-S7FCV7S5.js +51 -0
  189. package/dist/{chunk-5GGOLAKC.js → chunk-SDKLKB6I.js} +28 -26
  190. package/dist/chunk-SFSPGFCV.js +62 -0
  191. package/dist/{chunk-ZNCEKR4J.js → chunk-SFUP7TTO.js} +12 -8
  192. package/dist/{chunk-64EQYWCA.js → chunk-SLXZOMA6.js} +69 -19
  193. package/dist/chunk-SQV37XO2.js +273 -0
  194. package/dist/{chunk-K65BJIMT.js → chunk-SU74NDMQ.js} +19 -17
  195. package/dist/chunk-SYV5LHML.js +165 -0
  196. package/dist/chunk-T4YPZIQN.js +36 -0
  197. package/dist/chunk-T6DQR5TV.js +323 -0
  198. package/dist/{chunk-JIITQXFB.js → chunk-THDMSZ3R.js} +3075 -802
  199. package/dist/{chunk-JGZCG5VM.js → chunk-TNR75OXT.js} +7 -7
  200. package/dist/{chunk-D3PO4DOZ.js → chunk-TUULXQRW.js} +174 -15
  201. package/dist/chunk-TYQBFTBR.js +516 -0
  202. package/dist/chunk-U76OWS3Q.js +49 -0
  203. package/dist/{chunk-YYQN46FY.js → chunk-UCROWG2D.js} +27 -24
  204. package/dist/{chunk-6M5NK3K3.js → chunk-UF4AZOZB.js} +50 -10
  205. package/dist/chunk-UF4GLFBX.js +345 -0
  206. package/dist/{chunk-OT2O76OS.js → chunk-UGUP3ZM6.js} +240 -39
  207. package/dist/chunk-UNAGJYET.js +45 -0
  208. package/dist/{chunk-5WG5YP4T.js → chunk-UOR2DTHH.js} +16 -14
  209. package/dist/{chunk-S3QNRWYR.js → chunk-UPOY4YSQ.js} +14 -12
  210. package/dist/{chunk-EPTBZ3GP.js → chunk-UPS2DGFC.js} +1 -1
  211. package/dist/{chunk-4AK7IBVP.js → chunk-UUU4CLJG.js} +4 -2
  212. package/dist/{chunk-W3BQAZ3Q.js → chunk-UWMJKX5U.js} +14 -12
  213. package/dist/{chunk-QZSX3F7C.js → chunk-UWOJLHFT.js} +27 -23
  214. package/dist/chunk-VBTP56CE.js +535 -0
  215. package/dist/chunk-VCTWPLAO.js +211 -0
  216. package/dist/chunk-VNU26RCO.js +1215 -0
  217. package/dist/{chunk-CSZ4C5N6.js → chunk-VTZMAJ3W.js} +93 -10
  218. package/dist/{chunk-TXLH6WHQ.js → chunk-VW62D6QE.js} +14 -12
  219. package/dist/{chunk-CAQZUNOH.js → chunk-VY72R2XZ.js} +610 -3
  220. package/dist/{chunk-2DIQQJCB.js → chunk-VZALIKIF.js} +18 -15
  221. package/dist/{chunk-TYAID7B7.js → chunk-W62H2XSO.js} +25 -23
  222. package/dist/{chunk-HVUPKCGJ.js → chunk-W7VWI2YH.js} +9 -6
  223. package/dist/{chunk-TANFV3MZ.js → chunk-WERM6KPJ.js} +7 -4
  224. package/dist/{chunk-BOHJZTEQ.js → chunk-WF7B67YE.js} +208 -87
  225. package/dist/{chunk-7FBGJFEE.js → chunk-WG5U3F5V.js} +14 -12
  226. package/dist/{chunk-4NDAAFQT.js → chunk-WJF2CS6M.js} +8 -5
  227. package/dist/{chunk-XAKWMCXI.js → chunk-WKUJ3KPV.js} +4 -4
  228. package/dist/chunk-WMTRHUI5.js +103 -0
  229. package/dist/chunk-WNKPRSGI.js +36 -0
  230. package/dist/chunk-WXFLMQSR.js +223 -0
  231. package/dist/{chunk-RRTKKSLQ.js → chunk-X3WY6MN3.js} +8 -6
  232. package/dist/{chunk-ZCJDOK2S.js → chunk-X4CXA2IL.js} +47 -23
  233. package/dist/{chunk-UBBC2XSG.js → chunk-X5F3Q5LV.js} +560 -105
  234. package/dist/{chunk-C6EKFH7J.js → chunk-XD75VZIH.js} +9 -7
  235. package/dist/chunk-XERYFDB5.js +297 -0
  236. package/dist/chunk-XI2LCCYQ.js +420 -0
  237. package/dist/chunk-Y2EQNWKV.js +933 -0
  238. package/dist/{chunk-LR3R6Z2A.js → chunk-YHCMZC2J.js} +7 -7
  239. package/dist/chunk-YYY3AZFE.js +122 -0
  240. package/dist/{chunk-GDLULHTC.js → chunk-Z5IA3WDR.js} +19 -31
  241. package/dist/{chunk-T6XQL73F.js → chunk-ZFFYNRIO.js} +63 -23
  242. package/dist/{chunk-EDS2L2LD.js → chunk-ZFL7NY4F.js} +56 -27
  243. package/dist/{chunk-YMZ3TNYB.js → chunk-ZGULQAPZ.js} +7 -4
  244. package/dist/{chunk-4SKZDI62.js → chunk-ZIUFM5HT.js} +3 -1
  245. package/dist/{chunk-DKJA76CJ.js → chunk-ZJFRMSJT.js} +15 -13
  246. package/dist/chunk-ZJXLNDH4.js +239 -0
  247. package/dist/chunk-ZQ3ON2VQ.js +252 -0
  248. package/dist/{chunk-HITVBIJS.js → chunk-ZQ7SKESZ.js} +150 -415
  249. package/dist/{chunk-6QSERWXH.js → chunk-ZQXZ2SES.js} +24 -21
  250. package/dist/chunk-ZX57KSEQ.js +39 -0
  251. package/dist/{chunk-I3E7CX4H.js → chunk-ZZK56BLP.js} +5 -3
  252. package/dist/files.json +664 -368
  253. package/dist/packages/naysayer/constitution/constitution.yaml +19 -0
  254. package/dist/packages/sdk/npm/index.js +6194 -2542
  255. package/dist/packages/ui/dist/assets/{elk-api-tma0MCuh.js → elk-api-CIf-0gz5.js} +2 -2
  256. package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +47 -0
  257. package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +1 -0
  258. package/dist/packages/ui/dist/index.html +3 -2
  259. package/package.json +5 -5
  260. package/dist/chunk-2BF2EYJV.js +0 -174
  261. package/dist/chunk-42EVSKME.js +0 -37
  262. package/dist/chunk-4BKGMUIK.js +0 -53
  263. package/dist/chunk-5KLGBXG5.js +0 -48
  264. package/dist/chunk-6BNC6EQ4.js +0 -41
  265. package/dist/chunk-6D2CQ5II.js +0 -41
  266. package/dist/chunk-7AVHLZGD.js +0 -45
  267. package/dist/chunk-D46WUV3T.js +0 -33
  268. package/dist/chunk-E36QOJMD.js +0 -47
  269. package/dist/chunk-FQXYPF7E.js +0 -147
  270. package/dist/chunk-GBRFVT63.js +0 -45
  271. package/dist/chunk-ICY36XCH.js +0 -34
  272. package/dist/chunk-J4K3KVLD.js +0 -131
  273. package/dist/chunk-JZU3H6UQ.js +0 -54
  274. package/dist/chunk-NN2ZQEB4.js +0 -38
  275. package/dist/chunk-PCOCACY3.js +0 -385
  276. package/dist/chunk-RTEYOSJY.js +0 -29
  277. package/dist/chunk-RUVFXE2L.js +0 -666
  278. package/dist/chunk-RVH5SUW5.js +0 -69
  279. package/dist/chunk-VN3DP4LQ.js +0 -43
  280. package/dist/chunk-W5BVQF44.js +0 -36
  281. package/dist/chunk-WVPJSRRJ.js +0 -52
  282. package/dist/chunk-XPTOBS2D.js +0 -48
  283. package/dist/packages/ui/dist/assets/index-B54fm9FQ.js +0 -29
  284. package/dist/packages/ui/dist/assets/index-DD_hufQz.css +0 -1
@@ -7,9 +7,15 @@ import {
7
7
  ManualStep,
8
8
  changesDirOf,
9
9
  external_exports,
10
- require_dist,
10
+ orgPackDirOf,
11
11
  toCanonicalYaml
12
- } from "./chunk-S2A7YC3Q.js";
12
+ } from "./chunk-Q2TECDIT.js";
13
+ import {
14
+ renameRetrying
15
+ } from "./chunk-TUULXQRW.js";
16
+ import {
17
+ require_dist
18
+ } from "./chunk-BQGDB6ZL.js";
13
19
  import {
14
20
  __toESM
15
21
  } from "./chunk-TV45EUGM.js";
@@ -116,10 +122,190 @@ function workItemsCsv(stories, o = {}) {
116
122
  `).join("");
117
123
  }
118
124
 
125
+ // packages/adapters/dist/common.js
126
+ var Approval = external_exports.strictObject({
127
+ /** The person who approved: a handle from the Git host or directory. */
128
+ by: external_exports.string().min(1),
129
+ at: external_exports.iso.datetime({ offset: true }),
130
+ scope: external_exports.enum(["once", "standing"]).default("once"),
131
+ /** What was approved, e.g. a finding, hand-off PR or artifact path. */
132
+ ref: external_exports.string().min(1)
133
+ });
134
+ var AdapterError = class extends Error {
135
+ adapter;
136
+ code;
137
+ retryable;
138
+ constructor(adapter, code, message, retryable = code === "rate-limited" || code === "unavailable") {
139
+ super(`${adapter}: ${message}`);
140
+ this.adapter = adapter;
141
+ this.code = code;
142
+ this.retryable = retryable;
143
+ this.name = "AdapterError";
144
+ }
145
+ };
146
+ function requireApproval(adapter, approval, opts = {}) {
147
+ const r = Approval.safeParse(approval);
148
+ if (!r.success) {
149
+ throw new AdapterError(adapter, "not-approved", "this write needs a person's approval (by, at, ref)");
150
+ }
151
+ if (r.data.scope === "standing" && !opts.allowStanding) {
152
+ throw new AdapterError(adapter, "not-approved", "a standing approval can't cover this write; it needs approval each time");
153
+ }
154
+ return r.data;
155
+ }
156
+ var MockBase = class {
157
+ name;
158
+ journal = [];
159
+ failures = [];
160
+ constructor(name) {
161
+ this.name = name;
162
+ }
163
+ failNext(code, method) {
164
+ this.failures.push(method === void 0 ? { code } : { code, method });
165
+ }
166
+ /** Record a call and raise an injected failure if one is due. */
167
+ call(method, args, approval) {
168
+ const i = this.failures.findIndex((f) => f.method === void 0 || f.method === method);
169
+ if (i !== -1) {
170
+ const [f] = this.failures.splice(i, 1);
171
+ throw new AdapterError(this.name, f.code, `injected ${f.code} on ${method}`);
172
+ }
173
+ this.journal.push(approval ? { adapter: this.name, method, args, approval } : { adapter: this.name, method, args });
174
+ }
175
+ notFound(what) {
176
+ throw new AdapterError(this.name, "not-found", `${what} not found`);
177
+ }
178
+ };
179
+
180
+ // packages/adapters/dist/git-host.js
181
+ function mergeBlockers(pr) {
182
+ const out = [];
183
+ if (pr.state === "merged" || pr.state === "closed")
184
+ out.push(`the PR is ${pr.state}`);
185
+ if (pr.state === "draft")
186
+ out.push("the PR is a draft");
187
+ const latest = /* @__PURE__ */ new Map();
188
+ for (const r of pr.reviews)
189
+ if (r.state !== "commented")
190
+ latest.set(r.by, r.state);
191
+ if ([...latest.values()].includes("changes-requested"))
192
+ out.push("changes are requested");
193
+ const missing = pr.requiredReviewers.filter((r) => latest.get(r) !== "approved");
194
+ if (pr.requiredReviewers.length > 0 && missing.length === pr.requiredReviewers.length) {
195
+ out.push(`needs approval from ${pr.requiredReviewers.join(" or ")}`);
196
+ }
197
+ if (pr.requiredReviewers.length === 0 && ![...latest.values()].includes("approved"))
198
+ out.push("needs at least one approval");
199
+ const failing = pr.checks.filter((c) => c.status !== "passed").map((c) => `${c.name} ${c.status}`);
200
+ if (failing.length > 0)
201
+ out.push(`checks not passing: ${failing.join(", ")}`);
202
+ return out;
203
+ }
204
+ var MockGitHost = class extends MockBase {
205
+ repos = /* @__PURE__ */ new Map();
206
+ prs = /* @__PURE__ */ new Map();
207
+ numbers = /* @__PURE__ */ new Map();
208
+ constructor(repos = []) {
209
+ super("git-host");
210
+ for (const r of repos) {
211
+ const defaultBranch = r.defaultBranch ?? "main";
212
+ this.repos.set(r.repo, {
213
+ repo: r.repo,
214
+ defaultBranch,
215
+ protectedBranches: r.protectedBranches ?? [defaultBranch]
216
+ });
217
+ }
218
+ }
219
+ key = (repo, n) => `${repo}#${n}`;
220
+ async getRepo(repo) {
221
+ this.call("getRepo", [repo]);
222
+ return { ...this.repos.get(repo) ?? this.notFound(`repo ${repo}`) };
223
+ }
224
+ async getPullRequest(repo, number) {
225
+ this.call("getPullRequest", [repo, number]);
226
+ return structuredClone(this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`));
227
+ }
228
+ async listPullRequests(repo, q) {
229
+ this.call("listPullRequests", [repo, q]);
230
+ return [...this.prs.values()].filter((p2) => p2.repo === repo && (!q.head || p2.head === q.head) && (!q.state || p2.state === q.state)).map((p2) => structuredClone(p2));
231
+ }
232
+ async createPullRequest(input, approval) {
233
+ const a = requireApproval(this.name, approval);
234
+ this.call("createPullRequest", [input], a);
235
+ const info = this.repos.get(input.repo) ?? this.notFound(`repo ${input.repo}`);
236
+ if (info.protectedBranches.includes(input.head)) {
237
+ throw new AdapterError(this.name, "invalid", `${input.head} is protected and can't be a PR's source branch`);
238
+ }
239
+ if ([...this.prs.values()].some((p2) => p2.repo === input.repo && p2.head === input.head && (p2.state === "open" || p2.state === "draft"))) {
240
+ throw new AdapterError(this.name, "conflict", `an open PR from ${input.head} already exists`);
241
+ }
242
+ const n = (this.numbers.get(input.repo) ?? 0) + 1;
243
+ this.numbers.set(input.repo, n);
244
+ const pr = {
245
+ repo: input.repo,
246
+ number: n,
247
+ url: `https://git.example.com/${input.repo}/pull/${n}`,
248
+ title: input.title,
249
+ body: input.body,
250
+ head: input.head,
251
+ base: input.base,
252
+ state: input.draft ? "draft" : "open",
253
+ reviews: [],
254
+ checks: [],
255
+ requiredReviewers: []
256
+ };
257
+ this.prs.set(this.key(input.repo, n), pr);
258
+ return structuredClone(pr);
259
+ }
260
+ async comment(repo, number, body, approval) {
261
+ const a = requireApproval(this.name, approval);
262
+ this.call("comment", [repo, number, body], a);
263
+ if (!this.prs.has(this.key(repo, number)))
264
+ this.notFound(`PR ${repo}#${number}`);
265
+ }
266
+ async merge(repo, number, approval) {
267
+ const a = requireApproval(this.name, approval);
268
+ this.call("merge", [repo, number], a);
269
+ const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
270
+ const blockers = mergeBlockers(pr);
271
+ if (blockers.length > 0)
272
+ throw new AdapterError(this.name, "conflict", `can't merge: ${blockers.join("; ")}`);
273
+ pr.state = "merged";
274
+ return structuredClone(pr);
275
+ }
276
+ async closePullRequest(repo, number, approval) {
277
+ const a = requireApproval(this.name, approval);
278
+ this.call("closePullRequest", [repo, number], a);
279
+ const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
280
+ if (pr.state === "merged")
281
+ throw new AdapterError(this.name, "conflict", `PR ${number} is merged and can't be closed`);
282
+ pr.state = "closed";
283
+ return structuredClone(pr);
284
+ }
285
+ /** Test helpers: what reviewers and CI would do on the host. */
286
+ review(repo, number, by, state) {
287
+ (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).reviews.push({
288
+ by,
289
+ state
290
+ });
291
+ }
292
+ setChecks(repo, number, checks) {
293
+ (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).checks = checks;
294
+ }
295
+ requireReviewers(repo, number, reviewers) {
296
+ (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).requiredReviewers = reviewers;
297
+ }
298
+ markReady(repo, number) {
299
+ const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
300
+ if (pr.state === "draft")
301
+ pr.state = "open";
302
+ }
303
+ };
304
+
119
305
  // packages/adapters/dist/manual/steps.js
120
306
  var import_yaml = __toESM(require_dist(), 1);
121
307
  import { createHash } from "node:crypto";
122
- import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
308
+ import { mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
123
309
  import { dirname, join } from "node:path";
124
310
  var LEADING = [
125
311
  "schemaVersion",
@@ -170,7 +356,7 @@ async function writeAtomic(path, text) {
170
356
  const tmp = `${path}.tmp`;
171
357
  try {
172
358
  await writeFile(tmp, text, "utf8");
173
- await rename(tmp, path);
359
+ await renameRetrying(tmp, path);
174
360
  } catch (e) {
175
361
  await rm(tmp, { force: true });
176
362
  throw e;
@@ -456,186 +642,6 @@ function exportStep(step, format) {
456
642
  };
457
643
  }
458
644
 
459
- // packages/adapters/dist/common.js
460
- var Approval = external_exports.strictObject({
461
- /** The person who approved: a handle from the Git host or directory. */
462
- by: external_exports.string().min(1),
463
- at: external_exports.iso.datetime({ offset: true }),
464
- scope: external_exports.enum(["once", "standing"]).default("once"),
465
- /** What was approved, e.g. a finding, hand-off PR or artifact path. */
466
- ref: external_exports.string().min(1)
467
- });
468
- var AdapterError = class extends Error {
469
- adapter;
470
- code;
471
- retryable;
472
- constructor(adapter, code, message, retryable = code === "rate-limited" || code === "unavailable") {
473
- super(`${adapter}: ${message}`);
474
- this.adapter = adapter;
475
- this.code = code;
476
- this.retryable = retryable;
477
- this.name = "AdapterError";
478
- }
479
- };
480
- function requireApproval(adapter, approval, opts = {}) {
481
- const r = Approval.safeParse(approval);
482
- if (!r.success) {
483
- throw new AdapterError(adapter, "not-approved", "this write needs a person's approval (by, at, ref)");
484
- }
485
- if (r.data.scope === "standing" && !opts.allowStanding) {
486
- throw new AdapterError(adapter, "not-approved", "a standing approval can't cover this write; it needs approval each time");
487
- }
488
- return r.data;
489
- }
490
- var MockBase = class {
491
- name;
492
- journal = [];
493
- failures = [];
494
- constructor(name) {
495
- this.name = name;
496
- }
497
- failNext(code, method) {
498
- this.failures.push(method === void 0 ? { code } : { code, method });
499
- }
500
- /** Record a call and raise an injected failure if one is due. */
501
- call(method, args, approval) {
502
- const i = this.failures.findIndex((f) => f.method === void 0 || f.method === method);
503
- if (i !== -1) {
504
- const [f] = this.failures.splice(i, 1);
505
- throw new AdapterError(this.name, f.code, `injected ${f.code} on ${method}`);
506
- }
507
- this.journal.push(approval ? { adapter: this.name, method, args, approval } : { adapter: this.name, method, args });
508
- }
509
- notFound(what) {
510
- throw new AdapterError(this.name, "not-found", `${what} not found`);
511
- }
512
- };
513
-
514
- // packages/adapters/dist/git-host.js
515
- function mergeBlockers(pr) {
516
- const out = [];
517
- if (pr.state === "merged" || pr.state === "closed")
518
- out.push(`the PR is ${pr.state}`);
519
- if (pr.state === "draft")
520
- out.push("the PR is a draft");
521
- const latest = /* @__PURE__ */ new Map();
522
- for (const r of pr.reviews)
523
- if (r.state !== "commented")
524
- latest.set(r.by, r.state);
525
- if ([...latest.values()].includes("changes-requested"))
526
- out.push("changes are requested");
527
- const missing = pr.requiredReviewers.filter((r) => latest.get(r) !== "approved");
528
- if (pr.requiredReviewers.length > 0 && missing.length === pr.requiredReviewers.length) {
529
- out.push(`needs approval from ${pr.requiredReviewers.join(" or ")}`);
530
- }
531
- if (pr.requiredReviewers.length === 0 && ![...latest.values()].includes("approved"))
532
- out.push("needs at least one approval");
533
- const failing = pr.checks.filter((c) => c.status !== "passed").map((c) => `${c.name} ${c.status}`);
534
- if (failing.length > 0)
535
- out.push(`checks not passing: ${failing.join(", ")}`);
536
- return out;
537
- }
538
- var MockGitHost = class extends MockBase {
539
- repos = /* @__PURE__ */ new Map();
540
- prs = /* @__PURE__ */ new Map();
541
- numbers = /* @__PURE__ */ new Map();
542
- constructor(repos = []) {
543
- super("git-host");
544
- for (const r of repos) {
545
- const defaultBranch = r.defaultBranch ?? "main";
546
- this.repos.set(r.repo, {
547
- repo: r.repo,
548
- defaultBranch,
549
- protectedBranches: r.protectedBranches ?? [defaultBranch]
550
- });
551
- }
552
- }
553
- key = (repo, n) => `${repo}#${n}`;
554
- async getRepo(repo) {
555
- this.call("getRepo", [repo]);
556
- return { ...this.repos.get(repo) ?? this.notFound(`repo ${repo}`) };
557
- }
558
- async getPullRequest(repo, number) {
559
- this.call("getPullRequest", [repo, number]);
560
- return structuredClone(this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`));
561
- }
562
- async listPullRequests(repo, q) {
563
- this.call("listPullRequests", [repo, q]);
564
- return [...this.prs.values()].filter((p2) => p2.repo === repo && (!q.head || p2.head === q.head) && (!q.state || p2.state === q.state)).map((p2) => structuredClone(p2));
565
- }
566
- async createPullRequest(input, approval) {
567
- const a = requireApproval(this.name, approval);
568
- this.call("createPullRequest", [input], a);
569
- const info = this.repos.get(input.repo) ?? this.notFound(`repo ${input.repo}`);
570
- if (info.protectedBranches.includes(input.head)) {
571
- throw new AdapterError(this.name, "invalid", `${input.head} is protected and can't be a PR's source branch`);
572
- }
573
- if ([...this.prs.values()].some((p2) => p2.repo === input.repo && p2.head === input.head && (p2.state === "open" || p2.state === "draft"))) {
574
- throw new AdapterError(this.name, "conflict", `an open PR from ${input.head} already exists`);
575
- }
576
- const n = (this.numbers.get(input.repo) ?? 0) + 1;
577
- this.numbers.set(input.repo, n);
578
- const pr = {
579
- repo: input.repo,
580
- number: n,
581
- url: `https://git.example.com/${input.repo}/pull/${n}`,
582
- title: input.title,
583
- body: input.body,
584
- head: input.head,
585
- base: input.base,
586
- state: input.draft ? "draft" : "open",
587
- reviews: [],
588
- checks: [],
589
- requiredReviewers: []
590
- };
591
- this.prs.set(this.key(input.repo, n), pr);
592
- return structuredClone(pr);
593
- }
594
- async comment(repo, number, body, approval) {
595
- const a = requireApproval(this.name, approval);
596
- this.call("comment", [repo, number, body], a);
597
- if (!this.prs.has(this.key(repo, number)))
598
- this.notFound(`PR ${repo}#${number}`);
599
- }
600
- async merge(repo, number, approval) {
601
- const a = requireApproval(this.name, approval);
602
- this.call("merge", [repo, number], a);
603
- const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
604
- const blockers = mergeBlockers(pr);
605
- if (blockers.length > 0)
606
- throw new AdapterError(this.name, "conflict", `can't merge: ${blockers.join("; ")}`);
607
- pr.state = "merged";
608
- return structuredClone(pr);
609
- }
610
- async closePullRequest(repo, number, approval) {
611
- const a = requireApproval(this.name, approval);
612
- this.call("closePullRequest", [repo, number], a);
613
- const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
614
- if (pr.state === "merged")
615
- throw new AdapterError(this.name, "conflict", `PR ${number} is merged and can't be closed`);
616
- pr.state = "closed";
617
- return structuredClone(pr);
618
- }
619
- /** Test helpers: what reviewers and CI would do on the host. */
620
- review(repo, number, by, state) {
621
- (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).reviews.push({
622
- by,
623
- state
624
- });
625
- }
626
- setChecks(repo, number, checks) {
627
- (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).checks = checks;
628
- }
629
- requireReviewers(repo, number, reviewers) {
630
- (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).requiredReviewers = reviewers;
631
- }
632
- markReady(repo, number) {
633
- const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
634
- if (pr.state === "draft")
635
- pr.state = "open";
636
- }
637
- };
638
-
639
645
  // packages/adapters/dist/read-only.js
640
646
  var MockWiki = class extends MockBase {
641
647
  pages = /* @__PURE__ */ new Map();
@@ -845,6 +851,11 @@ var MockWorkTracker = class _MockWorkTracker extends MockBase {
845
851
  }
846
852
  };
847
853
 
854
+ // packages/adapters/dist/manual/git-host.js
855
+ var import_yaml2 = __toESM(require_dist(), 1);
856
+ import { readdir as readdir2, readFile as readFile2 } from "node:fs/promises";
857
+ import { join as join2 } from "node:path";
858
+
848
859
  // packages/adapters/dist/manual/base.js
849
860
  var nowIso2 = () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
850
861
  var PROVISIONAL = "manual:";
@@ -914,38 +925,98 @@ function changeOfBranch(branch) {
914
925
  const m = /^(?:handoff|task|change)\/([a-z0-9][a-z0-9._-]*)(?:\/|$)/.exec(branch);
915
926
  return m?.[1];
916
927
  }
928
+ var localOf = (open) => Number(open.inputs.number);
929
+ function recordedOf(open) {
930
+ const n = open.state === "done" ? Number(open.recorded?.values.number) : NaN;
931
+ return Number.isInteger(n) && n > 0 ? n : void 0;
932
+ }
933
+ var prName = (open) => {
934
+ const n = recordedOf(open);
935
+ return n ? `PR #${n}` : `the PR from ${String(open.inputs.head)}`;
936
+ };
937
+ var prSlug = (verb, open) => `${verb}-pr-${String(open.inputs.head)}`;
917
938
  var ManualGitHost = class extends ManualBase {
918
939
  constructor(opts) {
919
940
  super("git-host", "git-host", opts);
920
941
  }
942
+ /**
943
+ * Review round 48: the repo's own default branch, not one for every repo. A per-repo setting
944
+ * (`defaultBranch.<repo>`) first, then the repo's `defaultBranch` in the repos manifest (ADR
945
+ * 0123: the baseline the PRs build on), then the adapter's `defaultBranch` setting, else main.
946
+ * Its protected branches (`protectedBranches.<repo>`, else `protectedBranches`) always include
947
+ * the default branch.
948
+ */
921
949
  async getRepo(repo) {
922
950
  this.journal.push({ method: "getRepo" });
923
- const defaultBranch = this.setting("defaultBranch") ?? "main";
951
+ const defaultBranch = this.setting(`defaultBranch.${repo}`) ?? await this.manifestDefault(repo) ?? this.setting("defaultBranch") ?? "main";
952
+ const listed = this.settingList(`protectedBranches.${repo}`) ?? this.settingList("protectedBranches") ?? [];
924
953
  return {
925
954
  repo,
926
955
  defaultBranch,
927
- protectedBranches: this.settingList("protectedBranches") ?? [defaultBranch]
956
+ protectedBranches: listed.includes(defaultBranch) ? listed : [...listed, defaultBranch]
928
957
  };
929
958
  }
959
+ /** The defaultBranch a repos manifest of the metarepo's org pack gives the repo, when one does. */
960
+ async manifestDefault(repo) {
961
+ if (!this.opts.root)
962
+ return void 0;
963
+ const profiles = join2(orgPackDirOf(this.opts.root), "profiles");
964
+ const names = await readdir2(profiles, { withFileTypes: true }).then((d) => d.filter((x) => x.isDirectory()).map((x) => x.name).sort(), () => []);
965
+ for (const name of names) {
966
+ const text = await readFile2(join2(profiles, name, "repos.manifest.yaml"), "utf8").catch(() => void 0);
967
+ if (text === void 0)
968
+ continue;
969
+ let doc;
970
+ try {
971
+ doc = (0, import_yaml2.parse)(text);
972
+ } catch {
973
+ continue;
974
+ }
975
+ const repos = doc?.repos;
976
+ if (!Array.isArray(repos))
977
+ continue;
978
+ const entry = repos.find((r) => r?.id === repo);
979
+ if (!entry)
980
+ continue;
981
+ return typeof entry.defaultBranch === "string" && entry.defaultBranch.trim() ? entry.defaultBranch.trim() : void 0;
982
+ }
983
+ return void 0;
984
+ }
930
985
  async prSteps(repo) {
931
986
  return (await this.opts.store.list({ system: "git-host", action: "open-pull-request" })).filter((s) => !repo || s.inputs.repo === repo);
932
987
  }
933
- async related(repo, number, action) {
988
+ /** The steps of one PR, by the number Atticus gave it (which never changes). */
989
+ async related(open, action) {
990
+ const repo = String(open.inputs.repo);
991
+ const number = localOf(open);
934
992
  return (await this.opts.store.list({ system: "git-host", action })).filter((s) => s.inputs.repo === repo && s.inputs.number === number);
935
993
  }
994
+ /**
995
+ * Review round 44: the number the PR goes by. The recorded one, unless it is the number Atticus
996
+ * gave another PR in the repo, or one recorded for another PR too: then the number Atticus gave
997
+ * it, so no number a caller holds ever names two PRs (new numbers skip recorded ones).
998
+ */
999
+ async numberOf(open) {
1000
+ const local = localOf(open);
1001
+ const rec = recordedOf(open);
1002
+ if (rec === void 0 || rec === local)
1003
+ return local;
1004
+ const others = (await this.prSteps(String(open.inputs.repo))).filter((s) => s.id !== open.id);
1005
+ return others.some((s) => localOf(s) === rec || recordedOf(s) === rec) ? local : rec;
1006
+ }
936
1007
  async toPr(open) {
937
1008
  const repo = String(open.inputs.repo);
938
- const number = Number(open.inputs.number);
1009
+ const number = localOf(open);
939
1010
  const rec = open.state === "done" ? open.recorded?.values : void 0;
940
- const merged = (await this.related(repo, number, "merge-pull-request")).some((s) => s.state === "done");
941
- const reports = (await this.related(repo, number, "report-pull-request")).filter((s) => s.state === "done").sort((a, b) => a.recorded.at < b.recorded.at ? -1 : 1);
1011
+ const reports = (await this.related(open, "report-pull-request")).filter((s) => s.state === "done").sort((a, b) => a.recorded.at < b.recorded.at ? -1 : 1);
1012
+ const merged = (await this.related(open, "merge-pull-request")).some((s) => s.state === "done") || reports.some((s) => s.recorded?.values.merged === true);
942
1013
  const last = reports.at(-1)?.recorded?.values;
943
1014
  const list = (v) => Array.isArray(v) ? v.map(String) : [];
944
1015
  const reviews = [
945
1016
  ...list(last?.approvers).map((by) => ({ by, state: "approved" })),
946
1017
  ...list(last?.changesRequestedBy).map((by) => ({ by, state: "changes-requested" }))
947
1018
  ];
948
- const closed = (await this.related(repo, number, "close-pull-request")).some((s) => s.state === "done");
1019
+ const closed = (await this.related(open, "close-pull-request")).some((s) => s.state === "done");
949
1020
  let state = open.state === "done" ? open.inputs.draft ? "draft" : "open" : "draft";
950
1021
  if (open.state === "skipped" || closed)
951
1022
  state = "closed";
@@ -953,7 +1024,7 @@ var ManualGitHost = class extends ManualBase {
953
1024
  state = "merged";
954
1025
  return {
955
1026
  repo,
956
- number,
1027
+ number: await this.numberOf(open),
957
1028
  url: typeof rec?.url === "string" ? rec.url : `manual://git-host/${repo}/pull/${number}`,
958
1029
  title: String(open.inputs.title ?? ""),
959
1030
  body: open.fields.find((f) => f.name === "Description")?.value ?? "",
@@ -965,13 +1036,56 @@ var ManualGitHost = class extends ManualBase {
965
1036
  requiredReviewers: []
966
1037
  };
967
1038
  }
1039
+ /**
1040
+ * The PR by the number Atticus gave it (which a caller may have kept from before the person
1041
+ * recorded the real one, and which no other PR in the repo has), else by the recorded number
1042
+ * it goes by (numberOf). Review round 44: a recorded number equal to another PR's own number
1043
+ * finds that other PR, never this one, so a caller can't be handed another change's PR.
1044
+ */
968
1045
  async find(repo, number) {
969
- const s = (await this.prSteps(repo)).find((x) => x.inputs.number === number);
970
- return s ?? this.notFound(`PR ${repo}#${number}`, "no manual step opened it");
1046
+ const all = await this.prSteps(repo);
1047
+ const local = all.find((x) => localOf(x) === number);
1048
+ if (local)
1049
+ return local;
1050
+ for (const x of all)
1051
+ if (await this.numberOf(x) === number)
1052
+ return x;
1053
+ if (all.filter((x) => recordedOf(x) === number).length > 1)
1054
+ throw new AdapterError(this.name, "conflict", `#${number} was recorded for more than one pull request in ${repo}: correct the number on the step of the one it isn't (atticus todo), or use the number Atticus gave it`);
1055
+ return this.notFound(`PR ${repo}#${number}`, "no manual step opened it");
971
1056
  }
972
1057
  async getPullRequest(repo, number) {
973
1058
  this.journal.push({ method: "getPullRequest" });
974
- return this.toPr(await this.find(repo, number));
1059
+ const open = await this.find(repo, number);
1060
+ const pr = await this.toPr(open);
1061
+ await this.settle(open, pr);
1062
+ return pr;
1063
+ }
1064
+ /**
1065
+ * Keeps a PR's steps in step with what was recorded: a reviews step still open on a PR that
1066
+ * reads merged or closed is skipped, saying why; a task's PR open on the host, with its reviews
1067
+ * recorded but not its merge, gets a step to record that it merged (a task's PR has no gate to
1068
+ * make a Merge step; a hand-off's gets one when it syncs). Steps only: nothing is sent.
1069
+ */
1070
+ async settle(open, pr) {
1071
+ const waiting = (await this.related(open, "report-pull-request")).filter((s) => s.state === "open");
1072
+ if (pr.state === "merged" || pr.state === "closed") {
1073
+ for (const s of waiting)
1074
+ await recordStep(this.opts.store, s.id, {
1075
+ by: "atticus",
1076
+ at: this.now(),
1077
+ skip: true,
1078
+ note: `${prName(open)} is ${pr.state} on the Git host: nothing left to record.`
1079
+ });
1080
+ return;
1081
+ }
1082
+ if (pr.state !== "open" || waiting.length > 0)
1083
+ return;
1084
+ if (!String(open.inputs.head).startsWith("task/"))
1085
+ return;
1086
+ if ((await this.related(open, "merge-pull-request")).some((s) => s.state === "open"))
1087
+ return;
1088
+ await this.askForReviews(open, open.change);
975
1089
  }
976
1090
  async listPullRequests(repo, q) {
977
1091
  this.journal.push({ method: "listPullRequests" });
@@ -986,15 +1100,16 @@ var ManualGitHost = class extends ManualBase {
986
1100
  /** A report step for the PR's reviews and checks, unless one is still open. */
987
1101
  async askForReviews(open, change) {
988
1102
  const repo = String(open.inputs.repo);
989
- const number = Number(open.inputs.number);
990
- const reports = await this.related(repo, number, "report-pull-request");
1103
+ const number = localOf(open);
1104
+ const reports = await this.related(open, "report-pull-request");
991
1105
  if (reports.some((s) => s.state === "open"))
992
1106
  return;
1107
+ const again = reports.some((s) => s.state === "done") && recordedOf(open) !== void 0;
993
1108
  await this.step("report", {
994
- slug: `report-pr-${number}`,
1109
+ slug: prSlug("report", open),
995
1110
  action: "report-pull-request",
996
1111
  key: `git-host|report|${repo}|${number}|${reports.length}`,
997
- title: `Record the reviews and checks on PR ${number} (${open.inputs.title})`,
1112
+ title: again ? `Record that ${prName(open)} (${open.inputs.title}) merged, or its reviews again` : `Record the reviews and checks on ${prName(open)} (${open.inputs.title}), and whether it merged`,
998
1113
  where: `Git host: ${repo}, the pull request opened for step ${open.id}`,
999
1114
  ...change ? { change } : {},
1000
1115
  inputs: { repo, number },
@@ -1004,7 +1119,8 @@ var ManualGitHost = class extends ManualBase {
1004
1119
  ],
1005
1120
  instructions: [
1006
1121
  "Once reviewers have acted, record who approved, who asked for changes and whether the checks pass.",
1007
- "Name people by their handle on the Git host. Only what is recorded here counts for approval."
1122
+ "Name people by their handle on the Git host. Only what is recorded here counts for approval.",
1123
+ "Once it is merged on the Git host, record Merged on the Git host: yes here, and Atticus reads it as merged."
1008
1124
  ],
1009
1125
  result: [
1010
1126
  { name: "approvers", label: "Approved by", format: "handles", required: false },
@@ -1014,7 +1130,8 @@ var ManualGitHost = class extends ManualBase {
1014
1130
  format: "handles",
1015
1131
  required: false
1016
1132
  },
1017
- { name: "checksPassing", label: "All checks pass", format: "yes-no", required: true }
1133
+ { name: "checksPassing", label: "All checks pass", format: "yes-no", required: true },
1134
+ { name: "merged", label: "Merged on the Git host", format: "yes-no", required: false }
1018
1135
  ],
1019
1136
  dependsOn: [open.id]
1020
1137
  });
@@ -1032,14 +1149,15 @@ var ManualGitHost = class extends ManualBase {
1032
1149
  if (pr.state === "open" || pr.state === "draft")
1033
1150
  throw new AdapterError(this.name, "conflict", `an open PR from ${input.head} already exists`);
1034
1151
  }
1035
- const number = existing.reduce((n, s) => Math.max(n, Number(s.inputs.number)), 0) + 1;
1152
+ const number = existing.reduce((n, s) => Math.max(n, localOf(s), recordedOf(s) ?? 0), 0) + 1;
1036
1153
  const change = this.opts.change ?? changeOfBranch(input.head);
1037
1154
  const proc = this.procedureFor("open-pull-request");
1038
1155
  const open = await this.step("createPullRequest", {
1039
1156
  slug: `open-pr-${input.head}`,
1040
1157
  action: "open-pull-request",
1041
1158
  key: `git-host|pr|${input.repo}|${input.head}|${number}`,
1042
- title: `Open a pull request from ${input.head} into ${input.base}`,
1159
+ // Ninth UX walk: the release PRs of three repos had one title on Home; the repo tells them apart.
1160
+ title: `Open a pull request in ${input.repo} from ${input.head} into ${input.base}`,
1043
1161
  where: `Git host: ${input.repo}, new pull request`,
1044
1162
  ...change ? { change } : {},
1045
1163
  ...proc ?? {},
@@ -1077,13 +1195,13 @@ var ManualGitHost = class extends ManualBase {
1077
1195
  const open = await this.find(repo, number);
1078
1196
  const change = open.change;
1079
1197
  await this.step("comment", {
1080
- slug: `comment-pr-${number}`,
1198
+ slug: prSlug("comment", open),
1081
1199
  action: "comment-pull-request",
1082
- key: `git-host|comment|${repo}|${number}|${shortHash(body)}`,
1083
- title: `Post a comment on PR ${number} (${open.inputs.title})`,
1200
+ key: `git-host|comment|${repo}|${localOf(open)}|${shortHash(body)}`,
1201
+ title: `Post a comment on ${prName(open)} (${open.inputs.title})`,
1084
1202
  where: `Git host: ${repo}, the pull request opened for step ${open.id}`,
1085
1203
  ...change ? { change } : {},
1086
- inputs: { repo, number },
1204
+ inputs: { repo, number: localOf(open) },
1087
1205
  fields: [{ name: "Comment", value: body }],
1088
1206
  instructions: ["Post the comment below on the pull request."],
1089
1207
  dependsOn: [open.id]
@@ -1104,13 +1222,13 @@ var ManualGitHost = class extends ManualBase {
1104
1222
  if (pr.state === "closed")
1105
1223
  return pr;
1106
1224
  await this.step("closePullRequest", {
1107
- slug: `close-pr-${number}`,
1225
+ slug: prSlug("close", open),
1108
1226
  action: "close-pull-request",
1109
- key: `git-host|close|${repo}|${number}`,
1110
- title: `Close PR ${number} (${open.inputs.title}) without merging`,
1227
+ key: `git-host|close|${repo}|${localOf(open)}`,
1228
+ title: `Close ${prName(open)} (${open.inputs.title}) without merging`,
1111
1229
  where: `Git host: ${repo}, ${pr.url}`,
1112
1230
  ...open.change ? { change: open.change } : {},
1113
- inputs: { repo, number },
1231
+ inputs: { repo, number: localOf(open) },
1114
1232
  fields: [{ name: "Pull request", value: pr.url }],
1115
1233
  instructions: [
1116
1234
  "The change went back to the product owner: close the pull request on the Git host without merging it, then mark this step done."
@@ -1128,19 +1246,21 @@ var ManualGitHost = class extends ManualBase {
1128
1246
  const blockers = mergeBlockers(pr);
1129
1247
  if (blockers.length > 0)
1130
1248
  throw new AdapterError(this.name, "conflict", `can't merge: ${blockers.join("; ")}`);
1249
+ const recorder = (await this.related(open, "report-pull-request")).filter((s) => s.state === "done" && s.recorded).sort((a2, b) => a2.recorded.at < b.recorded.at ? -1 : 1).at(-1)?.recorded?.by;
1250
+ const approvedBy = pr.reviews.filter((r) => r.state === "approved").map((r) => r.by).join(", ");
1131
1251
  const step = await this.step("merge", {
1132
- slug: `merge-pr-${number}`,
1252
+ slug: prSlug("merge", open),
1133
1253
  action: "merge-pull-request",
1134
- key: `git-host|merge|${repo}|${number}`,
1135
- title: `Merge PR ${number} (${open.inputs.title}) on the Git host`,
1254
+ key: `git-host|merge|${repo}|${localOf(open)}`,
1255
+ title: `Merge ${prName(open)} (${open.inputs.title}) on the Git host`,
1136
1256
  where: `Git host: ${repo}, ${pr.url}`,
1137
1257
  ...open.change ? { change: open.change } : {},
1138
- inputs: { repo, number },
1258
+ inputs: { repo, number: localOf(open) },
1139
1259
  fields: [
1140
1260
  { name: "Pull request", value: pr.url },
1141
1261
  {
1142
1262
  name: "Approved by",
1143
- value: pr.reviews.filter((r) => r.state === "approved").map((r) => r.by).join(", ")
1263
+ value: approvedBy && recorder ? `${approvedBy} (recorded by ${recorder})` : approvedBy
1144
1264
  }
1145
1265
  ],
1146
1266
  instructions: [
@@ -1150,16 +1270,16 @@ var ManualGitHost = class extends ManualBase {
1150
1270
  result: [{ name: "mergedBy", label: "Merged by", format: "handles", required: false }],
1151
1271
  dependsOn: [open.id]
1152
1272
  }, a);
1153
- throw new AdapterError(this.name, "unavailable", `a person merges PR ${number} on the Git host: do step ${step.id} (atticus todo), then sync again`, false);
1273
+ throw new AdapterError(this.name, "unavailable", `a person merges ${prName(open)} on the Git host: do step ${step.id} (atticus todo), then sync again`, false);
1154
1274
  }
1155
1275
  };
1156
1276
 
1157
1277
  // packages/adapters/dist/manual/read-only.js
1158
- import { readdir as readdir2, readFile as readFile2, stat as stat2 } from "node:fs/promises";
1159
- import { isAbsolute, join as join2, relative, sep } from "node:path";
1278
+ import { readdir as readdir3, readFile as readFile3, stat as stat2 } from "node:fs/promises";
1279
+ import { isAbsolute, join as join3, relative, sep } from "node:path";
1160
1280
  function folder(opts, value, fallback) {
1161
1281
  const v = value ?? fallback;
1162
- return isAbsolute(v) ? v : join2(opts.root ?? ".", v);
1282
+ return isAbsolute(v) ? v : join3(opts.root ?? ".", v);
1163
1283
  }
1164
1284
  var ManualWiki = class extends ManualBase {
1165
1285
  constructor(opts) {
@@ -1174,19 +1294,19 @@ var ManualWiki = class extends ManualBase {
1174
1294
  const walk = async (d) => {
1175
1295
  let entries;
1176
1296
  try {
1177
- entries = await readdir2(d, { withFileTypes: true });
1297
+ entries = await readdir3(d, { withFileTypes: true });
1178
1298
  } catch {
1179
1299
  return;
1180
1300
  }
1181
1301
  for (const e of entries.sort((a, b) => a.name < b.name ? -1 : 1)) {
1182
1302
  if (e.name.startsWith("."))
1183
1303
  continue;
1184
- const full = join2(d, e.name);
1304
+ const full = join3(d, e.name);
1185
1305
  if (e.isDirectory())
1186
1306
  await walk(full);
1187
- else if (/\.(md|markdown)$/i.test(e.name)) {
1307
+ else if (e.isFile() && /\.(md|markdown)$/i.test(e.name)) {
1188
1308
  const id = relative(root, full).split(sep).join("/");
1189
- const body = await readFile2(full, "utf8");
1309
+ const body = await readFile3(full, "utf8");
1190
1310
  const title = /^#\s+(.+)$/m.exec(body)?.[1]?.trim() ?? e.name.replace(/\.(md|markdown)$/i, "");
1191
1311
  out.push({
1192
1312
  id,
@@ -1227,7 +1347,7 @@ var ManualDesignTool = class extends ManualBase {
1227
1347
  async getFile(key) {
1228
1348
  this.journal.push({ method: "getFile" });
1229
1349
  try {
1230
- return JSON.parse(await readFile2(join2(this.dir(), `${key}.json`), "utf8"));
1350
+ return JSON.parse(await readFile3(join3(this.dir(), `${key}.json`), "utf8"));
1231
1351
  } catch {
1232
1352
  return this.notFound(`design file ${key}`, `export it as ${key}.json into ${this.dir()}`);
1233
1353
  }
@@ -1235,7 +1355,7 @@ var ManualDesignTool = class extends ManualBase {
1235
1355
  async renderFrame(key, frameId) {
1236
1356
  this.journal.push({ method: "renderFrame" });
1237
1357
  try {
1238
- return new Uint8Array(await readFile2(join2(this.dir(), key, `${frameId}.png`)));
1358
+ return new Uint8Array(await readFile3(join3(this.dir(), key, `${frameId}.png`)));
1239
1359
  } catch {
1240
1360
  return this.notFound(`frame ${frameId}`, `export it as ${key}/${frameId}.png into ${this.dir()}`);
1241
1361
  }
@@ -1714,6 +1834,7 @@ export {
1714
1834
  requireApproval,
1715
1835
  workItemsCsv,
1716
1836
  mergeBlockers,
1837
+ MockGitHost,
1717
1838
  fileStepStore,
1718
1839
  checkResult,
1719
1840
  StepError,