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

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 (273) hide show
  1. package/dist/bin.js +8 -4
  2. package/dist/chunk-265LWMOA.js +91 -0
  3. package/dist/chunk-26WBY34Y.js +37 -0
  4. package/dist/{chunk-UBBC2XSG.js → chunk-26Z7OGQW.js} +518 -93
  5. package/dist/chunk-2D7PWSOK.js +172 -0
  6. package/dist/{chunk-JCZIKA4C.js → chunk-2HH3UCZM.js} +4 -4
  7. package/dist/{chunk-GDLULHTC.js → chunk-2HTEMYTB.js} +12 -26
  8. package/dist/chunk-2UCRFXFZ.js +130 -0
  9. package/dist/{chunk-MVZVGYXH.js → chunk-2V2ZPQQU.js} +81 -13
  10. package/dist/{chunk-BOHJZTEQ.js → chunk-36RY7ZXM.js} +130 -71
  11. package/dist/{chunk-I3E7CX4H.js → chunk-37WE3LS2.js} +3 -3
  12. package/dist/{chunk-IPKHE5D6.js → chunk-3AQ2R5NL.js} +1520 -871
  13. package/dist/chunk-3G6S7LAA.js +43 -0
  14. package/dist/chunk-3J5I7ZOU.js +58 -0
  15. package/dist/{chunk-65NYPGRC.js → chunk-3LZ6P5EP.js} +1 -1
  16. package/dist/chunk-3SSTNB4E.js +191 -0
  17. package/dist/chunk-3TD6S4TC.js +49 -0
  18. package/dist/{chunk-3C7EYRFZ.js → chunk-3UTYPHN3.js} +1 -1
  19. package/dist/{chunk-G2B4ZQGH.js → chunk-3WON4G3M.js} +2 -2
  20. package/dist/{chunk-S3QNRWYR.js → chunk-42EPP7OB.js} +12 -12
  21. package/dist/chunk-455SYIIE.js +113 -0
  22. package/dist/{chunk-YISXLPHN.js → chunk-4B6BT75O.js} +166 -23
  23. package/dist/{chunk-C6EKFH7J.js → chunk-4CLK2RJO.js} +7 -7
  24. package/dist/chunk-4CYTJ5TZ.js +38 -0
  25. package/dist/{chunk-EYWIDJFU.js → chunk-4D62IZII.js} +5 -5
  26. package/dist/chunk-4FOAYLI4.js +328 -0
  27. package/dist/{chunk-7JUKDRSZ.js → chunk-4KNOJC6J.js} +294 -215
  28. package/dist/{chunk-YMZ3TNYB.js → chunk-4PYC2UGC.js} +2 -2
  29. package/dist/{chunk-27NKUS3X.js → chunk-4SLBCEPD.js} +2104 -726
  30. package/dist/chunk-4TKVU2I2.js +122 -0
  31. package/dist/{chunk-RUVFXE2L.js → chunk-4WXRPQDE.js} +448 -47
  32. package/dist/{chunk-7ZUIMTOU.js → chunk-5CMPVC3N.js} +24 -24
  33. package/dist/chunk-5G7ILBUG.js +66 -0
  34. package/dist/{chunk-HFQCFSJR.js → chunk-5PV7S2ZP.js} +3 -3
  35. package/dist/{chunk-FITWGOJ2.js → chunk-5QUOPNLN.js} +4 -4
  36. package/dist/{chunk-Z6LF7HQN.js → chunk-5TDRBOAV.js} +5 -5
  37. package/dist/{chunk-T6AIP7H5.js → chunk-5WERBKLE.js} +199 -63
  38. package/dist/{chunk-XPCM366L.js → chunk-62DLJSLV.js} +8 -8
  39. package/dist/{chunk-L24C55VN.js → chunk-64AADMTW.js} +99 -25
  40. package/dist/{chunk-K65BJIMT.js → chunk-67BP7HXL.js} +17 -17
  41. package/dist/chunk-6DQYZU2W.js +379 -0
  42. package/dist/{chunk-EDS2L2LD.js → chunk-6EXDI5GI.js} +52 -26
  43. package/dist/chunk-6FNAKCET.js +38 -0
  44. package/dist/{chunk-6IU67AEK.js → chunk-75ASLHBT.js} +21 -15
  45. package/dist/{chunk-A3GY6SOA.js → chunk-75ZOZFGH.js} +18 -18
  46. package/dist/{chunk-MGYZM27B.js → chunk-77O633L5.js} +49 -23
  47. package/dist/{chunk-GQ4N4WKF.js → chunk-7AB6OWTV.js} +3 -3
  48. package/dist/{chunk-M766ZJ6W.js → chunk-7CZHUZBL.js} +25 -25
  49. package/dist/{chunk-A7UPUQFY.js → chunk-7FHNFCHK.js} +643 -124
  50. package/dist/chunk-7FUIVIBG.js +415 -0
  51. package/dist/{chunk-6QSERWXH.js → chunk-7QPCGTPS.js} +21 -21
  52. package/dist/{chunk-LR3R6Z2A.js → chunk-A2G72UI4.js} +7 -7
  53. package/dist/{chunk-I4JRCD6M.js → chunk-AE4P57KK.js} +23 -17
  54. package/dist/{chunk-AVJDSJ2F.js → chunk-AHW3RY3X.js} +7 -7
  55. package/dist/chunk-AM6FP6JW.js +43 -0
  56. package/dist/{chunk-CSZ4C5N6.js → chunk-AOCWFA7T.js} +93 -10
  57. package/dist/{chunk-EPTBZ3GP.js → chunk-API5TOUB.js} +1 -1
  58. package/dist/{chunk-652QWTLZ.js → chunk-AZDITBCT.js} +3 -3
  59. package/dist/{chunk-DPUYDDQG.js → chunk-BA2HUMDN.js} +25 -3
  60. package/dist/chunk-BA3U7ALS.js +99 -0
  61. package/dist/{chunk-HVUPKCGJ.js → chunk-BC6KKZ67.js} +5 -5
  62. package/dist/{chunk-CKSITVS4.js → chunk-BEPCKDCP.js} +2554 -722
  63. package/dist/{chunk-3ALD2W2A.js → chunk-BPPU3PW7.js} +4 -4
  64. package/dist/{chunk-QRAOANID.js → chunk-BVWWPBKD.js} +21 -21
  65. package/dist/{chunk-ZDPAS56H.js → chunk-BXBCMGIQ.js} +7 -1
  66. package/dist/chunk-BXZ4PKIT.js +233 -0
  67. package/dist/chunk-C7CEK3KW.js +247 -0
  68. package/dist/chunk-CFH3QH26.js +29 -0
  69. package/dist/chunk-CG6CULP6.js +170 -0
  70. package/dist/chunk-CLD4RVTA.js +45 -0
  71. package/dist/{chunk-DKJA76CJ.js → chunk-CNPY4NTZ.js} +13 -13
  72. package/dist/chunk-CNU5Q2D5.js +575 -0
  73. package/dist/{chunk-T2UYZSCQ.js → chunk-COYN3UAN.js} +126 -23
  74. package/dist/{chunk-23W7VWKR.js → chunk-CPK7QSBG.js} +1360 -113
  75. package/dist/{chunk-4AK7IBVP.js → chunk-D2WSW4GU.js} +1 -1
  76. package/dist/{chunk-ABWHYWNI.js → chunk-D57MFJPP.js} +3 -3
  77. package/dist/chunk-D5KV5PSK.js +45 -0
  78. package/dist/chunk-D5MASS4I.js +48 -0
  79. package/dist/{chunk-7EOBHUMC.js → chunk-DCWN3HFV.js} +2 -2
  80. package/dist/{chunk-QSXK2RGH.js → chunk-DDJPM5YX.js} +2 -2
  81. package/dist/chunk-DN4A2Q2O.js +57 -0
  82. package/dist/{chunk-IHMLFRVV.js → chunk-DUPZPDCJ.js} +58 -16
  83. package/dist/{chunk-PRPPGYZG.js → chunk-E2VXBSIR.js} +4 -4
  84. package/dist/chunk-E57AOFYN.js +32 -0
  85. package/dist/{chunk-UGLN7QHV.js → chunk-ECLXZWAG.js} +12 -12
  86. package/dist/{chunk-5WG5YP4T.js → chunk-EDZ45WIR.js} +14 -14
  87. package/dist/chunk-EFCQSMXB.js +37 -0
  88. package/dist/{chunk-2ANOROX3.js → chunk-EZIN5E5B.js} +8 -8
  89. package/dist/{chunk-BWZ77RQT.js → chunk-F6H2RJ3N.js} +1 -1
  90. package/dist/{chunk-OLQJTJJU.js → chunk-FAJDKNSD.js} +7 -3
  91. package/dist/chunk-FGAGWYZB.js +47 -0
  92. package/dist/{chunk-4WBVUHXN.js → chunk-FLVZFTLQ.js} +18 -18
  93. package/dist/chunk-FQ6WH6PB.js +140 -0
  94. package/dist/{chunk-T6XQL73F.js → chunk-FRHD22WM.js} +61 -23
  95. package/dist/{chunk-XAKWMCXI.js → chunk-FVMPFCDS.js} +4 -4
  96. package/dist/{chunk-B2WLAWNJ.js → chunk-FY3QIRTL.js} +3 -3
  97. package/dist/{chunk-CPA6HPVR.js → chunk-FYBF5MB2.js} +15 -11
  98. package/dist/{chunk-V2YTAIQO.js → chunk-G5YJBNDZ.js} +21 -6
  99. package/dist/chunk-G6IQYM25.js +339 -0
  100. package/dist/chunk-G6X4YL4D.js +161 -0
  101. package/dist/{chunk-SJRGMG6A.js → chunk-GC2VK3JT.js} +25 -25
  102. package/dist/{chunk-SP2I63OO.js → chunk-GCS3FZOB.js} +77 -3
  103. package/dist/{chunk-6TACQN3N.js → chunk-GDZB57IU.js} +5 -5
  104. package/dist/chunk-GIFMBCTW.js +221 -0
  105. package/dist/{chunk-YY6ZQQBP.js → chunk-GK4PYVEC.js} +18 -8
  106. package/dist/{chunk-TDD55CJH.js → chunk-GNWAOVFQ.js} +6 -5
  107. package/dist/chunk-GS76RXQE.js +226 -0
  108. package/dist/{chunk-YYQN46FY.js → chunk-GSGIZ2OO.js} +23 -23
  109. package/dist/chunk-GUYL7RMK.js +60 -0
  110. package/dist/chunk-GX74YWR7.js +321 -0
  111. package/dist/chunk-HE3HRDNZ.js +122 -0
  112. package/dist/{chunk-AIOQPLA5.js → chunk-HGHRSF3E.js} +30 -12
  113. package/dist/{chunk-2RMYG36Q.js → chunk-HK3VOHIE.js} +198 -336
  114. package/dist/{chunk-QZSX3F7C.js → chunk-HS4BGB4G.js} +24 -22
  115. package/dist/{chunk-XY3P7JW7.js → chunk-HSZMPH5T.js} +834 -149
  116. package/dist/{chunk-L6SGQIR3.js → chunk-HWD4JPU7.js} +4 -2
  117. package/dist/{chunk-PCVDV3UZ.js → chunk-HXXP2NTE.js} +6 -6
  118. package/dist/{chunk-AA6YULYB.js → chunk-I2A3Z5AK.js} +7 -7
  119. package/dist/{chunk-N7IXEHK3.js → chunk-ICHDSWEY.js} +7 -7
  120. package/dist/chunk-IFFRGC3N.js +31 -0
  121. package/dist/{chunk-4BN53TG3.js → chunk-IFHDV6KQ.js} +31 -23
  122. package/dist/chunk-J2O4LFVI.js +80 -0
  123. package/dist/chunk-J5AAZ6OJ.js +161 -0
  124. package/dist/{chunk-ZMFPW66A.js → chunk-JAABT3DA.js} +3 -3
  125. package/dist/chunk-JITJP64K.js +34 -0
  126. package/dist/chunk-JKIGL3XQ.js +162 -0
  127. package/dist/chunk-JRVNXLZP.js +615 -0
  128. package/dist/chunk-JRXHON4E.js +41 -0
  129. package/dist/{chunk-DHPACDG7.js → chunk-JS6WMC3J.js} +8 -8
  130. package/dist/chunk-JU4QNJSR.js +62 -0
  131. package/dist/{chunk-PAMPPUR6.js → chunk-JYMIB5XY.js} +1697 -172
  132. package/dist/{chunk-RRTKKSLQ.js → chunk-JYTIHTIK.js} +8 -6
  133. package/dist/{chunk-3HI6Z55Y.js → chunk-K332XW7K.js} +324 -39
  134. package/dist/{chunk-GLUX4EEP.js → chunk-K6JB6XTX.js} +9 -9
  135. package/dist/chunk-KDAHXQIE.js +294 -0
  136. package/dist/chunk-KYZMRSPS.js +93 -0
  137. package/dist/chunk-L4CESDPB.js +22 -0
  138. package/dist/{chunk-NXFPS2LR.js → chunk-LEBR5NHW.js} +14 -14
  139. package/dist/chunk-LIJJCBQI.js +223 -0
  140. package/dist/{chunk-DE76JROX.js → chunk-LIRVU3HW.js} +16 -16
  141. package/dist/{chunk-JMSCMUCA.js → chunk-LN77DXBM.js} +145 -21
  142. package/dist/{chunk-JIITQXFB.js → chunk-LNWEWYCM.js} +2969 -788
  143. package/dist/{chunk-TANFV3MZ.js → chunk-LO3BLMVG.js} +3 -3
  144. package/dist/chunk-LPV6T362.js +250 -0
  145. package/dist/{chunk-2VHF7OXM.js → chunk-LQH4P45K.js} +1 -1
  146. package/dist/chunk-LU4MQVAL.js +41 -0
  147. package/dist/chunk-LWDNKE4X.js +273 -0
  148. package/dist/chunk-M4H2UG4R.js +218 -0
  149. package/dist/{chunk-6BVONWJ7.js → chunk-M6D2U3YM.js} +3 -3
  150. package/dist/chunk-MD7KUEJ3.js +514 -0
  151. package/dist/{chunk-66YVAGGM.js → chunk-MMZUN7ZO.js} +20 -20
  152. package/dist/chunk-MZGRDONP.js +916 -0
  153. package/dist/chunk-N3RUGTGV.js +39 -0
  154. package/dist/{chunk-JGZCG5VM.js → chunk-NCB6656Z.js} +7 -7
  155. package/dist/{chunk-4NDAAFQT.js → chunk-NRQ65LTQ.js} +7 -5
  156. package/dist/{chunk-UNM6ZOKP.js → chunk-NTAVOWYD.js} +145 -18
  157. package/dist/{chunk-3USYZGRF.js → chunk-NYOABJNK.js} +36 -27
  158. package/dist/{chunk-WVPJSRRJ.js → chunk-O4IKAIZ2.js} +24 -20
  159. package/dist/{chunk-D3PO4DOZ.js → chunk-ODMBPDDV.js} +51 -14
  160. package/dist/chunk-OKUB6RJA.js +533 -0
  161. package/dist/chunk-OMPENNWY.js +39 -0
  162. package/dist/chunk-OPQZISG3.js +25 -0
  163. package/dist/{chunk-5GGOLAKC.js → chunk-OV57AHCG.js} +26 -26
  164. package/dist/chunk-OZJ3JLYI.js +58 -0
  165. package/dist/{chunk-KEM4SDDP.js → chunk-P2VBXX7N.js} +11 -10
  166. package/dist/{chunk-S2A7YC3Q.js → chunk-PAINMSID.js} +10150 -1720
  167. package/dist/chunk-PKJAV25S.js +43 -0
  168. package/dist/{chunk-EBEW3XXQ.js → chunk-PNQLCRSS.js} +4 -4
  169. package/dist/{chunk-WY6PP6AA.js → chunk-PQH56YF6.js} +37 -5
  170. package/dist/chunk-PRTBPXYA.js +50 -0
  171. package/dist/{chunk-YEDDOYSC.js → chunk-PRW3HXM3.js} +2 -2
  172. package/dist/chunk-PRZ7KMWL.js +42 -0
  173. package/dist/{chunk-6M5NK3K3.js → chunk-PTQ3ZALZ.js} +42 -4
  174. package/dist/{chunk-5GDRCDQB.js → chunk-PUEWDYGP.js} +2 -2
  175. package/dist/chunk-Q26LDIUV.js +236 -0
  176. package/dist/{chunk-CR3MTH32.js → chunk-Q46QDDMF.js} +77 -7
  177. package/dist/chunk-QBNWF5ZU.js +19 -0
  178. package/dist/chunk-QE527XRY.js +342 -0
  179. package/dist/{chunk-CNUKCS2T.js → chunk-QHJJMZLX.js} +1518 -54
  180. package/dist/chunk-QJCJOMW3.js +425 -0
  181. package/dist/{chunk-VYDBJ73M.js → chunk-QKMRFNMA.js} +15 -15
  182. package/dist/chunk-QOOEYDNJ.js +317 -0
  183. package/dist/chunk-QSIDVFB7.js +45 -0
  184. package/dist/{chunk-R77KLRB3.js → chunk-RA33EYS4.js} +19 -18
  185. package/dist/{chunk-DFBCSHVT.js → chunk-RALY3E5U.js} +4 -4
  186. package/dist/{chunk-ZCJDOK2S.js → chunk-S2RY3BOD.js} +35 -21
  187. package/dist/chunk-S5LSDXV4.js +40 -0
  188. package/dist/chunk-SB5GRUFM.js +54 -0
  189. package/dist/chunk-SH27FYPF.js +150 -0
  190. package/dist/chunk-T74WQQGS.js +40 -0
  191. package/dist/{chunk-O3WI5KWW.js → chunk-TGVVUKTG.js} +2 -2
  192. package/dist/chunk-THN26IEF.js +48 -0
  193. package/dist/chunk-TJH2EUAZ.js +47 -0
  194. package/dist/{chunk-ZNCEKR4J.js → chunk-TQ4TG57V.js} +12 -8
  195. package/dist/{chunk-7FBGJFEE.js → chunk-TQTRWENN.js} +12 -12
  196. package/dist/{chunk-TYAID7B7.js → chunk-TSM6T6GQ.js} +23 -23
  197. package/dist/{chunk-DPZHZQKE.js → chunk-TW3KOSQK.js} +43 -10
  198. package/dist/{chunk-MC3H7736.js → chunk-TWQRPM76.js} +37 -4
  199. package/dist/chunk-TYD6I4CZ.js +109 -0
  200. package/dist/chunk-U3NBK4EU.js +420 -0
  201. package/dist/{chunk-6JCPI55B.js → chunk-UDXWIPCB.js} +47 -7
  202. package/dist/{chunk-MMOSZPWJ.js → chunk-UEVZZZU2.js} +4 -4
  203. package/dist/{chunk-JBTK5OP2.js → chunk-UF4UHCIG.js} +2 -2
  204. package/dist/{chunk-6JUBZBMW.js → chunk-UFE36WJH.js} +4 -4
  205. package/dist/{chunk-ONLS5QA5.js → chunk-URIKUID7.js} +12 -12
  206. package/dist/chunk-UYLBRRFK.js +1106 -0
  207. package/dist/chunk-UZACEG2C.js +515 -0
  208. package/dist/{chunk-7SW2QWLU.js → chunk-VAMHOHUU.js} +12 -12
  209. package/dist/{chunk-RZPYKDWS.js → chunk-VUVGX5L2.js} +1 -1
  210. package/dist/{chunk-Q4D5X7QB.js → chunk-VYOCPTUB.js} +44 -24
  211. package/dist/{chunk-CAQZUNOH.js → chunk-WAZEXEJH.js} +567 -3
  212. package/dist/chunk-WCEF7H6L.js +221 -0
  213. package/dist/{chunk-2DIQQJCB.js → chunk-WEOMJHPV.js} +12 -12
  214. package/dist/{chunk-FHH4I4ZV.js → chunk-WFU77T3A.js} +12 -6
  215. package/dist/chunk-WIWTJMMR.js +292 -0
  216. package/dist/{chunk-2BFCZ3RK.js → chunk-WNTIOBOG.js} +18 -18
  217. package/dist/{chunk-7WD63HU2.js → chunk-X2CUXTWU.js} +6 -6
  218. package/dist/chunk-X7EMBM5X.js +34 -0
  219. package/dist/chunk-XEQCQO66.js +33 -0
  220. package/dist/{chunk-F7HYOUFF.js → chunk-XG4WJHLQ.js} +20 -4
  221. package/dist/{chunk-EFHQ3TWP.js → chunk-XOL3GFW2.js} +171 -31
  222. package/dist/{chunk-NE2W3OO7.js → chunk-XQ3YZ4QW.js} +22 -22
  223. package/dist/{chunk-CEXSU4S6.js → chunk-Y6K3CJBU.js} +723 -85
  224. package/dist/{chunk-4RS5KZQD.js → chunk-YAH5IQAL.js} +5 -5
  225. package/dist/{chunk-64EQYWCA.js → chunk-YBOVNMHC.js} +51 -14
  226. package/dist/chunk-YF5DZCPN.js +1212 -0
  227. package/dist/chunk-YIGBJNH4.js +37 -0
  228. package/dist/{chunk-BKVWTZ6A.js → chunk-YJ3TBOTK.js} +25 -25
  229. package/dist/{chunk-Q5AMFEWD.js → chunk-YKTE2RU3.js} +2 -2
  230. package/dist/{chunk-7EKXJZ2Y.js → chunk-YO2PKTXT.js} +296 -37
  231. package/dist/{chunk-6J5OKA4Y.js → chunk-YTTNTQOX.js} +15 -15
  232. package/dist/{chunk-OT2O76OS.js → chunk-YWAKDNMH.js} +183 -33
  233. package/dist/{chunk-R6XF6UR3.js → chunk-YZDZOEV4.js} +4 -4
  234. package/dist/chunk-Z3QFH7YG.js +17 -0
  235. package/dist/{chunk-W5BVQF44.js → chunk-Z6VLC5X4.js} +17 -17
  236. package/dist/{chunk-HLJAXMM4.js → chunk-ZFQMMU5Y.js} +2 -2
  237. package/dist/{chunk-W3BQAZ3Q.js → chunk-ZKYRDV7A.js} +12 -12
  238. package/dist/{chunk-ZMAINWBW.js → chunk-ZLS6PU2O.js} +3 -3
  239. package/dist/{chunk-ZVM6AKKM.js → chunk-ZOSD4FXV.js} +3 -3
  240. package/dist/chunk-ZPDDEVQX.js +47 -0
  241. package/dist/{chunk-TXLH6WHQ.js → chunk-ZQLRCA2V.js} +11 -11
  242. package/dist/{chunk-HITVBIJS.js → chunk-ZX7235KR.js} +128 -54
  243. package/dist/{chunk-GT4I4ZWM.js → chunk-ZZFHLRQW.js} +18 -16
  244. package/dist/files.json +636 -364
  245. package/dist/packages/naysayer/constitution/constitution.yaml +19 -0
  246. package/dist/packages/sdk/npm/index.js +5614 -2343
  247. package/dist/packages/ui/dist/assets/{elk-api-tma0MCuh.js → elk-api-CowTnhEJ.js} +2 -2
  248. package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +1 -0
  249. package/dist/packages/ui/dist/assets/index-z2wv0d5d.js +47 -0
  250. package/dist/packages/ui/dist/index.html +2 -2
  251. package/package.json +4 -4
  252. package/dist/chunk-2BF2EYJV.js +0 -174
  253. package/dist/chunk-42EVSKME.js +0 -37
  254. package/dist/chunk-4BKGMUIK.js +0 -53
  255. package/dist/chunk-5KLGBXG5.js +0 -48
  256. package/dist/chunk-6BNC6EQ4.js +0 -41
  257. package/dist/chunk-6D2CQ5II.js +0 -41
  258. package/dist/chunk-7AVHLZGD.js +0 -45
  259. package/dist/chunk-D46WUV3T.js +0 -33
  260. package/dist/chunk-E36QOJMD.js +0 -47
  261. package/dist/chunk-FQXYPF7E.js +0 -147
  262. package/dist/chunk-GBRFVT63.js +0 -45
  263. package/dist/chunk-ICY36XCH.js +0 -34
  264. package/dist/chunk-J4K3KVLD.js +0 -131
  265. package/dist/chunk-JZU3H6UQ.js +0 -54
  266. package/dist/chunk-NN2ZQEB4.js +0 -38
  267. package/dist/chunk-PCOCACY3.js +0 -385
  268. package/dist/chunk-RTEYOSJY.js +0 -29
  269. package/dist/chunk-RVH5SUW5.js +0 -69
  270. package/dist/chunk-VN3DP4LQ.js +0 -43
  271. package/dist/chunk-XPTOBS2D.js +0 -48
  272. package/dist/packages/ui/dist/assets/index-B54fm9FQ.js +0 -29
  273. package/dist/packages/ui/dist/assets/index-DD_hufQz.css +0 -1
@@ -9,7 +9,10 @@ import {
9
9
  external_exports,
10
10
  require_dist,
11
11
  toCanonicalYaml
12
- } from "./chunk-S2A7YC3Q.js";
12
+ } from "./chunk-PAINMSID.js";
13
+ import {
14
+ renameRetrying
15
+ } from "./chunk-ODMBPDDV.js";
13
16
  import {
14
17
  __toESM
15
18
  } from "./chunk-TV45EUGM.js";
@@ -116,10 +119,190 @@ function workItemsCsv(stories, o = {}) {
116
119
  `).join("");
117
120
  }
118
121
 
122
+ // packages/adapters/dist/common.js
123
+ var Approval = external_exports.strictObject({
124
+ /** The person who approved: a handle from the Git host or directory. */
125
+ by: external_exports.string().min(1),
126
+ at: external_exports.iso.datetime({ offset: true }),
127
+ scope: external_exports.enum(["once", "standing"]).default("once"),
128
+ /** What was approved, e.g. a finding, hand-off PR or artifact path. */
129
+ ref: external_exports.string().min(1)
130
+ });
131
+ var AdapterError = class extends Error {
132
+ adapter;
133
+ code;
134
+ retryable;
135
+ constructor(adapter, code, message, retryable = code === "rate-limited" || code === "unavailable") {
136
+ super(`${adapter}: ${message}`);
137
+ this.adapter = adapter;
138
+ this.code = code;
139
+ this.retryable = retryable;
140
+ this.name = "AdapterError";
141
+ }
142
+ };
143
+ function requireApproval(adapter, approval, opts = {}) {
144
+ const r = Approval.safeParse(approval);
145
+ if (!r.success) {
146
+ throw new AdapterError(adapter, "not-approved", "this write needs a person's approval (by, at, ref)");
147
+ }
148
+ if (r.data.scope === "standing" && !opts.allowStanding) {
149
+ throw new AdapterError(adapter, "not-approved", "a standing approval can't cover this write; it needs approval each time");
150
+ }
151
+ return r.data;
152
+ }
153
+ var MockBase = class {
154
+ name;
155
+ journal = [];
156
+ failures = [];
157
+ constructor(name) {
158
+ this.name = name;
159
+ }
160
+ failNext(code, method) {
161
+ this.failures.push(method === void 0 ? { code } : { code, method });
162
+ }
163
+ /** Record a call and raise an injected failure if one is due. */
164
+ call(method, args, approval) {
165
+ const i = this.failures.findIndex((f) => f.method === void 0 || f.method === method);
166
+ if (i !== -1) {
167
+ const [f] = this.failures.splice(i, 1);
168
+ throw new AdapterError(this.name, f.code, `injected ${f.code} on ${method}`);
169
+ }
170
+ this.journal.push(approval ? { adapter: this.name, method, args, approval } : { adapter: this.name, method, args });
171
+ }
172
+ notFound(what) {
173
+ throw new AdapterError(this.name, "not-found", `${what} not found`);
174
+ }
175
+ };
176
+
177
+ // packages/adapters/dist/git-host.js
178
+ function mergeBlockers(pr) {
179
+ const out = [];
180
+ if (pr.state === "merged" || pr.state === "closed")
181
+ out.push(`the PR is ${pr.state}`);
182
+ if (pr.state === "draft")
183
+ out.push("the PR is a draft");
184
+ const latest = /* @__PURE__ */ new Map();
185
+ for (const r of pr.reviews)
186
+ if (r.state !== "commented")
187
+ latest.set(r.by, r.state);
188
+ if ([...latest.values()].includes("changes-requested"))
189
+ out.push("changes are requested");
190
+ const missing = pr.requiredReviewers.filter((r) => latest.get(r) !== "approved");
191
+ if (pr.requiredReviewers.length > 0 && missing.length === pr.requiredReviewers.length) {
192
+ out.push(`needs approval from ${pr.requiredReviewers.join(" or ")}`);
193
+ }
194
+ if (pr.requiredReviewers.length === 0 && ![...latest.values()].includes("approved"))
195
+ out.push("needs at least one approval");
196
+ const failing = pr.checks.filter((c) => c.status !== "passed").map((c) => `${c.name} ${c.status}`);
197
+ if (failing.length > 0)
198
+ out.push(`checks not passing: ${failing.join(", ")}`);
199
+ return out;
200
+ }
201
+ var MockGitHost = class extends MockBase {
202
+ repos = /* @__PURE__ */ new Map();
203
+ prs = /* @__PURE__ */ new Map();
204
+ numbers = /* @__PURE__ */ new Map();
205
+ constructor(repos = []) {
206
+ super("git-host");
207
+ for (const r of repos) {
208
+ const defaultBranch = r.defaultBranch ?? "main";
209
+ this.repos.set(r.repo, {
210
+ repo: r.repo,
211
+ defaultBranch,
212
+ protectedBranches: r.protectedBranches ?? [defaultBranch]
213
+ });
214
+ }
215
+ }
216
+ key = (repo, n) => `${repo}#${n}`;
217
+ async getRepo(repo) {
218
+ this.call("getRepo", [repo]);
219
+ return { ...this.repos.get(repo) ?? this.notFound(`repo ${repo}`) };
220
+ }
221
+ async getPullRequest(repo, number) {
222
+ this.call("getPullRequest", [repo, number]);
223
+ return structuredClone(this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`));
224
+ }
225
+ async listPullRequests(repo, q) {
226
+ this.call("listPullRequests", [repo, q]);
227
+ 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));
228
+ }
229
+ async createPullRequest(input, approval) {
230
+ const a = requireApproval(this.name, approval);
231
+ this.call("createPullRequest", [input], a);
232
+ const info = this.repos.get(input.repo) ?? this.notFound(`repo ${input.repo}`);
233
+ if (info.protectedBranches.includes(input.head)) {
234
+ throw new AdapterError(this.name, "invalid", `${input.head} is protected and can't be a PR's source branch`);
235
+ }
236
+ if ([...this.prs.values()].some((p2) => p2.repo === input.repo && p2.head === input.head && (p2.state === "open" || p2.state === "draft"))) {
237
+ throw new AdapterError(this.name, "conflict", `an open PR from ${input.head} already exists`);
238
+ }
239
+ const n = (this.numbers.get(input.repo) ?? 0) + 1;
240
+ this.numbers.set(input.repo, n);
241
+ const pr = {
242
+ repo: input.repo,
243
+ number: n,
244
+ url: `https://git.example.com/${input.repo}/pull/${n}`,
245
+ title: input.title,
246
+ body: input.body,
247
+ head: input.head,
248
+ base: input.base,
249
+ state: input.draft ? "draft" : "open",
250
+ reviews: [],
251
+ checks: [],
252
+ requiredReviewers: []
253
+ };
254
+ this.prs.set(this.key(input.repo, n), pr);
255
+ return structuredClone(pr);
256
+ }
257
+ async comment(repo, number, body, approval) {
258
+ const a = requireApproval(this.name, approval);
259
+ this.call("comment", [repo, number, body], a);
260
+ if (!this.prs.has(this.key(repo, number)))
261
+ this.notFound(`PR ${repo}#${number}`);
262
+ }
263
+ async merge(repo, number, approval) {
264
+ const a = requireApproval(this.name, approval);
265
+ this.call("merge", [repo, number], a);
266
+ const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
267
+ const blockers = mergeBlockers(pr);
268
+ if (blockers.length > 0)
269
+ throw new AdapterError(this.name, "conflict", `can't merge: ${blockers.join("; ")}`);
270
+ pr.state = "merged";
271
+ return structuredClone(pr);
272
+ }
273
+ async closePullRequest(repo, number, approval) {
274
+ const a = requireApproval(this.name, approval);
275
+ this.call("closePullRequest", [repo, number], a);
276
+ const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
277
+ if (pr.state === "merged")
278
+ throw new AdapterError(this.name, "conflict", `PR ${number} is merged and can't be closed`);
279
+ pr.state = "closed";
280
+ return structuredClone(pr);
281
+ }
282
+ /** Test helpers: what reviewers and CI would do on the host. */
283
+ review(repo, number, by, state) {
284
+ (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).reviews.push({
285
+ by,
286
+ state
287
+ });
288
+ }
289
+ setChecks(repo, number, checks) {
290
+ (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).checks = checks;
291
+ }
292
+ requireReviewers(repo, number, reviewers) {
293
+ (this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`)).requiredReviewers = reviewers;
294
+ }
295
+ markReady(repo, number) {
296
+ const pr = this.prs.get(this.key(repo, number)) ?? this.notFound(`PR ${repo}#${number}`);
297
+ if (pr.state === "draft")
298
+ pr.state = "open";
299
+ }
300
+ };
301
+
119
302
  // packages/adapters/dist/manual/steps.js
120
303
  var import_yaml = __toESM(require_dist(), 1);
121
304
  import { createHash } from "node:crypto";
122
- import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
305
+ import { mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
123
306
  import { dirname, join } from "node:path";
124
307
  var LEADING = [
125
308
  "schemaVersion",
@@ -170,7 +353,7 @@ async function writeAtomic(path, text) {
170
353
  const tmp = `${path}.tmp`;
171
354
  try {
172
355
  await writeFile(tmp, text, "utf8");
173
- await rename(tmp, path);
356
+ await renameRetrying(tmp, path);
174
357
  } catch (e) {
175
358
  await rm(tmp, { force: true });
176
359
  throw e;
@@ -456,186 +639,6 @@ function exportStep(step, format) {
456
639
  };
457
640
  }
458
641
 
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
642
  // packages/adapters/dist/read-only.js
640
643
  var MockWiki = class extends MockBase {
641
644
  pages = /* @__PURE__ */ new Map();
@@ -914,6 +917,16 @@ function changeOfBranch(branch) {
914
917
  const m = /^(?:handoff|task|change)\/([a-z0-9][a-z0-9._-]*)(?:\/|$)/.exec(branch);
915
918
  return m?.[1];
916
919
  }
920
+ var localOf = (open) => Number(open.inputs.number);
921
+ function recordedOf(open) {
922
+ const n = open.state === "done" ? Number(open.recorded?.values.number) : NaN;
923
+ return Number.isInteger(n) && n > 0 ? n : void 0;
924
+ }
925
+ var prName = (open) => {
926
+ const n = recordedOf(open);
927
+ return n ? `PR #${n}` : `the PR from ${String(open.inputs.head)}`;
928
+ };
929
+ var prSlug = (verb, open) => `${verb}-pr-${String(open.inputs.head)}`;
917
930
  var ManualGitHost = class extends ManualBase {
918
931
  constructor(opts) {
919
932
  super("git-host", "git-host", opts);
@@ -930,22 +943,38 @@ var ManualGitHost = class extends ManualBase {
930
943
  async prSteps(repo) {
931
944
  return (await this.opts.store.list({ system: "git-host", action: "open-pull-request" })).filter((s) => !repo || s.inputs.repo === repo);
932
945
  }
933
- async related(repo, number, action) {
946
+ /** The steps of one PR, by the number Atticus gave it (which never changes). */
947
+ async related(open, action) {
948
+ const repo = String(open.inputs.repo);
949
+ const number = localOf(open);
934
950
  return (await this.opts.store.list({ system: "git-host", action })).filter((s) => s.inputs.repo === repo && s.inputs.number === number);
935
951
  }
952
+ /**
953
+ * Review round 44: the number the PR goes by. The recorded one, unless it is the number Atticus
954
+ * gave another PR in the repo, or one recorded for another PR too: then the number Atticus gave
955
+ * it, so no number a caller holds ever names two PRs (new numbers skip recorded ones).
956
+ */
957
+ async numberOf(open) {
958
+ const local = localOf(open);
959
+ const rec = recordedOf(open);
960
+ if (rec === void 0 || rec === local)
961
+ return local;
962
+ const others = (await this.prSteps(String(open.inputs.repo))).filter((s) => s.id !== open.id);
963
+ return others.some((s) => localOf(s) === rec || recordedOf(s) === rec) ? local : rec;
964
+ }
936
965
  async toPr(open) {
937
966
  const repo = String(open.inputs.repo);
938
- const number = Number(open.inputs.number);
967
+ const number = localOf(open);
939
968
  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);
969
+ 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);
970
+ const merged = (await this.related(open, "merge-pull-request")).some((s) => s.state === "done") || reports.some((s) => s.recorded?.values.merged === true);
942
971
  const last = reports.at(-1)?.recorded?.values;
943
972
  const list = (v) => Array.isArray(v) ? v.map(String) : [];
944
973
  const reviews = [
945
974
  ...list(last?.approvers).map((by) => ({ by, state: "approved" })),
946
975
  ...list(last?.changesRequestedBy).map((by) => ({ by, state: "changes-requested" }))
947
976
  ];
948
- const closed = (await this.related(repo, number, "close-pull-request")).some((s) => s.state === "done");
977
+ const closed = (await this.related(open, "close-pull-request")).some((s) => s.state === "done");
949
978
  let state = open.state === "done" ? open.inputs.draft ? "draft" : "open" : "draft";
950
979
  if (open.state === "skipped" || closed)
951
980
  state = "closed";
@@ -953,7 +982,7 @@ var ManualGitHost = class extends ManualBase {
953
982
  state = "merged";
954
983
  return {
955
984
  repo,
956
- number,
985
+ number: await this.numberOf(open),
957
986
  url: typeof rec?.url === "string" ? rec.url : `manual://git-host/${repo}/pull/${number}`,
958
987
  title: String(open.inputs.title ?? ""),
959
988
  body: open.fields.find((f) => f.name === "Description")?.value ?? "",
@@ -965,13 +994,56 @@ var ManualGitHost = class extends ManualBase {
965
994
  requiredReviewers: []
966
995
  };
967
996
  }
997
+ /**
998
+ * The PR by the number Atticus gave it (which a caller may have kept from before the person
999
+ * recorded the real one, and which no other PR in the repo has), else by the recorded number
1000
+ * it goes by (numberOf). Review round 44: a recorded number equal to another PR's own number
1001
+ * finds that other PR, never this one, so a caller can't be handed another change's PR.
1002
+ */
968
1003
  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");
1004
+ const all = await this.prSteps(repo);
1005
+ const local = all.find((x) => localOf(x) === number);
1006
+ if (local)
1007
+ return local;
1008
+ for (const x of all)
1009
+ if (await this.numberOf(x) === number)
1010
+ return x;
1011
+ if (all.filter((x) => recordedOf(x) === number).length > 1)
1012
+ 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`);
1013
+ return this.notFound(`PR ${repo}#${number}`, "no manual step opened it");
971
1014
  }
972
1015
  async getPullRequest(repo, number) {
973
1016
  this.journal.push({ method: "getPullRequest" });
974
- return this.toPr(await this.find(repo, number));
1017
+ const open = await this.find(repo, number);
1018
+ const pr = await this.toPr(open);
1019
+ await this.settle(open, pr);
1020
+ return pr;
1021
+ }
1022
+ /**
1023
+ * Keeps a PR's steps in step with what was recorded: a reviews step still open on a PR that
1024
+ * reads merged or closed is skipped, saying why; a task's PR open on the host, with its reviews
1025
+ * recorded but not its merge, gets a step to record that it merged (a task's PR has no gate to
1026
+ * make a Merge step; a hand-off's gets one when it syncs). Steps only: nothing is sent.
1027
+ */
1028
+ async settle(open, pr) {
1029
+ const waiting = (await this.related(open, "report-pull-request")).filter((s) => s.state === "open");
1030
+ if (pr.state === "merged" || pr.state === "closed") {
1031
+ for (const s of waiting)
1032
+ await recordStep(this.opts.store, s.id, {
1033
+ by: "atticus",
1034
+ at: this.now(),
1035
+ skip: true,
1036
+ note: `${prName(open)} is ${pr.state} on the Git host: nothing left to record.`
1037
+ });
1038
+ return;
1039
+ }
1040
+ if (pr.state !== "open" || waiting.length > 0)
1041
+ return;
1042
+ if (!String(open.inputs.head).startsWith("task/"))
1043
+ return;
1044
+ if ((await this.related(open, "merge-pull-request")).some((s) => s.state === "open"))
1045
+ return;
1046
+ await this.askForReviews(open, open.change);
975
1047
  }
976
1048
  async listPullRequests(repo, q) {
977
1049
  this.journal.push({ method: "listPullRequests" });
@@ -986,15 +1058,16 @@ var ManualGitHost = class extends ManualBase {
986
1058
  /** A report step for the PR's reviews and checks, unless one is still open. */
987
1059
  async askForReviews(open, change) {
988
1060
  const repo = String(open.inputs.repo);
989
- const number = Number(open.inputs.number);
990
- const reports = await this.related(repo, number, "report-pull-request");
1061
+ const number = localOf(open);
1062
+ const reports = await this.related(open, "report-pull-request");
991
1063
  if (reports.some((s) => s.state === "open"))
992
1064
  return;
1065
+ const again = reports.some((s) => s.state === "done") && recordedOf(open) !== void 0;
993
1066
  await this.step("report", {
994
- slug: `report-pr-${number}`,
1067
+ slug: prSlug("report", open),
995
1068
  action: "report-pull-request",
996
1069
  key: `git-host|report|${repo}|${number}|${reports.length}`,
997
- title: `Record the reviews and checks on PR ${number} (${open.inputs.title})`,
1070
+ 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
1071
  where: `Git host: ${repo}, the pull request opened for step ${open.id}`,
999
1072
  ...change ? { change } : {},
1000
1073
  inputs: { repo, number },
@@ -1004,7 +1077,8 @@ var ManualGitHost = class extends ManualBase {
1004
1077
  ],
1005
1078
  instructions: [
1006
1079
  "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."
1080
+ "Name people by their handle on the Git host. Only what is recorded here counts for approval.",
1081
+ "Once it is merged on the Git host, record Merged on the Git host: yes here, and Atticus reads it as merged."
1008
1082
  ],
1009
1083
  result: [
1010
1084
  { name: "approvers", label: "Approved by", format: "handles", required: false },
@@ -1014,7 +1088,8 @@ var ManualGitHost = class extends ManualBase {
1014
1088
  format: "handles",
1015
1089
  required: false
1016
1090
  },
1017
- { name: "checksPassing", label: "All checks pass", format: "yes-no", required: true }
1091
+ { name: "checksPassing", label: "All checks pass", format: "yes-no", required: true },
1092
+ { name: "merged", label: "Merged on the Git host", format: "yes-no", required: false }
1018
1093
  ],
1019
1094
  dependsOn: [open.id]
1020
1095
  });
@@ -1032,14 +1107,15 @@ var ManualGitHost = class extends ManualBase {
1032
1107
  if (pr.state === "open" || pr.state === "draft")
1033
1108
  throw new AdapterError(this.name, "conflict", `an open PR from ${input.head} already exists`);
1034
1109
  }
1035
- const number = existing.reduce((n, s) => Math.max(n, Number(s.inputs.number)), 0) + 1;
1110
+ const number = existing.reduce((n, s) => Math.max(n, localOf(s), recordedOf(s) ?? 0), 0) + 1;
1036
1111
  const change = this.opts.change ?? changeOfBranch(input.head);
1037
1112
  const proc = this.procedureFor("open-pull-request");
1038
1113
  const open = await this.step("createPullRequest", {
1039
1114
  slug: `open-pr-${input.head}`,
1040
1115
  action: "open-pull-request",
1041
1116
  key: `git-host|pr|${input.repo}|${input.head}|${number}`,
1042
- title: `Open a pull request from ${input.head} into ${input.base}`,
1117
+ // Ninth UX walk: the release PRs of three repos had one title on Home; the repo tells them apart.
1118
+ title: `Open a pull request in ${input.repo} from ${input.head} into ${input.base}`,
1043
1119
  where: `Git host: ${input.repo}, new pull request`,
1044
1120
  ...change ? { change } : {},
1045
1121
  ...proc ?? {},
@@ -1077,13 +1153,13 @@ var ManualGitHost = class extends ManualBase {
1077
1153
  const open = await this.find(repo, number);
1078
1154
  const change = open.change;
1079
1155
  await this.step("comment", {
1080
- slug: `comment-pr-${number}`,
1156
+ slug: prSlug("comment", open),
1081
1157
  action: "comment-pull-request",
1082
- key: `git-host|comment|${repo}|${number}|${shortHash(body)}`,
1083
- title: `Post a comment on PR ${number} (${open.inputs.title})`,
1158
+ key: `git-host|comment|${repo}|${localOf(open)}|${shortHash(body)}`,
1159
+ title: `Post a comment on ${prName(open)} (${open.inputs.title})`,
1084
1160
  where: `Git host: ${repo}, the pull request opened for step ${open.id}`,
1085
1161
  ...change ? { change } : {},
1086
- inputs: { repo, number },
1162
+ inputs: { repo, number: localOf(open) },
1087
1163
  fields: [{ name: "Comment", value: body }],
1088
1164
  instructions: ["Post the comment below on the pull request."],
1089
1165
  dependsOn: [open.id]
@@ -1104,13 +1180,13 @@ var ManualGitHost = class extends ManualBase {
1104
1180
  if (pr.state === "closed")
1105
1181
  return pr;
1106
1182
  await this.step("closePullRequest", {
1107
- slug: `close-pr-${number}`,
1183
+ slug: prSlug("close", open),
1108
1184
  action: "close-pull-request",
1109
- key: `git-host|close|${repo}|${number}`,
1110
- title: `Close PR ${number} (${open.inputs.title}) without merging`,
1185
+ key: `git-host|close|${repo}|${localOf(open)}`,
1186
+ title: `Close ${prName(open)} (${open.inputs.title}) without merging`,
1111
1187
  where: `Git host: ${repo}, ${pr.url}`,
1112
1188
  ...open.change ? { change: open.change } : {},
1113
- inputs: { repo, number },
1189
+ inputs: { repo, number: localOf(open) },
1114
1190
  fields: [{ name: "Pull request", value: pr.url }],
1115
1191
  instructions: [
1116
1192
  "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 +1204,21 @@ var ManualGitHost = class extends ManualBase {
1128
1204
  const blockers = mergeBlockers(pr);
1129
1205
  if (blockers.length > 0)
1130
1206
  throw new AdapterError(this.name, "conflict", `can't merge: ${blockers.join("; ")}`);
1207
+ 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;
1208
+ const approvedBy = pr.reviews.filter((r) => r.state === "approved").map((r) => r.by).join(", ");
1131
1209
  const step = await this.step("merge", {
1132
- slug: `merge-pr-${number}`,
1210
+ slug: prSlug("merge", open),
1133
1211
  action: "merge-pull-request",
1134
- key: `git-host|merge|${repo}|${number}`,
1135
- title: `Merge PR ${number} (${open.inputs.title}) on the Git host`,
1212
+ key: `git-host|merge|${repo}|${localOf(open)}`,
1213
+ title: `Merge ${prName(open)} (${open.inputs.title}) on the Git host`,
1136
1214
  where: `Git host: ${repo}, ${pr.url}`,
1137
1215
  ...open.change ? { change: open.change } : {},
1138
- inputs: { repo, number },
1216
+ inputs: { repo, number: localOf(open) },
1139
1217
  fields: [
1140
1218
  { name: "Pull request", value: pr.url },
1141
1219
  {
1142
1220
  name: "Approved by",
1143
- value: pr.reviews.filter((r) => r.state === "approved").map((r) => r.by).join(", ")
1221
+ value: approvedBy && recorder ? `${approvedBy} (recorded by ${recorder})` : approvedBy
1144
1222
  }
1145
1223
  ],
1146
1224
  instructions: [
@@ -1150,7 +1228,7 @@ var ManualGitHost = class extends ManualBase {
1150
1228
  result: [{ name: "mergedBy", label: "Merged by", format: "handles", required: false }],
1151
1229
  dependsOn: [open.id]
1152
1230
  }, 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);
1231
+ 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
1232
  }
1155
1233
  };
1156
1234
 
@@ -1184,7 +1262,7 @@ var ManualWiki = class extends ManualBase {
1184
1262
  const full = join2(d, e.name);
1185
1263
  if (e.isDirectory())
1186
1264
  await walk(full);
1187
- else if (/\.(md|markdown)$/i.test(e.name)) {
1265
+ else if (e.isFile() && /\.(md|markdown)$/i.test(e.name)) {
1188
1266
  const id = relative(root, full).split(sep).join("/");
1189
1267
  const body = await readFile2(full, "utf8");
1190
1268
  const title = /^#\s+(.+)$/m.exec(body)?.[1]?.trim() ?? e.name.replace(/\.(md|markdown)$/i, "");
@@ -1714,6 +1792,7 @@ export {
1714
1792
  requireApproval,
1715
1793
  workItemsCsv,
1716
1794
  mergeBlockers,
1795
+ MockGitHost,
1717
1796
  fileStepStore,
1718
1797
  checkResult,
1719
1798
  StepError,