@poetic-ai/poetic 1.42.0
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/.github/SECURITY.md +47 -0
- package/.nvmrc +1 -0
- package/.poetic/README.md +37 -0
- package/.poetic/providers/catalog.json +12051 -0
- package/.poetic/providers/pricing.json +1272 -0
- package/.poetic/providers/registry.json +3369 -0
- package/CHANGELOG.md +552 -0
- package/CODE_OF_CONDUCT.md +40 -0
- package/CONTRIBUTING.md +23 -0
- package/INSTALL.md +454 -0
- package/LICENSE +21 -0
- package/README.md +474 -0
- package/dist/BasicOptimizationCompetitionRunner-5H5TBYO4.js +153 -0
- package/dist/ExecutionTracker-UVONC4C6.js +16 -0
- package/dist/OptimizationConfig-7DFY2TST.js +17 -0
- package/dist/OptimizationEngine-JIMGP3LY.js +1597 -0
- package/dist/PromptStore-U6ZD3ZMQ.js +18 -0
- package/dist/actions-LUJPINLJ.js +322 -0
- package/dist/agent-ingest-3DJUJ7FU.js +53 -0
- package/dist/aggregator-DNCBINFO.js +12 -0
- package/dist/ai-judge-5QT5QJVU.js +156 -0
- package/dist/allowlist-grounding-RO6HKUFI.js +16 -0
- package/dist/allowlist-utils-23V7TJ3G.js +28 -0
- package/dist/anchored-turn-service-JULUCUIK.js +489 -0
- package/dist/api-transport-4TYTNLTJ.js +1087 -0
- package/dist/apply-completion-mode-AW2MOS3R.js +89 -0
- package/dist/artifact-migrator-23L45ISD.js +267 -0
- package/dist/ask-HWVV6QFR.js +135 -0
- package/dist/auth-5KEDKAPP.js +67 -0
- package/dist/auth-7TT3JINV.js +78 -0
- package/dist/auth-E6XUNZ5M.js +68 -0
- package/dist/auth-H3XDZE22.js +134 -0
- package/dist/auth-OC4E6633.js +71 -0
- package/dist/auth-S4CTX4GQ.js +44 -0
- package/dist/auth-YLH3S7EY.js +69 -0
- package/dist/auth-liveness-TDDEZY3T.js +46 -0
- package/dist/auto-optimizer-VPRWOWGU.js +80 -0
- package/dist/autoloop-cleanup-JOGKTLWA.js +109 -0
- package/dist/autoloop-evidence-gates-PCDALGVJ.js +38 -0
- package/dist/autoloop-gate-policy-Z7FVJVXV.js +175 -0
- package/dist/autoloop-helpers-2KTK43GL.js +22 -0
- package/dist/autoloop-ledger-W7QO62PX.js +96 -0
- package/dist/autoloop-ledger-subscriber-Z5RW5EIE.js +162 -0
- package/dist/autoloop-run-defaults-FERGRZGP.js +19 -0
- package/dist/autoloop-run-lock-CT2NWSV3.js +197 -0
- package/dist/autoloop-success-J2VKKBXQ.js +85 -0
- package/dist/autoloop-termination-summary-RN75F422.js +58 -0
- package/dist/autoloop-trajectory-XFIEXP5Z.js +282 -0
- package/dist/autoloop-wall-clock-T7ZVIQOC.js +12 -0
- package/dist/autonomous-loop-controller-PW4XVFGQ.js +4120 -0
- package/dist/backend-P3DAYRP7.js +29 -0
- package/dist/background-executor-CBN552V4.js +257 -0
- package/dist/backlog-execution-intent-U4XYPTV6.js +15 -0
- package/dist/backup-active-store-5WXG6SXT.js +17 -0
- package/dist/backup-telemetry-db-XGLXAA3N.js +254 -0
- package/dist/basic-competition-master-VCSBJVRN.js +344 -0
- package/dist/branch-archive-manager-RP6FP3ZC.js +254 -0
- package/dist/branch-cleanup-manager-RSHAI7YR.js +20 -0
- package/dist/build-gate-YHGRB4QB.js +71 -0
- package/dist/change-summary-WY7J5TOX.js +33 -0
- package/dist/chunk-23A26CSN.js +123 -0
- package/dist/chunk-27UTJD3M.js +265 -0
- package/dist/chunk-2A5CILN3.js +310 -0
- package/dist/chunk-2AQUWJPW.js +225 -0
- package/dist/chunk-2BZ53J6J.js +2344 -0
- package/dist/chunk-2DY5KNVM.js +276 -0
- package/dist/chunk-2EIA4RBE.js +659 -0
- package/dist/chunk-2IUXIGQD.js +1064 -0
- package/dist/chunk-2N42MS2Z.js +2193 -0
- package/dist/chunk-2QJ3H3L7.js +42 -0
- package/dist/chunk-2QLYTVYX.js +791 -0
- package/dist/chunk-2VSQMRCB.js +18 -0
- package/dist/chunk-2XQXYBM2.js +130 -0
- package/dist/chunk-2YFUIER7.js +426 -0
- package/dist/chunk-34CNP2HB.js +148 -0
- package/dist/chunk-35P3W3JX.js +456 -0
- package/dist/chunk-36PEBZAF.js +18 -0
- package/dist/chunk-3AOKYKA7.js +22 -0
- package/dist/chunk-3BCUNHKF.js +475 -0
- package/dist/chunk-3FLXLLB7.js +26 -0
- package/dist/chunk-3FOZ2VHV.js +100 -0
- package/dist/chunk-3G6FZCRF.js +106 -0
- package/dist/chunk-3M57DADF.js +44 -0
- package/dist/chunk-3S62LLWJ.js +543 -0
- package/dist/chunk-3ZPQLGV7.js +2904 -0
- package/dist/chunk-44N5WZZH.js +45 -0
- package/dist/chunk-45FPSA3B.js +125 -0
- package/dist/chunk-4BJ3O4RQ.js +929 -0
- package/dist/chunk-4BOP7T6L.js +2321 -0
- package/dist/chunk-4BTDUT2S.js +42 -0
- package/dist/chunk-4CSS7WVI.js +143 -0
- package/dist/chunk-4CUY7AFY.js +247 -0
- package/dist/chunk-4GSN5O5J.js +62 -0
- package/dist/chunk-4HN6DF7V.js +1027 -0
- package/dist/chunk-4IAPOG5V.js +415 -0
- package/dist/chunk-4IYIZQWV.js +48 -0
- package/dist/chunk-4NXPXE62.js +84 -0
- package/dist/chunk-4RCCF5BR.js +712 -0
- package/dist/chunk-4V7NAQ4R.js +19527 -0
- package/dist/chunk-4VJITV4P.js +445 -0
- package/dist/chunk-4YX7J6QL.js +1859 -0
- package/dist/chunk-527OBWQB.js +338 -0
- package/dist/chunk-5D4A7E3D.js +448 -0
- package/dist/chunk-5DLKYTQX.js +4003 -0
- package/dist/chunk-5EERLVZB.js +139 -0
- package/dist/chunk-5H72XE4H.js +256 -0
- package/dist/chunk-5HDP7XZG.js +91 -0
- package/dist/chunk-5LAMRH4X.js +969 -0
- package/dist/chunk-5LTN43AS.js +1972 -0
- package/dist/chunk-5RBHQYDB.js +2206 -0
- package/dist/chunk-5WCQRDRB.js +588 -0
- package/dist/chunk-5WRLK5KW.js +700 -0
- package/dist/chunk-5ZCXC23G.js +595 -0
- package/dist/chunk-6BM72ZMG.js +31 -0
- package/dist/chunk-6EDAJH2I.js +68 -0
- package/dist/chunk-6EQKFDBH.js +457 -0
- package/dist/chunk-6MFRHTRI.js +115 -0
- package/dist/chunk-6TZJRKNW.js +321 -0
- package/dist/chunk-6V7HGQFZ.js +20 -0
- package/dist/chunk-6VWVO2TU.js +3746 -0
- package/dist/chunk-6Y5TWI7H.js +146 -0
- package/dist/chunk-6Y5U7UFY.js +91 -0
- package/dist/chunk-6ZLAK3XG.js +14 -0
- package/dist/chunk-72XCRQED.js +34 -0
- package/dist/chunk-72YTZMAM.js +589 -0
- package/dist/chunk-73BBJOKA.js +263 -0
- package/dist/chunk-73NCTWKL.js +188 -0
- package/dist/chunk-77I6G4CO.js +1 -0
- package/dist/chunk-7DHRDWFS.js +3104 -0
- package/dist/chunk-7DNSNKJV.js +78 -0
- package/dist/chunk-7FMJVYBS.js +307 -0
- package/dist/chunk-7GDRQBQC.js +419 -0
- package/dist/chunk-7GPCEFUV.js +270 -0
- package/dist/chunk-7IL4A2PP.js +948 -0
- package/dist/chunk-7MMLMXO6.js +3679 -0
- package/dist/chunk-7QCZSLBH.js +1 -0
- package/dist/chunk-7R2WLDOS.js +62 -0
- package/dist/chunk-7T7RUJI7.js +949 -0
- package/dist/chunk-A2WKSVX7.js +43 -0
- package/dist/chunk-A3YGID55.js +133 -0
- package/dist/chunk-A722DEVA.js +14 -0
- package/dist/chunk-ACDIT7OP.js +1376 -0
- package/dist/chunk-ACKIPAOJ.js +302 -0
- package/dist/chunk-APPNGGN7.js +365 -0
- package/dist/chunk-APV6MK5E.js +137 -0
- package/dist/chunk-ASEP3M2W.js +968 -0
- package/dist/chunk-AT4TNPWW.js +2931 -0
- package/dist/chunk-ATVKCSGT.js +250 -0
- package/dist/chunk-AURFMVCD.js +899 -0
- package/dist/chunk-AX6GWE7V.js +47 -0
- package/dist/chunk-AY5EWJPF.js +385 -0
- package/dist/chunk-BAV2HJXS.js +194 -0
- package/dist/chunk-BBHRN366.js +89 -0
- package/dist/chunk-BBPSTTPA.js +1004 -0
- package/dist/chunk-BDATUDDJ.js +992 -0
- package/dist/chunk-BKE5PG5L.js +20414 -0
- package/dist/chunk-BLPHWMDK.js +797 -0
- package/dist/chunk-BSE4R6XD.js +322 -0
- package/dist/chunk-BXGMAU4A.js +396 -0
- package/dist/chunk-BXI4NXL3.js +507 -0
- package/dist/chunk-BZU2O43F.js +1125 -0
- package/dist/chunk-C3L6YQ7P.js +147 -0
- package/dist/chunk-C57KJOUQ.js +121 -0
- package/dist/chunk-CCV7BPSY.js +118 -0
- package/dist/chunk-CD7ISXA4.js +826 -0
- package/dist/chunk-CE5OZBYY.js +21 -0
- package/dist/chunk-CFBIG37O.js +154 -0
- package/dist/chunk-CJC6GZ46.js +457 -0
- package/dist/chunk-CKCDGXIV.js +408 -0
- package/dist/chunk-CKNX3TTP.js +10338 -0
- package/dist/chunk-CLKSETWE.js +10 -0
- package/dist/chunk-CP7H3HSP.js +1552 -0
- package/dist/chunk-CPLEWXNZ.js +66 -0
- package/dist/chunk-CQM3A35X.js +844 -0
- package/dist/chunk-CS6P76D3.js +103 -0
- package/dist/chunk-CTLUBNCW.js +622 -0
- package/dist/chunk-CUSRN6RJ.js +632 -0
- package/dist/chunk-D5EP5D2W.js +26 -0
- package/dist/chunk-D5RYINO7.js +412 -0
- package/dist/chunk-DBFS4HMH.js +751 -0
- package/dist/chunk-DC4ZYMXJ.js +115 -0
- package/dist/chunk-DCBZP442.js +9243 -0
- package/dist/chunk-DCYF7EKG.js +26 -0
- package/dist/chunk-DDMAFNUK.js +5351 -0
- package/dist/chunk-DF5SLDE4.js +966 -0
- package/dist/chunk-DJFW7SMX.js +348 -0
- package/dist/chunk-DQFLLBJW.js +121 -0
- package/dist/chunk-DSFM56OA.js +1203 -0
- package/dist/chunk-DTY4APYV.js +218 -0
- package/dist/chunk-DXH5JBRS.js +437 -0
- package/dist/chunk-E3NTPHEO.js +194 -0
- package/dist/chunk-E74LUIID.js +302 -0
- package/dist/chunk-EI57M5BI.js +194 -0
- package/dist/chunk-EJ4ZAWLV.js +305 -0
- package/dist/chunk-EJGCZGUF.js +1483 -0
- package/dist/chunk-EK2U3YEG.js +486 -0
- package/dist/chunk-ELMFYNV7.js +109 -0
- package/dist/chunk-ENRGKNR5.js +25 -0
- package/dist/chunk-ETYDXCK7.js +679 -0
- package/dist/chunk-EYRH3W74.js +239 -0
- package/dist/chunk-F23DIWNN.js +1024 -0
- package/dist/chunk-F5JO7HAS.js +94 -0
- package/dist/chunk-F7ER6ANO.js +174 -0
- package/dist/chunk-FATUVIIN.js +374 -0
- package/dist/chunk-FC23CTXV.js +322 -0
- package/dist/chunk-FD4ERYEG.js +22 -0
- package/dist/chunk-FH7WOJAE.js +79 -0
- package/dist/chunk-FHOWVDF5.js +1342 -0
- package/dist/chunk-FKAUPHMR.js +96 -0
- package/dist/chunk-FONNFJXA.js +137 -0
- package/dist/chunk-FQ7FSZRW.js +75 -0
- package/dist/chunk-FRG57FPM.js +240 -0
- package/dist/chunk-FUVP64ER.js +31 -0
- package/dist/chunk-FYOILAN5.js +6818 -0
- package/dist/chunk-G35UYQ6Z.js +69 -0
- package/dist/chunk-G36W2T2S.js +1143 -0
- package/dist/chunk-G3L2L5XZ.js +49 -0
- package/dist/chunk-G4THLFV3.js +148 -0
- package/dist/chunk-GAFJEYLK.js +29 -0
- package/dist/chunk-GFGYB2ZU.js +1689 -0
- package/dist/chunk-GG6KJYW6.js +85 -0
- package/dist/chunk-GHHFDU2U.js +55 -0
- package/dist/chunk-GHTZSQB7.js +57 -0
- package/dist/chunk-GK37ILCX.js +1231 -0
- package/dist/chunk-GKN3HMN4.js +2809 -0
- package/dist/chunk-GNVDBVJP.js +156 -0
- package/dist/chunk-GPEL3FBM.js +924 -0
- package/dist/chunk-GPSNGPZS.js +1604 -0
- package/dist/chunk-GSGD5E4C.js +30 -0
- package/dist/chunk-GSUQJJXQ.js +331 -0
- package/dist/chunk-GSV226X6.js +110 -0
- package/dist/chunk-H2AYQIHW.js +224 -0
- package/dist/chunk-H66DXFS5.js +1374 -0
- package/dist/chunk-H6G7QRMQ.js +35 -0
- package/dist/chunk-H7JAGHZT.js +59 -0
- package/dist/chunk-H7ZEFECA.js +316 -0
- package/dist/chunk-HAC6EHZZ.js +79 -0
- package/dist/chunk-HIO33P3G.js +19 -0
- package/dist/chunk-HMVQIPH3.js +547 -0
- package/dist/chunk-HOYBYAOA.js +257 -0
- package/dist/chunk-HX5P3CSP.js +1784 -0
- package/dist/chunk-I46EG2XQ.js +65 -0
- package/dist/chunk-I4NPDSCB.js +279 -0
- package/dist/chunk-I5WRT7ZR.js +514 -0
- package/dist/chunk-IC7I6YIJ.js +301 -0
- package/dist/chunk-IDCSOZVN.js +78 -0
- package/dist/chunk-IFCBYECK.js +112 -0
- package/dist/chunk-IFZCPEY2.js +66 -0
- package/dist/chunk-IKFP2KUR.js +48 -0
- package/dist/chunk-IRFBN336.js +878 -0
- package/dist/chunk-IUXNGKA6.js +152 -0
- package/dist/chunk-IV2RVAN7.js +1356 -0
- package/dist/chunk-IZYIQQ7X.js +53 -0
- package/dist/chunk-J3UUR7DE.js +210 -0
- package/dist/chunk-J54VUAY2.js +566 -0
- package/dist/chunk-J62KPGII.js +464 -0
- package/dist/chunk-J6P3FWWW.js +130 -0
- package/dist/chunk-JKBHJQMT.js +434 -0
- package/dist/chunk-JLS65NUQ.js +14 -0
- package/dist/chunk-JOSYEJKY.js +141 -0
- package/dist/chunk-JPKSXKNB.js +94 -0
- package/dist/chunk-JQNJB2BB.js +2440 -0
- package/dist/chunk-JRVNSWSQ.js +2626 -0
- package/dist/chunk-JSWMRQYG.js +28 -0
- package/dist/chunk-JZKNBBIB.js +152 -0
- package/dist/chunk-K54Y7MLK.js +160 -0
- package/dist/chunk-K65546RE.js +183 -0
- package/dist/chunk-KM3F7SYE.js +702 -0
- package/dist/chunk-KNDYMVWN.js +102 -0
- package/dist/chunk-KNT72VR6.js +132 -0
- package/dist/chunk-KP6YILMU.js +482 -0
- package/dist/chunk-KQEBSK3T.js +274 -0
- package/dist/chunk-KT6VHSPF.js +84 -0
- package/dist/chunk-KTMW65UX.js +14 -0
- package/dist/chunk-KZ5CJVBP.js +1813 -0
- package/dist/chunk-L4427KOE.js +26 -0
- package/dist/chunk-L6OM4A22.js +189 -0
- package/dist/chunk-L7E6XCRA.js +1042 -0
- package/dist/chunk-L7JZLXQL.js +173 -0
- package/dist/chunk-LAMKBTXX.js +40 -0
- package/dist/chunk-LDCF2MKN.js +132 -0
- package/dist/chunk-LEIIWPWQ.js +78 -0
- package/dist/chunk-LFTQVYBB.js +31 -0
- package/dist/chunk-LG3PDRTR.js +2872 -0
- package/dist/chunk-LGHII5ET.js +23 -0
- package/dist/chunk-LH5QY22X.js +1205 -0
- package/dist/chunk-LIVJ6266.js +438 -0
- package/dist/chunk-LKRAR3IH.js +276 -0
- package/dist/chunk-LO23NABI.js +3063 -0
- package/dist/chunk-LO3X5NLS.js +326 -0
- package/dist/chunk-LPITVM7M.js +339 -0
- package/dist/chunk-LR5IJIGV.js +810 -0
- package/dist/chunk-LRGMHROI.js +79 -0
- package/dist/chunk-LUVKFFWR.js +315 -0
- package/dist/chunk-LWCBNGH6.js +35 -0
- package/dist/chunk-LWTN3WRV.js +260 -0
- package/dist/chunk-M3HQYKQX.js +308 -0
- package/dist/chunk-M6GVSPEH.js +1016 -0
- package/dist/chunk-MF5HP6XV.js +221 -0
- package/dist/chunk-MHLCBZJB.js +328 -0
- package/dist/chunk-MN6PL4AN.js +120 -0
- package/dist/chunk-MOEY65Z6.js +5678 -0
- package/dist/chunk-MQ4WA34C.js +206 -0
- package/dist/chunk-MWHF5V7U.js +223 -0
- package/dist/chunk-MWHLBPNU.js +211 -0
- package/dist/chunk-MWK5UZQ3.js +1068 -0
- package/dist/chunk-MYLH2S4G.js +64 -0
- package/dist/chunk-MZ5WYKNA.js +28 -0
- package/dist/chunk-N4VTRA7K.js +131 -0
- package/dist/chunk-N5DX4JAK.js +12 -0
- package/dist/chunk-N65O4XTH.js +5011 -0
- package/dist/chunk-NEQUQHOX.js +223 -0
- package/dist/chunk-NGK6PEOG.js +25 -0
- package/dist/chunk-NJVD4PWE.js +1033 -0
- package/dist/chunk-NM6PMYY4.js +768 -0
- package/dist/chunk-NN4PJDHP.js +708 -0
- package/dist/chunk-NP2V3L7K.js +226 -0
- package/dist/chunk-NRLY536M.js +260 -0
- package/dist/chunk-NRNE225N.js +1270 -0
- package/dist/chunk-NS2K2GTP.js +605 -0
- package/dist/chunk-NS33V3IM.js +51 -0
- package/dist/chunk-NSHASMZZ.js +71 -0
- package/dist/chunk-NWOYOA6H.js +378 -0
- package/dist/chunk-NWRUSEXG.js +322 -0
- package/dist/chunk-NZGDAWIP.js +1905 -0
- package/dist/chunk-O47UOKU3.js +395 -0
- package/dist/chunk-O4G2W3ST.js +9831 -0
- package/dist/chunk-O6V4PNLO.js +63 -0
- package/dist/chunk-OA4GPILI.js +624 -0
- package/dist/chunk-OGMSYL6J.js +227 -0
- package/dist/chunk-OIS7J26S.js +319 -0
- package/dist/chunk-OMX5VL43.js +79 -0
- package/dist/chunk-ON3G73BU.js +264 -0
- package/dist/chunk-OPYFYTWQ.js +220 -0
- package/dist/chunk-OQ6K46CK.js +1734 -0
- package/dist/chunk-OYZYO7TV.js +47 -0
- package/dist/chunk-OZ4REHIN.js +4386 -0
- package/dist/chunk-P47VN5F4.js +282 -0
- package/dist/chunk-P5I4X7A7.js +353 -0
- package/dist/chunk-P6VQROCO.js +594 -0
- package/dist/chunk-P7CQGPLS.js +30 -0
- package/dist/chunk-PCAGC5MR.js +1763 -0
- package/dist/chunk-PFTQBXS6.js +5181 -0
- package/dist/chunk-PGSPX4SU.js +15 -0
- package/dist/chunk-PIKLF7BM.js +432 -0
- package/dist/chunk-PJWJ3SAV.js +22 -0
- package/dist/chunk-PKIFMV72.js +100 -0
- package/dist/chunk-PL37JDNA.js +189 -0
- package/dist/chunk-PTH5E5XO.js +195 -0
- package/dist/chunk-PW6AXLQC.js +4128 -0
- package/dist/chunk-PYITM4N2.js +79 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-Q3RO7N35.js +45 -0
- package/dist/chunk-Q3WIC6GQ.js +2670 -0
- package/dist/chunk-Q5XIXSHX.js +271 -0
- package/dist/chunk-QGJDMEOV.js +34 -0
- package/dist/chunk-QNOB37UH.js +58 -0
- package/dist/chunk-QOCOVLUH.js +462 -0
- package/dist/chunk-QTCJ5CC5.js +172 -0
- package/dist/chunk-QVFV5IP2.js +232 -0
- package/dist/chunk-QVZMFDYG.js +29 -0
- package/dist/chunk-R35PEUKH.js +511 -0
- package/dist/chunk-R4UWBC35.js +200 -0
- package/dist/chunk-R6MLCREW.js +44 -0
- package/dist/chunk-R6W23LKN.js +254 -0
- package/dist/chunk-R7XDDX2A.js +4007 -0
- package/dist/chunk-RDFRCT64.js +168 -0
- package/dist/chunk-RE5VZDFQ.js +58 -0
- package/dist/chunk-RGROYC2G.js +638 -0
- package/dist/chunk-RGWHUI5E.js +68 -0
- package/dist/chunk-RHVG6UNL.js +205 -0
- package/dist/chunk-RI4EX2QE.js +18 -0
- package/dist/chunk-RJAAKDRX.js +17 -0
- package/dist/chunk-ROMHOSMQ.js +185 -0
- package/dist/chunk-RWREC3KJ.js +517 -0
- package/dist/chunk-RYNETRDJ.js +118 -0
- package/dist/chunk-RZY7RKM5.js +500 -0
- package/dist/chunk-S2MNWFAG.js +52 -0
- package/dist/chunk-S2VQCZO4.js +22 -0
- package/dist/chunk-S54MKU6V.js +117 -0
- package/dist/chunk-S5OIDFRM.js +302 -0
- package/dist/chunk-SCW4ZF6R.js +150 -0
- package/dist/chunk-SLS2N4PH.js +2213 -0
- package/dist/chunk-SNLBO4BF.js +247 -0
- package/dist/chunk-SP3LFU6B.js +60 -0
- package/dist/chunk-SQQTDDQA.js +537 -0
- package/dist/chunk-STV6LYYE.js +45 -0
- package/dist/chunk-SURZ2WFE.js +326 -0
- package/dist/chunk-SZ7DL357.js +1047 -0
- package/dist/chunk-T5E4NQCM.js +5742 -0
- package/dist/chunk-TAJPCXSB.js +13 -0
- package/dist/chunk-TAOOYK3P.js +358 -0
- package/dist/chunk-TDSEX5CF.js +24 -0
- package/dist/chunk-TFTGP7Z7.js +174 -0
- package/dist/chunk-TGON4N4O.js +197 -0
- package/dist/chunk-TGQZHDY2.js +2373 -0
- package/dist/chunk-TJJZ2OKV.js +6783 -0
- package/dist/chunk-TRSVUPCX.js +25 -0
- package/dist/chunk-TSXGRLPR.js +107 -0
- package/dist/chunk-U2S3YEX3.js +224 -0
- package/dist/chunk-U45RTRGY.js +818 -0
- package/dist/chunk-U6C3VVWS.js +13 -0
- package/dist/chunk-UDMS5AD3.js +307 -0
- package/dist/chunk-UGX7GI37.js +94 -0
- package/dist/chunk-UH3JJSHK.js +1 -0
- package/dist/chunk-UHRBTZYY.js +208 -0
- package/dist/chunk-UHT2KRG5.js +193 -0
- package/dist/chunk-UI2F6DJ5.js +118 -0
- package/dist/chunk-UMAKSB4Z.js +284 -0
- package/dist/chunk-UR2IBGIM.js +521 -0
- package/dist/chunk-UUH2RVKS.js +585 -0
- package/dist/chunk-UVJ4PJDK.js +4533 -0
- package/dist/chunk-V53UG2OT.js +9924 -0
- package/dist/chunk-V72RMBM4.js +48 -0
- package/dist/chunk-VBNCKCCI.js +16 -0
- package/dist/chunk-VNSYKC25.js +24 -0
- package/dist/chunk-VPHVFK4A.js +1984 -0
- package/dist/chunk-VTLNJQ44.js +133 -0
- package/dist/chunk-VTW7HP3R.js +100 -0
- package/dist/chunk-VVGEPBPS.js +218 -0
- package/dist/chunk-VVLLL7I4.js +166 -0
- package/dist/chunk-VX3UMWB7.js +483 -0
- package/dist/chunk-VXF4Q3FW.js +20 -0
- package/dist/chunk-W3JMT2YY.js +712 -0
- package/dist/chunk-WDUORIHF.js +877 -0
- package/dist/chunk-WDVTY4U6.js +148 -0
- package/dist/chunk-WIFZCHEG.js +12566 -0
- package/dist/chunk-WIRN3F75.js +736 -0
- package/dist/chunk-WMPU2UOV.js +82 -0
- package/dist/chunk-WTOKKE2V.js +784 -0
- package/dist/chunk-WX5IRLF6.js +740 -0
- package/dist/chunk-WZ6U3O7I.js +1581 -0
- package/dist/chunk-XAONGNST.js +57 -0
- package/dist/chunk-XB5YLCLB.js +13 -0
- package/dist/chunk-XEP5NQ5Y.js +688 -0
- package/dist/chunk-XGYF2QMZ.js +351 -0
- package/dist/chunk-XHEKQENB.js +255 -0
- package/dist/chunk-XNO4FM6X.js +1124 -0
- package/dist/chunk-XPHKYHO4.js +878 -0
- package/dist/chunk-XPK2I4NC.js +405 -0
- package/dist/chunk-XPU2XADL.js +2175 -0
- package/dist/chunk-XQD2B6BB.js +507 -0
- package/dist/chunk-XT2ZQVTC.js +558 -0
- package/dist/chunk-XTXJGGUV.js +351 -0
- package/dist/chunk-XUXVDPSZ.js +50 -0
- package/dist/chunk-XV7NZL4B.js +57 -0
- package/dist/chunk-XZE4XARH.js +563 -0
- package/dist/chunk-XZYR5EDO.js +152 -0
- package/dist/chunk-Y3J4JMTU.js +61 -0
- package/dist/chunk-Y55LZN5U.js +52 -0
- package/dist/chunk-Y5VN7DMP.js +112 -0
- package/dist/chunk-Y67VAHN4.js +459 -0
- package/dist/chunk-YAXSKEUH.js +3544 -0
- package/dist/chunk-YB3JD4E6.js +975 -0
- package/dist/chunk-YESZJFK6.js +220 -0
- package/dist/chunk-YGXKOBQQ.js +292 -0
- package/dist/chunk-YMX76IOS.js +31 -0
- package/dist/chunk-YOTXESEH.js +257 -0
- package/dist/chunk-YTYIEZQY.js +119 -0
- package/dist/chunk-YVORHQ2S.js +579 -0
- package/dist/chunk-Z2CUQDAR.js +3429 -0
- package/dist/chunk-Z2KYOFHS.js +7000 -0
- package/dist/chunk-Z6PC7QX6.js +161 -0
- package/dist/chunk-ZDTGECTN.js +235 -0
- package/dist/chunk-ZIPWI2LY.js +151 -0
- package/dist/chunk-ZSKKMTQJ.js +554 -0
- package/dist/chunk-ZTT5IVPY.js +1160 -0
- package/dist/chunk-ZX65UI5W.js +78 -0
- package/dist/chunk-ZYG7GGKO.js +218 -0
- package/dist/chunk-ZZZUL4OF.js +38 -0
- package/dist/cli-utils-IXL26KJT.js +40 -0
- package/dist/cli-validation-WLXWLUJL.js +111 -0
- package/dist/commit-utils-P7CRJF5N.js +202 -0
- package/dist/compete-config-resolver-R5ULXMYH.js +76 -0
- package/dist/compete-request-62JESVET.js +364 -0
- package/dist/compete-results-QEPG6FZX.js +208 -0
- package/dist/competition-outcome-tracker-R32OOZ43.js +38 -0
- package/dist/config-JCOKXOQT.js +166 -0
- package/dist/config-audit-EL3GHXS7.js +360 -0
- package/dist/config-explain-TNILDEVJ.js +12 -0
- package/dist/config-loader-VPFPFO4B.js +38 -0
- package/dist/config-manager-7T4E2BQO.js +67 -0
- package/dist/config-validator-KKOHOW7O.js +72 -0
- package/dist/cost-YC42XUF3.js +53 -0
- package/dist/coverage-orchestrator-CISNKJC2.js +772 -0
- package/dist/coverage-scanner-YVD62MLH.js +12 -0
- package/dist/createCompetitionRunner-LJG6ZQSO.js +46 -0
- package/dist/data-migration-state-VJK64DLT.js +31 -0
- package/dist/db-migrator-XSEIOGWY.js +34 -0
- package/dist/discovery-JGYGDD25.js +25 -0
- package/dist/doctor-GJOYE7AE.js +186 -0
- package/dist/domain-analyzer-AWF3RP6E.js +29 -0
- package/dist/ensure-initialized-744DIZEZ.js +52 -0
- package/dist/entry.js +940 -0
- package/dist/environment-YS45U5ZI.js +81 -0
- package/dist/error-parser-core-PPZ36A4S.js +50 -0
- package/dist/escalation-ladder-MKTCEGSA.js +130 -0
- package/dist/evaluation-context-KV4GZNN7.js +35 -0
- package/dist/evidence-plan-resolver-GBSYSAPX.js +85 -0
- package/dist/execution-data-writer-3ODTBDLH.js +53 -0
- package/dist/execution-policy-applier-ZHD3DCF3.js +31 -0
- package/dist/execution-preflight-Z4Y64V3I.js +209 -0
- package/dist/execution-roles-R3DPPMD3.js +66 -0
- package/dist/exit-code-error-Z4SW2DVK.js +14 -0
- package/dist/external-temp-cleanup-N2RZH4QP.js +311 -0
- package/dist/factory-XBN7DFIM.js +149 -0
- package/dist/file-utils-XIVR2ZMA.js +47 -0
- package/dist/flywheel-autoloop-executor-UILGOFFK.js +249 -0
- package/dist/flywheel-competition-executor-JOBEXTRB.js +259 -0
- package/dist/flywheel-executor-6JFLA6J5.js +369 -0
- package/dist/flywheel-git-isolation-UC5NIEVU.js +48 -0
- package/dist/flywheel-manifest-5UC4VBMA.js +108 -0
- package/dist/flywheel-model-defaults-7CVKP53V.js +27 -0
- package/dist/flywheel-preflight-XEY5SHM6.js +104 -0
- package/dist/flywheel-resume-7HELH7QS.js +23 -0
- package/dist/flywheel-safety-7U7DPOAP.js +28 -0
- package/dist/flywheel-scope-decision-ZHKF6ZIN.js +11 -0
- package/dist/get-telemetry-logger-DPVWWIYY.js +73 -0
- package/dist/git-worktree-IY6V6DUO.js +18 -0
- package/dist/github-pr-manager-4LXEKJTA.js +211 -0
- package/dist/guidance-profile-config-E7XJL2VP.js +117 -0
- package/dist/guidance-profile-renderer-QK2YMAAP.js +21 -0
- package/dist/index-query-4JEUKA44.js +31 -0
- package/dist/index.js +108661 -0
- package/dist/instructions-6BURLQJC.js +64 -0
- package/dist/invoke-provider-auth-GRUYP44M.js +223 -0
- package/dist/judge-scoring.json +80 -0
- package/dist/judge-test.js +555 -0
- package/dist/lab-mode-OTWVHN63.js +39 -0
- package/dist/lab-utils-BJRFLGK4.js +23 -0
- package/dist/linux-host-class-UY4KVLFD.js +29 -0
- package/dist/llm-judge-executor-F7Z3HO77.js +133 -0
- package/dist/local-executor-CEHWE2PL.js +223 -0
- package/dist/logger-33TR6EE5.js +72 -0
- package/dist/loop-spec-XTLQAVZ7.js +191 -0
- package/dist/manager-2HJG5CLT.js +25 -0
- package/dist/matrix-prompt-builder-6UDN5X3F.js +497 -0
- package/dist/matrix-result-parser-7W35EUOV.js +15 -0
- package/dist/metadata-HQ43NDEK.js +22 -0
- package/dist/model-invocations-db-QBO4Y7WZ.js +38 -0
- package/dist/monitor-XGYBG2DW.js +72 -0
- package/dist/next-PB5ZXZKB.js +90 -0
- package/dist/next-ZBDK725T.js +69 -0
- package/dist/optimization-config-resolver-O6WKR47U.js +75 -0
- package/dist/package-3YCWIQQ5.js +10 -0
- package/dist/parallel-orchestrator-NL7YJJU2.js +297 -0
- package/dist/parallel-worker.js +279 -0
- package/dist/parse-git-status-PIAF3OTP.js +10 -0
- package/dist/path-security-ETTH6TZL.js +39 -0
- package/dist/pattern-bank-UNJR5ADV.js +15 -0
- package/dist/plan-backlog-list-fast-VAGYBV3J.js +270 -0
- package/dist/plan-backlog-show-fast-SG2CZPW3.js +406 -0
- package/dist/plan-sprint-list-fast-LURAX47V.js +162 -0
- package/dist/plan-sprint-status-fast-FJAODCHD.js +208 -0
- package/dist/plan-task-status-fast-HNYBMQI4.js +349 -0
- package/dist/plan-to-flywheel-Z4U3GWPN.js +456 -0
- package/dist/planning-backlog-3CQ5QQBQ.js +319 -0
- package/dist/poetic-root-V5DNXEAE.js +17 -0
- package/dist/preflight-OPANWMME.js +12 -0
- package/dist/process-registry-PDZJPTAS.js +27 -0
- package/dist/process-scanner-C22SYXYD.js +22 -0
- package/dist/processes-KMQUD7HY.js +29 -0
- package/dist/processes-json-fast-IBDXZ6WW.js +135 -0
- package/dist/profile-SE5EVXAP.js +149 -0
- package/dist/prompts-WZZPGWBX.js +168 -0
- package/dist/protected-branches-RNTEX7ET.js +57 -0
- package/dist/provider-aware-resource-manager-QBTZJMNP.js +18 -0
- package/dist/provider-matrix-N5X57V3Y.js +154 -0
- package/dist/provider-matrix-renderer-MZDWKKID.js +139 -0
- package/dist/provider-output-forwarding-DERID3TP.js +30 -0
- package/dist/provider-registry-J5NRBJKI.js +128 -0
- package/dist/provider-temp-cleanup-KYGLF6YU.js +14 -0
- package/dist/prune-engine-Q6E2DXBN.js +451 -0
- package/dist/quality-gate-YRHMQAEI.js +70 -0
- package/dist/quickstart-FIRLKGJI.js +62 -0
- package/dist/readiness-VZTMSG6J.js +96 -0
- package/dist/registry-YODFY77A.js +153 -0
- package/dist/repair-helpers-TTV5FEF4.js +117 -0
- package/dist/repo-root-2IGD4H7X.js +22 -0
- package/dist/resolution-engine-D6TX6FRG.js +127 -0
- package/dist/resolve-provider-cli-O2P6XZBZ.js +35 -0
- package/dist/restore-telemetry-db-BQL6DTQF.js +360 -0
- package/dist/result-streamer-WEHW476R.js +19 -0
- package/dist/routing-events-DHPUZDDF.js +27 -0
- package/dist/routing-history-store-UWCEXAP3.js +46 -0
- package/dist/routing-planner-F5WQEUOM.js +160 -0
- package/dist/run-poetic-tui-J6LWRJUP.js +13517 -0
- package/dist/run-simulation.js +376 -0
- package/dist/runner-CS2TNGHA.js +1092 -0
- package/dist/runner-HHH7ZN2Z.js +1571 -0
- package/dist/safety-OCC4KJJR.js +64 -0
- package/dist/safety-stanza-7SV3HGG3.js +60 -0
- package/dist/sandbox-32QXJEMV.js +81 -0
- package/dist/sandbox-RSO7VP6V.js +94 -0
- package/dist/schema-extensions.sql +234 -0
- package/dist/security-2KI5XNDG.js +17 -0
- package/dist/setup-bb-plugin-QAQWZCV5.js +738 -0
- package/dist/setup-claude-code-P7BTTSPO.js +317 -0
- package/dist/setup-temp-cleanup-GASCWZ2I.js +20 -0
- package/dist/shared-utils-D6U6UREP.js +37 -0
- package/dist/simple-artifact-goal-OTXNGZY6.js +25 -0
- package/dist/sprint-UIXPYOXQ.js +338 -0
- package/dist/sprint-bridge-4BHMSC3M.js +68 -0
- package/dist/sprint-execution-service-2B7WHL5L.js +311 -0
- package/dist/sprint-manager-IDQUDNQI.js +91 -0
- package/dist/sqlite-wrapper-UDWCTNLJ.js +17 -0
- package/dist/stale-cleanup-orchestrator-XWXV7KCZ.js +62 -0
- package/dist/storage-access-F6ALDN4S.js +22 -0
- package/dist/synthesis-XD6EDVHF.js +185 -0
- package/dist/task-classifier-LNLXSHOM.js +494 -0
- package/dist/task-list-fast-PTMA4LUC.js +147 -0
- package/dist/task-manager-XAT7GOWB.js +93 -0
- package/dist/task-splitter-U7DJ7W6A.js +79 -0
- package/dist/task-type-detector-OLVOMXZO.js +21 -0
- package/dist/task-type-resolver-KKNQYSB4.js +42 -0
- package/dist/telemetry-5HWBBXLX.js +131 -0
- package/dist/telemetry-health-tracker-DMSSGBZ2.js +11 -0
- package/dist/telemetry-path-resolver-7ICSG276.js +28 -0
- package/dist/telemetry-reliability-XUOZNZZ6.js +125 -0
- package/dist/token-estimator-MEQUL3EJ.js +37 -0
- package/dist/transports-KNSSV2V4.js +255 -0
- package/dist/unified-cost-tracker-4TFRBVPR.js +35 -0
- package/dist/unified-state-cleanup-LJPF2BOW.js +276 -0
- package/dist/universal-cost-calculator-BAJV35GA.js +42 -0
- package/dist/user-agents-GHUGCSKN.js +22 -0
- package/dist/variant-delivery-state-KLRNG6XA.js +33 -0
- package/dist/variant-state-cleanup-MZGGLQAJ.js +280 -0
- package/dist/variant-success-PJXWE3ZV.js +12 -0
- package/dist/variant-worker-KUWKBLAH.js +4196 -0
- package/dist/variant-worker.js +24 -0
- package/dist/variants-JE2FSAQS.js +233 -0
- package/dist/verification-toolchains-V24UHW6Q.js +28 -0
- package/dist/verify-commands-H3DTCSGI.js +37 -0
- package/dist/warning-EGQGUUIO.js +12 -0
- package/dist/work-edge-RWEDWJZF.js +49 -0
- package/dist/work-item-writer-WHAVZXAY.js +19 -0
- package/dist/worker-7SA2VS2Y.js +1435 -0
- package/dist/worker.js +19 -0
- package/dist/worktree-metrics-3DFUYVYE.js +26 -0
- package/dist/writeback-VZKHYHSN.js +44 -0
- package/docs/CLI_REFERENCE.md +7042 -0
- package/docs/PROVIDER_SETUP.md +1570 -0
- package/docs/README.md +96 -0
- package/docs/TROUBLESHOOTING.md +2232 -0
- package/docs/getting-started/QUICK_START.md +294 -0
- package/docs/getting-started/README.md +188 -0
- package/docs/getting-started/SETUP.md +52 -0
- package/docs/reference/AGENT_CONTEXT.md +38 -0
- package/docs/reference/PROVIDER_RELEASE_TIERS.md +34 -0
- package/docs/reference/README.md +381 -0
- package/docs/reference/SECURITY.md +262 -0
- package/integrations/bb-plugin-poetic/README.md +362 -0
- package/integrations/bb-plugin-poetic/app.css +341 -0
- package/integrations/bb-plugin-poetic/app.tsx +5059 -0
- package/integrations/bb-plugin-poetic/package.json +45 -0
- package/integrations/bb-plugin-poetic/server.ts +444 -0
- package/integrations/bb-plugin-poetic/src/adapter.ts +3312 -0
- package/integrations/bb-plugin-poetic/src/backlog-authoring-model.ts +150 -0
- package/integrations/bb-plugin-poetic/src/backlog-authoring-schema.ts +355 -0
- package/integrations/bb-plugin-poetic/src/backlog-authoring-service.ts +419 -0
- package/integrations/bb-plugin-poetic/src/backlog-authoring-view.ts +1026 -0
- package/integrations/bb-plugin-poetic/src/competition-defaults-schema.ts +122 -0
- package/integrations/bb-plugin-poetic/src/competition-defaults-service.ts +105 -0
- package/integrations/bb-plugin-poetic/src/competition-defaults-view.ts +138 -0
- package/integrations/bb-plugin-poetic/src/contract.ts +615 -0
- package/integrations/bb-plugin-poetic/src/finalize-model.ts +205 -0
- package/integrations/bb-plugin-poetic/src/finalize-schema.ts +158 -0
- package/integrations/bb-plugin-poetic/src/finalize-service.ts +382 -0
- package/integrations/bb-plugin-poetic/src/finalize-view.ts +159 -0
- package/integrations/bb-plugin-poetic/src/judge-operations-readback.ts +303 -0
- package/integrations/bb-plugin-poetic/src/judge-operations-schema.ts +33 -0
- package/integrations/bb-plugin-poetic/src/judge-operations-view.ts +459 -0
- package/integrations/bb-plugin-poetic/src/model.ts +1302 -0
- package/integrations/bb-plugin-poetic/src/monitor-service.ts +233 -0
- package/integrations/bb-plugin-poetic/src/panel-read-ux.ts +97 -0
- package/integrations/bb-plugin-poetic/src/patch-preview-schema.ts +166 -0
- package/integrations/bb-plugin-poetic/src/patch-preview-service.ts +480 -0
- package/integrations/bb-plugin-poetic/src/patch-preview-view.ts +109 -0
- package/integrations/bb-plugin-poetic/src/planning-readback.ts +204 -0
- package/integrations/bb-plugin-poetic/src/planning-service.ts +594 -0
- package/integrations/bb-plugin-poetic/src/planning-workspace-schema.ts +95 -0
- package/integrations/bb-plugin-poetic/src/planning-workspace.ts +323 -0
- package/integrations/bb-plugin-poetic/src/poll-handoff.ts +136 -0
- package/integrations/bb-plugin-poetic/src/project-target-server.ts +21 -0
- package/integrations/bb-plugin-poetic/src/project-target.ts +45 -0
- package/integrations/bb-plugin-poetic/src/reference-index.ts +192 -0
- package/integrations/bb-plugin-poetic/src/repository-schema.ts +30 -0
- package/integrations/bb-plugin-poetic/src/result-explorer-view.ts +597 -0
- package/integrations/bb-plugin-poetic/src/result-readback-model.ts +163 -0
- package/integrations/bb-plugin-poetic/src/result-readback-schema.ts +319 -0
- package/integrations/bb-plugin-poetic/src/result-readback-service.ts +333 -0
- package/integrations/bb-plugin-poetic/src/run-page-view.ts +177 -0
- package/integrations/bb-plugin-poetic/src/setup-config-schema.ts +291 -0
- package/integrations/bb-plugin-poetic/src/setup-config-service.ts +590 -0
- package/integrations/bb-plugin-poetic/src/setup-config-view.ts +413 -0
- package/integrations/bb-plugin-poetic/src/sprint-close-model.ts +150 -0
- package/integrations/bb-plugin-poetic/src/sprint-close-schema.ts +136 -0
- package/integrations/bb-plugin-poetic/src/sprint-close-service.ts +341 -0
- package/integrations/bb-plugin-poetic/src/sprint-close-view.ts +116 -0
- package/integrations/bb-plugin-poetic/src/sprint-composition-model.ts +714 -0
- package/integrations/bb-plugin-poetic/src/sprint-composition-readback.ts +231 -0
- package/integrations/bb-plugin-poetic/src/sprint-composition-schema.ts +601 -0
- package/integrations/bb-plugin-poetic/src/sprint-composition-service.ts +775 -0
- package/integrations/bb-plugin-poetic/src/sprint-composition-view.ts +1221 -0
- package/integrations/bb-plugin-poetic/src/task-authoring-model.ts +567 -0
- package/integrations/bb-plugin-poetic/src/task-authoring-schema.ts +635 -0
- package/integrations/bb-plugin-poetic/src/task-authoring-service.ts +842 -0
- package/integrations/bb-plugin-poetic/src/task-authoring-view.ts +1227 -0
- package/integrations/bb-plugin-poetic/src/task-detail-readback.ts +56 -0
- package/integrations/bb-plugin-poetic/src/task-detail-schema.ts +144 -0
- package/integrations/bb-plugin-poetic/src/task-navigation.ts +446 -0
- package/integrations/bb-plugin-poetic/src/workbench-route.ts +74 -0
- package/integrations/bb-plugin-poetic/tests/host-contract.test.ts +773 -0
- package/integrations/bb-plugin-poetic/tsconfig.json +18 -0
- package/integrations/bb-plugin-poetic/types/PROVENANCE.json +52 -0
- package/integrations/bb-plugin-poetic/types/bb-plugin-sdk-app.d.ts +1444 -0
- package/integrations/bb-plugin-poetic/types/bb-plugin-sdk.d.ts +13030 -0
- package/integrations/bb-plugin-poetic/vitest.host.config.ts +71 -0
- package/npm-shrinkwrap.json +4950 -0
- package/package.json +331 -0
- package/schemas/README.md +80 -0
- package/schemas/config-v1.schema.json +136 -0
- package/schemas/execution-config.schema.json +47 -0
- package/schemas/judge-scoring.schema.json +370 -0
- package/schemas/poetic.config.schema.json +2214 -0
- package/schemas/provider-config.schema.json +203 -0
- package/schemas/telemetry-config.schema.json +79 -0
- package/schemas/user-preferences.schema.json +141 -0
- package/scripts/assert-node-runtime.mjs +140 -0
- package/scripts/preflight-native.mjs +49 -0
- package/scripts/preinstall-node-check.mjs +78 -0
- package/scripts/setup-git-hooks.mjs +24 -0
- package/scripts/sync.sh +2722 -0
- package/scripts/write-node-launcher.sh +108 -0
- package/src/resources/gemini/slash-packs/default/plan.toml +15 -0
- package/src/resources/gemini/slash-packs/default/summary.toml +16 -0
- package/src/resources/gemini/slash-packs/default/tests.toml +16 -0
- package/templates/.poetic/README.md +37 -0
- package/templates/.poetic/agents/README.md +296 -0
- package/templates/.poetic/agents/api-documenter.md +147 -0
- package/templates/.poetic/agents/backend-architect.md +31 -0
- package/templates/.poetic/agents/code-reviewer.md +157 -0
- package/templates/.poetic/agents/data-scientist.md +179 -0
- package/templates/.poetic/agents/database-optimizer.md +145 -0
- package/templates/.poetic/agents/debugger.md +31 -0
- package/templates/.poetic/agents/deployment-engineer.md +164 -0
- package/templates/.poetic/agents/devops-troubleshooter.md +139 -0
- package/templates/.poetic/agents/frontend-developer.md +150 -0
- package/templates/.poetic/agents/javascript-pro.md +36 -0
- package/templates/.poetic/agents/performance-engineer.md +151 -0
- package/templates/.poetic/agents/python-pro.md +137 -0
- package/templates/.poetic/agents/test-automator.md +147 -0
- package/templates/.poetic/agents/typescript-pro.md +34 -0
- package/templates/.poetic/config/poetic.config.jsonc +69 -0
- package/templates/.poetic/config/project-context.template.json +6 -0
- package/templates/.poetic/config/task-type-aliases.presets/kanban.yaml +14 -0
- package/templates/.poetic/config/task-type-aliases.presets/scrum.yaml +17 -0
- package/templates/.poetic/config/task-type-aliases.presets/xp.yaml +12 -0
- package/templates/.poetic/config/task-type-aliases.yaml +28 -0
- package/templates/.poetic/gitignore.template +55 -0
- package/templates/.poetic/task-types/analysis.yaml +40 -0
- package/templates/.poetic/task-types/architecture.yaml +38 -0
- package/templates/.poetic/task-types/doc.yaml +35 -0
- package/templates/.poetic/task-types/feature.yaml +23 -0
- package/templates/.poetic/task-types/general.yaml +6 -0
- package/templates/.poetic/task-types/security.yaml +39 -0
- package/templates/AGENTS.template.md +99 -0
- package/templates/CLAUDE.template.md +1 -0
- package/templates/GEMINI.template.md +1 -0
- package/templates/builtin-workflows/code-review.yaml +73 -0
- package/templates/builtin-workflows/compete-streak.yaml +78 -0
- package/templates/builtin-workflows/hello-verify.yaml +10 -0
- package/templates/builtin-workflows/judge-regression.yaml +114 -0
- package/templates/builtin-workflows/skills/code-review/SKILL.md +60 -0
- package/templates/builtin-workflows/skills/hello-verify/SKILL.md +6 -0
- package/templates/guard-kit/GUARD_SETUP.md.template +255 -0
- package/templates/guard-kit/check.mjs.template +777 -0
- package/templates/guard-kit/config.json.template +6 -0
- package/templates/guard-kit/poetic-guard.yml.template +189 -0
- package/templates/profiles/README.md +56 -0
- package/templates/profiles/frontier-claude.json +27 -0
- package/templates/profiles/frontier-codex.json +26 -0
|
@@ -0,0 +1,1302 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { JudgeOperationsView } from './judge-operations-view.js';
|
|
3
|
+
import type { CanonicalTaskStatus, PlanningWorkspaceProjection } from './planning-service.js';
|
|
4
|
+
import { planningWorkspaceProjectionSchema } from './planning-workspace-schema.js';
|
|
5
|
+
import { repositorySchema } from './repository-schema.js';
|
|
6
|
+
import { type GetTaskDetailOutput, getTaskDetailOutputSchema } from './task-detail-schema.js';
|
|
7
|
+
|
|
8
|
+
export const RUN_SNAPSHOT_VERSION = '1.0.0' as const;
|
|
9
|
+
|
|
10
|
+
export const HOST_TRUST_DISCLOSURE = {
|
|
11
|
+
fullTrust: true,
|
|
12
|
+
hostEquivalentExecution: true,
|
|
13
|
+
providerAuth: 'native',
|
|
14
|
+
planningSync: false,
|
|
15
|
+
gitPush: false,
|
|
16
|
+
summary:
|
|
17
|
+
'This full-trust local plugin runs Poetic as your host user in the selected repository. Fusion may use native provider authentication and create worktrees or artifacts. This milestone action does not synchronize managed planning state or push Git changes.',
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
export const TRACKED_EXECUTION_DISCLOSURE = {
|
|
21
|
+
fullTrust: true,
|
|
22
|
+
hostEquivalentExecution: true,
|
|
23
|
+
providerAuth: 'native',
|
|
24
|
+
planningSync: true,
|
|
25
|
+
gitCommits: true,
|
|
26
|
+
gitPush: true,
|
|
27
|
+
pullRequestCreation: true,
|
|
28
|
+
explicitFinalization: true,
|
|
29
|
+
summary:
|
|
30
|
+
'Tracked execution runs the installed canonical Poetic backlog lifecycle as your host user. It requires a clean checkout and may create or switch branches, synchronize managed planning state, invoke providers, create commits, push Git changes, and open a pull request. Finalization remains a separate explicit Poetic action.',
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Closed BB task-action vocabulary. Each name maps to one fixed Poetic plan-task
|
|
35
|
+
* lifecycle command; the contract never accepts a free-form command, argv, flag,
|
|
36
|
+
* status matrix, or generic task update.
|
|
37
|
+
*/
|
|
38
|
+
export const TASK_ACTION_VOCABULARY = [
|
|
39
|
+
'start',
|
|
40
|
+
'block',
|
|
41
|
+
'unblock',
|
|
42
|
+
'review',
|
|
43
|
+
'complete',
|
|
44
|
+
'cancel',
|
|
45
|
+
'reopen',
|
|
46
|
+
] as const;
|
|
47
|
+
|
|
48
|
+
export type TaskActionKind = (typeof TASK_ACTION_VOCABULARY)[number];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Actions that archive or reopen terminal planning state. The request schema
|
|
52
|
+
* requires an extra archival/terminal confirmation for these only.
|
|
53
|
+
*/
|
|
54
|
+
export const TASK_ACTION_TERMINAL_KINDS = ['complete', 'cancel', 'reopen'] as const;
|
|
55
|
+
|
|
56
|
+
export type TaskActionTerminalKind = (typeof TASK_ACTION_TERMINAL_KINDS)[number];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Actions that require a non-empty reason string in the request schema.
|
|
60
|
+
*/
|
|
61
|
+
export const TASK_ACTION_REASON_KINDS = ['block', 'cancel', 'reopen'] as const;
|
|
62
|
+
|
|
63
|
+
export type TaskActionReasonKind = (typeof TASK_ACTION_REASON_KINDS)[number];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Disclosure for BB task lifecycle actions over managed planning files.
|
|
67
|
+
* Distinct from Fusion (no planning sync/push), tracked backlog execution
|
|
68
|
+
* (branch/PR/finalization lifecycle), and run cancellation (process control).
|
|
69
|
+
*/
|
|
70
|
+
export const TASK_PLANNING_DISCLOSURE = {
|
|
71
|
+
fullTrust: true,
|
|
72
|
+
hostEquivalentExecution: true,
|
|
73
|
+
providerAuth: 'native',
|
|
74
|
+
planningSync: true,
|
|
75
|
+
gitCommits: true,
|
|
76
|
+
gitPush: true,
|
|
77
|
+
managedPlanningMutation: true,
|
|
78
|
+
pullRequestCreation: false,
|
|
79
|
+
fusionLaunch: false,
|
|
80
|
+
trackedBacklogExecution: false,
|
|
81
|
+
runCancellation: false,
|
|
82
|
+
summary:
|
|
83
|
+
"Task lifecycle actions run the installed Poetic plan-task commands as your host user in the selected repository and branch. They mutate managed planning state, and Poetic's built-in managed sync commits and pushes those planning changes. They do not launch Fusion, start tracked backlog execution, create pull requests, or cancel runs. Complete archives a finished task; cancel archives without completion; reopen restores an archived or done task. BB never passes --no-sync or --force.",
|
|
84
|
+
} as const;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Consent the UI must collect before any task lifecycle action. Every field is
|
|
88
|
+
* a required true literal so partial or false consent fails schema validation.
|
|
89
|
+
*/
|
|
90
|
+
export interface TaskActionConsent {
|
|
91
|
+
hostExecution: true;
|
|
92
|
+
managedPlanningMutation: true;
|
|
93
|
+
automaticCommitAndPush: true;
|
|
94
|
+
selectedRepositoryAndBranch: true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Extra consent for complete, cancel, and reopen (archival or terminal restore).
|
|
99
|
+
*/
|
|
100
|
+
export interface TaskActionTerminalConsent extends TaskActionConsent {
|
|
101
|
+
archivalOrTerminalConfirmation: true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type TaskActionAdmissionScope = {
|
|
105
|
+
repositoryPath: string;
|
|
106
|
+
taskId: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Fixed Poetic argv prefix for each action in the closed vocabulary. Nothing is
|
|
111
|
+
* appended beyond the managed task id and, for the reason actions, the single
|
|
112
|
+
* `--reason=<text>` token: no `--no-sync`, no `--force`, no `--to`, no `--json`,
|
|
113
|
+
* and no caller-supplied flag can reach the child process.
|
|
114
|
+
*/
|
|
115
|
+
const TASK_ACTION_COMMAND: Readonly<Record<TaskActionKind, readonly string[]>> = {
|
|
116
|
+
start: ['plan', 'task', 'start'],
|
|
117
|
+
block: ['plan', 'task', 'block'],
|
|
118
|
+
unblock: ['plan', 'task', 'unblock'],
|
|
119
|
+
review: ['plan', 'task', 'review'],
|
|
120
|
+
complete: ['plan', 'task', 'complete'],
|
|
121
|
+
cancel: ['plan', 'task', 'cancel'],
|
|
122
|
+
reopen: ['plan', 'task', 'reopen'],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The action identity the adapter needs, narrowed so a reason is present exactly
|
|
127
|
+
* for the reason actions. The validated RPC request satisfies this shape.
|
|
128
|
+
*/
|
|
129
|
+
export type TaskActionCommandRequest =
|
|
130
|
+
| { action: Exclude<TaskActionKind, TaskActionReasonKind>; taskId: string }
|
|
131
|
+
| { action: TaskActionReasonKind; taskId: string; reason: string };
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Build the fixed argv for one task action.
|
|
135
|
+
*
|
|
136
|
+
* The reason is passed as a single `--reason=<text>` token so a reason that
|
|
137
|
+
* begins with a dash can never be read as another option, and the whole argv is
|
|
138
|
+
* spawned without a shell.
|
|
139
|
+
*/
|
|
140
|
+
export function taskActionArgv(request: TaskActionCommandRequest): string[] {
|
|
141
|
+
const argv = [...TASK_ACTION_COMMAND[request.action], request.taskId];
|
|
142
|
+
switch (request.action) {
|
|
143
|
+
case 'block':
|
|
144
|
+
case 'cancel':
|
|
145
|
+
case 'reopen':
|
|
146
|
+
argv.push(`--reason=${request.reason}`);
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
return argv;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* What Poetic's own invocation reported, for the current invocation only.
|
|
156
|
+
*
|
|
157
|
+
* `state` is exit evidence and nothing more: it never outranks the authoritative
|
|
158
|
+
* Planning Workspace and task reread, and it never asserts that managed sync
|
|
159
|
+
* reached the remote — hence the always-false
|
|
160
|
+
* `remoteSyncConfirmedByExitCode`. `attempts` is fixed at 1 because a timeout or
|
|
161
|
+
* an ambiguous completion is never retried automatically.
|
|
162
|
+
*/
|
|
163
|
+
export interface TaskActionCommandEvidence {
|
|
164
|
+
state: 'succeeded' | 'failed';
|
|
165
|
+
attempts: 1;
|
|
166
|
+
argv: string[];
|
|
167
|
+
diagnostics: string | null;
|
|
168
|
+
remoteSyncConfirmedByExitCode: false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Authoritative result of one applied task action: the command evidence plus a
|
|
173
|
+
* complete workspace reread and a fresh reread of the selected task.
|
|
174
|
+
*/
|
|
175
|
+
export interface TaskActionOutcome {
|
|
176
|
+
action: TaskActionKind;
|
|
177
|
+
taskId: string;
|
|
178
|
+
command: TaskActionCommandEvidence;
|
|
179
|
+
/** Advisory sync disclosure derived only from the fresh workspace reread. */
|
|
180
|
+
syncWarnings: string[];
|
|
181
|
+
workspace: PlanningWorkspaceProjection;
|
|
182
|
+
taskDetail: GetTaskDetailOutput;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Surface Poetic's current planning-sync evidence from a fresh workspace reread.
|
|
187
|
+
*
|
|
188
|
+
* Everything here comes from what Poetic published, never from the action's exit
|
|
189
|
+
* code, so a successful command with unpushed planning commits or a recorded
|
|
190
|
+
* sync failure still reads as a warning rather than as remote success.
|
|
191
|
+
*/
|
|
192
|
+
export function taskActionSyncWarnings(workspace: PlanningWorkspaceProjection): string[] {
|
|
193
|
+
const warnings: string[] = [];
|
|
194
|
+
const health = workspace.data.syncHealth;
|
|
195
|
+
if (health.state !== 'in-sync') {
|
|
196
|
+
warnings.push(health.detail ?? `Poetic reports planning sync state ${health.state}.`);
|
|
197
|
+
}
|
|
198
|
+
for (const note of workspace.notes) {
|
|
199
|
+
if (note.scope === 'sync-health') warnings.push(note.detail);
|
|
200
|
+
}
|
|
201
|
+
return [...new Set(warnings)];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Process-local admission for BB task actions. Prevents overlapping submissions
|
|
206
|
+
* for the same repository path and task id inside this plugin process only.
|
|
207
|
+
* Does not claim cross-process ownership, file locks, or Poetic-side exclusivity.
|
|
208
|
+
*/
|
|
209
|
+
export class ProcessLocalTaskActionAdmission {
|
|
210
|
+
private readonly claims = new Set<string>();
|
|
211
|
+
|
|
212
|
+
private scopeKey(scope: TaskActionAdmissionScope): string {
|
|
213
|
+
return `${scope.repositoryPath}\u0000${scope.taskId}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Claim exclusive process-local admission for one repository+task. Returns a
|
|
218
|
+
* release function that is safe to call more than once. Throws when another
|
|
219
|
+
* claim for the same scope is still held in this process.
|
|
220
|
+
*/
|
|
221
|
+
claim(scope: TaskActionAdmissionScope): () => void {
|
|
222
|
+
const key = this.scopeKey(scope);
|
|
223
|
+
if (this.claims.has(key)) {
|
|
224
|
+
throw new Error(
|
|
225
|
+
`A BB task action is already in progress for task ${scope.taskId} in this repository. Process-local admission refuses overlapping submissions; this is not cross-process ownership.`
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
this.claims.add(key);
|
|
229
|
+
let released = false;
|
|
230
|
+
return () => {
|
|
231
|
+
if (released) return;
|
|
232
|
+
released = true;
|
|
233
|
+
this.claims.delete(key);
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
isBusy(scope: TaskActionAdmissionScope): boolean {
|
|
238
|
+
return this.claims.has(this.scopeKey(scope));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Pure presentation and interaction for the BB task lifecycle controls.
|
|
244
|
+
*
|
|
245
|
+
* Nothing below reads Poetic internals, managed planning files, Git, the
|
|
246
|
+
* filesystem, or the network, and nothing mutates planning state. Displayed
|
|
247
|
+
* eligibility is advisory only: it never gates a submission and never predicts a
|
|
248
|
+
* resulting status. Poetic's own command outcome and its fresh rereads remain the
|
|
249
|
+
* only authority, so no queue movement or terminal state is ever derived here.
|
|
250
|
+
*/
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Consent checkboxes exactly as the operator left them. Plain booleans: nothing
|
|
254
|
+
* here counts as consent until `taskActionConsentPayload` converts it, and that
|
|
255
|
+
* conversion fails closed on a partial acknowledgement.
|
|
256
|
+
*/
|
|
257
|
+
export interface TaskActionConsentState {
|
|
258
|
+
hostExecution: boolean;
|
|
259
|
+
managedPlanningMutation: boolean;
|
|
260
|
+
automaticCommitAndPush: boolean;
|
|
261
|
+
selectedRepositoryAndBranch: boolean;
|
|
262
|
+
/** Required for complete, cancel, and reopen only. */
|
|
263
|
+
archivalOrTerminalConfirmation: boolean;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export const EMPTY_TASK_ACTION_CONSENT: Readonly<TaskActionConsentState> = {
|
|
267
|
+
hostExecution: false,
|
|
268
|
+
managedPlanningMutation: false,
|
|
269
|
+
automaticCommitAndPush: false,
|
|
270
|
+
selectedRepositoryAndBranch: false,
|
|
271
|
+
archivalOrTerminalConfirmation: false,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/** Reason text per reason action, as typed. Empty means no reason was given. */
|
|
275
|
+
export type TaskActionReasonState = Readonly<Record<TaskActionReasonKind, string>>;
|
|
276
|
+
|
|
277
|
+
export const EMPTY_TASK_ACTION_REASONS: TaskActionReasonState = {
|
|
278
|
+
block: '',
|
|
279
|
+
cancel: '',
|
|
280
|
+
reopen: '',
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
export function isTaskActionTerminalKind(action: TaskActionKind): action is TaskActionTerminalKind {
|
|
284
|
+
return (TASK_ACTION_TERMINAL_KINDS as readonly TaskActionKind[]).includes(action);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function isTaskActionReasonKind(action: TaskActionKind): action is TaskActionReasonKind {
|
|
288
|
+
return (TASK_ACTION_REASON_KINDS as readonly TaskActionKind[]).includes(action);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Convert collected consent into the exact shape the RPC schema requires, or
|
|
293
|
+
* null when the acknowledgement is incomplete. Returning null is the enforcement
|
|
294
|
+
* point: a caller cannot build a request without full consent.
|
|
295
|
+
*/
|
|
296
|
+
export function taskActionConsentPayload(
|
|
297
|
+
action: TaskActionKind,
|
|
298
|
+
consent: TaskActionConsentState
|
|
299
|
+
): TaskActionConsent | TaskActionTerminalConsent | null {
|
|
300
|
+
if (
|
|
301
|
+
!consent.hostExecution ||
|
|
302
|
+
!consent.managedPlanningMutation ||
|
|
303
|
+
!consent.automaticCommitAndPush ||
|
|
304
|
+
!consent.selectedRepositoryAndBranch
|
|
305
|
+
) {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
const base: TaskActionConsent = {
|
|
309
|
+
hostExecution: true,
|
|
310
|
+
managedPlanningMutation: true,
|
|
311
|
+
automaticCommitAndPush: true,
|
|
312
|
+
selectedRepositoryAndBranch: true,
|
|
313
|
+
};
|
|
314
|
+
if (!isTaskActionTerminalKind(action)) return base;
|
|
315
|
+
if (!consent.archivalOrTerminalConfirmation) return null;
|
|
316
|
+
return { ...base, archivalOrTerminalConfirmation: true };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Control labels. `complete` names completion and archival together, `unblock`
|
|
321
|
+
* names only the return to active planning so it can never read as completion,
|
|
322
|
+
* and `cancel` names the task explicitly so it stays distinct from cancelling a
|
|
323
|
+
* run.
|
|
324
|
+
*/
|
|
325
|
+
export const TASK_ACTION_LABELS: Readonly<Record<TaskActionKind, string>> = {
|
|
326
|
+
start: 'Start task',
|
|
327
|
+
block: 'Block task',
|
|
328
|
+
unblock: 'Unblock task',
|
|
329
|
+
review: 'Move task to review',
|
|
330
|
+
complete: 'Complete and archive task',
|
|
331
|
+
cancel: 'Cancel task',
|
|
332
|
+
reopen: 'Reopen task',
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
/** Concise action-first labels for buttons; detailed effects remain adjacent. */
|
|
336
|
+
export const TASK_ACTION_BUTTON_LABELS: Readonly<Record<TaskActionKind, string>> = {
|
|
337
|
+
start: 'Start Task',
|
|
338
|
+
block: 'Block Task',
|
|
339
|
+
unblock: 'Unblock Task',
|
|
340
|
+
review: 'Move to Review',
|
|
341
|
+
complete: 'Complete Task',
|
|
342
|
+
cancel: 'Cancel Task',
|
|
343
|
+
reopen: 'Reopen Task',
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* What each Poetic command is asked to do. These describe the request, never a
|
|
348
|
+
* predicted result: the recorded status always comes from Poetic's own reread.
|
|
349
|
+
*/
|
|
350
|
+
export const TASK_ACTION_EFFECTS: Readonly<Record<TaskActionKind, string>> = {
|
|
351
|
+
start: 'Asks Poetic to start this task. Poetic decides and records the resulting status.',
|
|
352
|
+
block: 'Asks Poetic to record this task as blocked with your reason.',
|
|
353
|
+
unblock:
|
|
354
|
+
'Asks Poetic to clear the recorded block and return this task to active planning. This is not completion: it never records a done, cancelled, or archived state.',
|
|
355
|
+
review: 'Asks Poetic to move this task into review.',
|
|
356
|
+
complete:
|
|
357
|
+
'Asks Poetic to complete this task and archive it out of active planning. Completion and archival happen together.',
|
|
358
|
+
cancel:
|
|
359
|
+
'Asks Poetic to cancel this task and archive it without completion. This is a planning action: it does not cancel a Poetic run or stop any running process.',
|
|
360
|
+
reopen: 'Asks Poetic to reopen this task from a done or cancelled state.',
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Statuses in which Poetic's last read makes an action a usual next step. This
|
|
365
|
+
* is a display hint only; every control stays submittable so Poetic, not BB,
|
|
366
|
+
* decides what a transition means.
|
|
367
|
+
*/
|
|
368
|
+
const TASK_ACTION_USUAL_STATUS: Readonly<Record<TaskActionKind, readonly CanonicalTaskStatus[]>> = {
|
|
369
|
+
start: ['todo'],
|
|
370
|
+
block: ['todo', 'in_progress', 'review'],
|
|
371
|
+
unblock: ['blocked'],
|
|
372
|
+
review: ['in_progress'],
|
|
373
|
+
complete: ['in_progress', 'review'],
|
|
374
|
+
cancel: ['todo', 'in_progress', 'review', 'blocked'],
|
|
375
|
+
reopen: ['done', 'cancelled'],
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* One progression-oriented presentation hint for each canonical status. This
|
|
380
|
+
* never hides or admits an action; Poetic remains the transition authority.
|
|
381
|
+
*/
|
|
382
|
+
const TASK_ACTION_RECOMMENDED: Readonly<Record<CanonicalTaskStatus, TaskActionKind>> = {
|
|
383
|
+
todo: 'start',
|
|
384
|
+
in_progress: 'review',
|
|
385
|
+
review: 'complete',
|
|
386
|
+
blocked: 'unblock',
|
|
387
|
+
done: 'reopen',
|
|
388
|
+
cancelled: 'reopen',
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Advisory eligibility hint. `advisory` is a true literal so this can never be
|
|
393
|
+
* read as an authoritative decision, and `unknown` stays distinct from `unusual`.
|
|
394
|
+
*/
|
|
395
|
+
export interface TaskActionAdvisoryView {
|
|
396
|
+
state: 'usual' | 'unusual' | 'unknown';
|
|
397
|
+
label: string;
|
|
398
|
+
advisory: true;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function taskActionAdvisory(
|
|
402
|
+
action: TaskActionKind,
|
|
403
|
+
status: CanonicalTaskStatus | null
|
|
404
|
+
): TaskActionAdvisoryView {
|
|
405
|
+
if (status === null) {
|
|
406
|
+
return {
|
|
407
|
+
state: 'unknown',
|
|
408
|
+
label:
|
|
409
|
+
'Poetic reported no status for this task, so BB cannot indicate whether this action is usual here. Poetic decides.',
|
|
410
|
+
advisory: true,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
if (TASK_ACTION_USUAL_STATUS[action].includes(status)) {
|
|
414
|
+
return {
|
|
415
|
+
state: 'usual',
|
|
416
|
+
label:
|
|
417
|
+
'Usual next step for the status Poetic last reported. Poetic still decides the result.',
|
|
418
|
+
advisory: true,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
state: 'unusual',
|
|
423
|
+
label:
|
|
424
|
+
'Not a usual next step for the status Poetic last reported. Submitting is still allowed; Poetic accepts or refuses it.',
|
|
425
|
+
advisory: true,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** The canonical read state BB holds for the selected task. */
|
|
430
|
+
export type TaskActionDetailState = 'available' | 'missing' | 'unavailable' | 'none';
|
|
431
|
+
|
|
432
|
+
/** One unresolved submission this panel owns. */
|
|
433
|
+
export interface TaskActionSubmissionState {
|
|
434
|
+
taskId: string;
|
|
435
|
+
action: TaskActionKind;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export interface TaskActionGateInput {
|
|
439
|
+
action: TaskActionKind;
|
|
440
|
+
taskId: string;
|
|
441
|
+
/** Raw reason text; trimmed here and required for the reason actions. */
|
|
442
|
+
reason: string;
|
|
443
|
+
consent: TaskActionConsentState;
|
|
444
|
+
/** Unresolved submission this panel already owns, or null. */
|
|
445
|
+
inFlight: TaskActionSubmissionState | null;
|
|
446
|
+
detailState: TaskActionDetailState;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* The single refusal gate for a task action, shared by the rendered controls and
|
|
451
|
+
* by request construction so a disabled control and a refused submission always
|
|
452
|
+
* agree. Returns the plain reason, or null when the action may be submitted.
|
|
453
|
+
*/
|
|
454
|
+
export function taskActionRefusal(input: TaskActionGateInput): string | null {
|
|
455
|
+
switch (input.detailState) {
|
|
456
|
+
case 'missing':
|
|
457
|
+
return `Poetic reports no managed task ${input.taskId}, so no lifecycle action is submitted.`;
|
|
458
|
+
case 'unavailable':
|
|
459
|
+
return `Poetic could not describe task ${input.taskId}, so no lifecycle action is submitted.`;
|
|
460
|
+
case 'none':
|
|
461
|
+
return 'BB holds no canonical task detail for this task, so no lifecycle action is submitted.';
|
|
462
|
+
default:
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
const inFlight = input.inFlight;
|
|
466
|
+
if (inFlight) {
|
|
467
|
+
if (inFlight.taskId === input.taskId && inFlight.action === input.action) {
|
|
468
|
+
return `This panel already submitted ${TASK_ACTION_LABELS[input.action].toLowerCase()} for ${input.taskId} and Poetic has not answered yet.`;
|
|
469
|
+
}
|
|
470
|
+
return `This panel already submitted ${TASK_ACTION_LABELS[inFlight.action].toLowerCase()} for ${inFlight.taskId} and Poetic has not answered yet. Wait for that action before submitting another.`;
|
|
471
|
+
}
|
|
472
|
+
if (isTaskActionReasonKind(input.action) && input.reason.trim().length === 0) {
|
|
473
|
+
return `Poetic requires a reason for ${TASK_ACTION_LABELS[input.action].toLowerCase()}. Enter one before submitting.`;
|
|
474
|
+
}
|
|
475
|
+
if (taskActionConsentPayload(input.action, input.consent) === null) {
|
|
476
|
+
return isTaskActionTerminalKind(input.action)
|
|
477
|
+
? 'Accept every consent line, including the archival or terminal confirmation, before submitting.'
|
|
478
|
+
: 'Accept every consent line before submitting.';
|
|
479
|
+
}
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** The validated repository and task identity every request carries. */
|
|
484
|
+
interface TaskActionRequestTarget {
|
|
485
|
+
projectId: string;
|
|
486
|
+
sourceId: string;
|
|
487
|
+
taskId: string;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* A fully validated applyTaskAction request. One member per action so it matches
|
|
492
|
+
* the frozen discriminated RPC schema exactly; nothing beyond the target, the
|
|
493
|
+
* task id, the required reason, and consent can be carried.
|
|
494
|
+
*/
|
|
495
|
+
export type TaskActionRequestPayload =
|
|
496
|
+
| (TaskActionRequestTarget & { action: 'start'; consent: TaskActionConsent })
|
|
497
|
+
| (TaskActionRequestTarget & { action: 'block'; reason: string; consent: TaskActionConsent })
|
|
498
|
+
| (TaskActionRequestTarget & { action: 'unblock'; consent: TaskActionConsent })
|
|
499
|
+
| (TaskActionRequestTarget & { action: 'review'; consent: TaskActionConsent })
|
|
500
|
+
| (TaskActionRequestTarget & { action: 'complete'; consent: TaskActionTerminalConsent })
|
|
501
|
+
| (TaskActionRequestTarget & {
|
|
502
|
+
action: 'cancel';
|
|
503
|
+
reason: string;
|
|
504
|
+
consent: TaskActionTerminalConsent;
|
|
505
|
+
})
|
|
506
|
+
| (TaskActionRequestTarget & {
|
|
507
|
+
action: 'reopen';
|
|
508
|
+
reason: string;
|
|
509
|
+
consent: TaskActionTerminalConsent;
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
export type TaskActionRequestDecision =
|
|
513
|
+
| { admitted: true; request: TaskActionRequestPayload }
|
|
514
|
+
| { admitted: false; reason: string };
|
|
515
|
+
|
|
516
|
+
export interface TaskActionRequestInput extends TaskActionGateInput {
|
|
517
|
+
projectId: string;
|
|
518
|
+
sourceId: string;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Build one applyTaskAction request, or refuse it. Required reasons, full
|
|
523
|
+
* consent, an available canonical read, and single-submission admission are all
|
|
524
|
+
* enforced here, before any RPC call exists.
|
|
525
|
+
*/
|
|
526
|
+
export function buildTaskActionRequest(input: TaskActionRequestInput): TaskActionRequestDecision {
|
|
527
|
+
const refusal = taskActionRefusal(input);
|
|
528
|
+
if (refusal !== null) return { admitted: false, reason: refusal };
|
|
529
|
+
const target: TaskActionRequestTarget = {
|
|
530
|
+
projectId: input.projectId,
|
|
531
|
+
sourceId: input.sourceId,
|
|
532
|
+
taskId: input.taskId,
|
|
533
|
+
};
|
|
534
|
+
const reason = input.reason.trim();
|
|
535
|
+
// The gate above passed, so `taskActionConsentPayload` accepted this consent:
|
|
536
|
+
// every base field is acknowledged, and for a terminal action the archival
|
|
537
|
+
// confirmation is too. These literals are therefore what consent already says,
|
|
538
|
+
// built without a cast so the RPC schema still type-checks each member.
|
|
539
|
+
const consent: TaskActionConsent = {
|
|
540
|
+
hostExecution: true,
|
|
541
|
+
managedPlanningMutation: true,
|
|
542
|
+
automaticCommitAndPush: true,
|
|
543
|
+
selectedRepositoryAndBranch: true,
|
|
544
|
+
};
|
|
545
|
+
const terminalConsent: TaskActionTerminalConsent = {
|
|
546
|
+
...consent,
|
|
547
|
+
archivalOrTerminalConfirmation: true,
|
|
548
|
+
};
|
|
549
|
+
switch (input.action) {
|
|
550
|
+
case 'start':
|
|
551
|
+
return { admitted: true, request: { ...target, action: 'start', consent } };
|
|
552
|
+
case 'unblock':
|
|
553
|
+
return { admitted: true, request: { ...target, action: 'unblock', consent } };
|
|
554
|
+
case 'review':
|
|
555
|
+
return { admitted: true, request: { ...target, action: 'review', consent } };
|
|
556
|
+
case 'block':
|
|
557
|
+
return { admitted: true, request: { ...target, action: 'block', reason, consent } };
|
|
558
|
+
case 'complete':
|
|
559
|
+
return {
|
|
560
|
+
admitted: true,
|
|
561
|
+
request: { ...target, action: 'complete', consent: terminalConsent },
|
|
562
|
+
};
|
|
563
|
+
case 'cancel':
|
|
564
|
+
return {
|
|
565
|
+
admitted: true,
|
|
566
|
+
request: { ...target, action: 'cancel', reason, consent: terminalConsent },
|
|
567
|
+
};
|
|
568
|
+
case 'reopen':
|
|
569
|
+
return {
|
|
570
|
+
admitted: true,
|
|
571
|
+
request: { ...target, action: 'reopen', reason, consent: terminalConsent },
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** One rendered lifecycle control. */
|
|
577
|
+
export interface TaskActionControlView {
|
|
578
|
+
action: TaskActionKind;
|
|
579
|
+
label: string;
|
|
580
|
+
buttonLabel: string;
|
|
581
|
+
effectLabel: string;
|
|
582
|
+
/**
|
|
583
|
+
* Always `task-lifecycle`: these controls act on managed planning state, never
|
|
584
|
+
* on a run, so cancelling a task can never be rendered as cancelling a run.
|
|
585
|
+
*/
|
|
586
|
+
domain: 'task-lifecycle';
|
|
587
|
+
requiresReason: boolean;
|
|
588
|
+
requiresTerminalConfirmation: boolean;
|
|
589
|
+
advisory: TaskActionAdvisoryView;
|
|
590
|
+
/** True while this panel's unresolved submission is exactly this action. */
|
|
591
|
+
busy: boolean;
|
|
592
|
+
/** True while this panel holds any unresolved lifecycle submission. */
|
|
593
|
+
taskBusy: boolean;
|
|
594
|
+
submittable: boolean;
|
|
595
|
+
/** Plain reason the control cannot be submitted; null when it can. */
|
|
596
|
+
blockedReason: string | null;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export interface TaskActionControlsView {
|
|
600
|
+
state: 'available' | 'unavailable';
|
|
601
|
+
taskId: string;
|
|
602
|
+
/** Why no controls are offered; null when they are. */
|
|
603
|
+
unavailableReason: string | null;
|
|
604
|
+
controls: readonly TaskActionControlView[];
|
|
605
|
+
/** Progression-oriented display hint only; null when status is unavailable. */
|
|
606
|
+
recommendedAction: TaskActionKind | null;
|
|
607
|
+
advisoryNotice: string;
|
|
608
|
+
concurrencyNotice: string;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
export interface TaskActionControlsInput {
|
|
612
|
+
taskId: string;
|
|
613
|
+
detailState: TaskActionDetailState;
|
|
614
|
+
/** Poetic's last reported status, used only for the advisory hint. */
|
|
615
|
+
status: CanonicalTaskStatus | null;
|
|
616
|
+
reasons: TaskActionReasonState;
|
|
617
|
+
consent: TaskActionConsentState;
|
|
618
|
+
inFlight: TaskActionSubmissionState | null;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export const TASK_ACTION_ADVISORY_NOTICE =
|
|
622
|
+
'Eligibility shown here is advisory. Poetic accepts or refuses every action, and its command outcome plus its fresh reread are the only authority.';
|
|
623
|
+
|
|
624
|
+
export const TASK_ACTION_CONCURRENCY_NOTICE =
|
|
625
|
+
'This panel submits one task lifecycle action at a time. Another BB panel or another process can still submit concurrently; Poetic-side admission, not this panel, is the authority for that.';
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Project the lifecycle controls for one selected task. Pure: the same input
|
|
629
|
+
* always yields the same view. No control is hidden on an advisory hint, and no
|
|
630
|
+
* resulting status, queue position, or terminal state is derived.
|
|
631
|
+
*/
|
|
632
|
+
export function buildTaskActionControlsView(
|
|
633
|
+
input: TaskActionControlsInput
|
|
634
|
+
): TaskActionControlsView {
|
|
635
|
+
const taskBusy = input.inFlight !== null;
|
|
636
|
+
const controls = TASK_ACTION_VOCABULARY.map((action) => {
|
|
637
|
+
const reason = isTaskActionReasonKind(action) ? input.reasons[action] : '';
|
|
638
|
+
const blockedReason = taskActionRefusal({
|
|
639
|
+
action,
|
|
640
|
+
taskId: input.taskId,
|
|
641
|
+
reason,
|
|
642
|
+
consent: input.consent,
|
|
643
|
+
inFlight: input.inFlight,
|
|
644
|
+
detailState: input.detailState,
|
|
645
|
+
});
|
|
646
|
+
return {
|
|
647
|
+
action,
|
|
648
|
+
label: TASK_ACTION_LABELS[action],
|
|
649
|
+
buttonLabel: TASK_ACTION_BUTTON_LABELS[action],
|
|
650
|
+
effectLabel: TASK_ACTION_EFFECTS[action],
|
|
651
|
+
domain: 'task-lifecycle' as const,
|
|
652
|
+
requiresReason: isTaskActionReasonKind(action),
|
|
653
|
+
requiresTerminalConfirmation: isTaskActionTerminalKind(action),
|
|
654
|
+
advisory: taskActionAdvisory(action, input.status),
|
|
655
|
+
busy: taskBusy && input.inFlight?.action === action,
|
|
656
|
+
taskBusy,
|
|
657
|
+
submittable: blockedReason === null,
|
|
658
|
+
blockedReason,
|
|
659
|
+
};
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
if (input.detailState !== 'available') {
|
|
663
|
+
return {
|
|
664
|
+
state: 'unavailable',
|
|
665
|
+
taskId: input.taskId,
|
|
666
|
+
unavailableReason:
|
|
667
|
+
controls[0]?.blockedReason ??
|
|
668
|
+
'BB holds no canonical task detail for this task, so no lifecycle action is offered.',
|
|
669
|
+
controls: [],
|
|
670
|
+
recommendedAction: null,
|
|
671
|
+
advisoryNotice: TASK_ACTION_ADVISORY_NOTICE,
|
|
672
|
+
concurrencyNotice: TASK_ACTION_CONCURRENCY_NOTICE,
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return {
|
|
677
|
+
state: 'available',
|
|
678
|
+
taskId: input.taskId,
|
|
679
|
+
unavailableReason: null,
|
|
680
|
+
controls,
|
|
681
|
+
recommendedAction: input.status === null ? null : TASK_ACTION_RECOMMENDED[input.status],
|
|
682
|
+
advisoryNotice: TASK_ACTION_ADVISORY_NOTICE,
|
|
683
|
+
concurrencyNotice: TASK_ACTION_CONCURRENCY_NOTICE,
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/** One consent line in the confirmation, with its current acknowledgement. */
|
|
688
|
+
export interface TaskActionConsentLineView {
|
|
689
|
+
key: keyof TaskActionConsentState;
|
|
690
|
+
label: string;
|
|
691
|
+
accepted: boolean;
|
|
692
|
+
required: boolean;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
const TASK_ACTION_CONSENT_LABELS: Readonly<Record<keyof TaskActionConsentState, string>> = {
|
|
696
|
+
hostExecution: 'Poetic runs as my host user in the repository shown above.',
|
|
697
|
+
managedPlanningMutation: 'This mutates managed planning state that Poetic owns.',
|
|
698
|
+
automaticCommitAndPush:
|
|
699
|
+
"Poetic's built-in managed sync commits and pushes these planning changes.",
|
|
700
|
+
selectedRepositoryAndBranch: 'I mean this repository path and this branch.',
|
|
701
|
+
archivalOrTerminalConfirmation:
|
|
702
|
+
'I confirm the archival or terminal effect of this action on the task.',
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
/** Placeholder shown in the disclosed command line while no reason is entered. */
|
|
706
|
+
export const TASK_ACTION_REASON_PLACEHOLDER = '<your reason>';
|
|
707
|
+
|
|
708
|
+
export interface TaskActionConfirmationInput extends TaskActionGateInput {
|
|
709
|
+
/** Selected repository path, rendered verbatim. */
|
|
710
|
+
repositoryPath: string;
|
|
711
|
+
/** Branch Poetic reported, or null for a detached HEAD. */
|
|
712
|
+
branch: string | null;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* The mutation confirmation for one action: what will run, where, on which
|
|
717
|
+
* branch, with which reason, and which consent is still outstanding. Repository
|
|
718
|
+
* path and branch are always disclosed, and a detached HEAD is named rather than
|
|
719
|
+
* blanked.
|
|
720
|
+
*/
|
|
721
|
+
export interface TaskActionConfirmationView {
|
|
722
|
+
action: TaskActionKind;
|
|
723
|
+
taskId: string;
|
|
724
|
+
headline: string;
|
|
725
|
+
/** Label of the control that actually submits, named for this action. */
|
|
726
|
+
submitLabel: string;
|
|
727
|
+
effectLabel: string;
|
|
728
|
+
repositoryPath: string;
|
|
729
|
+
branchLabel: string;
|
|
730
|
+
targetLine: string;
|
|
731
|
+
/** The exact fixed Poetic command that will run. */
|
|
732
|
+
commandLine: string;
|
|
733
|
+
/** The reason that will be sent, or null when the action takes none. */
|
|
734
|
+
reasonLine: string | null;
|
|
735
|
+
disclosureSummary: string;
|
|
736
|
+
consentLines: readonly TaskActionConsentLineView[];
|
|
737
|
+
submittable: boolean;
|
|
738
|
+
blockedReason: string | null;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
export function buildTaskActionConfirmationView(
|
|
742
|
+
input: TaskActionConfirmationInput
|
|
743
|
+
): TaskActionConfirmationView {
|
|
744
|
+
const reason = input.reason.trim();
|
|
745
|
+
const argv = isTaskActionReasonKind(input.action)
|
|
746
|
+
? taskActionArgv({
|
|
747
|
+
action: input.action,
|
|
748
|
+
taskId: input.taskId,
|
|
749
|
+
reason: reason.length === 0 ? TASK_ACTION_REASON_PLACEHOLDER : reason,
|
|
750
|
+
})
|
|
751
|
+
: taskActionArgv({ action: input.action, taskId: input.taskId });
|
|
752
|
+
const branchLabel = input.branch ?? 'detached HEAD (no named branch)';
|
|
753
|
+
const terminal = isTaskActionTerminalKind(input.action);
|
|
754
|
+
const consentKeys: Array<keyof TaskActionConsentState> = [
|
|
755
|
+
'hostExecution',
|
|
756
|
+
'managedPlanningMutation',
|
|
757
|
+
'automaticCommitAndPush',
|
|
758
|
+
'selectedRepositoryAndBranch',
|
|
759
|
+
...(terminal ? (['archivalOrTerminalConfirmation'] as const) : []),
|
|
760
|
+
];
|
|
761
|
+
const blockedReason = taskActionRefusal(input);
|
|
762
|
+
return {
|
|
763
|
+
action: input.action,
|
|
764
|
+
taskId: input.taskId,
|
|
765
|
+
headline: `Confirm ${TASK_ACTION_LABELS[input.action].toLowerCase()}`,
|
|
766
|
+
submitLabel: `Submit ${TASK_ACTION_LABELS[input.action].toLowerCase()}`,
|
|
767
|
+
effectLabel: TASK_ACTION_EFFECTS[input.action],
|
|
768
|
+
repositoryPath: input.repositoryPath,
|
|
769
|
+
branchLabel,
|
|
770
|
+
targetLine: `Task ${input.taskId} in ${input.repositoryPath} on ${branchLabel}`,
|
|
771
|
+
commandLine: `poetic ${argv.join(' ')}`,
|
|
772
|
+
reasonLine: isTaskActionReasonKind(input.action)
|
|
773
|
+
? reason.length === 0
|
|
774
|
+
? 'No reason entered yet; Poetic requires one for this action.'
|
|
775
|
+
: reason
|
|
776
|
+
: null,
|
|
777
|
+
disclosureSummary: TASK_PLANNING_DISCLOSURE.summary,
|
|
778
|
+
consentLines: consentKeys.map((key) => ({
|
|
779
|
+
key,
|
|
780
|
+
label: TASK_ACTION_CONSENT_LABELS[key],
|
|
781
|
+
accepted: input.consent[key],
|
|
782
|
+
required: true,
|
|
783
|
+
})),
|
|
784
|
+
submittable: blockedReason === null,
|
|
785
|
+
blockedReason,
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
/** What the applied action reported, as the panel received it. */
|
|
790
|
+
export interface TaskActionOutcomeInput {
|
|
791
|
+
action: TaskActionKind;
|
|
792
|
+
taskId: string;
|
|
793
|
+
command: TaskActionCommandEvidence;
|
|
794
|
+
syncWarnings: readonly string[];
|
|
795
|
+
taskDetail: GetTaskDetailOutput;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Plain rendering of one applied action. CLI diagnostics stay verbatim, a
|
|
800
|
+
* failure and a timeout are reported as ambiguous rather than as a known state,
|
|
801
|
+
* sync evidence stays advisory, and the canonical reread is named as the only
|
|
802
|
+
* authority. No status, queue position, or terminal state is derived here.
|
|
803
|
+
*/
|
|
804
|
+
export interface TaskActionOutcomeView {
|
|
805
|
+
action: TaskActionKind;
|
|
806
|
+
taskId: string;
|
|
807
|
+
state: 'succeeded' | 'failed';
|
|
808
|
+
headline: string;
|
|
809
|
+
commandLine: string;
|
|
810
|
+
attemptsNotice: string;
|
|
811
|
+
/** Poetic's own diagnostics, verbatim; null when it reported none. */
|
|
812
|
+
diagnostics: string | null;
|
|
813
|
+
/** Set whenever the outcome cannot be read as a known applied state. */
|
|
814
|
+
ambiguityNotice: string | null;
|
|
815
|
+
syncWarnings: readonly string[];
|
|
816
|
+
syncNotice: string;
|
|
817
|
+
taskState: 'available' | 'missing' | 'unavailable';
|
|
818
|
+
taskStateNotice: string;
|
|
819
|
+
refreshedNotice: string;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
export const TASK_ACTION_REFRESHED_NOTICE =
|
|
823
|
+
"Queues and task detail below are Poetic's fresh reread. BB moved nothing in the queue and predicted no resulting status.";
|
|
824
|
+
|
|
825
|
+
export function buildTaskActionOutcomeView(input: TaskActionOutcomeInput): TaskActionOutcomeView {
|
|
826
|
+
const diagnostics = input.command.diagnostics;
|
|
827
|
+
const timedOut = diagnostics !== null && /timed out|timeout/i.test(diagnostics);
|
|
828
|
+
const failed = input.command.state === 'failed';
|
|
829
|
+
const task = input.taskDetail.task;
|
|
830
|
+
const taskStateNotice =
|
|
831
|
+
task.state === 'available'
|
|
832
|
+
? 'Poetic re-read this task after the action; the canonical detail shown is that reread.'
|
|
833
|
+
: task.state === 'missing'
|
|
834
|
+
? `Poetic reports no managed task ${input.taskId} after this action. BB did not infer a completed, cancelled, or archived state.`
|
|
835
|
+
: `Poetic could not describe task ${input.taskId} after this action: ${task.reason}`;
|
|
836
|
+
return {
|
|
837
|
+
action: input.action,
|
|
838
|
+
taskId: input.taskId,
|
|
839
|
+
state: input.command.state,
|
|
840
|
+
headline: failed
|
|
841
|
+
? `Poetic reported the ${input.action} command failed for ${input.taskId}.`
|
|
842
|
+
: `Poetic reported the ${input.action} command completed for ${input.taskId}.`,
|
|
843
|
+
commandLine: `poetic ${input.command.argv.join(' ')}`,
|
|
844
|
+
attemptsNotice: 'BB ran this once and never retries it automatically.',
|
|
845
|
+
diagnostics,
|
|
846
|
+
ambiguityNotice: timedOut
|
|
847
|
+
? "Poetic's diagnostics mention a timeout, so whether the command finished is unknown. Nothing was retried; the canonical reread is the only authority."
|
|
848
|
+
: failed
|
|
849
|
+
? 'A failed command may still have applied part of its change. Nothing was retried; the canonical reread is the only authority.'
|
|
850
|
+
: null,
|
|
851
|
+
syncWarnings: [...input.syncWarnings],
|
|
852
|
+
syncNotice:
|
|
853
|
+
input.syncWarnings.length === 0
|
|
854
|
+
? 'Poetic reported no planning sync warnings on this reread. A zero exit still never confirms the managed sync reached the remote.'
|
|
855
|
+
: "A zero exit never confirms the managed sync reached the remote; the warnings above are Poetic's own fresh evidence.",
|
|
856
|
+
taskState: task.state,
|
|
857
|
+
taskStateNotice,
|
|
858
|
+
refreshedNotice: TASK_ACTION_REFRESHED_NOTICE,
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Consent every task lifecycle action must acknowledge: host-equivalent
|
|
864
|
+
* execution, managed planning mutation, automatic commit/push sync, and the
|
|
865
|
+
* selected repository/branch. No false/partial consent is accepted.
|
|
866
|
+
*/
|
|
867
|
+
export const taskActionConsentSchema = z
|
|
868
|
+
.object({
|
|
869
|
+
hostExecution: z.literal(true),
|
|
870
|
+
managedPlanningMutation: z.literal(true),
|
|
871
|
+
automaticCommitAndPush: z.literal(true),
|
|
872
|
+
selectedRepositoryAndBranch: z.literal(true),
|
|
873
|
+
})
|
|
874
|
+
.strict();
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Complete, cancel, and reopen additionally confirm archival or terminal
|
|
878
|
+
* restore effects (archive finished/cancelled tasks; reopen restores them).
|
|
879
|
+
*/
|
|
880
|
+
export const taskActionTerminalConsentSchema = taskActionConsentSchema
|
|
881
|
+
.extend({
|
|
882
|
+
archivalOrTerminalConfirmation: z.literal(true),
|
|
883
|
+
})
|
|
884
|
+
.strict();
|
|
885
|
+
|
|
886
|
+
/** Non-empty free-text reason required for block, cancel, and reopen only. */
|
|
887
|
+
const taskActionReasonSchema = z.string().trim().min(1).max(4_000);
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* A managed task id addresses one file under Poetic's managed task directory, so
|
|
891
|
+
* it must be a single safe path component: no separators, no traversal, and no
|
|
892
|
+
* leading dot or dash that could read as a hidden file or a flag.
|
|
893
|
+
*/
|
|
894
|
+
const taskActionTaskIdSchema = z
|
|
895
|
+
.string()
|
|
896
|
+
.min(1)
|
|
897
|
+
.max(200)
|
|
898
|
+
.regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, 'A task id must be a single safe path component.');
|
|
899
|
+
|
|
900
|
+
const taskActionTargetFields = {
|
|
901
|
+
projectId: z.string().min(1),
|
|
902
|
+
sourceId: z.string().min(1),
|
|
903
|
+
taskId: taskActionTaskIdSchema,
|
|
904
|
+
} as const;
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Closed discriminated applyTaskAction request. Only the frozen vocabulary is
|
|
908
|
+
* accepted. Reasons are schema-required for block/cancel/reopen. Complete has
|
|
909
|
+
* no force field. No action can request --no-sync, argv, cwd, env, executable,
|
|
910
|
+
* generic update, or a free-form lifecycle matrix.
|
|
911
|
+
*/
|
|
912
|
+
export const applyTaskActionInputSchema = z.discriminatedUnion('action', [
|
|
913
|
+
z
|
|
914
|
+
.object({
|
|
915
|
+
...taskActionTargetFields,
|
|
916
|
+
action: z.literal('start'),
|
|
917
|
+
consent: taskActionConsentSchema,
|
|
918
|
+
})
|
|
919
|
+
.strict(),
|
|
920
|
+
z
|
|
921
|
+
.object({
|
|
922
|
+
...taskActionTargetFields,
|
|
923
|
+
action: z.literal('block'),
|
|
924
|
+
reason: taskActionReasonSchema,
|
|
925
|
+
consent: taskActionConsentSchema,
|
|
926
|
+
})
|
|
927
|
+
.strict(),
|
|
928
|
+
z
|
|
929
|
+
.object({
|
|
930
|
+
...taskActionTargetFields,
|
|
931
|
+
action: z.literal('unblock'),
|
|
932
|
+
consent: taskActionConsentSchema,
|
|
933
|
+
})
|
|
934
|
+
.strict(),
|
|
935
|
+
z
|
|
936
|
+
.object({
|
|
937
|
+
...taskActionTargetFields,
|
|
938
|
+
action: z.literal('review'),
|
|
939
|
+
consent: taskActionConsentSchema,
|
|
940
|
+
})
|
|
941
|
+
.strict(),
|
|
942
|
+
z
|
|
943
|
+
.object({
|
|
944
|
+
...taskActionTargetFields,
|
|
945
|
+
action: z.literal('complete'),
|
|
946
|
+
consent: taskActionTerminalConsentSchema,
|
|
947
|
+
})
|
|
948
|
+
.strict(),
|
|
949
|
+
z
|
|
950
|
+
.object({
|
|
951
|
+
...taskActionTargetFields,
|
|
952
|
+
action: z.literal('cancel'),
|
|
953
|
+
reason: taskActionReasonSchema,
|
|
954
|
+
consent: taskActionTerminalConsentSchema,
|
|
955
|
+
})
|
|
956
|
+
.strict(),
|
|
957
|
+
z
|
|
958
|
+
.object({
|
|
959
|
+
...taskActionTargetFields,
|
|
960
|
+
action: z.literal('reopen'),
|
|
961
|
+
reason: taskActionReasonSchema,
|
|
962
|
+
consent: taskActionTerminalConsentSchema,
|
|
963
|
+
})
|
|
964
|
+
.strict(),
|
|
965
|
+
]);
|
|
966
|
+
|
|
967
|
+
export const taskPlanningDisclosureSchema = z
|
|
968
|
+
.object({
|
|
969
|
+
fullTrust: z.literal(true),
|
|
970
|
+
hostEquivalentExecution: z.literal(true),
|
|
971
|
+
providerAuth: z.literal('native'),
|
|
972
|
+
planningSync: z.literal(true),
|
|
973
|
+
gitCommits: z.literal(true),
|
|
974
|
+
gitPush: z.literal(true),
|
|
975
|
+
managedPlanningMutation: z.literal(true),
|
|
976
|
+
pullRequestCreation: z.literal(false),
|
|
977
|
+
fusionLaunch: z.literal(false),
|
|
978
|
+
trackedBacklogExecution: z.literal(false),
|
|
979
|
+
runCancellation: z.literal(false),
|
|
980
|
+
summary: z.string(),
|
|
981
|
+
})
|
|
982
|
+
.strict();
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* Poetic's reported outcome for the current invocation. `argv` discloses the
|
|
986
|
+
* exact fixed argv that ran, `attempts` is a literal 1 (no automatic retry), and
|
|
987
|
+
* `remoteSyncConfirmedByExitCode` is a literal false so a zero exit can never be
|
|
988
|
+
* rendered as confirmed remote synchronization.
|
|
989
|
+
*/
|
|
990
|
+
const taskActionCommandEvidenceSchema = z
|
|
991
|
+
.object({
|
|
992
|
+
state: z.enum(['succeeded', 'failed']),
|
|
993
|
+
attempts: z.literal(1),
|
|
994
|
+
argv: z.array(z.string().min(1)),
|
|
995
|
+
diagnostics: z.string().nullable(),
|
|
996
|
+
remoteSyncConfirmedByExitCode: z.literal(false),
|
|
997
|
+
})
|
|
998
|
+
.strict();
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* Authoritative post-action output: repository identity, the task-planning
|
|
1002
|
+
* disclosure, the accepted action, the current invocation's evidence, current
|
|
1003
|
+
* sync warnings, a full Planning Workspace reread, and a fresh reread of the
|
|
1004
|
+
* selected task. Poetic remains mutation authority; BB does not invent status
|
|
1005
|
+
* transitions, and the rereads outrank the exit code.
|
|
1006
|
+
*/
|
|
1007
|
+
export const applyTaskActionOutputSchema = z
|
|
1008
|
+
.object({
|
|
1009
|
+
repository: repositorySchema,
|
|
1010
|
+
disclosure: taskPlanningDisclosureSchema,
|
|
1011
|
+
action: z.enum(TASK_ACTION_VOCABULARY),
|
|
1012
|
+
taskId: taskActionTaskIdSchema,
|
|
1013
|
+
command: taskActionCommandEvidenceSchema,
|
|
1014
|
+
syncWarnings: z.array(z.string()),
|
|
1015
|
+
workspace: planningWorkspaceProjectionSchema,
|
|
1016
|
+
taskDetail: getTaskDetailOutputSchema,
|
|
1017
|
+
})
|
|
1018
|
+
.strict();
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Frozen public RPC method for task lifecycle actions. The vocabulary and
|
|
1022
|
+
* schemas are fixed here; BPTA-06 registers this method on the live contract.
|
|
1023
|
+
*/
|
|
1024
|
+
export const applyTaskActionMethod = {
|
|
1025
|
+
input: applyTaskActionInputSchema,
|
|
1026
|
+
output: applyTaskActionOutputSchema,
|
|
1027
|
+
} as const;
|
|
1028
|
+
|
|
1029
|
+
/** Live registered RPC methods on the BB plugin, in registration order. */
|
|
1030
|
+
export const LIVE_POETIC_RPC_METHODS = [
|
|
1031
|
+
'listProjects',
|
|
1032
|
+
'capabilities',
|
|
1033
|
+
'listBacklog',
|
|
1034
|
+
'planningWorkspace',
|
|
1035
|
+
'getBacklog',
|
|
1036
|
+
'getTask',
|
|
1037
|
+
'launchFusion',
|
|
1038
|
+
'launchCompetition',
|
|
1039
|
+
'launchTrackedBacklog',
|
|
1040
|
+
'observeCompetition',
|
|
1041
|
+
'pollRuns',
|
|
1042
|
+
'cancelRun',
|
|
1043
|
+
'applyTaskAction',
|
|
1044
|
+
'readResult',
|
|
1045
|
+
'previewPatch',
|
|
1046
|
+
'competitionDefaults',
|
|
1047
|
+
'setupStatus',
|
|
1048
|
+
// BPAU-07A registration delta. The three mutation names are frozen by
|
|
1049
|
+
// BPAU-00; the two sprint reads are added because neither was registered
|
|
1050
|
+
// before this sprint. Nothing is removed, renamed, or combined.
|
|
1051
|
+
'applyBacklogAuthoring',
|
|
1052
|
+
'applyTaskAuthoring',
|
|
1053
|
+
'applySprintComposition',
|
|
1054
|
+
'listSprints',
|
|
1055
|
+
'getSprint',
|
|
1056
|
+
'applyBacklogFinalize',
|
|
1057
|
+
'applySprintClose',
|
|
1058
|
+
] as const;
|
|
1059
|
+
|
|
1060
|
+
export type CompatibilityState =
|
|
1061
|
+
| 'exact'
|
|
1062
|
+
| 'compatible_minor_difference'
|
|
1063
|
+
| 'incompatible'
|
|
1064
|
+
| 'unavailable';
|
|
1065
|
+
|
|
1066
|
+
export interface RepositoryView {
|
|
1067
|
+
projectId: string;
|
|
1068
|
+
projectName: string;
|
|
1069
|
+
sourceId: string;
|
|
1070
|
+
path: string;
|
|
1071
|
+
branch: string | null;
|
|
1072
|
+
branchState: 'ready' | 'protected' | 'detached';
|
|
1073
|
+
poeticVersion: string | null;
|
|
1074
|
+
compatibility: CompatibilityState;
|
|
1075
|
+
state: 'ready' | 'warning' | 'blocked';
|
|
1076
|
+
messages: string[];
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
export interface BacklogItem {
|
|
1080
|
+
id: string;
|
|
1081
|
+
title: string;
|
|
1082
|
+
status: string;
|
|
1083
|
+
priority: string | null;
|
|
1084
|
+
complexity: number | null;
|
|
1085
|
+
domain: string | null;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Poetic's own status vocabulary for a tracked backlog execution, as published
|
|
1090
|
+
* by the kind-tagged operational readback. Never re-derived here.
|
|
1091
|
+
*/
|
|
1092
|
+
export type TrackedExecutionStatus =
|
|
1093
|
+
| 'queued'
|
|
1094
|
+
| 'running'
|
|
1095
|
+
| 'blocked'
|
|
1096
|
+
| 'succeeded'
|
|
1097
|
+
| 'failed'
|
|
1098
|
+
| 'cancelled'
|
|
1099
|
+
| 'unknown';
|
|
1100
|
+
|
|
1101
|
+
export type TrackedExecutionProcessState = 'alive' | 'gone' | 'unobserved';
|
|
1102
|
+
|
|
1103
|
+
/**
|
|
1104
|
+
* Authoritative provenance/process evidence for a tracked execution of one
|
|
1105
|
+
* backlog item, read from Poetic on every request. It is used only to refuse an
|
|
1106
|
+
* unsafe duplicate launch; it is never stored, cached, or rendered as run state.
|
|
1107
|
+
*/
|
|
1108
|
+
export interface TrackedExecutionEvidence {
|
|
1109
|
+
status: TrackedExecutionStatus;
|
|
1110
|
+
/** The provenance record's own status label, never re-interpreted. */
|
|
1111
|
+
provenanceStatus: string;
|
|
1112
|
+
processState: TrackedExecutionProcessState;
|
|
1113
|
+
executingPid: number | null;
|
|
1114
|
+
terminal: boolean;
|
|
1115
|
+
stale: boolean;
|
|
1116
|
+
label: string;
|
|
1117
|
+
compatibility: CompatibilityState;
|
|
1118
|
+
evidence: Array<{ kind: EvidenceKind; value: string }>;
|
|
1119
|
+
workflowId: string | null;
|
|
1120
|
+
taskIds: string[];
|
|
1121
|
+
branch: string | null;
|
|
1122
|
+
pullRequestNumber: number | null;
|
|
1123
|
+
lastCompletedStep: string | null;
|
|
1124
|
+
failedAtStep: string | null;
|
|
1125
|
+
errorMessage: string | null;
|
|
1126
|
+
blockers: string[];
|
|
1127
|
+
finalizationState: string;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
export interface BacklogDetail extends BacklogItem {
|
|
1131
|
+
body: string;
|
|
1132
|
+
createdAt: string | null;
|
|
1133
|
+
filePath: string;
|
|
1134
|
+
/**
|
|
1135
|
+
* Null when Poetic reports no local provenance record. `.poetic/provenance`
|
|
1136
|
+
* is local-only, so absence is never proof that nothing is executing.
|
|
1137
|
+
*/
|
|
1138
|
+
execution: TrackedExecutionEvidence | null;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
export type EvidenceKind =
|
|
1142
|
+
| 'artifact'
|
|
1143
|
+
| 'branch'
|
|
1144
|
+
| 'changed_file'
|
|
1145
|
+
| 'commit'
|
|
1146
|
+
| 'delivery'
|
|
1147
|
+
| 'judge'
|
|
1148
|
+
| 'patch'
|
|
1149
|
+
| 'pull_request'
|
|
1150
|
+
| 'synthesis'
|
|
1151
|
+
| 'verification'
|
|
1152
|
+
| 'workflow'
|
|
1153
|
+
| 'blocker'
|
|
1154
|
+
| 'finalization'
|
|
1155
|
+
| 'worktree';
|
|
1156
|
+
|
|
1157
|
+
export interface RunEvidence {
|
|
1158
|
+
kind: EvidenceKind;
|
|
1159
|
+
value: string;
|
|
1160
|
+
variant?: string;
|
|
1161
|
+
repository: string;
|
|
1162
|
+
runId: string;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* Whether this plugin still holds the local OS process handle it launched.
|
|
1167
|
+
*
|
|
1168
|
+
* `owned` — the launched child is still supervised by this adapter.
|
|
1169
|
+
* `lost` — a handle existed and is gone (process exit, plugin reload, or
|
|
1170
|
+
* BB server restart). Nothing is replayed; state is re-read.
|
|
1171
|
+
* `never-owned` — the run was discovered from Poetic, not launched here.
|
|
1172
|
+
*/
|
|
1173
|
+
export type ProcessHandleState = 'owned' | 'lost' | 'never-owned';
|
|
1174
|
+
|
|
1175
|
+
/**
|
|
1176
|
+
* What proves a run is controllable right now. Cancellation requires one of the
|
|
1177
|
+
* two positive values; `none` disables the control rather than guessing.
|
|
1178
|
+
*/
|
|
1179
|
+
export type ControlEvidence = 'local-process' | 'poetic-live-process' | 'none';
|
|
1180
|
+
|
|
1181
|
+
/**
|
|
1182
|
+
* Which canonical Poetic result readback describes this run. It names the
|
|
1183
|
+
* existing kind-tagged readback BB must request for the run and never a new
|
|
1184
|
+
* result authority, so a card can be navigated to its own result view without
|
|
1185
|
+
* re-deriving the kind from the standalone command string.
|
|
1186
|
+
*/
|
|
1187
|
+
export type RunResultKind = 'competition' | 'fusion' | 'backlog-execute';
|
|
1188
|
+
|
|
1189
|
+
export interface RunCard {
|
|
1190
|
+
operationId: string;
|
|
1191
|
+
runId: string | null;
|
|
1192
|
+
/** The canonical readback kind for this run's result view. */
|
|
1193
|
+
resultKind: RunResultKind;
|
|
1194
|
+
backlogItemId: string;
|
|
1195
|
+
title: string;
|
|
1196
|
+
repository: string;
|
|
1197
|
+
branch: string;
|
|
1198
|
+
status: 'starting' | 'running' | 'blocked' | 'succeeded' | 'failed' | 'cancelled' | 'unknown';
|
|
1199
|
+
phase: string;
|
|
1200
|
+
progressLine: string;
|
|
1201
|
+
/** Whether the visible line is model narration or the deterministic fallback. */
|
|
1202
|
+
progressSource: 'deterministic' | 'narrated';
|
|
1203
|
+
progressNarratedAt: string | null;
|
|
1204
|
+
/** True when an older narration was replaced by newer authoritative facts. */
|
|
1205
|
+
progressStale: boolean;
|
|
1206
|
+
/** Advisory narrator latency only; never a control or completion signal. */
|
|
1207
|
+
progressLatencyMs: number | null;
|
|
1208
|
+
progressAdvisory: string | null;
|
|
1209
|
+
progressSignature: string | null;
|
|
1210
|
+
terminal: boolean;
|
|
1211
|
+
/** True only when Poetic still exposes an addressable, non-terminal run. */
|
|
1212
|
+
cancelEligible: boolean;
|
|
1213
|
+
/** Whether this plugin still holds the OS process handle it launched. */
|
|
1214
|
+
processHandle: ProcessHandleState;
|
|
1215
|
+
/**
|
|
1216
|
+
* The evidence that authorizes cancellation. `none` means the control is
|
|
1217
|
+
* disabled: no confirmed live process exists to interrupt.
|
|
1218
|
+
*/
|
|
1219
|
+
controlEvidence: ControlEvidence;
|
|
1220
|
+
/**
|
|
1221
|
+
* True once cancellation has been requested through Poetic's own cancellation
|
|
1222
|
+
* surfaces. It does not assert a terminal state; the terminal state still
|
|
1223
|
+
* comes from Poetic or from the observed exit of the launched run.
|
|
1224
|
+
*/
|
|
1225
|
+
cancelRequested: boolean;
|
|
1226
|
+
compatibility: CompatibilityState;
|
|
1227
|
+
evidence: RunEvidence[];
|
|
1228
|
+
standaloneCommand: string | null;
|
|
1229
|
+
error: string | null;
|
|
1230
|
+
/**
|
|
1231
|
+
* Judge operations cockpit for this run, rendered from Poetic's optional
|
|
1232
|
+
* judge-operations projection. Null when Poetic published no such projection —
|
|
1233
|
+
* including for every record written before the projection existed — so absence
|
|
1234
|
+
* renders as unavailable evidence rather than as a judge result.
|
|
1235
|
+
*/
|
|
1236
|
+
judgeOperations: JudgeOperationsView | null;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Deterministic fingerprint of every field that affects rendered or actionable
|
|
1241
|
+
* run-card state. Omitting any of these lets mergeRunCards discard authoritative
|
|
1242
|
+
* updates (phase, evidence, compatibility, standalone command, identity labels)
|
|
1243
|
+
* while still returning the previous array for true no-ops.
|
|
1244
|
+
*/
|
|
1245
|
+
function runSignature(run: RunCard): string {
|
|
1246
|
+
return JSON.stringify([
|
|
1247
|
+
run.operationId,
|
|
1248
|
+
run.runId,
|
|
1249
|
+
run.resultKind,
|
|
1250
|
+
run.backlogItemId,
|
|
1251
|
+
run.title,
|
|
1252
|
+
run.repository,
|
|
1253
|
+
run.branch,
|
|
1254
|
+
run.status,
|
|
1255
|
+
run.phase,
|
|
1256
|
+
run.progressLine,
|
|
1257
|
+
run.progressSource,
|
|
1258
|
+
run.progressNarratedAt,
|
|
1259
|
+
run.progressStale,
|
|
1260
|
+
run.progressLatencyMs,
|
|
1261
|
+
run.progressAdvisory,
|
|
1262
|
+
run.progressSignature,
|
|
1263
|
+
run.terminal,
|
|
1264
|
+
run.cancelEligible,
|
|
1265
|
+
run.processHandle,
|
|
1266
|
+
run.controlEvidence,
|
|
1267
|
+
run.cancelRequested,
|
|
1268
|
+
run.compatibility,
|
|
1269
|
+
run.evidence,
|
|
1270
|
+
run.standaloneCommand,
|
|
1271
|
+
run.error,
|
|
1272
|
+
run.judgeOperations,
|
|
1273
|
+
]);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
/**
|
|
1277
|
+
* Merge freshly reported run cards into the panel's list. A Poetic run id is the
|
|
1278
|
+
* stable identity across adapter restarts; the local operation id is used only
|
|
1279
|
+
* until Poetic emits that id. Returns the previous array unchanged when nothing
|
|
1280
|
+
* observable moved, so polling does not churn the panel.
|
|
1281
|
+
*/
|
|
1282
|
+
export function mergeRunCards(previous: RunCard[], incoming: RunCard[]): RunCard[] {
|
|
1283
|
+
const sameIdentity = (left: RunCard, right: RunCard) =>
|
|
1284
|
+
left.operationId === right.operationId ||
|
|
1285
|
+
(left.runId !== null && right.runId !== null && left.runId === right.runId);
|
|
1286
|
+
const next = [...previous];
|
|
1287
|
+
for (const run of incoming) {
|
|
1288
|
+
const matchingIndex = next.findIndex((existing) => sameIdentity(existing, run));
|
|
1289
|
+
if (matchingIndex === -1) {
|
|
1290
|
+
next.push(run);
|
|
1291
|
+
continue;
|
|
1292
|
+
}
|
|
1293
|
+
next[matchingIndex] = run;
|
|
1294
|
+
for (let index = next.length - 1; index > matchingIndex; index -= 1) {
|
|
1295
|
+
if (sameIdentity(next[index] as RunCard, run)) next.splice(index, 1);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
const unchanged =
|
|
1299
|
+
next.length === previous.length &&
|
|
1300
|
+
next.every((run, index) => runSignature(run) === runSignature(previous[index] as RunCard));
|
|
1301
|
+
return unchanged ? previous : next;
|
|
1302
|
+
}
|