@iowarp/clio-coder 0.4.6 → 0.4.8
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/.claude-plugin/marketplace.json +283 -0
- package/CHANGELOG.md +79 -0
- package/CONTRIBUTING.md +178 -96
- package/NOTICE +8 -0
- package/README.md +100 -47
- package/dist/acp-JWPQZM2D.js +130 -0
- package/dist/agents-4GCDIRVX.js +149 -0
- package/dist/assets/codewiki.json +1 -1
- package/dist/assets/tui-notices/get-east-asian-width-LICENSE +9 -0
- package/dist/assets/tui-notices/marked-LICENSE +44 -0
- package/dist/assets/tui-notices/pi-tui-LICENSE +21 -0
- package/dist/assets/web-notices/@hono__node-server-LICENSE +21 -0
- package/dist/assets/web-notices/hono-LICENSE +21 -0
- package/dist/auth-SYAKTDQE.js +551 -0
- package/dist/background-OW67WMYR.js +37 -0
- package/dist/builtins-TKS63VNV.js +22 -0
- package/dist/chunk-2JSCCEKO.js +85 -0
- package/dist/chunk-2SXGG2IV.js +391 -0
- package/dist/chunk-2U2U5POA.js +59 -0
- package/dist/chunk-2ZWLMA3T.js +658 -0
- package/dist/chunk-36XSBPXL.js +579 -0
- package/dist/chunk-3IQOZRQ6.js +396 -0
- package/dist/chunk-3XE4NRLF.js +324 -0
- package/dist/chunk-44U2OUSM.js +243 -0
- package/dist/chunk-4P6M2TTE.js +119 -0
- package/dist/chunk-526ABLHD.js +1219 -0
- package/dist/chunk-5C2OQHLR.js +674 -0
- package/dist/chunk-5D2FNBMG.js +185 -0
- package/dist/chunk-5EQO5NWP.js +243 -0
- package/dist/chunk-5HULHKT2.js +32 -0
- package/dist/chunk-5UG6EZI3.js +66 -0
- package/dist/chunk-5W4FRA5Q.js +22283 -0
- package/dist/chunk-6R5MBXBJ.js +386 -0
- package/dist/chunk-6TKOFFGE.js +1058 -0
- package/dist/chunk-6UJ7RDI7.js +1143 -0
- package/dist/chunk-6X7VOCDY.js +44 -0
- package/dist/chunk-7QQRPB2E.js +915 -0
- package/dist/chunk-ARRUMZ7X.js +1377 -0
- package/dist/chunk-ATB3Q7YO.js +663 -0
- package/dist/chunk-AUHVBIDW.js +19 -0
- package/dist/chunk-BE4I3UJ2.js +668 -0
- package/dist/chunk-BFPHMSK7.js +169 -0
- package/dist/chunk-BHJMMCXS.js +466 -0
- package/dist/chunk-BIY22UUK.js +1322 -0
- package/dist/chunk-D55WO5J7.js +110 -0
- package/dist/chunk-DVJL77SO.js +162 -0
- package/dist/chunk-E2NSPYLC.js +814 -0
- package/dist/chunk-EFXMQYI6.js +4484 -0
- package/dist/chunk-EPYATQMG.js +2718 -0
- package/dist/chunk-EXKUF426.js +1801 -0
- package/dist/chunk-F7Y6QTPL.js +689 -0
- package/dist/chunk-FB3KTE2J.js +1710 -0
- package/dist/chunk-FNVPQQYT.js +117 -0
- package/dist/chunk-GEVQNST4.js +101 -0
- package/dist/chunk-GEYX2NZ5.js +697 -0
- package/dist/chunk-GJBJHJNY.js +2120 -0
- package/dist/chunk-GM4TY6VN.js +1233 -0
- package/dist/chunk-GVU4CXPJ.js +5191 -0
- package/dist/chunk-H5DPSUBB.js +637 -0
- package/dist/chunk-H77XBUBM.js +688 -0
- package/dist/chunk-HMGAKB7E.js +380 -0
- package/dist/chunk-HP7KJ5O2.js +797 -0
- package/dist/chunk-HVCAY2FH.js +67 -0
- package/dist/chunk-ICYIUNO4.js +35 -0
- package/dist/chunk-IILXVWJY.js +223 -0
- package/dist/chunk-JCVIL6TY.js +595 -0
- package/dist/chunk-JIMWEYWO.js +63 -0
- package/dist/chunk-JLBVCROW.js +562 -0
- package/dist/chunk-JOBN2YQQ.js +176 -0
- package/dist/chunk-JOL2QRLE.js +152 -0
- package/dist/chunk-JRA6OBHY.js +974 -0
- package/dist/chunk-JV25I7ID.js +1865 -0
- package/dist/chunk-JYKUMHCQ.js +705 -0
- package/dist/chunk-K3W6BF5C.js +283 -0
- package/dist/chunk-K45LHSCI.js +194 -0
- package/dist/chunk-K53E2PTW.js +1289 -0
- package/dist/chunk-K5UJD6MM.js +39 -0
- package/dist/chunk-KGP3UQGJ.js +200 -0
- package/dist/chunk-KKRXONXG.js +43 -0
- package/dist/chunk-KWJXCL2X.js +103 -0
- package/dist/chunk-L75H5B3B.js +446 -0
- package/dist/chunk-LLCGGVSW.js +108 -0
- package/dist/chunk-LZCCBLRC.js +57 -0
- package/dist/chunk-LZDLYSUN.js +197 -0
- package/dist/chunk-MATCRH3M.js +667 -0
- package/dist/chunk-MEHBW2SP.js +132 -0
- package/dist/chunk-MUXNDNMZ.js +659 -0
- package/dist/chunk-MWMW53WW.js +7346 -0
- package/dist/chunk-MZDPF35R.js +45 -0
- package/dist/chunk-MZKYVIWW.js +188 -0
- package/dist/chunk-O2QJDRWP.js +362 -0
- package/dist/chunk-O3HSB2YL.js +693 -0
- package/dist/chunk-OEMFEL26.js +891 -0
- package/dist/chunk-OH3YYA3B.js +15 -0
- package/dist/chunk-OPC4DQD6.js +634 -0
- package/dist/chunk-ORRNGQDV.js +207 -0
- package/dist/chunk-P4JS3MH5.js +165 -0
- package/dist/chunk-P7GTE4FX.js +308 -0
- package/dist/chunk-PAQVETLA.js +962 -0
- package/dist/chunk-PFZJMXIY.js +146 -0
- package/dist/chunk-PGEFOTJB.js +1974 -0
- package/dist/chunk-PJ5H5B7A.js +3151 -0
- package/dist/chunk-PMUUAABD.js +604 -0
- package/dist/chunk-Q32C6AWI.js +236 -0
- package/dist/chunk-QGIC5SX5.js +139 -0
- package/dist/chunk-QLAGXTTV.js +482 -0
- package/dist/chunk-QLKCCC2J.js +573 -0
- package/dist/chunk-QWUSS2QP.js +3630 -0
- package/dist/chunk-QYSAZMSH.js +47 -0
- package/dist/chunk-R5NRX5N4.js +123 -0
- package/dist/chunk-RAUOKUZV.js +1572 -0
- package/dist/chunk-RBES4TCZ.js +302 -0
- package/dist/chunk-RFCKPS2V.js +26 -0
- package/dist/chunk-RFULVPBX.js +318 -0
- package/dist/chunk-RKFNU5UA.js +404 -0
- package/dist/chunk-RM3XJX7P.js +1148 -0
- package/dist/chunk-RNLAPBJL.js +386 -0
- package/dist/chunk-RPMNIFRY.js +65 -0
- package/dist/chunk-RRZFRIJP.js +42 -0
- package/dist/chunk-RXI7K4J5.js +4493 -0
- package/dist/chunk-SER7RRAE.js +4271 -0
- package/dist/chunk-STC6CWUZ.js +402 -0
- package/dist/chunk-TEHVMHOK.js +97 -0
- package/dist/chunk-TOPICHGR.js +33 -0
- package/dist/chunk-U3TPUXOQ.js +2653 -0
- package/dist/chunk-UB33F3YW.js +709 -0
- package/dist/chunk-UDAK6GR2.js +175 -0
- package/dist/chunk-USBBEKHW.js +177 -0
- package/dist/chunk-V4ZKOKRB.js +13433 -0
- package/dist/chunk-W5RM7YAH.js +78 -0
- package/dist/chunk-W7KNI3F5.js +215 -0
- package/dist/chunk-WFTSK7N3.js +637 -0
- package/dist/chunk-WJWNZXRM.js +395 -0
- package/dist/chunk-WLHX3MM5.js +63 -0
- package/dist/chunk-WS4FOGLY.js +686 -0
- package/dist/chunk-WTZVSMQZ.js +52 -0
- package/dist/chunk-WWRV5RJI.js +165 -0
- package/dist/chunk-X6FLVUM5.js +141 -0
- package/dist/chunk-XC5POIL4.js +68 -0
- package/dist/chunk-XTLJDC2X.js +1013 -0
- package/dist/chunk-XW2UZICE.js +372 -0
- package/dist/chunk-Y3JU5RPK.js +8 -0
- package/dist/chunk-YGIV24MF.js +1018 -0
- package/dist/chunk-YJCCMYYT.js +125 -0
- package/dist/chunk-YKIIWURD.js +36 -0
- package/dist/chunk-YQ3GFEUY.js +341 -0
- package/dist/chunk-YXANQGCX.js +179 -0
- package/dist/chunk-YXFKLMX2.js +222 -0
- package/dist/chunk-ZST3FRCV.js +132 -0
- package/dist/cli/index.js +40 -40
- package/dist/clio-BPBAPZGA.js +26 -0
- package/dist/code-nav-KBQ3RIFK.js +686 -0
- package/dist/components-6DKAXWFN.js +674 -0
- package/dist/config-FWL5JK2H.js +270 -0
- package/dist/config-graph-ACDB26L2.js +156 -0
- package/dist/configure-ZIZ4YV62.js +85 -0
- package/dist/context-EZZPT2ZV.js +1074 -0
- package/dist/context-VIL5MFRH.js +282 -0
- package/dist/context-Z3GOBHDK.js +344 -0
- package/dist/context-clear-ZPB3L7MN.js +188 -0
- package/dist/context-index-W6A4V7OC.js +120 -0
- package/dist/context-map-DKL3QT6D.js +555 -0
- package/dist/context-working-set-2GLBVF7L.js +1559 -0
- package/dist/detail-VSBWYSGZ.js +119 -0
- package/dist/dispatch-runner-EEEHGKX4.js +2442 -0
- package/dist/docs-VMMWFVHL.js +101 -0
- package/dist/doctor-V5L4IQGP.js +812 -0
- package/dist/eval-VJYJ2BV3.js +5050 -0
- package/dist/eval-inventory-CX24K2JT.js +260 -0
- package/dist/evals-J2H5V6DD.js +104 -0
- package/dist/evidence-POWAEBEW.js +229 -0
- package/dist/evidence-XCCCLS36.js +242 -0
- package/dist/evidence-Y35YSXH6.js +388 -0
- package/dist/evolve-GPG72VB6.js +613 -0
- package/dist/extensions-YIZ7W3DA.js +308 -0
- package/dist/fleet-2MDCQ2VK.js +264 -0
- package/dist/fleet-W2AF3TOJ.js +919 -0
- package/dist/fleet-commands-WS56G26H.js +75 -0
- package/dist/fleet-decisions-MYGZ3JW7.js +52 -0
- package/dist/fleet-graph-ELTBXBAV.js +136 -0
- package/dist/fleet-inspect-45IK73L4.js +308 -0
- package/dist/fleet-preflight-T5NCZKHE.js +22 -0
- package/dist/fleet-validate-VG4JBLA4.js +91 -0
- package/dist/fleet-verify-VTSABAYO.js +206 -0
- package/dist/fleet-view-XC7WMKSS.js +123 -0
- package/dist/init-VTJNNTIP.js +329 -0
- package/dist/install-6PIF6F6W.js +19 -0
- package/dist/interop-IU6BNA7C.js +246 -0
- package/dist/inventory-QPQUTUUZ.js +123 -0
- package/dist/library-HUTAS57T.js +492 -0
- package/dist/library-LF7DLU6S.js +306 -0
- package/dist/library-Q3NWL5CM.js +75 -0
- package/dist/library-import-PPW4YUC5.js +183 -0
- package/dist/library-inventory-DIRVFRZU.js +56 -0
- package/dist/library-validation-XHUZ3INE.js +42 -0
- package/dist/memory-Z2LSKNV6.js +516 -0
- package/dist/models-3FTREYPY.js +302 -0
- package/dist/monitor-HF2MQRB3.js +781 -0
- package/dist/orchestrator-UYPA6W4S.js +41502 -0
- package/dist/panes-736XB73K.js +74 -0
- package/dist/panes-C4P3PIWT.js +103 -0
- package/dist/paths-JQ4QYIYB.js +67 -0
- package/dist/preload-XSLRYH3Y.js +120 -0
- package/dist/reset-V7QSPZYE.js +345 -0
- package/dist/resources-OJGDFHYT.js +181 -0
- package/dist/run-T354SMDW.js +892 -0
- package/dist/settings-MWZXO6RV.js +72 -0
- package/dist/share-Y5ZKJPND.js +293 -0
- package/dist/skills-4GLZC4LN.js +100 -0
- package/dist/skills-eval-L5T7GODM.js +1074 -0
- package/dist/skills-inventory-LASKXEZI.js +138 -0
- package/dist/slash-commands-OIMRU36D.js +95 -0
- package/dist/steer-KMAM2Y2C.js +77 -0
- package/dist/support-AWC3XKPX.js +38 -0
- package/dist/system-CD75NYBU.js +116 -0
- package/dist/targets-VSZX2J2S.js +1116 -0
- package/dist/tasks-AN567LYH.js +36 -0
- package/dist/terminal-lease-6KTWNHVY.js +418 -0
- package/dist/tools-AGRK3V5J.js +28 -0
- package/dist/trace-P4MQZD33.js +524 -0
- package/dist/tui-primitives-A6MUW32V.js +18 -0
- package/dist/uninstall-BRUTEPIC.js +432 -0
- package/dist/upgrade-SBCGHQGJ.js +307 -0
- package/dist/usage-BIDVTO6V.js +1061 -0
- package/dist/verifiers-LTGCAMXS.js +630 -0
- package/dist/verify-OZU4LLNP.js +30 -0
- package/dist/web/client/THIRD_PARTY_LICENSES.md +1809 -0
- package/dist/web/client/assets/abnfDiagram-VCTEODGH-C5wfoHm3.js +1 -0
- package/dist/web/client/assets/arc-oH91sfLl.js +1 -0
- package/dist/web/client/assets/architecture-7GRP2DOG-EGozsYEO.js +1 -0
- package/dist/web/client/assets/architectureDiagram-5GKGNRK7-z9FokbJl.js +36 -0
- package/dist/web/client/assets/array-BifhSqXX.js +1 -0
- package/dist/web/client/assets/atkinson-hyperlegible-next-latin-ext-wght-normal-C6vrW8VD.woff2 +0 -0
- package/dist/web/client/assets/atkinson-hyperlegible-next-latin-wght-normal-BcXVPD7q.woff2 +0 -0
- package/dist/web/client/assets/blockDiagram-I7D4REHJ-wi0_CYHL.js +129 -0
- package/dist/web/client/assets/c4Diagram-7LVT6UL2-DV7NYc2W.js +38 -0
- package/dist/web/client/assets/channel-CiUWbHN9.js +1 -0
- package/dist/web/client/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/web/client/assets/chunk-4HAMMTFA-Bhsegh3F.js +62 -0
- package/dist/web/client/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/web/client/assets/chunk-75Z2AOVW-RQCckcQG.js +2 -0
- package/dist/web/client/assets/chunk-DU6HZSFF-C5USiOAy.js +125 -0
- package/dist/web/client/assets/chunk-F27PBJKO-BcNqv2x1.js +1 -0
- package/dist/web/client/assets/chunk-FOHPRMQF-CoA4358r.js +161 -0
- package/dist/web/client/assets/chunk-GMAD6QVW-Bq8JWiZT.js +72 -0
- package/dist/web/client/assets/chunk-GVQU2GXP-DbchrAeJ.js +1 -0
- package/dist/web/client/assets/chunk-IMKFNOWR-DrpvjocK.js +231 -0
- package/dist/web/client/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/web/client/assets/chunk-L3NEJ4N5-DHLmTnCe.js +1 -0
- package/dist/web/client/assets/chunk-OSK3NFVY-CsRbtN9n.js +10 -0
- package/dist/web/client/assets/chunk-P2QGCYS3-aqPbxoMh.js +1 -0
- package/dist/web/client/assets/chunk-POPQ4Y6H-Dl5vw0h0.js +1 -0
- package/dist/web/client/assets/chunk-PWAF6VOD-D7OBRSdO.js +1 -0
- package/dist/web/client/assets/chunk-SHT3W25Y-CdKCIwuB.js +168 -0
- package/dist/web/client/assets/chunk-SVP7TREG-B94Nu_1-.js +88 -0
- package/dist/web/client/assets/chunk-TICWLB2K-jjRQI_hk.js +206 -0
- package/dist/web/client/assets/chunk-XXDRQBXY-azkbKE37.js +1 -0
- package/dist/web/client/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/web/client/assets/classDiagram-ZZMXUADV-CMODalmo.js +1 -0
- package/dist/web/client/assets/classDiagram-v2-VYDZK3BY-CMODalmo.js +1 -0
- package/dist/web/client/assets/commit-mono-latin-400-normal-s0S3qwFW.woff +0 -0
- package/dist/web/client/assets/commit-mono-latin-400-normal-wzhe4RuD.woff2 +0 -0
- package/dist/web/client/assets/cose-bilkent-JH36ORCC-RbQL23qS.js +1 -0
- package/dist/web/client/assets/cynefin-OW5HDTMX--i9RDU5f.js +1 -0
- package/dist/web/client/assets/cynefinDiagram-5FMLGOSQ-cRcvyBdp.js +62 -0
- package/dist/web/client/assets/cytoscape.esm-c2aL46s-.js +321 -0
- package/dist/web/client/assets/dagre-C-rnJpZF.js +1 -0
- package/dist/web/client/assets/dagre-GXQ25YYZ-C9mZmAPe.js +4 -0
- package/dist/web/client/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/web/client/assets/diagram-S7CK7UJ4-Oj_zlLDY.js +30 -0
- package/dist/web/client/assets/diagram-UQ7AKVKN-BWKbbfcR.js +41 -0
- package/dist/web/client/assets/diagram-VSXAHHWV-C3N3f7DO.js +3 -0
- package/dist/web/client/assets/diagram-VX7I27RA-CtDKDAWe.js +24 -0
- package/dist/web/client/assets/diagram-Z3DM3KII-B8bkBRCz.js +24 -0
- package/dist/web/client/assets/dist-D0_q-A2b.js +1 -0
- package/dist/web/client/assets/ebnfDiagram-PWID7BFC-CskW-Whx.js +1 -0
- package/dist/web/client/assets/erDiagram-RLTQ6QDP-C-83cgCW.js +99 -0
- package/dist/web/client/assets/eventmodeling-NTZA5JFV-DjVq8wKU.js +1 -0
- package/dist/web/client/assets/flowDiagram-HODETNUW-BUiCBGXt.js +1 -0
- package/dist/web/client/assets/ganttDiagram-EL5Y4UJY-B2lb8lvF.js +292 -0
- package/dist/web/client/assets/gitGraph-4MIJSDKK-B40cQtBE.js +1 -0
- package/dist/web/client/assets/gitGraphDiagram-WWUBYQGX-CH-7P7Di.js +106 -0
- package/dist/web/client/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/web/client/assets/index-Dsi52apB.css +1 -0
- package/dist/web/client/assets/index-FSIC94pi.js +83 -0
- package/dist/web/client/assets/info-A6RAGUB7-eCCE9D_Q.js +1 -0
- package/dist/web/client/assets/infoDiagram-27XIBGKW-DRnvqMjM.js +2 -0
- package/dist/web/client/assets/init-C-OQMol4.js +1 -0
- package/dist/web/client/assets/ishikawaDiagram-5VMMS53U-DBA_55wp.js +70 -0
- package/dist/web/client/assets/journeyDiagram-3NMN7TZE-C-ewpNl7.js +139 -0
- package/dist/web/client/assets/kanban-definition-UXKFOSKX-B1taGsu0.js +89 -0
- package/dist/web/client/assets/katex-ZlcWpGUi.js +257 -0
- package/dist/web/client/assets/line-lZ0kyxDI.js +1 -0
- package/dist/web/client/assets/linear-DIc8FgZj.js +1 -0
- package/dist/web/client/assets/mermaid-parser.core-SXolxpXw.js +7 -0
- package/dist/web/client/assets/mermaid.core-DXgQtkNg.js +44 -0
- package/dist/web/client/assets/mindmap-definition-YA3MSWOX-DXJas9K7.js +96 -0
- package/dist/web/client/assets/newsreader-latin-ext-wght-normal-C-3rgBeH.woff2 +0 -0
- package/dist/web/client/assets/newsreader-latin-wght-normal-CCVVNp6i.woff2 +0 -0
- package/dist/web/client/assets/newsreader-vietnamese-wght-normal-Czsa-EzN.woff2 +0 -0
- package/dist/web/client/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/web/client/assets/packet-AYTQ26CC-OqVl_07o.js +1 -0
- package/dist/web/client/assets/path-fybaL0A-.js +1 -0
- package/dist/web/client/assets/pegDiagram-XKGWAZYB-CPE_zdfN.js +1 -0
- package/dist/web/client/assets/pie-WAS4IAKB-DAxnMBLe.js +1 -0
- package/dist/web/client/assets/pieDiagram-E7YTZNPT-Uwjpufxv.js +39 -0
- package/dist/web/client/assets/prism-bash-D6zCJ74D.js +1 -0
- package/dist/web/client/assets/prism-c-04YixN25.js +1 -0
- package/dist/web/client/assets/prism-clike-DapgWyxx.js +1 -0
- package/dist/web/client/assets/prism-core-BngLtbUd.js +1 -0
- package/dist/web/client/assets/prism-cpp-C-lJbC-6.js +1 -0
- package/dist/web/client/assets/prism-css-CPgOzxXp.js +1 -0
- package/dist/web/client/assets/prism-diff-BF8m0_mq.js +3 -0
- package/dist/web/client/assets/prism-docker-DkT6yOFj.js +1 -0
- package/dist/web/client/assets/prism-fortran-Be5x3y1V.js +1 -0
- package/dist/web/client/assets/prism-go-C_8qAH5n.js +1 -0
- package/dist/web/client/assets/prism-ini-BESK3y0r.js +1 -0
- package/dist/web/client/assets/prism-javascript-BnO-swvr.js +1 -0
- package/dist/web/client/assets/prism-json-Dp_-W-Hv.js +1 -0
- package/dist/web/client/assets/prism-jsx-D-D0NWtC.js +1 -0
- package/dist/web/client/assets/prism-julia-DIjOgiAV.js +1 -0
- package/dist/web/client/assets/prism-latex-DNMbqcH_.js +1 -0
- package/dist/web/client/assets/prism-makefile-CRKWLQ8l.js +1 -0
- package/dist/web/client/assets/prism-markdown-C0FPJ1Iz.js +1 -0
- package/dist/web/client/assets/prism-markup-Cp04rIa1.js +1 -0
- package/dist/web/client/assets/prism-matlab-D-nk08al.js +1 -0
- package/dist/web/client/assets/prism-python-CfiSVtM6.js +1 -0
- package/dist/web/client/assets/prism-r-QmNGR8LX.js +1 -0
- package/dist/web/client/assets/prism-rust-Bu9N8X3N.js +1 -0
- package/dist/web/client/assets/prism-shell-session-Be4UuYoM.js +1 -0
- package/dist/web/client/assets/prism-sql-CYhVDMEE.js +1 -0
- package/dist/web/client/assets/prism-toml-DKb54GAT.js +1 -0
- package/dist/web/client/assets/prism-tsx-p6J2Kc_4.js +1 -0
- package/dist/web/client/assets/prism-typescript-BMqONzxf.js +1 -0
- package/dist/web/client/assets/prism-yaml-C0JHu8gr.js +1 -0
- package/dist/web/client/assets/purify.es-ChwZkWde.js +3 -0
- package/dist/web/client/assets/quadrantDiagram-AXDQQJYC-Bjs4yjgs.js +7 -0
- package/dist/web/client/assets/radar-RG4KPBEZ-CuCKjHM3.js +1 -0
- package/dist/web/client/assets/railroad-74A4TZTK-CnQK-Cc1.js +1 -0
- package/dist/web/client/assets/railroad-abnf-HS5TGJTU-BcW01NZG.js +1 -0
- package/dist/web/client/assets/railroad-ebnf-LZEXJU2U-B7YCEDDd.js +1 -0
- package/dist/web/client/assets/railroad-peg-WCYAUIDC-DjNZbSTZ.js +1 -0
- package/dist/web/client/assets/railroadDiagram-O6MQD6OU-BDDIPNLL.js +1 -0
- package/dist/web/client/assets/requirementDiagram-BXWQKSXE-B5Ydyxc1.js +84 -0
- package/dist/web/client/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dist/web/client/assets/sankeyDiagram-P5KCCOFB-Bw2Qym75.js +40 -0
- package/dist/web/client/assets/sequenceDiagram-WJ2MYXX4-BZf36nO0.js +162 -0
- package/dist/web/client/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- package/dist/web/client/assets/src-yeptRXpt.js +1 -0
- package/dist/web/client/assets/stateDiagram-D77RDMKH-DnH6JRkp.js +1 -0
- package/dist/web/client/assets/stateDiagram-v2-MP3YSRHH-C7QtHeK4.js +1 -0
- package/dist/web/client/assets/swimlanes-42K2YHIH-D9PZmtZg.js +1 -0
- package/dist/web/client/assets/swimlanesDiagram-VR7AAH4N-CBZlPFky.js +8 -0
- package/dist/web/client/assets/timeline-definition-24CTP7MA-CrkZZBo7.js +120 -0
- package/dist/web/client/assets/treeView-Q6P3EWNA-C9zDShoC.js +1 -0
- package/dist/web/client/assets/treemap-WGGIJYW6-B-plj9yK.js +1 -0
- package/dist/web/client/assets/vennDiagram-4TSXK5OY-VeOdaphN.js +34 -0
- package/dist/web/client/assets/wardley-WFR3VGLG-Wl1P_m6L.js +1 -0
- package/dist/web/client/assets/wardleyDiagram-VM6X3IG4-B85-R9t2.js +78 -0
- package/dist/web/client/assets/xychartDiagram-S5SC5T6Z-BrD8OW8m.js +7 -0
- package/dist/web/client/clio-coder-logo.webp +0 -0
- package/dist/web/client/icon-192.png +0 -0
- package/dist/web/client/icon-512.png +0 -0
- package/dist/web/client/index.html +4 -0
- package/dist/web/client/manifest.webmanifest +15 -0
- package/dist/web/client/offline.css +55 -0
- package/dist/web/client/offline.html +5 -0
- package/dist/web/client/offline.js +27 -0
- package/dist/web/client/sw.js +34 -0
- package/dist/web/ops-worker.js +37 -0
- package/dist/web/reads-worker.js +1726 -0
- package/dist/web/server.js +8499 -0
- package/dist/web-EU6ATJWA.js +13 -0
- package/dist/web-fetch-U22Q7HV4.js +788 -0
- package/dist/wiki-generate-LZRLFG6I.js +623 -0
- package/dist/with-panes-X5CZOGML.js +628 -0
- package/dist/worker/entry.js +300 -93
- package/docs/README.md +58 -14
- package/docs/architecture/acp.md +5 -9
- package/docs/architecture/alcf-provider.md +0 -3
- package/docs/architecture/architecture.md +8 -10
- package/docs/architecture/artifact-placement.md +0 -3
- package/docs/architecture/artifact-versions.md +3 -6
- package/docs/architecture/capacity-and-scheduling.md +0 -3
- package/docs/architecture/context-engine.md +35 -4
- package/docs/architecture/context-working-set.md +0 -3
- package/docs/architecture/dispatch-architecture-rationale.md +0 -3
- package/docs/architecture/dispatch-typed-intent.md +0 -3
- package/docs/architecture/evidence-and-memory.md +0 -3
- package/docs/architecture/library.md +30 -0
- package/docs/architecture/middleware-and-components.md +1 -4
- package/docs/architecture/model-catalog.md +21 -4
- package/docs/architecture/observability.md +0 -3
- package/docs/architecture/pi-boundary.md +23 -8
- package/docs/architecture/prompt-envelope-and-tools.md +6 -9
- package/docs/architecture/provider-adapter-cookbook.md +1 -4
- package/docs/architecture/safety-model.md +21 -5
- package/docs/architecture/session-lifecycle.md +12 -4
- package/docs/architecture/time-conventions.md +0 -3
- package/docs/architecture/trace-store.md +28 -20
- package/docs/architecture/tui-design.md +108 -12
- package/docs/architecture/worker-context.md +104 -0
- package/docs/architecture/worker-dispatch-mechanics.md +1 -4
- package/docs/guide/authoring-plugins.md +158 -0
- package/docs/guide/built-in-agents.md +5 -8
- package/docs/guide/commands-and-modes.md +162 -61
- package/docs/guide/configuration-and-targets.md +198 -5
- package/docs/guide/configuration-reference.md +36 -38
- package/docs/guide/environment-variables.md +2 -5
- package/docs/guide/exit-codes-and-output.md +1 -4
- package/docs/guide/extensions-and-sharing.md +92 -55
- package/docs/guide/fleet-dispatch.md +31 -7
- package/docs/guide/glossary.md +1 -4
- package/docs/guide/harness-extensions.md +289 -0
- package/docs/guide/installation-and-lifecycle.md +10 -13
- package/docs/guide/interop.md +241 -0
- package/docs/guide/panes-and-files.md +3 -6
- package/docs/guide/plugins.md +77 -0
- package/docs/guide/proactive-memory.md +0 -3
- package/docs/guide/resource-library.md +109 -45
- package/docs/guide/skills-marketplace.md +34 -73
- package/docs/guide/tool-usage.md +19 -10
- package/docs/guide/troubleshooting.md +1 -4
- package/docs/history/config-knobs-audit.md +0 -3
- package/docs/history/release-cut-checklist.md +0 -3
- package/docs/process/development-pipeline.md +14 -17
- package/docs/process/documentation-coverage.md +31 -4
- package/docs/process/documentation-guide.md +28 -27
- package/docs/process/eval-runner.md +8 -6
- package/docs/process/evals-internal.md +0 -3
- package/docs/process/evolution.md +0 -3
- package/docs/process/fleet-demo-runbook.md +0 -3
- package/docs/process/git-commit-provenance.md +0 -3
- package/docs/process/performance-methodology.md +2 -5
- package/docs/process/release-cut-checklist.md +114 -217
- package/docs/process/scientific-validation.md +23 -3
- package/evals/scalar-decision-machinery.ts +1 -1
- package/examples/extensions/README.md +67 -0
- package/examples/extensions/lab-status/clio-coder-extension.json +14 -0
- package/examples/extensions/lab-status/extension.mjs +68 -0
- package/examples/extensions/lab-status/jobs.synthetic.json +9 -0
- package/examples/extensions/measurements/clio-coder-extension.json +28 -0
- package/examples/extensions/measurements/summarize.cjs +23 -0
- package/library/README.md +109 -0
- package/library/_authoring/templates/agent/README.md +28 -0
- package/library/_authoring/templates/agent/agents/benchmark-scout.md +30 -0
- package/library/_authoring/templates/agent/plugin.json +23 -0
- package/library/_authoring/templates/fleet/README.md +29 -0
- package/library/_authoring/templates/fleet/fleets/pipeline-review.md +31 -0
- package/library/_authoring/templates/fleet/plugin.json +23 -0
- package/library/_authoring/templates/plugin/README.md +37 -0
- package/library/_authoring/templates/plugin/agents/data-curator.md +31 -0
- package/library/_authoring/templates/plugin/assets/curation-guide.md +22 -0
- package/library/_authoring/templates/plugin/plugin.json +42 -0
- package/library/_authoring/templates/plugin/prompts/inspect-dataset.md +15 -0
- package/library/_authoring/templates/plugin/skills/dataset-curation/SKILL.md +36 -0
- package/library/_authoring/templates/plugin/skills/dataset-curation/evals.md +17 -0
- package/library/_authoring/templates/prompt/README.md +28 -0
- package/library/_authoring/templates/prompt/plugin.json +23 -0
- package/library/_authoring/templates/prompt/prompts/paper-summary.md +26 -0
- package/library/_authoring/templates/skill/README.md +24 -0
- package/library/_authoring/templates/skill/SKILL.md +39 -0
- package/library/_authoring/templates/skill/evals.md +30 -0
- package/library/_authoring/templates/skill/plugin.json +23 -0
- package/library/agents/README.md +7 -0
- package/library/fleets/README.md +7 -0
- package/library/plugins/materio/README.md +137 -0
- package/library/plugins/materio/ai.iowarp.clio/agents/materio-lab-definer.md +208 -0
- package/library/plugins/materio/ai.iowarp.clio/agents/materio-literature-reviewer.md +308 -0
- package/library/plugins/materio/ai.iowarp.clio/agents/materio-research-explorer.md +249 -0
- package/library/plugins/materio/ai.iowarp.clio/agents/materio-task-executor.md +416 -0
- package/library/plugins/materio/ai.iowarp.clio/agents/materio-task-verifier.md +60 -0
- package/library/plugins/materio/ai.iowarp.clio/agents/materio-workflow-planner.md +238 -0
- package/library/plugins/materio/ai.iowarp.clio/fleets/materio-execute-task.md +50 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/add-task.md +66 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/archive-task.md +65 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/checkpoint.md +26 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/define-research-tasks.md +230 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/define-virtual-lab.md +181 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/execute-task.md +292 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/help.md +129 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/identify-research.md +206 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/literature-review.md +201 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/pause-research.md +12 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/progress.md +105 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/remove-task.md +63 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/resume-research.md +64 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/settings.md +16 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/status.md +92 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/upload-data.md +104 -0
- package/library/plugins/materio/ai.iowarp.clio/prompts/materio/wtfp.md +145 -0
- package/library/plugins/materio/ai.iowarp.clio/references/execution.md +56 -0
- package/library/plugins/materio/ai.iowarp.portability/provenance.json +9 -0
- package/library/plugins/materio/assets/actions/add-task.md +86 -0
- package/library/plugins/materio/assets/actions/archive-task.md +84 -0
- package/library/plugins/materio/assets/actions/checkpoint.md +47 -0
- package/library/plugins/materio/assets/actions/define-research-tasks.md +228 -0
- package/library/plugins/materio/assets/actions/define-virtual-lab.md +179 -0
- package/library/plugins/materio/assets/actions/execute-task.md +290 -0
- package/library/plugins/materio/assets/actions/help.md +140 -0
- package/library/plugins/materio/assets/actions/identify-research.md +204 -0
- package/library/plugins/materio/assets/actions/literature-review.md +199 -0
- package/library/plugins/materio/assets/actions/pause-research.md +34 -0
- package/library/plugins/materio/assets/actions/progress.md +125 -0
- package/library/plugins/materio/assets/actions/remove-task.md +82 -0
- package/library/plugins/materio/assets/actions/resume-research.md +84 -0
- package/library/plugins/materio/assets/actions/settings.md +38 -0
- package/library/plugins/materio/assets/actions/status.md +112 -0
- package/library/plugins/materio/assets/actions/upload-data.md +123 -0
- package/library/plugins/materio/assets/actions/wtfp.md +179 -0
- package/library/plugins/materio/assets/references/research-domains.md +134 -0
- package/library/plugins/materio/assets/references/research-policy.md +77 -0
- package/library/plugins/materio/assets/references/traditional-workflows.md +146 -0
- package/library/plugins/materio/assets/scripts/check_physics.py +271 -0
- package/library/plugins/materio/assets/scripts/check_scripts.py +248 -0
- package/library/plugins/materio/assets/scripts/project_plugin.py +165 -0
- package/library/plugins/materio/assets/scripts/research_state.py +400 -0
- package/library/plugins/materio/assets/scripts/verify_citations.py +616 -0
- package/library/plugins/materio/assets/templates/RESEARCH.md +39 -0
- package/library/plugins/materio/assets/templates/VIRTUAL-LAB.md +120 -0
- package/library/plugins/materio/assets/templates/WORKFLOW.md +42 -0
- package/library/plugins/materio/assets/templates/config.json +5 -0
- package/library/plugins/materio/evals/scripts.yaml +29 -0
- package/library/plugins/materio/plugin.json +530 -0
- package/library/plugins/materio/skills/materio-lab-definer/SKILL.md +74 -0
- package/library/plugins/materio/skills/materio-literature-reviewer/SKILL.md +64 -0
- package/library/plugins/materio/skills/materio-research-explorer/SKILL.md +74 -0
- package/library/plugins/materio/skills/materio-task-executor/SKILL.md +214 -0
- package/library/plugins/materio/skills/materio-task-verifier/SKILL.md +46 -0
- package/library/plugins/materio/skills/materio-workflow-planner/SKILL.md +79 -0
- package/library/plugins/materio/tests/test_check_physics.py +139 -0
- package/library/plugins/materio/tests/test_check_scripts.py +140 -0
- package/library/plugins/materio/tests/test_research_state.py +291 -0
- package/library/plugins/materio/tests/test_verify_citations.py +337 -0
- package/library/prompts/README.md +7 -0
- package/library/registry.yaml +921 -0
- package/library/skills/README.md +120 -0
- package/library/skills/coding/ast-grep/SKILL.md +213 -0
- package/library/skills/coding/ast-grep/evals.md +82 -0
- package/library/skills/coding/ast-grep/plugin.json +23 -0
- package/library/skills/coding/coding-standards/SKILL.md +164 -0
- package/library/skills/coding/coding-standards/evals.md +57 -0
- package/library/skills/coding/coding-standards/plugin.json +23 -0
- package/library/skills/coding/prototype/SKILL.md +151 -0
- package/library/skills/coding/prototype/evals.md +61 -0
- package/library/skills/coding/prototype/plugin.json +23 -0
- package/library/skills/coding/tdd/SKILL.md +134 -0
- package/library/skills/coding/tdd/evals.md +61 -0
- package/library/skills/coding/tdd/plugin.json +23 -0
- package/library/skills/context/context-handoff/SKILL.md +176 -0
- package/library/skills/context/context-handoff/evals.md +101 -0
- package/library/skills/context/context-handoff/plugin.json +23 -0
- package/library/skills/context/context-prime/SKILL.md +131 -0
- package/library/skills/context/context-prime/evals.md +99 -0
- package/library/skills/context/context-prime/plugin.json +23 -0
- package/library/skills/git/branch-closeout/SKILL.md +132 -0
- package/library/skills/git/branch-closeout/plugin.json +23 -0
- package/library/skills/git/file-ticket/SKILL.md +126 -0
- package/library/skills/git/file-ticket/plugin.json +23 -0
- package/library/skills/git/fix-issue/SKILL.md +136 -0
- package/library/skills/git/fix-issue/plugin.json +23 -0
- package/library/skills/git/resolve-merge-conflicts/SKILL.md +151 -0
- package/library/skills/git/resolve-merge-conflicts/evals.md +85 -0
- package/library/skills/git/resolve-merge-conflicts/plugin.json +23 -0
- package/library/skills/git/ship/SKILL.md +134 -0
- package/library/skills/git/ship/plugin.json +23 -0
- package/library/skills/git/worktree-create/SKILL.md +127 -0
- package/library/skills/git/worktree-create/plugin.json +23 -0
- package/library/skills/git/worktree-merge/SKILL.md +147 -0
- package/library/skills/git/worktree-merge/plugin.json +23 -0
- package/library/skills/meta/clio-coder-dev/SKILL.md +101 -0
- package/library/skills/meta/clio-coder-dev/evals.md +46 -0
- package/library/skills/meta/clio-coder-dev/plugin.json +23 -0
- package/library/skills/meta/clio-coder-test/SKILL.md +156 -0
- package/library/skills/meta/clio-coder-test/evals.md +62 -0
- package/library/skills/meta/clio-coder-test/plugin.json +23 -0
- package/library/skills/meta/clio-coder-test/references/test-map.md +97 -0
- package/library/skills/meta/credentials/SKILL.md +132 -0
- package/library/skills/meta/credentials/evals.md +104 -0
- package/library/skills/meta/credentials/plugin.json +23 -0
- package/library/skills/meta/find-skills/SKILL.md +85 -0
- package/library/skills/meta/find-skills/evals.md +65 -0
- package/library/skills/meta/find-skills/plugin.json +23 -0
- package/library/skills/meta/herdr/SKILL.md +133 -0
- package/library/skills/meta/herdr/evals.md +38 -0
- package/library/skills/meta/herdr/plugin.json +23 -0
- package/library/skills/meta/skill-craft/SKILL.md +139 -0
- package/library/skills/meta/skill-craft/evals.md +49 -0
- package/library/skills/meta/skill-craft/plugin.json +23 -0
- package/library/skills/planning/archify/SKILL.md +196 -0
- package/library/skills/planning/archify/plugin.json +23 -0
- package/library/skills/planning/architecture/SKILL.md +184 -0
- package/library/skills/planning/architecture/evals.md +101 -0
- package/library/skills/planning/architecture/plugin.json +23 -0
- package/library/skills/planning/backlog/SKILL.md +212 -0
- package/library/skills/planning/backlog/evals.md +185 -0
- package/library/skills/planning/backlog/plugin.json +23 -0
- package/library/skills/planning/prd/SKILL.md +129 -0
- package/library/skills/planning/prd/evals.md +103 -0
- package/library/skills/planning/prd/plugin.json +23 -0
- package/library/skills/planning/product-intent/SKILL.md +173 -0
- package/library/skills/planning/product-intent/evals.md +106 -0
- package/library/skills/planning/product-intent/plugin.json +23 -0
- package/library/skills/planning/tech-spec/SKILL.md +172 -0
- package/library/skills/planning/tech-spec/evals.md +120 -0
- package/library/skills/planning/tech-spec/plugin.json +23 -0
- package/library/skills/registry.yaml +144 -0
- package/library/skills/remote.yaml +13 -0
- package/library/skills/research/arxiv-literature/SKILL.md +168 -0
- package/library/skills/research/arxiv-literature/evals.md +108 -0
- package/library/skills/research/arxiv-literature/plugin.json +23 -0
- package/library/skills/research/experiment-protocol/SKILL.md +148 -0
- package/library/skills/research/experiment-protocol/evals.md +114 -0
- package/library/skills/research/experiment-protocol/plugin.json +23 -0
- package/library/skills/research/scientific-debugging/SKILL.md +149 -0
- package/library/skills/research/scientific-debugging/evals.md +156 -0
- package/library/skills/research/scientific-debugging/plugin.json +23 -0
- package/library/skills/research/scientific-modernization/SKILL.md +170 -0
- package/library/skills/research/scientific-modernization/evals.md +111 -0
- package/library/skills/research/scientific-modernization/plugin.json +23 -0
- package/library/skills/skill-marketplace.json +507 -0
- package/library/skills/workflow/cut-it/SKILL.md +153 -0
- package/library/skills/workflow/cut-it/evals.md +143 -0
- package/library/skills/workflow/cut-it/plugin.json +23 -0
- package/library/skills/workflow/design-council/SKILL.md +233 -0
- package/library/skills/workflow/design-council/evals.md +258 -0
- package/library/skills/workflow/design-council/plugin.json +23 -0
- package/library/skills/workflow/grill-me/SKILL.md +267 -0
- package/library/skills/workflow/grill-me/evals.md +231 -0
- package/library/skills/workflow/grill-me/plugin.json +23 -0
- package/library/skills/workflow/workflow-distiller/SKILL.md +204 -0
- package/library/skills/workflow/workflow-distiller/evals.md +233 -0
- package/library/skills/workflow/workflow-distiller/plugin.json +23 -0
- package/package.json +23 -14
- package/src/cli/agents.ts +1 -1
- package/src/cli/config-inspect.ts +1 -1
- package/src/cli/configure.ts +2 -2
- package/src/cli/docs.ts +65 -328
- package/src/cli/eval.ts +40 -6
- package/src/cli/extensions.ts +74 -8
- package/src/cli/fleet-preflight.ts +2 -0
- package/src/cli/fleet.ts +2 -0
- package/src/cli/index.ts +4 -4
- package/src/cli/interop-inspect.ts +61 -33
- package/src/cli/interop.ts +79 -9
- package/src/cli/library-import.ts +139 -0
- package/src/cli/library.ts +418 -120
- package/src/cli/run.ts +26 -9
- package/src/cli/skills-eval.ts +43 -6
- package/src/cli/skills-inventory.ts +6 -2
- package/src/cli/skills.ts +44 -491
- package/src/cli/trace.ts +4 -65
- package/src/cli/uninstall.ts +26 -0
- package/src/cli/usage.ts +3 -0
- package/src/cli/web.ts +79 -0
- package/src/core/bus-events.ts +8 -4
- package/src/core/config.ts +71 -0
- package/src/core/defaults.ts +1 -1
- package/src/core/domain-loader.ts +37 -28
- package/src/core/recent-models.ts +2 -2
- package/src/core/session-routing.ts +3 -3
- package/src/core/state-file-lock.ts +1 -1
- package/src/core/termination.ts +13 -9
- package/src/core/tool-names.ts +5 -0
- package/src/domains/agents/contract.ts +1 -1
- package/src/domains/agents/extension.ts +53 -9
- package/src/domains/agents/fleet-commands.ts +92 -1
- package/src/domains/agents/fleet-contract.ts +87 -19
- package/src/domains/agents/recipe.ts +5 -4
- package/src/domains/agents/registry.ts +80 -24
- package/src/domains/config/extension.ts +5 -4
- package/src/domains/config/keybindings.ts +155 -95
- package/src/domains/context/worker/contract.ts +91 -0
- package/src/domains/context/worker/pressure.ts +120 -0
- package/src/domains/context/worker/recall.ts +62 -0
- package/src/domains/context/worker/select.ts +164 -0
- package/src/domains/context/worker/snapshot.ts +35 -0
- package/src/domains/context/worker/store.ts +16 -0
- package/src/domains/context/working-set/replay/synthetic.ts +2 -1
- package/src/domains/dispatch/active-route-planner.ts +2 -0
- package/src/domains/dispatch/backoff.ts +1 -0
- package/src/domains/dispatch/code-step.ts +12 -2
- package/src/domains/dispatch/contract.ts +3 -0
- package/src/domains/dispatch/execution-plan.ts +2 -0
- package/src/domains/dispatch/extension.ts +184 -39
- package/src/domains/dispatch/fleet-plan.ts +10 -0
- package/src/domains/dispatch/fleet-run.ts +1 -0
- package/src/domains/dispatch/index.ts +1 -0
- package/src/domains/dispatch/orphan-recovery.ts +2 -0
- package/src/domains/dispatch/receipt-integrity.ts +7 -0
- package/src/domains/dispatch/state.ts +2 -2
- package/src/domains/dispatch/types.ts +7 -0
- package/src/domains/dispatch/validation.ts +12 -0
- package/src/domains/dispatch/workspace-checkpoint.ts +1 -1
- package/src/domains/eval/metrics/tracked.ts +22 -2
- package/src/domains/evidence/failure-attribution.ts +1 -0
- package/src/domains/evidence/trust-status.ts +22 -3
- package/src/domains/extensions/command-schema.ts +145 -0
- package/src/domains/extensions/command-tools.ts +15 -0
- package/src/domains/extensions/compatibility.ts +7 -0
- package/src/domains/extensions/contract.ts +0 -4
- package/src/domains/extensions/discovery.ts +69 -205
- package/src/domains/extensions/extension.ts +0 -4
- package/src/domains/extensions/index.ts +1 -5
- package/src/domains/extensions/manager.ts +1 -6
- package/src/domains/extensions/operator-commands.ts +29 -0
- package/src/domains/extensions/operator-runtime.ts +485 -0
- package/src/domains/extensions/public-api.ts +53 -0
- package/src/domains/extensions/runtime-child.mjs +114 -0
- package/src/domains/extensions/runtime-process.ts +306 -0
- package/src/domains/extensions/runtime-schema.ts +146 -0
- package/src/domains/extensions/snapshot-access.ts +21 -0
- package/src/domains/extensions/snapshot.ts +4 -32
- package/src/domains/extensions/state.ts +5 -83
- package/src/domains/extensions/types.ts +33 -34
- package/src/domains/interop/adopt.ts +546 -0
- package/src/domains/interop/detect.ts +50 -12
- package/src/domains/interop/foreign.ts +554 -0
- package/src/domains/interop/import.ts +277 -0
- package/src/domains/interop/index.ts +24 -0
- package/src/domains/interop/install.ts +6 -0
- package/src/domains/interop/inventory.ts +351 -0
- package/src/domains/interop/projection.ts +360 -0
- package/src/domains/interop/registry.ts +106 -3
- package/src/domains/interop/types.ts +51 -0
- package/src/domains/lifecycle/migrations/index.ts +0 -2
- package/src/domains/lifecycle/naming-resources.ts +1 -1
- package/src/domains/middleware/hooks.ts +2 -2
- package/src/domains/middleware/marketplace-offer.ts +1 -1
- package/src/domains/mux/contract.ts +1 -1
- package/src/domains/observability/background-memory-usage.ts +3 -0
- package/src/domains/observability/compaction-usage.ts +2 -0
- package/src/domains/observability/cost.ts +5 -0
- package/src/domains/observability/extension.ts +1 -0
- package/src/domains/observability/out-of-turn-usage.ts +2 -0
- package/src/domains/observability/trace-store.ts +65 -5
- package/src/domains/plugins/catalog.ts +204 -0
- package/src/domains/plugins/contract.ts +24 -0
- package/src/domains/plugins/discovery.ts +316 -0
- package/src/domains/plugins/extension.ts +40 -0
- package/src/domains/plugins/index.ts +77 -0
- package/src/domains/plugins/integrity.ts +6 -0
- package/src/domains/plugins/manifest.ts +3 -0
- package/src/domains/plugins/resources.ts +102 -0
- package/src/domains/plugins/state.ts +753 -0
- package/src/domains/plugins/types.ts +217 -0
- package/src/domains/prompts/extension.ts +4 -10
- package/src/domains/prompts/fragments/operating/skills.md +10 -10
- package/src/domains/providers/cache-deployment.ts +147 -0
- package/src/domains/providers/catalog.ts +12 -7
- package/src/domains/providers/extension.ts +27 -5
- package/src/domains/providers/index.ts +1 -0
- package/src/domains/providers/plugins.ts +3 -13
- package/src/domains/providers/runtimes/common/local-synth.ts +4 -0
- package/src/domains/providers/types/target-descriptor.ts +17 -0
- package/src/domains/resources/common-loader.ts +9 -6
- package/src/domains/resources/index.ts +67 -0
- package/src/domains/resources/library-actions.ts +836 -0
- package/src/domains/resources/library-evals.ts +38 -0
- package/src/domains/resources/library-inventory.ts +1048 -0
- package/src/domains/resources/library-types.ts +50 -0
- package/src/domains/resources/library-validation.ts +634 -0
- package/src/domains/resources/library.ts +437 -156
- package/src/domains/resources/package-references.ts +66 -0
- package/src/domains/resources/prompts/loader.ts +75 -41
- package/src/domains/resources/skills/install.ts +2 -2
- package/src/domains/resources/skills/loader.ts +77 -22
- package/src/domains/resources/skills/marketplace.ts +48 -57
- package/src/domains/resources/skills/promotion.ts +2 -2
- package/src/domains/resources/skills/provenance-pin.ts +17 -4
- package/src/domains/safety/action-classifier.ts +2 -2
- package/src/domains/safety/default-path-policy.ts +3 -1
- package/src/domains/safety/policy-engine.ts +1 -1
- package/src/domains/safety/protected-artifacts.ts +21 -5
- package/src/domains/safety/skill-authority.ts +5 -2
- package/src/domains/session/compaction/compact.ts +4 -1
- package/src/domains/session/entries.ts +1 -0
- package/src/domains/session/usage.ts +6 -7
- package/src/domains/share/archive.ts +1 -1
- package/src/engine/acp/server.ts +11 -0
- package/src/engine/ai.ts +2 -0
- package/src/engine/apis/openai-completions.ts +61 -6
- package/src/engine/notices/pi-tui-LICENSE +21 -0
- package/src/engine/prewarm.ts +232 -0
- package/src/engine/provider-diagnostics.ts +6 -1
- package/src/engine/tui.ts +3 -0
- package/src/engine/worker-runtime.ts +58 -14
- package/src/engine/worker-tools.ts +5 -0
- package/src/entry/orchestrator.ts +46 -21
- package/src/entry/plugin-reload.ts +18 -0
- package/src/interactive/application-controller.ts +67 -21
- package/src/interactive/chat-loop-messages.ts +3 -0
- package/src/interactive/chat-loop.ts +32 -11
- package/src/interactive/chat-panel.ts +5 -1
- package/src/interactive/clio-editor.ts +53 -21
- package/src/interactive/command-output.ts +56 -1
- package/src/interactive/editor-submit.ts +65 -28
- package/src/interactive/fleet-run-preview.ts +2 -0
- package/src/interactive/follow-up-queue-panel.ts +3 -3
- package/src/interactive/footer/dashboard.ts +4 -1
- package/src/interactive/footer/notifications.ts +2 -2
- package/src/interactive/footer/widgets.ts +2 -2
- package/src/interactive/interactive-application.ts +209 -21
- package/src/interactive/interactive-input-runtime.ts +254 -7
- package/src/interactive/interactive-presentation.ts +41 -12
- package/src/interactive/interactive-slash-runtime.ts +37 -8
- package/src/interactive/keybinding-manager.ts +156 -79
- package/src/interactive/keyboard-owner.ts +37 -0
- package/src/interactive/leader-key.ts +49 -102
- package/src/interactive/leader-menu.ts +45 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +9 -1
- package/src/interactive/overlay-frame.ts +15 -0
- package/src/interactive/overlay-key-routing.ts +46 -47
- package/src/interactive/overlay-lifecycle.ts +30 -15
- package/src/interactive/overlay-resource-openers.ts +56 -46
- package/src/interactive/overlays/ask-user.ts +630 -556
- package/src/interactive/overlays/extension-panel.ts +70 -0
- package/src/interactive/overlays/extensions.ts +28 -5
- package/src/interactive/overlays/fleet-run-approval.ts +7 -3
- package/src/interactive/overlays/help-reference.ts +89 -40
- package/src/interactive/overlays/interop.ts +122 -3
- package/src/interactive/overlays/keybinding-detail.ts +2 -2
- package/src/interactive/overlays/library-lifecycle.ts +90 -0
- package/src/interactive/overlays/library-model.ts +574 -0
- package/src/interactive/overlays/library-review.ts +557 -0
- package/src/interactive/overlays/library-tabs.ts +3 -15
- package/src/interactive/overlays/library.ts +602 -0
- package/src/interactive/overlays/list-overlay.ts +218 -39
- package/src/interactive/overlays/model-selector.ts +28 -25
- package/src/interactive/overlays/session-selector.ts +9 -3
- package/src/interactive/overlays/settings.ts +25 -18
- package/src/interactive/overlays/tree-selector.ts +16 -11
- package/src/interactive/permission-hint.ts +13 -0
- package/src/interactive/permission-overlay.ts +77 -28
- package/src/interactive/prewarm.ts +11 -197
- package/src/interactive/prompt-source-label.ts +21 -0
- package/src/interactive/renderers/reference-card.ts +35 -0
- package/src/interactive/renderers/worker-entry.ts +35 -3
- package/src/interactive/session-usage-reseed.ts +2 -0
- package/src/interactive/side-question.ts +2 -0
- package/src/interactive/slash-autocomplete.ts +99 -1
- package/src/interactive/slash-commands.ts +390 -67
- package/src/interactive/slash-spec.ts +0 -1
- package/src/interactive/terminal-lease.ts +44 -12
- package/src/interactive/turn-context.ts +1 -0
- package/src/interactive/turn-persistence.ts +3 -0
- package/src/interactive/turn-prewarm.ts +126 -19
- package/src/interactive/turn-queues.ts +8 -7
- package/src/interactive/turn-runtime.ts +15 -1
- package/src/interactive/view/view-overlay.ts +19 -14
- package/src/interactive/welcome-dashboard.ts +525 -408
- package/src/tools/bootstrap.ts +8 -0
- package/src/tools/builtin-tool-catalog.ts +15 -6
- package/src/tools/context/index.ts +58 -5
- package/src/tools/context/library.ts +465 -0
- package/src/tools/context/surface.ts +20 -6
- package/src/tools/core-bootstrap.ts +3 -0
- package/src/tools/dispatch-admission.ts +24 -1
- package/src/tools/dispatch-arguments.ts +8 -0
- package/src/tools/dispatch-plan.ts +32 -0
- package/src/tools/dispatch-schema.ts +31 -1
- package/src/tools/dispatch-types.ts +3 -0
- package/src/tools/dispatch.ts +1 -1
- package/src/tools/harness-extensions.ts +169 -0
- package/src/tools/observation.ts +4 -0
- package/src/tools/policy.ts +7 -1
- package/src/tools/registry.ts +31 -3
- package/src/tools/worker-evidence.ts +5 -0
- package/src/worker/context-seed.ts +192 -0
- package/src/worker/entry.ts +1 -0
- package/src/worker/spec-contract.ts +35 -1
- package/dist/acp-UVEVWSDL.js +0 -130
- package/dist/agents-VWY37DTK.js +0 -148
- package/dist/auth-PCV2XQDV.js +0 -551
- package/dist/builtins-PD652MTK.js +0 -22
- package/dist/chunk-22PQ4TX4.js +0 -360
- package/dist/chunk-24T2YZ7A.js +0 -22648
- package/dist/chunk-2AKYFREM.js +0 -1008
- package/dist/chunk-2QPI3TR3.js +0 -162
- package/dist/chunk-3BJGMT2D.js +0 -324
- package/dist/chunk-3HQVBIKD.js +0 -308
- package/dist/chunk-3JLFK5MW.js +0 -193
- package/dist/chunk-3O2ZAUGQ.js +0 -283
- package/dist/chunk-3QKXHCGS.js +0 -59
- package/dist/chunk-3T4DXWP6.js +0 -668
- package/dist/chunk-3UW3KU4A.js +0 -21
- package/dist/chunk-3WBALRQH.js +0 -5076
- package/dist/chunk-4DU2TVI4.js +0 -108
- package/dist/chunk-4U4TKZFR.js +0 -5052
- package/dist/chunk-4VMV6OS6.js +0 -101
- package/dist/chunk-536HXRFE.js +0 -1257
- package/dist/chunk-5CMARGPF.js +0 -477
- package/dist/chunk-5CY4Q6QI.js +0 -141
- package/dist/chunk-5QRX7SLS.js +0 -1018
- package/dist/chunk-5VTJP36Q.js +0 -36
- package/dist/chunk-5ZSZEYJK.js +0 -119
- package/dist/chunk-6HAO6X5B.js +0 -197
- package/dist/chunk-6OII3LOK.js +0 -404
- package/dist/chunk-6RYDAVQT.js +0 -4338
- package/dist/chunk-6VRRJT7L.js +0 -146
- package/dist/chunk-6YA46L5A.js +0 -386
- package/dist/chunk-77CZRFTE.js +0 -634
- package/dist/chunk-7JSSKXG2.js +0 -1215
- package/dist/chunk-7WUZEB2M.js +0 -165
- package/dist/chunk-7YJWEF2L.js +0 -974
- package/dist/chunk-ACCKVSHU.js +0 -44
- package/dist/chunk-B3MOMLJ4.js +0 -433
- package/dist/chunk-BBV5TKE6.js +0 -35
- package/dist/chunk-BLTEAUCB.js +0 -668
- package/dist/chunk-BS4GAMUB.js +0 -233
- package/dist/chunk-BT7HGDOX.js +0 -3151
- package/dist/chunk-CBSKDFWL.js +0 -101
- package/dist/chunk-CXQ37WJH.js +0 -45
- package/dist/chunk-DXLUVUD4.js +0 -1490
- package/dist/chunk-DZK63TZJ.js +0 -1334
- package/dist/chunk-E7RF4KBO.js +0 -266
- package/dist/chunk-ECOMVOHP.js +0 -139
- package/dist/chunk-EHOSNVVM.js +0 -59
- package/dist/chunk-F5Z7EWMN.js +0 -4484
- package/dist/chunk-FQOOGXBH.js +0 -579
- package/dist/chunk-GLYBJ4RQ.js +0 -396
- package/dist/chunk-HHVJNVUJ.js +0 -179
- package/dist/chunk-HL26ADLH.js +0 -77
- package/dist/chunk-HPTJF6DG.js +0 -2465
- package/dist/chunk-HXHFDHB6.js +0 -962
- package/dist/chunk-HZ2T2YED.js +0 -1687
- package/dist/chunk-HZFBVU5X.js +0 -666
- package/dist/chunk-I2K2NCZQ.js +0 -659
- package/dist/chunk-IGLVVNEG.js +0 -402
- package/dist/chunk-IKRWLEDA.js +0 -1567
- package/dist/chunk-J2FYEQ5L.js +0 -33
- package/dist/chunk-JMPL7NUB.js +0 -108
- package/dist/chunk-K2HL3GBL.js +0 -998
- package/dist/chunk-KAFMW7WM.js +0 -386
- package/dist/chunk-KTFSFCVN.js +0 -46
- package/dist/chunk-LIN2K3EL.js +0 -66
- package/dist/chunk-LUL5Z66S.js +0 -221
- package/dist/chunk-LVFANMOH.js +0 -466
- package/dist/chunk-LY4N4TTL.js +0 -117
- package/dist/chunk-LZBMXNLP.js +0 -1196
- package/dist/chunk-M6TAYK66.js +0 -807
- package/dist/chunk-N2OKBREN.js +0 -243
- package/dist/chunk-NC4KV7EL.js +0 -39
- package/dist/chunk-NF3BK5WR.js +0 -42
- package/dist/chunk-NNWJYUNO.js +0 -573
- package/dist/chunk-NTK3WTHM.js +0 -141
- package/dist/chunk-ODUTYZIU.js +0 -688
- package/dist/chunk-OQM5IVJY.js +0 -1377
- package/dist/chunk-P5JMBPDJ.js +0 -7192
- package/dist/chunk-P5SC4DLJ.js +0 -47
- package/dist/chunk-P6M7RKMI.js +0 -97
- package/dist/chunk-PWWSIB2A.js +0 -52
- package/dist/chunk-PZN2LQY6.js +0 -674
- package/dist/chunk-Q7NNUHQV.js +0 -705
- package/dist/chunk-QCOV5DFY.js +0 -911
- package/dist/chunk-QNWRHOMF.js +0 -692
- package/dist/chunk-QRFXEO6Y.js +0 -17
- package/dist/chunk-QXFBABFJ.js +0 -380
- package/dist/chunk-RGZNQ5CT.js +0 -657
- package/dist/chunk-SRZOW5L2.js +0 -1865
- package/dist/chunk-SXQKNKRA.js +0 -223
- package/dist/chunk-T334FW2H.js +0 -362
- package/dist/chunk-T52TPHYC.js +0 -318
- package/dist/chunk-TJFDL26W.js +0 -658
- package/dist/chunk-TN5FW4XY.js +0 -172
- package/dist/chunk-U7H5WRG5.js +0 -123
- package/dist/chunk-UFYNOQK4.js +0 -302
- package/dist/chunk-URBGEOH3.js +0 -32
- package/dist/chunk-USZA7GWL.js +0 -341
- package/dist/chunk-UUQ5G6EZ.js +0 -697
- package/dist/chunk-VAHLPXPY.js +0 -399
- package/dist/chunk-VANN3GDP.js +0 -2488
- package/dist/chunk-VHMX7SXF.js +0 -1289
- package/dist/chunk-WJIMKGD6.js +0 -132
- package/dist/chunk-WKUYQBCG.js +0 -795
- package/dist/chunk-WNGF5AJX.js +0 -1911
- package/dist/chunk-WV6TDAPN.js +0 -3627
- package/dist/chunk-X3BI7HTV.js +0 -562
- package/dist/chunk-XWMSPJYN.js +0 -149
- package/dist/chunk-YPRSNUTC.js +0 -395
- package/dist/chunk-ZS43Y2FT.js +0 -438
- package/dist/clio-QQCMTUZE.js +0 -26
- package/dist/code-nav-GUPM6766.js +0 -686
- package/dist/components-TNIKXCBH.js +0 -674
- package/dist/config-IIM7YOD3.js +0 -621
- package/dist/configure-4ZM5HWJX.js +0 -73
- package/dist/context-44BZLJ3J.js +0 -344
- package/dist/context-AIDVQKMW.js +0 -278
- package/dist/context-OL5P3HEP.js +0 -1031
- package/dist/context-clear-OQV76MYP.js +0 -184
- package/dist/context-index-HP2JFUWA.js +0 -120
- package/dist/context-map-INTXD54D.js +0 -555
- package/dist/context-working-set-ZUW3EGLS.js +0 -1556
- package/dist/detail-UXPWRANG.js +0 -115
- package/dist/dispatch-runner-P3ZW6G77.js +0 -2438
- package/dist/docs-BL7ROUFN.js +0 -292
- package/dist/doctor-JJVGPZWT.js +0 -797
- package/dist/eval-V2RTN3UH.js +0 -4972
- package/dist/eval-inventory-QOYZERXJ.js +0 -315
- package/dist/evidence-35PYWGSO.js +0 -225
- package/dist/evidence-CIGGKI6J.js +0 -383
- package/dist/evolve-33SM3NJP.js +0 -609
- package/dist/extensions-YVRHX6ZI.js +0 -229
- package/dist/fleet-LFO7SIPC.js +0 -908
- package/dist/fleet-commands-RLK72GU3.js +0 -75
- package/dist/fleet-decisions-3SBSCTCW.js +0 -159
- package/dist/fleet-graph-JZIBCGMW.js +0 -134
- package/dist/fleet-inspect-2L5YGGZJ.js +0 -469
- package/dist/fleet-preflight-QRSHIIDE.js +0 -22
- package/dist/fleet-validate-LIAVKDUU.js +0 -92
- package/dist/fleet-verify-JIK3OQZR.js +0 -202
- package/dist/fleet-view-IWHYGQKK.js +0 -118
- package/dist/init-NJEDOTQW.js +0 -321
- package/dist/interop-RVCAYECG.js +0 -115
- package/dist/inventory-74UL7UHU.js +0 -118
- package/dist/library-CTKZA7K3.js +0 -226
- package/dist/memory-I76I5VUH.js +0 -512
- package/dist/models-D4YDIQZQ.js +0 -289
- package/dist/monitor-NKVD55HX.js +0 -775
- package/dist/orchestrator-I6OATVPK.js +0 -39518
- package/dist/panes-7BTYH3XQ.js +0 -103
- package/dist/panes-WPOMEMRH.js +0 -74
- package/dist/paths-J3KN7UAO.js +0 -67
- package/dist/preload-EJAWJEIO.js +0 -116
- package/dist/reset-4XMQKDNZ.js +0 -345
- package/dist/resources-TVYVXK3Q.js +0 -125
- package/dist/run-OWQNNSJU.js +0 -872
- package/dist/share-NPZZMUXG.js +0 -290
- package/dist/skills-OXFEAWMT.js +0 -510
- package/dist/skills-eval-J5TCKSJA.js +0 -1034
- package/dist/skills-inventory-7II4DM57.js +0 -133
- package/dist/slash-commands-MDSDSWYF.js +0 -92
- package/dist/steer-S7D7IKPU.js +0 -77
- package/dist/support-5VAEC32W.js +0 -38
- package/dist/targets-KILZEOCE.js +0 -1109
- package/dist/tasks-R6P6OV22.js +0 -36
- package/dist/terminal-lease-LZCG2KN3.js +0 -405
- package/dist/tools-6OCQ6SVB.js +0 -28
- package/dist/trace-JHLXWUMN.js +0 -572
- package/dist/tui-primitives-RCY2HN7G.js +0 -17
- package/dist/uninstall-FXYMFFRT.js +0 -407
- package/dist/upgrade-D2OZH6IQ.js +0 -307
- package/dist/usage-PIASNUS4.js +0 -1052
- package/dist/verifiers-LTHUY2PX.js +0 -630
- package/dist/verify-HYF7KBVE.js +0 -30
- package/dist/web-fetch-MQN4FH3X.js +0 -788
- package/dist/wiki-generate-RK7JQ5NP.js +0 -615
- package/dist/with-panes-OFTNAR4Y.js +0 -628
- package/skills/README.md +0 -418
- package/skills/coding/ast-grep/SKILL.md +0 -213
- package/skills/coding/ast-grep/evals.md +0 -82
- package/skills/coding/coding-standards/SKILL.md +0 -164
- package/skills/coding/coding-standards/evals.md +0 -57
- package/skills/coding/prototype/SKILL.md +0 -151
- package/skills/coding/prototype/evals.md +0 -61
- package/skills/coding/tdd/SKILL.md +0 -134
- package/skills/coding/tdd/evals.md +0 -61
- package/skills/context/context-handoff/SKILL.md +0 -176
- package/skills/context/context-handoff/evals.md +0 -101
- package/skills/context/context-prime/SKILL.md +0 -131
- package/skills/context/context-prime/evals.md +0 -99
- package/skills/git/branch-closeout/SKILL.md +0 -132
- package/skills/git/file-ticket/SKILL.md +0 -126
- package/skills/git/fix-issue/SKILL.md +0 -136
- package/skills/git/resolve-merge-conflicts/SKILL.md +0 -151
- package/skills/git/resolve-merge-conflicts/evals.md +0 -85
- package/skills/git/ship/SKILL.md +0 -134
- package/skills/git/worktree-create/SKILL.md +0 -127
- package/skills/git/worktree-merge/SKILL.md +0 -147
- package/skills/meta/clio-coder-dev/SKILL.md +0 -101
- package/skills/meta/clio-coder-dev/evals.md +0 -46
- package/skills/meta/clio-coder-test/SKILL.md +0 -146
- package/skills/meta/clio-coder-test/evals.md +0 -48
- package/skills/meta/clio-coder-test/references/test-map.md +0 -96
- package/skills/meta/credentials/SKILL.md +0 -132
- package/skills/meta/credentials/evals.md +0 -104
- package/skills/meta/find-skills/SKILL.md +0 -78
- package/skills/meta/find-skills/evals.md +0 -47
- package/skills/meta/herdr/SKILL.md +0 -133
- package/skills/meta/herdr/evals.md +0 -38
- package/skills/meta/skill-craft/SKILL.md +0 -125
- package/skills/meta/skill-craft/evals.md +0 -41
- package/skills/planning/archify/SKILL.md +0 -196
- package/skills/planning/architecture/SKILL.md +0 -184
- package/skills/planning/architecture/evals.md +0 -101
- package/skills/planning/backlog/SKILL.md +0 -212
- package/skills/planning/backlog/evals.md +0 -185
- package/skills/planning/prd/SKILL.md +0 -129
- package/skills/planning/prd/evals.md +0 -103
- package/skills/planning/product-intent/SKILL.md +0 -173
- package/skills/planning/product-intent/evals.md +0 -106
- package/skills/planning/tech-spec/SKILL.md +0 -172
- package/skills/planning/tech-spec/evals.md +0 -120
- package/skills/registry.yaml +0 -144
- package/skills/remote.yaml +0 -13
- package/skills/research/arxiv-literature/SKILL.md +0 -168
- package/skills/research/arxiv-literature/evals.md +0 -108
- package/skills/research/experiment-protocol/SKILL.md +0 -148
- package/skills/research/experiment-protocol/evals.md +0 -114
- package/skills/research/scientific-debugging/SKILL.md +0 -149
- package/skills/research/scientific-debugging/evals.md +0 -156
- package/skills/research/scientific-modernization/SKILL.md +0 -170
- package/skills/research/scientific-modernization/evals.md +0 -111
- package/skills/skill-marketplace.json +0 -507
- package/skills/workflow/cut-it/SKILL.md +0 -153
- package/skills/workflow/cut-it/evals.md +0 -143
- package/skills/workflow/design-council/SKILL.md +0 -233
- package/skills/workflow/design-council/evals.md +0 -258
- package/skills/workflow/grill-me/SKILL.md +0 -267
- package/skills/workflow/grill-me/evals.md +0 -231
- package/skills/workflow/workflow-distiller/SKILL.md +0 -201
- package/skills/workflow/workflow-distiller/evals.md +0 -225
- package/src/domains/extensions/resource-path.ts +0 -27
- package/src/domains/extensions/resources.ts +0 -37
- package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +0 -27
- package/src/interactive/overlays/agents.ts +0 -70
- package/src/interactive/overlays/library-install-confirm.ts +0 -152
- package/src/interactive/overlays/prompts.ts +0 -89
- package/src/interactive/overlays/skills-hub.ts +0 -615
- /package/{skills → library/skills}/coding/ast-grep/references/rule_reference.md +0 -0
- /package/{skills → library/skills}/coding/prototype/references/LOGIC.md +0 -0
- /package/{skills → library/skills}/coding/prototype/references/UI.md +0 -0
- /package/{skills → library/skills}/coding/tdd/references/mocking.md +0 -0
- /package/{skills → library/skills}/coding/tdd/references/tests.md +0 -0
- /package/{skills → library/skills}/context/context-handoff/scripts/new-handoff.sh +0 -0
- /package/{skills → library/skills}/git/branch-closeout/evals.md +0 -0
- /package/{skills → library/skills}/git/branch-closeout/references/closeout-checklist.md +0 -0
- /package/{skills → library/skills}/git/file-ticket/assets/issue-template.md +0 -0
- /package/{skills → library/skills}/git/file-ticket/evals.md +0 -0
- /package/{skills → library/skills}/git/file-ticket/references/issue-discovery.md +0 -0
- /package/{skills → library/skills}/git/fix-issue/evals.md +0 -0
- /package/{skills → library/skills}/git/fix-issue/references/diagnosis-and-rca.md +0 -0
- /package/{skills → library/skills}/git/resolve-merge-conflicts/references/conflict-matrix.md +0 -0
- /package/{skills → library/skills}/git/ship/assets/pr-template.md +0 -0
- /package/{skills → library/skills}/git/ship/evals.md +0 -0
- /package/{skills → library/skills}/git/ship/references/remote-and-branch-policy.md +0 -0
- /package/{skills → library/skills}/git/worktree-create/evals.md +0 -0
- /package/{skills → library/skills}/git/worktree-create/references/worktree-setup.md +0 -0
- /package/{skills → library/skills}/git/worktree-merge/evals.md +0 -0
- /package/{skills → library/skills}/git/worktree-merge/references/merge-strategies.md +0 -0
- /package/{skills → library/skills}/meta/clio-coder-test/references/harness.md +0 -0
- /package/{skills → library/skills}/planning/archify/evals.md +0 -0
package/dist/chunk-BT7HGDOX.js
DELETED
|
@@ -1,3151 +0,0 @@
|
|
|
1
|
-
import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
TASK_MEMORY_DEFAULT_PROCEDURAL_CAP,
|
|
4
|
-
TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS,
|
|
5
|
-
isTerminalRunEnvelope,
|
|
6
|
-
runTaskMemoryPolicy,
|
|
7
|
-
taskMemoryBankDelta
|
|
8
|
-
} from "./chunk-P5JMBPDJ.js";
|
|
9
|
-
import {
|
|
10
|
-
taskBoardCounts
|
|
11
|
-
} from "./chunk-YPRSNUTC.js";
|
|
12
|
-
import {
|
|
13
|
-
legacyToolResultDigest,
|
|
14
|
-
sanitizeToolResultDigest
|
|
15
|
-
} from "./chunk-7JSSKXG2.js";
|
|
16
|
-
import {
|
|
17
|
-
INSTRUCTION_SHAPED_WARNING
|
|
18
|
-
} from "./chunk-WXA2CFJO.js";
|
|
19
|
-
import {
|
|
20
|
-
SKILL_INSTALL_OFFER_OPTION_NEVER,
|
|
21
|
-
SKILL_INSTALL_OFFER_OPTION_NOT_NOW,
|
|
22
|
-
SKILL_INSTALL_OFFER_OPTION_PROJECT,
|
|
23
|
-
SKILL_INSTALL_OFFER_OPTION_USER,
|
|
24
|
-
SKILL_SUGGESTION_ANCHOR,
|
|
25
|
-
SKILL_SUGGESTION_PREFIX
|
|
26
|
-
} from "./chunk-KAFMW7WM.js";
|
|
27
|
-
import {
|
|
28
|
-
hashToolCall
|
|
29
|
-
} from "./chunk-I2K2NCZQ.js";
|
|
30
|
-
import {
|
|
31
|
-
captureProjectSurface,
|
|
32
|
-
projectSurfaceTrustNotice
|
|
33
|
-
} from "./chunk-NTK3WTHM.js";
|
|
34
|
-
import {
|
|
35
|
-
registerForegroundStream
|
|
36
|
-
} from "./chunk-4U4TKZFR.js";
|
|
37
|
-
import {
|
|
38
|
-
ceilChars
|
|
39
|
-
} from "./chunk-77CZRFTE.js";
|
|
40
|
-
import {
|
|
41
|
-
ToolNames
|
|
42
|
-
} from "./chunk-EHOSNVVM.js";
|
|
43
|
-
import {
|
|
44
|
-
BusChannels
|
|
45
|
-
} from "./chunk-HL26ADLH.js";
|
|
46
|
-
import {
|
|
47
|
-
buildSafeToolEnv
|
|
48
|
-
} from "./chunk-GJ24ODAX.js";
|
|
49
|
-
import {
|
|
50
|
-
gitCommitAttributionEnabled,
|
|
51
|
-
reportCommitAttributionDiagnostic,
|
|
52
|
-
withManagedGitCommitAttributionEnvironment
|
|
53
|
-
} from "./chunk-LTR5QCLS.js";
|
|
54
|
-
import {
|
|
55
|
-
require_dist
|
|
56
|
-
} from "./chunk-B5GGDIHT.js";
|
|
57
|
-
import {
|
|
58
|
-
safeResourceWrite
|
|
59
|
-
} from "./chunk-ZZFWWYLX.js";
|
|
60
|
-
import {
|
|
61
|
-
clioConfigDir
|
|
62
|
-
} from "./chunk-CTTI7G3T.js";
|
|
63
|
-
import {
|
|
64
|
-
__toESM,
|
|
65
|
-
init_esm_shims
|
|
66
|
-
} from "./chunk-ECBHH7LU.js";
|
|
67
|
-
|
|
68
|
-
// src/domains/middleware/runtime.ts
|
|
69
|
-
init_esm_shims();
|
|
70
|
-
|
|
71
|
-
// src/domains/middleware/budget.ts
|
|
72
|
-
init_esm_shims();
|
|
73
|
-
|
|
74
|
-
// src/domains/middleware/types.ts
|
|
75
|
-
init_esm_shims();
|
|
76
|
-
var MIDDLEWARE_HOOKS = ["before_tool", "after_tool", "turn_start", "turn_end", "on_compaction"];
|
|
77
|
-
var MIDDLEWARE_EFFECT_KINDS = [
|
|
78
|
-
"inject_reminder",
|
|
79
|
-
"annotate_tool_result",
|
|
80
|
-
"block_tool",
|
|
81
|
-
"protect_path",
|
|
82
|
-
"request_continuation",
|
|
83
|
-
"require_tool",
|
|
84
|
-
"lock_tools"
|
|
85
|
-
];
|
|
86
|
-
var MIDDLEWARE_REMINDER_SEVERITIES = ["info", "advisory", "warn", "hard-block"];
|
|
87
|
-
var MIDDLEWARE_ANNOTATION_SEVERITIES = ["info", "warn"];
|
|
88
|
-
var MIDDLEWARE_HOOK_TEXT_MAX_CHARS = 16e3;
|
|
89
|
-
function metadataNumber(input, key) {
|
|
90
|
-
const value = input.metadata?.[key];
|
|
91
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
92
|
-
}
|
|
93
|
-
function metadataString(input, key) {
|
|
94
|
-
const value = input.metadata?.[key];
|
|
95
|
-
return typeof value === "string" ? value : null;
|
|
96
|
-
}
|
|
97
|
-
function isMiddlewareHook(value) {
|
|
98
|
-
return MIDDLEWARE_HOOKS.includes(value);
|
|
99
|
-
}
|
|
100
|
-
function isMiddlewareEffectKind(value) {
|
|
101
|
-
return MIDDLEWARE_EFFECT_KINDS.includes(value);
|
|
102
|
-
}
|
|
103
|
-
function isMiddlewareReminderSeverity(value) {
|
|
104
|
-
return MIDDLEWARE_REMINDER_SEVERITIES.includes(value);
|
|
105
|
-
}
|
|
106
|
-
function isMiddlewareAnnotationSeverity(value) {
|
|
107
|
-
return MIDDLEWARE_ANNOTATION_SEVERITIES.includes(value);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// src/domains/middleware/budget.ts
|
|
111
|
-
var DEFAULT_MIDDLEWARE_HOOK_BUDGETS_MS = {
|
|
112
|
-
before_tool: 25,
|
|
113
|
-
after_tool: 25,
|
|
114
|
-
turn_start: 50,
|
|
115
|
-
turn_end: 75,
|
|
116
|
-
on_compaction: 150
|
|
117
|
-
};
|
|
118
|
-
var DEFAULT_HOOK_BUDGET_WARMUP_CALLS = 1;
|
|
119
|
-
var DEFAULT_HOOK_BUDGET_WINDOW = 5;
|
|
120
|
-
var DEFAULT_HOOK_BUDGET_THRESHOLD = 3;
|
|
121
|
-
function parsePositiveMs(raw) {
|
|
122
|
-
if (raw === void 0) return null;
|
|
123
|
-
const value = Number(raw);
|
|
124
|
-
return Number.isFinite(value) && value > 0 ? value : null;
|
|
125
|
-
}
|
|
126
|
-
function parsePositiveInt(raw) {
|
|
127
|
-
if (raw === void 0) return null;
|
|
128
|
-
const value = Number(raw);
|
|
129
|
-
return Number.isInteger(value) && value > 0 ? value : null;
|
|
130
|
-
}
|
|
131
|
-
function parseNonNegativeInt(raw) {
|
|
132
|
-
if (raw === void 0) return null;
|
|
133
|
-
const value = Number(raw);
|
|
134
|
-
return Number.isInteger(value) && value >= 0 ? value : null;
|
|
135
|
-
}
|
|
136
|
-
function hookEnvSuffix(hook) {
|
|
137
|
-
return hook.toUpperCase();
|
|
138
|
-
}
|
|
139
|
-
function resolveHookBudgetsFromEnv(env = process.env) {
|
|
140
|
-
const global = parsePositiveMs(env.CLIO_CODER_HOOK_BUDGET_MS);
|
|
141
|
-
const map = {};
|
|
142
|
-
for (const hook of MIDDLEWARE_HOOKS) {
|
|
143
|
-
const perPhase = parsePositiveMs(env[`CLIO_CODER_HOOK_BUDGET_${hookEnvSuffix(hook)}_MS`]);
|
|
144
|
-
map[hook] = perPhase ?? global ?? DEFAULT_MIDDLEWARE_HOOK_BUDGETS_MS[hook];
|
|
145
|
-
}
|
|
146
|
-
return map;
|
|
147
|
-
}
|
|
148
|
-
function resolveHookBudgetTunablesFromEnv(env = process.env) {
|
|
149
|
-
return {
|
|
150
|
-
warmupCalls: parseNonNegativeInt(env.CLIO_CODER_HOOK_BUDGET_WARMUP_CALLS) ?? DEFAULT_HOOK_BUDGET_WARMUP_CALLS,
|
|
151
|
-
windowSize: parsePositiveInt(env.CLIO_CODER_HOOK_BUDGET_WINDOW) ?? DEFAULT_HOOK_BUDGET_WINDOW,
|
|
152
|
-
threshold: parsePositiveInt(env.CLIO_CODER_HOOK_BUDGET_THRESHOLD) ?? DEFAULT_HOOK_BUDGET_THRESHOLD
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function percentile(sortedAscending, p) {
|
|
156
|
-
if (sortedAscending.length === 0) return 0;
|
|
157
|
-
const rank = Math.ceil(p / 100 * sortedAscending.length);
|
|
158
|
-
const index = Math.min(sortedAscending.length - 1, Math.max(0, rank - 1));
|
|
159
|
-
return sortedAscending[index] ?? 0;
|
|
160
|
-
}
|
|
161
|
-
function createHookBudgetTracker(options = {}) {
|
|
162
|
-
const budgets = { ...DEFAULT_MIDDLEWARE_HOOK_BUDGETS_MS, ...options.budgets ?? {} };
|
|
163
|
-
const warmupCalls = Math.max(0, options.warmupCalls ?? DEFAULT_HOOK_BUDGET_WARMUP_CALLS);
|
|
164
|
-
const windowSize = Math.max(1, options.windowSize ?? DEFAULT_HOOK_BUDGET_WINDOW);
|
|
165
|
-
const threshold = Math.min(windowSize, Math.max(1, options.threshold ?? DEFAULT_HOOK_BUDGET_THRESHOLD));
|
|
166
|
-
const states = /* @__PURE__ */ new Map();
|
|
167
|
-
function statsFor(state, budgetMs) {
|
|
168
|
-
const sorted = [...state.window].sort((a, b) => a - b);
|
|
169
|
-
const overCount = state.window.reduce((count, ms) => ms > budgetMs ? count + 1 : count, 0);
|
|
170
|
-
return {
|
|
171
|
-
sampleCount: state.postWarmupCalls,
|
|
172
|
-
window: state.window.length,
|
|
173
|
-
overCount,
|
|
174
|
-
p50Ms: percentile(sorted, 50),
|
|
175
|
-
p95Ms: percentile(sorted, 95)
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
return {
|
|
179
|
-
budgetFor(hook) {
|
|
180
|
-
return budgets[hook];
|
|
181
|
-
},
|
|
182
|
-
record(registrationId, hook, elapsedMs) {
|
|
183
|
-
const budgetMs = budgets[hook];
|
|
184
|
-
const exceeded = elapsedMs > budgetMs;
|
|
185
|
-
const key = `${registrationId}\0${hook}`;
|
|
186
|
-
let state = states.get(key);
|
|
187
|
-
if (state === void 0) {
|
|
188
|
-
state = { calls: 0, postWarmupCalls: 0, window: [] };
|
|
189
|
-
states.set(key, state);
|
|
190
|
-
}
|
|
191
|
-
state.calls += 1;
|
|
192
|
-
if (state.calls <= warmupCalls) {
|
|
193
|
-
return {
|
|
194
|
-
budgetMs,
|
|
195
|
-
exceeded,
|
|
196
|
-
warmup: true,
|
|
197
|
-
warn: false,
|
|
198
|
-
stats: { sampleCount: 0, window: 0, overCount: 0, p50Ms: 0, p95Ms: 0 }
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
state.postWarmupCalls += 1;
|
|
202
|
-
state.window.push(elapsedMs);
|
|
203
|
-
if (state.window.length > windowSize) state.window.shift();
|
|
204
|
-
const stats = statsFor(state, budgetMs);
|
|
205
|
-
return {
|
|
206
|
-
budgetMs,
|
|
207
|
-
exceeded,
|
|
208
|
-
warmup: false,
|
|
209
|
-
warn: exceeded && stats.overCount >= threshold,
|
|
210
|
-
stats
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// src/domains/middleware/rules.ts
|
|
217
|
-
init_esm_shims();
|
|
218
|
-
|
|
219
|
-
// src/domains/middleware/injection-screen.ts
|
|
220
|
-
init_esm_shims();
|
|
221
|
-
var INJECTION_SCREEN_RULE = {
|
|
222
|
-
rule: {
|
|
223
|
-
id: "safety.untrusted-instructions",
|
|
224
|
-
source: "builtin",
|
|
225
|
-
description: "Warn when external tool data contains instruction-shaped markers",
|
|
226
|
-
enabled: true,
|
|
227
|
-
hooks: ["after_tool"],
|
|
228
|
-
effectKinds: ["annotate_tool_result"]
|
|
229
|
-
},
|
|
230
|
-
toolNames: ["web_fetch", "read", "bash", "dispatch", "monitor"],
|
|
231
|
-
predicate: (input) => input.metadata?.untrustedInstructionMarkers === true,
|
|
232
|
-
effects: [
|
|
233
|
-
{
|
|
234
|
-
kind: "annotate_tool_result",
|
|
235
|
-
severity: "warn",
|
|
236
|
-
message: INSTRUCTION_SHAPED_WARNING
|
|
237
|
-
}
|
|
238
|
-
]
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
// src/domains/middleware/stalled-turn.ts
|
|
242
|
-
init_esm_shims();
|
|
243
|
-
var STALLED_TURN_REGISTRATION_ID = "nudge.stalled-turn";
|
|
244
|
-
var STALLED_TURN_REQUEST_CONTINUATION_MESSAGE = "You ended your turn after announcing an action without executing it: no tools were called. Continue now and perform the announced action, or state plainly that you are finished and waiting for the user.";
|
|
245
|
-
var SKILL_SUGGESTION_WAIT_CONTINUATION_MESSAGE = "You ended your turn on a skill suggestion without doing the task. The suggestion line has already made the offer and only the operator loads a skill, so the skill choice needs nothing from them before you proceed. Continue the already-authorized task now without the skill. This continuation is not an operator answer to any other question: if the remaining work is a proposal awaiting an explicit operator go-ahead, park it on the task board and say so instead of implementing.";
|
|
246
|
-
var INTENT_PATTERN = /\b(let me|i['’]ll|i will|i am going to|i['’]m going to|now i|next i|let's|let us)\b/i;
|
|
247
|
-
var CONCRETE_ACTION_STEMS = [
|
|
248
|
-
"add",
|
|
249
|
-
"analyse",
|
|
250
|
-
"analyze",
|
|
251
|
-
"apply",
|
|
252
|
-
"audit",
|
|
253
|
-
"build",
|
|
254
|
-
"change",
|
|
255
|
-
"check",
|
|
256
|
-
"compare",
|
|
257
|
-
"compile",
|
|
258
|
-
"create",
|
|
259
|
-
"debug",
|
|
260
|
-
"delete",
|
|
261
|
-
"edit",
|
|
262
|
-
"execute",
|
|
263
|
-
"explore",
|
|
264
|
-
"find",
|
|
265
|
-
"fix",
|
|
266
|
-
"format",
|
|
267
|
-
"grep",
|
|
268
|
-
"implement",
|
|
269
|
-
"inspect",
|
|
270
|
-
"install",
|
|
271
|
-
"investigate",
|
|
272
|
-
"list",
|
|
273
|
-
"load",
|
|
274
|
-
"look",
|
|
275
|
-
"modify",
|
|
276
|
-
"open",
|
|
277
|
-
"patch",
|
|
278
|
-
"query",
|
|
279
|
-
"read",
|
|
280
|
-
"refactor",
|
|
281
|
-
"remove",
|
|
282
|
-
"rename",
|
|
283
|
-
"replace",
|
|
284
|
-
"review",
|
|
285
|
-
"run",
|
|
286
|
-
"scan",
|
|
287
|
-
"search",
|
|
288
|
-
"test",
|
|
289
|
-
"trace",
|
|
290
|
-
"update",
|
|
291
|
-
"validate",
|
|
292
|
-
"verify",
|
|
293
|
-
"write"
|
|
294
|
-
];
|
|
295
|
-
var DOUBLED_CONSONANT_STEMS = /* @__PURE__ */ new Set(["debug", "format", "run", "scan"]);
|
|
296
|
-
function concreteActionForms(stem) {
|
|
297
|
-
const forms = /* @__PURE__ */ new Set([stem, `${stem}s`, `${stem}ed`, `${stem}ing`]);
|
|
298
|
-
if (/(?:ch|sh|s|x|z)$/.test(stem)) forms.add(`${stem}es`);
|
|
299
|
-
if (stem.endsWith("e")) {
|
|
300
|
-
forms.add(`${stem}d`);
|
|
301
|
-
forms.add(`${stem.slice(0, -1)}ing`);
|
|
302
|
-
}
|
|
303
|
-
if (stem.endsWith("y")) {
|
|
304
|
-
forms.add(`${stem.slice(0, -1)}ies`);
|
|
305
|
-
forms.add(`${stem.slice(0, -1)}ied`);
|
|
306
|
-
}
|
|
307
|
-
if (DOUBLED_CONSONANT_STEMS.has(stem)) {
|
|
308
|
-
const doubled = `${stem}${stem.slice(-1)}`;
|
|
309
|
-
forms.add(`${doubled}ed`);
|
|
310
|
-
forms.add(`${doubled}ing`);
|
|
311
|
-
}
|
|
312
|
-
return [...forms];
|
|
313
|
-
}
|
|
314
|
-
var CONCRETE_ACTION_PATTERN = new RegExp(
|
|
315
|
-
`\\b(?:${CONCRETE_ACTION_STEMS.flatMap(concreteActionForms).join("|")})\\b`,
|
|
316
|
-
"giu"
|
|
317
|
-
);
|
|
318
|
-
var NAMED_PATH_EXTENSIONS = "c|cc|cfg|cjs|cmake|conf|cpp|cs|css|csv|env|go|h|hpp|html|ini|java|jl|js|json|jsx|lock|log|lua|md|mjs|nc|php|py|rb|rs|rst|sh|sql|toml|ts|tsx|txt|yaml|yml";
|
|
319
|
-
var NAMED_PATH_PATTERN = new RegExp(
|
|
320
|
-
`(?:^|[\\s\`"'(\\[])(?:[\\w@.\\-/]*[\\w@\\-]\\.(?:${NAMED_PATH_EXTENSIONS})\\b|(?:\\.{1,2}|~)\\/[\\w@.\\-/]+)`,
|
|
321
|
-
"iu"
|
|
322
|
-
);
|
|
323
|
-
var NAMED_COMMAND_PATTERN = /\b(?:npm|npx|pnpm|yarn|bun|git|cargo|rustc|cmake|ctest|ninja|meson|bazel|gradle|mvn|pytest|pip|python3?|node|deno|tsc|biome|eslint|prettier|jest|vitest|ruff|mypy|docker|kubectl|mpirun|srun|sbatch|gcc|clang)\s+[-\w./]/iu;
|
|
324
|
-
var ACTION_OBJECT_CONNECTOR_PATTERN = /^(?:at|for|in|into|on|through|to)\s+/i;
|
|
325
|
-
var ACTION_OBJECT_DETERMINER_PATTERN = /^(?:a|an|my|our|that|the|their|these|this|those|your)\s+/i;
|
|
326
|
-
var ACTION_OBJECT_PATTERN = /^(?!(?:again|everyone|later|next|now|soon|then|you)\b)[`"'./~]*[\p{L}\p{N}_-]/iu;
|
|
327
|
-
var CONDITIONAL_LEAD_IN_PATTERN = /\b(?:if|once|unless|until|when|whenever)\b/i;
|
|
328
|
-
var CONDITIONAL_INVITATION_PATTERN = /\b(?:answer|approve|ask|confirm|give|point|reply|respond|say|send|share|tell|type)\b[\s\S]*\b(?:and|then)\s*$/i;
|
|
329
|
-
var CONDITIONAL_OFFER_SUFFIX_PATTERN = /\b(?:if\s+(?:needed|necessary|requested|approved|confirmed)\b|(?:if|after|once|until|unless|when(?:ever)?|as\s+soon\s+as|provided|assuming)\b[^.!?]*\byou\b|(?:upon|on|after|with|pending|awaiting|following)\s+(?:your\s+|the\s+operator(?:'s)?\s+)?(?:approval|go-?ahead|confirmation|sign-?off|decision|word|green\s+light|okay|ok)\b)/i;
|
|
330
|
-
var OPERATOR_WAIT_LEAD_PATTERN = /\b(?:await(?:ing)?|pending|waiting\s+(?:for|on))\b/i;
|
|
331
|
-
var NEGATED_OR_HYPOTHETICAL_CLAUSE_PATTERN = /^\s*(?:not|never|would|could|might|may)\b/i;
|
|
332
|
-
var LET_ME_KNOW_PATTERN = /\blet me know\b/i;
|
|
333
|
-
var DEFERRAL_LEAD_PATTERN = /^\s*(?:just\s+|simply\s+|now\s+)?(?:wait|hold\s+off|hold|stand\s+by|pause|defer)\b/i;
|
|
334
|
-
var COMPLETION_PATTERN = /^\s*(?:all\s+done|done|complete|completed|all\s+set)\b|^\s*(?:here(?:'s| is)\s+)?(?:a\s+)?summary\b|^\s*summary\s*:?$/i;
|
|
335
|
-
var STALLED_TURN_RULE_DEFINITION = {
|
|
336
|
-
rule: {
|
|
337
|
-
id: STALLED_TURN_REGISTRATION_ID,
|
|
338
|
-
source: "builtin",
|
|
339
|
-
description: "request an automatic continuation when a turn announces work but calls no tools",
|
|
340
|
-
enabled: true,
|
|
341
|
-
hooks: ["turn_end"],
|
|
342
|
-
effectKinds: ["request_continuation"]
|
|
343
|
-
},
|
|
344
|
-
effects: [{ kind: "request_continuation", message: STALLED_TURN_REQUEST_CONTINUATION_MESSAGE }],
|
|
345
|
-
predicate: shouldRequestStalledTurnContinuation
|
|
346
|
-
};
|
|
347
|
-
var SKILL_WAIT_PATTERN = /\/skill\b|\bskills?\b|\bskip\b/i;
|
|
348
|
-
function isSkillSuggestionWait(input) {
|
|
349
|
-
if (input.hook !== "turn_end") return false;
|
|
350
|
-
if (!isNormalStopReason(input.metadata?.stopReason)) return false;
|
|
351
|
-
const text = input.text ?? "";
|
|
352
|
-
if (!text.includes(SKILL_SUGGESTION_PREFIX)) return false;
|
|
353
|
-
const toolNames = metadataString(input, "turnToolNames");
|
|
354
|
-
if (toolNames === null) {
|
|
355
|
-
if ((metadataNumber(input, "turnToolCalls") ?? 0) !== 0) return false;
|
|
356
|
-
} else if (toolNames.split(",").filter((name) => name.length > 0).some((name) => name !== ToolNames.Context)) {
|
|
357
|
-
return false;
|
|
358
|
-
}
|
|
359
|
-
const lastLine = lastNonEmptyLine(text);
|
|
360
|
-
if (lastLine === null) return false;
|
|
361
|
-
const finalSentence = lastSentence(lastLine);
|
|
362
|
-
if (finalSentence.length === 0) return false;
|
|
363
|
-
return SKILL_WAIT_PATTERN.test(finalSentence) || isQuestion(finalSentence) || LET_ME_KNOW_PATTERN.test(finalSentence);
|
|
364
|
-
}
|
|
365
|
-
function shouldRequestStalledTurnContinuation(input) {
|
|
366
|
-
if (input.hook !== "turn_end") return false;
|
|
367
|
-
if (input.metadata?.turnToolCalls !== 0) return false;
|
|
368
|
-
if (!isNormalStopReason(input.metadata?.stopReason)) return false;
|
|
369
|
-
const lastLine = lastNonEmptyLine(input.text ?? "");
|
|
370
|
-
if (lastLine === null) return false;
|
|
371
|
-
const finalSentence = lastSentence(lastLine);
|
|
372
|
-
if (finalSentence.length === 0) return false;
|
|
373
|
-
if (isQuestion(finalSentence)) return false;
|
|
374
|
-
if (LET_ME_KNOW_PATTERN.test(finalSentence)) return false;
|
|
375
|
-
if (COMPLETION_PATTERN.test(lastLine) || COMPLETION_PATTERN.test(finalSentence)) return false;
|
|
376
|
-
return announcesConcreteAction(finalSentence);
|
|
377
|
-
}
|
|
378
|
-
function announcesConcreteAction(sentence) {
|
|
379
|
-
const intent = INTENT_PATTERN.exec(sentence);
|
|
380
|
-
if (intent) {
|
|
381
|
-
const leadIn = sentence.slice(0, intent.index);
|
|
382
|
-
if (CONDITIONAL_LEAD_IN_PATTERN.test(leadIn) || CONDITIONAL_INVITATION_PATTERN.test(leadIn) || OPERATOR_WAIT_LEAD_PATTERN.test(leadIn) || CONDITIONAL_OFFER_SUFFIX_PATTERN.test(sentence)) {
|
|
383
|
-
return false;
|
|
384
|
-
}
|
|
385
|
-
const clause = sentence.slice(intent.index + intent[0].length);
|
|
386
|
-
if (DEFERRAL_LEAD_PATTERN.test(clause)) return false;
|
|
387
|
-
if (NEGATED_OR_HYPOTHETICAL_CLAUSE_PATTERN.test(clause)) return false;
|
|
388
|
-
if (hasActionWithObject(clause)) return true;
|
|
389
|
-
if (CONDITIONAL_LEAD_IN_PATTERN.test(clause)) return false;
|
|
390
|
-
return namesToolTarget(clause);
|
|
391
|
-
}
|
|
392
|
-
return sentence.endsWith(":") && hasActionWithObject(sentence);
|
|
393
|
-
}
|
|
394
|
-
function namesToolTarget(clause) {
|
|
395
|
-
return NAMED_PATH_PATTERN.test(clause) || NAMED_COMMAND_PATTERN.test(clause);
|
|
396
|
-
}
|
|
397
|
-
function hasActionWithObject(clause) {
|
|
398
|
-
for (const action of clause.matchAll(CONCRETE_ACTION_PATTERN)) {
|
|
399
|
-
const remainder = clause.slice((action.index ?? 0) + action[0].length).trimStart();
|
|
400
|
-
const withoutConnector = remainder.replace(ACTION_OBJECT_CONNECTOR_PATTERN, "");
|
|
401
|
-
const object = withoutConnector.replace(ACTION_OBJECT_DETERMINER_PATTERN, "");
|
|
402
|
-
if (ACTION_OBJECT_PATTERN.test(object)) return true;
|
|
403
|
-
}
|
|
404
|
-
return false;
|
|
405
|
-
}
|
|
406
|
-
function isNormalStopReason(value) {
|
|
407
|
-
if (value === void 0 || value === null) return true;
|
|
408
|
-
if (typeof value !== "string") return false;
|
|
409
|
-
const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
410
|
-
return normalized === "stop" || normalized === "end_turn" || normalized.startsWith("stop_sequence");
|
|
411
|
-
}
|
|
412
|
-
function lastNonEmptyLine(text) {
|
|
413
|
-
const lines = text.split(/\r?\n/);
|
|
414
|
-
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
415
|
-
const line = lines[index]?.trim();
|
|
416
|
-
if (line && line.length > 0) return line;
|
|
417
|
-
}
|
|
418
|
-
return null;
|
|
419
|
-
}
|
|
420
|
-
var SENTENCE_TERMINATOR_PATTERN = /[.!?]+["'’)\]]*(?=\s|$)/gu;
|
|
421
|
-
function lastSentence(line) {
|
|
422
|
-
const trimmed = line.trimEnd();
|
|
423
|
-
let start = 0;
|
|
424
|
-
for (const terminator of trimmed.matchAll(SENTENCE_TERMINATOR_PATTERN)) {
|
|
425
|
-
const end = (terminator.index ?? 0) + terminator[0].length;
|
|
426
|
-
if (end >= trimmed.length) break;
|
|
427
|
-
start = end;
|
|
428
|
-
}
|
|
429
|
-
return trimmed.slice(start).replace(/^[\s"'([{-]+/, "").trim();
|
|
430
|
-
}
|
|
431
|
-
function isQuestion(sentence) {
|
|
432
|
-
return /[?]["')\]]*$/.test(sentence.trim());
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// src/domains/middleware/rules.ts
|
|
436
|
-
var BUILTIN_MIDDLEWARE_RULE_DEFINITIONS = [
|
|
437
|
-
STALLED_TURN_RULE_DEFINITION,
|
|
438
|
-
INJECTION_SCREEN_RULE
|
|
439
|
-
];
|
|
440
|
-
var BUILTIN_MIDDLEWARE_RULE_IDS = BUILTIN_MIDDLEWARE_RULE_DEFINITIONS.map((definition) => definition.rule.id);
|
|
441
|
-
function listMiddlewareRuleDefinitions() {
|
|
442
|
-
return BUILTIN_MIDDLEWARE_RULE_DEFINITIONS.map(cloneRuleDefinition);
|
|
443
|
-
}
|
|
444
|
-
function listMiddlewareRules() {
|
|
445
|
-
return BUILTIN_MIDDLEWARE_RULE_DEFINITIONS.map((definition) => cloneMiddlewareRule(definition.rule));
|
|
446
|
-
}
|
|
447
|
-
function cloneMiddlewareRule(rule) {
|
|
448
|
-
return {
|
|
449
|
-
id: rule.id,
|
|
450
|
-
source: rule.source,
|
|
451
|
-
description: rule.description,
|
|
452
|
-
enabled: rule.enabled,
|
|
453
|
-
hooks: [...rule.hooks],
|
|
454
|
-
effectKinds: [...rule.effectKinds]
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
function cloneRuleDefinition(definition) {
|
|
458
|
-
const cloned = {
|
|
459
|
-
rule: cloneMiddlewareRule(definition.rule),
|
|
460
|
-
effects: [...definition.effects]
|
|
461
|
-
};
|
|
462
|
-
if (definition.toolNames !== void 0) cloned.toolNames = [...definition.toolNames];
|
|
463
|
-
if (definition.predicate !== void 0) cloned.predicate = definition.predicate;
|
|
464
|
-
return cloned;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// src/domains/middleware/runtime.ts
|
|
468
|
-
function writeMiddlewareDiagnosticToStderr(diagnostic) {
|
|
469
|
-
if (diagnostic.kind === "hook_failed") {
|
|
470
|
-
process.stderr.write(
|
|
471
|
-
`[clio-coder:middleware] registration '${diagnostic.registrationId}' failed on '${diagnostic.hook}': ${diagnostic.message}
|
|
472
|
-
`
|
|
473
|
-
);
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
if (diagnostic.kind === "registration_conflict") {
|
|
477
|
-
process.stderr.write(`[clio-coder:middleware] ${formatRegistrationConflict(diagnostic)}
|
|
478
|
-
`);
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
if (!diagnostic.steadyStateWarn && process.env.CLIO_CODER_HOOK_BUDGET_DEBUG !== "1") return;
|
|
482
|
-
const stats = diagnostic.stats;
|
|
483
|
-
const trend = stats.window > 0 ? ` (slow on ${stats.overCount}/${stats.window} recent ${diagnostic.hook} calls, p95 ${stats.p95Ms.toFixed(1)}ms)` : "";
|
|
484
|
-
process.stderr.write(
|
|
485
|
-
`[clio-coder:middleware] registration '${diagnostic.registrationId}' exceeded budget on '${diagnostic.hook}': ${diagnostic.elapsedMs.toFixed(1)}ms > ${diagnostic.budgetMs}ms${trend}
|
|
486
|
-
`
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
function formatRegistrationConflict(diagnostic) {
|
|
490
|
-
return diagnostic.action === "dropped" ? `${diagnostic.owner} registration '${diagnostic.registrationId}' (generation ${diagnostic.generation}) dropped: id is held by a ${diagnostic.conflictsWith} registration` : `${diagnostic.owner} registration '${diagnostic.registrationId}' (generation ${diagnostic.generation}) evicted by a ${diagnostic.conflictsWith} registration with the same id`;
|
|
491
|
-
}
|
|
492
|
-
function registrationFromRuleDefinition(definition) {
|
|
493
|
-
const registration = {
|
|
494
|
-
id: definition.rule.id,
|
|
495
|
-
description: definition.rule.description,
|
|
496
|
-
hooks: [...definition.rule.hooks],
|
|
497
|
-
evaluate: (input) => evaluateRuleDefinition(definition, input)
|
|
498
|
-
};
|
|
499
|
-
if (definition.toolNames !== void 0) registration.toolNames = [...definition.toolNames];
|
|
500
|
-
return registration;
|
|
501
|
-
}
|
|
502
|
-
function runMiddlewareRegistrations(input, registrations, options = {}) {
|
|
503
|
-
const onDiagnostic = options.onDiagnostic ?? writeMiddlewareDiagnosticToStderr;
|
|
504
|
-
const now = options.now ?? (() => performance.now());
|
|
505
|
-
const budgetTracker = options.budgetTracker ?? createHookBudgetTracker();
|
|
506
|
-
const effects = [];
|
|
507
|
-
const ruleIds = [];
|
|
508
|
-
for (const registration of registrations) {
|
|
509
|
-
if (!registration.hooks.includes(input.hook)) continue;
|
|
510
|
-
if (registration.toolNames !== void 0) {
|
|
511
|
-
if (input.toolName === void 0) continue;
|
|
512
|
-
if (!registration.toolNames.includes(input.toolName)) continue;
|
|
513
|
-
}
|
|
514
|
-
let emitted;
|
|
515
|
-
const startedAt = now();
|
|
516
|
-
try {
|
|
517
|
-
emitted = registration.evaluate(cloneHookInput(input), { priorEffects: [...effects] });
|
|
518
|
-
} catch (err) {
|
|
519
|
-
emitDiagnostic(onDiagnostic, {
|
|
520
|
-
kind: "hook_failed",
|
|
521
|
-
registrationId: registration.id,
|
|
522
|
-
hook: input.hook,
|
|
523
|
-
message: err instanceof Error ? err.message : String(err)
|
|
524
|
-
});
|
|
525
|
-
continue;
|
|
526
|
-
}
|
|
527
|
-
const elapsedMs = now() - startedAt;
|
|
528
|
-
const outcome = budgetTracker.record(registration.id, input.hook, elapsedMs);
|
|
529
|
-
if (outcome.exceeded && !outcome.warmup) {
|
|
530
|
-
emitDiagnostic(onDiagnostic, {
|
|
531
|
-
kind: "budget_exceeded",
|
|
532
|
-
registrationId: registration.id,
|
|
533
|
-
hook: input.hook,
|
|
534
|
-
elapsedMs,
|
|
535
|
-
budgetMs: outcome.budgetMs,
|
|
536
|
-
steadyStateWarn: outcome.warn,
|
|
537
|
-
stats: outcome.stats
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
if (emitted.length === 0) continue;
|
|
541
|
-
for (const effect of emitted) {
|
|
542
|
-
effects.push(cloneMiddlewareEffect(effect));
|
|
543
|
-
}
|
|
544
|
-
if (!ruleIds.includes(registration.id)) ruleIds.push(registration.id);
|
|
545
|
-
}
|
|
546
|
-
return {
|
|
547
|
-
hook: input.hook,
|
|
548
|
-
input: cloneHookInput(input),
|
|
549
|
-
effects,
|
|
550
|
-
ruleIds
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
async function runMiddlewareAsyncRegistrations(input, registrations, priorEffects = [], options = {}) {
|
|
554
|
-
const onDiagnostic = options.onDiagnostic ?? writeMiddlewareDiagnosticToStderr;
|
|
555
|
-
const effects = [];
|
|
556
|
-
const ruleIds = [];
|
|
557
|
-
for (const registration of registrations) {
|
|
558
|
-
if (registration.evaluateAsync === void 0 || !registration.hooks.includes(input.hook)) continue;
|
|
559
|
-
if (registration.toolNames !== void 0) {
|
|
560
|
-
if (input.toolName === void 0 || !registration.toolNames.includes(input.toolName)) continue;
|
|
561
|
-
}
|
|
562
|
-
let emitted;
|
|
563
|
-
try {
|
|
564
|
-
emitted = await registration.evaluateAsync(cloneHookInput(input), {
|
|
565
|
-
priorEffects: [...priorEffects, ...effects]
|
|
566
|
-
});
|
|
567
|
-
} catch (err) {
|
|
568
|
-
emitDiagnostic(onDiagnostic, {
|
|
569
|
-
kind: "hook_failed",
|
|
570
|
-
registrationId: registration.id,
|
|
571
|
-
hook: input.hook,
|
|
572
|
-
message: err instanceof Error ? err.message : String(err)
|
|
573
|
-
});
|
|
574
|
-
continue;
|
|
575
|
-
}
|
|
576
|
-
for (const effect of emitted) effects.push(cloneMiddlewareEffect(effect));
|
|
577
|
-
if (emitted.length > 0) ruleIds.push(registration.id);
|
|
578
|
-
}
|
|
579
|
-
return { hook: input.hook, input: cloneHookInput(input), effects, ruleIds };
|
|
580
|
-
}
|
|
581
|
-
function emitDiagnostic(sink, diagnostic) {
|
|
582
|
-
try {
|
|
583
|
-
sink(diagnostic);
|
|
584
|
-
} catch {
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
function evaluateRuleDefinition(definition, input) {
|
|
588
|
-
const rule = definition.rule;
|
|
589
|
-
if (!rule.enabled) return [];
|
|
590
|
-
if (!rule.hooks.includes(input.hook)) return [];
|
|
591
|
-
if (definition.toolNames !== void 0) {
|
|
592
|
-
if (input.toolName === void 0) return [];
|
|
593
|
-
if (!definition.toolNames.includes(input.toolName)) return [];
|
|
594
|
-
}
|
|
595
|
-
if (definition.predicate !== void 0 && !definition.predicate(input)) return [];
|
|
596
|
-
const declaredKinds = new Set(rule.effectKinds);
|
|
597
|
-
const emitted = [];
|
|
598
|
-
for (const effect of definition.effects) {
|
|
599
|
-
if (!declaredKinds.has(effect.kind)) continue;
|
|
600
|
-
emitted.push(cloneMiddlewareEffect(effect));
|
|
601
|
-
}
|
|
602
|
-
return emitted;
|
|
603
|
-
}
|
|
604
|
-
function cloneMiddlewareEffect(effect) {
|
|
605
|
-
switch (effect.kind) {
|
|
606
|
-
case "inject_reminder": {
|
|
607
|
-
const cloned = { kind: "inject_reminder", message: effect.message };
|
|
608
|
-
if (effect.severity !== void 0) cloned.severity = effect.severity;
|
|
609
|
-
return cloned;
|
|
610
|
-
}
|
|
611
|
-
case "annotate_tool_result": {
|
|
612
|
-
const cloned = { kind: "annotate_tool_result", message: effect.message };
|
|
613
|
-
if (effect.severity !== void 0) cloned.severity = effect.severity;
|
|
614
|
-
return cloned;
|
|
615
|
-
}
|
|
616
|
-
case "block_tool":
|
|
617
|
-
return { kind: "block_tool", reason: effect.reason, severity: effect.severity };
|
|
618
|
-
case "protect_path":
|
|
619
|
-
return { kind: "protect_path", path: effect.path, reason: effect.reason };
|
|
620
|
-
case "request_continuation":
|
|
621
|
-
return { kind: "request_continuation", message: effect.message };
|
|
622
|
-
case "require_tool":
|
|
623
|
-
return { kind: "require_tool", toolName: effect.toolName };
|
|
624
|
-
case "lock_tools":
|
|
625
|
-
return { kind: "lock_tools" };
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
function cloneHookInput(input) {
|
|
629
|
-
const cloned = { hook: input.hook };
|
|
630
|
-
if (input.runId !== void 0) cloned.runId = input.runId;
|
|
631
|
-
if (input.sessionId !== void 0) cloned.sessionId = input.sessionId;
|
|
632
|
-
if (input.turnId !== void 0) cloned.turnId = input.turnId;
|
|
633
|
-
if (input.toolCallId !== void 0) cloned.toolCallId = input.toolCallId;
|
|
634
|
-
if (input.correlationId !== void 0) cloned.correlationId = input.correlationId;
|
|
635
|
-
if (input.toolName !== void 0) cloned.toolName = input.toolName;
|
|
636
|
-
if (input.modelId !== void 0) cloned.modelId = input.modelId;
|
|
637
|
-
if (input.metadata !== void 0) cloned.metadata = { ...input.metadata };
|
|
638
|
-
if (input.toolArgs !== void 0) cloned.toolArgs = { ...input.toolArgs };
|
|
639
|
-
if (input.toolResultDetails !== void 0) cloned.toolResultDetails = { ...input.toolResultDetails };
|
|
640
|
-
if (input.toolResultDigest !== void 0) {
|
|
641
|
-
cloned.toolResultDigest = {
|
|
642
|
-
text: input.toolResultDigest.text,
|
|
643
|
-
provenance: { ...input.toolResultDigest.provenance }
|
|
644
|
-
};
|
|
645
|
-
}
|
|
646
|
-
if (input.text !== void 0) cloned.text = input.text.slice(0, MIDDLEWARE_HOOK_TEXT_MAX_CHARS);
|
|
647
|
-
return cloned;
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// src/domains/middleware/dispatch-nudge.ts
|
|
651
|
-
init_esm_shims();
|
|
652
|
-
var DETACHED_DISPATCH_NUDGE_REGISTRATION_ID = "nudge.detached-dispatch";
|
|
653
|
-
var READ_ONLY_EXPLORATION_NUDGE_REGISTRATION_ID = "nudge.read-only-exploration";
|
|
654
|
-
var READ_ONLY_EXPLORATION_NUDGE_CALL_THRESHOLD = 9;
|
|
655
|
-
var UNBACKED_WORKER_CLAIM_REGISTRATION_ID = "rail.unbacked-worker-claim";
|
|
656
|
-
var SCOUT_AGENT_ID = "scout";
|
|
657
|
-
var EXPLORATION_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
658
|
-
ToolNames.Read,
|
|
659
|
-
ToolNames.Grep,
|
|
660
|
-
ToolNames.Find,
|
|
661
|
-
ToolNames.Ls,
|
|
662
|
-
ToolNames.CodeNav,
|
|
663
|
-
ToolNames.Context,
|
|
664
|
-
ToolNames.Git
|
|
665
|
-
]);
|
|
666
|
-
var EXPLORATION_NUDGE_TURN_LIMIT = 32;
|
|
667
|
-
var NO_TURN = "no-turn";
|
|
668
|
-
var READ_ONLY_SHELL_COMMAND_PATTERN = /^\s*(?:awk|cat|fd|find|git|grep|head|jq|ls|rg|sed|tail|tree|wc)\b/;
|
|
669
|
-
function buildReadOnlyExplorationMessage() {
|
|
670
|
-
return `[Clio Coder] This turn used ${READ_ONLY_EXPLORATION_NUDGE_CALL_THRESHOLD}+ read-only exploration calls without a successful Scout dispatch; delegate broad repository reconnaissance to Scout.`;
|
|
671
|
-
}
|
|
672
|
-
function stringValue(value) {
|
|
673
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
674
|
-
}
|
|
675
|
-
function recordValue(value) {
|
|
676
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
677
|
-
}
|
|
678
|
-
function ordinaryDispatchAgents(args) {
|
|
679
|
-
if (!args || args.list === true || args.apply_winner !== void 0 || args.review !== void 0 && args.review !== false || args.mode === "compete") {
|
|
680
|
-
return null;
|
|
681
|
-
}
|
|
682
|
-
let tasks = args.tasks;
|
|
683
|
-
if (typeof tasks === "string") {
|
|
684
|
-
const raw = tasks.trim();
|
|
685
|
-
if (raw.startsWith("[") || raw.startsWith("{")) {
|
|
686
|
-
try {
|
|
687
|
-
tasks = JSON.parse(raw);
|
|
688
|
-
} catch {
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
if (recordValue(tasks) !== null || typeof tasks === "string") tasks = [tasks];
|
|
693
|
-
if (tasks === void 0 && typeof args.task === "string") tasks = [{ task: args.task }];
|
|
694
|
-
if (!Array.isArray(tasks) || tasks.length === 0) return null;
|
|
695
|
-
const sharedAgent = stringValue(args.agent) ?? stringValue(args.agent_id) ?? "coder";
|
|
696
|
-
const agents = [];
|
|
697
|
-
for (const task of tasks) {
|
|
698
|
-
if (typeof task === "string") {
|
|
699
|
-
if (stringValue(task) === null) return null;
|
|
700
|
-
agents.push(sharedAgent);
|
|
701
|
-
continue;
|
|
702
|
-
}
|
|
703
|
-
const record = recordValue(task);
|
|
704
|
-
if (!record || stringValue(record.task) === null) return null;
|
|
705
|
-
agents.push(stringValue(record.agent) ?? stringValue(record.agent_id) ?? sharedAgent);
|
|
706
|
-
}
|
|
707
|
-
return agents;
|
|
708
|
-
}
|
|
709
|
-
function dispatchTargetsScout(args) {
|
|
710
|
-
return ordinaryDispatchAgents(args)?.some((agent) => agent.toLowerCase() === SCOUT_AGENT_ID) === true;
|
|
711
|
-
}
|
|
712
|
-
function isNonRepositoryContextCall(input) {
|
|
713
|
-
if (input.toolName !== ToolNames.Context) return false;
|
|
714
|
-
const scope = stringValue(input.toolArgs?.scope)?.toLowerCase();
|
|
715
|
-
return scope !== null && scope !== "workspace";
|
|
716
|
-
}
|
|
717
|
-
function isReadOnlyExplorationCall(input) {
|
|
718
|
-
if (isNonRepositoryContextCall(input)) return false;
|
|
719
|
-
if (input.toolName && EXPLORATION_TOOL_NAMES.has(input.toolName)) return true;
|
|
720
|
-
if (input.toolName !== ToolNames.Bash) return false;
|
|
721
|
-
const command = input.toolArgs?.command;
|
|
722
|
-
return typeof command === "string" && READ_ONLY_SHELL_COMMAND_PATTERN.test(command);
|
|
723
|
-
}
|
|
724
|
-
function hasActiveTool(input, toolName) {
|
|
725
|
-
const activeToolNames = input.metadata?.activeToolNames;
|
|
726
|
-
return typeof activeToolNames === "string" && activeToolNames.split(",").map((name) => name.trim()).includes(toolName);
|
|
727
|
-
}
|
|
728
|
-
function newExplorationTurnState(advised = false) {
|
|
729
|
-
return {
|
|
730
|
-
readOnlyCalls: 0,
|
|
731
|
-
scoutSucceeded: false,
|
|
732
|
-
advised
|
|
733
|
-
};
|
|
734
|
-
}
|
|
735
|
-
function markScoutSuccess(state) {
|
|
736
|
-
state.scoutSucceeded = true;
|
|
737
|
-
}
|
|
738
|
-
function createReadOnlyExplorationNudgeRegistration() {
|
|
739
|
-
const byTurn = /* @__PURE__ */ new Map();
|
|
740
|
-
const turnKey = (input) => {
|
|
741
|
-
const userTurnId = input.hook === "turn_end" ? input.metadata?.userTurnId : void 0;
|
|
742
|
-
return (typeof userTurnId === "string" && userTurnId.length > 0 ? userTurnId : input.turnId) ?? input.runId ?? NO_TURN;
|
|
743
|
-
};
|
|
744
|
-
const remember = (key, state) => {
|
|
745
|
-
if (byTurn.size >= EXPLORATION_NUDGE_TURN_LIMIT && !byTurn.has(key)) {
|
|
746
|
-
const oldest = byTurn.keys().next().value;
|
|
747
|
-
if (oldest !== void 0) byTurn.delete(oldest);
|
|
748
|
-
}
|
|
749
|
-
byTurn.set(key, state);
|
|
750
|
-
return state;
|
|
751
|
-
};
|
|
752
|
-
const stateForTool = (key) => byTurn.get(key) ?? remember(key, newExplorationTurnState());
|
|
753
|
-
const takeTurnEndState = (key) => {
|
|
754
|
-
const bound = byTurn.get(key);
|
|
755
|
-
if (bound === void 0) return null;
|
|
756
|
-
byTurn.set(key, newExplorationTurnState(bound.advised));
|
|
757
|
-
return bound;
|
|
758
|
-
};
|
|
759
|
-
const markAdvised = (key) => {
|
|
760
|
-
const carried = byTurn.get(key);
|
|
761
|
-
if (carried) carried.advised = true;
|
|
762
|
-
};
|
|
763
|
-
return {
|
|
764
|
-
id: READ_ONLY_EXPLORATION_NUDGE_REGISTRATION_ID,
|
|
765
|
-
description: "advise Scout delegation after prolonged read-only repository exploration",
|
|
766
|
-
hooks: ["before_tool", "after_tool", "turn_end"],
|
|
767
|
-
evaluate(input) {
|
|
768
|
-
const key = turnKey(input);
|
|
769
|
-
if (input.hook === "before_tool" || input.hook === "after_tool") {
|
|
770
|
-
const state2 = stateForTool(key);
|
|
771
|
-
if (input.toolName === ToolNames.Dispatch) {
|
|
772
|
-
if (input.hook === "after_tool" && dispatchTargetsScout(input.toolArgs)) {
|
|
773
|
-
if (input.metadata?.resultKind === "ok") markScoutSuccess(state2);
|
|
774
|
-
}
|
|
775
|
-
return [];
|
|
776
|
-
}
|
|
777
|
-
if (input.hook === "after_tool" || !isReadOnlyExplorationCall(input)) return [];
|
|
778
|
-
state2.readOnlyCalls += 1;
|
|
779
|
-
return [];
|
|
780
|
-
}
|
|
781
|
-
if (input.hook !== "turn_end") return [];
|
|
782
|
-
const state = takeTurnEndState(key);
|
|
783
|
-
const stopReason = input.metadata?.stopReason;
|
|
784
|
-
if (stopReason !== void 0 && stopReason !== "stop") return [];
|
|
785
|
-
if (!hasActiveTool(input, ToolNames.Dispatch)) return [];
|
|
786
|
-
if (!state || state.advised || state.scoutSucceeded || state.readOnlyCalls < READ_ONLY_EXPLORATION_NUDGE_CALL_THRESHOLD) {
|
|
787
|
-
return [];
|
|
788
|
-
}
|
|
789
|
-
markAdvised(key);
|
|
790
|
-
return [{ kind: "inject_reminder", message: buildReadOnlyExplorationMessage(), severity: "info" }];
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
|
-
var WORKER_NOUN = "(?:scouts?|shadow (?:agent|worker)s?|sub-?agents?|workers?)";
|
|
795
|
-
var RESULT_VERB = "(?:found|reported|returned|investigated|explored|concluded|confirmed|discovered|surfaced|completed|is complete|came back)";
|
|
796
|
-
var WORKER_CLAIM_PATTERNS = [
|
|
797
|
-
// "the scout found ...", "the scout investigation is complete", "workers came back ..."
|
|
798
|
-
new RegExp(`\\b${WORKER_NOUN}\\b[^.\\n]{0,40}?\\b${RESULT_VERB}\\b`, "i"),
|
|
799
|
-
// "... reported by the scout"
|
|
800
|
-
new RegExp(`\\b${RESULT_VERB}\\b[^.\\n]{0,24}\\bby\\s+(?:the\\s+|a\\s+|our\\s+)?${WORKER_NOUN}\\b`, "i"),
|
|
801
|
-
// A titled worker deliverable: "Scout Shadow Report", "Worker findings".
|
|
802
|
-
/\b(?:scout|shadow|worker)\b[^\n]{0,20}\b(?:report|findings|summary)\b/i
|
|
803
|
-
];
|
|
804
|
-
function claimsWorkerResults(text) {
|
|
805
|
-
if (typeof text !== "string" || text.trim().length === 0) return false;
|
|
806
|
-
return WORKER_CLAIM_PATTERNS.some((pattern) => pattern.test(text));
|
|
807
|
-
}
|
|
808
|
-
function buildUnbackedWorkerClaimMessage() {
|
|
809
|
-
return "[Clio Coder] no dispatch ran this turn; worker results named above are not backed by a receipt. Dispatch the work or state plainly that you did it inline.";
|
|
810
|
-
}
|
|
811
|
-
function createUnbackedWorkerClaimRegistration() {
|
|
812
|
-
const dispatchedTurns = /* @__PURE__ */ new Set();
|
|
813
|
-
const turnKey = (input) => {
|
|
814
|
-
const userTurnId = input.hook === "turn_end" ? input.metadata?.userTurnId : void 0;
|
|
815
|
-
return (typeof userTurnId === "string" && userTurnId.length > 0 ? userTurnId : input.turnId) ?? input.runId ?? NO_TURN;
|
|
816
|
-
};
|
|
817
|
-
const remember = (key) => {
|
|
818
|
-
if (dispatchedTurns.size >= EXPLORATION_NUDGE_TURN_LIMIT && !dispatchedTurns.has(key)) {
|
|
819
|
-
const oldest = dispatchedTurns.values().next().value;
|
|
820
|
-
if (oldest !== void 0) dispatchedTurns.delete(oldest);
|
|
821
|
-
}
|
|
822
|
-
dispatchedTurns.add(key);
|
|
823
|
-
};
|
|
824
|
-
return {
|
|
825
|
-
id: UNBACKED_WORKER_CLAIM_REGISTRATION_ID,
|
|
826
|
-
description: "contradict a worker/scout result claim that no dispatch call in the turn backs",
|
|
827
|
-
hooks: ["after_tool", "turn_end"],
|
|
828
|
-
evaluate(input) {
|
|
829
|
-
const key = turnKey(input);
|
|
830
|
-
if (input.hook === "after_tool") {
|
|
831
|
-
if (input.toolName === ToolNames.Dispatch) remember(key);
|
|
832
|
-
return [];
|
|
833
|
-
}
|
|
834
|
-
if (input.hook !== "turn_end") return [];
|
|
835
|
-
const dispatched = dispatchedTurns.delete(key);
|
|
836
|
-
const stopReason = input.metadata?.stopReason;
|
|
837
|
-
if (stopReason !== void 0 && stopReason !== "stop") return [];
|
|
838
|
-
if (!hasActiveTool(input, ToolNames.Dispatch)) return [];
|
|
839
|
-
if (input.metadata?.sharedWorkerNote === true) return [];
|
|
840
|
-
if (dispatched || !claimsWorkerResults(input.text)) return [];
|
|
841
|
-
return [{ kind: "inject_reminder", message: buildUnbackedWorkerClaimMessage(), severity: "warn" }];
|
|
842
|
-
}
|
|
843
|
-
};
|
|
844
|
-
}
|
|
845
|
-
var TERMINAL_OUTCOME_ORDER = [
|
|
846
|
-
"succeeded",
|
|
847
|
-
"canceled",
|
|
848
|
-
"failed",
|
|
849
|
-
"timed_out",
|
|
850
|
-
"stalled",
|
|
851
|
-
"denied_by_policy",
|
|
852
|
-
"spawn_failed",
|
|
853
|
-
"missing",
|
|
854
|
-
"unknown"
|
|
855
|
-
];
|
|
856
|
-
function terminalOutcomeLabel(outcome) {
|
|
857
|
-
switch (outcome) {
|
|
858
|
-
case "timed_out":
|
|
859
|
-
return "timed out";
|
|
860
|
-
case "denied_by_policy":
|
|
861
|
-
return "denied by policy";
|
|
862
|
-
case "spawn_failed":
|
|
863
|
-
return "spawn failed";
|
|
864
|
-
case "missing":
|
|
865
|
-
return "ledger row missing";
|
|
866
|
-
case "unknown":
|
|
867
|
-
return "outcome unknown";
|
|
868
|
-
default:
|
|
869
|
-
return outcome;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
function incrementTerminalOutcome(counts, outcome) {
|
|
873
|
-
counts[outcome] = (counts[outcome] ?? 0) + 1;
|
|
874
|
-
}
|
|
875
|
-
function openDetachedBatchViews(dispatch) {
|
|
876
|
-
const detached = dispatch.detached;
|
|
877
|
-
if (!detached) return [];
|
|
878
|
-
let records;
|
|
879
|
-
try {
|
|
880
|
-
records = detached.list();
|
|
881
|
-
} catch {
|
|
882
|
-
return [];
|
|
883
|
-
}
|
|
884
|
-
return records.map((record) => {
|
|
885
|
-
let terminal = 0;
|
|
886
|
-
const terminalOutcomes = {};
|
|
887
|
-
for (const run of record.runs) {
|
|
888
|
-
const row = dispatch.getRun(run.runId);
|
|
889
|
-
if (row === null) {
|
|
890
|
-
terminal += 1;
|
|
891
|
-
incrementTerminalOutcome(terminalOutcomes, "missing");
|
|
892
|
-
} else if (isTerminalRunEnvelope(row)) {
|
|
893
|
-
terminal += 1;
|
|
894
|
-
incrementTerminalOutcome(terminalOutcomes, row.outcome ?? "unknown");
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
return { id: record.id, total: record.runs.length, terminal, terminalOutcomes };
|
|
898
|
-
});
|
|
899
|
-
}
|
|
900
|
-
function detachedBatchProgress(view) {
|
|
901
|
-
const terminalOutcomes = view.terminalOutcomes ?? {};
|
|
902
|
-
if (view.terminal === view.total && terminalOutcomes.succeeded === view.total) {
|
|
903
|
-
return `${view.terminal}/${view.total} run(s) done`;
|
|
904
|
-
}
|
|
905
|
-
let accountedFor = 0;
|
|
906
|
-
const breakdown = TERMINAL_OUTCOME_ORDER.flatMap((outcome) => {
|
|
907
|
-
const count = terminalOutcomes[outcome] ?? 0;
|
|
908
|
-
accountedFor += count;
|
|
909
|
-
return count > 0 ? [`${count} ${terminalOutcomeLabel(outcome)}`] : [];
|
|
910
|
-
});
|
|
911
|
-
const unavailable = Math.max(0, view.terminal - accountedFor);
|
|
912
|
-
if (unavailable > 0) breakdown.push(`${unavailable} outcome unknown`);
|
|
913
|
-
return `${view.terminal}/${view.total} run(s) terminal (${breakdown.join(", ")})`;
|
|
914
|
-
}
|
|
915
|
-
function buildDetachedBatchesMessage(ready, running) {
|
|
916
|
-
const rows = ready.map((view) => ` - batch ${view.id}: ${detachedBatchProgress(view)}`);
|
|
917
|
-
const runningNote = running.length > 0 ? `
|
|
918
|
-
${running.length} other detached batch(es) are still running; leave those for later.` : "";
|
|
919
|
-
return `[Clio Coder] ${ready.length} detached dispatch batch(es) finished and are uncollected:
|
|
920
|
-
${rows.join("\n")}
|
|
921
|
-
Collect each with monitor mode="collect" batch_id=<id> before final synthesis and act on the results. A batch stays open (and keeps nudging) until it is collected.${runningNote}`;
|
|
922
|
-
}
|
|
923
|
-
function createDetachedDispatchNudgeRegistration(options) {
|
|
924
|
-
return {
|
|
925
|
-
id: DETACHED_DISPATCH_NUDGE_REGISTRATION_ID,
|
|
926
|
-
description: "carry the turn onward when detached dispatch results are ready to collect",
|
|
927
|
-
hooks: ["turn_end"],
|
|
928
|
-
evaluate(input) {
|
|
929
|
-
if (input.hook !== "turn_end") return [];
|
|
930
|
-
const stopReason = input.metadata?.stopReason;
|
|
931
|
-
if (stopReason !== void 0 && stopReason !== "stop") return [];
|
|
932
|
-
const activeToolNames = input.metadata?.activeToolNames;
|
|
933
|
-
if (typeof activeToolNames === "string" && !activeToolNames.split(",").includes(ToolNames.Monitor)) return [];
|
|
934
|
-
let views;
|
|
935
|
-
try {
|
|
936
|
-
views = options.getOpenBatches();
|
|
937
|
-
} catch {
|
|
938
|
-
return [];
|
|
939
|
-
}
|
|
940
|
-
const ready = views.filter((view) => view.total > 0 && view.terminal >= view.total);
|
|
941
|
-
if (ready.length === 0) return [];
|
|
942
|
-
const running = views.filter((view) => view.total > 0 && view.terminal < view.total);
|
|
943
|
-
const message = buildDetachedBatchesMessage(ready, running);
|
|
944
|
-
return [
|
|
945
|
-
{ kind: "request_continuation", message },
|
|
946
|
-
{ kind: "inject_reminder", message, severity: "warn" }
|
|
947
|
-
];
|
|
948
|
-
}
|
|
949
|
-
};
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
// src/domains/middleware/hook-receipts.ts
|
|
953
|
-
init_esm_shims();
|
|
954
|
-
import { readFileSync } from "node:fs";
|
|
955
|
-
var HOOK_RECEIPT_LOG_CAPACITY = 200;
|
|
956
|
-
var PERSIST_THROTTLE_MS = 2e3;
|
|
957
|
-
function createHookReceiptLog(options = {}) {
|
|
958
|
-
const capacity = options.capacity ?? HOOK_RECEIPT_LOG_CAPACITY;
|
|
959
|
-
const now = options.now ?? Date.now;
|
|
960
|
-
const throttleMs = options.throttleMs ?? PERSIST_THROTTLE_MS;
|
|
961
|
-
const ring = [];
|
|
962
|
-
let lastPersistAt = 0;
|
|
963
|
-
let dirty = false;
|
|
964
|
-
const persist = () => {
|
|
965
|
-
if (options.persistPath === void 0) return;
|
|
966
|
-
const payload = { version: 1, receipts: ring };
|
|
967
|
-
try {
|
|
968
|
-
safeResourceWrite(options.persistPath, `${JSON.stringify(payload, null, 2)}
|
|
969
|
-
`, { encoding: "utf8" });
|
|
970
|
-
dirty = false;
|
|
971
|
-
} catch {
|
|
972
|
-
}
|
|
973
|
-
};
|
|
974
|
-
return {
|
|
975
|
-
record(receipt) {
|
|
976
|
-
ring.push(receipt);
|
|
977
|
-
while (ring.length > capacity) ring.shift();
|
|
978
|
-
dirty = true;
|
|
979
|
-
if (now() - lastPersistAt >= throttleMs) {
|
|
980
|
-
lastPersistAt = now();
|
|
981
|
-
persist();
|
|
982
|
-
}
|
|
983
|
-
},
|
|
984
|
-
list() {
|
|
985
|
-
return [...ring];
|
|
986
|
-
},
|
|
987
|
-
flush() {
|
|
988
|
-
if (dirty) persist();
|
|
989
|
-
}
|
|
990
|
-
};
|
|
991
|
-
}
|
|
992
|
-
function readPersistedHookReceipts(persistPath) {
|
|
993
|
-
let raw;
|
|
994
|
-
try {
|
|
995
|
-
raw = readFileSync(persistPath, "utf8");
|
|
996
|
-
} catch (error) {
|
|
997
|
-
if (error.code === "ENOENT") return [];
|
|
998
|
-
throw error;
|
|
999
|
-
}
|
|
1000
|
-
const parsed = JSON.parse(raw);
|
|
1001
|
-
if (parsed.version !== 1 || !Array.isArray(parsed.receipts)) {
|
|
1002
|
-
throw new Error(`${persistPath}: unrecognized hook receipt log shape`);
|
|
1003
|
-
}
|
|
1004
|
-
return parsed.receipts;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
// src/domains/middleware/skills-reminder.ts
|
|
1008
|
-
init_esm_shims();
|
|
1009
|
-
var SKILLS_REMINDER_REGISTRATION_ID = "observer.skills-reminder";
|
|
1010
|
-
function skillsReminderMessage(installed, installable = 0, modelActivation = false) {
|
|
1011
|
-
const counts = installable > 0 ? `${installed} installed, ${installable} installable from the marketplace` : `${installed} installed`;
|
|
1012
|
-
if (modelActivation) {
|
|
1013
|
-
return `[Skills] ${counts}. Start this task by listing them with context(scope="skills") and checking for a match; if one matches, load it with context(scope="skills", name="<name>") and continue the task in the same turn. A marketplace skill is not installed and is offered for install when the operator runs it. If none match, do not mention skills and continue with the task.`;
|
|
1014
|
-
}
|
|
1015
|
-
return `[Skills] ${counts}. Start this task by listing them with context(scope="skills") and checking for a match; if one matches, open your reply with the line \`${SKILL_SUGGESTION_ANCHOR}\` (a comma-separated sequence, in order, when several compose) and then continue the task in the same turn without the skill. Only the operator loads a skill, and a marketplace skill is offered for install when the operator runs it. If none match, do not mention skills and continue with the task.`;
|
|
1016
|
-
}
|
|
1017
|
-
var NO_EFFECTS = [];
|
|
1018
|
-
var GREETING_WORDS = /* @__PURE__ */ new Set([
|
|
1019
|
-
"hi",
|
|
1020
|
-
"hello",
|
|
1021
|
-
"hey",
|
|
1022
|
-
"heya",
|
|
1023
|
-
"hiya",
|
|
1024
|
-
"howdy",
|
|
1025
|
-
"yo",
|
|
1026
|
-
"sup",
|
|
1027
|
-
"hola",
|
|
1028
|
-
"greetings",
|
|
1029
|
-
"gm",
|
|
1030
|
-
"gn",
|
|
1031
|
-
"morning",
|
|
1032
|
-
"afternoon",
|
|
1033
|
-
"evening",
|
|
1034
|
-
"good",
|
|
1035
|
-
"day",
|
|
1036
|
-
"night",
|
|
1037
|
-
"there",
|
|
1038
|
-
"you",
|
|
1039
|
-
"clio",
|
|
1040
|
-
"thanks",
|
|
1041
|
-
"thank",
|
|
1042
|
-
"thankyou",
|
|
1043
|
-
"thx",
|
|
1044
|
-
"ty",
|
|
1045
|
-
"ok",
|
|
1046
|
-
"okay",
|
|
1047
|
-
"k",
|
|
1048
|
-
"cool",
|
|
1049
|
-
"nice",
|
|
1050
|
-
"test",
|
|
1051
|
-
"testing",
|
|
1052
|
-
"ping",
|
|
1053
|
-
"pong"
|
|
1054
|
-
]);
|
|
1055
|
-
function isSubstantiveUserTurn(text) {
|
|
1056
|
-
const normalized = (text ?? "").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").replace(/\s+/g, " ").trim();
|
|
1057
|
-
if (normalized.length === 0) return false;
|
|
1058
|
-
const tokens = normalized.split(" ");
|
|
1059
|
-
if (tokens.length > 4) return true;
|
|
1060
|
-
return tokens.some((token) => !GREETING_WORDS.has(token));
|
|
1061
|
-
}
|
|
1062
|
-
function createSkillsReminderRegistration(deps) {
|
|
1063
|
-
let lastSeenSessionId;
|
|
1064
|
-
let spentForActiveSession = false;
|
|
1065
|
-
let observedFreshStart = false;
|
|
1066
|
-
let observedAnyTurn = false;
|
|
1067
|
-
return {
|
|
1068
|
-
id: SKILLS_REMINDER_REGISTRATION_ID,
|
|
1069
|
-
description: "once per session, on the first substantive turn, teaches the skill-suggestion reply protocol; keeps a turn going that stopped on the suggestion",
|
|
1070
|
-
hooks: ["turn_start", "turn_end"],
|
|
1071
|
-
evaluate(input) {
|
|
1072
|
-
if (input.hook === "turn_end") {
|
|
1073
|
-
return isSkillSuggestionWait(input) ? [{ kind: "request_continuation", message: SKILL_SUGGESTION_WAIT_CONTINUATION_MESSAGE }] : NO_EFFECTS;
|
|
1074
|
-
}
|
|
1075
|
-
const sessionId = input.sessionId ?? null;
|
|
1076
|
-
if (lastSeenSessionId === void 0) {
|
|
1077
|
-
lastSeenSessionId = sessionId;
|
|
1078
|
-
} else if (lastSeenSessionId === null && sessionId !== null) {
|
|
1079
|
-
lastSeenSessionId = sessionId;
|
|
1080
|
-
} else if (sessionId !== lastSeenSessionId) {
|
|
1081
|
-
lastSeenSessionId = sessionId;
|
|
1082
|
-
spentForActiveSession = false;
|
|
1083
|
-
observedFreshStart = false;
|
|
1084
|
-
observedAnyTurn = false;
|
|
1085
|
-
}
|
|
1086
|
-
if (spentForActiveSession) return NO_EFFECTS;
|
|
1087
|
-
const conversationMessages = metadataNumber(input, "conversationMessages");
|
|
1088
|
-
if (!observedAnyTurn) {
|
|
1089
|
-
observedAnyTurn = true;
|
|
1090
|
-
if (conversationMessages === null || conversationMessages > 0) {
|
|
1091
|
-
spentForActiveSession = true;
|
|
1092
|
-
return NO_EFFECTS;
|
|
1093
|
-
}
|
|
1094
|
-
observedFreshStart = true;
|
|
1095
|
-
}
|
|
1096
|
-
if (!observedFreshStart) {
|
|
1097
|
-
spentForActiveSession = true;
|
|
1098
|
-
return NO_EFFECTS;
|
|
1099
|
-
}
|
|
1100
|
-
if (!isSubstantiveUserTurn(input.text)) return NO_EFFECTS;
|
|
1101
|
-
spentForActiveSession = true;
|
|
1102
|
-
const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
|
|
1103
|
-
if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS;
|
|
1104
|
-
let installed = 0;
|
|
1105
|
-
let installable = 0;
|
|
1106
|
-
try {
|
|
1107
|
-
installed = deps.countModelVisibleSkills();
|
|
1108
|
-
installable = deps.countInstallableSkills?.() ?? 0;
|
|
1109
|
-
} catch {
|
|
1110
|
-
return NO_EFFECTS;
|
|
1111
|
-
}
|
|
1112
|
-
if (installed <= 0 && installable <= 0) return NO_EFFECTS;
|
|
1113
|
-
let modelActivation = false;
|
|
1114
|
-
try {
|
|
1115
|
-
modelActivation = deps.modelMayActivateSkills?.() ?? false;
|
|
1116
|
-
} catch {
|
|
1117
|
-
}
|
|
1118
|
-
return [
|
|
1119
|
-
{
|
|
1120
|
-
kind: "inject_reminder",
|
|
1121
|
-
severity: "info",
|
|
1122
|
-
message: skillsReminderMessage(installed, installable, modelActivation)
|
|
1123
|
-
}
|
|
1124
|
-
];
|
|
1125
|
-
}
|
|
1126
|
-
};
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
// src/domains/middleware/marketplace-offer.ts
|
|
1130
|
-
init_esm_shims();
|
|
1131
|
-
import { randomUUID } from "node:crypto";
|
|
1132
|
-
|
|
1133
|
-
// src/domains/resources/skills/promotion.ts
|
|
1134
|
-
init_esm_shims();
|
|
1135
|
-
import { existsSync, readFileSync as readFileSync2 } from "node:fs";
|
|
1136
|
-
import path from "node:path";
|
|
1137
|
-
var TOKEN_STOPWORDS = /* @__PURE__ */ new Set([
|
|
1138
|
-
"the",
|
|
1139
|
-
"a",
|
|
1140
|
-
"an",
|
|
1141
|
-
"and",
|
|
1142
|
-
"or",
|
|
1143
|
-
"for",
|
|
1144
|
-
"with",
|
|
1145
|
-
"this",
|
|
1146
|
-
"that",
|
|
1147
|
-
"when",
|
|
1148
|
-
"what",
|
|
1149
|
-
"how",
|
|
1150
|
-
"into",
|
|
1151
|
-
"from",
|
|
1152
|
-
"use",
|
|
1153
|
-
"used",
|
|
1154
|
-
"using",
|
|
1155
|
-
"one",
|
|
1156
|
-
"not",
|
|
1157
|
-
"skill",
|
|
1158
|
-
"skills",
|
|
1159
|
-
"clio",
|
|
1160
|
-
"please",
|
|
1161
|
-
"can",
|
|
1162
|
-
"you",
|
|
1163
|
-
"should",
|
|
1164
|
-
"would",
|
|
1165
|
-
"about",
|
|
1166
|
-
"need",
|
|
1167
|
-
"want",
|
|
1168
|
-
"help",
|
|
1169
|
-
"make",
|
|
1170
|
-
"file",
|
|
1171
|
-
"files",
|
|
1172
|
-
"code"
|
|
1173
|
-
]);
|
|
1174
|
-
function normalize(text) {
|
|
1175
|
-
return text.toLowerCase().replace(/[^\p{L}\p{N}\s]/gu, " ").replace(/\s+/g, " ").trim();
|
|
1176
|
-
}
|
|
1177
|
-
function distinctiveTokens(text) {
|
|
1178
|
-
return new Set(
|
|
1179
|
-
normalize(text).split(" ").filter((token) => token.length >= 4 && !TOKEN_STOPWORDS.has(token))
|
|
1180
|
-
);
|
|
1181
|
-
}
|
|
1182
|
-
var TRIGGER_SCORE = 4;
|
|
1183
|
-
var TOKEN_FIRE_THRESHOLD = 3;
|
|
1184
|
-
function scorePromotionEntry(userText, entry) {
|
|
1185
|
-
const haystack = ` ${normalize(userText)} `;
|
|
1186
|
-
if (haystack.trim().length === 0) return null;
|
|
1187
|
-
for (const trigger of entry.triggers ?? []) {
|
|
1188
|
-
const phrase = normalize(trigger);
|
|
1189
|
-
if (phrase.length >= 4 && haystack.includes(` ${phrase} `)) {
|
|
1190
|
-
return { entry, score: TRIGGER_SCORE, matchedTrigger: trigger };
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
const requestTokens = distinctiveTokens(userText);
|
|
1194
|
-
if (requestTokens.size === 0) return null;
|
|
1195
|
-
const entryTokens = distinctiveTokens(`${entry.name.replace(/-/g, " ")} ${entry.description}`);
|
|
1196
|
-
let overlap = 0;
|
|
1197
|
-
for (const token of requestTokens) if (entryTokens.has(token)) overlap += 1;
|
|
1198
|
-
return overlap >= TOKEN_FIRE_THRESHOLD ? { entry, score: overlap } : null;
|
|
1199
|
-
}
|
|
1200
|
-
function matchMarketplaceSkills(userText, entries, excludedNames) {
|
|
1201
|
-
const matches = [];
|
|
1202
|
-
for (const entry of entries) {
|
|
1203
|
-
if (entry.kind !== "skill" || excludedNames.has(entry.name)) continue;
|
|
1204
|
-
const match = scorePromotionEntry(userText, entry);
|
|
1205
|
-
if (match) matches.push(match);
|
|
1206
|
-
}
|
|
1207
|
-
return matches.sort(
|
|
1208
|
-
(a, b) => Number(b.matchedTrigger !== void 0) - Number(a.matchedTrigger !== void 0) || b.score - a.score || a.entry.name.localeCompare(b.entry.name)
|
|
1209
|
-
);
|
|
1210
|
-
}
|
|
1211
|
-
var OWN_MARKETPLACE_URL_PREFIX = "https://github.com/iowarp/clio-coder/";
|
|
1212
|
-
function isOwnMarketplaceSource(entry) {
|
|
1213
|
-
const source = entry.sourceUrl.trim();
|
|
1214
|
-
if (/^(?:https?:\/\/|git@)/.test(source)) return source.startsWith(OWN_MARKETPLACE_URL_PREFIX);
|
|
1215
|
-
return entry.origin === "catalog" && path.isAbsolute(source);
|
|
1216
|
-
}
|
|
1217
|
-
function assertPromotionInstallSource(entry) {
|
|
1218
|
-
if (isOwnMarketplaceSource(entry)) return;
|
|
1219
|
-
throw new Error(
|
|
1220
|
-
`skill promotion: refusing to install "${entry.name}" from ${entry.sourceUrl}; promotion installs only from Clio's own marketplace (local catalog or ${OWN_MARKETPLACE_URL_PREFIX}). Install manually with clio-coder skills install if intended.`
|
|
1221
|
-
);
|
|
1222
|
-
}
|
|
1223
|
-
var PROMOTION_DECLINES_FILE = "skill-promotion-declines.json";
|
|
1224
|
-
function declineKey(name, version) {
|
|
1225
|
-
return `${name}@${version ?? ""}`;
|
|
1226
|
-
}
|
|
1227
|
-
function declinesPath(configDir) {
|
|
1228
|
-
return path.join(configDir ?? clioConfigDir(), PROMOTION_DECLINES_FILE);
|
|
1229
|
-
}
|
|
1230
|
-
function readPromotionDeclines(configDir) {
|
|
1231
|
-
const file = declinesPath(configDir);
|
|
1232
|
-
if (!existsSync(file)) return { never: {} };
|
|
1233
|
-
try {
|
|
1234
|
-
const parsed = JSON.parse(readFileSync2(file, "utf8"));
|
|
1235
|
-
const never = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed.never : void 0;
|
|
1236
|
-
if (never && typeof never === "object" && !Array.isArray(never)) {
|
|
1237
|
-
const entries = Object.entries(never).filter(
|
|
1238
|
-
(pair) => typeof pair[1] === "string"
|
|
1239
|
-
);
|
|
1240
|
-
return { never: Object.fromEntries(entries) };
|
|
1241
|
-
}
|
|
1242
|
-
} catch {
|
|
1243
|
-
}
|
|
1244
|
-
return { never: {} };
|
|
1245
|
-
}
|
|
1246
|
-
function recordPromotionNeverDecline(name, version, configDir) {
|
|
1247
|
-
const store = readPromotionDeclines(configDir);
|
|
1248
|
-
store.never[declineKey(name, version)] = (/* @__PURE__ */ new Date()).toISOString();
|
|
1249
|
-
safeResourceWrite(declinesPath(configDir), `${JSON.stringify(store, null, 2)}
|
|
1250
|
-
`, { encoding: "utf8" });
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
// src/domains/middleware/marketplace-offer.ts
|
|
1254
|
-
var MARKETPLACE_OFFER_REGISTRATION_ID = "observer.marketplace-offer";
|
|
1255
|
-
var NO_EFFECTS2 = [];
|
|
1256
|
-
function offerBindingTag(offerTag) {
|
|
1257
|
-
return `[clio-install:${offerTag}]`;
|
|
1258
|
-
}
|
|
1259
|
-
function boundedDescription(text) {
|
|
1260
|
-
return text.replace(/\[[^[\]]*\]/gu, " ").replace(/\s+/gu, " ").trim().slice(0, 200);
|
|
1261
|
-
}
|
|
1262
|
-
function marketplaceOfferReminder(entry, offerTag) {
|
|
1263
|
-
return `[Marketplace] This request may need expertise no installed skill covers. The local marketplace has "${entry.name}" (not installed): ${boundedDescription(entry.description)} First check the installed side with context(scope="skills"); if ${entry.name} is genuinely the right fit and nothing installed serves, ask the operator with ask_user (mode=single_question, header "Install skill") whether to install ${entry.name}, offering exactly these options in this order: "${SKILL_INSTALL_OFFER_OPTION_PROJECT}", "${SKILL_INSTALL_OFFER_OPTION_USER}", "${SKILL_INSTALL_OFFER_OPTION_NOT_NOW}", "${SKILL_INSTALL_OFFER_OPTION_NEVER}". Include the exact tag ${offerBindingTag(offerTag)} verbatim in that question's text so the harness can bind the answer to this offer; the harness acts only on an answer carrying this tag. Then continue the task in the same turn. The harness handles the answer; never install or load a skill yourself. If it is not actually needed, do not mention it.`;
|
|
1264
|
-
}
|
|
1265
|
-
function answersFromDetails(details) {
|
|
1266
|
-
const raw = details?.answers;
|
|
1267
|
-
if (!Array.isArray(raw)) return [];
|
|
1268
|
-
return raw.filter(
|
|
1269
|
-
(entry) => typeof entry === "object" && entry !== null && typeof entry.question === "string" && typeof entry.answer === "string"
|
|
1270
|
-
);
|
|
1271
|
-
}
|
|
1272
|
-
function chosenOfferOption(answer) {
|
|
1273
|
-
const labels = [
|
|
1274
|
-
SKILL_INSTALL_OFFER_OPTION_PROJECT,
|
|
1275
|
-
SKILL_INSTALL_OFFER_OPTION_USER,
|
|
1276
|
-
SKILL_INSTALL_OFFER_OPTION_NOT_NOW,
|
|
1277
|
-
SKILL_INSTALL_OFFER_OPTION_NEVER
|
|
1278
|
-
];
|
|
1279
|
-
for (const label of labels) {
|
|
1280
|
-
if (answer.options?.includes(label)) return label;
|
|
1281
|
-
}
|
|
1282
|
-
for (const label of labels) {
|
|
1283
|
-
if (answer.answer.includes(label)) return label;
|
|
1284
|
-
}
|
|
1285
|
-
return null;
|
|
1286
|
-
}
|
|
1287
|
-
function createMarketplaceOfferRegistration(deps) {
|
|
1288
|
-
const declines = deps.declines ?? {
|
|
1289
|
-
readNever: () => readPromotionDeclines().never,
|
|
1290
|
-
recordNever: (name, version) => recordPromotionNeverDecline(name, version)
|
|
1291
|
-
};
|
|
1292
|
-
const newOfferTag = deps.newOfferTag ?? (() => randomUUID());
|
|
1293
|
-
let lastSeenSessionId;
|
|
1294
|
-
let offeredNames = /* @__PURE__ */ new Set();
|
|
1295
|
-
let sessionDeclines = /* @__PURE__ */ new Set();
|
|
1296
|
-
let installedNamesCache = null;
|
|
1297
|
-
let marketplaceEntriesCache = null;
|
|
1298
|
-
let pendingOffer = null;
|
|
1299
|
-
const trackSession = (input) => {
|
|
1300
|
-
const sessionId = input.sessionId ?? null;
|
|
1301
|
-
if (lastSeenSessionId === void 0 || lastSeenSessionId === null && sessionId !== null) {
|
|
1302
|
-
lastSeenSessionId = sessionId;
|
|
1303
|
-
return;
|
|
1304
|
-
}
|
|
1305
|
-
if (sessionId !== lastSeenSessionId) {
|
|
1306
|
-
lastSeenSessionId = sessionId;
|
|
1307
|
-
offeredNames = /* @__PURE__ */ new Set();
|
|
1308
|
-
sessionDeclines = /* @__PURE__ */ new Set();
|
|
1309
|
-
pendingOffer = null;
|
|
1310
|
-
installedNamesCache = null;
|
|
1311
|
-
marketplaceEntriesCache = null;
|
|
1312
|
-
}
|
|
1313
|
-
};
|
|
1314
|
-
const bestMatch = (text) => {
|
|
1315
|
-
const installedWasCached = installedNamesCache !== null;
|
|
1316
|
-
let never;
|
|
1317
|
-
try {
|
|
1318
|
-
installedNamesCache ??= new Set(deps.listInstalledSkillNames());
|
|
1319
|
-
marketplaceEntriesCache ??= deps.listMarketplaceEntries();
|
|
1320
|
-
never = declines.readNever();
|
|
1321
|
-
} catch {
|
|
1322
|
-
return null;
|
|
1323
|
-
}
|
|
1324
|
-
const declinedKeys = /* @__PURE__ */ new Set([...Object.keys(never), ...sessionDeclines]);
|
|
1325
|
-
const findMatch = () => matchMarketplaceSkills(
|
|
1326
|
-
text,
|
|
1327
|
-
marketplaceEntriesCache ?? [],
|
|
1328
|
-
/* @__PURE__ */ new Set([...installedNamesCache ?? [], ...offeredNames])
|
|
1329
|
-
).find((candidate) => !declinedKeys.has(declineKey(candidate.entry.name, candidate.entry.version))) ?? null;
|
|
1330
|
-
let match = findMatch();
|
|
1331
|
-
if (match && installedWasCached) {
|
|
1332
|
-
try {
|
|
1333
|
-
installedNamesCache = new Set(deps.listInstalledSkillNames());
|
|
1334
|
-
} catch {
|
|
1335
|
-
return null;
|
|
1336
|
-
}
|
|
1337
|
-
match = findMatch();
|
|
1338
|
-
}
|
|
1339
|
-
return match;
|
|
1340
|
-
};
|
|
1341
|
-
const installGated = (entry, scope) => {
|
|
1342
|
-
assertPromotionInstallSource(entry);
|
|
1343
|
-
const result = deps.installEntry(entry, scope);
|
|
1344
|
-
installedNamesCache?.add(entry.name);
|
|
1345
|
-
return result;
|
|
1346
|
-
};
|
|
1347
|
-
const evaluateAskUserAnswers = (input) => {
|
|
1348
|
-
const offer = pendingOffer;
|
|
1349
|
-
if (!offer) return NO_EFFECTS2;
|
|
1350
|
-
const marker = offerBindingTag(offer.tag);
|
|
1351
|
-
if (input.toolResultDetails?.cancelled === true) {
|
|
1352
|
-
return NO_EFFECTS2;
|
|
1353
|
-
}
|
|
1354
|
-
for (const answer of answersFromDetails(input.toolResultDetails)) {
|
|
1355
|
-
if (!answer.question.includes(marker)) continue;
|
|
1356
|
-
const option = chosenOfferOption(answer);
|
|
1357
|
-
if (option === null) continue;
|
|
1358
|
-
pendingOffer = null;
|
|
1359
|
-
const offerKey = declineKey(offer.entry.name, offer.entry.version);
|
|
1360
|
-
if (option === SKILL_INSTALL_OFFER_OPTION_NOT_NOW) {
|
|
1361
|
-
sessionDeclines.add(offerKey);
|
|
1362
|
-
return NO_EFFECTS2;
|
|
1363
|
-
}
|
|
1364
|
-
if (option === SKILL_INSTALL_OFFER_OPTION_NEVER) {
|
|
1365
|
-
sessionDeclines.add(offerKey);
|
|
1366
|
-
try {
|
|
1367
|
-
declines.recordNever(offer.entry.name, offer.entry.version);
|
|
1368
|
-
} catch {
|
|
1369
|
-
}
|
|
1370
|
-
return NO_EFFECTS2;
|
|
1371
|
-
}
|
|
1372
|
-
const scope = option === SKILL_INSTALL_OFFER_OPTION_USER ? "user" : "project";
|
|
1373
|
-
try {
|
|
1374
|
-
const result = installGated(offer.entry, scope);
|
|
1375
|
-
return [
|
|
1376
|
-
{
|
|
1377
|
-
kind: "annotate_tool_result",
|
|
1378
|
-
severity: "info",
|
|
1379
|
-
message: `[Marketplace] Installed skill "${offer.entry.name}" (${scope} scope) to ${result.path}. It is installed but not active; the operator activates it with /skill ${offer.entry.name}.`
|
|
1380
|
-
}
|
|
1381
|
-
];
|
|
1382
|
-
} catch (error) {
|
|
1383
|
-
sessionDeclines.add(offerKey);
|
|
1384
|
-
return [
|
|
1385
|
-
{
|
|
1386
|
-
kind: "annotate_tool_result",
|
|
1387
|
-
severity: "warn",
|
|
1388
|
-
message: `[Marketplace] Install of "${offer.entry.name}" failed: ${error instanceof Error ? error.message : String(error)}. Continue the task without it.`
|
|
1389
|
-
}
|
|
1390
|
-
];
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
return NO_EFFECTS2;
|
|
1394
|
-
};
|
|
1395
|
-
return {
|
|
1396
|
-
id: MARKETPLACE_OFFER_REGISTRATION_ID,
|
|
1397
|
-
description: "offers an uninstalled marketplace skill via ask_user when the request matches it; consented installs run gated to Clio's own marketplace, declines are remembered",
|
|
1398
|
-
hooks: ["turn_start", "after_tool"],
|
|
1399
|
-
evaluate(input) {
|
|
1400
|
-
trackSession(input);
|
|
1401
|
-
if (input.hook === "after_tool") {
|
|
1402
|
-
return input.toolName === ToolNames.AskUser ? evaluateAskUserAnswers(input) : NO_EFFECTS2;
|
|
1403
|
-
}
|
|
1404
|
-
if (input.hook !== "turn_start") return NO_EFFECTS2;
|
|
1405
|
-
if (!isSubstantiveUserTurn(input.text)) return NO_EFFECTS2;
|
|
1406
|
-
const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
|
|
1407
|
-
if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS2;
|
|
1408
|
-
const match = bestMatch(input.text ?? "");
|
|
1409
|
-
if (!match) return NO_EFFECTS2;
|
|
1410
|
-
offeredNames.add(match.entry.name);
|
|
1411
|
-
if (deps.interactive === false) {
|
|
1412
|
-
return [
|
|
1413
|
-
{
|
|
1414
|
-
kind: "inject_reminder",
|
|
1415
|
-
severity: "info",
|
|
1416
|
-
message: `[Marketplace] Skill "${match.entry.name}" matches this request; install with clio-coder skills install ${match.entry.name}.`
|
|
1417
|
-
}
|
|
1418
|
-
];
|
|
1419
|
-
}
|
|
1420
|
-
const tag = newOfferTag();
|
|
1421
|
-
pendingOffer = { entry: match.entry, tag };
|
|
1422
|
-
return [{ kind: "inject_reminder", severity: "info", message: marketplaceOfferReminder(match.entry, tag) }];
|
|
1423
|
-
}
|
|
1424
|
-
};
|
|
1425
|
-
}
|
|
1426
|
-
|
|
1427
|
-
// src/domains/middleware/memory-intervention.ts
|
|
1428
|
-
init_esm_shims();
|
|
1429
|
-
import { createHash } from "node:crypto";
|
|
1430
|
-
var MEMORY_INTERVENTION_REGISTRATION_ID = "observer.memory-intervention";
|
|
1431
|
-
var MEMORY_INTERVENTION_DEFAULT_WINDOW_STEPS = 8;
|
|
1432
|
-
var MEMORY_INTERVENTION_DEFAULT_MAX_TOKENS = 2e3;
|
|
1433
|
-
var MEMORY_INTERVENTION_DEFAULT_EVERY_N_TOOLS = 10;
|
|
1434
|
-
var MEMORY_INTERVENTION_TIMEOUT_BACKOFF_THRESHOLD = 2;
|
|
1435
|
-
var MEMORY_INTERVENTION_ACTIVITY_LIMIT = 20;
|
|
1436
|
-
var CALL_DESCRIPTION_MAX_CHARS = 180;
|
|
1437
|
-
var NO_EFFECTS3 = [];
|
|
1438
|
-
function createMemoryInterventionRegistration(deps) {
|
|
1439
|
-
let generation = 0;
|
|
1440
|
-
let generationController = new AbortController();
|
|
1441
|
-
let observedSessionId;
|
|
1442
|
-
let disposed = false;
|
|
1443
|
-
const pending = /* @__PURE__ */ new Map();
|
|
1444
|
-
const trajectory = [];
|
|
1445
|
-
const failures = /* @__PURE__ */ new Map();
|
|
1446
|
-
let toolStep = 0;
|
|
1447
|
-
let lastTurnEndStep = 0;
|
|
1448
|
-
let reactivateAfterCompaction = false;
|
|
1449
|
-
let lastInjectedOperationFingerprint = null;
|
|
1450
|
-
let currentTask = "(current task unavailable)";
|
|
1451
|
-
let toolsSinceMemoryStep = 0;
|
|
1452
|
-
let consecutiveErrors = 0;
|
|
1453
|
-
let lastPromptedBoundary = null;
|
|
1454
|
-
let lastInjectedMessage = null;
|
|
1455
|
-
let lastDecision = null;
|
|
1456
|
-
const pendingTriggers = /* @__PURE__ */ new Set();
|
|
1457
|
-
const activity = [];
|
|
1458
|
-
const annotatedThisTurn = /* @__PURE__ */ new Set();
|
|
1459
|
-
let telemetryBankSnapshot = deps.bank.snapshot();
|
|
1460
|
-
let promptedStepInFlight = false;
|
|
1461
|
-
let promptedStepTier = "rules";
|
|
1462
|
-
let outstandingStep = Promise.resolve();
|
|
1463
|
-
let rulesInjectedSincePromptedStep = false;
|
|
1464
|
-
let annotatedSinceTurnEnd = false;
|
|
1465
|
-
let consecutiveLlmTimeouts = 0;
|
|
1466
|
-
return {
|
|
1467
|
-
reset,
|
|
1468
|
-
dispose() {
|
|
1469
|
-
disposed = true;
|
|
1470
|
-
reset();
|
|
1471
|
-
},
|
|
1472
|
-
id: MEMORY_INTERVENTION_REGISTRATION_ID,
|
|
1473
|
-
description: "maintain bounded task execution memory and selectively remind after repeated failures or compaction",
|
|
1474
|
-
hooks: ["before_tool", "after_tool", "turn_start", "turn_end", "on_compaction"],
|
|
1475
|
-
evaluate(input) {
|
|
1476
|
-
observeSession(input);
|
|
1477
|
-
if (disposed || !settings().enabled) return NO_EFFECTS3;
|
|
1478
|
-
try {
|
|
1479
|
-
switch (input.hook) {
|
|
1480
|
-
case "before_tool":
|
|
1481
|
-
observeBeforeTool(input);
|
|
1482
|
-
return NO_EFFECTS3;
|
|
1483
|
-
case "after_tool":
|
|
1484
|
-
return observeAfterTool(input);
|
|
1485
|
-
case "turn_end": {
|
|
1486
|
-
if (toolStep <= lastTurnEndStep) return NO_EFFECTS3;
|
|
1487
|
-
const alreadyReported = annotatedSinceTurnEnd;
|
|
1488
|
-
annotatedSinceTurnEnd = false;
|
|
1489
|
-
const started = process.hrtime.bigint();
|
|
1490
|
-
const effects = decideRepeatedFailure();
|
|
1491
|
-
if (alreadyReported && effects.length === 0) return effects;
|
|
1492
|
-
emitTelemetry(
|
|
1493
|
-
[effects.length > 0 ? "repeated_failure" : "turn_end"],
|
|
1494
|
-
"rules",
|
|
1495
|
-
effects.length > 0 ? "injected" : "silent",
|
|
1496
|
-
effects.length > 0 ? "intervened" : "no_repeated_failure",
|
|
1497
|
-
citedEntryCount(effects[0]?.kind === "inject_reminder" ? effects[0].message : null),
|
|
1498
|
-
0,
|
|
1499
|
-
0,
|
|
1500
|
-
started
|
|
1501
|
-
);
|
|
1502
|
-
return effects;
|
|
1503
|
-
}
|
|
1504
|
-
case "on_compaction":
|
|
1505
|
-
if (input.metadata?.stage === "working_set_recall") return NO_EFFECTS3;
|
|
1506
|
-
reactivateAfterCompaction = true;
|
|
1507
|
-
return NO_EFFECTS3;
|
|
1508
|
-
case "turn_start": {
|
|
1509
|
-
if (input.text?.trim()) currentTask = shortText(input.text, 2e3);
|
|
1510
|
-
annotatedThisTurn.clear();
|
|
1511
|
-
const shouldReactivate = reactivateAfterCompaction;
|
|
1512
|
-
const started = process.hrtime.bigint();
|
|
1513
|
-
const effects = reactivateKnowledge();
|
|
1514
|
-
if (shouldReactivate) {
|
|
1515
|
-
emitTelemetry(
|
|
1516
|
-
["post_compaction"],
|
|
1517
|
-
"rules",
|
|
1518
|
-
effects.length > 0 ? "injected" : "silent",
|
|
1519
|
-
effects.length > 0 ? "intervened" : "bank_empty",
|
|
1520
|
-
citedEntryCount(effects[0]?.kind === "inject_reminder" ? effects[0].message : null),
|
|
1521
|
-
0,
|
|
1522
|
-
0,
|
|
1523
|
-
started
|
|
1524
|
-
);
|
|
1525
|
-
}
|
|
1526
|
-
return effects;
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
} catch {
|
|
1530
|
-
return NO_EFFECTS3;
|
|
1531
|
-
}
|
|
1532
|
-
},
|
|
1533
|
-
/**
|
|
1534
|
-
* Kicks off the background memory step and returns immediately. The pi
|
|
1535
|
-
* agent does not go idle until every `agent_end` listener settles, so
|
|
1536
|
-
* awaiting a local memory model here would stall the visible turn for its
|
|
1537
|
-
* full latency. Small local models measure in tens of seconds, which is far
|
|
1538
|
-
* past any tolerable end-of-turn pause and past the policy timeout itself.
|
|
1539
|
-
* The reminder is delivered through `onDeferredReminder` instead, landing
|
|
1540
|
-
* in the next submitted turn, which is where an awaited turn_end reminder
|
|
1541
|
-
* would have been buffered anyway.
|
|
1542
|
-
*/
|
|
1543
|
-
async evaluateAsync(input, context) {
|
|
1544
|
-
observeSession(input);
|
|
1545
|
-
if (disposed || !settings().enabled || input.hook !== "turn_end" || pendingTriggers.size === 0) return NO_EFFECTS3;
|
|
1546
|
-
const boundary = input.turnId ?? input.metadata?.userTurnId?.toString() ?? `tool-step:${toolStep}`;
|
|
1547
|
-
if (boundary === lastPromptedBoundary) return NO_EFFECTS3;
|
|
1548
|
-
if (deps.deliversDeferredReminders === false) {
|
|
1549
|
-
emitTelemetry([...pendingTriggers], "rules", "silent", "no_consumer", 0, 0, 0, process.hrtime.bigint());
|
|
1550
|
-
pendingTriggers.clear();
|
|
1551
|
-
return NO_EFFECTS3;
|
|
1552
|
-
}
|
|
1553
|
-
if (promptedStepInFlight) {
|
|
1554
|
-
emitTelemetry(
|
|
1555
|
-
[...pendingTriggers],
|
|
1556
|
-
promptedStepTier,
|
|
1557
|
-
"dropped",
|
|
1558
|
-
"step_in_flight",
|
|
1559
|
-
0,
|
|
1560
|
-
0,
|
|
1561
|
-
0,
|
|
1562
|
-
process.hrtime.bigint()
|
|
1563
|
-
);
|
|
1564
|
-
return NO_EFFECTS3;
|
|
1565
|
-
}
|
|
1566
|
-
lastPromptedBoundary = boundary;
|
|
1567
|
-
const triggers = [...pendingTriggers];
|
|
1568
|
-
pendingTriggers.clear();
|
|
1569
|
-
toolsSinceMemoryStep = 0;
|
|
1570
|
-
consecutiveErrors = 0;
|
|
1571
|
-
const rulesAlreadySpoke = rulesInjectedSincePromptedStep || (context?.priorEffects.some(
|
|
1572
|
-
(effect) => effect.kind === "inject_reminder" && effect.message.startsWith("Memory:")
|
|
1573
|
-
) ?? false);
|
|
1574
|
-
rulesInjectedSincePromptedStep = false;
|
|
1575
|
-
const stepGeneration = generation;
|
|
1576
|
-
promptedStepInFlight = true;
|
|
1577
|
-
outstandingStep = runPromptedStep({
|
|
1578
|
-
deterministicTrigger: triggers.some((trigger) => trigger !== "interval"),
|
|
1579
|
-
suppressIntervention: rulesAlreadySpoke,
|
|
1580
|
-
triggerReasons: triggers
|
|
1581
|
-
}).then((result) => {
|
|
1582
|
-
if (stepGeneration !== generation || disposed) return;
|
|
1583
|
-
if (rulesAlreadySpoke && result.decision === "silent") lastDecision = "injected";
|
|
1584
|
-
if (result.reminder === null) return;
|
|
1585
|
-
lastInjectedMessage = result.reminder;
|
|
1586
|
-
deps.onDeferredReminder?.(result.reminder);
|
|
1587
|
-
}).catch(() => {
|
|
1588
|
-
}).finally(() => {
|
|
1589
|
-
if (stepGeneration === generation) promptedStepInFlight = false;
|
|
1590
|
-
});
|
|
1591
|
-
return NO_EFFECTS3;
|
|
1592
|
-
},
|
|
1593
|
-
runPromptedStep,
|
|
1594
|
-
signalLoop() {
|
|
1595
|
-
if (!disposed && settings().enabled) pendingTriggers.add("loop_signal");
|
|
1596
|
-
},
|
|
1597
|
-
lastDecision: () => lastDecision,
|
|
1598
|
-
recentActivity: () => [...activity],
|
|
1599
|
-
stepInFlight: () => promptedStepInFlight,
|
|
1600
|
-
whenIdle: () => outstandingStep
|
|
1601
|
-
};
|
|
1602
|
-
function observeSession(input) {
|
|
1603
|
-
if (input.sessionId === void 0) return;
|
|
1604
|
-
if (observedSessionId !== void 0 && observedSessionId !== input.sessionId) reset();
|
|
1605
|
-
observedSessionId = input.sessionId;
|
|
1606
|
-
}
|
|
1607
|
-
function reset() {
|
|
1608
|
-
generation += 1;
|
|
1609
|
-
generationController.abort();
|
|
1610
|
-
generationController = new AbortController();
|
|
1611
|
-
deps.bank.clear();
|
|
1612
|
-
pending.clear();
|
|
1613
|
-
trajectory.length = 0;
|
|
1614
|
-
failures.clear();
|
|
1615
|
-
toolStep = 0;
|
|
1616
|
-
lastTurnEndStep = 0;
|
|
1617
|
-
reactivateAfterCompaction = false;
|
|
1618
|
-
lastInjectedOperationFingerprint = null;
|
|
1619
|
-
currentTask = "(current task unavailable)";
|
|
1620
|
-
toolsSinceMemoryStep = 0;
|
|
1621
|
-
consecutiveErrors = 0;
|
|
1622
|
-
lastPromptedBoundary = null;
|
|
1623
|
-
lastInjectedMessage = null;
|
|
1624
|
-
lastDecision = null;
|
|
1625
|
-
pendingTriggers.clear();
|
|
1626
|
-
activity.length = 0;
|
|
1627
|
-
annotatedThisTurn.clear();
|
|
1628
|
-
telemetryBankSnapshot = deps.bank.snapshot();
|
|
1629
|
-
promptedStepInFlight = false;
|
|
1630
|
-
promptedStepTier = "rules";
|
|
1631
|
-
outstandingStep = Promise.resolve();
|
|
1632
|
-
rulesInjectedSincePromptedStep = false;
|
|
1633
|
-
annotatedSinceTurnEnd = false;
|
|
1634
|
-
consecutiveLlmTimeouts = 0;
|
|
1635
|
-
observedSessionId = void 0;
|
|
1636
|
-
}
|
|
1637
|
-
function settings() {
|
|
1638
|
-
const live = deps.getSettings?.();
|
|
1639
|
-
return {
|
|
1640
|
-
enabled: live?.enabled ?? deps.enabled ?? true,
|
|
1641
|
-
everyNTools: Math.max(
|
|
1642
|
-
2,
|
|
1643
|
-
positiveInteger(live?.everyNTools ?? deps.everyNTools, MEMORY_INTERVENTION_DEFAULT_EVERY_N_TOOLS)
|
|
1644
|
-
),
|
|
1645
|
-
windowSteps: positiveInteger(live?.windowSteps ?? deps.windowSteps, MEMORY_INTERVENTION_DEFAULT_WINDOW_STEPS),
|
|
1646
|
-
maxTokens: positiveInteger(live?.maxTokens ?? deps.maxTokens, MEMORY_INTERVENTION_DEFAULT_MAX_TOKENS),
|
|
1647
|
-
timeoutMs: positiveInteger(live?.timeoutMs ?? deps.timeoutMs, TASK_MEMORY_POLICY_DEFAULT_TIMEOUT_MS)
|
|
1648
|
-
};
|
|
1649
|
-
}
|
|
1650
|
-
async function runPromptedStep(input) {
|
|
1651
|
-
const silent = (reason) => ({
|
|
1652
|
-
decision: "silent",
|
|
1653
|
-
reason,
|
|
1654
|
-
bankOperations: 0,
|
|
1655
|
-
droppedOperations: 0,
|
|
1656
|
-
reminder: null,
|
|
1657
|
-
inputTokens: 0,
|
|
1658
|
-
outputTokens: 0,
|
|
1659
|
-
usage: null,
|
|
1660
|
-
effects: NO_EFFECTS3
|
|
1661
|
-
});
|
|
1662
|
-
const live = settings();
|
|
1663
|
-
const stepGeneration = generation;
|
|
1664
|
-
const isCurrent = () => !disposed && stepGeneration === generation;
|
|
1665
|
-
const usageSink = deps.captureStepUsage?.();
|
|
1666
|
-
if (disposed || !live.enabled) {
|
|
1667
|
-
const result = silent("no_client");
|
|
1668
|
-
lastDecision = result.decision;
|
|
1669
|
-
return result;
|
|
1670
|
-
}
|
|
1671
|
-
const started = process.hrtime.bigint();
|
|
1672
|
-
let attemptStarted = started;
|
|
1673
|
-
const triggers = input.triggerReasons?.length ? input.triggerReasons : ["manual"];
|
|
1674
|
-
let tier = "rules";
|
|
1675
|
-
promptedStepTier = tier;
|
|
1676
|
-
let promptedResult;
|
|
1677
|
-
let telemetryDecision = null;
|
|
1678
|
-
try {
|
|
1679
|
-
if (consecutiveLlmTimeouts >= MEMORY_INTERVENTION_TIMEOUT_BACKOFF_THRESHOLD) {
|
|
1680
|
-
promptedResult = silent("llm_timeout_backoff");
|
|
1681
|
-
} else {
|
|
1682
|
-
const client = deps.getModelClient?.() ?? null;
|
|
1683
|
-
if (client === null) {
|
|
1684
|
-
promptedResult = silent("no_client");
|
|
1685
|
-
} else if (deps.backgroundEndpointBusy?.() === true) {
|
|
1686
|
-
tier = "llm";
|
|
1687
|
-
promptedStepTier = tier;
|
|
1688
|
-
promptedResult = silent("endpoint_busy");
|
|
1689
|
-
telemetryDecision = "dropped";
|
|
1690
|
-
} else {
|
|
1691
|
-
tier = "llm";
|
|
1692
|
-
promptedStepTier = tier;
|
|
1693
|
-
const runClient = (selected, timeoutMs) => runTaskMemoryPolicy(deps.bank, selected, {
|
|
1694
|
-
isCurrent,
|
|
1695
|
-
signal: generationController.signal,
|
|
1696
|
-
onStepUsage: (usage) => {
|
|
1697
|
-
if (usageSink) usageSink(usage, isCurrent());
|
|
1698
|
-
else deps.onStepUsage?.(usage);
|
|
1699
|
-
},
|
|
1700
|
-
task: input.task?.trim() || currentTask,
|
|
1701
|
-
trajectory: [...trajectory],
|
|
1702
|
-
deterministicTrigger: input.deterministicTrigger,
|
|
1703
|
-
maxTokens: live.maxTokens,
|
|
1704
|
-
modelMaxTokens: positiveInteger(deps.getModelMaxTokens?.(live.maxTokens), live.maxTokens),
|
|
1705
|
-
...input.suppressIntervention === void 0 ? {} : { suppressIntervention: input.suppressIntervention },
|
|
1706
|
-
previousReminder: lastInjectedMessage,
|
|
1707
|
-
timeoutMs,
|
|
1708
|
-
...deps.onEnvelope === void 0 ? {} : { onEnvelope: deps.onEnvelope }
|
|
1709
|
-
});
|
|
1710
|
-
const remainingMs = () => Math.floor(live.timeoutMs - Number(process.hrtime.bigint() - started) / 1e6);
|
|
1711
|
-
const initialTimeoutMs = remainingMs();
|
|
1712
|
-
promptedResult = initialTimeoutMs <= 0 ? { ...silent("deadline"), decision: "timeout" } : await runClient(client, initialTimeoutMs);
|
|
1713
|
-
if (promptedResult.reason === "client_error" && isCurrent() && remainingMs() > 0) {
|
|
1714
|
-
let fallback = null;
|
|
1715
|
-
let fallbackReady = false;
|
|
1716
|
-
try {
|
|
1717
|
-
fallback = deps.getFallbackModelClient?.() ?? null;
|
|
1718
|
-
fallbackReady = fallback !== null && deps.backgroundEndpointBusy?.() !== true;
|
|
1719
|
-
} catch {
|
|
1720
|
-
}
|
|
1721
|
-
const fallbackTimeoutMs = remainingMs();
|
|
1722
|
-
if (fallback !== null && fallbackReady && isCurrent() && fallbackTimeoutMs > 0) {
|
|
1723
|
-
emitTelemetry(
|
|
1724
|
-
triggers,
|
|
1725
|
-
tier,
|
|
1726
|
-
promptedResult.decision,
|
|
1727
|
-
promptedResult.reason,
|
|
1728
|
-
0,
|
|
1729
|
-
promptedResult.inputTokens,
|
|
1730
|
-
promptedResult.outputTokens,
|
|
1731
|
-
started,
|
|
1732
|
-
{ bankOperations: promptedResult.bankOperations, droppedOperations: promptedResult.droppedOperations }
|
|
1733
|
-
);
|
|
1734
|
-
attemptStarted = process.hrtime.bigint();
|
|
1735
|
-
promptedResult = await runClient(fallback, fallbackTimeoutMs);
|
|
1736
|
-
}
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
} catch (error) {
|
|
1741
|
-
promptedResult = silent("client_error");
|
|
1742
|
-
deps.onEnvelope?.({
|
|
1743
|
-
systemPrompt: "",
|
|
1744
|
-
userPrompt: "",
|
|
1745
|
-
response: "",
|
|
1746
|
-
decision: "silent",
|
|
1747
|
-
reason: "client_error",
|
|
1748
|
-
bankOperations: 0,
|
|
1749
|
-
droppedOperations: 0,
|
|
1750
|
-
reminder: null,
|
|
1751
|
-
error: error instanceof Error ? error.message : "resolving the background model client failed"
|
|
1752
|
-
});
|
|
1753
|
-
}
|
|
1754
|
-
if (!isCurrent()) return { ...promptedResult, reminder: null, effects: NO_EFFECTS3 };
|
|
1755
|
-
if (promptedResult.reason === "endpoint_busy") telemetryDecision = "dropped";
|
|
1756
|
-
if (tier === "llm" && promptedResult.decision === "timeout") consecutiveLlmTimeouts += 1;
|
|
1757
|
-
else if (tier === "llm" && telemetryDecision !== "dropped") consecutiveLlmTimeouts = 0;
|
|
1758
|
-
lastDecision = promptedResult.decision;
|
|
1759
|
-
if (promptedResult.decision === "injected") reportInjectedEntries(promptedResult.reminder);
|
|
1760
|
-
emitTelemetry(
|
|
1761
|
-
triggers,
|
|
1762
|
-
tier,
|
|
1763
|
-
telemetryDecision ?? promptedResult.decision,
|
|
1764
|
-
promptedResult.reason,
|
|
1765
|
-
citedEntryCount(promptedResult.reminder),
|
|
1766
|
-
promptedResult.inputTokens,
|
|
1767
|
-
promptedResult.outputTokens,
|
|
1768
|
-
attemptStarted,
|
|
1769
|
-
{ bankOperations: promptedResult.bankOperations, droppedOperations: promptedResult.droppedOperations }
|
|
1770
|
-
);
|
|
1771
|
-
return {
|
|
1772
|
-
...promptedResult,
|
|
1773
|
-
effects: promptedResult.reminder === null ? NO_EFFECTS3 : [{ kind: "inject_reminder", message: promptedResult.reminder, severity: "advisory" }]
|
|
1774
|
-
};
|
|
1775
|
-
}
|
|
1776
|
-
function emitTelemetry(triggerReasons, tier, decision, reason, citedEntries2, inputTokens, outputTokens, started, operations = { bankOperations: 0, droppedOperations: 0 }) {
|
|
1777
|
-
const next = deps.bank.snapshot();
|
|
1778
|
-
const bankDelta = taskMemoryBankDelta(telemetryBankSnapshot, next);
|
|
1779
|
-
telemetryBankSnapshot = next;
|
|
1780
|
-
const latencyMs = Number(process.hrtime.bigint() - started) / 1e6;
|
|
1781
|
-
try {
|
|
1782
|
-
deps.telemetry?.record({
|
|
1783
|
-
triggerReasons,
|
|
1784
|
-
tier,
|
|
1785
|
-
bankDelta,
|
|
1786
|
-
decision,
|
|
1787
|
-
reason,
|
|
1788
|
-
bankOperations: operations.bankOperations,
|
|
1789
|
-
droppedOperations: operations.droppedOperations,
|
|
1790
|
-
citedEntries: citedEntries2,
|
|
1791
|
-
inputTokens,
|
|
1792
|
-
outputTokens,
|
|
1793
|
-
latencyMs
|
|
1794
|
-
});
|
|
1795
|
-
} catch {
|
|
1796
|
-
}
|
|
1797
|
-
const event = {
|
|
1798
|
-
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1799
|
-
triggerReasons: [...new Set(triggerReasons)],
|
|
1800
|
-
tier,
|
|
1801
|
-
decision,
|
|
1802
|
-
reason,
|
|
1803
|
-
citedEntries: citedEntries2,
|
|
1804
|
-
bankWrites: countBankWrites(bankDelta),
|
|
1805
|
-
latencyMs
|
|
1806
|
-
};
|
|
1807
|
-
activity.unshift(event);
|
|
1808
|
-
if (activity.length > MEMORY_INTERVENTION_ACTIVITY_LIMIT) activity.length = MEMORY_INTERVENTION_ACTIVITY_LIMIT;
|
|
1809
|
-
}
|
|
1810
|
-
function citedEntries(message) {
|
|
1811
|
-
if (message === null) return [];
|
|
1812
|
-
const snapshot = deps.bank.snapshot();
|
|
1813
|
-
return [...snapshot.knowledge, ...snapshot.procedural].filter((entry) => message.includes(`[${entry.id}]`));
|
|
1814
|
-
}
|
|
1815
|
-
function citedEntryCount(message) {
|
|
1816
|
-
return citedEntries(message).length;
|
|
1817
|
-
}
|
|
1818
|
-
function reportInjectedEntries(reminder) {
|
|
1819
|
-
if (deps.onInjectedEntries === void 0) return;
|
|
1820
|
-
const entries = citedEntries(reminder);
|
|
1821
|
-
if (entries.length === 0) return;
|
|
1822
|
-
try {
|
|
1823
|
-
deps.onInjectedEntries(entries);
|
|
1824
|
-
} catch {
|
|
1825
|
-
}
|
|
1826
|
-
}
|
|
1827
|
-
function observeBeforeTool(input) {
|
|
1828
|
-
const prepared = prepareToolStep(input);
|
|
1829
|
-
if (prepared === null) return;
|
|
1830
|
-
setBounded(pending, pendingKey(input, prepared.operationFingerprint), prepared, settings().windowSteps);
|
|
1831
|
-
}
|
|
1832
|
-
function observeAfterTool(input) {
|
|
1833
|
-
const fallback = prepareToolStep(input);
|
|
1834
|
-
if (fallback === null) return NO_EFFECTS3;
|
|
1835
|
-
const key = pendingKey(input, fallback.operationFingerprint);
|
|
1836
|
-
const prepared = pending.get(key) ?? fallback;
|
|
1837
|
-
pending.delete(key);
|
|
1838
|
-
const outcome = input.metadata?.resultKind === "error" ? "error" : "ok";
|
|
1839
|
-
toolStep += 1;
|
|
1840
|
-
toolsSinceMemoryStep += 1;
|
|
1841
|
-
const live = settings();
|
|
1842
|
-
if (toolsSinceMemoryStep >= live.everyNTools) pendingTriggers.add("interval");
|
|
1843
|
-
if (outcome === "error") {
|
|
1844
|
-
consecutiveErrors += 1;
|
|
1845
|
-
if (consecutiveErrors >= 2) pendingTriggers.add("tool_error_streak");
|
|
1846
|
-
} else {
|
|
1847
|
-
consecutiveErrors = 0;
|
|
1848
|
-
}
|
|
1849
|
-
const digest = resultDigest(input, outcome);
|
|
1850
|
-
const step = {
|
|
1851
|
-
...prepared,
|
|
1852
|
-
step: toolStep,
|
|
1853
|
-
outcome,
|
|
1854
|
-
resultDigest: digest.text,
|
|
1855
|
-
resultDigestProvenance: digest.provenance
|
|
1856
|
-
};
|
|
1857
|
-
trajectory.push(step);
|
|
1858
|
-
if (trajectory.length > live.windowSteps) trajectory.splice(0, trajectory.length - live.windowSteps);
|
|
1859
|
-
if (outcome !== "error") return NO_EFFECTS3;
|
|
1860
|
-
rememberFailure(step);
|
|
1861
|
-
return annotateRepeatedFailure(step);
|
|
1862
|
-
}
|
|
1863
|
-
function annotateRepeatedFailure(step) {
|
|
1864
|
-
if (annotatedThisTurn.has(step.operationFingerprint)) return NO_EFFECTS3;
|
|
1865
|
-
const occurrences = trajectory.filter(
|
|
1866
|
-
(candidate) => candidate.outcome === "error" && candidate.operationFingerprint === step.operationFingerprint
|
|
1867
|
-
).length;
|
|
1868
|
-
const failure = failures.get(step.operationFingerprint);
|
|
1869
|
-
if (occurrences < 2 || failure === void 0) return NO_EFFECTS3;
|
|
1870
|
-
const message = boundedReminder(
|
|
1871
|
-
`Memory: [${failure.entryId}] you already tried ${failure.callDescription} at step ${failure.firstStep} and it failed with ${failure.errorDigest}. Change the approach rather than repeating it.`,
|
|
1872
|
-
settings().maxTokens
|
|
1873
|
-
);
|
|
1874
|
-
if (message.length === 0) return NO_EFFECTS3;
|
|
1875
|
-
annotatedThisTurn.add(step.operationFingerprint);
|
|
1876
|
-
lastInjectedOperationFingerprint = step.operationFingerprint;
|
|
1877
|
-
lastDecision = "injected";
|
|
1878
|
-
rulesInjectedSincePromptedStep = true;
|
|
1879
|
-
annotatedSinceTurnEnd = true;
|
|
1880
|
-
deps.bank.recordInjection([failure.entryId]);
|
|
1881
|
-
emitTelemetry(["repeated_failure"], "rules", "injected", "intervened", 1, 0, 0, process.hrtime.bigint());
|
|
1882
|
-
return [{ kind: "annotate_tool_result", message, severity: "warn" }];
|
|
1883
|
-
}
|
|
1884
|
-
function rememberFailure(step) {
|
|
1885
|
-
const previous = failures.get(step.operationFingerprint);
|
|
1886
|
-
const attempts = (previous?.attempts ?? 0) + 1;
|
|
1887
|
-
const firstStep = previous?.firstStep ?? step.step;
|
|
1888
|
-
const content = proceduralContent(step.callDescription, attempts, firstStep, step.resultDigest);
|
|
1889
|
-
let entryId;
|
|
1890
|
-
if (previous === void 0) {
|
|
1891
|
-
entryId = deps.bank.saveProcedural(content).id;
|
|
1892
|
-
} else {
|
|
1893
|
-
try {
|
|
1894
|
-
entryId = deps.bank.saveProcedural(content, { id: previous.entryId }).id;
|
|
1895
|
-
} catch {
|
|
1896
|
-
entryId = deps.bank.saveProcedural(content).id;
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
setBounded(
|
|
1900
|
-
failures,
|
|
1901
|
-
step.operationFingerprint,
|
|
1902
|
-
{
|
|
1903
|
-
entryId,
|
|
1904
|
-
attempts,
|
|
1905
|
-
firstStep,
|
|
1906
|
-
callDescription: step.callDescription,
|
|
1907
|
-
errorDigest: step.resultDigest
|
|
1908
|
-
},
|
|
1909
|
-
TASK_MEMORY_DEFAULT_PROCEDURAL_CAP
|
|
1910
|
-
);
|
|
1911
|
-
}
|
|
1912
|
-
function decideRepeatedFailure() {
|
|
1913
|
-
try {
|
|
1914
|
-
for (let index = trajectory.length - 1; index >= 0; index -= 1) {
|
|
1915
|
-
const step = trajectory[index];
|
|
1916
|
-
if (step === void 0 || step.outcome !== "error" || step.step <= lastTurnEndStep || step.operationFingerprint === lastInjectedOperationFingerprint) {
|
|
1917
|
-
continue;
|
|
1918
|
-
}
|
|
1919
|
-
const occurrences = trajectory.filter(
|
|
1920
|
-
(candidate) => candidate.outcome === "error" && candidate.operationFingerprint === step.operationFingerprint
|
|
1921
|
-
).length;
|
|
1922
|
-
const failure = failures.get(step.operationFingerprint);
|
|
1923
|
-
if (occurrences < 2 || failure === void 0) continue;
|
|
1924
|
-
const message = boundedReminder(
|
|
1925
|
-
`Memory: [${failure.entryId}] you already tried ${failure.callDescription} at step ${failure.firstStep} and it failed with ${failure.errorDigest}.`,
|
|
1926
|
-
settings().maxTokens
|
|
1927
|
-
);
|
|
1928
|
-
if (message.length === 0) return NO_EFFECTS3;
|
|
1929
|
-
lastInjectedOperationFingerprint = step.operationFingerprint;
|
|
1930
|
-
lastInjectedMessage = message;
|
|
1931
|
-
lastDecision = "injected";
|
|
1932
|
-
rulesInjectedSincePromptedStep = true;
|
|
1933
|
-
deps.bank.recordInjection([failure.entryId]);
|
|
1934
|
-
return [{ kind: "inject_reminder", message, severity: "advisory" }];
|
|
1935
|
-
}
|
|
1936
|
-
lastDecision = "silent";
|
|
1937
|
-
return NO_EFFECTS3;
|
|
1938
|
-
} finally {
|
|
1939
|
-
lastTurnEndStep = toolStep;
|
|
1940
|
-
}
|
|
1941
|
-
}
|
|
1942
|
-
function reactivateKnowledge() {
|
|
1943
|
-
if (!reactivateAfterCompaction) return NO_EFFECTS3;
|
|
1944
|
-
reactivateAfterCompaction = false;
|
|
1945
|
-
const prefix = "Memory: execution state restored after compaction:\n";
|
|
1946
|
-
const maxTokens = settings().maxTokens;
|
|
1947
|
-
const prefixTokens = ceilChars(prefix.length);
|
|
1948
|
-
const rendered = deps.bank.renderRestoredState(Math.max(0, maxTokens - prefixTokens));
|
|
1949
|
-
if (rendered.length === 0) {
|
|
1950
|
-
lastDecision = "silent";
|
|
1951
|
-
return NO_EFFECTS3;
|
|
1952
|
-
}
|
|
1953
|
-
const message = boundedReminder(`${prefix}${rendered}`, maxTokens);
|
|
1954
|
-
if (message.length === 0) {
|
|
1955
|
-
lastDecision = "silent";
|
|
1956
|
-
return NO_EFFECTS3;
|
|
1957
|
-
}
|
|
1958
|
-
const citedIds = [...message.matchAll(/\[([^\]]+)\]/gu)].map((match) => match[1]).filter((id) => id !== void 0);
|
|
1959
|
-
deps.bank.recordInjection(citedIds);
|
|
1960
|
-
lastInjectedMessage = message;
|
|
1961
|
-
lastDecision = "injected";
|
|
1962
|
-
return [{ kind: "inject_reminder", message, severity: "advisory" }];
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
function prepareToolStep(input) {
|
|
1966
|
-
const toolName = input.toolName?.trim();
|
|
1967
|
-
if (!toolName) return null;
|
|
1968
|
-
const canonical = hashToolCall(toolName, input.toolArgs ?? {});
|
|
1969
|
-
return {
|
|
1970
|
-
toolName,
|
|
1971
|
-
operationFingerprint: createHash("sha256").update(canonical).digest("hex").slice(0, 16),
|
|
1972
|
-
callDescription: shortText(canonical, CALL_DESCRIPTION_MAX_CHARS)
|
|
1973
|
-
};
|
|
1974
|
-
}
|
|
1975
|
-
function pendingKey(input, operationFingerprint) {
|
|
1976
|
-
return input.toolCallId ?? `anonymous:${operationFingerprint}`;
|
|
1977
|
-
}
|
|
1978
|
-
function resultDigest(input, outcome) {
|
|
1979
|
-
if (input.toolResultDigest !== void 0) return sanitizeToolResultDigest(input.toolResultDigest);
|
|
1980
|
-
if (outcome === "error") {
|
|
1981
|
-
const metadataMessage = input.metadata?.errorMessage;
|
|
1982
|
-
if (typeof metadataMessage === "string" && metadataMessage.trim().length > 0) {
|
|
1983
|
-
return legacyToolResultDigest(diagnosticLine(metadataMessage), { outcome });
|
|
1984
|
-
}
|
|
1985
|
-
for (const key of ["error", "message"]) {
|
|
1986
|
-
const value = input.toolResultDetails?.[key];
|
|
1987
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
1988
|
-
return legacyToolResultDigest(diagnosticLine(value), { outcome });
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
return legacyToolResultDigest("", { outcome });
|
|
1992
|
-
}
|
|
1993
|
-
const resultFingerprint = input.metadata?.resultFingerprint;
|
|
1994
|
-
return legacyToolResultDigest(
|
|
1995
|
-
typeof resultFingerprint === "string" ? `ok result ${resultFingerprint.slice(0, 16)}` : "ok",
|
|
1996
|
-
{ outcome }
|
|
1997
|
-
);
|
|
1998
|
-
}
|
|
1999
|
-
var DIAGNOSTIC_HINT = /\b(error|failed|failure|cannot|unable|expected|refused|denied|missing|not found|timed out|timeout|fatal)\b/iu;
|
|
2000
|
-
function diagnosticLine(value) {
|
|
2001
|
-
const lines = value.split(/\r?\n/u).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
2002
|
-
return lines.find((line) => DIAGNOSTIC_HINT.test(line)) ?? lines[0] ?? "";
|
|
2003
|
-
}
|
|
2004
|
-
function proceduralContent(call, attempts, firstStep, error) {
|
|
2005
|
-
return `${call} failed ${attempts} time${attempts === 1 ? "" : "s"}; first observed at step ${firstStep}: ${error}.`;
|
|
2006
|
-
}
|
|
2007
|
-
function boundedReminder(message, maxTokens) {
|
|
2008
|
-
const maxChars = maxTokens * 4;
|
|
2009
|
-
if (maxChars <= 0) return "";
|
|
2010
|
-
const normalized = message.replace(/[^\S\n]+/gu, " ").trim();
|
|
2011
|
-
return normalized.length <= maxChars ? normalized : normalized.slice(0, maxChars).trimEnd();
|
|
2012
|
-
}
|
|
2013
|
-
function shortText(value, maxChars) {
|
|
2014
|
-
const normalized = value.replace(/\s+/gu, " ").trim();
|
|
2015
|
-
return normalized.length <= maxChars ? normalized : `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
|
|
2016
|
-
}
|
|
2017
|
-
function positiveInteger(value, fallback) {
|
|
2018
|
-
return value !== void 0 && Number.isInteger(value) && value > 0 ? value : fallback;
|
|
2019
|
-
}
|
|
2020
|
-
function countBankWrites(delta) {
|
|
2021
|
-
return [delta.status, delta.knowledge, delta.procedural].reduce(
|
|
2022
|
-
(total, entry) => total + entry.added + entry.updated + entry.deleted,
|
|
2023
|
-
0
|
|
2024
|
-
);
|
|
2025
|
-
}
|
|
2026
|
-
function setBounded(map, key, value, capacity) {
|
|
2027
|
-
if (!map.has(key) && map.size >= capacity) {
|
|
2028
|
-
const oldest = map.keys().next().value;
|
|
2029
|
-
if (oldest !== void 0) map.delete(oldest);
|
|
2030
|
-
}
|
|
2031
|
-
map.set(key, value);
|
|
2032
|
-
}
|
|
2033
|
-
|
|
2034
|
-
// src/domains/middleware/memory-step-endpoint.ts
|
|
2035
|
-
init_esm_shims();
|
|
2036
|
-
function announceMemoryStepEndpoint(deps, complete) {
|
|
2037
|
-
const { bus, endpointKey, targetId } = deps;
|
|
2038
|
-
if (endpointKey === null) return complete;
|
|
2039
|
-
return async (request) => {
|
|
2040
|
-
const releaseEndpointSlot = registerForegroundStream(endpointKey);
|
|
2041
|
-
try {
|
|
2042
|
-
return await complete(request);
|
|
2043
|
-
} finally {
|
|
2044
|
-
releaseEndpointSlot();
|
|
2045
|
-
if (bus !== null) {
|
|
2046
|
-
try {
|
|
2047
|
-
bus.emit(BusChannels.MemoryStepCompleted, { endpointKey, targetId });
|
|
2048
|
-
} catch {
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
};
|
|
2053
|
-
}
|
|
2054
|
-
|
|
2055
|
-
// src/domains/middleware/task-board-reminder.ts
|
|
2056
|
-
init_esm_shims();
|
|
2057
|
-
var TASK_BOARD_REMINDER_REGISTRATION_ID = "observer.task-board-reminder";
|
|
2058
|
-
function taskBoardReminderMessage(steps) {
|
|
2059
|
-
return `[Tasks] This request enumerates ${steps} steps. Before the first edit, declare the task board: tasks action="plan" with a title and one task per authorized step, then work them one at a time ("start", then "done" with an evidence note). A plan does not authorize implementation: for proposed work awaiting an operator go-ahead, use action="block" with a note naming the pending operator decision, or action="drop", and wait.`;
|
|
2060
|
-
}
|
|
2061
|
-
function countEnumeratedSteps(text) {
|
|
2062
|
-
const value = text ?? "";
|
|
2063
|
-
if (value.trim().length === 0) return 0;
|
|
2064
|
-
const markers = [];
|
|
2065
|
-
const markerPattern = /(?:^|[\s(])(?:step\s+)?([1-9])\s*[).:]\s/gi;
|
|
2066
|
-
let match = markerPattern.exec(value);
|
|
2067
|
-
while (match !== null) {
|
|
2068
|
-
const digit = Number(match[1]);
|
|
2069
|
-
if (Number.isInteger(digit)) markers.push(digit);
|
|
2070
|
-
match = markerPattern.exec(value);
|
|
2071
|
-
}
|
|
2072
|
-
let run = 0;
|
|
2073
|
-
for (const digit of markers) {
|
|
2074
|
-
if (digit === run + 1) run += 1;
|
|
2075
|
-
else if (digit === 1) run = 1;
|
|
2076
|
-
}
|
|
2077
|
-
if (run >= 3) return run;
|
|
2078
|
-
const bulletLines = value.split(/\r?\n/).filter((line) => /^\s*[-*]\s+\S/.test(line)).length;
|
|
2079
|
-
return bulletLines >= 3 ? bulletLines : 0;
|
|
2080
|
-
}
|
|
2081
|
-
var NO_EFFECTS4 = [];
|
|
2082
|
-
function createTaskBoardReminderRegistration() {
|
|
2083
|
-
let lastSeenSessionId;
|
|
2084
|
-
let spentForActiveSession = false;
|
|
2085
|
-
return {
|
|
2086
|
-
id: TASK_BOARD_REMINDER_REGISTRATION_ID,
|
|
2087
|
-
description: "once per session, on the first explicitly enumerated multi-step turn, teaches the board-first protocol",
|
|
2088
|
-
hooks: ["turn_start"],
|
|
2089
|
-
evaluate(input) {
|
|
2090
|
-
const sessionId = input.sessionId ?? null;
|
|
2091
|
-
if (lastSeenSessionId === void 0 || lastSeenSessionId === null && sessionId !== null) {
|
|
2092
|
-
lastSeenSessionId = sessionId;
|
|
2093
|
-
} else if (sessionId !== lastSeenSessionId) {
|
|
2094
|
-
lastSeenSessionId = sessionId;
|
|
2095
|
-
spentForActiveSession = false;
|
|
2096
|
-
}
|
|
2097
|
-
if (spentForActiveSession) return NO_EFFECTS4;
|
|
2098
|
-
const steps = countEnumeratedSteps(input.text);
|
|
2099
|
-
if (steps < 3) return NO_EFFECTS4;
|
|
2100
|
-
spentForActiveSession = true;
|
|
2101
|
-
const pendingSkillRequests = metadataNumber(input, "pendingSkillRequests");
|
|
2102
|
-
if (pendingSkillRequests !== null && pendingSkillRequests > 0) return NO_EFFECTS4;
|
|
2103
|
-
return [{ kind: "inject_reminder", severity: "info", message: taskBoardReminderMessage(steps) }];
|
|
2104
|
-
}
|
|
2105
|
-
};
|
|
2106
|
-
}
|
|
2107
|
-
|
|
2108
|
-
// src/domains/middleware/task-nudge.ts
|
|
2109
|
-
init_esm_shims();
|
|
2110
|
-
var TASK_NUDGE_REGISTRATION_ID = "nudge.open-tasks";
|
|
2111
|
-
function openTasks(board) {
|
|
2112
|
-
return board.tasks.filter((task) => task.status === "pending" || task.status === "active");
|
|
2113
|
-
}
|
|
2114
|
-
function buildOpenTasksMessage(board) {
|
|
2115
|
-
const open = openTasks(board);
|
|
2116
|
-
const counts = taskBoardCounts(board);
|
|
2117
|
-
const rows = open.map((task) => ` ${task.status === "active" ? "[>]" : "[ ]"} ${task.id} ${task.title}`);
|
|
2118
|
-
return `[Clio Coder] task board "${board.title}" still has ${open.length} of ${counts.total} task(s) open:
|
|
2119
|
-
${rows.join("\n")}
|
|
2120
|
-
Continue only work already authorized by the operator. This reminder and a self-created plan are not authorization to implement a proposal. If implementation awaits an operator decision, use tasks action="block" with a note naming that pending operator decision, or action="drop"; then wait for an explicit operator go-ahead. A skill-install choice does not authorize implementation. Otherwise record the honest state on the board: tasks action="done" with an evidence note, action="block" with a reason, or action="drop". Do not end the turn with a stale board.`;
|
|
2121
|
-
}
|
|
2122
|
-
function createTaskNudgeRegistration(options) {
|
|
2123
|
-
return {
|
|
2124
|
-
id: TASK_NUDGE_REGISTRATION_ID,
|
|
2125
|
-
description: "carry the turn onward when a work turn ends with open task-board tasks",
|
|
2126
|
-
hooks: ["turn_end"],
|
|
2127
|
-
evaluate(input) {
|
|
2128
|
-
if (input.hook !== "turn_end") return [];
|
|
2129
|
-
const stopReason = input.metadata?.stopReason;
|
|
2130
|
-
if (stopReason !== void 0 && stopReason !== "stop") return [];
|
|
2131
|
-
const turnToolCalls = input.metadata?.turnToolCalls;
|
|
2132
|
-
if (typeof turnToolCalls !== "number" || turnToolCalls <= 0) return [];
|
|
2133
|
-
const activeToolNames = input.metadata?.activeToolNames;
|
|
2134
|
-
if (typeof activeToolNames === "string" && !activeToolNames.split(",").includes(ToolNames.Tasks)) return [];
|
|
2135
|
-
let board;
|
|
2136
|
-
try {
|
|
2137
|
-
board = options.getBoard();
|
|
2138
|
-
} catch {
|
|
2139
|
-
return [];
|
|
2140
|
-
}
|
|
2141
|
-
if (board === null || openTasks(board).length === 0) return [];
|
|
2142
|
-
const message = buildOpenTasksMessage(board);
|
|
2143
|
-
return [
|
|
2144
|
-
{ kind: "request_continuation", message },
|
|
2145
|
-
{ kind: "inject_reminder", message, severity: "warn" }
|
|
2146
|
-
];
|
|
2147
|
-
}
|
|
2148
|
-
};
|
|
2149
|
-
}
|
|
2150
|
-
|
|
2151
|
-
// src/domains/middleware/tool-choice-control.ts
|
|
2152
|
-
init_esm_shims();
|
|
2153
|
-
function createMiddlewareToolChoiceControl() {
|
|
2154
|
-
let choice = { kind: "auto" };
|
|
2155
|
-
return {
|
|
2156
|
-
apply(effects) {
|
|
2157
|
-
for (const effect of effects) {
|
|
2158
|
-
if (effect.kind === "lock_tools") {
|
|
2159
|
-
choice = { kind: "none" };
|
|
2160
|
-
continue;
|
|
2161
|
-
}
|
|
2162
|
-
if (effect.kind === "require_tool" && choice.kind !== "none") {
|
|
2163
|
-
choice = { kind: "required", toolName: effect.toolName };
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
},
|
|
2167
|
-
current: () => choice,
|
|
2168
|
-
toolStarted(toolName) {
|
|
2169
|
-
if (choice.kind === "required" && choice.toolName === toolName) choice = { kind: "auto" };
|
|
2170
|
-
},
|
|
2171
|
-
reset() {
|
|
2172
|
-
choice = { kind: "auto" };
|
|
2173
|
-
}
|
|
2174
|
-
};
|
|
2175
|
-
}
|
|
2176
|
-
|
|
2177
|
-
// src/domains/middleware/watchdog.ts
|
|
2178
|
-
init_esm_shims();
|
|
2179
|
-
var WATCHDOG_REGISTRATION_ID = "observer.watchdog";
|
|
2180
|
-
var WATCHDOG_DIFF_MAX_BYTES = 12 * 1024;
|
|
2181
|
-
var WATCHDOG_PATHS_MAX = 40;
|
|
2182
|
-
var WATCHDOG_TRUNCATION_MARKER = "\n[diff truncated]";
|
|
2183
|
-
var MUTATING_TOOL_NAMES = /* @__PURE__ */ new Set([ToolNames.Write, ToolNames.Edit, ToolNames.Artifact]);
|
|
2184
|
-
var NO_EFFECTS5 = [];
|
|
2185
|
-
function stringValue2(value) {
|
|
2186
|
-
return typeof value === "string" && value.length > 0 ? value : null;
|
|
2187
|
-
}
|
|
2188
|
-
function firstPath(details) {
|
|
2189
|
-
const paths = details?.paths;
|
|
2190
|
-
if (!Array.isArray(paths)) return null;
|
|
2191
|
-
for (const entry of paths) {
|
|
2192
|
-
const path2 = stringValue2(entry);
|
|
2193
|
-
if (path2 !== null) return path2;
|
|
2194
|
-
}
|
|
2195
|
-
return null;
|
|
2196
|
-
}
|
|
2197
|
-
function coalesceTurnDiff(byPath, maxBytes = WATCHDOG_DIFF_MAX_BYTES) {
|
|
2198
|
-
const blocks = [];
|
|
2199
|
-
let index = 0;
|
|
2200
|
-
for (const [path2, diff] of byPath) {
|
|
2201
|
-
if (index >= WATCHDOG_PATHS_MAX) {
|
|
2202
|
-
blocks.push(`[${byPath.size - WATCHDOG_PATHS_MAX} more changed path(s) omitted]`);
|
|
2203
|
-
break;
|
|
2204
|
-
}
|
|
2205
|
-
blocks.push(`--- ${path2}
|
|
2206
|
-
${diff}`);
|
|
2207
|
-
index += 1;
|
|
2208
|
-
}
|
|
2209
|
-
const whole = blocks.join("\n\n");
|
|
2210
|
-
if (Buffer.byteLength(whole, "utf8") <= maxBytes) return whole;
|
|
2211
|
-
const room = Math.max(0, maxBytes - Buffer.byteLength(WATCHDOG_TRUNCATION_MARKER, "utf8"));
|
|
2212
|
-
const buffer = Buffer.from(whole, "utf8");
|
|
2213
|
-
let cut = Math.min(room, buffer.byteLength);
|
|
2214
|
-
while (cut > 0) {
|
|
2215
|
-
const next = buffer[cut];
|
|
2216
|
-
if (next === void 0 || (next & 192) !== 128) break;
|
|
2217
|
-
cut -= 1;
|
|
2218
|
-
}
|
|
2219
|
-
return `${buffer.subarray(0, cut).toString("utf8")}${WATCHDOG_TRUNCATION_MARKER}`;
|
|
2220
|
-
}
|
|
2221
|
-
var WATCHDOG_TASK = "Review the coalesced diff in the briefing against the scope it names. Report one check per concern: a change outside the stated scope, a change the scope required that the diff does not make, or a defect visible in the diff itself. Run no commands and change nothing.";
|
|
2222
|
-
function watchdogBriefing(trigger) {
|
|
2223
|
-
const scope = trigger.scope === null ? "(no task board; scope is unstated)" : trigger.scope;
|
|
2224
|
-
const paths = trigger.paths.length === 0 ? "(none)" : trigger.paths.join("\n");
|
|
2225
|
-
return [
|
|
2226
|
-
"## Current scope",
|
|
2227
|
-
scope,
|
|
2228
|
-
"",
|
|
2229
|
-
"## Changed paths",
|
|
2230
|
-
paths,
|
|
2231
|
-
"",
|
|
2232
|
-
"## Coalesced diff for this turn",
|
|
2233
|
-
trigger.diff
|
|
2234
|
-
].join("\n");
|
|
2235
|
-
}
|
|
2236
|
-
function createWatchdogRegistration(deps) {
|
|
2237
|
-
const diffByPath = /* @__PURE__ */ new Map();
|
|
2238
|
-
let toolCalls = 0;
|
|
2239
|
-
let dropped = 0;
|
|
2240
|
-
let inFlight = false;
|
|
2241
|
-
let outstanding = Promise.resolve();
|
|
2242
|
-
const active = () => {
|
|
2243
|
-
if (deps.firesOnThisSurface === false) return null;
|
|
2244
|
-
let settings;
|
|
2245
|
-
try {
|
|
2246
|
-
settings = deps.getSettings();
|
|
2247
|
-
} catch {
|
|
2248
|
-
return null;
|
|
2249
|
-
}
|
|
2250
|
-
return settings.enabled ? settings : null;
|
|
2251
|
-
};
|
|
2252
|
-
const resetTurn = () => {
|
|
2253
|
-
diffByPath.clear();
|
|
2254
|
-
toolCalls = 0;
|
|
2255
|
-
};
|
|
2256
|
-
const fire = (reason) => {
|
|
2257
|
-
if (diffByPath.size === 0) return;
|
|
2258
|
-
if (inFlight) {
|
|
2259
|
-
dropped += 1;
|
|
2260
|
-
return;
|
|
2261
|
-
}
|
|
2262
|
-
const trigger = {
|
|
2263
|
-
reason,
|
|
2264
|
-
diff: coalesceTurnDiff(diffByPath),
|
|
2265
|
-
paths: [...diffByPath.keys()].slice(0, WATCHDOG_PATHS_MAX),
|
|
2266
|
-
scope: scopeNow(),
|
|
2267
|
-
toolCalls
|
|
2268
|
-
};
|
|
2269
|
-
inFlight = true;
|
|
2270
|
-
let started;
|
|
2271
|
-
try {
|
|
2272
|
-
started = deps.run(trigger);
|
|
2273
|
-
} catch {
|
|
2274
|
-
inFlight = false;
|
|
2275
|
-
return;
|
|
2276
|
-
}
|
|
2277
|
-
outstanding = started.catch(() => {
|
|
2278
|
-
}).finally(() => {
|
|
2279
|
-
inFlight = false;
|
|
2280
|
-
});
|
|
2281
|
-
};
|
|
2282
|
-
const scopeNow = () => {
|
|
2283
|
-
try {
|
|
2284
|
-
return deps.getScope?.() ?? null;
|
|
2285
|
-
} catch {
|
|
2286
|
-
return null;
|
|
2287
|
-
}
|
|
2288
|
-
};
|
|
2289
|
-
return {
|
|
2290
|
-
id: WATCHDOG_REGISTRATION_ID,
|
|
2291
|
-
description: "review a mutating turn's coalesced diff against the board scope with a read-only verifier run",
|
|
2292
|
-
hooks: ["after_tool", "turn_end"],
|
|
2293
|
-
evaluate(input) {
|
|
2294
|
-
const settings = active();
|
|
2295
|
-
if (settings === null) {
|
|
2296
|
-
if (input.hook === "turn_end") resetTurn();
|
|
2297
|
-
return NO_EFFECTS5;
|
|
2298
|
-
}
|
|
2299
|
-
if (input.hook === "after_tool") {
|
|
2300
|
-
toolCalls += 1;
|
|
2301
|
-
recordMutation(input);
|
|
2302
|
-
const cadence = settings.cadenceToolCalls;
|
|
2303
|
-
if (cadence !== void 0 && cadence >= 1 && toolCalls % cadence === 0) fire("cadence");
|
|
2304
|
-
return NO_EFFECTS5;
|
|
2305
|
-
}
|
|
2306
|
-
if (input.hook !== "turn_end") return NO_EFFECTS5;
|
|
2307
|
-
fire("turn_end");
|
|
2308
|
-
resetTurn();
|
|
2309
|
-
return NO_EFFECTS5;
|
|
2310
|
-
},
|
|
2311
|
-
droppedTriggers: () => dropped,
|
|
2312
|
-
runInFlight: () => inFlight,
|
|
2313
|
-
whenIdle: () => outstanding
|
|
2314
|
-
};
|
|
2315
|
-
function recordMutation(input) {
|
|
2316
|
-
if (input.metadata?.resultKind !== "ok") return;
|
|
2317
|
-
if (input.toolName === void 0 || !MUTATING_TOOL_NAMES.has(input.toolName)) return;
|
|
2318
|
-
const diff = stringValue2(input.toolResultDetails?.diff);
|
|
2319
|
-
if (diff === null) return;
|
|
2320
|
-
diffByPath.set(firstPath(input.toolResultDetails) ?? input.toolName, diff);
|
|
2321
|
-
}
|
|
2322
|
-
}
|
|
2323
|
-
|
|
2324
|
-
// src/domains/middleware/index.ts
|
|
2325
|
-
init_esm_shims();
|
|
2326
|
-
|
|
2327
|
-
// src/domains/middleware/extension.ts
|
|
2328
|
-
init_esm_shims();
|
|
2329
|
-
|
|
2330
|
-
// src/domains/middleware/registrations.ts
|
|
2331
|
-
init_esm_shims();
|
|
2332
|
-
var MIDDLEWARE_REGISTRATION_OWNERS = ["user-hooks"];
|
|
2333
|
-
function isRegistrationOwner(value) {
|
|
2334
|
-
return MIDDLEWARE_REGISTRATION_OWNERS.includes(value);
|
|
2335
|
-
}
|
|
2336
|
-
function createMiddlewareRegistrationTable(options) {
|
|
2337
|
-
const fixed = Object.freeze([...options.fixed]);
|
|
2338
|
-
const fixedIds = new Set(fixed.map((registration) => registration.id));
|
|
2339
|
-
const buildList = (host, slots) => {
|
|
2340
|
-
const list = [...fixed];
|
|
2341
|
-
const slotAt = (index) => {
|
|
2342
|
-
for (const owner of MIDDLEWARE_REGISTRATION_OWNERS) {
|
|
2343
|
-
const slot = slots.get(owner);
|
|
2344
|
-
if (slot !== void 0 && slot.anchor === index) list.push(...slot.registrations);
|
|
2345
|
-
}
|
|
2346
|
-
};
|
|
2347
|
-
for (let index = 0; index < host.length; index += 1) {
|
|
2348
|
-
slotAt(index);
|
|
2349
|
-
list.push(host[index]);
|
|
2350
|
-
}
|
|
2351
|
-
slotAt(host.length);
|
|
2352
|
-
return Object.freeze(list);
|
|
2353
|
-
};
|
|
2354
|
-
const makeState = (host, slots) => Object.freeze({
|
|
2355
|
-
host: Object.freeze([...host]),
|
|
2356
|
-
hostIds: new Set(host.map((registration) => registration.id)),
|
|
2357
|
-
slots: new Map(slots),
|
|
2358
|
-
list: buildList(host, slots)
|
|
2359
|
-
});
|
|
2360
|
-
let state = makeState([], /* @__PURE__ */ new Map());
|
|
2361
|
-
const emit = (diagnostic) => {
|
|
2362
|
-
try {
|
|
2363
|
-
options.diagnosticSink()(diagnostic);
|
|
2364
|
-
} catch {
|
|
2365
|
-
}
|
|
2366
|
-
};
|
|
2367
|
-
const slotFor = (base, owner) => base.slots.get(owner) ?? { generation: 0, registrations: [], anchor: base.host.length };
|
|
2368
|
-
const disposeGeneration = (owner, generation) => {
|
|
2369
|
-
const base = state;
|
|
2370
|
-
const held = base.slots.get(owner);
|
|
2371
|
-
if (held === void 0 || held.generation !== generation || held.registrations.length === 0) return;
|
|
2372
|
-
const slots = new Map(base.slots);
|
|
2373
|
-
slots.set(owner, { ...held, registrations: Object.freeze([]) });
|
|
2374
|
-
state = makeState(base.host, slots);
|
|
2375
|
-
};
|
|
2376
|
-
const table = {
|
|
2377
|
-
list: () => state.list,
|
|
2378
|
-
registerHook(registration) {
|
|
2379
|
-
const base = state;
|
|
2380
|
-
if (fixedIds.has(registration.id) || base.hostIds.has(registration.id)) return;
|
|
2381
|
-
const evictions = [];
|
|
2382
|
-
const slots = new Map(base.slots);
|
|
2383
|
-
for (const [owner, slot] of base.slots) {
|
|
2384
|
-
if (!slot.registrations.some((entry) => entry.id === registration.id)) continue;
|
|
2385
|
-
slots.set(owner, {
|
|
2386
|
-
...slot,
|
|
2387
|
-
registrations: Object.freeze(slot.registrations.filter((entry) => entry.id !== registration.id))
|
|
2388
|
-
});
|
|
2389
|
-
evictions.push({
|
|
2390
|
-
kind: "registration_conflict",
|
|
2391
|
-
registrationId: registration.id,
|
|
2392
|
-
owner,
|
|
2393
|
-
generation: slot.generation,
|
|
2394
|
-
conflictsWith: "host",
|
|
2395
|
-
action: "evicted"
|
|
2396
|
-
});
|
|
2397
|
-
}
|
|
2398
|
-
state = makeState([...base.host, registration], slots);
|
|
2399
|
-
for (const eviction of evictions) emit(eviction);
|
|
2400
|
-
},
|
|
2401
|
-
prepareReplacement(owner, generation, registrations) {
|
|
2402
|
-
if (!isRegistrationOwner(owner)) {
|
|
2403
|
-
return { status: "rejected", owner, reason: "unknown-owner", activeGeneration: 0 };
|
|
2404
|
-
}
|
|
2405
|
-
const base = state;
|
|
2406
|
-
const slot = slotFor(base, owner);
|
|
2407
|
-
if (!Number.isInteger(generation) || generation <= slot.generation) {
|
|
2408
|
-
return { status: "rejected", owner, reason: "stale", activeGeneration: slot.generation };
|
|
2409
|
-
}
|
|
2410
|
-
const dropped = [];
|
|
2411
|
-
const conflicts = [];
|
|
2412
|
-
const accepted = [];
|
|
2413
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2414
|
-
for (const registration of registrations) {
|
|
2415
|
-
const conflictsWith = fixedIds.has(registration.id) ? "builtin" : base.hostIds.has(registration.id) ? "host" : seen.has(registration.id) ? "owned" : null;
|
|
2416
|
-
if (conflictsWith !== null) {
|
|
2417
|
-
dropped.push({ id: registration.id, conflictsWith });
|
|
2418
|
-
conflicts.push({
|
|
2419
|
-
kind: "registration_conflict",
|
|
2420
|
-
registrationId: registration.id,
|
|
2421
|
-
owner,
|
|
2422
|
-
generation,
|
|
2423
|
-
conflictsWith,
|
|
2424
|
-
action: "dropped"
|
|
2425
|
-
});
|
|
2426
|
-
continue;
|
|
2427
|
-
}
|
|
2428
|
-
seen.add(registration.id);
|
|
2429
|
-
accepted.push(registration);
|
|
2430
|
-
}
|
|
2431
|
-
const slots = new Map(base.slots);
|
|
2432
|
-
slots.set(owner, { generation, registrations: Object.freeze(accepted), anchor: slot.anchor });
|
|
2433
|
-
const prepared = makeState(base.host, slots);
|
|
2434
|
-
let settled = false;
|
|
2435
|
-
const frozenDropped = Object.freeze(dropped);
|
|
2436
|
-
const frozenConflicts = Object.freeze(conflicts);
|
|
2437
|
-
const replacement = {
|
|
2438
|
-
owner,
|
|
2439
|
-
generation,
|
|
2440
|
-
dropped: frozenDropped,
|
|
2441
|
-
conflicts: frozenConflicts,
|
|
2442
|
-
size: accepted.length,
|
|
2443
|
-
// Reference identity on the base state covers every kind of
|
|
2444
|
-
// intervening change: host appends, other replacements, disposals.
|
|
2445
|
-
current: () => !settled && state === base,
|
|
2446
|
-
publish() {
|
|
2447
|
-
settled = true;
|
|
2448
|
-
state = prepared;
|
|
2449
|
-
},
|
|
2450
|
-
emitConflicts() {
|
|
2451
|
-
for (const conflict of frozenConflicts) emit(conflict);
|
|
2452
|
-
},
|
|
2453
|
-
dispose() {
|
|
2454
|
-
disposeGeneration(owner, generation);
|
|
2455
|
-
},
|
|
2456
|
-
discard() {
|
|
2457
|
-
settled = true;
|
|
2458
|
-
}
|
|
2459
|
-
};
|
|
2460
|
-
return { status: "prepared", replacement };
|
|
2461
|
-
},
|
|
2462
|
-
replaceRegistrations(owner, generation, registrations) {
|
|
2463
|
-
const prepared = table.prepareReplacement(owner, generation, registrations);
|
|
2464
|
-
if (prepared.status === "rejected") {
|
|
2465
|
-
return {
|
|
2466
|
-
applied: false,
|
|
2467
|
-
owner: prepared.owner,
|
|
2468
|
-
activeGeneration: prepared.activeGeneration,
|
|
2469
|
-
reason: prepared.reason,
|
|
2470
|
-
dropped: [],
|
|
2471
|
-
dispose: () => void 0
|
|
2472
|
-
};
|
|
2473
|
-
}
|
|
2474
|
-
const replacement = prepared.replacement;
|
|
2475
|
-
if (!replacement.current()) {
|
|
2476
|
-
replacement.discard();
|
|
2477
|
-
return {
|
|
2478
|
-
applied: false,
|
|
2479
|
-
owner,
|
|
2480
|
-
activeGeneration: table.ownedGeneration(owner),
|
|
2481
|
-
reason: "stale",
|
|
2482
|
-
dropped: replacement.dropped,
|
|
2483
|
-
dispose: () => void 0
|
|
2484
|
-
};
|
|
2485
|
-
}
|
|
2486
|
-
replacement.publish();
|
|
2487
|
-
replacement.emitConflicts();
|
|
2488
|
-
return {
|
|
2489
|
-
applied: true,
|
|
2490
|
-
owner,
|
|
2491
|
-
activeGeneration: generation,
|
|
2492
|
-
dropped: replacement.dropped,
|
|
2493
|
-
dispose: () => replacement.dispose()
|
|
2494
|
-
};
|
|
2495
|
-
},
|
|
2496
|
-
ownedGeneration(owner) {
|
|
2497
|
-
return state.slots.get(owner)?.generation ?? 0;
|
|
2498
|
-
}
|
|
2499
|
-
};
|
|
2500
|
-
return table;
|
|
2501
|
-
}
|
|
2502
|
-
|
|
2503
|
-
// src/domains/middleware/snapshot.ts
|
|
2504
|
-
init_esm_shims();
|
|
2505
|
-
function createMiddlewareSnapshot(rules = listMiddlewareRules()) {
|
|
2506
|
-
return {
|
|
2507
|
-
version: 1,
|
|
2508
|
-
rules: rules.map(cloneMiddlewareRule)
|
|
2509
|
-
};
|
|
2510
|
-
}
|
|
2511
|
-
function createMiddlewareContractFromSnapshot(snapshot) {
|
|
2512
|
-
const builtinById = new Map(listMiddlewareRuleDefinitions().map((definition) => [definition.rule.id, definition]));
|
|
2513
|
-
const definitions = snapshot.rules.map((rule) => {
|
|
2514
|
-
const builtin = builtinById.get(rule.id);
|
|
2515
|
-
const definition = {
|
|
2516
|
-
rule: cloneMiddlewareRule(rule),
|
|
2517
|
-
effects: builtin === void 0 ? [] : builtin.effects.map(cloneMiddlewareEffect)
|
|
2518
|
-
};
|
|
2519
|
-
if (builtin?.toolNames !== void 0) definition.toolNames = [...builtin.toolNames];
|
|
2520
|
-
if (builtin?.predicate !== void 0) definition.predicate = builtin.predicate;
|
|
2521
|
-
return definition;
|
|
2522
|
-
});
|
|
2523
|
-
let diagnosticSink;
|
|
2524
|
-
const table = createMiddlewareRegistrationTable({
|
|
2525
|
-
fixed: definitions.map(registrationFromRuleDefinition),
|
|
2526
|
-
diagnosticSink: () => diagnosticSink ?? writeMiddlewareDiagnosticToStderr
|
|
2527
|
-
});
|
|
2528
|
-
const budgetTracker = createHookBudgetTracker({
|
|
2529
|
-
budgets: resolveHookBudgetsFromEnv(),
|
|
2530
|
-
...resolveHookBudgetTunablesFromEnv()
|
|
2531
|
-
});
|
|
2532
|
-
return {
|
|
2533
|
-
runHook(input) {
|
|
2534
|
-
const registrations = table.list();
|
|
2535
|
-
return runMiddlewareRegistrations(input, registrations, {
|
|
2536
|
-
budgetTracker,
|
|
2537
|
-
...diagnosticSink !== void 0 ? { onDiagnostic: diagnosticSink } : {}
|
|
2538
|
-
});
|
|
2539
|
-
},
|
|
2540
|
-
listRules() {
|
|
2541
|
-
return definitions.map((definition) => cloneMiddlewareRule(definition.rule));
|
|
2542
|
-
},
|
|
2543
|
-
snapshot() {
|
|
2544
|
-
return createMiddlewareSnapshot(definitions.map((definition) => definition.rule));
|
|
2545
|
-
},
|
|
2546
|
-
registerHook(registration) {
|
|
2547
|
-
table.registerHook(registration);
|
|
2548
|
-
},
|
|
2549
|
-
setDiagnosticSink(sink) {
|
|
2550
|
-
diagnosticSink = sink;
|
|
2551
|
-
},
|
|
2552
|
-
prepareRegistrationReplacement(owner, generation, registrations) {
|
|
2553
|
-
return table.prepareReplacement(owner, generation, registrations);
|
|
2554
|
-
},
|
|
2555
|
-
replaceRegistrations(owner, generation, registrations) {
|
|
2556
|
-
return table.replaceRegistrations(owner, generation, registrations);
|
|
2557
|
-
},
|
|
2558
|
-
ownedGeneration(owner) {
|
|
2559
|
-
return table.ownedGeneration(owner);
|
|
2560
|
-
}
|
|
2561
|
-
};
|
|
2562
|
-
}
|
|
2563
|
-
|
|
2564
|
-
// src/domains/middleware/extension.ts
|
|
2565
|
-
function createEnvHookBudgetTracker(env = process.env) {
|
|
2566
|
-
return createHookBudgetTracker({ budgets: resolveHookBudgetsFromEnv(env), ...resolveHookBudgetTunablesFromEnv(env) });
|
|
2567
|
-
}
|
|
2568
|
-
function createMiddlewareBundle(options = {}) {
|
|
2569
|
-
const ruleDefinitions = combineRuleDefinitions(listMiddlewareRuleDefinitions(), options.ruleDefinitions ?? []);
|
|
2570
|
-
let diagnosticSink = options.onDiagnostic;
|
|
2571
|
-
const table = createMiddlewareRegistrationTable({
|
|
2572
|
-
fixed: ruleDefinitions.map(registrationFromRuleDefinition),
|
|
2573
|
-
diagnosticSink: () => diagnosticSink ?? writeMiddlewareDiagnosticToStderr
|
|
2574
|
-
});
|
|
2575
|
-
for (const registration of options.registrations ?? []) table.registerHook(registration);
|
|
2576
|
-
const budgetTracker = options.budgetTracker ?? createEnvHookBudgetTracker();
|
|
2577
|
-
const contract = {
|
|
2578
|
-
runHook(input) {
|
|
2579
|
-
const registrations = table.list();
|
|
2580
|
-
return runMiddlewareRegistrations(input, registrations, {
|
|
2581
|
-
budgetTracker,
|
|
2582
|
-
...diagnosticSink !== void 0 ? { onDiagnostic: diagnosticSink } : {}
|
|
2583
|
-
});
|
|
2584
|
-
},
|
|
2585
|
-
runAsyncHook(input, priorEffects = []) {
|
|
2586
|
-
const registrations = table.list();
|
|
2587
|
-
return runMiddlewareAsyncRegistrations(input, registrations, priorEffects, {
|
|
2588
|
-
...diagnosticSink !== void 0 ? { onDiagnostic: diagnosticSink } : {}
|
|
2589
|
-
});
|
|
2590
|
-
},
|
|
2591
|
-
listRules() {
|
|
2592
|
-
return ruleDefinitions.map((definition) => cloneMiddlewareRule(definition.rule));
|
|
2593
|
-
},
|
|
2594
|
-
snapshot() {
|
|
2595
|
-
return createMiddlewareSnapshot(ruleDefinitions.map((definition) => definition.rule));
|
|
2596
|
-
},
|
|
2597
|
-
registerHook(registration) {
|
|
2598
|
-
table.registerHook(registration);
|
|
2599
|
-
},
|
|
2600
|
-
setDiagnosticSink(sink) {
|
|
2601
|
-
diagnosticSink = sink;
|
|
2602
|
-
},
|
|
2603
|
-
prepareRegistrationReplacement(owner, generation, registrations) {
|
|
2604
|
-
return table.prepareReplacement(owner, generation, registrations);
|
|
2605
|
-
},
|
|
2606
|
-
replaceRegistrations(owner, generation, registrations) {
|
|
2607
|
-
return table.replaceRegistrations(owner, generation, registrations);
|
|
2608
|
-
},
|
|
2609
|
-
ownedGeneration(owner) {
|
|
2610
|
-
return table.ownedGeneration(owner);
|
|
2611
|
-
}
|
|
2612
|
-
};
|
|
2613
|
-
return {
|
|
2614
|
-
extension: {
|
|
2615
|
-
start() {
|
|
2616
|
-
return void 0;
|
|
2617
|
-
}
|
|
2618
|
-
},
|
|
2619
|
-
contract
|
|
2620
|
-
};
|
|
2621
|
-
}
|
|
2622
|
-
function combineRuleDefinitions(builtin, registered) {
|
|
2623
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2624
|
-
const combined = [];
|
|
2625
|
-
for (const definition of [...builtin, ...registered]) {
|
|
2626
|
-
if (seen.has(definition.rule.id)) continue;
|
|
2627
|
-
seen.add(definition.rule.id);
|
|
2628
|
-
combined.push(definition);
|
|
2629
|
-
}
|
|
2630
|
-
return combined;
|
|
2631
|
-
}
|
|
2632
|
-
|
|
2633
|
-
// src/domains/middleware/manifest.ts
|
|
2634
|
-
init_esm_shims();
|
|
2635
|
-
var MiddlewareManifest = {
|
|
2636
|
-
name: "middleware",
|
|
2637
|
-
dependsOn: []
|
|
2638
|
-
};
|
|
2639
|
-
|
|
2640
|
-
// src/domains/middleware/hooks.ts
|
|
2641
|
-
init_esm_shims();
|
|
2642
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
2643
|
-
import { isAbsolute, resolve } from "node:path";
|
|
2644
|
-
|
|
2645
|
-
// src/domains/middleware/validate.ts
|
|
2646
|
-
init_esm_shims();
|
|
2647
|
-
function validateMiddlewareEffect(value, source = "$") {
|
|
2648
|
-
const issues = [];
|
|
2649
|
-
const effect = readMiddlewareEffect(value, source, issues);
|
|
2650
|
-
if (issues.length > 0 || effect === null) return { valid: false, issues };
|
|
2651
|
-
return { valid: true, effect, issues: [] };
|
|
2652
|
-
}
|
|
2653
|
-
function readMiddlewareEffect(value, path2, issues) {
|
|
2654
|
-
if (!isRecord(value)) {
|
|
2655
|
-
issues.push({ path: path2, message: "expected middleware effect object" });
|
|
2656
|
-
return null;
|
|
2657
|
-
}
|
|
2658
|
-
const kindValue = value.kind;
|
|
2659
|
-
if (typeof kindValue !== "string" || !isMiddlewareEffectKind(kindValue)) {
|
|
2660
|
-
issues.push({ path: `${path2}.kind`, message: "expected known middleware effect kind" });
|
|
2661
|
-
return null;
|
|
2662
|
-
}
|
|
2663
|
-
switch (kindValue) {
|
|
2664
|
-
case "inject_reminder":
|
|
2665
|
-
return readInjectReminder(value, path2, issues);
|
|
2666
|
-
case "annotate_tool_result":
|
|
2667
|
-
return readAnnotateToolResult(value, path2, issues);
|
|
2668
|
-
case "block_tool":
|
|
2669
|
-
return readBlockTool(value, path2, issues);
|
|
2670
|
-
case "protect_path":
|
|
2671
|
-
return readProtectPath(value, path2, issues);
|
|
2672
|
-
case "request_continuation":
|
|
2673
|
-
return readRequestContinuation(value, path2, issues);
|
|
2674
|
-
case "require_tool":
|
|
2675
|
-
return readRequireTool(value, path2, issues);
|
|
2676
|
-
case "lock_tools":
|
|
2677
|
-
rejectUnexpectedFields(value, path2, ["kind"], issues);
|
|
2678
|
-
return { kind: "lock_tools" };
|
|
2679
|
-
}
|
|
2680
|
-
}
|
|
2681
|
-
function readRequireTool(record, path2, issues) {
|
|
2682
|
-
rejectUnexpectedFields(record, path2, ["kind", "toolName"], issues);
|
|
2683
|
-
const toolName = readRequiredString(record, `${path2}.toolName`, issues);
|
|
2684
|
-
return toolName === null ? null : { kind: "require_tool", toolName };
|
|
2685
|
-
}
|
|
2686
|
-
function readInjectReminder(record, path2, issues) {
|
|
2687
|
-
rejectUnexpectedFields(record, path2, ["kind", "message", "severity"], issues);
|
|
2688
|
-
const message = readRequiredString(record, `${path2}.message`, issues);
|
|
2689
|
-
const severity = readOptionalString(record, `${path2}.severity`, issues);
|
|
2690
|
-
if (severity !== void 0 && !isMiddlewareReminderSeverity(severity)) {
|
|
2691
|
-
issues.push({ path: `${path2}.severity`, message: "expected info, advisory, warn, or hard-block" });
|
|
2692
|
-
}
|
|
2693
|
-
if (message === null) return null;
|
|
2694
|
-
const effect = { kind: "inject_reminder", message };
|
|
2695
|
-
if (severity !== void 0 && isMiddlewareReminderSeverity(severity)) effect.severity = severity;
|
|
2696
|
-
return effect;
|
|
2697
|
-
}
|
|
2698
|
-
function readAnnotateToolResult(record, path2, issues) {
|
|
2699
|
-
rejectUnexpectedFields(record, path2, ["kind", "message", "severity"], issues);
|
|
2700
|
-
const message = readRequiredString(record, `${path2}.message`, issues);
|
|
2701
|
-
const severity = readOptionalString(record, `${path2}.severity`, issues);
|
|
2702
|
-
if (severity !== void 0 && !isMiddlewareAnnotationSeverity(severity)) {
|
|
2703
|
-
issues.push({ path: `${path2}.severity`, message: "expected info or warn" });
|
|
2704
|
-
}
|
|
2705
|
-
if (message === null) return null;
|
|
2706
|
-
const effect = { kind: "annotate_tool_result", message };
|
|
2707
|
-
if (severity !== void 0 && isMiddlewareAnnotationSeverity(severity)) effect.severity = severity;
|
|
2708
|
-
return effect;
|
|
2709
|
-
}
|
|
2710
|
-
function readBlockTool(record, path2, issues) {
|
|
2711
|
-
rejectUnexpectedFields(record, path2, ["kind", "reason", "severity"], issues);
|
|
2712
|
-
const reason = readRequiredString(record, `${path2}.reason`, issues);
|
|
2713
|
-
const severity = readRequiredString(record, `${path2}.severity`, issues);
|
|
2714
|
-
if (severity !== null && severity !== "hard-block") {
|
|
2715
|
-
issues.push({ path: `${path2}.severity`, message: "expected hard-block" });
|
|
2716
|
-
}
|
|
2717
|
-
if (reason === null || severity !== "hard-block") return null;
|
|
2718
|
-
return { kind: "block_tool", reason, severity };
|
|
2719
|
-
}
|
|
2720
|
-
function readProtectPath(record, path2, issues) {
|
|
2721
|
-
rejectUnexpectedFields(record, path2, ["kind", "path", "reason"], issues);
|
|
2722
|
-
const protectedPath = readRequiredString(record, `${path2}.path`, issues);
|
|
2723
|
-
const reason = readRequiredString(record, `${path2}.reason`, issues);
|
|
2724
|
-
if (protectedPath === null || reason === null) return null;
|
|
2725
|
-
return { kind: "protect_path", path: protectedPath, reason };
|
|
2726
|
-
}
|
|
2727
|
-
function readRequestContinuation(record, path2, issues) {
|
|
2728
|
-
rejectUnexpectedFields(record, path2, ["kind", "message"], issues);
|
|
2729
|
-
const message = readRequiredString(record, `${path2}.message`, issues);
|
|
2730
|
-
if (message === null) return null;
|
|
2731
|
-
return { kind: "request_continuation", message };
|
|
2732
|
-
}
|
|
2733
|
-
function readRequiredString(record, path2, issues) {
|
|
2734
|
-
const value = record[pathField(path2)];
|
|
2735
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
2736
|
-
issues.push({ path: path2, message: "expected non-empty string" });
|
|
2737
|
-
return null;
|
|
2738
|
-
}
|
|
2739
|
-
return value;
|
|
2740
|
-
}
|
|
2741
|
-
function readOptionalString(record, path2, issues) {
|
|
2742
|
-
const field = pathField(path2);
|
|
2743
|
-
if (!Object.hasOwn(record, field)) return void 0;
|
|
2744
|
-
const value = record[field];
|
|
2745
|
-
if (typeof value !== "string" || value.trim().length === 0) {
|
|
2746
|
-
issues.push({ path: path2, message: "expected non-empty string" });
|
|
2747
|
-
return void 0;
|
|
2748
|
-
}
|
|
2749
|
-
return value;
|
|
2750
|
-
}
|
|
2751
|
-
function rejectUnexpectedFields(record, path2, allowedFields, issues) {
|
|
2752
|
-
const allowed = new Set(allowedFields);
|
|
2753
|
-
for (const field of Object.keys(record).sort((a, b) => a.localeCompare(b))) {
|
|
2754
|
-
if (!allowed.has(field)) issues.push({ path: `${path2}.${field}`, message: "unexpected field" });
|
|
2755
|
-
}
|
|
2756
|
-
}
|
|
2757
|
-
function pathField(path2) {
|
|
2758
|
-
return path2.slice(path2.lastIndexOf(".") + 1);
|
|
2759
|
-
}
|
|
2760
|
-
function isRecord(value) {
|
|
2761
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2762
|
-
}
|
|
2763
|
-
|
|
2764
|
-
// src/domains/middleware/hooks.ts
|
|
2765
|
-
var USER_HOOK_ORIGIN_ORDER = ["extension", "user", "project", "project.local"];
|
|
2766
|
-
var USER_HOOK_COMMAND_TIMEOUT_DEFAULT_MS = 2e3;
|
|
2767
|
-
var USER_HOOK_COMMAND_TIMEOUT_MIN_MS = 100;
|
|
2768
|
-
var USER_HOOK_COMMAND_TIMEOUT_MAX_MS = 5e3;
|
|
2769
|
-
var USER_HOOK_COMMAND_OUTPUT_MAX_CHARS = 4e3;
|
|
2770
|
-
var USER_HOOK_PROMPT_MAX_CHARS = 2e3;
|
|
2771
|
-
function isRecord2(value) {
|
|
2772
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2773
|
-
}
|
|
2774
|
-
function stableHash(value) {
|
|
2775
|
-
return createHash2("sha256").update(canonicalJson(value)).digest("hex").slice(0, 16);
|
|
2776
|
-
}
|
|
2777
|
-
function canonicalJson(value) {
|
|
2778
|
-
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
2779
|
-
if (isRecord2(value)) {
|
|
2780
|
-
const keys = Object.keys(value).sort();
|
|
2781
|
-
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
|
|
2782
|
-
}
|
|
2783
|
-
return JSON.stringify(value) ?? "null";
|
|
2784
|
-
}
|
|
2785
|
-
function readStringArray(value) {
|
|
2786
|
-
if (!Array.isArray(value)) return null;
|
|
2787
|
-
const out = [];
|
|
2788
|
-
for (const item of value) {
|
|
2789
|
-
if (typeof item !== "string" || item.length === 0) return null;
|
|
2790
|
-
out.push(item);
|
|
2791
|
-
}
|
|
2792
|
-
return out;
|
|
2793
|
-
}
|
|
2794
|
-
function normalizeCommandSpec(raw, options, issues) {
|
|
2795
|
-
const argv = readStringArray(raw.argv);
|
|
2796
|
-
if (!argv || argv.length === 0) {
|
|
2797
|
-
issues.push("command.argv must be a non-empty array of non-empty strings");
|
|
2798
|
-
return null;
|
|
2799
|
-
}
|
|
2800
|
-
const spec = {
|
|
2801
|
-
kind: "command",
|
|
2802
|
-
argv,
|
|
2803
|
-
cwd: resolve(options.workspaceRoot),
|
|
2804
|
-
timeoutMs: USER_HOOK_COMMAND_TIMEOUT_DEFAULT_MS,
|
|
2805
|
-
as: "annotate"
|
|
2806
|
-
};
|
|
2807
|
-
if (raw.cwd !== void 0) {
|
|
2808
|
-
if (typeof raw.cwd !== "string" || raw.cwd.length === 0) {
|
|
2809
|
-
issues.push("command.cwd must be a non-empty string");
|
|
2810
|
-
return null;
|
|
2811
|
-
}
|
|
2812
|
-
const resolved = isAbsolute(raw.cwd) ? resolve(raw.cwd) : resolve(options.workspaceRoot, raw.cwd);
|
|
2813
|
-
if (!isWithin(resolved, options.workspaceRoot)) {
|
|
2814
|
-
issues.push("command.cwd must resolve under the workspace root");
|
|
2815
|
-
return null;
|
|
2816
|
-
}
|
|
2817
|
-
spec.cwd = resolved;
|
|
2818
|
-
}
|
|
2819
|
-
if (raw.timeoutMs !== void 0) {
|
|
2820
|
-
if (typeof raw.timeoutMs !== "number" || !Number.isFinite(raw.timeoutMs)) {
|
|
2821
|
-
issues.push("command.timeoutMs must be a number");
|
|
2822
|
-
return null;
|
|
2823
|
-
}
|
|
2824
|
-
spec.timeoutMs = Math.min(
|
|
2825
|
-
USER_HOOK_COMMAND_TIMEOUT_MAX_MS,
|
|
2826
|
-
Math.max(USER_HOOK_COMMAND_TIMEOUT_MIN_MS, Math.floor(raw.timeoutMs))
|
|
2827
|
-
);
|
|
2828
|
-
}
|
|
2829
|
-
if (raw.as !== void 0) {
|
|
2830
|
-
if (raw.as !== "annotate" && raw.as !== "reminder") {
|
|
2831
|
-
issues.push('command.as must be "annotate" or "reminder"');
|
|
2832
|
-
return null;
|
|
2833
|
-
}
|
|
2834
|
-
spec.as = raw.as;
|
|
2835
|
-
}
|
|
2836
|
-
return spec;
|
|
2837
|
-
}
|
|
2838
|
-
function normalizePromptSpec(raw, issues) {
|
|
2839
|
-
if (typeof raw.message !== "string" || raw.message.trim().length === 0) {
|
|
2840
|
-
issues.push("prompt.message must be a non-empty string");
|
|
2841
|
-
return null;
|
|
2842
|
-
}
|
|
2843
|
-
let severity = "info";
|
|
2844
|
-
if (raw.severity !== void 0) {
|
|
2845
|
-
if (typeof raw.severity !== "string" || !isMiddlewareReminderSeverity(raw.severity)) {
|
|
2846
|
-
issues.push("prompt.severity must be info, advisory, warn, or hard-block");
|
|
2847
|
-
return null;
|
|
2848
|
-
}
|
|
2849
|
-
severity = raw.severity;
|
|
2850
|
-
}
|
|
2851
|
-
return { kind: "prompt", message: raw.message.slice(0, USER_HOOK_PROMPT_MAX_CHARS), severity };
|
|
2852
|
-
}
|
|
2853
|
-
function normalizeEffectSpec(raw, issues) {
|
|
2854
|
-
const result = validateMiddlewareEffect(raw.effect ?? raw, "effect");
|
|
2855
|
-
if (!result.valid) {
|
|
2856
|
-
for (const issue of result.issues) issues.push(`effect: ${issue.message}`);
|
|
2857
|
-
return null;
|
|
2858
|
-
}
|
|
2859
|
-
return { kind: "effect", effect: result.effect };
|
|
2860
|
-
}
|
|
2861
|
-
function isWithin(child, parent) {
|
|
2862
|
-
const rel = resolve(child);
|
|
2863
|
-
const base = resolve(parent);
|
|
2864
|
-
return rel === base || rel.startsWith(`${base}/`);
|
|
2865
|
-
}
|
|
2866
|
-
function normalizeUserHook(raw, source, options) {
|
|
2867
|
-
const issues = [];
|
|
2868
|
-
if (!isRecord2(raw)) {
|
|
2869
|
-
return { issues: ["hook declaration must be an object"] };
|
|
2870
|
-
}
|
|
2871
|
-
if (raw.on === void 0 || typeof raw.on !== "string" || !isMiddlewareHook(raw.on)) {
|
|
2872
|
-
issues.push("on must be one of before_tool, after_tool, turn_start, turn_end, on_compaction");
|
|
2873
|
-
}
|
|
2874
|
-
let tools;
|
|
2875
|
-
if (raw.tools !== void 0) {
|
|
2876
|
-
const parsed = readStringArray(raw.tools);
|
|
2877
|
-
if (!parsed) issues.push("tools must be an array of non-empty tool names");
|
|
2878
|
-
else tools = parsed;
|
|
2879
|
-
}
|
|
2880
|
-
let enabled = true;
|
|
2881
|
-
if (raw.enabled !== void 0) {
|
|
2882
|
-
if (typeof raw.enabled !== "boolean") issues.push("enabled must be a boolean");
|
|
2883
|
-
else enabled = raw.enabled;
|
|
2884
|
-
}
|
|
2885
|
-
let spec = null;
|
|
2886
|
-
if (raw.kind === "command") spec = normalizeCommandSpec(raw, options, issues);
|
|
2887
|
-
else if (raw.kind === "prompt") spec = normalizePromptSpec(raw, issues);
|
|
2888
|
-
else if (raw.kind === "effect") spec = normalizeEffectSpec(raw, issues);
|
|
2889
|
-
else issues.push('kind must be "command", "prompt", or "effect"');
|
|
2890
|
-
if (issues.length > 0 || spec === null || raw.on === void 0 || typeof raw.on !== "string") {
|
|
2891
|
-
return { issues };
|
|
2892
|
-
}
|
|
2893
|
-
const on = raw.on;
|
|
2894
|
-
const hash = stableHash({ on, tools: tools ?? null, spec });
|
|
2895
|
-
const id = typeof raw.id === "string" && raw.id.length > 0 ? raw.id : `${source.sourceId ?? source.origin}.${spec.kind}.${hash}`;
|
|
2896
|
-
const hook = { id, source, hash, on, enabled, spec };
|
|
2897
|
-
if (tools !== void 0) hook.tools = tools;
|
|
2898
|
-
return { hook, issues };
|
|
2899
|
-
}
|
|
2900
|
-
function declarationsArray(declarations) {
|
|
2901
|
-
if (Array.isArray(declarations)) return declarations;
|
|
2902
|
-
if (isRecord2(declarations) && Array.isArray(declarations.hooks)) return declarations.hooks;
|
|
2903
|
-
return [];
|
|
2904
|
-
}
|
|
2905
|
-
function loadUserHooks(batches, options) {
|
|
2906
|
-
const ordered = [...batches].sort(
|
|
2907
|
-
(a, b) => USER_HOOK_ORIGIN_ORDER.indexOf(a.source.origin) - USER_HOOK_ORIGIN_ORDER.indexOf(b.source.origin)
|
|
2908
|
-
);
|
|
2909
|
-
const byId = /* @__PURE__ */ new Map();
|
|
2910
|
-
const overridden = [];
|
|
2911
|
-
const issues = [];
|
|
2912
|
-
for (const batch of ordered) {
|
|
2913
|
-
const declarations = declarationsArray(batch.declarations);
|
|
2914
|
-
declarations.forEach((raw, index) => {
|
|
2915
|
-
const result = normalizeUserHook(raw, batch.source, options);
|
|
2916
|
-
if (!result.hook) {
|
|
2917
|
-
issues.push({ source: batch.source, index, issues: result.issues });
|
|
2918
|
-
return;
|
|
2919
|
-
}
|
|
2920
|
-
const existing = byId.get(result.hook.id);
|
|
2921
|
-
if (existing) overridden.push({ winner: batch.source, loser: existing });
|
|
2922
|
-
byId.set(result.hook.id, result.hook);
|
|
2923
|
-
});
|
|
2924
|
-
}
|
|
2925
|
-
return { hooks: [...byId.values()], overridden, issues };
|
|
2926
|
-
}
|
|
2927
|
-
function reminderEffect(message, severity) {
|
|
2928
|
-
return severity === "info" ? { kind: "inject_reminder", message } : { kind: "inject_reminder", message, severity };
|
|
2929
|
-
}
|
|
2930
|
-
function commandEffect(hook, output) {
|
|
2931
|
-
const message = output.slice(0, USER_HOOK_COMMAND_OUTPUT_MAX_CHARS);
|
|
2932
|
-
return hook.as === "reminder" ? { kind: "inject_reminder", message } : { kind: "annotate_tool_result", message };
|
|
2933
|
-
}
|
|
2934
|
-
function userHookToRegistration(hook, deps) {
|
|
2935
|
-
const now = deps.now ?? Date.now;
|
|
2936
|
-
const extension = hook.source.extension === void 0 ? void 0 : receiptExtension(hook.source.extension);
|
|
2937
|
-
const baseReceipt = (input) => ({
|
|
2938
|
-
at: now(),
|
|
2939
|
-
hookId: hook.id,
|
|
2940
|
-
origin: hook.source.origin,
|
|
2941
|
-
sourcePath: hook.source.sourcePath,
|
|
2942
|
-
hash: hook.hash,
|
|
2943
|
-
hook: hook.on,
|
|
2944
|
-
kind: hook.spec.kind,
|
|
2945
|
-
...extension !== void 0 ? { extension: { ...extension } } : {},
|
|
2946
|
-
...input.toolName !== void 0 ? { toolName: input.toolName } : {}
|
|
2947
|
-
});
|
|
2948
|
-
const registration = {
|
|
2949
|
-
id: hook.id,
|
|
2950
|
-
description: `${hook.spec.kind} hook from ${hook.source.origin} (${hook.source.sourcePath})`,
|
|
2951
|
-
hooks: [hook.on],
|
|
2952
|
-
evaluate: (input) => {
|
|
2953
|
-
if (!hook.enabled) return [];
|
|
2954
|
-
try {
|
|
2955
|
-
if (deps.isTrusted?.() === false) {
|
|
2956
|
-
deps.recordReceipt({ ...baseReceipt(input), outcome: "skipped" });
|
|
2957
|
-
return [];
|
|
2958
|
-
}
|
|
2959
|
-
return evaluateHook(hook, deps, baseReceipt(input));
|
|
2960
|
-
} catch {
|
|
2961
|
-
deps.recordReceipt({ ...baseReceipt(input), outcome: "skipped" });
|
|
2962
|
-
return [];
|
|
2963
|
-
}
|
|
2964
|
-
}
|
|
2965
|
-
};
|
|
2966
|
-
if (hook.tools !== void 0) registration.toolNames = [...hook.tools];
|
|
2967
|
-
return registration;
|
|
2968
|
-
}
|
|
2969
|
-
function receiptExtension(source) {
|
|
2970
|
-
return {
|
|
2971
|
-
id: source.provenance.id,
|
|
2972
|
-
scope: source.provenance.scope,
|
|
2973
|
-
canonicalRoot: source.provenance.canonicalRoot,
|
|
2974
|
-
manifestDigest: source.provenance.manifestDigest,
|
|
2975
|
-
contentDigest: source.provenance.contentDigest,
|
|
2976
|
-
declarationsDigest: source.declarationsDigest,
|
|
2977
|
-
generation: source.generation
|
|
2978
|
-
};
|
|
2979
|
-
}
|
|
2980
|
-
function evaluateHook(hook, deps, base) {
|
|
2981
|
-
if (hook.spec.kind === "prompt") {
|
|
2982
|
-
const effect2 = reminderEffect(hook.spec.message, hook.spec.severity);
|
|
2983
|
-
deps.recordReceipt({ ...base, outcome: "emitted", effectKinds: ["inject_reminder"] });
|
|
2984
|
-
return [effect2];
|
|
2985
|
-
}
|
|
2986
|
-
if (hook.spec.kind === "effect") {
|
|
2987
|
-
deps.recordReceipt({ ...base, outcome: "emitted", effectKinds: [hook.spec.effect.kind] });
|
|
2988
|
-
return [hook.spec.effect];
|
|
2989
|
-
}
|
|
2990
|
-
const result = deps.runCommand(hook.spec.argv, {
|
|
2991
|
-
timeoutMs: hook.spec.timeoutMs,
|
|
2992
|
-
...hook.spec.cwd !== void 0 ? { cwd: hook.spec.cwd } : {}
|
|
2993
|
-
});
|
|
2994
|
-
const output = (result.stdout || result.stderr || "").trim();
|
|
2995
|
-
if (result.timedOut) {
|
|
2996
|
-
deps.recordReceipt({ ...base, outcome: "command-timeout", exitCode: result.code ?? -1, outputChars: output.length });
|
|
2997
|
-
return [];
|
|
2998
|
-
}
|
|
2999
|
-
const outcome = result.code === 0 ? "command-ok" : "command-failed";
|
|
3000
|
-
deps.recordReceipt({ ...base, outcome, exitCode: result.code ?? -1, outputChars: output.length });
|
|
3001
|
-
if (output.length === 0) return [];
|
|
3002
|
-
const effect = commandEffect(hook.spec, output);
|
|
3003
|
-
return [effect];
|
|
3004
|
-
}
|
|
3005
|
-
|
|
3006
|
-
// src/domains/middleware/hooks-io.ts
|
|
3007
|
-
init_esm_shims();
|
|
3008
|
-
var import_yaml = __toESM(require_dist(), 1);
|
|
3009
|
-
import { spawnSync } from "node:child_process";
|
|
3010
|
-
var COMMAND_OUTPUT_MAX_BYTES = 1024 * 1024;
|
|
3011
|
-
function readBatch(source, filePath, text, fileIssues) {
|
|
3012
|
-
try {
|
|
3013
|
-
const parsed = (0, import_yaml.parse)(text);
|
|
3014
|
-
return { source, declarations: parsed ?? [] };
|
|
3015
|
-
} catch (err) {
|
|
3016
|
-
fileIssues.push({
|
|
3017
|
-
source,
|
|
3018
|
-
message: `failed to parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`
|
|
3019
|
-
});
|
|
3020
|
-
return null;
|
|
3021
|
-
}
|
|
3022
|
-
}
|
|
3023
|
-
function readHookSources(options) {
|
|
3024
|
-
const fileIssues = [];
|
|
3025
|
-
const batches = [];
|
|
3026
|
-
const captured = options.capturedSources;
|
|
3027
|
-
for (const entry of captured?.sources ?? []) {
|
|
3028
|
-
const source = {
|
|
3029
|
-
origin: "extension",
|
|
3030
|
-
sourcePath: `${entry.provenance.id}:hooks.yaml`,
|
|
3031
|
-
sourceId: entry.provenance.id,
|
|
3032
|
-
extension: {
|
|
3033
|
-
provenance: entry.provenance,
|
|
3034
|
-
generation: captured?.generation ?? 0,
|
|
3035
|
-
declarationsDigest: entry.declarationsDigest
|
|
3036
|
-
}
|
|
3037
|
-
};
|
|
3038
|
-
if (entry.parseError !== void 0) {
|
|
3039
|
-
fileIssues.push({ source, message: `failed to parse ${source.sourcePath}: ${entry.parseError}` });
|
|
3040
|
-
continue;
|
|
3041
|
-
}
|
|
3042
|
-
batches.push({ source, declarations: entry.declarations });
|
|
3043
|
-
}
|
|
3044
|
-
const projectSurface = captureProjectSurface(options.cwd, "hooks");
|
|
3045
|
-
for (const [index, file] of projectSurface.files.entries()) {
|
|
3046
|
-
const source = {
|
|
3047
|
-
origin: index === 0 ? "project" : "project.local",
|
|
3048
|
-
sourcePath: index === 0 ? ".clio-coder/hooks.yaml" : ".clio-coder/hooks.local.yaml"
|
|
3049
|
-
};
|
|
3050
|
-
if (file.error !== void 0) fileIssues.push({ source, message: file.error });
|
|
3051
|
-
if (file.text === null) continue;
|
|
3052
|
-
if (projectSurface.verdict !== "trusted") {
|
|
3053
|
-
fileIssues.push({ source, message: projectSurfaceTrustNotice(projectSurface, file.path) });
|
|
3054
|
-
continue;
|
|
3055
|
-
}
|
|
3056
|
-
const batch = readBatch(source, file.path, file.text, fileIssues);
|
|
3057
|
-
if (batch) batches.push(batch);
|
|
3058
|
-
}
|
|
3059
|
-
return { batches, fileIssues, projectSurface };
|
|
3060
|
-
}
|
|
3061
|
-
function buildUserHookRegistrations(options) {
|
|
3062
|
-
const workspaceRoot = options.workspaceRoot ?? options.cwd;
|
|
3063
|
-
const readOptions = { cwd: options.cwd };
|
|
3064
|
-
if (options.capturedSources !== void 0) readOptions.capturedSources = options.capturedSources;
|
|
3065
|
-
const { batches, fileIssues, projectSurface } = readHookSources(readOptions);
|
|
3066
|
-
const loaded = loadUserHooks(batches, { workspaceRoot });
|
|
3067
|
-
const runCommand = options.runCommand ?? spawnSyncCommandRunner();
|
|
3068
|
-
let reportedUntrusted = false;
|
|
3069
|
-
const projectStillTrusted = () => {
|
|
3070
|
-
const current = captureProjectSurface(options.cwd, "hooks");
|
|
3071
|
-
if (current.verdict === "trusted" && current.contentHash === projectSurface.contentHash) return true;
|
|
3072
|
-
if (!reportedUntrusted) {
|
|
3073
|
-
reportedUntrusted = true;
|
|
3074
|
-
options.report?.(
|
|
3075
|
-
`[clio-coder:hooks] project hooks changed or trust was revoked; hooks skipped. Review with clio-coder config trust hooks, then reload extensions.`
|
|
3076
|
-
);
|
|
3077
|
-
}
|
|
3078
|
-
return false;
|
|
3079
|
-
};
|
|
3080
|
-
const registrations = loaded.hooks.map(
|
|
3081
|
-
(hook) => userHookToRegistration(hook, {
|
|
3082
|
-
recordReceipt: options.recordReceipt,
|
|
3083
|
-
runCommand,
|
|
3084
|
-
...hook.source.origin === "project" || hook.source.origin === "project.local" ? { isTrusted: projectStillTrusted } : {},
|
|
3085
|
-
...options.now !== void 0 ? { now: options.now } : {}
|
|
3086
|
-
})
|
|
3087
|
-
);
|
|
3088
|
-
return { ...loaded, fileIssues, registrations };
|
|
3089
|
-
}
|
|
3090
|
-
function spawnSyncCommandRunner() {
|
|
3091
|
-
return (argv, options) => {
|
|
3092
|
-
const [command, ...args] = argv;
|
|
3093
|
-
const attribution = withManagedGitCommitAttributionEnvironment(buildSafeToolEnv(), {
|
|
3094
|
-
cwd: options.cwd ?? process.cwd(),
|
|
3095
|
-
enabled: gitCommitAttributionEnabled(process.env),
|
|
3096
|
-
evidence: {}
|
|
3097
|
-
});
|
|
3098
|
-
reportCommitAttributionDiagnostic(attribution.diagnostic);
|
|
3099
|
-
const result = spawnSync(command ?? "", args, {
|
|
3100
|
-
...options.cwd !== void 0 ? { cwd: options.cwd } : {},
|
|
3101
|
-
timeout: options.timeoutMs,
|
|
3102
|
-
maxBuffer: COMMAND_OUTPUT_MAX_BYTES,
|
|
3103
|
-
encoding: "utf8",
|
|
3104
|
-
shell: false,
|
|
3105
|
-
env: attribution.env
|
|
3106
|
-
});
|
|
3107
|
-
const timedOut = result.error !== void 0 && result.error.code === "ETIMEDOUT";
|
|
3108
|
-
return {
|
|
3109
|
-
code: result.status,
|
|
3110
|
-
timedOut,
|
|
3111
|
-
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
3112
|
-
stderr: typeof result.stderr === "string" ? result.stderr : ""
|
|
3113
|
-
};
|
|
3114
|
-
};
|
|
3115
|
-
}
|
|
3116
|
-
|
|
3117
|
-
// src/domains/middleware/index.ts
|
|
3118
|
-
var MiddlewareDomainModule = {
|
|
3119
|
-
manifest: MiddlewareManifest,
|
|
3120
|
-
createExtension: () => createMiddlewareBundle()
|
|
3121
|
-
};
|
|
3122
|
-
|
|
3123
|
-
export {
|
|
3124
|
-
MIDDLEWARE_HOOK_TEXT_MAX_CHARS,
|
|
3125
|
-
shouldRequestStalledTurnContinuation,
|
|
3126
|
-
writeMiddlewareDiagnosticToStderr,
|
|
3127
|
-
formatRegistrationConflict,
|
|
3128
|
-
createMiddlewareContractFromSnapshot,
|
|
3129
|
-
createReadOnlyExplorationNudgeRegistration,
|
|
3130
|
-
createUnbackedWorkerClaimRegistration,
|
|
3131
|
-
openDetachedBatchViews,
|
|
3132
|
-
createDetachedDispatchNudgeRegistration,
|
|
3133
|
-
HOOK_RECEIPT_LOG_CAPACITY,
|
|
3134
|
-
createHookReceiptLog,
|
|
3135
|
-
readPersistedHookReceipts,
|
|
3136
|
-
loadUserHooks,
|
|
3137
|
-
readHookSources,
|
|
3138
|
-
buildUserHookRegistrations,
|
|
3139
|
-
createSkillsReminderRegistration,
|
|
3140
|
-
createMarketplaceOfferRegistration,
|
|
3141
|
-
createMemoryInterventionRegistration,
|
|
3142
|
-
announceMemoryStepEndpoint,
|
|
3143
|
-
createTaskBoardReminderRegistration,
|
|
3144
|
-
createTaskNudgeRegistration,
|
|
3145
|
-
createMiddlewareToolChoiceControl,
|
|
3146
|
-
WATCHDOG_TASK,
|
|
3147
|
-
watchdogBriefing,
|
|
3148
|
-
createWatchdogRegistration,
|
|
3149
|
-
MiddlewareDomainModule
|
|
3150
|
-
};
|
|
3151
|
-
//# sourceMappingURL=chunk-BT7HGDOX.js.map
|