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

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 (279) hide show
  1. package/dist/bin.js +12 -7
  2. package/dist/{chunk-LYBNHMVZ.js → chunk-27AJAKX7.js} +3 -3
  3. package/dist/{chunk-KXITGYLF.js → chunk-2QPJ4E4Z.js} +2 -2
  4. package/dist/{chunk-EIPTLPFC.js → chunk-2UMSHYCB.js} +24 -24
  5. package/dist/{chunk-6PPOWY5E.js → chunk-2WUTCPPJ.js} +6 -6
  6. package/dist/{chunk-VNU26RCO.js → chunk-2YSD6E6V.js} +33 -32
  7. package/dist/{chunk-P32RUW3B.js → chunk-3424TLIJ.js} +39 -7
  8. package/dist/{chunk-2MMCFP5C.js → chunk-3ASYYMOX.js} +8 -8
  9. package/dist/{chunk-PKBHS4AA.js → chunk-3EWKO457.js} +48 -17
  10. package/dist/{chunk-J3IOLXWM.js → chunk-3EX5HCZD.js} +5 -5
  11. package/dist/{chunk-BDKC6H5P.js → chunk-3MYBT62N.js} +5 -5
  12. package/dist/{chunk-ZFL7NY4F.js → chunk-3UHV76UD.js} +69 -41
  13. package/dist/{chunk-Q4K5WB2W.js → chunk-3ZA3AK2D.js} +10 -10
  14. package/dist/{chunk-O7FDLW7L.js → chunk-4ETO2FXE.js} +5 -5
  15. package/dist/{chunk-AFWUDXEM.js → chunk-4FLNCK6Q.js} +26 -11
  16. package/dist/{chunk-745DAZ4L.js → chunk-4GAB5ZOZ.js} +901 -332
  17. package/dist/{chunk-3RM4UK6W.js → chunk-4MYHETJ3.js} +18 -18
  18. package/dist/chunk-4R3TO4VL.js +94 -0
  19. package/dist/chunk-5MYE42AP.js +43 -0
  20. package/dist/chunk-5O7U67UA.js +57 -0
  21. package/dist/{chunk-Y2EQNWKV.js → chunk-5OXKCH4Z.js} +31 -31
  22. package/dist/{chunk-O45HFTFS.js → chunk-5VTIWEWP.js} +2 -2
  23. package/dist/{chunk-UNAGJYET.js → chunk-63NFFAGI.js} +12 -12
  24. package/dist/{chunk-6ZJ5A7AF.js → chunk-66AQ2JIU.js} +9 -9
  25. package/dist/chunk-6JVPBGQG.js +50 -0
  26. package/dist/{chunk-VY72R2XZ.js → chunk-6NCPLIIP.js} +124 -2
  27. package/dist/{chunk-D73UEXYW.js → chunk-6NN36LVK.js} +3 -3
  28. package/dist/{chunk-7FTTA3HD.js → chunk-6R5VHR3N.js} +5 -5
  29. package/dist/{chunk-CADWLE2T.js → chunk-6RQOINER.js} +4 -4
  30. package/dist/{chunk-WG5U3F5V.js → chunk-6RYB3EET.js} +12 -12
  31. package/dist/{chunk-RXPJMEOW.js → chunk-6SNTHK43.js} +10 -10
  32. package/dist/{chunk-ZFFYNRIO.js → chunk-6Y4FXOMI.js} +24 -22
  33. package/dist/{chunk-SQV37XO2.js → chunk-6ZFF7XSL.js} +6 -6
  34. package/dist/{chunk-JA5FI3QV.js → chunk-6ZSYLZ7O.js} +3 -3
  35. package/dist/{chunk-JENSEMXF.js → chunk-73CC73I4.js} +1 -1
  36. package/dist/{chunk-2F4CYZKJ.js → chunk-73GFVW2L.js} +5 -5
  37. package/dist/{chunk-M3NANSDZ.js → chunk-73V2OONC.js} +15 -15
  38. package/dist/{chunk-WKUJ3KPV.js → chunk-75OMRKY2.js} +4 -4
  39. package/dist/{chunk-7BR7IPOH.js → chunk-7IFTSAHP.js} +8 -8
  40. package/dist/{chunk-OWNCM4ZN.js → chunk-7K5OH45X.js} +136 -16
  41. package/dist/{chunk-VCTWPLAO.js → chunk-7NQAGYK4.js} +8 -8
  42. package/dist/{chunk-O4GXGGBX.js → chunk-7XWJ6ED2.js} +12 -12
  43. package/dist/{chunk-MFR5OPBD.js → chunk-7XYLNQFO.js} +5 -5
  44. package/dist/{chunk-GCWRWSU7.js → chunk-7YQBDE5W.js} +4 -4
  45. package/dist/{chunk-QKUJMING.js → chunk-A4JXVO5O.js} +5 -5
  46. package/dist/{chunk-LKOR5UET.js → chunk-AFBCNZRZ.js} +24 -24
  47. package/dist/{chunk-BXYMYEJ4.js → chunk-AGOLEMHK.js} +13 -14
  48. package/dist/{chunk-AVTBS4OW.js → chunk-AHFQHPFF.js} +22 -22
  49. package/dist/{chunk-NY2XSR5K.js → chunk-APDN6UOR.js} +116 -18
  50. package/dist/chunk-AQRUQNFB.js +322 -0
  51. package/dist/{chunk-5NMKONLP.js → chunk-AVMWESFZ.js} +3 -2
  52. package/dist/chunk-B4AEL3RF.js +1011 -0
  53. package/dist/{chunk-H7KM7LZE.js → chunk-BAY4K55I.js} +11 -11
  54. package/dist/{chunk-XD75VZIH.js → chunk-BFL4PO64.js} +7 -7
  55. package/dist/{chunk-34S2WGOB.js → chunk-BFMTGNAQ.js} +5 -3
  56. package/dist/{chunk-SLXZOMA6.js → chunk-BP33TBLI.js} +4 -4
  57. package/dist/{chunk-IFKEI4SA.js → chunk-BUUJ7N4O.js} +11 -11
  58. package/dist/{chunk-EGQRREQH.js → chunk-BYBU2EIB.js} +26 -15
  59. package/dist/{chunk-SFUP7TTO.js → chunk-C6ORPLCN.js} +4 -4
  60. package/dist/{chunk-IVBOQAGB.js → chunk-CA3DKO4D.js} +24 -2
  61. package/dist/{chunk-57TDNMI3.js → chunk-CFUDAW3R.js} +15 -15
  62. package/dist/{chunk-FFTRTL6R.js → chunk-CJEBRJBS.js} +4 -4
  63. package/dist/{chunk-EPCJQQWD.js → chunk-CKVBDVIW.js} +4 -4
  64. package/dist/{chunk-FPJPLKDW.js → chunk-CMB7FXHJ.js} +38 -16
  65. package/dist/{chunk-INQHESFB.js → chunk-CQ7RF4QN.js} +4 -4
  66. package/dist/{chunk-63YRMR6J.js → chunk-CS4BMJLL.js} +5 -5
  67. package/dist/{chunk-BPK5P77O.js → chunk-CT6NINGR.js} +3 -3
  68. package/dist/chunk-CXTG6AWM.js +40 -0
  69. package/dist/{chunk-CXJ6FUKN.js → chunk-CZ2ZS7AT.js} +9 -4
  70. package/dist/{chunk-S4PMJU6H.js → chunk-D6BVLTDV.js} +85 -29
  71. package/dist/{chunk-M32BLWDH.js → chunk-DCRYOMTM.js} +12 -12
  72. package/dist/{chunk-REWWDVQB.js → chunk-DHKDH464.js} +4 -4
  73. package/dist/{chunk-2LGRMVCA.js → chunk-DSHRA72L.js} +10 -10
  74. package/dist/{chunk-THDMSZ3R.js → chunk-E3PDCQRH.js} +2765 -665
  75. package/dist/chunk-EHXDB3SA.js +25 -0
  76. package/dist/{chunk-BTGPE6CR.js → chunk-EMVZIOOD.js} +7 -7
  77. package/dist/{chunk-DOBQKHIF.js → chunk-ENH6Z4TY.js} +28 -27
  78. package/dist/{chunk-LGFL54FP.js → chunk-EVTI22PQ.js} +6 -2
  79. package/dist/{chunk-7MJSQTL5.js → chunk-EXJZBL5N.js} +20 -20
  80. package/dist/{chunk-N3XIYPU3.js → chunk-FBCVC2GJ.js} +12 -12
  81. package/dist/{chunk-UWOJLHFT.js → chunk-FJVUHQPS.js} +34 -23
  82. package/dist/{chunk-7IGKHZ4Z.js → chunk-FL344WQD.js} +218 -211
  83. package/dist/{chunk-IH2XURVQ.js → chunk-FMJYKLDY.js} +5 -5
  84. package/dist/chunk-FMR2D3AZ.js +41 -0
  85. package/dist/{chunk-Q2TECDIT.js → chunk-FPBUTZI5.js} +2201 -326
  86. package/dist/{chunk-PJSJPMJI.js → chunk-FQVSLBTV.js} +3 -3
  87. package/dist/{chunk-NXJ5URP6.js → chunk-FRAEQVYN.js} +23 -22
  88. package/dist/{chunk-RLDGWLQ7.js → chunk-FRCOKUU4.js} +7 -7
  89. package/dist/{chunk-DCZWQLYT.js → chunk-FSN6JFXB.js} +18 -15
  90. package/dist/{chunk-W7VWI2YH.js → chunk-FTLYXMHA.js} +5 -5
  91. package/dist/{chunk-7GJS6DNX.js → chunk-FVYZ4Y52.js} +11 -3
  92. package/dist/{chunk-CQDGOPGH.js → chunk-G6EFXTUO.js} +2 -2
  93. package/dist/{chunk-JB5LINEM.js → chunk-G7VBMOZH.js} +3 -3
  94. package/dist/{chunk-7ASNL4Q4.js → chunk-GM4EFHUX.js} +15 -15
  95. package/dist/chunk-GOZLTLRY.js +232 -0
  96. package/dist/chunk-GPNMSX5H.js +36 -0
  97. package/dist/{chunk-BQ4SQQC6.js → chunk-GUGQSIQM.js} +9 -9
  98. package/dist/{chunk-E3ISYXO3.js → chunk-HJQVUOUL.js} +12 -12
  99. package/dist/{chunk-MFHL5URL.js → chunk-HMWJWYE2.js} +16 -16
  100. package/dist/{chunk-YYY3AZFE.js → chunk-HMZ2DRBC.js} +2 -2
  101. package/dist/{chunk-C3RY6KU6.js → chunk-HRS5O7VV.js} +500 -163
  102. package/dist/{chunk-AJQ72EBM.js → chunk-HUGQZQ2K.js} +6 -6
  103. package/dist/{chunk-AJYXNTNZ.js → chunk-ICBGVVRI.js} +10 -10
  104. package/dist/{chunk-J2JAKCIW.js → chunk-IKAW2KJU.js} +17 -17
  105. package/dist/{chunk-OUBGGKDU.js → chunk-IMZFOMVX.js} +1 -1
  106. package/dist/{chunk-LDLL7LB3.js → chunk-ISG547IS.js} +22 -22
  107. package/dist/{chunk-GZY6RUZ6.js → chunk-IYNCSYU4.js} +5 -2
  108. package/dist/{chunk-H5HBGNXU.js → chunk-J25YOUIZ.js} +4 -4
  109. package/dist/chunk-J2CDBSFP.js +69 -0
  110. package/dist/chunk-J2H7YG3K.js +34 -0
  111. package/dist/{chunk-SFSPGFCV.js → chunk-J32IPTVQ.js} +20 -20
  112. package/dist/{chunk-BEVTIBRH.js → chunk-J4CPHJUL.js} +5 -5
  113. package/dist/{chunk-F3P7N7SF.js → chunk-JFFKHIM6.js} +1 -1
  114. package/dist/{chunk-RUGXBPWI.js → chunk-JMEWJPF2.js} +8 -8
  115. package/dist/{chunk-WERM6KPJ.js → chunk-JSP73CDW.js} +9 -4
  116. package/dist/{chunk-66PPNOON.js → chunk-JXAKYP45.js} +26 -25
  117. package/dist/{chunk-7JITZFJC.js → chunk-K4OXYSGS.js} +4 -4
  118. package/dist/{chunk-EHA7RMZ3.js → chunk-K4RNVDR4.js} +4 -4
  119. package/dist/{chunk-R44CYFPV.js → chunk-K757G7AD.js} +12 -12
  120. package/dist/{chunk-FUJM6RTF.js → chunk-KDJ2YKAZ.js} +7 -7
  121. package/dist/{chunk-QAXW2N3B.js → chunk-KT6Q44CA.js} +28 -30
  122. package/dist/{chunk-EBL2R3YG.js → chunk-KTNOBTV5.js} +4 -4
  123. package/dist/chunk-KVVNAUIG.js +66 -0
  124. package/dist/{chunk-X5F3Q5LV.js → chunk-L3RCQWVQ.js} +21 -18
  125. package/dist/{chunk-7IOWA5D5.js → chunk-LHH5KG5A.js} +13 -3
  126. package/dist/{chunk-TNR75OXT.js → chunk-LM45GMMB.js} +11 -8
  127. package/dist/{chunk-FSMSFDLD.js → chunk-LO6Y7OTG.js} +4 -4
  128. package/dist/{chunk-WF7B67YE.js → chunk-LPDTDFKA.js} +10 -10
  129. package/dist/{chunk-SU74NDMQ.js → chunk-LSHSDC6S.js} +17 -17
  130. package/dist/{chunk-LJXMYKZJ.js → chunk-LZVHP7CT.js} +5 -5
  131. package/dist/{chunk-3NWDLGG6.js → chunk-M3EOFSPY.js} +26 -26
  132. package/dist/chunk-MBYYQHPM.js +31 -0
  133. package/dist/{chunk-KQGURXFU.js → chunk-MEJ63LDG.js} +32 -11
  134. package/dist/{chunk-FZOJFH7Q.js → chunk-MH2ZK67S.js} +11 -11
  135. package/dist/{chunk-R7NYHMUU.js → chunk-MLGWSBF4.js} +5108 -3895
  136. package/dist/{chunk-WJF2CS6M.js → chunk-MNIPPBCT.js} +5 -5
  137. package/dist/{chunk-XERYFDB5.js → chunk-MWF4PXQR.js} +32 -31
  138. package/dist/{chunk-BO4KX37X.js → chunk-N2YX6JMY.js} +18 -18
  139. package/dist/{chunk-GUX3PTYM.js → chunk-NAPHHWW2.js} +3 -3
  140. package/dist/{chunk-UUU4CLJG.js → chunk-NC755EKE.js} +5 -1
  141. package/dist/{chunk-WMTRHUI5.js → chunk-NCLZJCXA.js} +21 -21
  142. package/dist/chunk-NKJDO4UC.js +39 -0
  143. package/dist/chunk-NOYOFYAJ.js +59 -0
  144. package/dist/{chunk-ZQ3ON2VQ.js → chunk-NROSSWMS.js} +5 -5
  145. package/dist/{chunk-UWMJKX5U.js → chunk-OBUB3H72.js} +12 -12
  146. package/dist/{chunk-VW62D6QE.js → chunk-OCQWSFJD.js} +7 -7
  147. package/dist/{chunk-UPOY4YSQ.js → chunk-OK6JGLE7.js} +12 -12
  148. package/dist/{chunk-TYQBFTBR.js → chunk-OPWGPQ2N.js} +5 -5
  149. package/dist/{chunk-PPD7HTDP.js → chunk-OSYHGGL3.js} +18 -18
  150. package/dist/chunk-OXXZZ7HQ.js +50 -0
  151. package/dist/{chunk-5BD2KYLE.js → chunk-P22EPEBR.js} +16 -16
  152. package/dist/chunk-P4YUT7W7.js +45 -0
  153. package/dist/chunk-PCCLVIDP.js +217 -0
  154. package/dist/{chunk-CMDXGQTS.js → chunk-PFULMC2D.js} +21 -20
  155. package/dist/chunk-PGAMTKBI.js +16 -0
  156. package/dist/{chunk-6MUGR4LS.js → chunk-PNSSE7JM.js} +93 -18
  157. package/dist/{chunk-HYU5VLGA.js → chunk-POEMZECG.js} +1 -1
  158. package/dist/{chunk-UCROWG2D.js → chunk-POSDBRKV.js} +23 -23
  159. package/dist/{chunk-KDNTAPLX.js → chunk-POSZFDSQ.js} +3 -3
  160. package/dist/{chunk-3NFFJL5D.js → chunk-PQQKZPBU.js} +1 -1
  161. package/dist/{chunk-4EURQWQD.js → chunk-PRMUQUWN.js} +10 -10
  162. package/dist/{chunk-MO6P2JZH.js → chunk-PT4USJNN.js} +7 -7
  163. package/dist/{chunk-BTY3HZBO.js → chunk-PWXB5GBB.js} +16 -16
  164. package/dist/{chunk-S7FCV7S5.js → chunk-PXW2RZGQ.js} +1 -1
  165. package/dist/{chunk-NDCF4R6S.js → chunk-Q367UGYN.js} +3 -3
  166. package/dist/{chunk-IUPG3UKI.js → chunk-QAVRDONY.js} +187 -123
  167. package/dist/{chunk-E6ZIEVOI.js → chunk-QBMLBCQH.js} +12 -12
  168. package/dist/{chunk-VZALIKIF.js → chunk-QLQIFJP3.js} +12 -12
  169. package/dist/{chunk-EMRIQUND.js → chunk-QLWDIKO4.js} +82 -27
  170. package/dist/{chunk-PMUAJGLI.js → chunk-QVVGJVVX.js} +16 -16
  171. package/dist/{chunk-LNBQOP7D.js → chunk-QX4MAMUG.js} +21 -21
  172. package/dist/{chunk-X3WY6MN3.js → chunk-QZWRPQTI.js} +6 -6
  173. package/dist/{chunk-ISUAAMGS.js → chunk-RCG5IAAT.js} +18 -11
  174. package/dist/chunk-RGZFOKVO.js +106 -0
  175. package/dist/{chunk-O5PXQR67.js → chunk-RLZFL76D.js} +4 -4
  176. package/dist/{chunk-UF4AZOZB.js → chunk-RPQITJNX.js} +5 -5
  177. package/dist/{chunk-NR2UJWOC.js → chunk-RQQYEDAC.js} +8 -8
  178. package/dist/chunk-RQSLHZ7T.js +36 -0
  179. package/dist/{chunk-UPS2DGFC.js → chunk-RRQUQAXP.js} +1 -1
  180. package/dist/chunk-RYQ4JCFT.js +65 -0
  181. package/dist/{chunk-JLUCKAEL.js → chunk-S35DIFJH.js} +17 -17
  182. package/dist/{chunk-UGUP3ZM6.js → chunk-S5GSQPIN.js} +9 -9
  183. package/dist/chunk-S5XFO4GY.js +42 -0
  184. package/dist/chunk-S6LW2RRC.js +25 -0
  185. package/dist/{chunk-W62H2XSO.js → chunk-S6W3D5GS.js} +23 -23
  186. package/dist/{chunk-CX4RZ2KS.js → chunk-S7GUZ45I.js} +3 -3
  187. package/dist/{chunk-L27SV425.js → chunk-SCT4CEF7.js} +20 -20
  188. package/dist/{chunk-VTZMAJ3W.js → chunk-SK5RVP7X.js} +8 -8
  189. package/dist/{chunk-JAVI7JSP.js → chunk-SRTUETF5.js} +23 -22
  190. package/dist/{chunk-MZCGSXVR.js → chunk-SVGGMBJI.js} +13 -13
  191. package/dist/{chunk-SDKLKB6I.js → chunk-SWNKO4C4.js} +32 -25
  192. package/dist/chunk-SYP56T2D.js +65 -0
  193. package/dist/{chunk-5SJZW52K.js → chunk-T33TPFGI.js} +22 -22
  194. package/dist/{chunk-ZJXLNDH4.js → chunk-T3FNG2H2.js} +12 -12
  195. package/dist/{chunk-BIGDQDHD.js → chunk-T6MAWL5P.js} +4 -4
  196. package/dist/{chunk-RGERPOIV.js → chunk-T6MX7WXM.js} +14 -11
  197. package/dist/{chunk-QFWA2DPH.js → chunk-T7IIEDA3.js} +5 -5
  198. package/dist/{chunk-Z5IA3WDR.js → chunk-TABH4RBZ.js} +156 -79
  199. package/dist/{chunk-6ZGLAACW.js → chunk-TDSCKP3V.js} +2 -2
  200. package/dist/{chunk-G6X77UJZ.js → chunk-TMFMXQEN.js} +21 -21
  201. package/dist/{chunk-P2V7QW4D.js → chunk-TNCF26JK.js} +11 -11
  202. package/dist/{chunk-2GF7OLF3.js → chunk-TUM52SOE.js} +19 -15
  203. package/dist/{chunk-PBPBMP2B.js → chunk-TV56QLLV.js} +3 -3
  204. package/dist/{chunk-SYV5LHML.js → chunk-TVQSXWWV.js} +33 -33
  205. package/dist/{chunk-VBTP56CE.js → chunk-TXNSQ24G.js} +9 -8
  206. package/dist/{chunk-ZX57KSEQ.js → chunk-UALE35WK.js} +3 -3
  207. package/dist/{chunk-42SIDKEU.js → chunk-UJF7PIMP.js} +26 -26
  208. package/dist/{chunk-ONUPY3H6.js → chunk-UMCDODBX.js} +24 -24
  209. package/dist/{chunk-JJF6HALY.js → chunk-UTPIFH4I.js} +3 -3
  210. package/dist/{chunk-O7XLYEFA.js → chunk-V7PEHQZU.js} +54 -22
  211. package/dist/{chunk-XI2LCCYQ.js → chunk-VJFXQISZ.js} +8 -8
  212. package/dist/{chunk-AFZ3QA6W.js → chunk-VJZI6KFP.js} +22 -22
  213. package/dist/{chunk-Q6DFNVRJ.js → chunk-VK7WYA64.js} +12 -12
  214. package/dist/{chunk-6OJQOPUN.js → chunk-VKTXFFOZ.js} +2 -2
  215. package/dist/{chunk-MG4ZL5RW.js → chunk-VNIN7Q6Q.js} +16 -16
  216. package/dist/{chunk-ZQXZ2SES.js → chunk-VRO7KSGL.js} +21 -21
  217. package/dist/{chunk-OHVTTOPS.js → chunk-W3AZE7LN.js} +3 -3
  218. package/dist/chunk-W4TNCEI4.js +44 -0
  219. package/dist/{chunk-X4CXA2IL.js → chunk-W5VYJWOG.js} +22 -22
  220. package/dist/{chunk-7DOR27HL.js → chunk-WF3RCZNO.js} +6 -6
  221. package/dist/{chunk-LGBMTVNT.js → chunk-WOMQQWTO.js} +5 -5
  222. package/dist/{chunk-2Q56PQPS.js → chunk-WXVTYLVH.js} +2 -2
  223. package/dist/{chunk-UOR2DTHH.js → chunk-WYGTSZHR.js} +16 -14
  224. package/dist/{chunk-IDKCWSM5.js → chunk-WZYM5M4U.js} +388 -104
  225. package/dist/{chunk-U76OWS3Q.js → chunk-X5ZHDSLU.js} +23 -23
  226. package/dist/chunk-X7XVMYIL.js +5 -0
  227. package/dist/{chunk-2IIMFOPM.js → chunk-X7ZKNSK4.js} +18 -18
  228. package/dist/{chunk-UF4GLFBX.js → chunk-XAPXKFIS.js} +22 -22
  229. package/dist/{chunk-LQJPN536.js → chunk-XF6TSZW2.js} +2 -2
  230. package/dist/{chunk-T6DQR5TV.js → chunk-XFDDJQT7.js} +12 -12
  231. package/dist/{chunk-OHNCWBKF.js → chunk-XGO74QWR.js} +4 -4
  232. package/dist/chunk-XLZAAAPX.js +43 -0
  233. package/dist/{chunk-2RLKFUUL.js → chunk-XMUWPA56.js} +23 -23
  234. package/dist/{chunk-JRBFANFE.js → chunk-XNFM6WUK.js} +15 -15
  235. package/dist/{chunk-LO6P2VYG.js → chunk-XOMEQVLK.js} +2 -2
  236. package/dist/{chunk-YHCMZC2J.js → chunk-Y2H7X3VI.js} +7 -7
  237. package/dist/{chunk-ZZK56BLP.js → chunk-Y5IE6YKD.js} +4 -4
  238. package/dist/{chunk-KFAVQZSX.js → chunk-YD3KTW4H.js} +12 -12
  239. package/dist/{chunk-LZ7NUC62.js → chunk-YDCOZOER.js} +18 -18
  240. package/dist/{chunk-LFGTYX5U.js → chunk-YERAAEO4.js} +17 -17
  241. package/dist/{chunk-BHT7QK4G.js → chunk-YHMPDIRG.js} +4 -4
  242. package/dist/{chunk-ZJFRMSJT.js → chunk-Z2D4P3R3.js} +12 -12
  243. package/dist/{chunk-O66DM6DJ.js → chunk-Z3H27OMV.js} +4 -4
  244. package/dist/{chunk-7UOMVMFG.js → chunk-Z3RAFU5B.js} +15 -15
  245. package/dist/{chunk-FFLNS6VP.js → chunk-ZENHDXRZ.js} +21 -17
  246. package/dist/{chunk-23XVSEV5.js → chunk-ZFHFC74B.js} +18 -18
  247. package/dist/{chunk-53T4O55J.js → chunk-ZJGCGKA4.js} +3 -3
  248. package/dist/{chunk-WXFLMQSR.js → chunk-ZLQEQR3D.js} +5 -5
  249. package/dist/{chunk-HNM2YQT2.js → chunk-ZNHQGG7J.js} +7 -7
  250. package/dist/{chunk-2Q5EDGEO.js → chunk-ZNTTW4IT.js} +5 -5
  251. package/dist/{chunk-ZQ7SKESZ.js → chunk-ZR6J4QFQ.js} +7 -7
  252. package/dist/{chunk-PAQ2AS5E.js → chunk-ZSNOILL5.js} +1 -1
  253. package/dist/files.json +563 -511
  254. package/dist/packages/sdk/npm/index.js +1043 -43
  255. package/dist/packages/ui/dist/assets/{elk-api-CIf-0gz5.js → elk-api-DxfAMOJq.js} +2 -2
  256. package/dist/packages/ui/dist/assets/index-Buit9TfP.js +62 -0
  257. package/dist/packages/ui/dist/assets/index-Jyc9dFeZ.css +1 -0
  258. package/dist/packages/ui/dist/index.html +2 -2
  259. package/package.json +4 -4
  260. package/dist/chunk-2SKB4O2E.js +0 -59
  261. package/dist/chunk-4U276ICE.js +0 -39
  262. package/dist/chunk-6H3Z5JHH.js +0 -64
  263. package/dist/chunk-C4R4JLHE.js +0 -40
  264. package/dist/chunk-CBGGOQWU.js +0 -82
  265. package/dist/chunk-DLOBCJL6.js +0 -48
  266. package/dist/chunk-GIW4ZVDB.js +0 -39
  267. package/dist/chunk-IP74LCOQ.js +0 -57
  268. package/dist/chunk-IPHHDDC6.js +0 -45
  269. package/dist/chunk-KJXD4PNL.js +0 -50
  270. package/dist/chunk-KN5BXMWN.js +0 -44
  271. package/dist/chunk-OMI6FPPN.js +0 -43
  272. package/dist/chunk-OTLDSZDV.js +0 -69
  273. package/dist/chunk-PSOFBQWB.js +0 -42
  274. package/dist/chunk-T4YPZIQN.js +0 -36
  275. package/dist/chunk-TUULXQRW.js +0 -420
  276. package/dist/chunk-WNKPRSGI.js +0 -36
  277. package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +0 -47
  278. package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +0 -1
  279. package/dist/{chunk-24XLDU72.js → chunk-PXMV2LLY.js} +3 -3
@@ -6,24 +6,26 @@ var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
6
6
  import {
7
7
  STORE_MARKER,
8
8
  addStoreReference,
9
+ archiveRefuses,
10
+ blockingIssues,
9
11
  readStoreMarker,
10
12
  readStoreVia
11
- } from "./chunk-UUU4CLJG.js";
13
+ } from "./chunk-NC755EKE.js";
12
14
  import {
13
15
  AdapterError,
14
16
  mergeBlockers,
15
17
  requireApproval
16
- } from "./chunk-7IGKHZ4Z.js";
18
+ } from "./chunk-FL344WQD.js";
17
19
  import {
18
20
  outsideProfileSystems,
19
21
  readCatalog
20
- } from "./chunk-J2JAKCIW.js";
22
+ } from "./chunk-IKAW2KJU.js";
21
23
  import {
22
24
  baseClonePath,
23
25
  createGit,
24
26
  readChangeRepos,
25
27
  writeChangeRepos
26
- } from "./chunk-PKBHS4AA.js";
28
+ } from "./chunk-3EWKO457.js";
27
29
  import {
28
30
  ChangeArtifact,
29
31
  ChangeLifecycle,
@@ -40,22 +42,25 @@ import {
40
42
  external_exports,
41
43
  fastGateOf,
42
44
  fastPathOf,
45
+ handleKey,
43
46
  handoffBranch,
44
47
  isAssistantResolution,
45
48
  listQuestions,
46
49
  loadOpenSpecSettings,
47
50
  loadOrgPack,
51
+ nextOwnersOf,
48
52
  openspecDirOf,
49
53
  orgPackDirOf,
50
54
  questionsRelOf,
51
55
  readFlow,
52
56
  readQuestion,
53
57
  specFlowFiles,
58
+ taskBranch,
54
59
  toCanonicalYaml
55
- } from "./chunk-Q2TECDIT.js";
60
+ } from "./chunk-FPBUTZI5.js";
56
61
  import {
57
62
  writeFileAtomic
58
- } from "./chunk-TUULXQRW.js";
63
+ } from "./chunk-B4AEL3RF.js";
59
64
  import {
60
65
  require_dist
61
66
  } from "./chunk-BQGDB6ZL.js";
@@ -1840,14 +1845,195 @@ function prApprovers(handoff2, approvers) {
1840
1845
  }
1841
1846
 
1842
1847
  // packages/changes/dist/assess.js
1843
- import { readFile as readFile9 } from "node:fs/promises";
1844
- import { join as join10 } from "node:path";
1848
+ import { readFile as readFile10 } from "node:fs/promises";
1849
+ import { join as join11 } from "node:path";
1845
1850
 
1846
1851
  // packages/changes/dist/release-prs.js
1852
+ var import_yaml8 = __toESM(require_dist(), 1);
1853
+ import { readFile as readFile9, writeFile } from "node:fs/promises";
1854
+ import { existsSync as existsSync2 } from "node:fs";
1855
+ import { join as join10 } from "node:path";
1856
+
1857
+ // packages/changes/dist/task-branches.js
1847
1858
  var import_yaml7 = __toESM(require_dist(), 1);
1848
- import { readFile as readFile8, writeFile } from "node:fs/promises";
1849
1859
  import { existsSync } from "node:fs";
1860
+ import { readdir as readdir5, readFile as readFile8 } from "node:fs/promises";
1850
1861
  import { join as join9 } from "node:path";
1862
+ var TASK_DECISION_FILE = "decision.yaml";
1863
+ var TaskDecision = external_exports.strictObject({
1864
+ schemaVersion: external_exports.literal(1),
1865
+ task: external_exports.string().min(1),
1866
+ branch: external_exports.string().min(1),
1867
+ /** The task branch's commit the person decided over. */
1868
+ commit: external_exports.string().regex(/^[0-9a-f]{7,64}$/),
1869
+ by: external_exports.string().min(1),
1870
+ at: external_exports.string().min(1),
1871
+ reason: external_exports.string().min(1)
1872
+ });
1873
+ async function taskRefs(root, id) {
1874
+ const dir = join9(changeFolder(root, id), "tasks");
1875
+ const out = [];
1876
+ for (const d of await readdir5(dir, { withFileTypes: true }).catch(() => [])) {
1877
+ if (!d.isDirectory())
1878
+ continue;
1879
+ const text = await readFile8(join9(dir, d.name, "task-run.yaml"), "utf8").catch(() => void 0);
1880
+ let y;
1881
+ try {
1882
+ y = text ? (0, import_yaml7.parse)(text) : void 0;
1883
+ } catch {
1884
+ y = void 0;
1885
+ }
1886
+ const task = String(y?.task ?? d.name);
1887
+ let branch;
1888
+ try {
1889
+ branch = typeof y?.branch === "string" ? y.branch : taskBranch(id, task);
1890
+ } catch {
1891
+ continue;
1892
+ }
1893
+ const pr = y?.pr;
1894
+ out.push({
1895
+ task,
1896
+ ...typeof y?.repo === "string" ? { repo: y.repo } : {},
1897
+ branch,
1898
+ ...typeof y?.state === "string" ? { state: y.state } : {},
1899
+ ...pr && typeof pr.number === "number" && typeof pr.url === "string" ? { pr: { number: pr.number, url: pr.url } } : {},
1900
+ ...y?.ticked ? { ticked: true } : {},
1901
+ ...typeof y?.commit === "string" && /^[0-9a-f]{7,64}$/.test(y.commit) ? { commit: y.commit } : {}
1902
+ });
1903
+ }
1904
+ return out;
1905
+ }
1906
+ function repoDir(root, r) {
1907
+ const dirs = [join9(root, r.worktree)];
1908
+ try {
1909
+ dirs.push(baseClonePath(root, r.id));
1910
+ } catch {
1911
+ }
1912
+ return dirs.find((d) => existsSync(d));
1913
+ }
1914
+ async function readTaskDecision(root, id, task) {
1915
+ const text = await readFile8(join9(changeFolder(root, id), "tasks", task, TASK_DECISION_FILE), "utf8").catch(() => void 0);
1916
+ if (text === void 0)
1917
+ return void 0;
1918
+ try {
1919
+ const r = TaskDecision.safeParse((0, import_yaml7.parse)(text));
1920
+ return r.success ? r.data : void 0;
1921
+ } catch {
1922
+ return void 0;
1923
+ }
1924
+ }
1925
+ async function unmergedTaskBranches(root, id, o = {}) {
1926
+ const cr = await readChangeRepos(root, id).catch(() => void 0);
1927
+ if (!cr?.repos.length)
1928
+ return [];
1929
+ const git = o.git ?? createGit({ timeoutMs: 3e4 });
1930
+ const remote = o.remote ?? "origin";
1931
+ const from = changeBranch(id);
1932
+ const records = await taskRefs(root, id);
1933
+ const out = [];
1934
+ const sha = (dir, ref) => git(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], dir).then((x) => x.stdout.trim() || void 0, () => void 0);
1935
+ for (const r of cr.repos) {
1936
+ const dir = repoDir(root, r);
1937
+ if (!dir)
1938
+ continue;
1939
+ const listed = await git(["for-each-ref", "--format=%(refname)", `refs/heads/task/${id}/`], dir).then((x) => x.stdout.split(/\r?\n/).map((l) => l.trim().replace(/^refs\/heads\//, "")).filter(Boolean), () => []);
1940
+ const branches = /* @__PURE__ */ new Map();
1941
+ for (const b of listed) {
1942
+ const mine = records.find((x) => x.branch === b && (!x.repo || x.repo === r.id));
1943
+ const other = records.find((x) => x.branch === b);
1944
+ branches.set(b, mine ?? { task: other?.task ?? b.split("/").at(-1), branch: b });
1945
+ }
1946
+ for (const x of records)
1947
+ if (x.repo === r.id && !branches.has(x.branch))
1948
+ branches.set(x.branch, x);
1949
+ const refs = [...branches.values()].filter((x) => (!x.repo || x.repo === r.id) && (!o.task || x.task === o.task));
1950
+ if (!refs.length)
1951
+ continue;
1952
+ const not = [];
1953
+ if (await sha(dir, `refs/heads/${from}`))
1954
+ not.push(`refs/heads/${from}`);
1955
+ if (!o.offline) {
1956
+ const onHost = await git(["ls-remote", "--heads", remote, `refs/heads/${from}`], dir).then((x) => x.stdout.trim().split(/\s+/)[0] || void 0, () => void 0);
1957
+ if (onHost && !await sha(dir, onHost))
1958
+ await git(["fetch", "-q", remote, `+refs/heads/${from}:refs/remotes/${remote}/${from}`], dir).catch(() => void 0);
1959
+ if (onHost && await sha(dir, onHost))
1960
+ not.push(onHost);
1961
+ } else if (await sha(dir, `refs/remotes/${remote}/${from}`))
1962
+ not.push(`refs/remotes/${remote}/${from}`);
1963
+ for (const x of refs) {
1964
+ const tip = await sha(dir, `refs/heads/${x.branch}`);
1965
+ if (!tip)
1966
+ continue;
1967
+ const merged = x.ticked && x.commit ? await sha(dir, x.commit) : void 0;
1968
+ if (x.ticked && !merged)
1969
+ continue;
1970
+ const decided = await readTaskDecision(root, id, x.task);
1971
+ if (decided && decided.branch === x.branch && sameSha(decided.commit, tip))
1972
+ continue;
1973
+ const commits = await git([
1974
+ "rev-list",
1975
+ "--count",
1976
+ `refs/heads/${x.branch}`,
1977
+ ...not.length || merged ? ["--not", ...not, ...merged ? [merged] : []] : []
1978
+ ], dir).then((y) => Number(y.stdout.trim()) || 0, () => 0);
1979
+ if (commits > 0)
1980
+ out.push({
1981
+ task: x.task,
1982
+ repo: r.id,
1983
+ branch: x.branch,
1984
+ commits,
1985
+ ...x.state ? { state: x.state } : {},
1986
+ ...x.pr ? { pr: x.pr } : {}
1987
+ });
1988
+ }
1989
+ }
1990
+ return out.sort((a, b) => a.task < b.task ? -1 : a.task > b.task ? 1 : 0);
1991
+ }
1992
+ var sameSha = (a, b) => a.startsWith(b) || b.startsWith(a);
1993
+ function unmergedTaskWords(id, u) {
1994
+ const from = changeBranch(id);
1995
+ const n = `${u.commits} commit${u.commits === 1 ? "" : "s"}`;
1996
+ const what = u.state === "pr-open" && u.pr ? `its PR #${u.pr.number} isn't merged yet: a person merges it on the Git host (${u.pr.url}), then Sync records it` : u.state === "unverified" || u.state === "needs-person" || u.state === "failed" ? `it was never built and raised: Build and raise PR on the Task board (or Run again), then merge its PR into ${from}` : `raise its PR (Raise the task's PR on the Task board) and merge it into ${from}`;
1997
+ return `Task ${u.task}'s branch ${u.branch} in ${u.repo} has ${n} not in ${from}, so its code isn't in the change: ${what}. If its work isn't needed, mark the task done with a reason.`;
1998
+ }
1999
+ async function taskBranchReasons(root, id, o = {}) {
2000
+ return (await unmergedTaskBranches(root, id, o)).map((u) => ({
2001
+ code: "task-not-merged",
2002
+ message: unmergedTaskWords(id, u)
2003
+ }));
2004
+ }
2005
+ async function recordTaskDecision(root, id, task, o) {
2006
+ const reason = o.reason.trim();
2007
+ if (!reason)
2008
+ throw new ChangeError("invalid", `Say why task ${task}'s work isn't needed in ${id}: a reason is recorded with the decision.`);
2009
+ const branch = taskBranch(id, task);
2010
+ const git = o.git ?? createGit({ timeoutMs: 3e4 });
2011
+ const cr = await readChangeRepos(root, id).catch(() => void 0);
2012
+ let commit;
2013
+ for (const r of cr?.repos ?? []) {
2014
+ const dir = repoDir(root, r);
2015
+ if (!dir)
2016
+ continue;
2017
+ commit = await git(["rev-parse", "--verify", "--quiet", `refs/heads/${branch}^{commit}`], dir).then((x) => x.stdout.trim() || void 0, () => void 0);
2018
+ if (commit)
2019
+ break;
2020
+ }
2021
+ if (!commit)
2022
+ throw new ChangeError("refused", `Task ${task} has no branch ${branch} here, so there is nothing to decide: mark it done.`);
2023
+ const d = TaskDecision.parse({
2024
+ schemaVersion: 1,
2025
+ task,
2026
+ branch,
2027
+ commit,
2028
+ by: o.by.trim(),
2029
+ at: o.at,
2030
+ reason
2031
+ });
2032
+ await writeFileAtomic(join9(changeFolder(root, id), "tasks", task, TASK_DECISION_FILE), toCanonicalYaml(d, ["schemaVersion", "task", "branch", "commit"]));
2033
+ return d;
2034
+ }
2035
+
2036
+ // packages/changes/dist/release-prs.js
1851
2037
  var RELEASE_PR_STATES = [
1852
2038
  "qa",
1853
2039
  "release-ready",
@@ -1878,11 +2064,11 @@ var NothingFile = external_exports.strictObject({
1878
2064
  });
1879
2065
  async function readReleaseFile(root, id) {
1880
2066
  const empty = { schemaVersion: 1, nothingToRelease: [] };
1881
- const text = await readFile8(join9(changeFolder(root, id), RELEASE_PRS_FILE), "utf8").catch(() => void 0);
2067
+ const text = await readFile9(join10(changeFolder(root, id), RELEASE_PRS_FILE), "utf8").catch(() => void 0);
1882
2068
  if (text === void 0)
1883
2069
  return empty;
1884
2070
  try {
1885
- const r = NothingFile.safeParse((0, import_yaml7.parse)(text));
2071
+ const r = NothingFile.safeParse((0, import_yaml8.parse)(text));
1886
2072
  return r.success ? r.data : empty;
1887
2073
  } catch {
1888
2074
  return empty;
@@ -1893,19 +2079,19 @@ async function readNothing(root, id) {
1893
2079
  }
1894
2080
  async function writeReleaseFile(root, id, nothing, merged) {
1895
2081
  const byRepo = (xs) => [...xs].sort((a, b) => a.repo < b.repo ? -1 : a.repo > b.repo ? 1 : 0);
1896
- await writeFile(join9(changeFolder(root, id), RELEASE_PRS_FILE), toCanonicalYaml(NothingFile.parse({
2082
+ await writeFile(join10(changeFolder(root, id), RELEASE_PRS_FILE), toCanonicalYaml(NothingFile.parse({
1897
2083
  schemaVersion: 1,
1898
2084
  nothingToRelease: byRepo(nothing),
1899
2085
  ...merged.length ? { merged: byRepo(merged) } : {}
1900
2086
  })), "utf8");
1901
2087
  }
1902
- function repoDir(root, r) {
1903
- const dirs = [join9(root, r.worktree)];
2088
+ function repoDir2(root, r) {
2089
+ const dirs = [join10(root, r.worktree)];
1904
2090
  try {
1905
2091
  dirs.push(baseClonePath(root, r.id));
1906
2092
  } catch {
1907
2093
  }
1908
- return dirs.find((d) => existsSync(d));
2094
+ return dirs.find((d) => existsSync2(d));
1909
2095
  }
1910
2096
  async function staleReleasePrs(root, id, o = {}) {
1911
2097
  const out = /* @__PURE__ */ new Set();
@@ -1921,23 +2107,24 @@ async function staleReleasePrs(root, id, o = {}) {
1921
2107
  const entry = merged.find((x) => x.repo === r.id && x.number === r.pr.number);
1922
2108
  if (!entry)
1923
2109
  continue;
1924
- const dir = repoDir(root, r);
2110
+ const dir = repoDir2(root, r);
1925
2111
  if (!dir)
1926
2112
  continue;
1927
- if (await movedPast(git, dir, remote, r.branch, entry.commit))
2113
+ if (await movedPast(git, dir, remote, r.branch, entry.commit, o.offline))
1928
2114
  out.add(r.id);
1929
2115
  }
1930
2116
  return out;
1931
2117
  }
1932
- async function movedPast(git, dir, remote, branch, commit) {
2118
+ var lastFetched = (git, dir, remote, branch) => git(["rev-parse", "--verify", "--quiet", `refs/remotes/${remote}/${branch}^{commit}`], dir).then((x) => x.stdout.trim() || void 0, () => void 0);
2119
+ async function movedPast(git, dir, remote, branch, commit, offline) {
1933
2120
  const ref = `refs/heads/${branch}`;
1934
2121
  const known = (sha) => git(["cat-file", "-e", `${sha}^{commit}`], dir).then(() => true, () => false);
1935
2122
  const here = await git(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], dir).then((x) => x.stdout.trim() || void 0, () => void 0);
1936
- const onHost = await git(["ls-remote", "--heads", remote, ref], dir).then((x) => x.stdout.trim().split(/\s+/)[0] || void 0, () => void 0);
1937
- if (onHost && !sameSha(onHost, commit) && !await known(onHost))
2123
+ const onHost = offline ? await lastFetched(git, dir, remote, branch) : await git(["ls-remote", "--heads", remote, ref], dir).then((x) => x.stdout.trim().split(/\s+/)[0] || void 0, () => void 0);
2124
+ if (!offline && onHost && !sameSha2(onHost, commit) && !await known(onHost))
1938
2125
  await git(["fetch", "-q", remote, `+${ref}:refs/remotes/${remote}/${branch}`], dir).catch(() => void 0);
1939
2126
  const ahead = async (sha) => {
1940
- if (!sha || sameSha(sha, commit))
2127
+ if (!sha || sameSha2(sha, commit))
1941
2128
  return false;
1942
2129
  if (!await known(sha) || !await known(commit))
1943
2130
  return true;
@@ -1961,17 +2148,19 @@ async function nothingToRelease(root, id, o = {}) {
1961
2148
  }
1962
2149
  return out;
1963
2150
  async function moved(r, commit) {
1964
- const dir = repoDir(root, r);
2151
+ const dir = repoDir2(root, r);
1965
2152
  if (!dir)
1966
2153
  return false;
1967
2154
  const ref = `refs/heads/${r.branch}`;
1968
2155
  const here = await git(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], dir).then((x) => x.stdout.trim() || void 0, () => void 0);
1969
- const onHost = await git(["ls-remote", "--heads", remote, ref], dir).then((x) => x.stdout.trim().split(/\s+/)[0] || void 0, () => void 0);
1970
- const at = (sha) => sha !== void 0 && (commit === void 0 || !sameSha(sha, commit));
2156
+ const fetched = o.offline ? await lastFetched(git, dir, remote, r.branch) : void 0;
2157
+ const behind = !!fetched && !!commit && await git(["merge-base", "--is-ancestor", fetched, commit], dir).then(() => true, () => false);
2158
+ const onHost = o.offline ? behind ? void 0 : fetched : await git(["ls-remote", "--heads", remote, ref], dir).then((x) => x.stdout.trim().split(/\s+/)[0] || void 0, () => void 0);
2159
+ const at = (sha) => sha !== void 0 && (commit === void 0 || !sameSha2(sha, commit));
1971
2160
  return at(here) || at(onHost);
1972
2161
  }
1973
2162
  }
1974
- var sameSha = (a, b) => a.startsWith(b) || b.startsWith(a);
2163
+ var sameSha2 = (a, b) => a.startsWith(b) || b.startsWith(a);
1975
2164
  var firstLine = (e) => (e instanceof Error ? e.message : String(e)).split("\n")[0].replace(/\.$/, "");
1976
2165
  var prOf = (pr, now) => ({
1977
2166
  url: pr.url,
@@ -2006,6 +2195,7 @@ async function raiseReleasePrs(root, id, o) {
2006
2195
  const before = file.nothingToRelease;
2007
2196
  const nothing = new Map(before.map((x) => [x.repo, x]));
2008
2197
  const stale = await staleReleasePrs(root, id, { git, remote });
2198
+ const unmerged = await unmergedTaskBranches(root, id, { git, remote });
2009
2199
  for (const r of repos) {
2010
2200
  const movedOn = r.pr?.state === "merged" && stale.has(r.id) ? `Release PR #${r.pr.number} merged before ${r.branch} moved on; this one carries what landed since.` : void 0;
2011
2201
  if (!live(r.pr) || movedOn)
@@ -2019,6 +2209,15 @@ async function raiseReleasePrs(root, id, o) {
2019
2209
  });
2020
2210
  continue;
2021
2211
  }
2212
+ const held = unmerged.filter((u) => u.repo === r.id);
2213
+ if (held.length) {
2214
+ rows.push({
2215
+ repo: r.id,
2216
+ outcome: "refused",
2217
+ message: `${r.id}: no release PR, since ${r.branch} lacks the code of ${held.length === 1 ? `task ${held[0].task}` : `tasks ${held.map((u) => u.task).join(", ")}`}. ${held.map((u) => unmergedTaskWords(id, u)).join(" ")}`
2218
+ });
2219
+ continue;
2220
+ }
2022
2221
  if (r.branch !== expected) {
2023
2222
  rows.push({
2024
2223
  repo: r.id,
@@ -2058,8 +2257,8 @@ async function raiseReleasePrs(root, id, o) {
2058
2257
  continue;
2059
2258
  }
2060
2259
  const notes = movedOn ? [movedOn] : [];
2061
- const dir = join9(root, r.worktree);
2062
- if (existsSync(dir)) {
2260
+ const dir = join10(root, r.worktree);
2261
+ if (existsSync2(dir)) {
2063
2262
  const onHost = await git(["ls-remote", "--heads", remote, `refs/heads/${r.branch}`], dir).then((x) => x.stdout.trim() ? "yes" : "no").catch((e) => {
2064
2263
  notes.push(`Atticus couldn't reach ${remote} (${firstLine(e)}): push ${r.branch} yourself if the host lacks it.`);
2065
2264
  return "unknown";
@@ -2222,7 +2421,7 @@ async function syncReleasePrs(root, id, o) {
2222
2421
  return { change: id, rows };
2223
2422
  }
2224
2423
  async function branchTip(root, r, g, remote) {
2225
- const dir = repoDir(root, r);
2424
+ const dir = repoDir2(root, r);
2226
2425
  if (!dir)
2227
2426
  return void 0;
2228
2427
  const git = g ?? createGit({ timeoutMs: 3e4 });
@@ -2246,11 +2445,11 @@ function buildOf(pr) {
2246
2445
  return "passed";
2247
2446
  }
2248
2447
  async function requireMergedPrs(root) {
2249
- const text = await readFile8(join9(orgPackDirOf(root), "process", "ci.yaml"), "utf8").catch(() => void 0);
2448
+ const text = await readFile9(join10(orgPackDirOf(root), "process", "ci.yaml"), "utf8").catch(() => void 0);
2250
2449
  if (text === void 0)
2251
2450
  return true;
2252
2451
  try {
2253
- const v = (0, import_yaml7.parse)(text)?.archive?.requireMergedPrs;
2452
+ const v = (0, import_yaml8.parse)(text)?.archive?.requireMergedPrs;
2254
2453
  return v !== false;
2255
2454
  } catch {
2256
2455
  return true;
@@ -2263,7 +2462,7 @@ async function releasePrReasons(root, id, o = {}) {
2263
2462
  const merged = await requireMergedPrs(root);
2264
2463
  const nothing = await nothingToRelease(root, id, o);
2265
2464
  const stale = await staleReleasePrs(root, id, o);
2266
- const out = [];
2465
+ const out = await taskBranchReasons(root, id, o);
2267
2466
  for (const r of cr.repos) {
2268
2467
  if (!r.pr && nothing.has(r.id))
2269
2468
  continue;
@@ -2335,7 +2534,11 @@ async function assess(ctx, change) {
2335
2534
  ...stageReasons.length ? [] : await checkMandatoryRounds(ctx.root, change, phaseGates(ctx, phase).filter((g) => mandatoryGates(ctx).includes(g))),
2336
2535
  // ADR 0184: go/no-go is decided over the release PRs, each repo's change branch into its
2337
2536
  // default branch, merged (unless the org pack's ci.yaml says archive.requireMergedPrs: false).
2338
- ...phase === "release" ? await releasePrReasons(ctx.root, change.id) : []
2537
+ // Both read refs here only (the host's branches as last fetched): an assessment runs on every
2538
+ // page load (Home's cockpit), which never reaches the Git host; Sync and the release steps do.
2539
+ ...phase === "release" ? await releasePrReasons(ctx.root, change.id, { offline: true }) : [],
2540
+ // App-only audit: Build ready waits for every task's work to be in the change branch.
2541
+ ...phase === "build" ? await taskBranchReasons(ctx.root, change.id, { offline: true }) : []
2339
2542
  ];
2340
2543
  const next = change.state === "returned" ? phaseState(phase) : nextState(type, phase);
2341
2544
  const live2 = change.state === "returned" ? void 0 : liveHandoff(change);
@@ -2378,7 +2581,7 @@ async function changeReport(root, id) {
2378
2581
  return { ...a, nextStep: nextStep(a, tasks), problems: ctx.problems };
2379
2582
  }
2380
2583
  async function taskTicks(root, id) {
2381
- const text = await readFile9(join10(changeFolder(root, id), "tasks.md"), "utf8").catch(() => "");
2584
+ const text = await readFile10(join11(changeFolder(root, id), "tasks.md"), "utf8").catch(() => "");
2382
2585
  const boxes = [...text.matchAll(/^\s*[-*]\s+\[([ xX])\]/gm)].map((m) => m[1] !== " ");
2383
2586
  return boxes.length ? { done: boxes.filter(Boolean).length, total: boxes.length } : void 0;
2384
2587
  }
@@ -2409,9 +2612,9 @@ function nextStep(a, tasks) {
2409
2612
  }
2410
2613
 
2411
2614
  // packages/changes/dist/new-change.js
2412
- var import_yaml8 = __toESM(require_dist(), 1);
2413
- import { mkdir, readFile as readFile10, writeFile as writeFile2 } from "node:fs/promises";
2414
- import { join as join11 } from "node:path";
2615
+ var import_yaml9 = __toESM(require_dist(), 1);
2616
+ import { mkdir, readFile as readFile11, writeFile as writeFile2 } from "node:fs/promises";
2617
+ import { join as join12 } from "node:path";
2415
2618
  var nowIso2 = () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
2416
2619
  var strip2 = (h) => h.startsWith("@") ? h.slice(1) : h;
2417
2620
  function windowsUnsafeName(id) {
@@ -2423,7 +2626,7 @@ function slugify(title) {
2423
2626
  }
2424
2627
  async function exists(path) {
2425
2628
  try {
2426
- await readFile10(path);
2629
+ await readFile11(path);
2427
2630
  return true;
2428
2631
  } catch {
2429
2632
  return false;
@@ -2431,7 +2634,7 @@ async function exists(path) {
2431
2634
  }
2432
2635
  async function defaultSchema(root) {
2433
2636
  try {
2434
- const cfg = (0, import_yaml8.parse)(await readFile10(join11(openspecDirOf(root), "config.yaml"), "utf8"));
2637
+ const cfg = (0, import_yaml9.parse)(await readFile11(join12(openspecDirOf(root), "config.yaml"), "utf8"));
2435
2638
  if (cfg && typeof cfg.schema === "string")
2436
2639
  return cfg.schema;
2437
2640
  } catch {
@@ -2455,17 +2658,17 @@ async function newChange(root, opts) {
2455
2658
  const now = opts.now ?? nowIso2();
2456
2659
  const by = strip2(opts.by);
2457
2660
  const dir = changeFolder(root, id);
2458
- if (opts.openspec && !await exists(join11(dir, ".openspec.yaml"))) {
2661
+ if (opts.openspec && !await exists(join12(dir, ".openspec.yaml"))) {
2459
2662
  await opts.openspec.newChange(id, { description: opts.title });
2460
2663
  } else {
2461
2664
  await mkdir(dir, { recursive: true });
2462
- if (!await exists(join11(dir, ".openspec.yaml")))
2463
- await writeFile2(join11(dir, ".openspec.yaml"), `schema: ${await defaultSchema(root)}
2665
+ if (!await exists(join12(dir, ".openspec.yaml")))
2666
+ await writeFile2(join12(dir, ".openspec.yaml"), `schema: ${await defaultSchema(root)}
2464
2667
  created: ${now.slice(0, 10)}
2465
2668
  `, "utf8");
2466
2669
  }
2467
- if (!await exists(join11(dir, "brief.md")))
2468
- await writeFileAtomic(join11(dir, "brief.md"), renderTemplate(template, {
2670
+ if (!await exists(join12(dir, "brief.md")))
2671
+ await writeFileAtomic(join12(dir, "brief.md"), renderTemplate(template, {
2469
2672
  title: opts.title,
2470
2673
  id,
2471
2674
  type: type.id,
@@ -2505,7 +2708,7 @@ created: ${now.slice(0, 10)}
2505
2708
  // packages/changes/dist/publish.js
2506
2709
  import { rm } from "node:fs/promises";
2507
2710
  import { randomUUID } from "node:crypto";
2508
- import { join as join12, resolve } from "node:path";
2711
+ import { join as join13, resolve } from "node:path";
2509
2712
  function gitHandoffPublisher(opts = {}) {
2510
2713
  const remote = opts.remote ?? "origin";
2511
2714
  const env = opts.env ?? process.env;
@@ -2539,7 +2742,7 @@ function gitHandoffPublisher(opts = {}) {
2539
2742
  "--quiet",
2540
2743
  `refs/remotes/${remote}/${base}^{commit}`
2541
2744
  ]) ?? await out(["rev-parse", "--verify", `refs/heads/${base}^{commit}`]);
2542
- const index = join12(gitDir, `atticus-handoff-index-${process.pid}-${randomUUID()}`);
2745
+ const index = join13(gitDir, `atticus-handoff-index-${process.pid}-${randomUUID()}`);
2543
2746
  const staged = createGit({ env: { ...env, GIT_INDEX_FILE: index } });
2544
2747
  try {
2545
2748
  await staged(["read-tree", start], root);
@@ -2548,8 +2751,8 @@ function gitHandoffPublisher(opts = {}) {
2548
2751
  const tree = (await staged(["write-tree"], root)).stdout.trim();
2549
2752
  const startTree = await out(["rev-parse", `${start}^{tree}`]);
2550
2753
  const commit = tree === startTree ? start : await out(["commit-tree", tree, "-p", start, "-m", message]);
2551
- await out(["push", "--quiet", remote, `${commit}:refs/heads/${branch}`]);
2552
2754
  await keepLocalBranch(out, tryOut, branch, start, commit);
2755
+ await out(["push", "--quiet", remote, `${commit}:refs/heads/${branch}`]);
2553
2756
  return { commit, changed: commit !== onRemote };
2554
2757
  } finally {
2555
2758
  await rm(index, { force: true });
@@ -2558,6 +2761,23 @@ function gitHandoffPublisher(opts = {}) {
2558
2761
  }
2559
2762
  }
2560
2763
  var queue = /* @__PURE__ */ new Map();
2764
+ async function handoffBranchPushed(root, branch, o = {}) {
2765
+ const git = createGit({ env: o.env ?? process.env });
2766
+ const sha = (ref) => git(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`], root).then((x) => x.stdout.trim() || void 0, () => void 0);
2767
+ const here = await sha(`refs/heads/${branch}`);
2768
+ if (!here)
2769
+ return true;
2770
+ return await sha(`refs/remotes/${o.remote ?? "origin"}/${branch}`) === here;
2771
+ }
2772
+ async function pushHandoffBranch(root, branch, o) {
2773
+ requireApproval("git", o.approval);
2774
+ if (!/^handoff\//.test(branch))
2775
+ throw new Error(`${branch} isn't a hand-off branch`);
2776
+ const git = createGit({ env: o.env ?? process.env });
2777
+ const commit = (await git(["rev-parse", "--verify", `refs/heads/${branch}^{commit}`], root)).stdout.trim();
2778
+ await git(["push", "--quiet", o.remote ?? "origin", `refs/heads/${branch}:refs/heads/${branch}`], root);
2779
+ return { branch, commit };
2780
+ }
2561
2781
  async function keepLocalBranch(out, tryOut, branch, start, commit) {
2562
2782
  const ref = `refs/heads/${branch}`;
2563
2783
  const local = await tryOut(["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]);
@@ -2577,13 +2797,13 @@ async function keepLocalBranch(out, tryOut, branch, start, commit) {
2577
2797
  }
2578
2798
 
2579
2799
  // packages/changes/dist/handoff.js
2580
- import { readdir as readdir6, readFile as readFile12 } from "node:fs/promises";
2581
- import { join as join14 } from "node:path";
2800
+ import { readdir as readdir7, readFile as readFile13 } from "node:fs/promises";
2801
+ import { join as join15 } from "node:path";
2582
2802
 
2583
2803
  // packages/changes/dist/drafted.js
2584
- var import_yaml9 = __toESM(require_dist(), 1);
2585
- import { mkdir as mkdir2, readdir as readdir5, readFile as readFile11, rm as rm2 } from "node:fs/promises";
2586
- import { dirname, join as join13, relative, sep } from "node:path";
2804
+ var import_yaml10 = __toESM(require_dist(), 1);
2805
+ import { mkdir as mkdir2, readdir as readdir6, readFile as readFile12, rm as rm2 } from "node:fs/promises";
2806
+ import { dirname, join as join14, relative, sep } from "node:path";
2587
2807
  var CAPTURE_SCHEMA_VERSION = 1;
2588
2808
  var DraftCapture = external_exports.object({
2589
2809
  schemaVersion: external_exports.literal(CAPTURE_SCHEMA_VERSION),
@@ -2658,7 +2878,7 @@ var sameText = (text, recorded) => sha256(text) === recorded || sha256(text.repl
2658
2878
  async function walk2(dir, rel = "") {
2659
2879
  let entries;
2660
2880
  try {
2661
- entries = await readdir5(join13(dir, rel), { withFileTypes: true });
2881
+ entries = await readdir6(join14(dir, rel), { withFileTypes: true });
2662
2882
  } catch {
2663
2883
  return [];
2664
2884
  }
@@ -2803,7 +3023,7 @@ async function captureHandoff(input) {
2803
3023
  } else {
2804
3024
  const texts = await Promise.all(recorded.map(async (r) => [
2805
3025
  r,
2806
- await readFile11(join13(folder, ...r.path.split("/")), "utf8").catch(() => void 0)
3026
+ await readFile12(join14(folder, ...r.path.split("/")), "utf8").catch(() => void 0)
2807
3027
  ]));
2808
3028
  if (texts.every(([r, t]) => t !== void 0 && sameText(t, r.sha256))) {
2809
3029
  from = "working-tree";
@@ -2867,10 +3087,10 @@ async function captureHandoff(input) {
2867
3087
  } : {}
2868
3088
  };
2869
3089
  const p = capturePaths(name);
2870
- await rm2(join13(folder, ...p.drafted.split("/")), { recursive: true, force: true });
2871
- await rm2(join13(folder, ...p.merged.split("/")), { recursive: true, force: true });
3090
+ await rm2(join14(folder, ...p.drafted.split("/")), { recursive: true, force: true });
3091
+ await rm2(join14(folder, ...p.merged.split("/")), { recursive: true, force: true });
2872
3092
  const put = async (base, rel, text) => {
2873
- const f = join13(folder, ...base.split("/"), ...rel.split("/"));
3093
+ const f = join14(folder, ...base.split("/"), ...rel.split("/"));
2874
3094
  await mkdir2(dirname(f), { recursive: true });
2875
3095
  await writeFileAtomic(f, text);
2876
3096
  };
@@ -2879,37 +3099,37 @@ async function captureHandoff(input) {
2879
3099
  if (state === "captured")
2880
3100
  for (const [rel, t] of mergedFiles)
2881
3101
  await put(p.merged, rel, t);
2882
- await mkdir2(join13(folder, "stage"), { recursive: true });
2883
- await writeFileAtomic(join13(folder, ...p.capture.split("/")), HEADER + (0, import_yaml9.stringify)(capture, { lineWidth: 0 }));
3102
+ await mkdir2(join14(folder, "stage"), { recursive: true });
3103
+ await writeFileAtomic(join14(folder, ...p.capture.split("/")), HEADER + (0, import_yaml10.stringify)(capture, { lineWidth: 0 }));
2884
3104
  return { capture, file: p.capture };
2885
3105
  }
2886
3106
  async function readFolderFiles(dir) {
2887
3107
  const out = /* @__PURE__ */ new Map();
2888
3108
  for (const f of await walk2(dir))
2889
- out.set(f, (await readFile11(join13(dir, ...f.split("/")), "utf8")).replace(/\r\n/g, "\n"));
3109
+ out.set(f, (await readFile12(join14(dir, ...f.split("/")), "utf8")).replace(/\r\n/g, "\n"));
2890
3110
  return out;
2891
3111
  }
2892
3112
  async function changeFolders(root) {
2893
- const base = join13(root, ...changesRelOf(root).split("/"));
3113
+ const base = join14(root, ...changesRelOf(root).split("/"));
2894
3114
  const out = [];
2895
- const list = async (dir) => (await readdir5(dir, { withFileTypes: true }).catch(() => [])).filter((e) => e.isDirectory()).map((e) => e.name).sort();
3115
+ const list = async (dir) => (await readdir6(dir, { withFileTypes: true }).catch(() => [])).filter((e) => e.isDirectory()).map((e) => e.name).sort();
2896
3116
  for (const name of await list(base)) {
2897
3117
  if (name === "archive")
2898
- for (const a of await list(join13(base, "archive")))
2899
- out.push(join13(base, "archive", a));
3118
+ for (const a of await list(join14(base, "archive")))
3119
+ out.push(join14(base, "archive", a));
2900
3120
  else
2901
- out.push(join13(base, name));
3121
+ out.push(join14(base, name));
2902
3122
  }
2903
3123
  return out;
2904
3124
  }
2905
3125
  async function readDraftPairs(root) {
2906
3126
  const out = [];
2907
3127
  for (const folder of await changeFolders(root)) {
2908
- const names = (await readdir5(join13(folder, "stage")).catch(() => [])).filter((f) => f.endsWith(".capture.yaml")).sort();
3128
+ const names = (await readdir6(join14(folder, "stage")).catch(() => [])).filter((f) => f.endsWith(".capture.yaml")).sort();
2909
3129
  for (const f of names) {
2910
3130
  let capture;
2911
3131
  try {
2912
- capture = DraftCapture.parse((0, import_yaml9.parse)(await readFile11(join13(folder, "stage", f), "utf8")));
3132
+ capture = DraftCapture.parse((0, import_yaml10.parse)(await readFile12(join14(folder, "stage", f), "utf8")));
2913
3133
  } catch {
2914
3134
  continue;
2915
3135
  }
@@ -2917,8 +3137,8 @@ async function readDraftPairs(root) {
2917
3137
  out.push({
2918
3138
  capture,
2919
3139
  folder: relative(root, folder).split(sep).join("/"),
2920
- drafted: await readFolderFiles(join13(folder, ...p.drafted.split("/"))),
2921
- merged: await readFolderFiles(join13(folder, ...p.merged.split("/")))
3140
+ drafted: await readFolderFiles(join14(folder, ...p.drafted.split("/"))),
3141
+ merged: await readFolderFiles(join14(folder, ...p.merged.split("/")))
2922
3142
  });
2923
3143
  }
2924
3144
  }
@@ -2938,8 +3158,8 @@ async function completeCaptures(root, ctx, o) {
2938
3158
  continue;
2939
3159
  for (const h of change.handoffs.filter((x) => x.state === "merged")) {
2940
3160
  const { name } = await captureStageOf(ctx, change, h.phase);
2941
- const file = join13(changeFolder(root, change.id), ...capturePaths(name).capture.split("/"));
2942
- const prior = await readFile11(file, "utf8").then((t) => DraftCapture.safeParse((0, import_yaml9.parse)(t)), () => void 0);
3161
+ const file = join14(changeFolder(root, change.id), ...capturePaths(name).capture.split("/"));
3162
+ const prior = await readFile12(file, "utf8").then((t) => DraftCapture.safeParse((0, import_yaml10.parse)(t)), () => void 0);
2943
3163
  if (prior?.success && prior.data.pr.number === h.pr.number && prior.data.state !== "waiting-for-merge")
2944
3164
  continue;
2945
3165
  const base = prior?.success ? prior.data.base : o.defaultBase ?? "main";
@@ -2963,6 +3183,7 @@ async function completeCaptures(root, ctx, o) {
2963
3183
  // packages/changes/dist/handoff.js
2964
3184
  var nowIso3 = () => (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
2965
3185
  var strip3 = (h) => h.startsWith("@") ? h.slice(1) : h;
3186
+ var sameHandle = (a, b) => handleKey(a) === handleKey(b);
2966
3187
  function metarepo(ctx, repo) {
2967
3188
  const fromRuntime = ctx.orgPack.runtime.adapters.gitHost?.settings.metarepo;
2968
3189
  const r = repo ?? (typeof fromRuntime === "string" ? fromRuntime : void 0);
@@ -2979,16 +3200,16 @@ async function load(root, id) {
2979
3200
  }
2980
3201
  async function walkReview(dir, gate) {
2981
3202
  const out = [];
2982
- const base = join14(dir, "review", gate);
3203
+ const base = join15(dir, "review", gate);
2983
3204
  let rounds;
2984
3205
  try {
2985
- rounds = (await readdir6(base)).filter((r) => /^\d+$/.test(r)).sort((a, b) => Number(a) - Number(b));
3206
+ rounds = (await readdir7(base)).filter((r) => /^\d+$/.test(r)).sort((a, b) => Number(a) - Number(b));
2986
3207
  } catch {
2987
3208
  return [];
2988
3209
  }
2989
3210
  for (const r of rounds) {
2990
3211
  try {
2991
- for (const f of (await readdir6(join14(base, r))).filter((x) => /\.ya?ml$/.test(x)).sort())
3212
+ for (const f of (await readdir7(join15(base, r))).filter((x) => /\.ya?ml$/.test(x)).sort())
2992
3213
  out.push(`review/${gate}/${r}/${f}`);
2993
3214
  } catch {
2994
3215
  }
@@ -2999,12 +3220,12 @@ async function keptPairFiles(dir) {
2999
3220
  const out = [];
3000
3221
  let entries;
3001
3222
  try {
3002
- entries = await readdir6(join14(dir, "stage"), { withFileTypes: true });
3223
+ entries = await readdir7(join15(dir, "stage"), { withFileTypes: true });
3003
3224
  } catch {
3004
3225
  return out;
3005
3226
  }
3006
3227
  const walk3 = async (rel) => {
3007
- for (const e of await readdir6(join14(dir, ...rel.split("/")), { withFileTypes: true }).catch(() => [])) {
3228
+ for (const e of await readdir7(join15(dir, ...rel.split("/")), { withFileTypes: true }).catch(() => [])) {
3008
3229
  const p = `${rel}/${e.name}`;
3009
3230
  if (e.isDirectory())
3010
3231
  await walk3(p);
@@ -3038,15 +3259,20 @@ async function handoffFiles(ctx, a, phase) {
3038
3259
  for (const f of await stageFiles(dir, step))
3039
3260
  files.add(f);
3040
3261
  }
3041
- const present = async (f) => readFile12(join14(dir, ...f.split("/"))).then(() => true, () => false);
3042
- for (const own of ["stage/corrections.yaml", "stage/drafted.yaml"])
3262
+ const present = async (f) => readFile13(join15(dir, ...f.split("/"))).then(() => true, () => false);
3263
+ for (const own of [
3264
+ "stage/corrections.yaml",
3265
+ "stage/drafted.yaml",
3266
+ "stage/stories-numbers.yaml",
3267
+ "stage/stories-shape.yaml"
3268
+ ])
3043
3269
  if (await present(own))
3044
3270
  files.add(own);
3045
3271
  if (phase === "build") {
3046
3272
  for (const extra of ["tasks.md", "repos.yaml"])
3047
3273
  if (await present(extra))
3048
3274
  files.add(extra);
3049
- for (const t of await readdir6(join14(dir, "tasks"), { withFileTypes: true }).catch(() => []))
3275
+ for (const t of await readdir7(join15(dir, "tasks"), { withFileTypes: true }).catch(() => []))
3050
3276
  if (t.isDirectory() && await present(`tasks/${t.name}/report.md`))
3051
3277
  files.add(`tasks/${t.name}/report.md`);
3052
3278
  }
@@ -3069,6 +3295,11 @@ async function changeQuestionFiles(root, id) {
3069
3295
  const rel = questionsRelOf(root);
3070
3296
  return questions.filter((q) => namesChange(q.askedBy.command, id) || namesChange(q.rerun, id)).map((q) => `${rel}/${q.id}.yaml`).sort();
3071
3297
  }
3298
+ function nextRoleOf(c, phase, person) {
3299
+ const n = nextOwnersOf(phase, c.owners);
3300
+ return n?.people.includes(person) ? ` (${n.role.replace(/-/g, " ")})` : "";
3301
+ }
3302
+ var nextRoleName = (phase) => (nextOwnersOf(phase, {})?.role ?? "reviewer").replace(/-/g, " ");
3072
3303
  function prBody(a, phase, next, paths, reviewers, review) {
3073
3304
  const c = a.change;
3074
3305
  const lines2 = [
@@ -3084,7 +3315,7 @@ function prBody(a, phase, next, paths, reviewers, review) {
3084
3315
  "",
3085
3316
  "### Reviewers",
3086
3317
  "",
3087
- ...reviewers.length ? reviewers.map((r) => `- @${r}`) : ["- None"],
3318
+ ...reviewers.length ? reviewers.map((r) => `- @${r}${nextRoleOf(c, phase, r)}`) : [`- None: name the ${nextRoleName(phase)} under the change's owners`],
3088
3319
  "",
3089
3320
  "### Risk",
3090
3321
  "",
@@ -3115,7 +3346,7 @@ async function handoff(root, id, opts) {
3115
3346
  await requireValid(opts.openspec, id);
3116
3347
  const { files, artifacts } = await handoffFiles(ctx, a, phase);
3117
3348
  const dir = changeFolder(root, id);
3118
- const hashed = await Promise.all(files.map(async (path) => ({ path, sha256: sha256(await readFile12(join14(dir, path))) })));
3349
+ const hashed = await Promise.all(files.map(async (path) => ({ path, sha256: sha256(await readFile13(join15(dir, path))) })));
3119
3350
  const authors = { ...change.authors };
3120
3351
  for (const art of artifacts) {
3121
3352
  const people = (opts.authors?.[art] ?? [by]).map(strip3);
@@ -3130,8 +3361,11 @@ async function handoff(root, id, opts) {
3130
3361
  ...questionFiles
3131
3362
  ];
3132
3363
  const reviewers = [
3133
- ...new Set(files.flatMap((f) => ownersFor(ctx.codeowners, `${rel}/${id}/${f}`)))
3134
- ].filter((p) => p !== by).sort();
3364
+ .../* @__PURE__ */ new Set([
3365
+ ...files.flatMap((f) => ownersFor(ctx.codeowners, `${rel}/${id}/${f}`)),
3366
+ ...nextOwnersOf(phase, change.owners)?.people ?? []
3367
+ ])
3368
+ ].filter((p) => sameHandle(p, by) === false).sort();
3135
3369
  const live2 = change.state === "returned" ? void 0 : liveHandoff(change);
3136
3370
  if (live2 && live2.phase === phase) {
3137
3371
  const pr2 = await handoffPr(opts.gitHost, repo, id, live2);
@@ -3429,10 +3663,15 @@ async function returnToPo(root, id, opts) {
3429
3663
  async function requireValid(openspec, id) {
3430
3664
  const r = await openspec.validate({ item: id, type: "change", strict: true });
3431
3665
  const item = r.items[0];
3432
- if (!item || item.valid)
3666
+ const issues = item ? blockingIssues(item.issues) : [];
3667
+ if (!item || item.valid && issues.length === 0)
3433
3668
  return;
3434
- throw new ChangeError("refused", `${id} doesn't pass openspec validate --strict.`, item.issues.filter((i) => i.level !== "INFO").map((i) => ({ code: "openspec-invalid", message: `${i.path}: ${i.message}` })));
3669
+ throw new ChangeError("refused", `${id} doesn't pass openspec validate --strict.`, issues.map((i) => ({
3670
+ code: "openspec-invalid",
3671
+ message: `${i.path}: ${i.message}${archiveRefuses(i) ? ` ${ADDED_ONLY}` : ""}`
3672
+ })));
3435
3673
  }
3674
+ var ADDED_ONLY = `A spec that openspec/specs doesn't have yet takes "## ADDED Requirements" only: change the delta's MODIFIED (or RENAMED, REMOVED) heading to ADDED, or run the stage that wrote it again.`;
3436
3675
  async function archiveChange(root, id, opts) {
3437
3676
  const { ctx, change } = await load(root, id);
3438
3677
  const a = await assess(ctx, change);
@@ -3453,14 +3692,25 @@ async function archiveChange(root, id, opts) {
3453
3692
  };
3454
3693
  await changeStore(root).write(updated);
3455
3694
  if (opts.openspec)
3456
- await opts.openspec.archive(id);
3695
+ try {
3696
+ await opts.openspec.archive(id);
3697
+ } catch (e) {
3698
+ await changeStore(root).write(change);
3699
+ const words = (e instanceof Error ? e.message : String(e)).trim();
3700
+ throw new ChangeError("refused", `OpenSpec refused to archive ${id}, so nothing was archived.`, [
3701
+ {
3702
+ code: "openspec-invalid",
3703
+ message: `${words.replace(/\.?$/, ".")}${/target spec does not exist|only ADDED/i.test(words) ? ` ${ADDED_ONLY}` : " Fix what it says, then archive again (atticus openspec validate " + id + " --strict says more)."}`
3704
+ }
3705
+ ]);
3706
+ }
3457
3707
  return updated;
3458
3708
  }
3459
3709
 
3460
3710
  // packages/changes/dist/learn.js
3461
- var import_yaml10 = __toESM(require_dist(), 1);
3462
- import { readFile as readFile13 } from "node:fs/promises";
3463
- import { join as join15 } from "node:path";
3711
+ var import_yaml11 = __toESM(require_dist(), 1);
3712
+ import { readFile as readFile14 } from "node:fs/promises";
3713
+ import { join as join16 } from "node:path";
3464
3714
  var LEARN_SCHEMA_VERSION = 1;
3465
3715
  var MAX_CELLS = 4e6;
3466
3716
  var lines = (text) => {
@@ -3807,7 +4057,7 @@ async function pairTouches(root, p) {
3807
4057
  let entry;
3808
4058
  const yaml = (t) => {
3809
4059
  try {
3810
- const v = (0, import_yaml10.parse)(t);
4060
+ const v = (0, import_yaml11.parse)(t);
3811
4061
  return v && typeof v === "object" ? v : void 0;
3812
4062
  } catch {
3813
4063
  return void 0;
@@ -3849,7 +4099,7 @@ async function pairTouches(root, p) {
3849
4099
  flows.push(m[1]);
3850
4100
  }
3851
4101
  }
3852
- const change = yaml(await readFile13(join15(root, ...p.folder.split("/"), "change.yaml"), "utf8").catch(() => ""));
4102
+ const change = yaml(await readFile14(join16(root, ...p.folder.split("/"), "change.yaml"), "utf8").catch(() => ""));
3853
4103
  const touches = change?.touches ?? {};
3854
4104
  for (const r of Array.isArray(touches.repos) ? touches.repos : [])
3855
4105
  if (typeof r === "string")
@@ -3942,8 +4192,8 @@ async function detectConflicts(root) {
3942
4192
  }
3943
4193
 
3944
4194
  // packages/changes/dist/size.js
3945
- import { readFile as readFile14 } from "node:fs/promises";
3946
- import { join as join16 } from "node:path";
4195
+ import { readFile as readFile15 } from "node:fs/promises";
4196
+ import { join as join17 } from "node:path";
3947
4197
  async function changeSize(ctx, change) {
3948
4198
  const type = ctx.orgPack.changeTypes.types.find((t) => t.id === change.type);
3949
4199
  if (!type)
@@ -3952,7 +4202,7 @@ async function changeSize(ctx, change) {
3952
4202
  why: "standard",
3953
4203
  words: `${change.type} isn't a change type in change-types.yaml, so ${change.id} takes the full path.`
3954
4204
  };
3955
- const brief = await readFile14(join16(changeFolder(ctx.root, change.id), "brief.md"), "utf8").catch(() => "");
4205
+ const brief = await readFile15(join17(changeFolder(ctx.root, change.id), "brief.md"), "utf8").catch(() => "");
3956
4206
  const f = fastPathOf(type, brief);
3957
4207
  const gate = f.fast ? fastGateOf(type, ctx.orgPack.gates) : void 0;
3958
4208
  const words = {
@@ -3966,13 +4216,13 @@ async function changeSize(ctx, change) {
3966
4216
  }
3967
4217
 
3968
4218
  // packages/changes/dist/openspec-stores.js
3969
- import { existsSync as existsSync2 } from "node:fs";
3970
- import { readFile as readFile15, writeFile as writeFile3 } from "node:fs/promises";
4219
+ import { existsSync as existsSync3 } from "node:fs";
4220
+ import { readFile as readFile16, writeFile as writeFile3 } from "node:fs/promises";
3971
4221
  import { homedir } from "node:os";
3972
- import { basename, isAbsolute, join as join17, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
4222
+ import { basename, isAbsolute, join as join18, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
3973
4223
  function storeDirOf(root, path) {
3974
4224
  if (path === "~" || path.startsWith("~/") || path.startsWith("~\\"))
3975
- return join17(homedir(), path.slice(2));
4225
+ return join18(homedir(), path.slice(2));
3976
4226
  return isAbsolute(path) ? resolve2(path) : resolve2(root, path);
3977
4227
  }
3978
4228
  function packRel(root) {
@@ -4002,7 +4252,7 @@ async function storeSpecLookup(root, capability) {
4002
4252
  var REMOTE = /^[a-z][a-z0-9+.-]*:\/\//i;
4003
4253
  var SCP = /^[^/\\]+@[^:/\\]+:/;
4004
4254
  async function metarepoOrigin(root, git = createGit()) {
4005
- if (!existsSync2(join17(root, ".git")))
4255
+ if (!existsSync3(join18(root, ".git")))
4006
4256
  return void 0;
4007
4257
  try {
4008
4258
  const url = (await git(["remote", "get-url", "origin"], root)).stdout.trim();
@@ -4013,7 +4263,7 @@ async function metarepoOrigin(root, git = createGit()) {
4013
4263
  return void 0;
4014
4264
  }
4015
4265
  }
4016
- async function referenceMetarepoIn(root, repoDir2, o = {}) {
4266
+ async function referenceMetarepoIn(root, repoDir3, o = {}) {
4017
4267
  const { settings } = await loadOpenSpecSettings(orgPackDirOf(root));
4018
4268
  if (!settings.referenceInRepos)
4019
4269
  return { action: "off" };
@@ -4025,8 +4275,8 @@ async function referenceMetarepoIn(root, repoDir2, o = {}) {
4025
4275
  file,
4026
4276
  why: marker.missing ? `this metarepo isn't an OpenSpec store yet (no ${STORE_MARKER}): run atticus upgrade --openspec-store, commit the file, then hand down again` : `this metarepo's ${STORE_MARKER} can't be read (${marker.notes.join("; ")})`
4027
4277
  };
4028
- const path = join17(repoDir2, "openspec", "config.yaml");
4029
- const text = await readFile15(path, "utf8").catch(() => void 0);
4278
+ const path = join18(repoDir3, "openspec", "config.yaml");
4279
+ const text = await readFile16(path, "utf8").catch(() => void 0);
4030
4280
  if (text === void 0)
4031
4281
  return {
4032
4282
  action: "skipped",
@@ -4043,7 +4293,7 @@ async function referenceMetarepoIn(root, repoDir2, o = {}) {
4043
4293
  }
4044
4294
 
4045
4295
  // packages/changes/dist/merge-record.js
4046
- var import_yaml11 = __toESM(require_dist(), 1);
4296
+ var import_yaml12 = __toESM(require_dist(), 1);
4047
4297
  import { isDeepStrictEqual } from "node:util";
4048
4298
  var HANDOFF_RANK = {
4049
4299
  open: 0,
@@ -4161,7 +4411,7 @@ function mergeChangeRecords(base, ours, theirs) {
4161
4411
  }
4162
4412
  function readRecord(text) {
4163
4413
  try {
4164
- const r = ChangeLifecycle.safeParse((0, import_yaml11.parse)(text));
4414
+ const r = ChangeLifecycle.safeParse((0, import_yaml12.parse)(text));
4165
4415
  return r.success ? r.data : void 0;
4166
4416
  } catch {
4167
4417
  return void 0;
@@ -4212,6 +4462,29 @@ async function setChangeOwners(root, id, owners) {
4212
4462
  return r.data;
4213
4463
  }
4214
4464
 
4465
+ // packages/changes/dist/edit-hash.js
4466
+ import { createHash as createHash2 } from "node:crypto";
4467
+ function editText(file, text) {
4468
+ const lf = text.replace(/\r\n?/g, "\n");
4469
+ return isTasks(file) ? lf.replace(/^(\s*[-*]\s+\[)[ xX]?(\])/gm, "$1 $2") : lf;
4470
+ }
4471
+ function editSha(file, text) {
4472
+ const h = createHash2("sha256");
4473
+ if (typeof text !== "string" && !text.includes(13) && !isTasks(file))
4474
+ return h.update(text).digest("hex");
4475
+ const t = typeof text === "string" ? text : text.toString("utf8");
4476
+ return h.update(editText(file, t), "utf8").digest("hex");
4477
+ }
4478
+ function wroteThis(file, text, hash) {
4479
+ if (hash === void 0)
4480
+ return false;
4481
+ if (editSha(file, text) === hash)
4482
+ return true;
4483
+ const t = typeof text === "string" ? text : text.toString("utf8");
4484
+ return createHash2("sha256").update(t.replace(/\r\n?/g, "\n"), "utf8").digest("hex") === hash;
4485
+ }
4486
+ var isTasks = (file) => file.split(/[\\/]/).at(-1) === "tasks.md";
4487
+
4215
4488
  export {
4216
4489
  ChangeError,
4217
4490
  readTables,
@@ -4278,6 +4551,12 @@ export {
4278
4551
  workProgress,
4279
4552
  privacyImpact,
4280
4553
  prApprovers,
4554
+ TASK_DECISION_FILE,
4555
+ readTaskDecision,
4556
+ unmergedTaskBranches,
4557
+ unmergedTaskWords,
4558
+ taskBranchReasons,
4559
+ recordTaskDecision,
4281
4560
  RELEASE_PR_STATES,
4282
4561
  RELEASE_PRS_FILE,
4283
4562
  staleReleasePrs,
@@ -4296,6 +4575,8 @@ export {
4296
4575
  slugify,
4297
4576
  newChange,
4298
4577
  gitHandoffPublisher,
4578
+ handoffBranchPushed,
4579
+ pushHandoffBranch,
4299
4580
  CAPTURE_SCHEMA_VERSION,
4300
4581
  DraftCapture,
4301
4582
  capturePaths,
@@ -4335,5 +4616,8 @@ export {
4335
4616
  mergeChangeText,
4336
4617
  OWNER_ROLE_KEYS,
4337
4618
  ChangeOwnersError,
4338
- setChangeOwners
4619
+ setChangeOwners,
4620
+ editText,
4621
+ editSha,
4622
+ wroteThis
4339
4623
  };