@iowarp/clio-coder 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/NOTICE +33 -0
- package/README.md +7 -2
- package/dist/{acp-7LOELQFP.js → acp-G5WJBNCT.js} +13 -12
- package/dist/{agents-FIBG2SHA.js → agents-FMV2Q5G4.js} +39 -36
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-OI4LIH2I.js → auth-3IDSJEIK.js} +16 -15
- package/dist/{builtins-AD25UL3C.js → builtins-XCZWXSC7.js} +3 -3
- package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
- package/dist/{chunk-56KB5IJP.js → chunk-2OQE55CK.js} +3 -3
- package/dist/{chunk-N3PBVRTZ.js → chunk-32KWKNSF.js} +9 -7
- package/dist/{chunk-VKBMFOYV.js → chunk-36EJLSQQ.js} +23 -27
- package/dist/{chunk-465CC7FK.js → chunk-3BT2XMV4.js} +16 -13
- package/dist/{chunk-NQ6UCCOD.js → chunk-3URVFKWK.js} +7 -7
- package/dist/{chunk-WIE7ZOSW.js → chunk-3XML7CDN.js} +2 -2
- package/dist/chunk-42FMPA75.js +101 -0
- package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
- package/dist/{chunk-HAY4ZE2P.js → chunk-5PSMVOLM.js} +2 -2
- package/dist/{chunk-JEQQR47K.js → chunk-6DB53AJS.js} +168 -9
- package/dist/{chunk-KV2AOLDF.js → chunk-76ONBSIA.js} +5 -25
- package/dist/{chunk-FALJGAWU.js → chunk-7MCTRUCE.js} +2 -2
- package/dist/{chunk-5T7RBWN2.js → chunk-AB44T6BB.js} +5 -5
- package/dist/chunk-B7OBL7PK.js +1405 -0
- package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
- package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
- package/dist/{chunk-O6I4CIEU.js → chunk-BKFJHQCA.js} +6 -6
- package/dist/chunk-BKFM6EJV.js +462 -0
- package/dist/chunk-BMS5RKQY.js +27 -0
- package/dist/{chunk-MV2VUEJC.js → chunk-BPKCPIL7.js} +2 -2
- package/dist/{chunk-TEO2TLVN.js → chunk-BUMFYQFY.js} +964 -1120
- package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
- package/dist/chunk-C2LTL2W6.js +2447 -0
- package/dist/{chunk-EBOC7MT3.js → chunk-CODPRO7Q.js} +8 -8
- package/dist/{chunk-HPCTNZM2.js → chunk-CTJ4RNAA.js} +4 -4
- package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
- package/dist/{chunk-MIX5N5AC.js → chunk-DQITNCXG.js} +394 -154
- package/dist/{chunk-S4COXYBG.js → chunk-DYJP44XW.js} +129 -106
- package/dist/{chunk-N5XKWMDW.js → chunk-F4CKPOEQ.js} +6 -6
- package/dist/{chunk-AMKHQW3C.js → chunk-FEFIFZTL.js} +3 -3
- package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
- package/dist/{chunk-7C6RYZGQ.js → chunk-GKF55TAZ.js} +3 -3
- package/dist/{chunk-B5XRQOLB.js → chunk-GR5G2PVF.js} +9 -8
- package/dist/{chunk-XDOQXGFO.js → chunk-GXNLGKAB.js} +64 -8
- package/dist/chunk-HHV2GANA.js +88 -0
- package/dist/{chunk-774ILSRL.js → chunk-HI63TFOG.js} +4 -3
- package/dist/{chunk-R7LNVMCS.js → chunk-HJJTYUHX.js} +64 -72
- package/dist/{chunk-RKRLDWD3.js → chunk-HLW2MRKE.js} +1 -1
- package/dist/{chunk-CA42X6KT.js → chunk-HWHKMHUA.js} +6 -6
- package/dist/chunk-HZHHCK24.js +1631 -0
- package/dist/{chunk-HJB5IUKP.js → chunk-I5VEOC6I.js} +12 -12
- package/dist/chunk-IBEBSCYA.js +564 -0
- package/dist/chunk-IQ7KR472.js +362 -0
- package/dist/{chunk-4H6ULJ3H.js → chunk-J4W7KFM7.js} +921 -990
- package/dist/{chunk-4LJX2PUC.js → chunk-JDG2WCRO.js} +5 -5
- package/dist/{chunk-NZU6YDNV.js → chunk-K5C3NCBD.js} +4 -4
- package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
- package/dist/{chunk-NNNWO6F2.js → chunk-KFZI4NIL.js} +93 -3
- package/dist/chunk-KMVISBZR.js +132 -0
- package/dist/{chunk-BVDVID7E.js → chunk-LDQ2ZF2M.js} +2 -2
- package/dist/{chunk-OEDBCISO.js → chunk-LQ3DZAMX.js} +2 -2
- package/dist/{chunk-PZ4I4JE2.js → chunk-LY4S7GJC.js} +124 -116
- package/dist/{chunk-3DUR4WUA.js → chunk-MLKNTWH2.js} +19 -19
- package/dist/chunk-NEKRRTYW.js +56 -0
- package/dist/{chunk-5DQRIYDZ.js → chunk-NHCZP4K7.js} +2 -2
- package/dist/chunk-NHLBIGRH.js +1506 -0
- package/dist/chunk-NQQH3YT7.js +302 -0
- package/dist/chunk-NYS75XW5.js +15 -0
- package/dist/{chunk-TD7UE2L5.js → chunk-O4XIVISU.js} +7 -7
- package/dist/{chunk-WXCJ7VME.js → chunk-O6TL7WWY.js} +6 -6
- package/dist/chunk-OQBA45DZ.js +97 -0
- package/dist/{chunk-LU7P4LHA.js → chunk-P3FOHJT4.js} +2 -2
- package/dist/chunk-PMZCIOCJ.js +25 -0
- package/dist/{chunk-I4HZDVNP.js → chunk-PQEFIJ36.js} +2 -2
- package/dist/{chunk-HKO36JWF.js → chunk-QBJA7R7N.js} +31 -3
- package/dist/chunk-QDC3K2U3.js +262 -0
- package/dist/{chunk-5HFBWUMU.js → chunk-QLFS5GO2.js} +4 -4
- package/dist/{chunk-GAYUJ7LE.js → chunk-QLL7ILRG.js} +41 -32
- package/dist/{chunk-LXPJXFM5.js → chunk-QREDIESB.js} +7 -7
- package/dist/chunk-QSNYB6ZV.js +195 -0
- package/dist/chunk-R346GLFC.js +31 -0
- package/dist/{chunk-VPTUJU4P.js → chunk-SJ5ZKQ4S.js} +2 -2
- package/dist/{chunk-QQ7EKM72.js → chunk-SP2RXXYO.js} +6 -54
- package/dist/chunk-SUCTJL45.js +45 -0
- package/dist/{chunk-5QKCQQ3E.js → chunk-SUW5DORT.js} +2 -2
- package/dist/chunk-T56WDKA5.js +183 -0
- package/dist/chunk-TVHHYFHE.js +255 -0
- package/dist/{chunk-IHKBWSXF.js → chunk-TZ3SGWZZ.js} +2 -2
- package/dist/{chunk-ECUO3KDP.js → chunk-U77AMWDL.js} +47 -7
- package/dist/{chunk-3UUY7R3Z.js → chunk-ULC6OTWO.js} +7 -7
- package/dist/{chunk-AEYBF3TB.js → chunk-UM7N4G5A.js} +2 -2
- package/dist/{chunk-3V5AYSEQ.js → chunk-UXMFQ54G.js} +43 -36
- package/dist/{chunk-YW7UVM5V.js → chunk-V5DHCITQ.js} +34 -1
- package/dist/{chunk-47CMYGET.js → chunk-VAZSBTKF.js} +2 -2
- package/dist/{chunk-3MRC2YSQ.js → chunk-VEO4AP2K.js} +2 -2
- package/dist/{chunk-PNY46YEY.js → chunk-VFA6GDY5.js} +47 -3
- package/dist/chunk-VO67MWHC.js +75 -0
- package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
- package/dist/{chunk-AD7Y7STJ.js → chunk-VYMXRQI6.js} +36 -22
- package/dist/{chunk-T3Z6VAAF.js → chunk-W5VSYASO.js} +19 -17
- package/dist/{chunk-5PVQ4SRS.js → chunk-WZR7K7ZX.js} +7 -123
- package/dist/{chunk-DG4M6ZUE.js → chunk-X3YGUTOB.js} +4 -4
- package/dist/chunk-X75E3D2N.js +686 -0
- package/dist/{chunk-P3JGPQFL.js → chunk-YDFRH54B.js} +4 -4
- package/dist/chunk-YJX4SHTD.js +40 -0
- package/dist/{chunk-ZI647VB5.js → chunk-YPI3QQCF.js} +2 -2
- package/dist/{chunk-YSEHGPCT.js → chunk-Z2RR6MAK.js} +3 -3
- package/dist/{chunk-HCBCAYZU.js → chunk-Z4TXYIEG.js} +5 -5
- package/dist/cli/index.js +47 -36
- package/dist/{clio-LT5V7SSZ.js → clio-2JXHBBY5.js} +7 -7
- package/dist/{code-nav-LMW275PA.js → code-nav-3YYRMYNF.js} +6 -6
- package/dist/{compile-cache-CVJMMODC.js → compile-cache-7FPE6PS3.js} +3 -3
- package/dist/{components-ZFA3SAER.js → components-RYZV4JGP.js} +5 -5
- package/dist/{config-RXS5T3JT.js → config-QZPCMYSO.js} +58 -50
- package/dist/{configure-2WYWSCSD.js → configure-TEGEBYCA.js} +21 -19
- package/dist/{context-I3BTOTCS.js → context-AV7OEZ4D.js} +11 -11
- package/dist/{context-MVOORGMF.js → context-E6H5RNMC.js} +49 -41
- package/dist/{context-PALKKQYL.js → context-GSXUE4CT.js} +25 -23
- package/dist/{context-clear-N2WOYZ2K.js → context-clear-SHIBYK6T.js} +48 -40
- package/dist/{context-working-set-MIEVECVZ.js → context-working-set-5ZGKPGZQ.js} +11 -10
- package/dist/{dispatch-runner-VVA4SRRH.js → dispatch-runner-EFMJT4LD.js} +88 -60
- package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
- package/dist/doctor-QOA5FNY5.js +313 -0
- package/dist/{eval-IJ5VEZDJ.js → eval-TFBYQH4H.js} +66 -64
- package/dist/eval-inventory-SXH7PDKX.js +316 -0
- package/dist/{evidence-L5APPXNV.js → evidence-ERGESKGN.js} +198 -44
- package/dist/{evolve-RGNKFJ52.js → evolve-VDXTSYCJ.js} +46 -38
- package/dist/{extensions-7WYWUX5A.js → extensions-7BGBHN57.js} +6 -6
- package/dist/{fleet-6CNVBZZP.js → fleet-2RRVDF2V.js} +189 -101
- package/dist/{fleet-commands-L2SXSYEI.js → fleet-commands-VJ726XIA.js} +10 -10
- package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
- package/dist/{fleet-graph-2J3OOIPO.js → fleet-graph-JF5QOATM.js} +16 -15
- package/dist/fleet-inspect-VLY4S7QM.js +442 -0
- package/dist/{fleet-preflight-CZRJ4JP5.js → fleet-preflight-AIZUEJOY.js} +6 -5
- package/dist/{fleet-validate-C5RI6DP7.js → fleet-validate-AJRPDMDV.js} +20 -18
- package/dist/fleet-verify-JFEL2L3H.js +175 -0
- package/dist/fleet-view-ZCON35AG.js +102 -0
- package/dist/{init-VBN2ACVA.js → init-DN2WWLFE.js} +64 -56
- package/dist/install-XGLBQY5E.js +13 -0
- package/dist/interop-OZBKXAYL.js +114 -0
- package/dist/{library-JHGUMLY2.js → library-YWZG7IMW.js} +19 -18
- package/dist/{memory-K4OQIYWG.js → memory-I4C4HMLW.js} +48 -40
- package/dist/{models-2NCZUWDD.js → models-CEYXJBO6.js} +30 -28
- package/dist/{monitor-MMVTJABD.js → monitor-NZ6GCI3P.js} +53 -47
- package/dist/{orchestrator-ZKBPCHW6.js → orchestrator-GCGQ4N5I.js} +6311 -7145
- package/dist/panes-HMABYVO4.js +58 -0
- package/dist/panes-KY6W3V2E.js +103 -0
- package/dist/{paths-DBXMZMDU.js → paths-II4K7DNR.js} +5 -5
- package/dist/{reset-DD5JGOY3.js → reset-DQ6FGCSH.js} +13 -11
- package/dist/resources-BB3MVJMD.js +111 -0
- package/dist/{run-QEGNX7FL.js → run-H2GQDUER.js} +113 -82
- package/dist/{share-JKD3BQMW.js → share-GTJN6A5O.js} +18 -17
- package/dist/{skills-LMQIKDOZ.js → skills-L55TEW6R.js} +31 -24
- package/dist/{skills-eval-I7X2774U.js → skills-eval-XVXPH2JI.js} +61 -52
- package/dist/skills-inventory-S4MXPJFV.js +126 -0
- package/dist/slash-commands-ZSGASKJC.js +77 -0
- package/dist/{steer-CF5TDANS.js → steer-RZGSCY4R.js} +3 -3
- package/dist/{support-I7LOJLIF.js → support-PKEUNNQL.js} +4 -4
- package/dist/{targets-RUSR6B5Z.js → targets-NCPZ644J.js} +31 -29
- package/dist/{terminal-lease-QYVORFR4.js → terminal-lease-44SV3YCN.js} +4 -4
- package/dist/tools-DAF3DI3C.js +27 -0
- package/dist/{trace-ODOQIVIW.js → trace-FYVW2MQA.js} +149 -7
- package/dist/tui-primitives-2AKXQNZK.js +13 -0
- package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
- package/dist/{upgrade-XANW3FXB.js → upgrade-3XPP6OQL.js} +26 -24
- package/dist/{usage-4H7ZRXQT.js → usage-3NLHGTU2.js} +57 -49
- package/dist/{verifiers-UZXNBZEB.js → verifiers-SSQONKRT.js} +171 -12
- package/dist/{verify-BVKWTNDL.js → verify-3U6J7FZI.js} +9 -9
- package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
- package/dist/{wiki-generate-MY7WV2QI.js → wiki-generate-CEHYGPGQ.js} +67 -59
- package/dist/with-panes-MKB46MPQ.js +782 -0
- package/dist/worker/entry.js +101 -66
- package/docs/README.md +3 -2
- package/docs/acp.md +24 -3
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-versions.md +4 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +43 -5
- package/docs/commands-and-modes.md +31 -2
- package/docs/configuration-and-targets.md +40 -10
- package/docs/context-engine.md +1 -1
- package/docs/development-pipeline.md +19 -0
- package/docs/dispatch-typed-intent.md +385 -0
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +1 -0
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +2 -2
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +25 -1
- package/docs/fleet-dispatch.md +22 -1
- package/docs/installation-and-lifecycle.md +15 -2
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +10 -1
- package/docs/observability.md +3 -3
- package/docs/proactive-memory.md +1 -1
- package/docs/prompt-envelope-and-tools.md +1 -1
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/safety-model.md +2 -2
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +1 -1
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +18 -8
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +4 -2
- package/src/cli/acp.ts +6 -2
- package/src/cli/argv.ts +25 -0
- package/src/cli/configure.ts +23 -21
- package/src/cli/doctor-panes.ts +124 -0
- package/src/cli/doctor-toolchain.ts +57 -0
- package/src/cli/doctor.ts +20 -1
- package/src/cli/eval-inventory.ts +436 -0
- package/src/cli/eval.ts +13 -0
- package/src/cli/evidence-detail.ts +88 -0
- package/src/cli/evidence-inventory.ts +183 -0
- package/src/cli/evidence.ts +30 -5
- package/src/cli/fleet-decisions.ts +69 -0
- package/src/cli/fleet-inspect.ts +334 -0
- package/src/cli/fleet-verify.ts +133 -0
- package/src/cli/fleet-view.ts +810 -0
- package/src/cli/fleet.ts +148 -37
- package/src/cli/index.ts +14 -2
- package/src/cli/interop-inspect.ts +128 -0
- package/src/cli/interop.ts +34 -0
- package/src/cli/panes.ts +35 -0
- package/src/cli/reset.ts +5 -2
- package/src/cli/run.ts +58 -0
- package/src/cli/skills-inventory.ts +185 -0
- package/src/cli/skills.ts +16 -13
- package/src/cli/tools.ts +321 -0
- package/src/cli/trace-inspect.ts +252 -0
- package/src/cli/trace.ts +23 -2
- package/src/cli/verifiers-inspect.ts +347 -0
- package/src/cli/verifiers.ts +9 -0
- package/src/core/bus-events.ts +4 -0
- package/src/core/config.ts +49 -0
- package/src/core/defaults.ts +93 -7
- package/src/core/response-schema.ts +44 -4
- package/src/core/theme-token-hex.ts +43 -0
- package/src/core/tool-names.ts +2 -1
- package/src/core/xdg.ts +1 -1
- package/src/domains/agents/fleets/build-review.md +0 -3
- package/src/domains/agents/fleets/build-test.md +0 -3
- package/src/domains/agents/result-contract-filesystem.ts +32 -0
- package/src/domains/agents/result-contract.ts +164 -35
- package/src/domains/config/classify.ts +3 -0
- package/src/domains/dispatch/admission-error.ts +9 -0
- package/src/domains/dispatch/admission.ts +22 -21
- package/src/domains/dispatch/capacity-lease.ts +21 -1
- package/src/domains/dispatch/council-topology.ts +398 -0
- package/src/domains/dispatch/extension.ts +222 -50
- package/src/domains/dispatch/fleet-node-prompt.ts +62 -0
- package/src/domains/dispatch/fleet-plan.ts +7 -2
- package/src/domains/dispatch/fleet-run.ts +64 -1
- package/src/domains/dispatch/gate-decisions.ts +11 -1
- package/src/domains/dispatch/gate-role-prompts.ts +9 -0
- package/src/domains/dispatch/gate-topology.ts +289 -0
- package/src/domains/dispatch/index.ts +19 -0
- package/src/domains/dispatch/intent-compatibility.ts +330 -0
- package/src/domains/dispatch/intent.ts +85 -1
- package/src/domains/dispatch/reservation-store.ts +24 -4
- package/src/domains/dispatch/run-event-journal-bridge.ts +149 -0
- package/src/domains/dispatch/run-event-journal.ts +598 -0
- package/src/domains/dispatch/state.ts +45 -1
- package/src/domains/dispatch/types.ts +13 -0
- package/src/domains/dispatch/validation.ts +33 -8
- package/src/domains/eval/compare/compare.ts +3 -16
- package/src/domains/eval/inventory.ts +113 -0
- package/src/domains/eval/schema/serving.ts +31 -0
- package/src/domains/evidence/store.ts +6 -0
- package/src/domains/memory/index.ts +0 -1
- package/src/domains/memory/task-memory-policy.ts +6 -10
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/memory-intervention.ts +33 -21
- package/src/domains/mux/contract.ts +434 -0
- package/src/domains/mux/detect.ts +158 -0
- package/src/domains/mux/extension.ts +47 -0
- package/src/domains/mux/index.ts +96 -0
- package/src/domains/mux/manifest.ts +6 -0
- package/src/domains/mux/operations.ts +164 -0
- package/src/domains/mux/pane-registry.ts +90 -0
- package/src/domains/mux/protocol.ts +49 -0
- package/src/domains/mux/socket-client.ts +816 -0
- package/src/domains/mux/types.ts +222 -0
- package/src/domains/mux/viewer-command.ts +59 -0
- package/src/domains/mux/yazi/assets/init.lua +2 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/LICENSE +21 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/README.md +78 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/main.lua +255 -0
- package/src/domains/mux/yazi/assets/plugins/git.yazi/types.lua +12 -0
- package/src/domains/mux/yazi/assets/yazi.toml +17 -0
- package/src/domains/mux/yazi/event-stream.ts +180 -0
- package/src/domains/mux/yazi/profile.ts +299 -0
- package/src/domains/mux/yazi/session.ts +228 -0
- package/src/domains/mux/yazi/theme.ts +30 -0
- package/src/domains/observability/cost.ts +21 -0
- package/src/domains/observability/index.ts +2 -0
- package/src/domains/observability/trace-store.ts +42 -0
- package/src/domains/providers/endpoint-capacity.ts +154 -22
- package/src/domains/providers/endpoint-slots-store.ts +189 -0
- package/src/domains/providers/extension.ts +20 -3
- package/src/domains/providers/index.ts +22 -0
- package/src/domains/providers/model-runtime-capabilities.ts +32 -0
- package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -0
- package/src/domains/providers/runtimes/protocol/litellm.ts +375 -0
- package/src/domains/providers/support.ts +1 -0
- package/src/domains/providers/target-model-cache.ts +124 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/skills/loader.ts +33 -0
- package/src/domains/safety/action-classifier.ts +6 -0
- package/src/domains/toolchain/archive.ts +175 -0
- package/src/domains/toolchain/contract.ts +28 -0
- package/src/domains/toolchain/extension.ts +47 -0
- package/src/domains/toolchain/index.ts +39 -0
- package/src/domains/toolchain/install.ts +327 -0
- package/src/domains/toolchain/manifest.ts +8 -0
- package/src/domains/toolchain/paths.ts +34 -0
- package/src/domains/toolchain/registry.ts +265 -0
- package/src/domains/toolchain/remove.ts +218 -0
- package/src/domains/toolchain/resolve.ts +182 -0
- package/src/domains/toolchain/types.ts +113 -0
- package/src/domains/toolchain/version.ts +88 -0
- package/src/engine/acp/server.ts +413 -70
- package/src/engine/acp/types.ts +19 -1
- package/src/engine/claude/sdk-module.ts +98 -0
- package/src/engine/claude/sdk-runtime.ts +19 -11
- package/src/engine/tui-primitives.ts +21 -0
- package/src/engine/tui.ts +1 -0
- package/src/engine/worker-runtime.ts +2 -13
- package/src/entry/boot-options.ts +2 -0
- package/src/entry/orchestrator.ts +103 -5
- package/src/entry/panes-activation.ts +31 -0
- package/src/entry/with-panes.ts +20 -0
- package/src/interactive/context-overlay.ts +1 -0
- package/src/interactive/cost-overlay.ts +2 -0
- package/src/interactive/council-grid.ts +1 -3
- package/src/interactive/council.ts +11 -0
- package/src/interactive/dispatch-board.ts +26 -16
- package/src/interactive/interactive-application.ts +153 -6
- package/src/interactive/interactive-input-runtime.ts +7 -0
- package/src/interactive/interactive-slash-runtime.ts +36 -6
- package/src/interactive/memory-overlay.ts +1 -0
- package/src/interactive/modal-marker.ts +170 -0
- package/src/interactive/mux-bridge.ts +214 -0
- package/src/interactive/overlay-frame.ts +58 -2
- package/src/interactive/overlay-general-openers.ts +1 -0
- package/src/interactive/overlay-key-routing.ts +14 -3
- package/src/interactive/overlay-lifecycle.ts +19 -3
- package/src/interactive/overlay-model-selectors.ts +40 -3
- package/src/interactive/overlay-permission-lifecycle.ts +90 -22
- package/src/interactive/overlay-transitions.ts +18 -4
- package/src/interactive/overlays/agents.ts +1 -0
- package/src/interactive/overlays/ask-user.ts +136 -30
- package/src/interactive/overlays/auth-dialog.ts +1 -0
- package/src/interactive/overlays/context-reset.ts +1 -0
- package/src/interactive/overlays/cwd-fallback.ts +1 -0
- package/src/interactive/overlays/decisions.ts +11 -11
- package/src/interactive/overlays/extensions.ts +1 -0
- package/src/interactive/overlays/fleet-run-approval.ts +1 -0
- package/src/interactive/overlays/handoff-review.ts +1 -0
- package/src/interactive/overlays/help-reference.ts +2 -0
- package/src/interactive/overlays/interop.ts +1 -0
- package/src/interactive/overlays/library-install-confirm.ts +1 -0
- package/src/interactive/overlays/library-tabs.ts +28 -0
- package/src/interactive/overlays/list-overlay.ts +10 -1
- package/src/interactive/overlays/message-picker.ts +1 -0
- package/src/interactive/overlays/model-scope.ts +86 -0
- package/src/interactive/overlays/model-selector.ts +1 -0
- package/src/interactive/overlays/prompts.ts +1 -0
- package/src/interactive/overlays/session-selector.ts +1 -0
- package/src/interactive/overlays/settings-sections.ts +30 -0
- package/src/interactive/overlays/settings.ts +579 -44
- package/src/interactive/overlays/side-question.ts +1 -0
- package/src/interactive/overlays/skills-hub.ts +3 -11
- package/src/interactive/overlays/tree-selector.ts +1 -0
- package/src/interactive/pane-policy.ts +46 -0
- package/src/interactive/panes-runtime.ts +292 -0
- package/src/interactive/renderers/compaction-summary.ts +29 -0
- package/src/interactive/renderers/worker-entry.ts +122 -14
- package/src/interactive/slash-commands.ts +251 -15
- package/src/interactive/tasks-overlay.ts +1 -0
- package/src/interactive/theme/tokens.ts +3 -14
- package/src/interactive/turn-context.ts +47 -2
- package/src/interactive/view/artifacts.ts +109 -1
- package/src/interactive/view/view-overlay.ts +1 -0
- package/src/interactive/watch-pane.ts +152 -0
- package/src/interactive/worker-progress.ts +7 -1
- package/src/interactive/worker-receipts.ts +19 -1
- package/src/interactive/worker-stream.ts +5 -0
- package/src/interactive/yazi-bridge.ts +444 -0
- package/src/tools/bootstrap.ts +26 -2
- package/src/tools/builtin-tool-catalog.ts +15 -0
- package/src/tools/compete-worktrees.ts +83 -2
- package/src/tools/core-bootstrap.ts +2 -1
- package/src/tools/dispatch-admission.ts +14 -3
- package/src/tools/dispatch-arguments.ts +20 -20
- package/src/tools/dispatch-run-events.ts +134 -19
- package/src/tools/dispatch-runner.ts +29 -7
- package/src/tools/dispatch-types.ts +15 -3
- package/src/tools/dispatch.ts +1 -1
- package/src/tools/executables.ts +17 -14
- package/src/tools/observation.ts +54 -4
- package/src/tools/panes-surface.ts +38 -0
- package/src/tools/panes.ts +112 -0
- package/src/tools/policy.ts +10 -1
- package/src/tools/presentation.ts +1 -0
- package/dist/chunk-D73KXYPF.js +0 -37
- package/dist/chunk-MLOK6ZOS.js +0 -2888
- package/dist/chunk-YKOFT37S.js +0 -279
- package/dist/doctor-TWBWFK5V.js +0 -165
|
@@ -105,6 +105,15 @@ export interface ResultContractFilesystem {
|
|
|
105
105
|
* calling an unreadable path fabricated.
|
|
106
106
|
*/
|
|
107
107
|
pathExists?(path: string): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Whether this location is a directory. Optional for the same reason as
|
|
110
|
+
* `pathExists`: a contract that only needs a file's bytes never asks. A
|
|
111
|
+
* Scout citation does, because a survey task cites directories, and a
|
|
112
|
+
* directory has no bytes to read and no line to ground. Absent means the
|
|
113
|
+
* distinction is unobservable here, so an unreadable location stays
|
|
114
|
+
* unreadable rather than being assumed to be a directory.
|
|
115
|
+
*/
|
|
116
|
+
isDirectory?(path: string): boolean;
|
|
108
117
|
}
|
|
109
118
|
|
|
110
119
|
/**
|
|
@@ -792,6 +801,41 @@ function parseChecks(value: unknown): VerifierCheck[] | null {
|
|
|
792
801
|
|
|
793
802
|
type ScoutCitationEvidence = ScoutCitation & { contentDigest: string };
|
|
794
803
|
|
|
804
|
+
/**
|
|
805
|
+
* Where a citation lands relative to the workspace root, after the written form
|
|
806
|
+
* is normalized away.
|
|
807
|
+
*
|
|
808
|
+
* A model writes the same location six ways: `src`, `./src`, `src/`, `./src/`,
|
|
809
|
+
* and for the root itself `.` or `./`. `path.resolve` collapses every one of
|
|
810
|
+
* them, so the containment question is answered on the resolved pair and never
|
|
811
|
+
* on the string the model typed.
|
|
812
|
+
*
|
|
813
|
+
* The root is the case that broke. `path.relative(cwd, cwd)` is the empty
|
|
814
|
+
* string, and the check read empty as "not inside", which is exactly backwards:
|
|
815
|
+
* the workspace root is the one path guaranteed to be contained. A
|
|
816
|
+
* directory-survey Scout cites `.` because that is what it surveyed, and four
|
|
817
|
+
* runs died `result_contract_exhausted` on evidence that never left the
|
|
818
|
+
* workspace. Containment is unchanged for a real escape, which still resolves
|
|
819
|
+
* to a `..` segment or an absolute path outside the root.
|
|
820
|
+
*/
|
|
821
|
+
function citationWithinWorkspace(cwd: string, citedPath: string): boolean {
|
|
822
|
+
const relative = path.relative(cwd, citedPath);
|
|
823
|
+
if (relative === "") return true;
|
|
824
|
+
return !(relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative));
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* A directory citation carries no bytes and no line, so its evidence digest is
|
|
829
|
+
* bound to the location instead. Prefixed so it can never collide with the
|
|
830
|
+
* content digest of a file that happens to hold the same text.
|
|
831
|
+
*/
|
|
832
|
+
function directoryCitationDigest(cwd: string, citedPath: string): string {
|
|
833
|
+
const relative = path.relative(cwd, citedPath);
|
|
834
|
+
return createHash("sha256")
|
|
835
|
+
.update(`directory:${relative === "" ? "." : relative}`, "utf8")
|
|
836
|
+
.digest("hex");
|
|
837
|
+
}
|
|
838
|
+
|
|
795
839
|
/** One citation against the workspace and, where known, against this run's own reads. */
|
|
796
840
|
function validateScoutCitation(
|
|
797
841
|
input: ResultContractValidationInput,
|
|
@@ -799,10 +843,17 @@ function validateScoutCitation(
|
|
|
799
843
|
): { ok: true; evidence: ScoutCitationEvidence } | { ok: false; reason: string } {
|
|
800
844
|
const cwd = path.resolve(input.cwd);
|
|
801
845
|
const citedPath = path.resolve(cwd, citation.path);
|
|
802
|
-
|
|
803
|
-
if (relative === "" || relative.startsWith(`..${path.sep}`) || relative === ".." || path.isAbsolute(relative)) {
|
|
846
|
+
if (!citationWithinWorkspace(cwd, citedPath)) {
|
|
804
847
|
return { ok: false, reason: `Scout citation path escapes the workspace: ${citation.path}` };
|
|
805
848
|
}
|
|
849
|
+
// A directory is a legal reconnaissance location. Existence is the whole
|
|
850
|
+
// check available: there is no content to digest, no line count to bound the
|
|
851
|
+
// cited line against, and no read span to ground it in, because a survey
|
|
852
|
+
// lists a directory rather than reading it. Requiring a live read here would
|
|
853
|
+
// reject the correct answer to every directory-survey task.
|
|
854
|
+
if (input.filesystem.isDirectory?.(citedPath) === true) {
|
|
855
|
+
return { ok: true, evidence: { ...citation, contentDigest: directoryCitationDigest(cwd, citedPath) } };
|
|
856
|
+
}
|
|
806
857
|
const content = input.filesystem.readFile(citedPath);
|
|
807
858
|
if (content === null) return { ok: false, reason: `Scout citation cannot be read: ${citation.path}` };
|
|
808
859
|
const lineCount = content.split(/\r\n|\r|\n/u).length;
|
|
@@ -888,14 +939,57 @@ function groundDegradedScout(
|
|
|
888
939
|
|
|
889
940
|
function validateVerifier(contract: ResultContract, output: string | null): ResultContractValidation {
|
|
890
941
|
const parsed = parseJson(output);
|
|
891
|
-
if (!parsed.ok) return failure(contract, "fail", parsed.reason);
|
|
942
|
+
if (!parsed.ok) return failure(contract, "fail", `Verifier result payload failed: ${parsed.reason}`);
|
|
892
943
|
const value = parsed.value;
|
|
893
|
-
|
|
894
|
-
|
|
944
|
+
const unknown = Object.keys(value).filter((key) => key !== "verdict" && key !== "checks");
|
|
945
|
+
if (unknown.length > 0) {
|
|
946
|
+
return failure(
|
|
947
|
+
contract,
|
|
948
|
+
"fail",
|
|
949
|
+
`Verifier result field${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")} ${unknown.length === 1 ? "is" : "are"} not legal; legal top-level fields are verdict and checks`,
|
|
950
|
+
);
|
|
895
951
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
952
|
+
if (value.verdict !== "pass" && value.verdict !== "fail") {
|
|
953
|
+
return failure(contract, "fail", 'Verifier field "verdict" must be one of: pass | fail');
|
|
954
|
+
}
|
|
955
|
+
if (!Array.isArray(value.checks) || value.checks.length === 0) {
|
|
956
|
+
return failure(
|
|
957
|
+
contract,
|
|
958
|
+
"fail",
|
|
959
|
+
'Verifier field "checks" must be a non-empty array of {name, passed, evidence}; each checks[].passed value must be one of: true | false',
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
const checks: VerifierCheck[] = [];
|
|
963
|
+
for (const [index, raw] of value.checks.entries()) {
|
|
964
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
965
|
+
return failure(contract, "fail", `Verifier field "checks[${index}]" must be an object`);
|
|
966
|
+
}
|
|
967
|
+
const check = raw as Record<string, unknown>;
|
|
968
|
+
const checkUnknown = Object.keys(check).filter((key) => key !== "name" && key !== "passed" && key !== "evidence");
|
|
969
|
+
if (checkUnknown.length > 0) {
|
|
970
|
+
return failure(
|
|
971
|
+
contract,
|
|
972
|
+
"fail",
|
|
973
|
+
`Verifier field "checks[${index}].${checkUnknown[0]}" is not legal; legal check fields are name, passed, and evidence`,
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
if (!string(check.name)) {
|
|
977
|
+
return failure(contract, "fail", `Verifier field "checks[${index}].name" must be a non-empty string`);
|
|
978
|
+
}
|
|
979
|
+
if (typeof check.passed !== "boolean") {
|
|
980
|
+
return failure(contract, "fail", `Verifier field "checks[${index}].passed" must be one of: true | false`);
|
|
981
|
+
}
|
|
982
|
+
if (!string(check.evidence)) {
|
|
983
|
+
return failure(contract, "fail", `Verifier field "checks[${index}].evidence" must be a non-empty string`);
|
|
984
|
+
}
|
|
985
|
+
checks.push({ name: check.name, passed: check.passed, evidence: check.evidence });
|
|
986
|
+
}
|
|
987
|
+
if ((value.verdict === "pass") !== checks.every((check) => check.passed)) {
|
|
988
|
+
return failure(
|
|
989
|
+
contract,
|
|
990
|
+
"fail",
|
|
991
|
+
'Verifier field "verdict" must agree with every checks[].passed value; verdict legal values are pass | fail and checks[].passed legal values are true | false',
|
|
992
|
+
);
|
|
899
993
|
}
|
|
900
994
|
const verifier: VerifierResult = { verdict: value.verdict, checks };
|
|
901
995
|
return success(contract, value.verdict, verifier, { verifier });
|
|
@@ -1086,23 +1180,39 @@ export function resultContractAuthorship(contract: ResultContract, output: strin
|
|
|
1086
1180
|
|
|
1087
1181
|
function validateDebugger(contract: ResultContract, output: string | null): ResultContractValidation {
|
|
1088
1182
|
const parsed = parseJson(output);
|
|
1089
|
-
if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
|
|
1183
|
+
if (!parsed.ok) return failure(contract, "unmeasured", `Debugger result payload failed: ${parsed.reason}`);
|
|
1090
1184
|
const value = parsed.value;
|
|
1185
|
+
const unknown = Object.keys(value).filter(
|
|
1186
|
+
(key) => key !== "diagnosis" && key !== "reproduction" && key !== "evidence",
|
|
1187
|
+
);
|
|
1188
|
+
if (unknown.length > 0) {
|
|
1189
|
+
return failure(
|
|
1190
|
+
contract,
|
|
1191
|
+
"unmeasured",
|
|
1192
|
+
`Debugger result field${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")} ${unknown.length === 1 ? "is" : "are"} not legal; legal top-level fields are diagnosis, reproduction, and evidence`,
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
if (!string(value.diagnosis)) {
|
|
1196
|
+
return failure(contract, "unmeasured", 'Debugger field "diagnosis" must be a non-empty string');
|
|
1197
|
+
}
|
|
1091
1198
|
if (
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
value.reproduction !== "not-reproduced" &&
|
|
1096
|
-
value.reproduction !== "unknown") ||
|
|
1097
|
-
!Array.isArray(value.evidence) ||
|
|
1098
|
-
value.evidence.some((entry) => !string(entry))
|
|
1199
|
+
value.reproduction !== "reproduced" &&
|
|
1200
|
+
value.reproduction !== "not-reproduced" &&
|
|
1201
|
+
value.reproduction !== "unknown"
|
|
1099
1202
|
) {
|
|
1100
1203
|
return failure(
|
|
1101
1204
|
contract,
|
|
1102
1205
|
"unmeasured",
|
|
1103
|
-
|
|
1206
|
+
'Debugger field "reproduction" must be one of: reproduced | not-reproduced | unknown',
|
|
1104
1207
|
);
|
|
1105
1208
|
}
|
|
1209
|
+
if (!Array.isArray(value.evidence)) {
|
|
1210
|
+
return failure(contract, "unmeasured", 'Debugger field "evidence" must be an array of strings');
|
|
1211
|
+
}
|
|
1212
|
+
const malformedEvidence = value.evidence.findIndex((entry) => !string(entry));
|
|
1213
|
+
if (malformedEvidence >= 0) {
|
|
1214
|
+
return failure(contract, "unmeasured", `Debugger field "evidence[${malformedEvidence}]" must be a non-empty string`);
|
|
1215
|
+
}
|
|
1106
1216
|
return success(contract, "unmeasured", value);
|
|
1107
1217
|
}
|
|
1108
1218
|
|
|
@@ -1112,29 +1222,47 @@ function validateResearch(
|
|
|
1112
1222
|
networkAllowed: boolean,
|
|
1113
1223
|
): ResultContractValidation {
|
|
1114
1224
|
const parsed = parseJson(output);
|
|
1115
|
-
if (!parsed.ok) return failure(contract, "unmeasured", parsed.reason);
|
|
1225
|
+
if (!parsed.ok) return failure(contract, "unmeasured", `Research result payload failed: ${parsed.reason}`);
|
|
1116
1226
|
const value = parsed.value;
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
(value.source !== "local" && value.source !== "external") ||
|
|
1120
|
-
!Array.isArray(value.findings)
|
|
1121
|
-
) {
|
|
1227
|
+
const unknown = Object.keys(value).filter((key) => key !== "source" && key !== "findings");
|
|
1228
|
+
if (unknown.length > 0) {
|
|
1122
1229
|
return failure(
|
|
1123
1230
|
contract,
|
|
1124
1231
|
"unmeasured",
|
|
1125
|
-
|
|
1232
|
+
`Research result field${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")} ${unknown.length === 1 ? "is" : "are"} not legal; legal top-level fields are source and findings`,
|
|
1126
1233
|
);
|
|
1127
1234
|
}
|
|
1235
|
+
if (value.source !== "local" && value.source !== "external") {
|
|
1236
|
+
return failure(contract, "unmeasured", 'Research field "source" must be one of: local | external');
|
|
1237
|
+
}
|
|
1238
|
+
if (!Array.isArray(value.findings)) {
|
|
1239
|
+
return failure(contract, "unmeasured", 'Research field "findings" must be an array of {claim, evidence} objects');
|
|
1240
|
+
}
|
|
1128
1241
|
if (value.source === "external" && !networkAllowed) {
|
|
1129
|
-
return failure(
|
|
1242
|
+
return failure(
|
|
1243
|
+
contract,
|
|
1244
|
+
"unmeasured",
|
|
1245
|
+
'Research field "source" is external but the run has no allowed network posture; legal values are local | external, and use local for workspace-only evidence',
|
|
1246
|
+
);
|
|
1130
1247
|
}
|
|
1131
|
-
for (const finding of value.findings) {
|
|
1248
|
+
for (const [index, finding] of value.findings.entries()) {
|
|
1132
1249
|
if (finding === null || typeof finding !== "object" || Array.isArray(finding)) {
|
|
1133
|
-
return failure(contract, "unmeasured",
|
|
1250
|
+
return failure(contract, "unmeasured", `Research field "findings[${index}]" must be an object`);
|
|
1134
1251
|
}
|
|
1135
1252
|
const record = finding as Record<string, unknown>;
|
|
1136
|
-
|
|
1137
|
-
|
|
1253
|
+
const findingUnknown = Object.keys(record).filter((key) => key !== "claim" && key !== "evidence");
|
|
1254
|
+
if (findingUnknown.length > 0) {
|
|
1255
|
+
return failure(
|
|
1256
|
+
contract,
|
|
1257
|
+
"unmeasured",
|
|
1258
|
+
`Research field "findings[${index}].${findingUnknown[0]}" is not legal; legal finding fields are claim and evidence`,
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
if (!string(record.claim)) {
|
|
1262
|
+
return failure(contract, "unmeasured", `Research field "findings[${index}].claim" must be a non-empty string`);
|
|
1263
|
+
}
|
|
1264
|
+
if (!string(record.evidence)) {
|
|
1265
|
+
return failure(contract, "unmeasured", `Research field "findings[${index}].evidence" must be a non-empty string`);
|
|
1138
1266
|
}
|
|
1139
1267
|
}
|
|
1140
1268
|
return success(contract, "unmeasured", value);
|
|
@@ -1415,10 +1543,11 @@ export const RESULT_CONTRACT_ANCHOR_LIMIT = 12;
|
|
|
1415
1543
|
|
|
1416
1544
|
/**
|
|
1417
1545
|
* The exact terminal shape each contract accepts, quoted to the model verbatim.
|
|
1418
|
-
* This is the one place a contract's wire example is written; agent recipes
|
|
1419
|
-
* repair rounds
|
|
1546
|
+
* This is the one place a contract's wire example is written; agent recipes,
|
|
1547
|
+
* repair rounds, and a fleet node's own answer directive all cite it, so a
|
|
1548
|
+
* prompt cannot drift from its validator.
|
|
1420
1549
|
*/
|
|
1421
|
-
function resultContractShape(contract: ResultContract): string {
|
|
1550
|
+
export function resultContractShape(contract: ResultContract): string {
|
|
1422
1551
|
switch (contract.kind) {
|
|
1423
1552
|
case "architect-plan":
|
|
1424
1553
|
return `a plan artifact written to ${contract.path}, then optionally {"commitMessage":"...","summary":"..."} describing it`;
|
|
@@ -1428,15 +1557,15 @@ function resultContractShape(contract: ResultContract): string {
|
|
|
1428
1557
|
// run already failed twice, so it is told the cheaper exit as well.
|
|
1429
1558
|
return '{"findings":[{"claim":"what you observed","path":"src/file.ts","line":1}],"needsSplit":false,"proposedSubtasks":[]} or {"findings":[],"needsSplit":true,"proposedSubtasks":[{"id":"inspect","task":"Inspect the boundary","dependencies":[],"expectedResultContract":"scout-report","requestedAuthority":"read-only"}]} or, if you cannot produce a citation you are sure of, at least {"findings":[{"claim":"what you observed"}]}, which is accepted as an ungrounded lead rather than losing the run';
|
|
1430
1559
|
case "verifier-report":
|
|
1431
|
-
return '{"verdict":"pass","checks":[{"name":"npm run typecheck","passed":true,"evidence":"exit 0"}]}';
|
|
1560
|
+
return 'one of {"verdict":"pass","checks":[{"name":"npm run typecheck","passed":true,"evidence":"exit 0"}]} or {"verdict":"fail","checks":[{"name":"npm run typecheck","passed":false,"evidence":"exit 1"}]}; verdict legal values are pass | fail and checks[].passed legal values are true | false';
|
|
1432
1561
|
case "council-report":
|
|
1433
1562
|
return '{"members":[{"label":"alpha","runId":"run-1","round":1,"answer":"..."}],"synthesis":{"kind":"none"}}';
|
|
1434
1563
|
case "council-ballot":
|
|
1435
1564
|
return COUNCIL_BALLOT_SHAPE;
|
|
1436
1565
|
case "debugger-report":
|
|
1437
|
-
return '{"diagnosis":"...","reproduction":"reproduced","evidence":["..."]}';
|
|
1566
|
+
return 'one of {"diagnosis":"...","reproduction":"reproduced","evidence":["..."]}, {"diagnosis":"...","reproduction":"not-reproduced","evidence":["..."]}, or {"diagnosis":"...","reproduction":"unknown","evidence":["..."]}; reproduction legal values are reproduced | not-reproduced | unknown';
|
|
1438
1567
|
case "research-report":
|
|
1439
|
-
return '{"source":"local","findings":[{"claim":"...","evidence":"..."}]}';
|
|
1568
|
+
return 'one of {"source":"local","findings":[{"claim":"...","evidence":"..."}]} or {"source":"external","findings":[{"claim":"...","evidence":"..."}]}; source legal values are local | external';
|
|
1440
1569
|
case "mutation-report":
|
|
1441
1570
|
return '{"mutatedPaths":["src/file.ts"],"validations":[{"name":"npm test","passed":true,"evidence":"exit 0"}],"commitMessage":"optional: the commit message for this change","summary":"optional: one line"}';
|
|
1442
1571
|
case "provenance-report":
|
|
@@ -28,6 +28,9 @@ const HOT_RELOAD_FIELDS = new Set<string>([
|
|
|
28
28
|
"modelSelector",
|
|
29
29
|
"terminal.smoothStreaming",
|
|
30
30
|
"attribution.gitCommits",
|
|
31
|
+
// The bridge reads these on every explicit open; no mux re-detection is
|
|
32
|
+
// needed because the host capability rung remains `panes.enabled`.
|
|
33
|
+
"panes.yazi",
|
|
31
34
|
// The watchdog registration reads its settings live on every trigger, so
|
|
32
35
|
// enabling it, retargeting it, or changing its cadence takes effect on the
|
|
33
36
|
// next turn boundary without a restart or a session-routing patch.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A queued assignment was intentionally canceled before it acquired capacity. */
|
|
2
|
+
export class AdmissionCanceledError extends Error {
|
|
3
|
+
readonly code = "admission_canceled" as const;
|
|
4
|
+
|
|
5
|
+
constructor(message = "dispatch: admission canceled before a capacity slot opened") {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "AdmissionCanceledError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -2,6 +2,7 @@ import { randomBytes } from "node:crypto";
|
|
|
2
2
|
import { endpointLabel } from "../providers/endpoint-capacity.js";
|
|
3
3
|
import type { ActionClass } from "../safety/action-classifier.js";
|
|
4
4
|
import type { ScopeSpec } from "../safety/scope.js";
|
|
5
|
+
import { AdmissionCanceledError } from "./admission-error.js";
|
|
5
6
|
import { createAdmissionQueue } from "./admission-queue.js";
|
|
6
7
|
import {
|
|
7
8
|
acquireCapacityLease,
|
|
@@ -131,7 +132,12 @@ function describeAdmissionFailure(input: {
|
|
|
131
132
|
holders === undefined
|
|
132
133
|
? "the supplied capacity snapshot does not attribute the occupied slots"
|
|
133
134
|
: describeEndpointCapacityHolders(holders);
|
|
134
|
-
|
|
135
|
+
const queued = input.queueDepth > 0 ? `, ${input.queueDepth} more queued` : "";
|
|
136
|
+
return [
|
|
137
|
+
`dispatch: admission timed out after ${Math.round(input.waitedMs)}ms waiting for an endpoint slot`,
|
|
138
|
+
` on '${endpointLabel(input.endpointKey)}' (${endpointActive}/${endpointLimit} slots${queued}): ${occupancy}.`,
|
|
139
|
+
" Wait for the running request to settle or dispatch this work again.",
|
|
140
|
+
].join("");
|
|
135
141
|
}
|
|
136
142
|
}
|
|
137
143
|
const nodeLimit = input.limits.nodes[input.nodeId];
|
|
@@ -202,14 +208,9 @@ export function createCapacityAdmissionController(options: {
|
|
|
202
208
|
admittedLease = request.value();
|
|
203
209
|
return true;
|
|
204
210
|
} catch (error) {
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
if (error instanceof Error && /endpoint '.*' capacity reached/u.test(error.message)) {
|
|
209
|
-
queue.fail(request.requestId, error);
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
// Node and global capacity can wait. Anything else fails the request.
|
|
211
|
+
// Saturation at any capacity dimension is transient and keeps its
|
|
212
|
+
// assignment in the one bounded admission queue. Unavailable capacity,
|
|
213
|
+
// draining, corrupt state, and every other error still fail immediately.
|
|
213
214
|
if (error instanceof Error && /capacity reached/.test(error.message)) return false;
|
|
214
215
|
queue.fail(request.requestId, error instanceof Error ? error : new Error(String(error)));
|
|
215
216
|
return false;
|
|
@@ -278,18 +279,18 @@ export function createCapacityAdmissionController(options: {
|
|
|
278
279
|
pumpNow();
|
|
279
280
|
const outcome = await outcomePromise;
|
|
280
281
|
if (outcome.state !== "admitted") {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
);
|
|
282
|
+
const detail = describeAdmissionFailure({
|
|
283
|
+
state: outcome.state,
|
|
284
|
+
nodeId: input.nodeId,
|
|
285
|
+
...(input.endpointKey !== undefined ? { endpointKey: input.endpointKey } : {}),
|
|
286
|
+
waitedMs: now() - queuedAt,
|
|
287
|
+
overdueAtQueueMs: queuedAt - input.deadlineAt,
|
|
288
|
+
queueDepth: queue.size(),
|
|
289
|
+
limits: options.limits(),
|
|
290
|
+
usage: options.usage?.() ?? capacityLeaseUsage({ nowMs: now() }),
|
|
291
|
+
});
|
|
292
|
+
if (outcome.state === "canceled") throw new AdmissionCanceledError(detail);
|
|
293
|
+
throw new Error(detail);
|
|
293
294
|
}
|
|
294
295
|
const lease = acquired.get(input.assignmentId);
|
|
295
296
|
if (!lease) throw new Error("dispatch: admitted request has no capacity lease");
|
|
@@ -263,6 +263,26 @@ export function describeEndpointCapacityHolders(holders: EndpointCapacityHolders
|
|
|
263
263
|
return `${named} ${total === 1 ? "holds" : "hold"} ${total === 1 ? "the slot" : "the slots"}`;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
+
/**
|
|
267
|
+
* The ways past a saturated inference endpoint, in the order an operator can
|
|
268
|
+
* act on them.
|
|
269
|
+
*
|
|
270
|
+
* `maxConcurrentRequests` is named because the conservative default of one slot
|
|
271
|
+
* is a guess about an unprobed server, and on a server started with
|
|
272
|
+
* `--parallel 4` it is simply wrong. Without that sentence the denial reads as
|
|
273
|
+
* a hardware limit and the operator has no reason to look for a setting.
|
|
274
|
+
*
|
|
275
|
+
* `rosterFloor` is the smallest same-wave width the caller's topology can have.
|
|
276
|
+
* A council runs its whole roster in one wave, so "dispatch fewer at once" is
|
|
277
|
+
* not a move it has; saying so keeps the remedy honest.
|
|
278
|
+
*/
|
|
279
|
+
export function endpointCapacityRemedy(input?: { rosterFloor?: number }): string {
|
|
280
|
+
const ways =
|
|
281
|
+
"set this target's maxConcurrentRequests to the slot count the server was started with, collect in-flight runs, or point workers at a second server";
|
|
282
|
+
if (input?.rosterFloor === undefined) return `reduce the same-wave worker count, ${ways}`;
|
|
283
|
+
return `a council runs its whole roster in one wave and cannot go below ${input.rosterFloor} members, so ${ways}`;
|
|
284
|
+
}
|
|
285
|
+
|
|
266
286
|
function assertCapacity(
|
|
267
287
|
file: CapacityStateFile,
|
|
268
288
|
nodeId: string,
|
|
@@ -299,7 +319,7 @@ function assertCapacity(
|
|
|
299
319
|
const used = holders.leases + holders.reservations + holders.foregroundStreams;
|
|
300
320
|
if (used >= endpointLimit)
|
|
301
321
|
throw new Error(
|
|
302
|
-
`dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity reached (${used}/${endpointLimit} slots): ${describeEndpointCapacityHolders(holders)};
|
|
322
|
+
`dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity reached (${used}/${endpointLimit} slots): ${describeEndpointCapacityHolders(holders)}; ${endpointCapacityRemedy()}`,
|
|
303
323
|
);
|
|
304
324
|
}
|
|
305
325
|
}
|