@maycombhq/atticus 2.0.0-beta.2 → 2.0.0-beta.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +8 -4
- package/dist/chunk-23XVSEV5.js +49 -0
- package/dist/{chunk-ZDPAS56H.js → chunk-24OXGB3P.js} +8 -2
- package/dist/{chunk-7EOBHUMC.js → chunk-24XLDU72.js} +4 -3
- package/dist/{chunk-CR3MTH32.js → chunk-2F4CYZKJ.js} +86 -11
- package/dist/{chunk-6IU67AEK.js → chunk-2GF7OLF3.js} +23 -15
- package/dist/chunk-2IIMFOPM.js +41 -0
- package/dist/chunk-2LGRMVCA.js +617 -0
- package/dist/{chunk-XPCM366L.js → chunk-2MMCFP5C.js} +10 -8
- package/dist/{chunk-JBTK5OP2.js → chunk-2Q56PQPS.js} +6 -4
- package/dist/{chunk-Z6LF7HQN.js → chunk-2Q5EDGEO.js} +7 -5
- package/dist/{chunk-3USYZGRF.js → chunk-2RLKFUUL.js} +38 -27
- package/dist/chunk-2SKB4O2E.js +59 -0
- package/dist/{chunk-SP2I63OO.js → chunk-34S2WGOB.js} +87 -4
- package/dist/{chunk-GQ4N4WKF.js → chunk-3NFFJL5D.js} +33 -27
- package/dist/{chunk-SJRGMG6A.js → chunk-3NWDLGG6.js} +28 -25
- package/dist/{chunk-4WBVUHXN.js → chunk-3RM4UK6W.js} +20 -18
- package/dist/chunk-42SIDKEU.js +583 -0
- package/dist/{chunk-GLUX4EEP.js → chunk-4EURQWQD.js} +20 -15
- package/dist/chunk-4U276ICE.js +39 -0
- package/dist/{chunk-ZMFPW66A.js → chunk-53T4O55J.js} +4 -3
- package/dist/{chunk-6J5OKA4Y.js → chunk-57TDNMI3.js} +17 -15
- package/dist/chunk-5BD2KYLE.js +57 -0
- package/dist/{chunk-7EFILTCI.js → chunk-5F7GFN2F.js} +28 -0
- package/dist/chunk-5NMKONLP.js +95 -0
- package/dist/{chunk-7ZUIMTOU.js → chunk-5SJZW52K.js} +26 -24
- package/dist/{chunk-4RS5KZQD.js → chunk-63YRMR6J.js} +6 -5
- package/dist/chunk-66PPNOON.js +62 -0
- package/dist/chunk-6H3Z5JHH.js +64 -0
- package/dist/{chunk-CEXSU4S6.js → chunk-6MUGR4LS.js} +775 -89
- package/dist/{chunk-QSXK2RGH.js → chunk-6OJQOPUN.js} +5 -3
- package/dist/{chunk-MVZVGYXH.js → chunk-6PPOWY5E.js} +84 -14
- package/dist/{chunk-7EKXJZ2Y.js → chunk-6ZGLAACW.js} +299 -38
- package/dist/chunk-6ZJ5A7AF.js +222 -0
- package/dist/{chunk-L24C55VN.js → chunk-745DAZ4L.js} +142 -30
- package/dist/{chunk-Q4D5X7QB.js → chunk-7ASNL4Q4.js} +46 -24
- package/dist/chunk-7BR7IPOH.js +35 -0
- package/dist/{chunk-7WD63HU2.js → chunk-7DOR27HL.js} +6 -6
- package/dist/chunk-7FTTA3HD.js +341 -0
- package/dist/{chunk-OLQJTJJU.js → chunk-7GJS6DNX.js} +12 -3
- package/dist/{chunk-7JUKDRSZ.js → chunk-7IGKHZ4Z.js} +347 -226
- package/dist/{chunk-G2B4ZQGH.js → chunk-7IOWA5D5.js} +11 -6
- package/dist/{chunk-EBEW3XXQ.js → chunk-7JITZFJC.js} +7 -5
- package/dist/chunk-7MJSQTL5.js +174 -0
- package/dist/{chunk-I4JRCD6M.js → chunk-7UOMVMFG.js} +25 -17
- package/dist/{chunk-YY6ZQQBP.js → chunk-AFWUDXEM.js} +19 -7
- package/dist/chunk-AFZ3QA6W.js +47 -0
- package/dist/chunk-AJQ72EBM.js +420 -0
- package/dist/chunk-AJYXNTNZ.js +317 -0
- package/dist/chunk-AVTBS4OW.js +49 -0
- package/dist/{chunk-FHH4I4ZV.js → chunk-BDKC6H5P.js} +12 -6
- package/dist/{chunk-IPKHE5D6.js → chunk-BEVTIBRH.js} +1526 -875
- package/dist/chunk-BHT7QK4G.js +162 -0
- package/dist/{chunk-6JUBZBMW.js → chunk-BIGDQDHD.js} +6 -4
- package/dist/{chunk-2BFCZ3RK.js → chunk-BO4KX37X.js} +20 -18
- package/dist/chunk-BPK5P77O.js +115 -0
- package/dist/chunk-BQ4SQQC6.js +59 -0
- package/dist/chunk-BQGDB6ZL.js +7342 -0
- package/dist/{chunk-2ANOROX3.js → chunk-BTGPE6CR.js} +11 -9
- package/dist/chunk-BTY3HZBO.js +93 -0
- package/dist/{chunk-DPZHZQKE.js → chunk-BXYMYEJ4.js} +44 -10
- package/dist/{chunk-2RMYG36Q.js → chunk-C3RY6KU6.js} +309 -346
- package/dist/chunk-C4R4JLHE.js +40 -0
- package/dist/chunk-CADWLE2T.js +18 -0
- package/dist/chunk-CBGGOQWU.js +82 -0
- package/dist/chunk-CMDXGQTS.js +47 -0
- package/dist/{chunk-MC3H7736.js → chunk-CQDGOPGH.js} +58 -18
- package/dist/{chunk-HFQCFSJR.js → chunk-CX4RZ2KS.js} +4 -3
- package/dist/{chunk-PAMPPUR6.js → chunk-CXJ6FUKN.js} +1852 -207
- package/dist/{chunk-ABWHYWNI.js → chunk-D73UEXYW.js} +3 -3
- package/dist/chunk-DCZWQLYT.js +1205 -0
- package/dist/chunk-DLOBCJL6.js +48 -0
- package/dist/{chunk-4BN53TG3.js → chunk-DOBQKHIF.js} +31 -23
- package/dist/chunk-E3ISYXO3.js +423 -0
- package/dist/{chunk-7SW2QWLU.js → chunk-E6ZIEVOI.js} +16 -13
- package/dist/chunk-EBL2R3YG.js +43 -0
- package/dist/{chunk-AIOQPLA5.js → chunk-EGQRREQH.js} +41 -15
- package/dist/chunk-EHA7RMZ3.js +58 -0
- package/dist/{chunk-M766ZJ6W.js → chunk-EIPTLPFC.js} +38 -27
- package/dist/chunk-EMRIQUND.js +517 -0
- package/dist/{chunk-DFBCSHVT.js → chunk-EPCJQQWD.js} +6 -4
- package/dist/{chunk-RZPYKDWS.js → chunk-F3P7N7SF.js} +1 -1
- package/dist/{chunk-R77KLRB3.js → chunk-FFLNS6VP.js} +21 -18
- package/dist/chunk-FFTRTL6R.js +26 -0
- package/dist/{chunk-IHMLFRVV.js → chunk-FPJPLKDW.js} +62 -16
- package/dist/{chunk-JCZIKA4C.js → chunk-FSMSFDLD.js} +5 -4
- package/dist/{chunk-AVJDSJ2F.js → chunk-FUJM6RTF.js} +8 -7
- package/dist/chunk-FZOJFH7Q.js +132 -0
- package/dist/{chunk-QRAOANID.js → chunk-G6X77UJZ.js} +23 -21
- package/dist/{chunk-3ALD2W2A.js → chunk-GCWRWSU7.js} +10 -4
- package/dist/chunk-GIW4ZVDB.js +39 -0
- package/dist/{chunk-B2WLAWNJ.js → chunk-GUX3PTYM.js} +3 -3
- package/dist/{chunk-DPUYDDQG.js → chunk-GZY6RUZ6.js} +25 -3
- package/dist/chunk-H4VO6WG3.js +10 -0
- package/dist/{chunk-MMOSZPWJ.js → chunk-H5HBGNXU.js} +5 -4
- package/dist/chunk-H7KM7LZE.js +229 -0
- package/dist/{chunk-AA6YULYB.js → chunk-HNM2YQT2.js} +7 -7
- package/dist/{chunk-3C7EYRFZ.js → chunk-HYU5VLGA.js} +1 -1
- package/dist/{chunk-XY3P7JW7.js → chunk-IDKCWSM5.js} +1032 -172
- package/dist/chunk-IFKEI4SA.js +237 -0
- package/dist/{chunk-F7HYOUFF.js → chunk-IGOE6KPG.js} +67 -22
- package/dist/{chunk-TDD55CJH.js → chunk-IH2XURVQ.js} +6 -5
- package/dist/chunk-INQHESFB.js +38 -0
- package/dist/chunk-IP74LCOQ.js +57 -0
- package/dist/chunk-IPHHDDC6.js +45 -0
- package/dist/{chunk-T6AIP7H5.js → chunk-ISUAAMGS.js} +110 -153
- package/dist/{chunk-A7UPUQFY.js → chunk-IUPG3UKI.js} +624 -319
- package/dist/{chunk-L6SGQIR3.js → chunk-IVBOQAGB.js} +7 -3
- package/dist/{chunk-27NKUS3X.js → chunk-J2JAKCIW.js} +2205 -796
- package/dist/{chunk-V2YTAIQO.js → chunk-J3IOLXWM.js} +24 -7
- package/dist/chunk-JA5FI3QV.js +142 -0
- package/dist/chunk-JAVI7JSP.js +49 -0
- package/dist/{chunk-HLJAXMM4.js → chunk-JB5LINEM.js} +6 -2
- package/dist/{chunk-2VHF7OXM.js → chunk-JENSEMXF.js} +1 -1
- package/dist/{chunk-6BVONWJ7.js → chunk-JJF6HALY.js} +4 -3
- package/dist/chunk-JLUCKAEL.js +38 -0
- package/dist/chunk-JRBFANFE.js +221 -0
- package/dist/{chunk-R6XF6UR3.js → chunk-KDNTAPLX.js} +4 -4
- package/dist/chunk-KFAVQZSX.js +33 -0
- package/dist/chunk-KJXD4PNL.js +50 -0
- package/dist/chunk-KN5BXMWN.js +44 -0
- package/dist/{chunk-PCVDV3UZ.js → chunk-KQGURXFU.js} +9 -7
- package/dist/{chunk-WY6PP6AA.js → chunk-KXITGYLF.js} +40 -6
- package/dist/{chunk-66YVAGGM.js → chunk-L27SV425.js} +22 -20
- package/dist/{chunk-NE2W3OO7.js → chunk-LDLL7LB3.js} +24 -22
- package/dist/chunk-LFGTYX5U.js +379 -0
- package/dist/{chunk-EYWIDJFU.js → chunk-LGBMTVNT.js} +7 -5
- package/dist/{chunk-Q5AMFEWD.js → chunk-LGFL54FP.js} +3 -2
- package/dist/{chunk-6TACQN3N.js → chunk-LJXMYKZJ.js} +7 -5
- package/dist/{chunk-BKVWTZ6A.js → chunk-LKOR5UET.js} +29 -26
- package/dist/chunk-LNBQOP7D.js +294 -0
- package/dist/{chunk-O3WI5KWW.js → chunk-LO6P2VYG.js} +2 -2
- package/dist/chunk-LQJPN536.js +122 -0
- package/dist/{chunk-YEDDOYSC.js → chunk-LYBNHMVZ.js} +29 -5
- package/dist/{chunk-A3GY6SOA.js → chunk-LZ7NUC62.js} +20 -18
- package/dist/chunk-M32BLWDH.js +37 -0
- package/dist/{chunk-VYDBJ73M.js → chunk-M3NANSDZ.js} +17 -15
- package/dist/chunk-MFHL5URL.js +31 -0
- package/dist/chunk-MFR5OPBD.js +109 -0
- package/dist/{chunk-DE76JROX.js → chunk-MG4ZL5RW.js} +32 -20
- package/dist/{chunk-N7IXEHK3.js → chunk-MO6P2JZH.js} +10 -8
- package/dist/{chunk-65NYPGRC.js → chunk-MUWDB4R4.js} +1 -1
- package/dist/chunk-MZCGSXVR.js +34 -0
- package/dist/{chunk-MGYZM27B.js → chunk-N3XIYPU3.js} +51 -23
- package/dist/chunk-NDCF4R6S.js +172 -0
- package/dist/{chunk-DHPACDG7.js → chunk-NR2UJWOC.js} +10 -8
- package/dist/chunk-NXJ5URP6.js +51 -0
- package/dist/{chunk-UNM6ZOKP.js → chunk-NY2XSR5K.js} +147 -18
- package/dist/{chunk-5GDRCDQB.js → chunk-O45HFTFS.js} +3 -2
- package/dist/{chunk-ONLS5QA5.js → chunk-O4GXGGBX.js} +14 -12
- package/dist/chunk-O5PXQR67.js +249 -0
- package/dist/{chunk-PRPPGYZG.js → chunk-O66DM6DJ.js} +6 -4
- package/dist/{chunk-KEM4SDDP.js → chunk-O7FDLW7L.js} +11 -8
- package/dist/{chunk-T2UYZSCQ.js → chunk-O7XLYEFA.js} +169 -29
- package/dist/{chunk-FITWGOJ2.js → chunk-OHNCWBKF.js} +4 -4
- package/dist/{chunk-652QWTLZ.js → chunk-OHVTTOPS.js} +3 -3
- package/dist/chunk-OMI6FPPN.js +43 -0
- package/dist/chunk-ONUPY3H6.js +53 -0
- package/dist/chunk-OTLDSZDV.js +69 -0
- package/dist/chunk-OUBGGKDU.js +22 -0
- package/dist/chunk-OWNCM4ZN.js +330 -0
- package/dist/{chunk-YISXLPHN.js → chunk-P2V7QW4D.js} +235 -35
- package/dist/{chunk-CNUKCS2T.js → chunk-P32RUW3B.js} +1632 -93
- package/dist/{chunk-BWZ77RQT.js → chunk-PAQ2AS5E.js} +1 -1
- package/dist/{chunk-ZMAINWBW.js → chunk-PBPBMP2B.js} +4 -3
- package/dist/{chunk-ZVM6AKKM.js → chunk-PJSJPMJI.js} +3 -3
- package/dist/{chunk-EFHQ3TWP.js → chunk-PKBHS4AA.js} +233 -56
- package/dist/{chunk-GT4I4ZWM.js → chunk-PMUAJGLI.js} +20 -16
- package/dist/chunk-PPD7HTDP.js +152 -0
- package/dist/chunk-PSOFBQWB.js +42 -0
- package/dist/{chunk-S2A7YC3Q.js → chunk-Q2TECDIT.js} +10694 -8896
- package/dist/chunk-Q4K5WB2W.js +42 -0
- package/dist/{chunk-UGLN7QHV.js → chunk-Q6DFNVRJ.js} +14 -12
- package/dist/chunk-QA4O2GGC.js +265 -0
- package/dist/chunk-QAXW2N3B.js +1216 -0
- package/dist/chunk-QBNWF5ZU.js +19 -0
- package/dist/chunk-QFWA2DPH.js +224 -0
- package/dist/{chunk-23W7VWKR.js → chunk-QKUJMING.js} +1363 -114
- package/dist/{chunk-NXFPS2LR.js → chunk-R44CYFPV.js} +16 -13
- package/dist/{chunk-CKSITVS4.js → chunk-R7NYHMUU.js} +2687 -786
- package/dist/chunk-REWWDVQB.js +162 -0
- package/dist/{chunk-JMSCMUCA.js → chunk-RGERPOIV.js} +145 -21
- package/dist/{chunk-6JCPI55B.js → chunk-RLDGWLQ7.js} +49 -7
- package/dist/chunk-RUGXBPWI.js +384 -0
- package/dist/{chunk-CPA6HPVR.js → chunk-RXPJMEOW.js} +18 -12
- package/dist/{chunk-3HI6Z55Y.js → chunk-S4PMJU6H.js} +339 -43
- package/dist/chunk-S5LSDXV4.js +40 -0
- package/dist/chunk-S7FCV7S5.js +51 -0
- package/dist/{chunk-5GGOLAKC.js → chunk-SDKLKB6I.js} +28 -26
- package/dist/chunk-SFSPGFCV.js +62 -0
- package/dist/{chunk-ZNCEKR4J.js → chunk-SFUP7TTO.js} +12 -8
- package/dist/{chunk-64EQYWCA.js → chunk-SLXZOMA6.js} +69 -19
- package/dist/chunk-SQV37XO2.js +273 -0
- package/dist/{chunk-K65BJIMT.js → chunk-SU74NDMQ.js} +19 -17
- package/dist/chunk-SYV5LHML.js +165 -0
- package/dist/chunk-T4YPZIQN.js +36 -0
- package/dist/chunk-T6DQR5TV.js +323 -0
- package/dist/{chunk-JIITQXFB.js → chunk-THDMSZ3R.js} +3075 -802
- package/dist/{chunk-JGZCG5VM.js → chunk-TNR75OXT.js} +7 -7
- package/dist/{chunk-D3PO4DOZ.js → chunk-TUULXQRW.js} +174 -15
- package/dist/chunk-TYQBFTBR.js +516 -0
- package/dist/chunk-U76OWS3Q.js +49 -0
- package/dist/{chunk-YYQN46FY.js → chunk-UCROWG2D.js} +27 -24
- package/dist/{chunk-6M5NK3K3.js → chunk-UF4AZOZB.js} +50 -10
- package/dist/chunk-UF4GLFBX.js +345 -0
- package/dist/{chunk-OT2O76OS.js → chunk-UGUP3ZM6.js} +240 -39
- package/dist/chunk-UNAGJYET.js +45 -0
- package/dist/{chunk-5WG5YP4T.js → chunk-UOR2DTHH.js} +16 -14
- package/dist/{chunk-S3QNRWYR.js → chunk-UPOY4YSQ.js} +14 -12
- package/dist/{chunk-EPTBZ3GP.js → chunk-UPS2DGFC.js} +1 -1
- package/dist/{chunk-4AK7IBVP.js → chunk-UUU4CLJG.js} +4 -2
- package/dist/{chunk-W3BQAZ3Q.js → chunk-UWMJKX5U.js} +14 -12
- package/dist/{chunk-QZSX3F7C.js → chunk-UWOJLHFT.js} +27 -23
- package/dist/chunk-VBTP56CE.js +535 -0
- package/dist/chunk-VCTWPLAO.js +211 -0
- package/dist/chunk-VNU26RCO.js +1215 -0
- package/dist/{chunk-CSZ4C5N6.js → chunk-VTZMAJ3W.js} +93 -10
- package/dist/{chunk-TXLH6WHQ.js → chunk-VW62D6QE.js} +14 -12
- package/dist/{chunk-CAQZUNOH.js → chunk-VY72R2XZ.js} +610 -3
- package/dist/{chunk-2DIQQJCB.js → chunk-VZALIKIF.js} +18 -15
- package/dist/{chunk-TYAID7B7.js → chunk-W62H2XSO.js} +25 -23
- package/dist/{chunk-HVUPKCGJ.js → chunk-W7VWI2YH.js} +9 -6
- package/dist/{chunk-TANFV3MZ.js → chunk-WERM6KPJ.js} +7 -4
- package/dist/{chunk-BOHJZTEQ.js → chunk-WF7B67YE.js} +208 -87
- package/dist/{chunk-7FBGJFEE.js → chunk-WG5U3F5V.js} +14 -12
- package/dist/{chunk-4NDAAFQT.js → chunk-WJF2CS6M.js} +8 -5
- package/dist/{chunk-XAKWMCXI.js → chunk-WKUJ3KPV.js} +4 -4
- package/dist/chunk-WMTRHUI5.js +103 -0
- package/dist/chunk-WNKPRSGI.js +36 -0
- package/dist/chunk-WXFLMQSR.js +223 -0
- package/dist/{chunk-RRTKKSLQ.js → chunk-X3WY6MN3.js} +8 -6
- package/dist/{chunk-ZCJDOK2S.js → chunk-X4CXA2IL.js} +47 -23
- package/dist/{chunk-UBBC2XSG.js → chunk-X5F3Q5LV.js} +560 -105
- package/dist/{chunk-C6EKFH7J.js → chunk-XD75VZIH.js} +9 -7
- package/dist/chunk-XERYFDB5.js +297 -0
- package/dist/chunk-XI2LCCYQ.js +420 -0
- package/dist/chunk-Y2EQNWKV.js +933 -0
- package/dist/{chunk-LR3R6Z2A.js → chunk-YHCMZC2J.js} +7 -7
- package/dist/chunk-YYY3AZFE.js +122 -0
- package/dist/{chunk-GDLULHTC.js → chunk-Z5IA3WDR.js} +19 -31
- package/dist/{chunk-T6XQL73F.js → chunk-ZFFYNRIO.js} +63 -23
- package/dist/{chunk-EDS2L2LD.js → chunk-ZFL7NY4F.js} +56 -27
- package/dist/{chunk-YMZ3TNYB.js → chunk-ZGULQAPZ.js} +7 -4
- package/dist/{chunk-4SKZDI62.js → chunk-ZIUFM5HT.js} +3 -1
- package/dist/{chunk-DKJA76CJ.js → chunk-ZJFRMSJT.js} +15 -13
- package/dist/chunk-ZJXLNDH4.js +239 -0
- package/dist/chunk-ZQ3ON2VQ.js +252 -0
- package/dist/{chunk-HITVBIJS.js → chunk-ZQ7SKESZ.js} +150 -415
- package/dist/{chunk-6QSERWXH.js → chunk-ZQXZ2SES.js} +24 -21
- package/dist/chunk-ZX57KSEQ.js +39 -0
- package/dist/{chunk-I3E7CX4H.js → chunk-ZZK56BLP.js} +5 -3
- package/dist/files.json +664 -368
- package/dist/packages/naysayer/constitution/constitution.yaml +19 -0
- package/dist/packages/sdk/npm/index.js +6194 -2542
- package/dist/packages/ui/dist/assets/{elk-api-tma0MCuh.js → elk-api-CIf-0gz5.js} +2 -2
- package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +47 -0
- package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +1 -0
- package/dist/packages/ui/dist/index.html +3 -2
- package/package.json +5 -5
- package/dist/chunk-2BF2EYJV.js +0 -174
- package/dist/chunk-42EVSKME.js +0 -37
- package/dist/chunk-4BKGMUIK.js +0 -53
- package/dist/chunk-5KLGBXG5.js +0 -48
- package/dist/chunk-6BNC6EQ4.js +0 -41
- package/dist/chunk-6D2CQ5II.js +0 -41
- package/dist/chunk-7AVHLZGD.js +0 -45
- package/dist/chunk-D46WUV3T.js +0 -33
- package/dist/chunk-E36QOJMD.js +0 -47
- package/dist/chunk-FQXYPF7E.js +0 -147
- package/dist/chunk-GBRFVT63.js +0 -45
- package/dist/chunk-ICY36XCH.js +0 -34
- package/dist/chunk-J4K3KVLD.js +0 -131
- package/dist/chunk-JZU3H6UQ.js +0 -54
- package/dist/chunk-NN2ZQEB4.js +0 -38
- package/dist/chunk-PCOCACY3.js +0 -385
- package/dist/chunk-RTEYOSJY.js +0 -29
- package/dist/chunk-RUVFXE2L.js +0 -666
- package/dist/chunk-RVH5SUW5.js +0 -69
- package/dist/chunk-VN3DP4LQ.js +0 -43
- package/dist/chunk-W5BVQF44.js +0 -36
- package/dist/chunk-WVPJSRRJ.js +0 -52
- package/dist/chunk-XPTOBS2D.js +0 -48
- package/dist/packages/ui/dist/assets/index-B54fm9FQ.js +0 -29
- package/dist/packages/ui/dist/assets/index-DD_hufQz.css +0 -1
|
@@ -6,55 +6,60 @@ var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
|
|
|
6
6
|
import {
|
|
7
7
|
slug,
|
|
8
8
|
writeGateRound
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-BTGPE6CR.js";
|
|
10
10
|
import {
|
|
11
|
+
catchUpChangeBranch,
|
|
11
12
|
changeWorktree,
|
|
12
13
|
handDown,
|
|
13
14
|
loadTask,
|
|
14
15
|
openTaskWorktree,
|
|
15
|
-
readChangeTasks
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from "./chunk-IPKHE5D6.js";
|
|
16
|
+
readChangeTasks,
|
|
17
|
+
setTaskDone,
|
|
18
|
+
taskBranchOwnCommits
|
|
19
|
+
} from "./chunk-UGUP3ZM6.js";
|
|
20
20
|
import {
|
|
21
21
|
conform,
|
|
22
22
|
readConformDeltas,
|
|
23
23
|
readTaskSteps,
|
|
24
24
|
renderTaskContext,
|
|
25
|
-
taskContext
|
|
26
|
-
|
|
25
|
+
taskContext,
|
|
26
|
+
withBuildLine
|
|
27
|
+
} from "./chunk-R7NYHMUU.js";
|
|
28
|
+
import {
|
|
29
|
+
buildEngineFor
|
|
30
|
+
} from "./chunk-BEVTIBRH.js";
|
|
27
31
|
import {
|
|
28
32
|
readChangeFiles,
|
|
29
33
|
readRound,
|
|
34
|
+
readStoryIndex,
|
|
30
35
|
roundsOf,
|
|
31
36
|
writeQuarantineItems
|
|
32
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-S4PMJU6H.js";
|
|
33
38
|
import {
|
|
34
39
|
changeFolder,
|
|
35
40
|
changeStore
|
|
36
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-IDKCWSM5.js";
|
|
37
42
|
import {
|
|
38
43
|
AdapterError,
|
|
39
44
|
createAdapters,
|
|
40
45
|
fileStepStore,
|
|
41
46
|
requireApproval
|
|
42
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-7IGKHZ4Z.js";
|
|
43
48
|
import {
|
|
44
49
|
scanEstate
|
|
45
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-J2JAKCIW.js";
|
|
46
51
|
import {
|
|
47
52
|
baseClonePath,
|
|
48
53
|
createGit,
|
|
49
54
|
toRepoRelative
|
|
50
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-PKBHS4AA.js";
|
|
51
56
|
import {
|
|
52
57
|
HandoffRuntime,
|
|
53
58
|
buildContextPack,
|
|
54
59
|
createRuntime,
|
|
55
60
|
quarantineItems,
|
|
56
61
|
toRunSummary
|
|
57
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-P32RUW3B.js";
|
|
58
63
|
import {
|
|
59
64
|
AgentDefinition,
|
|
60
65
|
ChecklistPack,
|
|
@@ -68,16 +73,20 @@ import {
|
|
|
68
73
|
changesRelOf,
|
|
69
74
|
external_exports,
|
|
70
75
|
readRepoSpec,
|
|
71
|
-
require_dist,
|
|
72
76
|
runsDirOf,
|
|
73
77
|
runsRelOf,
|
|
74
78
|
stateDirOf,
|
|
75
79
|
taskBranch,
|
|
76
80
|
toCanonicalYaml
|
|
77
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-Q2TECDIT.js";
|
|
78
82
|
import {
|
|
83
|
+
LockHeldError,
|
|
84
|
+
acquireLock,
|
|
79
85
|
writeFileAtomic
|
|
80
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-TUULXQRW.js";
|
|
87
|
+
import {
|
|
88
|
+
require_dist
|
|
89
|
+
} from "./chunk-BQGDB6ZL.js";
|
|
81
90
|
import {
|
|
82
91
|
__toESM
|
|
83
92
|
} from "./chunk-TV45EUGM.js";
|
|
@@ -156,27 +165,162 @@ async function applyChanges(worktree, changes) {
|
|
|
156
165
|
|
|
157
166
|
// packages/taskrun/dist/commands.js
|
|
158
167
|
import { spawn } from "node:child_process";
|
|
168
|
+
var KEEP_OUTPUT = 4 * 1024 * 1024;
|
|
169
|
+
function tail(max = KEEP_OUTPUT) {
|
|
170
|
+
let text = "";
|
|
171
|
+
let dropped = 0;
|
|
172
|
+
return {
|
|
173
|
+
add(d) {
|
|
174
|
+
text += d;
|
|
175
|
+
if (text.length > max) {
|
|
176
|
+
dropped += text.length - max;
|
|
177
|
+
text = text.slice(text.length - max);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
get text() {
|
|
181
|
+
return dropped ? `[${dropped} characters of output left out]
|
|
182
|
+
${text}` : text;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function stopTree(child, signal = "SIGTERM") {
|
|
187
|
+
if (child.pid === void 0)
|
|
188
|
+
return;
|
|
189
|
+
if (process.platform === "win32") {
|
|
190
|
+
const k = spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], { windowsHide: true });
|
|
191
|
+
k.on("error", () => child.kill());
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
process.kill(-child.pid, signal);
|
|
196
|
+
} catch {
|
|
197
|
+
child.kill(signal);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
var live = /* @__PURE__ */ new Set();
|
|
201
|
+
var SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
202
|
+
var stopping = false;
|
|
203
|
+
var stopRequested = () => stopping;
|
|
204
|
+
var stopper = new AbortController();
|
|
205
|
+
var stopSignal = stopper.signal;
|
|
206
|
+
function stopAllBuilds() {
|
|
207
|
+
stopping = true;
|
|
208
|
+
for (const c of live)
|
|
209
|
+
stopTree(c);
|
|
210
|
+
if (!stopper.signal.aborted)
|
|
211
|
+
stopper.abort();
|
|
212
|
+
}
|
|
213
|
+
var holds = 0;
|
|
214
|
+
var pending;
|
|
215
|
+
var SIGNAL_GRACE_MS = 1e4;
|
|
216
|
+
var onSignal = (sig) => {
|
|
217
|
+
stopAllBuilds();
|
|
218
|
+
if (process.listenerCount(sig) > 1)
|
|
219
|
+
return;
|
|
220
|
+
if (!pending) {
|
|
221
|
+
pending = sig;
|
|
222
|
+
setTimeout(raise, SIGNAL_GRACE_MS);
|
|
223
|
+
}
|
|
224
|
+
settle();
|
|
225
|
+
};
|
|
226
|
+
function raise() {
|
|
227
|
+
const sig = pending;
|
|
228
|
+
if (!sig)
|
|
229
|
+
return;
|
|
230
|
+
unhook();
|
|
231
|
+
process.kill(process.pid, sig);
|
|
232
|
+
}
|
|
233
|
+
function settle() {
|
|
234
|
+
if (holds > 0 || live.size > 0)
|
|
235
|
+
return;
|
|
236
|
+
if (pending)
|
|
237
|
+
raise();
|
|
238
|
+
else
|
|
239
|
+
unhook();
|
|
240
|
+
}
|
|
241
|
+
var onExit = () => {
|
|
242
|
+
for (const c of live)
|
|
243
|
+
stopTree(c, "SIGKILL");
|
|
244
|
+
};
|
|
245
|
+
var hooked = false;
|
|
246
|
+
function hook() {
|
|
247
|
+
if (hooked)
|
|
248
|
+
return;
|
|
249
|
+
hooked = true;
|
|
250
|
+
for (const s of SIGNALS)
|
|
251
|
+
process.prependListener(s, onSignal);
|
|
252
|
+
process.on("exit", onExit);
|
|
253
|
+
}
|
|
254
|
+
function unhook() {
|
|
255
|
+
if (!hooked)
|
|
256
|
+
return;
|
|
257
|
+
hooked = false;
|
|
258
|
+
for (const s of SIGNALS)
|
|
259
|
+
process.off(s, onSignal);
|
|
260
|
+
process.off("exit", onExit);
|
|
261
|
+
}
|
|
262
|
+
function holdSignals() {
|
|
263
|
+
holds++;
|
|
264
|
+
hook();
|
|
265
|
+
let released = false;
|
|
266
|
+
return () => {
|
|
267
|
+
if (released)
|
|
268
|
+
return;
|
|
269
|
+
released = true;
|
|
270
|
+
holds--;
|
|
271
|
+
settle();
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
var track = (c) => {
|
|
275
|
+
live.add(c);
|
|
276
|
+
hook();
|
|
277
|
+
};
|
|
278
|
+
var untrack = (c) => {
|
|
279
|
+
live.delete(c);
|
|
280
|
+
settle();
|
|
281
|
+
};
|
|
282
|
+
var STOP_GRACE_MS = 5e3;
|
|
159
283
|
function shellCommandRunner() {
|
|
160
284
|
return (command, cwd, o = {}) => new Promise((resolve) => {
|
|
285
|
+
if (stopping) {
|
|
286
|
+
resolve({ exitCode: null, stdout: "", stderr: "Atticus is stopping.", stopped: true });
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
161
289
|
const child = spawn(command, {
|
|
162
290
|
cwd,
|
|
163
291
|
shell: true,
|
|
164
292
|
env: { ...process.env, ...o.env },
|
|
165
|
-
windowsHide: true
|
|
293
|
+
windowsHide: true,
|
|
294
|
+
// Its own process group off Windows, so a timeout stops the build, not only the shell.
|
|
295
|
+
detached: process.platform !== "win32"
|
|
166
296
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
297
|
+
track(child);
|
|
298
|
+
const out = tail();
|
|
299
|
+
const err = tail();
|
|
300
|
+
let done2 = false;
|
|
301
|
+
let kill;
|
|
302
|
+
let drain;
|
|
303
|
+
const finish2 = (r) => {
|
|
304
|
+
if (done2)
|
|
305
|
+
return;
|
|
306
|
+
done2 = true;
|
|
173
307
|
clearTimeout(timer);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
308
|
+
clearTimeout(kill);
|
|
309
|
+
clearTimeout(drain);
|
|
310
|
+
untrack(child);
|
|
311
|
+
resolve(stopping ? { ...r, stopped: true } : r);
|
|
312
|
+
};
|
|
313
|
+
const timer = setTimeout(() => {
|
|
314
|
+
stopTree(child);
|
|
315
|
+
kill = setTimeout(() => stopTree(child, "SIGKILL"), STOP_GRACE_MS);
|
|
316
|
+
}, o.timeoutMs ?? 30 * 6e4);
|
|
317
|
+
child.stdout.setEncoding("utf8").on("data", (d) => out.add(d));
|
|
318
|
+
child.stderr.setEncoding("utf8").on("data", (d) => err.add(d));
|
|
319
|
+
child.on("error", (e) => finish2({ exitCode: null, stdout: out.text, stderr: err.text + e.message }));
|
|
320
|
+
child.on("exit", (code) => {
|
|
321
|
+
drain = setTimeout(() => finish2({ exitCode: code, stdout: out.text, stderr: err.text }), 2e3);
|
|
179
322
|
});
|
|
323
|
+
child.on("close", (code) => finish2({ exitCode: code, stdout: out.text, stderr: err.text }));
|
|
180
324
|
});
|
|
181
325
|
}
|
|
182
326
|
|
|
@@ -189,13 +333,16 @@ var TaskRunState = external_exports.enum([
|
|
|
189
333
|
"planned",
|
|
190
334
|
/** Hand-off mode: the person's assistant is doing the step. */
|
|
191
335
|
"waiting",
|
|
192
|
-
/**
|
|
336
|
+
/**
|
|
337
|
+
* Draft finished with a passing build, committed on the task branch. Also a PR that wasn't
|
|
338
|
+
* raised (the push or the Git host failed): its note says why, and it can be raised again.
|
|
339
|
+
*/
|
|
193
340
|
"built",
|
|
194
341
|
/** Draft finished but the repo has no build command, so nothing was checked. */
|
|
195
342
|
"unverified",
|
|
196
343
|
/** The PR from the task branch to the change branch is open. */
|
|
197
344
|
"pr-open",
|
|
198
|
-
/** The build still fails after the allowed fix rounds, or a
|
|
345
|
+
/** The build still fails after the allowed fix rounds, or a step after it can't be done: a person takes over. */
|
|
199
346
|
"needs-person",
|
|
200
347
|
/** The AI run itself failed. */
|
|
201
348
|
"failed"
|
|
@@ -234,6 +381,16 @@ var TaskRunRecord = external_exports.strictObject({
|
|
|
234
381
|
changed: external_exports.array(external_exports.string()).default([]),
|
|
235
382
|
commit: external_exports.string().optional(),
|
|
236
383
|
pr: external_exports.strictObject({ number: external_exports.number().int().positive(), url: external_exports.string() }).optional(),
|
|
384
|
+
/**
|
|
385
|
+
* Seventh UX walk: when Atticus ticked the task in tasks.md because its PR merged. It ticks a
|
|
386
|
+
* task once, so a person who unticks it keeps it unticked.
|
|
387
|
+
*/
|
|
388
|
+
ticked: external_exports.string().optional(),
|
|
389
|
+
/**
|
|
390
|
+
* Eighth UX walk: who last ticked (done) or unticked the task by hand on the Task board, and
|
|
391
|
+
* when, so a task Atticus ticked and a person ticked again says who did.
|
|
392
|
+
*/
|
|
393
|
+
marked: external_exports.strictObject({ done: external_exports.boolean(), by: external_exports.string().min(1), at: external_exports.string() }).optional(),
|
|
237
394
|
startedAt: external_exports.string(),
|
|
238
395
|
finishedAt: external_exports.string().optional(),
|
|
239
396
|
notes: external_exports.array(external_exports.string()).default([])
|
|
@@ -266,6 +423,23 @@ async function saveRunSummary(root, change, task, s) {
|
|
|
266
423
|
await writeFileAtomic(join2(changeFolder(root, change), rel), toCanonicalYaml(RunSummary.parse(s), ["schemaVersion", "runId"]));
|
|
267
424
|
return rel;
|
|
268
425
|
}
|
|
426
|
+
async function taskRunOfRun(root, change, runId) {
|
|
427
|
+
for (const t of (await readdir(join2(changeFolder(root, change), "tasks"), { withFileTypes: true }).catch(() => [])).filter((d) => d.isDirectory())) {
|
|
428
|
+
const r = await readTaskRun(root, change, t.name).catch(() => void 0);
|
|
429
|
+
if (r && (r.waiting === runId || r.runs.includes(runId)))
|
|
430
|
+
return r;
|
|
431
|
+
}
|
|
432
|
+
return void 0;
|
|
433
|
+
}
|
|
434
|
+
async function findTaskRunOfRun(root, runId) {
|
|
435
|
+
const changes = changesDirOf(root);
|
|
436
|
+
for (const c of (await readdir(changes, { withFileTypes: true }).catch(() => [])).filter((d) => d.isDirectory() && d.name !== "archive")) {
|
|
437
|
+
const r = await taskRunOfRun(root, c.name, runId).catch(() => void 0);
|
|
438
|
+
if (r)
|
|
439
|
+
return r;
|
|
440
|
+
}
|
|
441
|
+
return void 0;
|
|
442
|
+
}
|
|
269
443
|
async function findWaitingTaskRun(root, runId) {
|
|
270
444
|
const changes = changesDirOf(root);
|
|
271
445
|
for (const c of (await readdir(changes, { withFileTypes: true }).catch(() => [])).filter((d) => d.isDirectory())) {
|
|
@@ -374,30 +548,34 @@ ${s.body.trim()}`,
|
|
|
374
548
|
trusted: true
|
|
375
549
|
}))
|
|
376
550
|
];
|
|
377
|
-
const artifact = (rel, priority) => {
|
|
551
|
+
const artifact = (rel, priority, text = (raw) => raw) => {
|
|
378
552
|
const d = t.files.docs.get(rel);
|
|
379
553
|
if (d)
|
|
380
554
|
sources.push({
|
|
381
555
|
id: rel,
|
|
382
556
|
kind: "artifact",
|
|
383
557
|
origin: `${changesRelOf(t.root)}/${t.change.id}/${rel}`,
|
|
384
|
-
text: d.raw,
|
|
558
|
+
text: text(d.raw),
|
|
385
559
|
classification: "internal",
|
|
386
560
|
priority
|
|
387
561
|
});
|
|
388
562
|
};
|
|
389
|
-
const context = await taskContext(t.root, t.change.id, t.task.id
|
|
563
|
+
const context = await taskContext(t.root, t.change.id, t.task.id, {
|
|
564
|
+
at: { worktree: p.worktreeRel, branch: taskBranch(t.change.id, t.task.id) }
|
|
565
|
+
}).catch(() => void 0);
|
|
390
566
|
if (context)
|
|
391
567
|
sources.push({
|
|
392
568
|
id: "task-context",
|
|
393
569
|
kind: "artifact",
|
|
394
570
|
origin: `atticus task context ${t.change.id} ${t.task.id}`,
|
|
395
|
-
|
|
571
|
+
// The pack wraps and screens the whole file as one source, so its parts aren't fenced
|
|
572
|
+
// again inside it (review round 47).
|
|
573
|
+
text: renderTaskContext(context, { fence: false }).replace(/\r\n/g, "\n"),
|
|
396
574
|
classification: "internal",
|
|
397
575
|
priority: 35
|
|
398
576
|
});
|
|
399
577
|
for (const s of t.task.stories)
|
|
400
|
-
artifact(`stories/${s}.md`, 30);
|
|
578
|
+
artifact(`stories/${s}.md`, 30, (raw) => withBuildLine(raw, t.repo.id, t.repo.build));
|
|
401
579
|
for (const a of ["design.md", "interfaces.md", "mappings.md", "data.md"])
|
|
402
580
|
artifact(a, 20);
|
|
403
581
|
const needs = await readIf(join3(t.root, ...changesRelOf(t.root).split("/"), t.change.id, "needs.md"));
|
|
@@ -501,6 +679,7 @@ function gitScanAt(root, git) {
|
|
|
501
679
|
return {
|
|
502
680
|
records: s.records,
|
|
503
681
|
files,
|
|
682
|
+
basis: s.basis?.[repo] ?? { from: "readers" },
|
|
504
683
|
problems: s.problems.filter((p) => !p.repo || p.repo === repo).map((p) => `${p.repo ? `${p.repo}: ` : ""}${p.source}: ${p.message}`)
|
|
505
684
|
};
|
|
506
685
|
} finally {
|
|
@@ -654,7 +833,8 @@ async function conformChange(root, change, o = {}) {
|
|
|
654
833
|
tasks,
|
|
655
834
|
before: before.records,
|
|
656
835
|
after: after.records,
|
|
657
|
-
files: after.files
|
|
836
|
+
files: after.files,
|
|
837
|
+
basis: after.basis
|
|
658
838
|
});
|
|
659
839
|
const count = (s) => r.items.filter((i) => i.status === s).length;
|
|
660
840
|
const result = {
|
|
@@ -814,7 +994,7 @@ async function aiStep(c, buildLog) {
|
|
|
814
994
|
if (c.runtime instanceof HandoffRuntime) {
|
|
815
995
|
await writeFile2(join5(runsDirOf(c.root), request.change, prepared.runId, "prompt.md"), handoffPrompt(c, prepared), "utf8");
|
|
816
996
|
}
|
|
817
|
-
const run = await c.runtime.run(prepared.runId);
|
|
997
|
+
const run = await c.runtime.run(prepared.runId, stopSignal);
|
|
818
998
|
await summarise(c, run);
|
|
819
999
|
return run;
|
|
820
1000
|
}
|
|
@@ -827,7 +1007,7 @@ function handoffPrompt(c, run) {
|
|
|
827
1007
|
"",
|
|
828
1008
|
run.request.pack.prompt.trimEnd(),
|
|
829
1009
|
"",
|
|
830
|
-
`When you are done, run: atticus handoff done ${run.runId}`,
|
|
1010
|
+
c.record.level === "pr" ? `When you are done, stop and ask the person to run: atticus handoff done ${run.runId} --approve (it pushes the branch and opens a PR, so the person runs it, never you)` : `When you are done, run: atticus handoff done ${run.runId}`,
|
|
831
1011
|
""
|
|
832
1012
|
].join("\n");
|
|
833
1013
|
}
|
|
@@ -837,6 +1017,8 @@ async function build(c, runId, fixRun) {
|
|
|
837
1017
|
return void 0;
|
|
838
1018
|
const n = c.record.attempts.length + 1;
|
|
839
1019
|
const res = await c.commands(command, c.worktree);
|
|
1020
|
+
if (res.stopped)
|
|
1021
|
+
c.stopped = true;
|
|
840
1022
|
const logRel = `${runsRelOf(c.root)}/${c.t.change.id}/${runId}/build-${n}.log`;
|
|
841
1023
|
await mkdir3(join5(runsDirOf(c.root), c.t.change.id, runId), { recursive: true });
|
|
842
1024
|
await writeFile2(join5(c.root, logRel), `$ ${command}
|
|
@@ -856,14 +1038,24 @@ ${res.stderr}` : ""}
|
|
|
856
1038
|
c.record.attempts.push(a);
|
|
857
1039
|
return a;
|
|
858
1040
|
}
|
|
1041
|
+
async function changedFiles(c) {
|
|
1042
|
+
const r = await c.git(["-c", "core.quotePath=false", "status", "--porcelain", "-z"], c.worktree);
|
|
1043
|
+
const parts = r.stdout.split("\0").filter(Boolean);
|
|
1044
|
+
const out = [];
|
|
1045
|
+
for (let k = 0; k < parts.length; k++) {
|
|
1046
|
+
const e = parts[k];
|
|
1047
|
+
if (/^[RC]/.test(e))
|
|
1048
|
+
k++;
|
|
1049
|
+
if (e.slice(3))
|
|
1050
|
+
out.push(e.slice(3));
|
|
1051
|
+
}
|
|
1052
|
+
return out;
|
|
1053
|
+
}
|
|
859
1054
|
async function applyAnswer(c, run) {
|
|
860
1055
|
if (c.runtime.kind === "headless-claude-code") {
|
|
861
|
-
const
|
|
862
|
-
for (const l of changed.stdout.split("\n").filter(Boolean)) {
|
|
863
|
-
const p = l.slice(3).trim();
|
|
1056
|
+
for (const p of await changedFiles(c))
|
|
864
1057
|
if (!c.record.changed.includes(p))
|
|
865
1058
|
c.record.changed.push(p);
|
|
866
|
-
}
|
|
867
1059
|
await writeReport(c, run.output ?? "");
|
|
868
1060
|
return [];
|
|
869
1061
|
}
|
|
@@ -892,7 +1084,8 @@ async function buildAndFix(c, runId) {
|
|
|
892
1084
|
return;
|
|
893
1085
|
}
|
|
894
1086
|
let fixes = 0;
|
|
895
|
-
|
|
1087
|
+
const halted = () => c.stopped || stopRequested();
|
|
1088
|
+
while (!a.passed && !halted() && fixes < c.maxFix && c.runtime.kind !== "hand-off") {
|
|
896
1089
|
fixes++;
|
|
897
1090
|
const log = await import("node:fs/promises").then((fs) => fs.readFile(join5(c.root, a.log), "utf8"));
|
|
898
1091
|
const fix = await aiStep(c, { command: a.command, text: log, attempt: fixes });
|
|
@@ -900,6 +1093,8 @@ async function buildAndFix(c, runId) {
|
|
|
900
1093
|
c.record.notes.push(`Fix round ${fixes} failed: ${fix.errors.join("; ") || fix.state}.`);
|
|
901
1094
|
break;
|
|
902
1095
|
}
|
|
1096
|
+
if (halted())
|
|
1097
|
+
break;
|
|
903
1098
|
const problems = await applyAnswer(c, fix);
|
|
904
1099
|
if (problems.length) {
|
|
905
1100
|
c.record.notes.push(`Fix round ${fixes} was not applied: ${problems.join("; ")}.`);
|
|
@@ -907,6 +1102,11 @@ async function buildAndFix(c, runId) {
|
|
|
907
1102
|
}
|
|
908
1103
|
a = await build(c, runId, fix.runId);
|
|
909
1104
|
}
|
|
1105
|
+
if (halted()) {
|
|
1106
|
+
c.record.state = "needs-person";
|
|
1107
|
+
c.record.notes.push(`Atticus was stopped while the build ran, so nothing more was done; a person takes over in ${c.record.worktree}. See ${a.log}.`);
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
910
1110
|
if (!a.passed) {
|
|
911
1111
|
c.record.state = "needs-person";
|
|
912
1112
|
c.record.notes.push(`The build still fails after ${fixes} fix round${fixes === 1 ? "" : "s"}; a person takes over in ${c.record.worktree}. See ${a.log}.`);
|
|
@@ -918,8 +1118,15 @@ async function commit(c, runId) {
|
|
|
918
1118
|
await c.git(["add", "-A", "--", "."], c.worktree);
|
|
919
1119
|
const staged = (await c.git(["diff", "--cached", "--name-only"], c.worktree)).stdout.trim();
|
|
920
1120
|
if (!staged) {
|
|
921
|
-
|
|
922
|
-
|
|
1121
|
+
const own = await ownTaskCommit(c);
|
|
1122
|
+
if (own) {
|
|
1123
|
+
c.record.commit = own;
|
|
1124
|
+
c.record.notes.push(`Nothing new to commit: ${c.record.branch} already has this task's commit ${own.slice(0, 12)}, ahead of ${changeBranch(c.t.change.id)}, so it is the one built and raised.`);
|
|
1125
|
+
return true;
|
|
1126
|
+
}
|
|
1127
|
+
c.record.state = "needs-person";
|
|
1128
|
+
c.record.notes.push(`The AI's answer changed nothing in ${c.record.branch}, so there is nothing to commit: run the task again, or do it by hand in ${c.record.worktree}.`);
|
|
1129
|
+
return false;
|
|
923
1130
|
}
|
|
924
1131
|
await c.git([
|
|
925
1132
|
"commit",
|
|
@@ -933,10 +1140,22 @@ Atticus-Run: ${runId}
|
|
|
933
1140
|
Requested-By: ${c.record.by}`
|
|
934
1141
|
], c.worktree);
|
|
935
1142
|
c.record.commit = (await c.git(["rev-parse", "HEAD"], c.worktree)).stdout.trim();
|
|
1143
|
+
return true;
|
|
1144
|
+
}
|
|
1145
|
+
async function ownTaskCommit(c) {
|
|
1146
|
+
const base = changeBranch(c.t.change.id);
|
|
1147
|
+
const log = await c.git(["log", "--format=%B%x00", `refs/heads/${base}..HEAD`], c.worktree).catch(() => ({ stdout: "" }));
|
|
1148
|
+
const mine = log.stdout.split("\0").some((m) => {
|
|
1149
|
+
const lines = m.split("\n").map((l) => l.trim());
|
|
1150
|
+
return lines.includes(`Atticus-Change: ${c.t.change.id}`) && lines.includes(`Atticus-Task: ${c.t.task.id}`);
|
|
1151
|
+
});
|
|
1152
|
+
if (!mine)
|
|
1153
|
+
return void 0;
|
|
1154
|
+
return (await c.git(["rev-parse", "HEAD"], c.worktree)).stdout.trim() || void 0;
|
|
936
1155
|
}
|
|
937
1156
|
async function openPr(c) {
|
|
938
1157
|
if (c.record.state !== "built") {
|
|
939
|
-
c.record.notes.push(c.record.state === "unverified" ?
|
|
1158
|
+
c.record.notes.push(c.record.state === "unverified" ? `No PR: a pull request needs a passing build, and ${c.t.repo.id} has no build command: set a build command for ${c.t.repo.id} (build: under its entry in repos.manifest.yaml), then run task ${c.t.task.id} again.` : "No PR: the build doesn't pass.");
|
|
940
1159
|
if (c.record.state === "unverified")
|
|
941
1160
|
c.record.state = "needs-person";
|
|
942
1161
|
return;
|
|
@@ -948,20 +1167,25 @@ async function openPr(c) {
|
|
|
948
1167
|
return;
|
|
949
1168
|
}
|
|
950
1169
|
const base = changeBranch(c.t.change.id);
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
"push",
|
|
959
|
-
"-q",
|
|
960
|
-
"origin",
|
|
961
|
-
`refs/heads/${base}:refs/heads/${base}`,
|
|
962
|
-
`refs/heads/${c.record.branch}:refs/heads/${c.record.branch}`
|
|
963
|
-
], c.worktree);
|
|
1170
|
+
if (!c.record.commit)
|
|
1171
|
+
throw new TaskRunError("refused", `Task ${c.t.task.id} has no commit to raise: run the task again, or do it by hand in ${c.record.worktree}.`);
|
|
1172
|
+
const head = (await c.git(["rev-parse", "--verify", "-q", `refs/heads/${c.record.branch}`], c.worktree).catch(() => ({ stdout: "" }))).stdout.trim();
|
|
1173
|
+
if (!head)
|
|
1174
|
+
throw new TaskRunError("refused", `Task ${c.t.task.id}'s branch ${c.record.branch} isn't in ${c.record.worktree} any more: run the task again.`);
|
|
1175
|
+
if (head !== c.record.commit)
|
|
1176
|
+
throw new TaskRunError("refused", `Task ${c.t.task.id}'s branch ${c.record.branch} has commits that weren't built (it is at ${head.slice(0, 12)}; the build passed at ${c.record.commit.slice(0, 12)}): run the task again so its build checks them, or push ${c.record.branch} and open its PR into ${base} yourself.`);
|
|
964
1177
|
try {
|
|
1178
|
+
const info = await c.gitHost.getRepo(c.t.repo.id);
|
|
1179
|
+
for (const b of [c.record.branch, base])
|
|
1180
|
+
if (info.protectedBranches.includes(b))
|
|
1181
|
+
throw new TaskRunError("refused", `${b} is protected in ${c.t.repo.id}; Run with AI never pushes to or opens a PR into a protected branch.`);
|
|
1182
|
+
if (base === info.defaultBranch)
|
|
1183
|
+
throw new TaskRunError("refused", `${base} is ${c.t.repo.id}'s default branch; task PRs go into the change branch.`);
|
|
1184
|
+
const onHost = (await c.git(["ls-remote", "--heads", "origin", `refs/heads/${base}`], c.worktree)).stdout.trim();
|
|
1185
|
+
const refs = [`refs/heads/${c.record.branch}:refs/heads/${c.record.branch}`];
|
|
1186
|
+
if (!onHost)
|
|
1187
|
+
refs.unshift(`refs/heads/${base}:refs/heads/${base}`);
|
|
1188
|
+
await c.git(["push", "-q", ...refs.length > 1 ? ["--atomic"] : [], "origin", ...refs], c.worktree);
|
|
965
1189
|
const pr = await c.gitHost.createPullRequest({
|
|
966
1190
|
repo: c.t.repo.id,
|
|
967
1191
|
head: c.record.branch,
|
|
@@ -979,15 +1203,27 @@ async function openPr(c) {
|
|
|
979
1203
|
c.record.pr = { number: pr.number, url: pr.url };
|
|
980
1204
|
c.record.state = "pr-open";
|
|
981
1205
|
} catch (e) {
|
|
982
|
-
if (e instanceof
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1206
|
+
if (e instanceof TaskRunError)
|
|
1207
|
+
throw e;
|
|
1208
|
+
if (e instanceof AdapterError && e.code === "conflict") {
|
|
1209
|
+
const open = (await c.gitHost.listPullRequests(c.t.repo.id, { head: c.record.branch }).catch(() => [])).filter((p) => p.base === base && (p.state === "open" || p.state === "draft")).at(0);
|
|
1210
|
+
if (open) {
|
|
1211
|
+
c.record.pr = { number: open.number, url: open.url };
|
|
1212
|
+
c.record.state = "pr-open";
|
|
1213
|
+
c.record.notes.push(`PR #${open.number} from ${c.record.branch} into ${base} was already open on the Git host; recorded it (${open.url}).`);
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
986
1216
|
}
|
|
987
|
-
|
|
1217
|
+
c.record.notes.push(`${PR_NOT_RAISED} ${(e instanceof Error ? e.message : String(e)).replace(/\.?$/, ".")} The build still passes: fix that and raise the task's PR again (Raise the task's PR on the Task board), or push ${c.record.branch} and open its PR into ${base} yourself.`);
|
|
988
1218
|
}
|
|
989
1219
|
}
|
|
1220
|
+
var PR_NOT_RAISED = "The PR wasn't raised:";
|
|
990
1221
|
async function finish(c, run) {
|
|
1222
|
+
if (stopRequested()) {
|
|
1223
|
+
c.record.state = "needs-person";
|
|
1224
|
+
c.record.notes.push(c.runtime.kind === "headless-claude-code" ? `Atticus was stopped while Claude Code worked, so nothing more was done; the worktree ${c.record.worktree} may hold some of its edits.` : `Atticus was stopped before the answer was applied, so nothing was written; run the task again.`);
|
|
1225
|
+
return done(c);
|
|
1226
|
+
}
|
|
991
1227
|
if (c.record.level === "plan") {
|
|
992
1228
|
if (c.runtime.kind !== "hand-off")
|
|
993
1229
|
await writeFileAtomic(join5(changeFolder(c.root, c.t.change.id), run.request.outputPath), `${(run.output ?? "").trim()}
|
|
@@ -1003,45 +1239,255 @@ async function finish(c, run) {
|
|
|
1003
1239
|
}
|
|
1004
1240
|
}
|
|
1005
1241
|
await buildAndFix(c, run.runId);
|
|
1006
|
-
|
|
1007
|
-
|
|
1242
|
+
await afterBuild(c, run.runId, c.record.state === "built" || c.record.state === "unverified");
|
|
1243
|
+
}
|
|
1244
|
+
return done(c);
|
|
1245
|
+
}
|
|
1246
|
+
async function afterBuild(c, runId, commitIt, first) {
|
|
1247
|
+
try {
|
|
1248
|
+
await first?.();
|
|
1249
|
+
if (commitIt && !await commit(c, runId))
|
|
1250
|
+
return;
|
|
1008
1251
|
await conformAfterBuild(c);
|
|
1009
1252
|
if (c.record.level === "pr")
|
|
1010
1253
|
await openPr(c);
|
|
1254
|
+
} catch (e) {
|
|
1255
|
+
c.record.state = "needs-person";
|
|
1256
|
+
c.record.notes.push(`${e instanceof Error ? e.message : String(e)} \u2014 the work is in ${c.record.worktree} (branch ${c.record.branch}): finish it there by hand, or fix that and run the task again.`);
|
|
1011
1257
|
}
|
|
1012
|
-
return done(c);
|
|
1013
1258
|
}
|
|
1014
1259
|
async function done(c) {
|
|
1015
1260
|
delete c.record.waiting;
|
|
1016
1261
|
c.record.finishedAt = stamp2(c.now());
|
|
1017
1262
|
return saveTaskRun(c.root, c.record);
|
|
1018
1263
|
}
|
|
1264
|
+
function levelOf(t, asked) {
|
|
1265
|
+
const rt = t.ctx.orgPack.runtime;
|
|
1266
|
+
const cap = rt.autonomy.capPerRepo[t.repo.id];
|
|
1267
|
+
const capped = cap ? AUTONOMY[cap] : void 0;
|
|
1268
|
+
if (asked === void 0) {
|
|
1269
|
+
const level = AUTONOMY[rt.autonomy.default];
|
|
1270
|
+
return capped && LEVEL_RANK[level] > LEVEL_RANK[capped] ? capped : level;
|
|
1271
|
+
}
|
|
1272
|
+
if (capped && LEVEL_RANK[asked] > LEVEL_RANK[capped])
|
|
1273
|
+
throw new TaskRunError("refused", `${t.repo.id} allows Run with AI up to ${cap} (runtime.yaml autonomy.capPerRepo); ask for a lower level.`);
|
|
1274
|
+
return asked;
|
|
1275
|
+
}
|
|
1276
|
+
async function ownTaskPr(host, r, held) {
|
|
1277
|
+
const pr = await host.getPullRequest(r.repo, held.number);
|
|
1278
|
+
if (pr.head === r.branch)
|
|
1279
|
+
return pr;
|
|
1280
|
+
const mine = await host.listPullRequests(r.repo, { head: r.branch });
|
|
1281
|
+
const own = mine.find((x) => x.url === held.url) ?? mine.at(-1);
|
|
1282
|
+
if (own)
|
|
1283
|
+
return own;
|
|
1284
|
+
throw new TaskRunError("refused", `PR #${held.number} on the Git host is from ${pr.head}, not ${r.branch}, and no PR from ${r.branch} was found`);
|
|
1285
|
+
}
|
|
1286
|
+
async function refuseIfHeld(root, t, host, git) {
|
|
1287
|
+
const before = await readTaskRun(root, t.change.id, t.task.id);
|
|
1288
|
+
if (before?.state === "pr-open") {
|
|
1289
|
+
let state;
|
|
1290
|
+
let why = "";
|
|
1291
|
+
try {
|
|
1292
|
+
const h = host();
|
|
1293
|
+
if (!h)
|
|
1294
|
+
why = "no Git host is connected (runtime.yaml adapters.gitHost)";
|
|
1295
|
+
else if (before.pr)
|
|
1296
|
+
state = (await ownTaskPr(h, before, before.pr)).state;
|
|
1297
|
+
} catch (e) {
|
|
1298
|
+
why = e instanceof Error ? e.message : String(e);
|
|
1299
|
+
}
|
|
1300
|
+
if (before.pr && (state === "merged" || state === "closed")) {
|
|
1301
|
+
const own = await taskBranchOwnCommits(root, t.change.id, t.task.id, t.repo.id, git);
|
|
1302
|
+
if (own > 0) {
|
|
1303
|
+
const branch = taskBranch(t.change.id, t.task.id);
|
|
1304
|
+
const from = changeBranch(t.change.id);
|
|
1305
|
+
const clone = baseClonePath(root, t.repo.id);
|
|
1306
|
+
const carried = state === "closed" ? "the commits that PR carried" : "commits the change branch hasn't (a squash or rebase merge took them in another form)";
|
|
1307
|
+
throw new TaskRunError("refused", `Task ${t.task.id}'s earlier PR ${before.pr.url} is ${state}, and its branch ${branch} still has ${carried} (${own} not in ${from}): running the task again would raise them again. Atticus doesn't delete or rewrite them. To start the task afresh, remove its worktree and branch here (git -C ${clone} worktree remove ${join5(root, before.worktree)}, then git -C ${clone} branch -D ${branch}) and delete ${branch} on the Git host, then run the task again; or ask whoever looks after the workspace for a fresh start.`);
|
|
1308
|
+
}
|
|
1309
|
+
return { notes: [`Its earlier PR ${before.pr.url} is ${state}.`], settled: true };
|
|
1310
|
+
}
|
|
1311
|
+
throw new TaskRunError("refused", `Task ${t.task.id}'s PR is open (${before.pr?.url ?? "see its run"}): running the task again would start over beside it. Merge or close the PR first, then run the task again.${why ? ` (Atticus couldn't ask the Git host whether it still is: ${why}.)` : ""}`);
|
|
1312
|
+
}
|
|
1313
|
+
const open = ["prepared", "waiting", "produced", "failed"];
|
|
1314
|
+
if (before?.state === "waiting" && before.waiting && open.includes(await handoffRunState(root, t.change.id, before.waiting) ?? ""))
|
|
1315
|
+
throw new TaskRunError("refused", `Task ${t.task.id} already waits on your assistant (run ${before.waiting}, in ${before.worktree}): finish it with Done on its run page (Model runs) or atticus handoff done ${before.waiting}, or Cancel it there and run the task again.`);
|
|
1316
|
+
return { notes: [] };
|
|
1317
|
+
}
|
|
1318
|
+
async function taskPrState(root, changeId, taskId, o = {}) {
|
|
1319
|
+
const r = await readTaskRun(root, changeId, taskId).catch(() => void 0);
|
|
1320
|
+
if (r?.state !== "pr-open" || !r.pr)
|
|
1321
|
+
return void 0;
|
|
1322
|
+
const pr = r.pr;
|
|
1323
|
+
const ask = async () => {
|
|
1324
|
+
const host = o.gitHost ?? gitHostOf(root, await loadTask(root, changeId, taskId));
|
|
1325
|
+
if (!host)
|
|
1326
|
+
return void 0;
|
|
1327
|
+
const s = (await ownTaskPr(host, r, pr)).state;
|
|
1328
|
+
return s === "merged" || s === "closed" ? s : "open";
|
|
1329
|
+
};
|
|
1330
|
+
let timer;
|
|
1331
|
+
const late = new Promise((res) => {
|
|
1332
|
+
timer = setTimeout(() => res(void 0), o.timeoutMs ?? 3e3);
|
|
1333
|
+
});
|
|
1334
|
+
try {
|
|
1335
|
+
return await Promise.race([ask(), late]);
|
|
1336
|
+
} catch {
|
|
1337
|
+
return void 0;
|
|
1338
|
+
} finally {
|
|
1339
|
+
clearTimeout(timer);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
async function settleTaskPr(root, changeId, taskId, o = {}) {
|
|
1343
|
+
const r = await readTaskRun(root, changeId, taskId).catch(() => void 0);
|
|
1344
|
+
if (r?.state !== "pr-open" || !r.pr)
|
|
1345
|
+
return {};
|
|
1346
|
+
const recorded = r.pr;
|
|
1347
|
+
const ask = async () => {
|
|
1348
|
+
const host = o.gitHost ?? gitHostOf(root, await loadTask(root, changeId, taskId));
|
|
1349
|
+
if (!host)
|
|
1350
|
+
return void 0;
|
|
1351
|
+
return ownTaskPr(host, r, recorded);
|
|
1352
|
+
};
|
|
1353
|
+
let timer;
|
|
1354
|
+
const late = new Promise((res) => {
|
|
1355
|
+
timer = setTimeout(() => res(void 0), o.timeoutMs ?? 3e3);
|
|
1356
|
+
});
|
|
1357
|
+
const pr = await Promise.race([ask(), late]).catch(() => void 0).finally(() => clearTimeout(timer));
|
|
1358
|
+
if (!pr)
|
|
1359
|
+
return {};
|
|
1360
|
+
const state = pr.state === "merged" || pr.state === "closed" ? pr.state : "open";
|
|
1361
|
+
const cur = await readTaskRun(root, changeId, taskId).catch(() => void 0);
|
|
1362
|
+
if (cur?.state !== "pr-open" || cur.pr?.url !== recorded.url)
|
|
1363
|
+
return { state };
|
|
1364
|
+
let changed = false;
|
|
1365
|
+
if (pr.number !== recorded.number || pr.url !== recorded.url) {
|
|
1366
|
+
cur.pr = { number: pr.number, url: pr.url };
|
|
1367
|
+
changed = true;
|
|
1368
|
+
}
|
|
1369
|
+
let ticked = false;
|
|
1370
|
+
if (state === "merged" && !cur.ticked) {
|
|
1371
|
+
ticked = await setTaskDone(root, changeId, taskId, true);
|
|
1372
|
+
cur.ticked = stamp2((o.now ?? (() => /* @__PURE__ */ new Date()))());
|
|
1373
|
+
if (ticked)
|
|
1374
|
+
cur.notes.push(`Ticked ${taskId} in tasks.md: PR #${pr.number} merged on the Git host. The tick rides the change's build hand-off.`);
|
|
1375
|
+
changed = true;
|
|
1376
|
+
}
|
|
1377
|
+
if (changed)
|
|
1378
|
+
await saveTaskRun(root, cur);
|
|
1379
|
+
return { state, ...ticked ? { ticked: true } : {} };
|
|
1380
|
+
}
|
|
1381
|
+
function gitHostConnected(root, t, given) {
|
|
1382
|
+
try {
|
|
1383
|
+
return !!(given ?? gitHostOf(root, t));
|
|
1384
|
+
} catch {
|
|
1385
|
+
return false;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
async function previewTaskRun(root, changeId, taskId, o = {}) {
|
|
1389
|
+
const t = await loadTask(root, changeId, taskId);
|
|
1390
|
+
const level = levelOf(t, o.level);
|
|
1391
|
+
await refuseIfHeld(root, t, () => o.gitHost ?? gitHostOf(root, t), createGit());
|
|
1392
|
+
return {
|
|
1393
|
+
change: t.change.id,
|
|
1394
|
+
task: t.task.id,
|
|
1395
|
+
repo: t.repo.id,
|
|
1396
|
+
level,
|
|
1397
|
+
branch: taskBranch(t.change.id, t.task.id),
|
|
1398
|
+
gitHost: level === "pr" && !o.skipGitHost ? gitHostConnected(root, t, o.gitHost) : false
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
async function cancelTaskRunWait(root, runId, o) {
|
|
1402
|
+
const r = await findWaitingTaskRun(root, runId);
|
|
1403
|
+
if (!r) {
|
|
1404
|
+
await o.cancelRun?.();
|
|
1405
|
+
return void 0;
|
|
1406
|
+
}
|
|
1407
|
+
const lock = await holdTask(root, r.change, r.task);
|
|
1408
|
+
try {
|
|
1409
|
+
const cur = await findWaitingTaskRun(root, runId);
|
|
1410
|
+
await o.cancelRun?.();
|
|
1411
|
+
if (!cur)
|
|
1412
|
+
return void 0;
|
|
1413
|
+
delete cur.waiting;
|
|
1414
|
+
cur.state = "failed";
|
|
1415
|
+
cur.notes.push(`Run ${runId} was cancelled by ${o.by}, so nothing more was done; run the task again.`);
|
|
1416
|
+
cur.finishedAt = stamp2((o.now ?? (() => /* @__PURE__ */ new Date()))());
|
|
1417
|
+
return await saveTaskRun(root, cur);
|
|
1418
|
+
} finally {
|
|
1419
|
+
await lock.release();
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
async function handoffRunState(root, change, runId) {
|
|
1423
|
+
const text = await import("node:fs/promises").then((fs) => fs.readFile(join5(runsDirOf(root), change, runId, "run.json"), "utf8").catch(() => void 0));
|
|
1424
|
+
if (!text)
|
|
1425
|
+
return void 0;
|
|
1426
|
+
try {
|
|
1427
|
+
return JSON.parse(text).state;
|
|
1428
|
+
} catch {
|
|
1429
|
+
return void 0;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
async function holdTask(root, change, task) {
|
|
1433
|
+
try {
|
|
1434
|
+
return await acquireLock(root, `task-run-${change}-${task}`, `run of task ${task} of ${change}`, void 0, { maxAgeMs: 12 * 60 * 6e4 });
|
|
1435
|
+
} catch (e) {
|
|
1436
|
+
if (e instanceof LockHeldError)
|
|
1437
|
+
throw new TaskRunError("refused", e.message);
|
|
1438
|
+
throw e;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1019
1441
|
async function runTask(root, changeId, taskId, o) {
|
|
1442
|
+
const lock = await holdTask(root, changeId, taskId);
|
|
1443
|
+
const release = holdSignals();
|
|
1444
|
+
try {
|
|
1445
|
+
return await runTaskHeld(root, changeId, taskId, o);
|
|
1446
|
+
} finally {
|
|
1447
|
+
await lock.release();
|
|
1448
|
+
release();
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
async function runTaskHeld(root, changeId, taskId, o) {
|
|
1020
1452
|
const now = o.now ?? (() => /* @__PURE__ */ new Date());
|
|
1021
1453
|
const git = o.git ?? createGit();
|
|
1022
1454
|
let t = await loadTask(root, changeId, taskId);
|
|
1023
1455
|
const rt = t.ctx.orgPack.runtime;
|
|
1024
|
-
const level = o.level
|
|
1025
|
-
const
|
|
1026
|
-
if (cap && LEVEL_RANK[level] > LEVEL_RANK[AUTONOMY[cap]])
|
|
1027
|
-
throw new TaskRunError("refused", `${t.repo.id} allows Run with AI up to ${cap} (runtime.yaml autonomy.capPerRepo); ask for a lower level.`);
|
|
1456
|
+
const level = levelOf(t, o.level);
|
|
1457
|
+
const earlier = await refuseIfHeld(root, t, () => o.gitHost ?? gitHostOf(root, t), git);
|
|
1028
1458
|
if (level === "pr") {
|
|
1029
1459
|
try {
|
|
1030
1460
|
requireApproval("git-host", o.approval);
|
|
1031
1461
|
} catch {
|
|
1032
|
-
throw new TaskRunError("refused", "The pr level pushes the task branch and opens a PR, which needs
|
|
1462
|
+
throw new TaskRunError("refused", "The pr level pushes the task branch and opens a PR, which needs the person's yes: ask them to run it with --approve (an assistant never approves a push).");
|
|
1033
1463
|
}
|
|
1034
1464
|
}
|
|
1035
1465
|
const engine = buildEngineFor(t.ctx.orgPack, t.repo.id);
|
|
1036
1466
|
const changeDir = await changeWorktree(root, t.change.id, t.repo.id);
|
|
1037
1467
|
const handed = engine === "speckit" ? `specs/${t.task.id}/plan.md` : `.atticus/tasks/${t.task.id}.md`;
|
|
1038
|
-
const notes = [];
|
|
1468
|
+
const notes = [...earlier.notes];
|
|
1469
|
+
try {
|
|
1470
|
+
const caught = await catchUpChangeBranch(root, t.change.id, t.task.id, t.repo.id, changeDir, git, earlier.settled ? { settled: true } : {});
|
|
1471
|
+
if (caught)
|
|
1472
|
+
notes.push(caught);
|
|
1473
|
+
} catch (e) {
|
|
1474
|
+
if (e instanceof Error && e.name === "SpecKitError")
|
|
1475
|
+
throw new TaskRunError("refused", e.message);
|
|
1476
|
+
throw e;
|
|
1477
|
+
}
|
|
1039
1478
|
if (!existsSync2(join5(changeDir, handed))) {
|
|
1040
1479
|
const h = await handDown(root, t.change.id, t.task.id, { git });
|
|
1041
1480
|
notes.push(`Handed the task down first (${h.feature} in ${h.repo}${h.commit ? `, commit ${h.commit.slice(0, 12)}` : ""}).`);
|
|
1042
1481
|
t = await loadTask(root, changeId, taskId);
|
|
1043
1482
|
}
|
|
1044
|
-
|
|
1483
|
+
let wt;
|
|
1484
|
+
try {
|
|
1485
|
+
wt = await openTaskWorktree(root, t.change.id, t.task.id, t.repo.id, git, earlier.settled ? { fresh: true } : {});
|
|
1486
|
+
} catch (e) {
|
|
1487
|
+
if (e instanceof Error && e.name === "SpecKitError")
|
|
1488
|
+
throw new TaskRunError("refused", e.message);
|
|
1489
|
+
throw e;
|
|
1490
|
+
}
|
|
1045
1491
|
const runtime = o.runtime ?? await createRuntime(t.ctx.orgPack, {
|
|
1046
1492
|
root,
|
|
1047
1493
|
...o.mode ? { mode: o.mode } : {},
|
|
@@ -1097,16 +1543,36 @@ async function runTask(root, changeId, taskId, o) {
|
|
|
1097
1543
|
record.waiting = run.runId;
|
|
1098
1544
|
return saveTaskRun(root, record);
|
|
1099
1545
|
}
|
|
1100
|
-
if (run.state !== "validated") {
|
|
1546
|
+
if (run.state !== "validated" && !stopRequested()) {
|
|
1101
1547
|
record.notes.push(`The AI run ended ${run.state}: ${run.errors.join("; ") || "no reason given"}.`);
|
|
1102
1548
|
return done(c);
|
|
1103
1549
|
}
|
|
1104
1550
|
return finish(c, run);
|
|
1105
1551
|
}
|
|
1106
1552
|
async function completeTaskHandoff(root, runId, o = {}) {
|
|
1107
|
-
const
|
|
1108
|
-
if (!
|
|
1553
|
+
const waiting = await findWaitingTaskRun(root, runId);
|
|
1554
|
+
if (!waiting)
|
|
1109
1555
|
throw new TaskRunError("not-found", `No task run is waiting on ${runId}.`);
|
|
1556
|
+
if (waiting.level === "pr" && !o.approval)
|
|
1557
|
+
throw new TaskRunError("refused", `Task ${waiting.task} runs at the pr level, which pushes ${waiting.branch} and opens a PR: ask the person to run atticus handoff done ${runId} --approve (an assistant never approves a push).`);
|
|
1558
|
+
const lock = await holdTask(root, waiting.change, waiting.task);
|
|
1559
|
+
const release = holdSignals();
|
|
1560
|
+
try {
|
|
1561
|
+
const state = await handoffRunState(root, waiting.change, runId);
|
|
1562
|
+
if (state === void 0)
|
|
1563
|
+
throw new TaskRunError("refused", `Run ${runId} isn't on this machine (its files are kept where it was started): run the task again here (atticus task run ${waiting.change} ${waiting.task}).`);
|
|
1564
|
+
if (state === "cancelled")
|
|
1565
|
+
throw new TaskRunError("refused", `Run ${runId} was cancelled; run the task again (atticus task run ${waiting.change} ${waiting.task}).`);
|
|
1566
|
+
const record = await findWaitingTaskRun(root, runId);
|
|
1567
|
+
if (!record)
|
|
1568
|
+
throw new TaskRunError("not-found", `No task run is waiting on ${runId}.`);
|
|
1569
|
+
return await completeHeld(root, runId, record, o);
|
|
1570
|
+
} finally {
|
|
1571
|
+
await lock.release();
|
|
1572
|
+
release();
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
async function completeHeld(root, runId, record, o) {
|
|
1110
1576
|
const now = o.now ?? (() => /* @__PURE__ */ new Date());
|
|
1111
1577
|
const git = o.git ?? createGit();
|
|
1112
1578
|
const t = await loadTask(root, record.change, record.task);
|
|
@@ -1138,7 +1604,11 @@ async function completeTaskHandoff(root, runId, o = {}) {
|
|
|
1138
1604
|
return [`${file.slice(root.length + 1)} is empty`];
|
|
1139
1605
|
if (record.level === "plan")
|
|
1140
1606
|
return [];
|
|
1607
|
+
if (stopRequested())
|
|
1608
|
+
return ["Atticus was stopped"];
|
|
1141
1609
|
attempt = await build(c, runId);
|
|
1610
|
+
if (c.stopped)
|
|
1611
|
+
return ["Atticus was stopped while the build ran"];
|
|
1142
1612
|
if (!attempt)
|
|
1143
1613
|
return [];
|
|
1144
1614
|
return attempt.passed ? [] : [`${attempt.command} failed; see ${attempt.log}`];
|
|
@@ -1154,19 +1624,32 @@ async function completeTaskHandoff(root, runId, o = {}) {
|
|
|
1154
1624
|
record.state = attempt ? "built" : "unverified";
|
|
1155
1625
|
if (!attempt)
|
|
1156
1626
|
record.notes.push(`${t.repo.id} has no build command in repos.manifest.yaml, so the change wasn't built or tested.`);
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
}
|
|
1163
|
-
await commit(c, runId);
|
|
1164
|
-
await conformAfterBuild(c);
|
|
1165
|
-
if (record.level === "pr")
|
|
1166
|
-
await openPr(c);
|
|
1627
|
+
await afterBuild(c, runId, true, async () => {
|
|
1628
|
+
for (const p of await changedFiles(c))
|
|
1629
|
+
if (!record.changed.includes(p))
|
|
1630
|
+
record.changed.push(p);
|
|
1631
|
+
});
|
|
1167
1632
|
}
|
|
1168
1633
|
return done(c);
|
|
1169
1634
|
}
|
|
1635
|
+
if (c.stopped || stopRequested()) {
|
|
1636
|
+
if (c.stopped && record.attempts.at(-1)?.passed === false)
|
|
1637
|
+
record.attempts.pop();
|
|
1638
|
+
record.state = "waiting";
|
|
1639
|
+
record.waiting = runId;
|
|
1640
|
+
await handoff.retry(runId);
|
|
1641
|
+
await handoff.run(runId);
|
|
1642
|
+
record.notes.push(`Atticus was stopped while it checked the work, so nothing more was done; run atticus handoff done ${runId} again.`);
|
|
1643
|
+
return saveTaskRun(root, record);
|
|
1644
|
+
}
|
|
1645
|
+
if (!attempt) {
|
|
1646
|
+
record.state = "waiting";
|
|
1647
|
+
record.waiting = runId;
|
|
1648
|
+
await handoff.retry(runId);
|
|
1649
|
+
await handoff.run(runId);
|
|
1650
|
+
record.notes.push(`${run.errors.join("; ") || "The answer isn't there yet"}: write it, then run atticus handoff done ${runId} again.`);
|
|
1651
|
+
return saveTaskRun(root, record);
|
|
1652
|
+
}
|
|
1170
1653
|
const builds = record.attempts.length;
|
|
1171
1654
|
if (attempt && !attempt.passed && builds <= c.maxFix) {
|
|
1172
1655
|
await handoff.retry(runId);
|
|
@@ -1178,15 +1661,207 @@ async function completeTaskHandoff(root, runId, o = {}) {
|
|
|
1178
1661
|
record.notes.push(attempt && !attempt.passed ? `The build still fails after ${builds} attempts; a person takes over in ${record.worktree}.` : `The hand-off failed: ${run.errors.join("; ")}.`);
|
|
1179
1662
|
return done(c);
|
|
1180
1663
|
}
|
|
1664
|
+
async function raiseTaskPr(root, changeId, taskId, o) {
|
|
1665
|
+
try {
|
|
1666
|
+
requireApproval("git-host", o.approval);
|
|
1667
|
+
} catch {
|
|
1668
|
+
throw new TaskRunError("refused", "A task's PR pushes its branch and opens a PR, which needs the person's yes (an assistant never approves a push).");
|
|
1669
|
+
}
|
|
1670
|
+
const lock = await holdTask(root, changeId, taskId);
|
|
1671
|
+
try {
|
|
1672
|
+
const record = await readTaskRun(root, changeId, taskId);
|
|
1673
|
+
if (!record || record.level === "plan" || ["planned", "failed"].includes(record.state))
|
|
1674
|
+
throw new TaskRunError("refused", `Task ${taskId} hasn't been drafted yet: run it with AI first; its PR comes after the draft.`);
|
|
1675
|
+
if (record.state === "pr-open")
|
|
1676
|
+
throw new TaskRunError("refused", `Task ${taskId}'s PR is already open: ${record.pr?.url ?? "see its run"}.`);
|
|
1677
|
+
if (record.state === "waiting")
|
|
1678
|
+
throw new TaskRunError("refused", `Task ${taskId} still waits on your assistant (run ${record.waiting ?? "on its page"}): finish it with Done first; its PR comes after the build.`);
|
|
1679
|
+
const change = changeBranch(changeId);
|
|
1680
|
+
if (record.state === "unverified")
|
|
1681
|
+
throw new TaskRunError("refused", `Atticus opens a task's PR only after a passing build, and ${record.repo} has no build command in repos.manifest.yaml: add one and run task ${taskId} again, or push ${record.branch} and open its PR into ${change} yourself.`);
|
|
1682
|
+
if (record.state !== "built" || !record.commit)
|
|
1683
|
+
throw new TaskRunError("refused", `Task ${taskId} has no passing build to raise (it is ${record.state}): see its run's notes, then run it again.`);
|
|
1684
|
+
const t = await loadTask(root, changeId, taskId);
|
|
1685
|
+
const gitHost = o.gitHost ?? gitHostOf(root, t);
|
|
1686
|
+
if (!gitHost)
|
|
1687
|
+
throw new TaskRunError("refused", `No Git host is connected (runtime.yaml adapters.gitHost): push ${record.branch} and open its PR into ${change} yourself.`);
|
|
1688
|
+
const now = o.now ?? (() => /* @__PURE__ */ new Date());
|
|
1689
|
+
const c = {
|
|
1690
|
+
root,
|
|
1691
|
+
t,
|
|
1692
|
+
record,
|
|
1693
|
+
worktree: join5(root, record.worktree),
|
|
1694
|
+
runtime: void 0,
|
|
1695
|
+
commands: shellCommandRunner(),
|
|
1696
|
+
git: o.git ?? createGit(),
|
|
1697
|
+
gitHost,
|
|
1698
|
+
approval: o.approval,
|
|
1699
|
+
now,
|
|
1700
|
+
maxFix: t.ctx.orgPack.runtime.autonomy.maxFixRounds
|
|
1701
|
+
};
|
|
1702
|
+
await openPr(c);
|
|
1703
|
+
if (record.state === "pr-open")
|
|
1704
|
+
record.notes.push(`PR raised by ${o.approval.by} after the draft (${o.approval.ref}).`);
|
|
1705
|
+
return await done(c);
|
|
1706
|
+
} finally {
|
|
1707
|
+
await lock.release();
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1181
1710
|
async function isTaskRun(root, runId) {
|
|
1182
1711
|
return await findWaitingTaskRun(root, runId) !== void 0;
|
|
1183
1712
|
}
|
|
1184
1713
|
|
|
1714
|
+
// packages/taskrun/dist/ready.js
|
|
1715
|
+
var PAST = {
|
|
1716
|
+
waiting: "it is with your assistant: Done on its run carries on",
|
|
1717
|
+
built: "it is drafted: its PR is the next step",
|
|
1718
|
+
unverified: "it is drafted but not built: its repo has no build command",
|
|
1719
|
+
"pr-open": "its PR is open on the Git host",
|
|
1720
|
+
"needs-person": "it needs a person: carry on in its worktree, or Run with AI on it"
|
|
1721
|
+
};
|
|
1722
|
+
function sameRepoBefore(tasks, t) {
|
|
1723
|
+
const mine = tasks.slice(0, tasks.indexOf(t)).filter((x) => x.repo === t.repo);
|
|
1724
|
+
let cut = mine.length;
|
|
1725
|
+
if (t.parallel)
|
|
1726
|
+
while (cut > 0 && mine[cut - 1].parallel)
|
|
1727
|
+
cut--;
|
|
1728
|
+
return mine.slice(0, cut).filter((x) => !x.done).map((x) => x.id);
|
|
1729
|
+
}
|
|
1730
|
+
function planReadyTasks(o) {
|
|
1731
|
+
const deps = new Map(o.stories.map((s) => [s.id, s.dependsOn]));
|
|
1732
|
+
const rank = (repo) => {
|
|
1733
|
+
const i = o.repoOrder?.indexOf(repo) ?? -1;
|
|
1734
|
+
return i < 0 ? Number.MAX_SAFE_INTEGER : i;
|
|
1735
|
+
};
|
|
1736
|
+
const firstOfRepo = /* @__PURE__ */ new Map();
|
|
1737
|
+
o.tasks.forEach((t, i) => {
|
|
1738
|
+
if (!firstOfRepo.has(t.repo))
|
|
1739
|
+
firstOfRepo.set(t.repo, i);
|
|
1740
|
+
});
|
|
1741
|
+
const order = o.tasks.map((t, i) => ({ t, i })).sort((a, b) => rank(a.t.repo) - rank(b.t.repo) || firstOfRepo.get(a.t.repo) - firstOfRepo.get(b.t.repo) || a.i - b.i).map((x) => x.t);
|
|
1742
|
+
const out = [];
|
|
1743
|
+
for (const t of order) {
|
|
1744
|
+
if (t.done)
|
|
1745
|
+
continue;
|
|
1746
|
+
const before = new Set(t.stories.flatMap((s) => deps.get(s) ?? []));
|
|
1747
|
+
const byStory = o.tasks.filter((x) => x.id !== t.id && !x.done && x.stories.some((s) => before.has(s))).map((x) => x.id);
|
|
1748
|
+
const sameRepo = sameRepoBefore(o.tasks, t).filter((id) => !byStory.includes(id));
|
|
1749
|
+
const waitsFor = o.tasks.map((x) => x.id).filter((id) => byStory.includes(id) || sameRepo.includes(id));
|
|
1750
|
+
const past = t.state && !(t.state === "pr-open" && t.prSettled) ? PAST[t.state] : void 0;
|
|
1751
|
+
const named = [
|
|
1752
|
+
...byStory,
|
|
1753
|
+
...sameRepo.length ? [`${sameRepo.join(", ")} (same repo)`] : []
|
|
1754
|
+
].join(", ");
|
|
1755
|
+
const why = waitsFor.length ? `it waits for ${waitsFor.length === 1 ? "task" : "tasks"} ${named} to be done first` : past;
|
|
1756
|
+
out.push({
|
|
1757
|
+
id: t.id,
|
|
1758
|
+
repo: t.repo,
|
|
1759
|
+
ready: !why,
|
|
1760
|
+
waitsFor,
|
|
1761
|
+
...sameRepo.length ? { sameRepo } : {},
|
|
1762
|
+
...why ? { why } : {}
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
return { tasks: out, ready: out.filter((t) => t.ready).map((t) => t.id) };
|
|
1766
|
+
}
|
|
1767
|
+
async function readyTasksOf(root, change, o = {}) {
|
|
1768
|
+
const files = await readChangeFiles(changeFolder(root, change));
|
|
1769
|
+
const tasks = [];
|
|
1770
|
+
for (const t of readChangeTasks(files)) {
|
|
1771
|
+
const r = await readTaskRun(root, change, t.id).catch(() => void 0);
|
|
1772
|
+
const pr = o.prStates?.get(t.id);
|
|
1773
|
+
tasks.push({
|
|
1774
|
+
id: t.id,
|
|
1775
|
+
repo: t.repo,
|
|
1776
|
+
done: t.done,
|
|
1777
|
+
stories: t.stories,
|
|
1778
|
+
...t.parallel ? { parallel: true } : {},
|
|
1779
|
+
...r ? { state: r.state } : {},
|
|
1780
|
+
...pr === "merged" || pr === "closed" ? { prSettled: pr } : {}
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
return planReadyTasks({
|
|
1784
|
+
tasks,
|
|
1785
|
+
stories: readStoryIndex(files),
|
|
1786
|
+
...o.repoOrder ? { repoOrder: o.repoOrder } : {}
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
function needsPerson(r) {
|
|
1790
|
+
if (r.state === "failed")
|
|
1791
|
+
return r.notes.at(-1) ?? `the run for task ${r.task} failed`;
|
|
1792
|
+
if (r.state === "needs-person")
|
|
1793
|
+
return r.notes.at(-1) ?? `task ${r.task} needs a person`;
|
|
1794
|
+
if (r.state === "waiting")
|
|
1795
|
+
return `task ${r.task} is with your assistant: Done on its run first`;
|
|
1796
|
+
if (r.state === "unverified")
|
|
1797
|
+
return `task ${r.task} is drafted but ${r.repo} has no build command, so nothing was built`;
|
|
1798
|
+
if (r.level === "pr" && r.state === "built")
|
|
1799
|
+
return r.notes.at(-1) ?? `task ${r.task}'s PR wasn't raised`;
|
|
1800
|
+
return void 0;
|
|
1801
|
+
}
|
|
1802
|
+
async function runReadyTasks(root, change, o) {
|
|
1803
|
+
const plan = await readyTasksOf(root, change, {
|
|
1804
|
+
...o.repoOrder ? { repoOrder: o.repoOrder } : {},
|
|
1805
|
+
...o.prStates ? { prStates: o.prStates } : {}
|
|
1806
|
+
});
|
|
1807
|
+
const planned = o.only ? plan.ready.filter((id) => o.only.includes(id)) : plan.ready;
|
|
1808
|
+
const repoOf = new Map(plan.tasks.map((t) => [t.id, t.repo]));
|
|
1809
|
+
if (o.dryRun) {
|
|
1810
|
+
const previews = [];
|
|
1811
|
+
for (const task of planned)
|
|
1812
|
+
try {
|
|
1813
|
+
previews.push(await previewTaskRun(root, change, task, {
|
|
1814
|
+
...o.level ? { level: o.level } : {},
|
|
1815
|
+
...o.gitHost ? { gitHost: o.gitHost } : {}
|
|
1816
|
+
}));
|
|
1817
|
+
} catch (e) {
|
|
1818
|
+
previews.push({ task, refused: e.message });
|
|
1819
|
+
}
|
|
1820
|
+
return { planned, ran: [], previews };
|
|
1821
|
+
}
|
|
1822
|
+
const { only: _only, before, levelFor, progress, cancelled, repoOrder: _r, prStates: _p, dryRun: _d, ...run } = o;
|
|
1823
|
+
const ran = [];
|
|
1824
|
+
for (const [i, task] of planned.entries()) {
|
|
1825
|
+
const repo = repoOf.get(task) ?? "";
|
|
1826
|
+
if (cancelled?.())
|
|
1827
|
+
return { planned, ran, stopped: { task, why: "the run was cancelled" } };
|
|
1828
|
+
progress?.(i, planned.length, `Task ${task} on ${repo}`);
|
|
1829
|
+
const refusedBefore = await before?.(task);
|
|
1830
|
+
if (refusedBefore) {
|
|
1831
|
+
ran.push({ task, repo, refused: refusedBefore });
|
|
1832
|
+
return { planned, ran, stopped: { task, why: refusedBefore } };
|
|
1833
|
+
}
|
|
1834
|
+
let record;
|
|
1835
|
+
try {
|
|
1836
|
+
const level = run.level ?? await levelFor?.(task);
|
|
1837
|
+
record = await runTask(root, change, task, { ...run, ...level ? { level } : {} });
|
|
1838
|
+
} catch (e) {
|
|
1839
|
+
const why2 = e.message;
|
|
1840
|
+
ran.push({ task, repo, refused: why2 });
|
|
1841
|
+
return { planned, ran, stopped: { task, why: why2 } };
|
|
1842
|
+
}
|
|
1843
|
+
ran.push({ task, repo, record });
|
|
1844
|
+
const why = needsPerson(record);
|
|
1845
|
+
if (why)
|
|
1846
|
+
return { planned, ran, stopped: { task, why } };
|
|
1847
|
+
}
|
|
1848
|
+
progress?.(planned.length, planned.length, "Done");
|
|
1849
|
+
return { planned, ran };
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1185
1852
|
export {
|
|
1186
1853
|
FILE_FORMAT,
|
|
1187
1854
|
refusedPath,
|
|
1188
1855
|
parseAnswer,
|
|
1189
1856
|
applyChanges,
|
|
1857
|
+
KEEP_OUTPUT,
|
|
1858
|
+
tail,
|
|
1859
|
+
stopRequested,
|
|
1860
|
+
stopSignal,
|
|
1861
|
+
stopAllBuilds,
|
|
1862
|
+
SIGNAL_GRACE_MS,
|
|
1863
|
+
holdSignals,
|
|
1864
|
+
STOP_GRACE_MS,
|
|
1190
1865
|
shellCommandRunner,
|
|
1191
1866
|
TaskRunState,
|
|
1192
1867
|
RunLevel,
|
|
@@ -1196,6 +1871,8 @@ export {
|
|
|
1196
1871
|
saveTaskRun,
|
|
1197
1872
|
readTaskRun,
|
|
1198
1873
|
saveRunSummary,
|
|
1874
|
+
taskRunOfRun,
|
|
1875
|
+
findTaskRunOfRun,
|
|
1199
1876
|
findWaitingTaskRun,
|
|
1200
1877
|
TASK_RUNNER,
|
|
1201
1878
|
taskRunnerAgent,
|
|
@@ -1211,7 +1888,16 @@ export {
|
|
|
1211
1888
|
conformanceOf,
|
|
1212
1889
|
conformAfterBuild,
|
|
1213
1890
|
TaskRunError,
|
|
1891
|
+
taskPrState,
|
|
1892
|
+
settleTaskPr,
|
|
1893
|
+
previewTaskRun,
|
|
1894
|
+
cancelTaskRunWait,
|
|
1214
1895
|
runTask,
|
|
1215
1896
|
completeTaskHandoff,
|
|
1216
|
-
|
|
1897
|
+
raiseTaskPr,
|
|
1898
|
+
isTaskRun,
|
|
1899
|
+
planReadyTasks,
|
|
1900
|
+
readyTasksOf,
|
|
1901
|
+
needsPerson,
|
|
1902
|
+
runReadyTasks
|
|
1217
1903
|
};
|