@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
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
decideReviewGate,
|
|
4
|
+
materializePendingGateDecision,
|
|
5
|
+
readGateDecisionArtifacts,
|
|
6
|
+
readGateDecisionArtifactsForRunIds,
|
|
7
|
+
stagePendingGateDecision,
|
|
8
|
+
verifyGateDecisionArtifact
|
|
9
|
+
} from "./chunk-X75E3D2N.js";
|
|
2
10
|
import {
|
|
3
11
|
RUN_RECEIPT_INTEGRITY_ALGORITHM,
|
|
4
12
|
RUN_RECEIPT_INTEGRITY_VERSION,
|
|
@@ -10,24 +18,20 @@ import {
|
|
|
10
18
|
inspectRunReceiptTrustStatus,
|
|
11
19
|
isReceiptIntegrity,
|
|
12
20
|
isTrustStatusIdentifier,
|
|
13
|
-
loadEvalArtifact,
|
|
14
21
|
normalizeTrustStatus,
|
|
15
|
-
parseEvalArtifactV4,
|
|
16
|
-
redactArtifactForStorage,
|
|
17
22
|
retiredIntegrityVersionOf,
|
|
18
23
|
sha256,
|
|
19
|
-
sumEvalHarnessMetrics,
|
|
20
24
|
trustVerdict,
|
|
21
25
|
verifyReceiptIntegrity,
|
|
22
26
|
withReceiptIntegrity
|
|
23
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-B7OBL7PK.js";
|
|
24
28
|
import {
|
|
25
29
|
protectedArtifactFromSessionEntry,
|
|
26
30
|
protectedArtifactStateFromSessionEntries,
|
|
27
31
|
readAuditRows,
|
|
28
32
|
readSessionEntriesForId,
|
|
29
33
|
responseModelIdObservationFromRecord
|
|
30
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-QREDIESB.js";
|
|
31
35
|
import {
|
|
32
36
|
applyTaskWorktree,
|
|
33
37
|
captureWorkspaceSnapshot,
|
|
@@ -35,19 +39,32 @@ import {
|
|
|
35
39
|
createTaskWorktree,
|
|
36
40
|
createWriteBoundaryEnforcer,
|
|
37
41
|
gitCheckoutRoot
|
|
38
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-U77AMWDL.js";
|
|
39
43
|
import {
|
|
40
44
|
executionPlanAncestors,
|
|
41
45
|
spliceExecutionPlan
|
|
42
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-QBJA7R7N.js";
|
|
43
47
|
import {
|
|
44
48
|
parseRigorOverride,
|
|
45
49
|
resolveRigor
|
|
46
50
|
} from "./chunk-RVG5JXAL.js";
|
|
47
51
|
import {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
loadEvalArtifact,
|
|
53
|
+
parseEvalArtifactV4,
|
|
54
|
+
redactArtifactForStorage,
|
|
55
|
+
sumEvalHarnessMetrics
|
|
56
|
+
} from "./chunk-NHLBIGRH.js";
|
|
57
|
+
import {
|
|
58
|
+
defaultRunEventJournal,
|
|
59
|
+
removeRunEventJournals
|
|
60
|
+
} from "./chunk-IQ7KR472.js";
|
|
61
|
+
import {
|
|
62
|
+
AdmissionCanceledError,
|
|
63
|
+
EVENT_TEE_LIMIT,
|
|
64
|
+
createWorkerOutputCapture,
|
|
65
|
+
durableAssistantTextFromEvent,
|
|
66
|
+
startDispatchEventPump
|
|
67
|
+
} from "./chunk-T56WDKA5.js";
|
|
51
68
|
import {
|
|
52
69
|
LOCAL_NODE_ID,
|
|
53
70
|
computeSettingsFingerprint,
|
|
@@ -58,9 +75,14 @@ import {
|
|
|
58
75
|
receiptAttestationFields,
|
|
59
76
|
routeFactVerdict,
|
|
60
77
|
spawnNativeWorker
|
|
61
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-QLFS5GO2.js";
|
|
79
|
+
import {
|
|
80
|
+
FLEET_COMMAND_BASE_ENV,
|
|
81
|
+
normalizeWriteBoundary
|
|
82
|
+
} from "./chunk-CTJ4RNAA.js";
|
|
62
83
|
import {
|
|
63
84
|
AGENT_LEDGER_PROMPT_MAX_CHARS,
|
|
85
|
+
COUNCIL_MIN_MEMBERS,
|
|
64
86
|
RETRYABLE_OUTCOMES,
|
|
65
87
|
UnsupportedResponseSchemaError,
|
|
66
88
|
WORKER_EXIT_PERMISSION_REQUIRED,
|
|
@@ -70,24 +92,23 @@ import {
|
|
|
70
92
|
agentRoleReadinessReport,
|
|
71
93
|
agentRouteCandidates,
|
|
72
94
|
antigravitySubprocessConfigForAutonomy,
|
|
73
|
-
applyToolProfile,
|
|
74
95
|
approvedRouteCandidates,
|
|
75
96
|
assertApprovedAssignmentRoute,
|
|
76
97
|
assertApprovedRecoveryCapability,
|
|
77
|
-
assertToolProfileEnforceable,
|
|
78
98
|
claimConflicts,
|
|
79
99
|
classifyAgentTask,
|
|
80
100
|
claudeSubprocessPermissionConfigForAutonomy,
|
|
81
101
|
competeStanceLiner,
|
|
82
102
|
createRunEffectsRecorder,
|
|
103
|
+
declaredScopeIntent,
|
|
83
104
|
declaredScopeReplacementDiagnostic,
|
|
84
105
|
declaredScopeReplacementNotice,
|
|
85
|
-
describeCallAction,
|
|
86
106
|
isBoundedGateRolePrompt,
|
|
87
107
|
isClaudeCanonicalTool,
|
|
88
108
|
isResponseSchemaRejection,
|
|
89
109
|
isRunOutcomeCode,
|
|
90
110
|
networkToolsDisabled,
|
|
111
|
+
nodeResultContractFilesystem,
|
|
91
112
|
projectExecutionHandoffs,
|
|
92
113
|
renderAgentLedger,
|
|
93
114
|
resolveDispatchPathScope,
|
|
@@ -98,7 +119,7 @@ import {
|
|
|
98
119
|
serializeWorkerRuntimeDescriptor,
|
|
99
120
|
toolPromptHintsForNames,
|
|
100
121
|
validateJobSpec
|
|
101
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-J4W7KFM7.js";
|
|
102
123
|
import {
|
|
103
124
|
decideRoute,
|
|
104
125
|
defaultRoutingIntent,
|
|
@@ -116,7 +137,20 @@ import {
|
|
|
116
137
|
routingIntentRejection,
|
|
117
138
|
sameRouteIdentity,
|
|
118
139
|
toRouteCandidate
|
|
119
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-SJ5ZKQ4S.js";
|
|
141
|
+
import {
|
|
142
|
+
assessFinishContract
|
|
143
|
+
} from "./chunk-GKF55TAZ.js";
|
|
144
|
+
import {
|
|
145
|
+
WRITE_ROOT_REFUSED_TOOLS
|
|
146
|
+
} from "./chunk-32KWKNSF.js";
|
|
147
|
+
import {
|
|
148
|
+
describeCallAction
|
|
149
|
+
} from "./chunk-TVHHYFHE.js";
|
|
150
|
+
import {
|
|
151
|
+
applyToolProfile,
|
|
152
|
+
assertToolProfileEnforceable
|
|
153
|
+
} from "./chunk-42FMPA75.js";
|
|
120
154
|
import {
|
|
121
155
|
appliesRecipeResultContract,
|
|
122
156
|
gateRouteCorrelation,
|
|
@@ -126,14 +160,30 @@ import {
|
|
|
126
160
|
withAttemptRole
|
|
127
161
|
} from "./chunk-H7IXIC72.js";
|
|
128
162
|
import {
|
|
129
|
-
|
|
130
|
-
} from "./chunk-
|
|
163
|
+
compareCodepoints
|
|
164
|
+
} from "./chunk-5LXZXPKX.js";
|
|
131
165
|
import {
|
|
132
|
-
|
|
133
|
-
|
|
166
|
+
DEFAULT_AUTONOMY_LEVEL,
|
|
167
|
+
autonomyDenyRejection,
|
|
168
|
+
isSkillActivation,
|
|
169
|
+
mapAutonomy
|
|
170
|
+
} from "./chunk-RAPCMZL4.js";
|
|
134
171
|
import {
|
|
135
|
-
|
|
136
|
-
|
|
172
|
+
createRedactionTally,
|
|
173
|
+
redactSecretsDeep,
|
|
174
|
+
redactSecretsText
|
|
175
|
+
} from "./chunk-4BJ5BYCE.js";
|
|
176
|
+
import {
|
|
177
|
+
truncateUtf8
|
|
178
|
+
} from "./chunk-6XLNIQDB.js";
|
|
179
|
+
import {
|
|
180
|
+
canonicalJson,
|
|
181
|
+
endpointIdentityHash,
|
|
182
|
+
parseAgentLedgerBody
|
|
183
|
+
} from "./chunk-CMZWFGD2.js";
|
|
184
|
+
import {
|
|
185
|
+
pathBoundaryCovers
|
|
186
|
+
} from "./chunk-HHV2GANA.js";
|
|
137
187
|
import {
|
|
138
188
|
agentSpecFingerprint,
|
|
139
189
|
assertAgentSpecPolicy,
|
|
@@ -141,78 +191,61 @@ import {
|
|
|
141
191
|
isUserVisibleAgent,
|
|
142
192
|
normalizeAgentSpec,
|
|
143
193
|
parseJsonObjectPayload,
|
|
144
|
-
parseVerifierResult,
|
|
145
|
-
pathBoundaryCovers,
|
|
146
194
|
resolveAgentToolCompatibility,
|
|
147
195
|
resultContractAuthorship,
|
|
148
196
|
validateRecipeResult
|
|
149
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-DYJP44XW.js";
|
|
150
198
|
import {
|
|
151
199
|
detectValidationCommand
|
|
152
|
-
} from "./chunk-
|
|
153
|
-
import {
|
|
154
|
-
DEFAULT_AUTONOMY_LEVEL,
|
|
155
|
-
autonomyDenyRejection,
|
|
156
|
-
isSkillActivation,
|
|
157
|
-
mapAutonomy
|
|
158
|
-
} from "./chunk-RAPCMZL4.js";
|
|
200
|
+
} from "./chunk-GCSMB2KY.js";
|
|
159
201
|
import {
|
|
160
202
|
isProjectVerifierCheckId,
|
|
161
203
|
isVerificationScriptName
|
|
162
204
|
} from "./chunk-UL3WSD3F.js";
|
|
163
|
-
import {
|
|
164
|
-
createRedactionTally,
|
|
165
|
-
redactSecretsDeep,
|
|
166
|
-
redactSecretsText
|
|
167
|
-
} from "./chunk-4BJ5BYCE.js";
|
|
168
205
|
import {
|
|
169
206
|
canonicalizeExistingPath
|
|
170
207
|
} from "./chunk-ECH6PKUQ.js";
|
|
171
|
-
import {
|
|
172
|
-
canonicalJson,
|
|
173
|
-
endpointIdentityHash,
|
|
174
|
-
parseAgentLedgerBody
|
|
175
|
-
} from "./chunk-CMZWFGD2.js";
|
|
176
|
-
import {
|
|
177
|
-
truncateUtf8
|
|
178
|
-
} from "./chunk-6XLNIQDB.js";
|
|
179
208
|
import {
|
|
180
209
|
ToolNames,
|
|
181
210
|
isBuiltinToolName
|
|
182
|
-
} from "./chunk-
|
|
211
|
+
} from "./chunk-K6BSR66V.js";
|
|
183
212
|
import {
|
|
184
213
|
canonicalizeWireModelId,
|
|
185
|
-
|
|
214
|
+
endpointCapacityFor,
|
|
186
215
|
endpointCapacityForStatus,
|
|
187
216
|
endpointLabel,
|
|
188
217
|
firstRuntimeResolutionError,
|
|
189
218
|
foregroundStreamUsage,
|
|
190
219
|
isDispatchEligibleRuntime,
|
|
220
|
+
normalizeCostProvenance,
|
|
221
|
+
resolveEndpointCapacities,
|
|
191
222
|
resolveModelCapabilities,
|
|
192
223
|
resolveRuntimeTarget,
|
|
193
224
|
runtimeResolutionWarnings,
|
|
194
225
|
runtimeTargetSnapshot
|
|
195
|
-
} from "./chunk-
|
|
226
|
+
} from "./chunk-DQITNCXG.js";
|
|
196
227
|
import {
|
|
197
228
|
ceilChars
|
|
198
|
-
} from "./chunk-
|
|
229
|
+
} from "./chunk-UM7N4G5A.js";
|
|
230
|
+
import {
|
|
231
|
+
BusChannels
|
|
232
|
+
} from "./chunk-HLW2MRKE.js";
|
|
233
|
+
import {
|
|
234
|
+
atomicWrite
|
|
235
|
+
} from "./chunk-76ONBSIA.js";
|
|
236
|
+
import {
|
|
237
|
+
assertSafeId
|
|
238
|
+
} from "./chunk-R346GLFC.js";
|
|
199
239
|
import {
|
|
200
240
|
attributeCommitMessage,
|
|
201
241
|
gitCommitAttributionEnabled,
|
|
202
242
|
reportCommitAttributionDiagnostic,
|
|
203
243
|
withManagedGitCommitAttributionEnvironment
|
|
204
|
-
} from "./chunk-
|
|
244
|
+
} from "./chunk-BBVJUZHB.js";
|
|
205
245
|
import {
|
|
206
246
|
MAX_TIMER_DELAY_MS,
|
|
207
247
|
rawDurationMs
|
|
208
248
|
} from "./chunk-FQ4SKYE4.js";
|
|
209
|
-
import {
|
|
210
|
-
BusChannels
|
|
211
|
-
} from "./chunk-RKRLDWD3.js";
|
|
212
|
-
import {
|
|
213
|
-
assertSafeId,
|
|
214
|
-
atomicWrite
|
|
215
|
-
} from "./chunk-KV2AOLDF.js";
|
|
216
249
|
import {
|
|
217
250
|
AI_AGENT_NAME
|
|
218
251
|
} from "./chunk-6EJMN2Y3.js";
|
|
@@ -226,14 +259,14 @@ import {
|
|
|
226
259
|
DEFAULT_DELEGATION_TURN_TIMEOUT_MS,
|
|
227
260
|
DEFAULT_SETTINGS,
|
|
228
261
|
THINKING_LEVELS
|
|
229
|
-
} from "./chunk-
|
|
262
|
+
} from "./chunk-GXNLGKAB.js";
|
|
230
263
|
import {
|
|
231
264
|
GUARDRAIL_DEFAULTS,
|
|
232
265
|
resolveGuardrail
|
|
233
266
|
} from "./chunk-4ZG3XFUR.js";
|
|
234
267
|
import {
|
|
235
268
|
targetRequiresAuth
|
|
236
|
-
} from "./chunk-
|
|
269
|
+
} from "./chunk-BBVYXMFO.js";
|
|
237
270
|
import {
|
|
238
271
|
FILE_LOCK_ACQUIRE_TIMEOUT_MS,
|
|
239
272
|
withStateFileLock,
|
|
@@ -248,7 +281,7 @@ import {
|
|
|
248
281
|
clioDataDir,
|
|
249
282
|
clioStateDir,
|
|
250
283
|
stateRootRemoved
|
|
251
|
-
} from "./chunk-
|
|
284
|
+
} from "./chunk-BYP5D4HI.js";
|
|
252
285
|
import {
|
|
253
286
|
resolveEffectivePricing
|
|
254
287
|
} from "./chunk-VO2LKSTM.js";
|
|
@@ -409,8 +442,8 @@ var StdioJsonRpcTransport = class {
|
|
|
409
442
|
constructor(command, args, options = {}) {
|
|
410
443
|
this.terminationGraceMs = boundedMilliseconds(options.terminationGraceMs, 500);
|
|
411
444
|
this.terminationWaitMs = boundedMilliseconds(options.terminationWaitMs, 2e3);
|
|
412
|
-
this.childClosePromise = new Promise((
|
|
413
|
-
this.resolveChildClose =
|
|
445
|
+
this.childClosePromise = new Promise((resolve4) => {
|
|
446
|
+
this.resolveChildClose = resolve4;
|
|
414
447
|
});
|
|
415
448
|
const childEnvironment = options.env ? { ...process.env, ...options.env } : process.env;
|
|
416
449
|
const attribution = withManagedGitCommitAttributionEnvironment(childEnvironment, {
|
|
@@ -467,10 +500,10 @@ var StdioJsonRpcTransport = class {
|
|
|
467
500
|
const requestTimeoutMs = validateRequestTimeout(method, timeoutMs);
|
|
468
501
|
const id = this.nextId++;
|
|
469
502
|
const message = { jsonrpc: "2.0", id, method, params };
|
|
470
|
-
const promise = new Promise((
|
|
503
|
+
const promise = new Promise((resolve4, reject) => {
|
|
471
504
|
const pending = {
|
|
472
505
|
method,
|
|
473
|
-
resolve: (value) =>
|
|
506
|
+
resolve: (value) => resolve4(value),
|
|
474
507
|
reject
|
|
475
508
|
};
|
|
476
509
|
if (requestTimeoutMs !== void 0) {
|
|
@@ -657,9 +690,9 @@ var StdioJsonRpcTransport = class {
|
|
|
657
690
|
if (remaining <= 0) return this.terminationObserved();
|
|
658
691
|
const interval = Math.min(10, remaining);
|
|
659
692
|
if (this.childHandlesClosed) {
|
|
660
|
-
await new Promise((
|
|
693
|
+
await new Promise((resolve4) => setTimeout(resolve4, interval));
|
|
661
694
|
} else {
|
|
662
|
-
await Promise.race([this.childClosePromise, new Promise((
|
|
695
|
+
await Promise.race([this.childClosePromise, new Promise((resolve4) => setTimeout(resolve4, interval))]);
|
|
663
696
|
}
|
|
664
697
|
}
|
|
665
698
|
return true;
|
|
@@ -724,10 +757,10 @@ var StreamJsonRpcPeerTransport = class {
|
|
|
724
757
|
const requestTimeoutMs = validateRequestTimeout(method, timeoutMs);
|
|
725
758
|
const id = this.nextId++;
|
|
726
759
|
const message = { jsonrpc: "2.0", id, method, params };
|
|
727
|
-
const promise = new Promise((
|
|
760
|
+
const promise = new Promise((resolve4, reject) => {
|
|
728
761
|
const pending = {
|
|
729
762
|
method,
|
|
730
|
-
resolve: (value) =>
|
|
763
|
+
resolve: (value) => resolve4(value),
|
|
731
764
|
reject
|
|
732
765
|
};
|
|
733
766
|
if (requestTimeoutMs !== void 0) {
|
|
@@ -891,162 +924,6 @@ function createStdioServerTransport(options = {}) {
|
|
|
891
924
|
return new StreamJsonRpcPeerTransport(options);
|
|
892
925
|
}
|
|
893
926
|
|
|
894
|
-
// src/domains/dispatch/event-pump.ts
|
|
895
|
-
init_esm_shims();
|
|
896
|
-
var EVENT_TEE_LIMIT = 1024;
|
|
897
|
-
function startDispatchEventPump(source, fold, options = {}) {
|
|
898
|
-
const limit = options.limit ?? EVENT_TEE_LIMIT;
|
|
899
|
-
const pending = [...options.prelude ?? []];
|
|
900
|
-
const waiters = [];
|
|
901
|
-
let finished = false;
|
|
902
|
-
let abandoned = false;
|
|
903
|
-
let dropped = 0;
|
|
904
|
-
const push = (value) => {
|
|
905
|
-
if (abandoned) return;
|
|
906
|
-
const waiter = waiters.shift();
|
|
907
|
-
if (waiter) {
|
|
908
|
-
waiter({ value, done: false });
|
|
909
|
-
return;
|
|
910
|
-
}
|
|
911
|
-
pending.push(value);
|
|
912
|
-
while (pending.length > limit) {
|
|
913
|
-
pending.shift();
|
|
914
|
-
dropped += 1;
|
|
915
|
-
}
|
|
916
|
-
};
|
|
917
|
-
const end = () => {
|
|
918
|
-
finished = true;
|
|
919
|
-
while (waiters.length > 0) {
|
|
920
|
-
waiters.shift()?.({ value: void 0, done: true });
|
|
921
|
-
}
|
|
922
|
-
};
|
|
923
|
-
const notify = (event) => {
|
|
924
|
-
try {
|
|
925
|
-
options.onEvent?.(event);
|
|
926
|
-
} catch (error) {
|
|
927
|
-
options.onError?.(error);
|
|
928
|
-
}
|
|
929
|
-
};
|
|
930
|
-
const done = (async () => {
|
|
931
|
-
try {
|
|
932
|
-
for (const event of options.prelude ?? []) notify(event);
|
|
933
|
-
for await (const event of source) {
|
|
934
|
-
try {
|
|
935
|
-
fold(event);
|
|
936
|
-
} catch (error) {
|
|
937
|
-
options.onError?.(error);
|
|
938
|
-
}
|
|
939
|
-
notify(event);
|
|
940
|
-
push(event);
|
|
941
|
-
}
|
|
942
|
-
} catch (error) {
|
|
943
|
-
options.onError?.(error);
|
|
944
|
-
} finally {
|
|
945
|
-
end();
|
|
946
|
-
}
|
|
947
|
-
})();
|
|
948
|
-
const events = {
|
|
949
|
-
next() {
|
|
950
|
-
if (pending.length > 0) {
|
|
951
|
-
return Promise.resolve({ value: pending.shift(), done: false });
|
|
952
|
-
}
|
|
953
|
-
if (finished || abandoned) return Promise.resolve({ value: void 0, done: true });
|
|
954
|
-
return new Promise((resolve5) => {
|
|
955
|
-
waiters.push(resolve5);
|
|
956
|
-
});
|
|
957
|
-
},
|
|
958
|
-
return() {
|
|
959
|
-
abandoned = true;
|
|
960
|
-
pending.length = 0;
|
|
961
|
-
while (waiters.length > 0) {
|
|
962
|
-
waiters.shift()?.({ value: void 0, done: true });
|
|
963
|
-
}
|
|
964
|
-
return Promise.resolve({ value: void 0, done: true });
|
|
965
|
-
},
|
|
966
|
-
[Symbol.asyncIterator]() {
|
|
967
|
-
return this;
|
|
968
|
-
}
|
|
969
|
-
};
|
|
970
|
-
return { events, done, droppedEvents: () => dropped };
|
|
971
|
-
}
|
|
972
|
-
var WORKER_OUTPUT_MAX_BYTES = 8192;
|
|
973
|
-
var WORKER_OUTPUT_TRUNCATION_MARKER = "\n[worker output truncated]";
|
|
974
|
-
function isRecord2(value) {
|
|
975
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
976
|
-
}
|
|
977
|
-
function assistantTextFromContent(content) {
|
|
978
|
-
if (typeof content === "string") return content;
|
|
979
|
-
if (!Array.isArray(content)) return "";
|
|
980
|
-
return content.map((block) => {
|
|
981
|
-
if (typeof block === "string") return block;
|
|
982
|
-
if (!isRecord2(block)) return "";
|
|
983
|
-
return typeof block.text === "string" ? block.text : "";
|
|
984
|
-
}).join("");
|
|
985
|
-
}
|
|
986
|
-
function isDurableAssistantMessage(message) {
|
|
987
|
-
const stopReason = message.stopReason;
|
|
988
|
-
if (stopReason === "toolUse" || stopReason === "error" || stopReason === "aborted" || stopReason === "cancelled") {
|
|
989
|
-
return false;
|
|
990
|
-
}
|
|
991
|
-
if (!Array.isArray(message.content)) return true;
|
|
992
|
-
return !message.content.some((block) => isRecord2(block) && block.type === "toolCall");
|
|
993
|
-
}
|
|
994
|
-
function durableAssistantTextFromEvent(event) {
|
|
995
|
-
if (!isRecord2(event) || event.type !== "message_end" || !isRecord2(event.message)) return "";
|
|
996
|
-
if (event.message.role !== "assistant" || !isDurableAssistantMessage(event.message)) return "";
|
|
997
|
-
return assistantTextFromContent(event.message.content);
|
|
998
|
-
}
|
|
999
|
-
function boundedOutput(state, text) {
|
|
1000
|
-
const bytes = Buffer.byteLength(text, "utf8");
|
|
1001
|
-
const bounded = truncateUtf8(text, WORKER_OUTPUT_MAX_BYTES, WORKER_OUTPUT_TRUNCATION_MARKER);
|
|
1002
|
-
return { state, text: bounded, bytes, truncated: bounded !== text };
|
|
1003
|
-
}
|
|
1004
|
-
function createWorkerOutputCapture() {
|
|
1005
|
-
let finalText = null;
|
|
1006
|
-
let partialText = "";
|
|
1007
|
-
let partialBytes = 0;
|
|
1008
|
-
let partialStored = 0;
|
|
1009
|
-
return {
|
|
1010
|
-
observe(event) {
|
|
1011
|
-
if (!isRecord2(event)) return;
|
|
1012
|
-
if (event.type === "message_end") {
|
|
1013
|
-
const message = isRecord2(event.message) ? event.message : null;
|
|
1014
|
-
partialText = "";
|
|
1015
|
-
partialBytes = 0;
|
|
1016
|
-
partialStored = 0;
|
|
1017
|
-
if (message === null || message.role !== "assistant") return;
|
|
1018
|
-
if (!isDurableAssistantMessage(message)) return;
|
|
1019
|
-
const text = assistantTextFromContent(message.content).trim();
|
|
1020
|
-
if (text.length > 0) finalText = text;
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
if (event.type !== "message_update") return;
|
|
1024
|
-
const assistantEvent = isRecord2(event.assistantMessageEvent) ? event.assistantMessageEvent : null;
|
|
1025
|
-
if (assistantEvent === null || assistantEvent.type !== "text_delta") return;
|
|
1026
|
-
const delta = assistantEvent.delta;
|
|
1027
|
-
if (typeof delta !== "string" || delta.length === 0) return;
|
|
1028
|
-
partialBytes += Buffer.byteLength(delta, "utf8");
|
|
1029
|
-
if (partialStored < WORKER_OUTPUT_MAX_BYTES) {
|
|
1030
|
-
partialText += delta;
|
|
1031
|
-
partialStored += Buffer.byteLength(delta, "utf8");
|
|
1032
|
-
}
|
|
1033
|
-
},
|
|
1034
|
-
snapshot() {
|
|
1035
|
-
if (partialBytes > 0 && partialText.trim().length > 0) {
|
|
1036
|
-
const bounded = truncateUtf8(partialText.trim(), WORKER_OUTPUT_MAX_BYTES, WORKER_OUTPUT_TRUNCATION_MARKER);
|
|
1037
|
-
return {
|
|
1038
|
-
state: "partial",
|
|
1039
|
-
text: bounded,
|
|
1040
|
-
bytes: partialBytes,
|
|
1041
|
-
truncated: bounded !== partialText.trim() || partialBytes > partialStored
|
|
1042
|
-
};
|
|
1043
|
-
}
|
|
1044
|
-
if (finalText !== null) return boundedOutput("final", finalText);
|
|
1045
|
-
return void 0;
|
|
1046
|
-
}
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
927
|
// src/domains/dispatch/capacity-lease.ts
|
|
1051
928
|
init_esm_shims();
|
|
1052
929
|
import { randomBytes } from "node:crypto";
|
|
@@ -1186,6 +1063,11 @@ function describeEndpointCapacityHolders(holders) {
|
|
|
1186
1063
|
const total = holders.leases + holders.reservations + holders.foregroundStreams;
|
|
1187
1064
|
return `${named} ${total === 1 ? "holds" : "hold"} ${total === 1 ? "the slot" : "the slots"}`;
|
|
1188
1065
|
}
|
|
1066
|
+
function endpointCapacityRemedy(input) {
|
|
1067
|
+
const ways = "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";
|
|
1068
|
+
if (input?.rosterFloor === void 0) return `reduce the same-wave worker count, ${ways}`;
|
|
1069
|
+
return `a council runs its whole roster in one wave and cannot go below ${input.rosterFloor} members, so ${ways}`;
|
|
1070
|
+
}
|
|
1189
1071
|
function assertCapacity(file, nodeId, endpointKey, limits) {
|
|
1190
1072
|
const held2 = heldReservationUsage(file.reservations);
|
|
1191
1073
|
const globalUsed = file.leases.length + held2.global;
|
|
@@ -1214,7 +1096,7 @@ function assertCapacity(file, nodeId, endpointKey, limits) {
|
|
|
1214
1096
|
const used = holders.leases + holders.reservations + holders.foregroundStreams;
|
|
1215
1097
|
if (used >= endpointLimit)
|
|
1216
1098
|
throw new Error(
|
|
1217
|
-
`dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity reached (${used}/${endpointLimit} slots): ${describeEndpointCapacityHolders(holders)};
|
|
1099
|
+
`dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity reached (${used}/${endpointLimit} slots): ${describeEndpointCapacityHolders(holders)}; ${endpointCapacityRemedy()}`
|
|
1218
1100
|
);
|
|
1219
1101
|
}
|
|
1220
1102
|
}
|
|
@@ -1548,7 +1430,7 @@ function renderDispatchReviewerTask(originalTask, builderRunId, cycle, intent) {
|
|
|
1548
1430
|
|
|
1549
1431
|
// src/domains/dispatch/receipt-findings.ts
|
|
1550
1432
|
init_esm_shims();
|
|
1551
|
-
import { createHash as
|
|
1433
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
1552
1434
|
|
|
1553
1435
|
// src/domains/evidence/index.ts
|
|
1554
1436
|
init_esm_shims();
|
|
@@ -1556,15 +1438,15 @@ init_esm_shims();
|
|
|
1556
1438
|
// src/domains/evidence/build.ts
|
|
1557
1439
|
init_esm_shims();
|
|
1558
1440
|
import { mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
|
|
1559
|
-
import { join as
|
|
1441
|
+
import { join as join16 } from "node:path";
|
|
1560
1442
|
|
|
1561
1443
|
// src/domains/dispatch/index.ts
|
|
1562
1444
|
init_esm_shims();
|
|
1563
1445
|
|
|
1564
1446
|
// src/domains/dispatch/extension.ts
|
|
1565
1447
|
init_esm_shims();
|
|
1566
|
-
import { createHash as
|
|
1567
|
-
import {
|
|
1448
|
+
import { createHash as createHash7, randomBytes as randomBytes5 } from "node:crypto";
|
|
1449
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync11 } from "node:fs";
|
|
1568
1450
|
import { isAbsolute as isAbsolute2, relative, resolve as resolvePath, sep } from "node:path";
|
|
1569
1451
|
import { performance as performance5 } from "node:perf_hooks";
|
|
1570
1452
|
|
|
@@ -1575,20 +1457,20 @@ import { performance as performance4 } from "node:perf_hooks";
|
|
|
1575
1457
|
// src/engine/acp/event-mapper.ts
|
|
1576
1458
|
init_esm_shims();
|
|
1577
1459
|
import { performance as performance2 } from "node:perf_hooks";
|
|
1578
|
-
function
|
|
1460
|
+
function isRecord2(value) {
|
|
1579
1461
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1580
1462
|
}
|
|
1581
1463
|
function textFromContent(value) {
|
|
1582
1464
|
if (typeof value === "string") return value;
|
|
1583
|
-
if (!
|
|
1465
|
+
if (!isRecord2(value)) return "";
|
|
1584
1466
|
if (value.type === "text" && typeof value.text === "string") return value.text;
|
|
1585
|
-
if (
|
|
1467
|
+
if (isRecord2(value.content)) return textFromContent(value.content);
|
|
1586
1468
|
return "";
|
|
1587
1469
|
}
|
|
1588
1470
|
function toolContentText(value) {
|
|
1589
1471
|
if (typeof value === "string") return value;
|
|
1590
1472
|
if (Array.isArray(value)) return value.map(toolContentText).filter(Boolean).join("\n");
|
|
1591
|
-
if (!
|
|
1473
|
+
if (!isRecord2(value)) return "";
|
|
1592
1474
|
const direct = textFromContent(value);
|
|
1593
1475
|
if (direct.length > 0) return direct;
|
|
1594
1476
|
return "";
|
|
@@ -1611,8 +1493,8 @@ var AcpEventMapper = class {
|
|
|
1611
1493
|
/** Tool-call id to its `performance.now()` start mark; spans only, never an instant. */
|
|
1612
1494
|
toolStarts = /* @__PURE__ */ new Map();
|
|
1613
1495
|
mapUpdate(params) {
|
|
1614
|
-
const record =
|
|
1615
|
-
const update =
|
|
1496
|
+
const record = isRecord2(params) ? params : {};
|
|
1497
|
+
const update = isRecord2(record.update) ? record.update : {};
|
|
1616
1498
|
const kind = typeof update.sessionUpdate === "string" ? update.sessionUpdate : "";
|
|
1617
1499
|
if (kind === "agent_message_chunk" || kind === "user_message_chunk") {
|
|
1618
1500
|
const text = textFromContent(update.content);
|
|
@@ -1779,7 +1661,7 @@ var MOVE_DESTINATION_PATH_KEYS = [
|
|
|
1779
1661
|
"new_path",
|
|
1780
1662
|
"target"
|
|
1781
1663
|
];
|
|
1782
|
-
function
|
|
1664
|
+
function isRecord3(value) {
|
|
1783
1665
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1784
1666
|
}
|
|
1785
1667
|
function stringField(record, ...keys) {
|
|
@@ -1913,7 +1795,7 @@ function extractLocationPaths(locations, cwd) {
|
|
|
1913
1795
|
const paths = [];
|
|
1914
1796
|
const errors = [];
|
|
1915
1797
|
for (const value of locations) {
|
|
1916
|
-
if (!
|
|
1798
|
+
if (!isRecord3(value)) {
|
|
1917
1799
|
errors.push("locations contains a non-object entry");
|
|
1918
1800
|
continue;
|
|
1919
1801
|
}
|
|
@@ -1928,11 +1810,11 @@ function extractLocationPaths(locations, cwd) {
|
|
|
1928
1810
|
return { paths, provided: true, errors };
|
|
1929
1811
|
}
|
|
1930
1812
|
function mutationTargets(toolCall, kind, cwd) {
|
|
1931
|
-
const rawInput =
|
|
1813
|
+
const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
|
|
1932
1814
|
const raw = extractRawMutationPaths(rawInput, kind, cwd);
|
|
1933
1815
|
const locations = extractLocationPaths(toolCall?.locations, cwd);
|
|
1934
1816
|
const errors = [...raw.errors, ...locations.errors];
|
|
1935
|
-
if (toolCall?.rawInput !== void 0 && !
|
|
1817
|
+
if (toolCall?.rawInput !== void 0 && !isRecord3(toolCall.rawInput)) {
|
|
1936
1818
|
errors.push("rawInput must be an object");
|
|
1937
1819
|
}
|
|
1938
1820
|
if (raw.provided && locations.provided && !samePathSet(raw.paths, locations.paths)) {
|
|
@@ -2002,11 +1884,11 @@ function mapMutationToolCall(toolCall, kind, displayTool, cwd, metadataError) {
|
|
|
2002
1884
|
};
|
|
2003
1885
|
}
|
|
2004
1886
|
function mapPathBearingToolCall(toolCall, tool, displayTool, cwd, targetRequired) {
|
|
2005
|
-
const rawInput =
|
|
1887
|
+
const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
|
|
2006
1888
|
const raw = extractPathFields(rawInput, SINGLE_MUTATION_PATH_KEYS, MULTI_MUTATION_PATH_KEYS, cwd, "rawInput");
|
|
2007
1889
|
const locations = extractLocationPaths(toolCall?.locations, cwd);
|
|
2008
1890
|
const errors = [...raw.errors, ...locations.errors];
|
|
2009
|
-
if (toolCall?.rawInput !== void 0 && !
|
|
1891
|
+
if (toolCall?.rawInput !== void 0 && !isRecord3(toolCall.rawInput)) errors.push("rawInput must be an object");
|
|
2010
1892
|
if (raw.provided && locations.provided && !samePathSet(raw.paths, locations.paths)) {
|
|
2011
1893
|
errors.push("rawInput and locations contain conflicting path targets");
|
|
2012
1894
|
}
|
|
@@ -2027,7 +1909,7 @@ function mapPathBearingToolCall(toolCall, tool, displayTool, cwd, targetRequired
|
|
|
2027
1909
|
}
|
|
2028
1910
|
function mapToolCall(toolCall, cwd) {
|
|
2029
1911
|
const kind = typeof toolCall?.kind === "string" ? toolCall.kind.toLowerCase() : "";
|
|
2030
|
-
const rawInput =
|
|
1912
|
+
const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
|
|
2031
1913
|
const rawTool = stringField(rawInput, "tool", "toolName", "tool_name", "name");
|
|
2032
1914
|
const title = typeof toolCall?.title === "string" ? toolCall.title : void 0;
|
|
2033
1915
|
const displayTool = rawTool ?? kind ?? title ?? "unknown";
|
|
@@ -2131,9 +2013,9 @@ var AcpToolMediator = class {
|
|
|
2131
2013
|
async handle(params) {
|
|
2132
2014
|
const startedAt = performance3.now();
|
|
2133
2015
|
this.requested += 1;
|
|
2134
|
-
const parsed =
|
|
2016
|
+
const parsed = isRecord3(params) ? params : {};
|
|
2135
2017
|
const options = Array.isArray(parsed.options) ? parsed.options : [];
|
|
2136
|
-
const toolCall =
|
|
2018
|
+
const toolCall = isRecord3(parsed.toolCall) ? parsed.toolCall : void 0;
|
|
2137
2019
|
const mapped = mapToolCall(toolCall, this.input.cwd);
|
|
2138
2020
|
let decision = "denied";
|
|
2139
2021
|
let reason;
|
|
@@ -2236,6 +2118,7 @@ var AcpToolMediator = class {
|
|
|
2236
2118
|
init_esm_shims();
|
|
2237
2119
|
var ACP_USAGE_META_KEY = "clio-coder/usage";
|
|
2238
2120
|
var ACP_SESSION_META_KEY = "clio-coder/session";
|
|
2121
|
+
var ACP_AGENT_META_KEY = "clio-coder/agent";
|
|
2239
2122
|
var ACP_MAX_STRING_BYTES = 4096;
|
|
2240
2123
|
var ACP_MAX_RAW_RECORD_BYTES = 32768;
|
|
2241
2124
|
var ACP_MAX_CHUNK_BYTES = 16384;
|
|
@@ -2254,7 +2137,7 @@ var AsyncEventQueue = class {
|
|
|
2254
2137
|
const value = this.values.shift();
|
|
2255
2138
|
if (value !== void 0) return Promise.resolve({ done: false, value });
|
|
2256
2139
|
if (this.done) return Promise.resolve({ done: true, value: void 0 });
|
|
2257
|
-
return new Promise((
|
|
2140
|
+
return new Promise((resolve4) => this.waiters.push(resolve4));
|
|
2258
2141
|
}
|
|
2259
2142
|
push(value) {
|
|
2260
2143
|
if (this.done) return;
|
|
@@ -2274,22 +2157,22 @@ var AsyncEventQueue = class {
|
|
|
2274
2157
|
}
|
|
2275
2158
|
}
|
|
2276
2159
|
};
|
|
2277
|
-
function
|
|
2160
|
+
function isRecord4(value) {
|
|
2278
2161
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2279
2162
|
}
|
|
2280
2163
|
function sessionIdFrom(value) {
|
|
2281
2164
|
if (typeof value === "string" && value.length > 0) return value;
|
|
2282
|
-
if (!
|
|
2165
|
+
if (!isRecord4(value)) return null;
|
|
2283
2166
|
const sessionId = value.sessionId ?? value.id;
|
|
2284
2167
|
return typeof sessionId === "string" && sessionId.length > 0 ? sessionId : null;
|
|
2285
2168
|
}
|
|
2286
2169
|
function supportsSessionClose(init) {
|
|
2287
2170
|
const caps = init?.agentCapabilities;
|
|
2288
|
-
if (!
|
|
2289
|
-
const meta =
|
|
2290
|
-
if (
|
|
2171
|
+
if (!isRecord4(caps)) return false;
|
|
2172
|
+
const meta = isRecord4(caps._meta) ? caps._meta[ACP_SESSION_META_KEY] : void 0;
|
|
2173
|
+
if (isRecord4(meta) && meta.close === true) return true;
|
|
2291
2174
|
const sessionCaps = caps.sessionCapabilities;
|
|
2292
|
-
return
|
|
2175
|
+
return isRecord4(sessionCaps) && isRecord4(sessionCaps.close);
|
|
2293
2176
|
}
|
|
2294
2177
|
function flattenPrompt(input) {
|
|
2295
2178
|
const parts = [
|
|
@@ -2313,7 +2196,7 @@ function finite(value) {
|
|
|
2313
2196
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
2314
2197
|
}
|
|
2315
2198
|
function mergeUsage(into, raw) {
|
|
2316
|
-
if (!
|
|
2199
|
+
if (!isRecord4(raw)) return;
|
|
2317
2200
|
into.inputTokens += finite(raw.input) + finite(raw.inputTokens) + finite(raw.input_tokens);
|
|
2318
2201
|
into.outputTokens += finite(raw.output) + finite(raw.outputTokens) + finite(raw.output_tokens);
|
|
2319
2202
|
into.cacheReadTokens += finite(raw.cacheRead) + finite(raw.cacheReadTokens) + finite(raw.cache_read_tokens);
|
|
@@ -2459,7 +2342,7 @@ function startAcpDelegationRun(input) {
|
|
|
2459
2342
|
},
|
|
2460
2343
|
turnTimeoutMs
|
|
2461
2344
|
);
|
|
2462
|
-
const metaUsage =
|
|
2345
|
+
const metaUsage = isRecord4(promptResponse?._meta) ? promptResponse._meta[ACP_USAGE_META_KEY] : void 0;
|
|
2463
2346
|
if (metaUsage !== void 0) {
|
|
2464
2347
|
mergeUsage(usage, metaUsage);
|
|
2465
2348
|
} else {
|
|
@@ -2977,8 +2860,8 @@ function createAssignmentEventStream(options = {}) {
|
|
|
2977
2860
|
return Promise.resolve({ value: pending.shift(), done: false });
|
|
2978
2861
|
}
|
|
2979
2862
|
if (finished || abandoned) return Promise.resolve({ value: void 0, done: true });
|
|
2980
|
-
return new Promise((
|
|
2981
|
-
waiters.push(
|
|
2863
|
+
return new Promise((resolve4) => {
|
|
2864
|
+
waiters.push(resolve4);
|
|
2982
2865
|
});
|
|
2983
2866
|
},
|
|
2984
2867
|
return() {
|
|
@@ -3082,10 +2965,10 @@ var AssignmentRegistry = class {
|
|
|
3082
2965
|
const id = asAssignmentId(rootRunId);
|
|
3083
2966
|
const existing = this.#assignments.get(id);
|
|
3084
2967
|
if (existing) return this.#snapshot(existing);
|
|
3085
|
-
let
|
|
2968
|
+
let resolve4;
|
|
3086
2969
|
let reject;
|
|
3087
2970
|
const terminal = new Promise((resolvePromise, rejectPromise) => {
|
|
3088
|
-
|
|
2971
|
+
resolve4 = resolvePromise;
|
|
3089
2972
|
reject = rejectPromise;
|
|
3090
2973
|
});
|
|
3091
2974
|
const assignment = {
|
|
@@ -3100,7 +2983,7 @@ var AssignmentRegistry = class {
|
|
|
3100
2983
|
outcomeDetail: null,
|
|
3101
2984
|
terminal,
|
|
3102
2985
|
stream: createAssignmentEventStream(this.#onStreamError !== void 0 ? { onError: this.#onStreamError } : {}),
|
|
3103
|
-
resolve:
|
|
2986
|
+
resolve: resolve4,
|
|
3104
2987
|
reject
|
|
3105
2988
|
};
|
|
3106
2989
|
this.#assignments.set(id, assignment);
|
|
@@ -3340,10 +3223,10 @@ function createAdmissionQueue(options) {
|
|
|
3340
3223
|
const effectiveDeadline = Math.min(request.deadlineAt, request.queuedAt + options.finiteCeilingMs);
|
|
3341
3224
|
if (!Number.isFinite(effectiveDeadline))
|
|
3342
3225
|
return Promise.reject(new Error("dispatch: queued request requires a finite deadline"));
|
|
3343
|
-
return new Promise((
|
|
3226
|
+
return new Promise((resolve4, reject) => {
|
|
3344
3227
|
const bounded = { ...request, deadlineAt: effectiveDeadline };
|
|
3345
3228
|
const timer = setTimeout(() => remove(request.requestId, "timed_out"), Math.max(0, effectiveDeadline - now()));
|
|
3346
|
-
entries.set(request.requestId, { request: bounded, resolve:
|
|
3229
|
+
entries.set(request.requestId, { request: bounded, resolve: resolve4, reject, timer });
|
|
3347
3230
|
});
|
|
3348
3231
|
},
|
|
3349
3232
|
cancel(requestId) {
|
|
@@ -3407,7 +3290,8 @@ import { randomBytes as randomBytes2 } from "node:crypto";
|
|
|
3407
3290
|
var MAX_RESERVATION_RECORDS = 500;
|
|
3408
3291
|
var DEFAULT_RESERVATION_TTL_MS = 15 * 6e4;
|
|
3409
3292
|
function endpointCapacityDenial(input) {
|
|
3410
|
-
|
|
3293
|
+
const remedy = endpointCapacityRemedy(input.topology === "council" ? { rosterFloor: COUNCIL_MIN_MEMBERS } : void 0);
|
|
3294
|
+
return `dispatch: admission denied: endpoint '${endpointLabel(input.endpointKey)}' capacity exceeded (${input.used + input.requested}/${input.limit} slots): ${describeEndpointCapacityHolders(input)}; ${remedy}`;
|
|
3411
3295
|
}
|
|
3412
3296
|
function copyRecord(record) {
|
|
3413
3297
|
return { ...record, members: record.members.map((member) => ({ ...member })) };
|
|
@@ -3415,7 +3299,7 @@ function copyRecord(record) {
|
|
|
3415
3299
|
function validRecord(value) {
|
|
3416
3300
|
if (typeof value !== "object" || value === null) return false;
|
|
3417
3301
|
const record = value;
|
|
3418
|
-
return typeof record.ownerId === "string" && typeof record.ownerPid === "number" && Number.isInteger(record.ownerPid) && record.ownerPid > 0 && (record.topology === "parallel" || record.topology === "detached" || record.topology === "sequential" || record.topology === "pipeline" || record.topology === "review" || record.topology === "compete") && (record.status === "active" || record.status === "released" || record.status === "rolled_back" || record.status === "expired") && typeof record.createdAt === "string" && typeof record.expiresAt === "string" && (record.settledAt === null || typeof record.settledAt === "string") && Array.isArray(record.members) && record.members.every(
|
|
3302
|
+
return typeof record.ownerId === "string" && typeof record.ownerPid === "number" && Number.isInteger(record.ownerPid) && record.ownerPid > 0 && (record.topology === "parallel" || record.topology === "detached" || record.topology === "sequential" || record.topology === "pipeline" || record.topology === "review" || record.topology === "compete" || record.topology === "council") && (record.status === "active" || record.status === "released" || record.status === "rolled_back" || record.status === "expired") && typeof record.createdAt === "string" && typeof record.expiresAt === "string" && (record.settledAt === null || typeof record.settledAt === "string") && Array.isArray(record.members) && record.members.every(
|
|
3419
3303
|
(member) => typeof member.memberId === "string" && Number.isInteger(member.wave) && typeof member.nodeId === "string" && (member.endpointKey === void 0 || typeof member.endpointKey === "string") && typeof member.costUpperBoundUsd === "number" && Number.isFinite(member.costUpperBoundUsd) && member.costUpperBoundUsd >= 0 && (member.status === "held" || member.status === "consumed" || member.status === "released") && (member.consumedAt === null || typeof member.consumedAt === "string") && (member.releasedAt === null || typeof member.releasedAt === "string")
|
|
3420
3304
|
);
|
|
3421
3305
|
}
|
|
@@ -3469,7 +3353,7 @@ function outstandingTasks(record) {
|
|
|
3469
3353
|
function outstandingBudget(record) {
|
|
3470
3354
|
return record.members.filter((member) => member.status === "held" || member.status === "consumed").reduce((sum, member) => sum + member.costUpperBoundUsd, 0);
|
|
3471
3355
|
}
|
|
3472
|
-
function allocateReservation(tasks, existing, capacity) {
|
|
3356
|
+
function allocateReservation(tasks, existing, capacity, topology) {
|
|
3473
3357
|
if (tasks.length === 0) return { ok: false, reason: "reservation requires at least one task" };
|
|
3474
3358
|
const duplicate = tasks.find((task, index) => tasks.slice(0, index).some((entry) => entry.memberId === task.memberId));
|
|
3475
3359
|
if (duplicate) return { ok: false, reason: `duplicate reservation member '${duplicate.memberId}'` };
|
|
@@ -3507,7 +3391,8 @@ function allocateReservation(tasks, existing, capacity) {
|
|
|
3507
3391
|
requested: slots,
|
|
3508
3392
|
leases: endpoint.leases ?? endpoint.active - (endpoint.foregroundStreams ?? 0),
|
|
3509
3393
|
reservations: heldSlots,
|
|
3510
|
-
foregroundStreams: endpoint.foregroundStreams ?? 0
|
|
3394
|
+
foregroundStreams: endpoint.foregroundStreams ?? 0,
|
|
3395
|
+
...topology === void 0 ? {} : { topology }
|
|
3511
3396
|
})
|
|
3512
3397
|
};
|
|
3513
3398
|
}
|
|
@@ -3535,7 +3420,7 @@ function createDispatchReservation(input) {
|
|
|
3535
3420
|
`dispatch: reservation denied: capacity is draining (requested by pid ${drain.requestedByPid} at ${drain.requestedAt})`
|
|
3536
3421
|
);
|
|
3537
3422
|
}
|
|
3538
|
-
const planned = allocateReservation(input.tasks, records, input.capacity);
|
|
3423
|
+
const planned = allocateReservation(input.tasks, records, input.capacity, input.topology);
|
|
3539
3424
|
if (!planned.ok) {
|
|
3540
3425
|
replaceReservations(state, records);
|
|
3541
3426
|
writeCapacityStateUnsafe(state);
|
|
@@ -3802,7 +3687,12 @@ function describeAdmissionFailure(input) {
|
|
|
3802
3687
|
if (endpointLimit !== void 0 && endpointActive >= endpointLimit) {
|
|
3803
3688
|
const holders = input.usage.endpointHolders?.[input.endpointKey];
|
|
3804
3689
|
const occupancy = holders === void 0 ? "the supplied capacity snapshot does not attribute the occupied slots" : describeEndpointCapacityHolders(holders);
|
|
3805
|
-
|
|
3690
|
+
const queued2 = input.queueDepth > 0 ? `, ${input.queueDepth} more queued` : "";
|
|
3691
|
+
return [
|
|
3692
|
+
`dispatch: admission timed out after ${Math.round(input.waitedMs)}ms waiting for an endpoint slot`,
|
|
3693
|
+
` on '${endpointLabel(input.endpointKey)}' (${endpointActive}/${endpointLimit} slots${queued2}): ${occupancy}.`,
|
|
3694
|
+
" Wait for the running request to settle or dispatch this work again."
|
|
3695
|
+
].join("");
|
|
3806
3696
|
}
|
|
3807
3697
|
}
|
|
3808
3698
|
const nodeLimit = input.limits.nodes[input.nodeId];
|
|
@@ -3846,10 +3736,6 @@ function createCapacityAdmissionController(options) {
|
|
|
3846
3736
|
admittedLease = request.value();
|
|
3847
3737
|
return true;
|
|
3848
3738
|
} catch (error) {
|
|
3849
|
-
if (error instanceof Error && /endpoint '.*' capacity reached/u.test(error.message)) {
|
|
3850
|
-
queue.fail(request.requestId, error);
|
|
3851
|
-
return false;
|
|
3852
|
-
}
|
|
3853
3739
|
if (error instanceof Error && /capacity reached/.test(error.message)) return false;
|
|
3854
3740
|
queue.fail(request.requestId, error instanceof Error ? error : new Error(String(error)));
|
|
3855
3741
|
return false;
|
|
@@ -3914,18 +3800,18 @@ function createCapacityAdmissionController(options) {
|
|
|
3914
3800
|
pumpNow();
|
|
3915
3801
|
const outcome = await outcomePromise;
|
|
3916
3802
|
if (outcome.state !== "admitted") {
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
);
|
|
3803
|
+
const detail = describeAdmissionFailure({
|
|
3804
|
+
state: outcome.state,
|
|
3805
|
+
nodeId: input.nodeId,
|
|
3806
|
+
...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
|
|
3807
|
+
waitedMs: now() - queuedAt,
|
|
3808
|
+
overdueAtQueueMs: queuedAt - input.deadlineAt,
|
|
3809
|
+
queueDepth: queue.size(),
|
|
3810
|
+
limits: options.limits(),
|
|
3811
|
+
usage: options.usage?.() ?? capacityLeaseUsage({ nowMs: now() })
|
|
3812
|
+
});
|
|
3813
|
+
if (outcome.state === "canceled") throw new AdmissionCanceledError(detail);
|
|
3814
|
+
throw new Error(detail);
|
|
3929
3815
|
}
|
|
3930
3816
|
const lease = acquired.get(input.assignmentId);
|
|
3931
3817
|
if (!lease) throw new Error("dispatch: admitted request has no capacity lease");
|
|
@@ -5737,697 +5623,46 @@ function collectReproducibilityMetadata(cwd, safety) {
|
|
|
5737
5623
|
commit,
|
|
5738
5624
|
dirty: dirtyEntries === null ? null : dirtyEntries > 0,
|
|
5739
5625
|
dirtyEntries,
|
|
5740
|
-
statusHash: status === null ? null : sha2564(status)
|
|
5741
|
-
},
|
|
5742
|
-
safetyPolicy: {
|
|
5743
|
-
version: safety?.version ?? 1,
|
|
5744
|
-
rulePackHash: safety?.rulePackHash ?? null,
|
|
5745
|
-
rulePackVersion: safety?.rulePackVersion ?? null,
|
|
5746
|
-
projectPolicyPath: safety?.projectPolicyPath ?? null,
|
|
5747
|
-
projectPolicyHash: safety?.projectPolicyHash ?? null,
|
|
5748
|
-
projectPolicyValid: safety?.projectPolicyValid ?? null
|
|
5749
|
-
}
|
|
5750
|
-
};
|
|
5751
|
-
}
|
|
5752
|
-
function git(cwd, args) {
|
|
5753
|
-
const result = spawnSync("git", [...args], {
|
|
5754
|
-
cwd,
|
|
5755
|
-
encoding: "utf8",
|
|
5756
|
-
timeout: 1e3,
|
|
5757
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
5758
|
-
});
|
|
5759
|
-
if (result.status !== 0 || typeof result.stdout !== "string") return null;
|
|
5760
|
-
const trimmed = result.stdout.trim();
|
|
5761
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
5762
|
-
}
|
|
5763
|
-
function sha2564(input) {
|
|
5764
|
-
return createHash5("sha256").update(input, "utf8").digest("hex");
|
|
5765
|
-
}
|
|
5766
|
-
|
|
5767
|
-
// src/domains/dispatch/route-observer.ts
|
|
5768
|
-
init_esm_shims();
|
|
5769
|
-
import { appendFileSync, existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync3, readFileSync as readFileSync10, renameSync as renameSync4, statSync } from "node:fs";
|
|
5770
|
-
import { join as join12 } from "node:path";
|
|
5771
|
-
|
|
5772
|
-
// src/domains/dispatch/gate-decisions.ts
|
|
5773
|
-
init_esm_shims();
|
|
5774
|
-
import { createHash as createHash6, randomBytes as randomBytes4 } from "node:crypto";
|
|
5775
|
-
import { closeSync, existsSync as existsSync8, fsyncSync, mkdirSync as mkdirSync4, openSync, readdirSync as readdirSync2, readFileSync as readFileSync8, rmSync } from "node:fs";
|
|
5776
|
-
import { dirname as dirname3, join as join10, resolve as resolve4 } from "node:path";
|
|
5777
|
-
function parseReviewGateResult(output) {
|
|
5778
|
-
const result = parseVerifierResult(output);
|
|
5779
|
-
return result === null ? { ok: false, reason: "reviewer did not return a valid verifier report" } : { ok: true, result };
|
|
5780
|
-
}
|
|
5781
|
-
function decideReviewGate(input) {
|
|
5782
|
-
const base = {
|
|
5783
|
-
group: input.group,
|
|
5784
|
-
topology: "review",
|
|
5785
|
-
cycle: input.cycle,
|
|
5786
|
-
subjects: input.subjects,
|
|
5787
|
-
decider: input.decider,
|
|
5788
|
-
correlation: input.correlation
|
|
5789
|
-
};
|
|
5790
|
-
const parsed = parseReviewGateResult(input.output);
|
|
5791
|
-
if (!parsed.ok) {
|
|
5792
|
-
return {
|
|
5793
|
-
draft: { ...base, outcome: "exhausted", detail: parsed.reason },
|
|
5794
|
-
verdict: null,
|
|
5795
|
-
findings: null,
|
|
5796
|
-
needsDecision: `review gate produced no structured verdict in cycle ${input.cycle}: ${parsed.reason}`
|
|
5797
|
-
};
|
|
5798
|
-
}
|
|
5799
|
-
if (parsed.result.verdict === "pass" || input.terminalCycle) {
|
|
5800
|
-
return {
|
|
5801
|
-
draft: { ...base, outcome: parsed.result.verdict },
|
|
5802
|
-
verdict: parsed.result.verdict,
|
|
5803
|
-
findings: null,
|
|
5804
|
-
needsDecision: null
|
|
5805
|
-
};
|
|
5806
|
-
}
|
|
5807
|
-
const failed = parsed.result.checks.filter((check) => !check.passed);
|
|
5808
|
-
return {
|
|
5809
|
-
draft: { ...base, outcome: "revise", detail: `reviewer reported ${failed.length} failed check(s)` },
|
|
5810
|
-
verdict: null,
|
|
5811
|
-
findings: JSON.stringify({ verdict: "fail", checks: failed }),
|
|
5812
|
-
needsDecision: null
|
|
5813
|
-
};
|
|
5814
|
-
}
|
|
5815
|
-
function parseGateChecks(value) {
|
|
5816
|
-
if (!Array.isArray(value) || value.length === 0) return null;
|
|
5817
|
-
const checks = [];
|
|
5818
|
-
for (const entry of value) {
|
|
5819
|
-
if (!isRecord6(entry)) return null;
|
|
5820
|
-
const keys = Object.keys(entry);
|
|
5821
|
-
if (keys.some((key) => key !== "name" && key !== "passed" && key !== "evidence") || typeof entry.name !== "string" || entry.name.trim().length === 0 || typeof entry.passed !== "boolean" || typeof entry.evidence !== "string" || entry.evidence.trim().length === 0) {
|
|
5822
|
-
return null;
|
|
5823
|
-
}
|
|
5824
|
-
checks.push({ name: entry.name, passed: entry.passed, evidence: entry.evidence });
|
|
5825
|
-
}
|
|
5826
|
-
return checks;
|
|
5827
|
-
}
|
|
5828
|
-
function parseCompeteGateResult(output, candidateCount) {
|
|
5829
|
-
const parsed = parseJsonObjectPayload(output);
|
|
5830
|
-
if (!parsed.ok) {
|
|
5831
|
-
return {
|
|
5832
|
-
ok: false,
|
|
5833
|
-
reason: parsed.reason === "not-object" ? "judge result must be a JSON object" : "judge result must be valid JSON"
|
|
5834
|
-
};
|
|
5835
|
-
}
|
|
5836
|
-
const value = parsed.value;
|
|
5837
|
-
if (Object.keys(value).some((key) => key !== "winner" && key !== "checks")) {
|
|
5838
|
-
return { ok: false, reason: "judge result has unknown fields" };
|
|
5839
|
-
}
|
|
5840
|
-
const winner = value.winner;
|
|
5841
|
-
if (typeof winner !== "number" || !Number.isSafeInteger(winner) || winner < 1 || winner > candidateCount) {
|
|
5842
|
-
return { ok: false, reason: `judge winner must be an integer 1..${candidateCount}` };
|
|
5843
|
-
}
|
|
5844
|
-
const checks = parseGateChecks(value.checks);
|
|
5845
|
-
if (checks === null) return { ok: false, reason: "judge result must carry typed checks with evidence" };
|
|
5846
|
-
return { ok: true, result: { winner, checks } };
|
|
5847
|
-
}
|
|
5848
|
-
function decisionsDirectory(stateDir = clioStateDir()) {
|
|
5849
|
-
return join10(stateDir, "gate-decisions");
|
|
5850
|
-
}
|
|
5851
|
-
function pendingDecisionsDirectory(stateDir = clioStateDir()) {
|
|
5852
|
-
return join10(decisionsDirectory(stateDir), "pending");
|
|
5853
|
-
}
|
|
5854
|
-
function isRecord6(value) {
|
|
5855
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5856
|
-
}
|
|
5857
|
-
function isSubjectRef(value) {
|
|
5858
|
-
if (!isRecord6(value) || typeof value.runId !== "string" || value.runId.trim().length === 0) return false;
|
|
5859
|
-
return typeof value.digest === "string" && /^[0-9a-f]{64}$/.test(value.digest);
|
|
5860
|
-
}
|
|
5861
|
-
function isSafeDecisionId(value) {
|
|
5862
|
-
return typeof value === "string" && value.length > 0 && value.length <= 256 && /^[A-Za-z0-9._-]+$/.test(value);
|
|
5863
|
-
}
|
|
5864
|
-
function isCorrelation(value) {
|
|
5865
|
-
if (!isRecord6(value)) return false;
|
|
5866
|
-
const fields = ["agent", "target", "modelFamily", "runtime", "node", "independent"];
|
|
5867
|
-
if (Object.keys(value).some((key) => !fields.includes(key))) return false;
|
|
5868
|
-
if (!fields.every((field) => typeof value[field] === "boolean")) return false;
|
|
5869
|
-
return value.independent === (!value.agent && !value.modelFamily);
|
|
5870
|
-
}
|
|
5871
|
-
function semanticError(value) {
|
|
5872
|
-
if (!isRecord6(value)) return "gate decision is not an object";
|
|
5873
|
-
if (value.version !== 2) return "unsupported gate decision version";
|
|
5874
|
-
if (!isSafeDecisionId(value.id)) return "gate decision id invalid";
|
|
5875
|
-
if (typeof value.group !== "string" || value.group.length === 0) return "gate decision group invalid";
|
|
5876
|
-
if (value.topology !== "review" && value.topology !== "compete") return "gate decision topology invalid";
|
|
5877
|
-
if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
|
|
5878
|
-
return "gate decision cycle invalid";
|
|
5879
|
-
}
|
|
5880
|
-
const reviewOutcome = value.outcome === "pass" || value.outcome === "fail" || value.outcome === "revise" || value.outcome === "exhausted";
|
|
5881
|
-
const competeOutcome = value.outcome === "winner" || value.outcome === "no-winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
5882
|
-
if (value.topology === "review" && !reviewOutcome || value.topology === "compete" && !competeOutcome) {
|
|
5883
|
-
return "gate decision outcome is incompatible with topology";
|
|
5884
|
-
}
|
|
5885
|
-
if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
|
|
5886
|
-
return "gate decision subjects invalid";
|
|
5887
|
-
}
|
|
5888
|
-
if (value.decider !== void 0 && !isSubjectRef(value.decider)) return "gate decision decider invalid";
|
|
5889
|
-
if (value.decider === void 0) {
|
|
5890
|
-
if (value.correlation !== void 0) return "gate decision correlation requires a decider";
|
|
5891
|
-
} else if (!isCorrelation(value.correlation)) {
|
|
5892
|
-
return "gate decision correlation invalid";
|
|
5893
|
-
}
|
|
5894
|
-
if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
|
|
5895
|
-
return "gate decision timestamp invalid";
|
|
5896
|
-
}
|
|
5897
|
-
const needsWinner = value.outcome === "winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
5898
|
-
if (needsWinner) {
|
|
5899
|
-
if (!isRecord6(value.winner) || typeof value.winner.index !== "number" || !Number.isInteger(value.winner.index) || value.winner.index < 1 || !isSubjectRef(value.winner.subject) || typeof value.winner.branch !== "string" || value.winner.branch !== `clio/compete/${value.group}/${value.winner.index}`) {
|
|
5900
|
-
return "gate decision winner invalid";
|
|
5901
|
-
}
|
|
5902
|
-
const winnerSubject = value.winner.subject;
|
|
5903
|
-
if (!value.subjects.some((subject) => subject.runId === winnerSubject.runId)) {
|
|
5904
|
-
return "gate decision winner is not a subject";
|
|
5905
|
-
}
|
|
5906
|
-
} else if (value.winner !== void 0) {
|
|
5907
|
-
return "gate decision winner is not valid for this outcome";
|
|
5908
|
-
}
|
|
5909
|
-
const needsConfirmation = value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
5910
|
-
if (needsConfirmation) {
|
|
5911
|
-
if (!isRecord6(value.confirmation) || typeof value.confirmation.id !== "string" || value.confirmation.id.length === 0 || typeof value.confirmation.digest !== "string" || !/^[0-9a-f]{64}$/.test(value.confirmation.digest)) {
|
|
5912
|
-
return "gate decision confirmation invalid";
|
|
5913
|
-
}
|
|
5914
|
-
} else if (value.confirmation !== void 0) {
|
|
5915
|
-
return "gate decision confirmation is not valid for this outcome";
|
|
5916
|
-
}
|
|
5917
|
-
if (value.detail !== void 0 && typeof value.detail !== "string") return "gate decision detail invalid";
|
|
5918
|
-
if (!isRecord6(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string") {
|
|
5919
|
-
return "gate decision integrity invalid";
|
|
5920
|
-
}
|
|
5921
|
-
return null;
|
|
5922
|
-
}
|
|
5923
|
-
function safeGroup(group) {
|
|
5924
|
-
const safe = group.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 128);
|
|
5925
|
-
return safe.length > 0 ? safe : "gate";
|
|
5926
|
-
}
|
|
5927
|
-
function newDecisionId(group) {
|
|
5928
|
-
return `${safeGroup(group)}-${Date.now().toString(36)}-${randomBytes4(6).toString("hex")}`;
|
|
5929
|
-
}
|
|
5930
|
-
function decisionArtifactPath(id, stateDir = clioStateDir()) {
|
|
5931
|
-
return join10(decisionsDirectory(stateDir), `${id}.json`);
|
|
5932
|
-
}
|
|
5933
|
-
function pendingDecisionPath(id, stateDir = clioStateDir()) {
|
|
5934
|
-
return join10(pendingDecisionsDirectory(stateDir), `${id}.json`);
|
|
5935
|
-
}
|
|
5936
|
-
function decisionPayload(decision) {
|
|
5937
|
-
return {
|
|
5938
|
-
contract: "clio.gateDecision.integrity",
|
|
5939
|
-
version: decision.version,
|
|
5940
|
-
id: decision.id,
|
|
5941
|
-
group: decision.group,
|
|
5942
|
-
topology: decision.topology,
|
|
5943
|
-
cycle: decision.cycle,
|
|
5944
|
-
outcome: decision.outcome,
|
|
5945
|
-
subjects: decision.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
|
|
5946
|
-
...decision.decider !== void 0 ? { decider: { runId: decision.decider.runId, digest: decision.decider.digest } } : {},
|
|
5947
|
-
...decision.correlation !== void 0 ? { correlation: { ...decision.correlation } } : {},
|
|
5948
|
-
...decision.winner !== void 0 ? {
|
|
5949
|
-
winner: {
|
|
5950
|
-
index: decision.winner.index,
|
|
5951
|
-
subject: {
|
|
5952
|
-
runId: decision.winner.subject.runId,
|
|
5953
|
-
digest: decision.winner.subject.digest
|
|
5954
|
-
},
|
|
5955
|
-
branch: decision.winner.branch
|
|
5956
|
-
}
|
|
5957
|
-
} : {},
|
|
5958
|
-
...decision.confirmation !== void 0 ? { confirmation: { id: decision.confirmation.id, digest: decision.confirmation.digest } } : {},
|
|
5959
|
-
...decision.detail !== void 0 ? { detail: decision.detail } : {},
|
|
5960
|
-
createdAt: decision.createdAt
|
|
5961
|
-
};
|
|
5962
|
-
}
|
|
5963
|
-
function decisionDigest(decision) {
|
|
5964
|
-
return createHash6("sha256").update(JSON.stringify(decisionPayload(decision)), "utf8").digest("hex");
|
|
5965
|
-
}
|
|
5966
|
-
function artifactWithoutIntegrity(artifact) {
|
|
5967
|
-
const result = {
|
|
5968
|
-
version: artifact.version,
|
|
5969
|
-
id: artifact.id,
|
|
5970
|
-
group: artifact.group,
|
|
5971
|
-
topology: artifact.topology,
|
|
5972
|
-
cycle: artifact.cycle,
|
|
5973
|
-
outcome: artifact.outcome,
|
|
5974
|
-
subjects: artifact.subjects.map((subject) => ({ ...subject })),
|
|
5975
|
-
createdAt: artifact.createdAt
|
|
5976
|
-
};
|
|
5977
|
-
if (artifact.decider !== void 0) result.decider = { ...artifact.decider };
|
|
5978
|
-
if (artifact.correlation !== void 0) result.correlation = { ...artifact.correlation };
|
|
5979
|
-
if (artifact.winner !== void 0) {
|
|
5980
|
-
result.winner = {
|
|
5981
|
-
index: artifact.winner.index,
|
|
5982
|
-
subject: { ...artifact.winner.subject },
|
|
5983
|
-
branch: artifact.winner.branch
|
|
5984
|
-
};
|
|
5985
|
-
}
|
|
5986
|
-
if (artifact.confirmation !== void 0) result.confirmation = { ...artifact.confirmation };
|
|
5987
|
-
if (artifact.detail !== void 0) result.detail = artifact.detail;
|
|
5988
|
-
return result;
|
|
5989
|
-
}
|
|
5990
|
-
function verifyGateDecisionArtifact(artifact) {
|
|
5991
|
-
const invalid = semanticError(artifact);
|
|
5992
|
-
if (invalid !== null) return { ok: false, reason: invalid };
|
|
5993
|
-
if (!/^[0-9a-f]{64}$/.test(artifact.integrity.digest)) return { ok: false, reason: "gate decision integrity invalid" };
|
|
5994
|
-
return decisionDigest(artifactWithoutIntegrity(artifact)) === artifact.integrity.digest ? { ok: true } : { ok: false, reason: "gate decision integrity mismatch" };
|
|
5995
|
-
}
|
|
5996
|
-
function buildGateDecisionArtifact(draft, id = newDecisionId(draft.group), createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()) {
|
|
5997
|
-
if (draft.group.trim().length === 0) throw new Error("gate decision group is required");
|
|
5998
|
-
if (!Number.isInteger(draft.cycle) || draft.cycle < 1)
|
|
5999
|
-
throw new Error("gate decision cycle must be a positive integer");
|
|
6000
|
-
if (draft.subjects.length === 0) throw new Error("gate decision requires at least one subject receipt");
|
|
6001
|
-
const withoutIntegrity = {
|
|
6002
|
-
version: 2,
|
|
6003
|
-
id,
|
|
6004
|
-
group: draft.group,
|
|
6005
|
-
topology: draft.topology,
|
|
6006
|
-
cycle: draft.cycle,
|
|
6007
|
-
outcome: draft.outcome,
|
|
6008
|
-
subjects: draft.subjects.map((subject) => ({ ...subject })),
|
|
6009
|
-
createdAt
|
|
6010
|
-
};
|
|
6011
|
-
if (draft.decider !== void 0) withoutIntegrity.decider = { ...draft.decider };
|
|
6012
|
-
if (draft.correlation !== void 0) withoutIntegrity.correlation = { ...draft.correlation };
|
|
6013
|
-
if (draft.winner !== void 0) {
|
|
6014
|
-
withoutIntegrity.winner = {
|
|
6015
|
-
index: draft.winner.index,
|
|
6016
|
-
subject: { ...draft.winner.subject },
|
|
6017
|
-
branch: draft.winner.branch
|
|
6018
|
-
};
|
|
6019
|
-
}
|
|
6020
|
-
if (draft.confirmation !== void 0) withoutIntegrity.confirmation = { ...draft.confirmation };
|
|
6021
|
-
if (draft.detail !== void 0) withoutIntegrity.detail = draft.detail;
|
|
6022
|
-
const artifact = {
|
|
6023
|
-
...withoutIntegrity,
|
|
6024
|
-
integrity: { algorithm: "sha256", digest: decisionDigest(withoutIntegrity) }
|
|
6025
|
-
};
|
|
6026
|
-
const verification = verifyGateDecisionArtifact(artifact);
|
|
6027
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
6028
|
-
return artifact;
|
|
6029
|
-
}
|
|
6030
|
-
function readVerifiedArtifact(path2) {
|
|
6031
|
-
let value;
|
|
6032
|
-
try {
|
|
6033
|
-
value = JSON.parse(readFileSync8(path2, "utf8"));
|
|
6034
|
-
} catch (error) {
|
|
6035
|
-
throw new Error(
|
|
6036
|
-
`gate decision artifact is unreadable at ${path2}: ${error instanceof Error ? error.message : String(error)}`
|
|
6037
|
-
);
|
|
6038
|
-
}
|
|
6039
|
-
const artifact = value;
|
|
6040
|
-
const verification = verifyGateDecisionArtifact(artifact);
|
|
6041
|
-
if (!verification.ok) throw new Error(`gate decision artifact is invalid at ${path2}: ${verification.reason}`);
|
|
6042
|
-
return artifact;
|
|
6043
|
-
}
|
|
6044
|
-
function persistGateDecisionArtifact(artifact, stateDir, allowIdenticalExisting) {
|
|
6045
|
-
const verification = verifyGateDecisionArtifact(artifact);
|
|
6046
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
6047
|
-
const directory = decisionsDirectory(stateDir);
|
|
6048
|
-
mkdirSync4(directory, { recursive: true });
|
|
6049
|
-
const path2 = decisionArtifactPath(artifact.id, stateDir);
|
|
6050
|
-
if (existsSync8(path2)) {
|
|
6051
|
-
const existing = readVerifiedArtifact(path2);
|
|
6052
|
-
if (allowIdenticalExisting && existing.id === artifact.id && existing.integrity.digest === artifact.integrity.digest) {
|
|
6053
|
-
return { artifact: existing, path: path2 };
|
|
6054
|
-
}
|
|
6055
|
-
throw new Error(`gate decision artifact collision: ${artifact.id}`);
|
|
6056
|
-
}
|
|
6057
|
-
atomicWrite(path2, JSON.stringify(artifact, null, 2));
|
|
6058
|
-
return { artifact, path: path2 };
|
|
6059
|
-
}
|
|
6060
|
-
function cloneGateDecisionArtifact(artifact) {
|
|
6061
|
-
return {
|
|
6062
|
-
...artifactWithoutIntegrity(artifact),
|
|
6063
|
-
integrity: { ...artifact.integrity }
|
|
6064
|
-
};
|
|
6065
|
-
}
|
|
6066
|
-
function pendingRecordPayload(record) {
|
|
6067
|
-
if (record.kind === "output") {
|
|
6068
|
-
return {
|
|
6069
|
-
contract: "clio.gateDecision.pending",
|
|
6070
|
-
version: record.version,
|
|
6071
|
-
kind: record.kind,
|
|
6072
|
-
id: record.id,
|
|
6073
|
-
group: record.group,
|
|
6074
|
-
topology: record.topology,
|
|
6075
|
-
cycle: record.cycle,
|
|
6076
|
-
subjects: record.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
|
|
6077
|
-
deciderRunId: record.deciderRunId,
|
|
6078
|
-
finalOutput: record.finalOutput,
|
|
6079
|
-
...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
|
|
6080
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
6081
|
-
createdAt: record.createdAt
|
|
6082
|
-
};
|
|
6083
|
-
}
|
|
6084
|
-
const decisionWithoutIntegrity = artifactWithoutIntegrity(record.decision);
|
|
6085
|
-
return {
|
|
6086
|
-
contract: "clio.gateDecision.pending",
|
|
6087
|
-
version: record.version,
|
|
6088
|
-
kind: record.kind,
|
|
6089
|
-
id: record.id,
|
|
6090
|
-
decision: {
|
|
6091
|
-
...decisionPayload(decisionWithoutIntegrity),
|
|
6092
|
-
integrity: { ...record.decision.integrity }
|
|
6093
|
-
},
|
|
6094
|
-
...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
|
|
6095
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
6096
|
-
createdAt: record.createdAt
|
|
6097
|
-
};
|
|
6098
|
-
}
|
|
6099
|
-
function pendingRecordDigest(record) {
|
|
6100
|
-
return createHash6("sha256").update(JSON.stringify(pendingRecordPayload(record)), "utf8").digest("hex");
|
|
6101
|
-
}
|
|
6102
|
-
function pendingRecordWithoutIntegrity(record) {
|
|
6103
|
-
if (record.kind === "output") {
|
|
6104
|
-
return {
|
|
6105
|
-
version: record.version,
|
|
6106
|
-
kind: record.kind,
|
|
6107
|
-
id: record.id,
|
|
6108
|
-
group: record.group,
|
|
6109
|
-
topology: record.topology,
|
|
6110
|
-
cycle: record.cycle,
|
|
6111
|
-
subjects: record.subjects.map((subject) => ({ ...subject })),
|
|
6112
|
-
deciderRunId: record.deciderRunId,
|
|
6113
|
-
finalOutput: record.finalOutput,
|
|
6114
|
-
...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
|
|
6115
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
6116
|
-
createdAt: record.createdAt
|
|
6117
|
-
};
|
|
6118
|
-
}
|
|
6119
|
-
return {
|
|
6120
|
-
version: record.version,
|
|
6121
|
-
kind: record.kind,
|
|
6122
|
-
id: record.id,
|
|
6123
|
-
decision: cloneGateDecisionArtifact(record.decision),
|
|
6124
|
-
...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
|
|
6125
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
6126
|
-
createdAt: record.createdAt
|
|
6127
|
-
};
|
|
6128
|
-
}
|
|
6129
|
-
function pendingSemanticError(value) {
|
|
6130
|
-
if (!isRecord6(value)) return "pending gate decision is not an object";
|
|
6131
|
-
if (value.version !== 1) return "unsupported pending gate decision version";
|
|
6132
|
-
if (!isSafeDecisionId(value.id)) return "pending gate decision id invalid";
|
|
6133
|
-
if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
|
|
6134
|
-
return "pending gate decision timestamp invalid";
|
|
6135
|
-
}
|
|
6136
|
-
if (!isRecord6(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string" || !/^[0-9a-f]{64}$/.test(value.integrity.digest)) {
|
|
6137
|
-
return "pending gate decision integrity invalid";
|
|
6138
|
-
}
|
|
6139
|
-
if (value.kind === "output") {
|
|
6140
|
-
if (typeof value.group !== "string" || value.group.trim().length === 0) {
|
|
6141
|
-
return "pending gate output group invalid";
|
|
6142
|
-
}
|
|
6143
|
-
if (value.topology !== "review" && value.topology !== "compete") {
|
|
6144
|
-
return "pending gate output topology invalid";
|
|
6145
|
-
}
|
|
6146
|
-
if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
|
|
6147
|
-
return "pending gate output cycle invalid";
|
|
6148
|
-
}
|
|
6149
|
-
if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
|
|
6150
|
-
return "pending gate output subjects invalid";
|
|
6151
|
-
}
|
|
6152
|
-
if (typeof value.deciderRunId !== "string" || value.deciderRunId.trim().length === 0) {
|
|
6153
|
-
return "pending gate output decider run id invalid";
|
|
6154
|
-
}
|
|
6155
|
-
if (typeof value.finalOutput !== "string") return "pending gate output text invalid";
|
|
6156
|
-
if (value.terminalCycle !== void 0 && typeof value.terminalCycle !== "boolean") {
|
|
6157
|
-
return "pending gate output terminal-cycle marker invalid";
|
|
6158
|
-
}
|
|
6159
|
-
if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
|
|
6160
|
-
return "pending gate output resource root invalid";
|
|
6161
|
-
}
|
|
6162
|
-
return null;
|
|
6163
|
-
}
|
|
6164
|
-
if (value.kind !== "decision") return "pending gate decision kind invalid";
|
|
6165
|
-
if (!isRecord6(value.decision)) return "pending gate decision artifact invalid";
|
|
6166
|
-
const verification = verifyGateDecisionArtifact(value.decision);
|
|
6167
|
-
if (!verification.ok) return `pending gate decision artifact invalid: ${verification.reason}`;
|
|
6168
|
-
if (value.decision.id !== value.id) return "pending gate decision artifact id mismatch";
|
|
6169
|
-
if (value.decision.createdAt !== value.createdAt) return "pending gate decision artifact timestamp mismatch";
|
|
6170
|
-
if (value.finalOutput !== void 0 && typeof value.finalOutput !== "string") {
|
|
6171
|
-
return "pending gate decision output invalid";
|
|
6172
|
-
}
|
|
6173
|
-
if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
|
|
6174
|
-
return "pending gate decision resource root invalid";
|
|
6175
|
-
}
|
|
6176
|
-
return null;
|
|
6177
|
-
}
|
|
6178
|
-
function verifyPendingGateDecisionRecord(record) {
|
|
6179
|
-
const invalid = pendingSemanticError(record);
|
|
6180
|
-
if (invalid !== null) return { ok: false, reason: invalid };
|
|
6181
|
-
return pendingRecordDigest(pendingRecordWithoutIntegrity(record)) === record.integrity.digest ? { ok: true } : { ok: false, reason: "pending gate decision integrity mismatch" };
|
|
6182
|
-
}
|
|
6183
|
-
function clonePendingGateDecisionRecord(record) {
|
|
6184
|
-
const without = pendingRecordWithoutIntegrity(record);
|
|
6185
|
-
return {
|
|
6186
|
-
...without,
|
|
6187
|
-
integrity: { ...record.integrity }
|
|
6188
|
-
};
|
|
6189
|
-
}
|
|
6190
|
-
function parsePendingGateDecisionRecord(value) {
|
|
6191
|
-
const invalid = pendingSemanticError(value);
|
|
6192
|
-
if (invalid !== null) throw new Error(invalid);
|
|
6193
|
-
const record = clonePendingGateDecisionRecord(value);
|
|
6194
|
-
const verification = verifyPendingGateDecisionRecord(record);
|
|
6195
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
6196
|
-
return record;
|
|
6197
|
-
}
|
|
6198
|
-
function assertPendingHandlePath(handle) {
|
|
6199
|
-
const expected = pendingDecisionPath(handle.record.id, handle.stateDir);
|
|
6200
|
-
if (resolve4(handle.path) !== resolve4(expected)) {
|
|
6201
|
-
throw new Error(`pending gate decision path does not match id ${handle.record.id}`);
|
|
6202
|
-
}
|
|
6203
|
-
}
|
|
6204
|
-
function pendingHandle(record, stateDir) {
|
|
6205
|
-
return {
|
|
6206
|
-
record: clonePendingGateDecisionRecord(record),
|
|
6207
|
-
path: pendingDecisionPath(record.id, stateDir),
|
|
6208
|
-
stateDir
|
|
6209
|
-
};
|
|
6210
|
-
}
|
|
6211
|
-
function persistPendingGateDecision(record, stateDir, allowReplace) {
|
|
6212
|
-
const verification = verifyPendingGateDecisionRecord(record);
|
|
6213
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
6214
|
-
const path2 = pendingDecisionPath(record.id, stateDir);
|
|
6215
|
-
mkdirSync4(dirname3(path2), { recursive: true });
|
|
6216
|
-
if (!allowReplace && existsSync8(path2)) throw new Error(`pending gate decision collision: ${record.id}`);
|
|
6217
|
-
atomicWrite(path2, JSON.stringify(record, null, 2));
|
|
6218
|
-
return pendingHandle(record, stateDir);
|
|
6219
|
-
}
|
|
6220
|
-
function loadPendingGateDecision(handle) {
|
|
6221
|
-
assertPendingHandlePath(handle);
|
|
6222
|
-
if (!existsSync8(handle.path)) return null;
|
|
6223
|
-
const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync8(handle.path, "utf8")));
|
|
6224
|
-
if (record.id !== handle.record.id) throw new Error("pending gate decision changed identity on disk");
|
|
6225
|
-
return pendingHandle(record, handle.stateDir);
|
|
6226
|
-
}
|
|
6227
|
-
function fsyncDirectoryBestEffort(path2) {
|
|
6228
|
-
let fd = null;
|
|
6229
|
-
try {
|
|
6230
|
-
fd = openSync(path2, "r");
|
|
6231
|
-
fsyncSync(fd);
|
|
6232
|
-
} catch {
|
|
6233
|
-
} finally {
|
|
6234
|
-
if (fd !== null) closeSync(fd);
|
|
6235
|
-
}
|
|
6236
|
-
}
|
|
6237
|
-
function clearPendingGateDecision(handle) {
|
|
6238
|
-
assertPendingHandlePath(handle);
|
|
6239
|
-
rmSync(handle.path, { force: true });
|
|
6240
|
-
fsyncDirectoryBestEffort(dirname3(handle.path));
|
|
6241
|
-
}
|
|
6242
|
-
function sameSubjectRefs(left, right) {
|
|
6243
|
-
return left.length === right.length && left.every((subject, index) => {
|
|
6244
|
-
const other = right[index];
|
|
6245
|
-
return other !== void 0 && subject.runId === other.runId && subject.digest === other.digest;
|
|
6246
|
-
});
|
|
6247
|
-
}
|
|
6248
|
-
function stagePendingGateOutput(draft, stateDir = clioStateDir()) {
|
|
6249
|
-
const id = newDecisionId(draft.group);
|
|
6250
|
-
const withoutIntegrity = {
|
|
6251
|
-
version: 1,
|
|
6252
|
-
kind: "output",
|
|
6253
|
-
id,
|
|
6254
|
-
group: draft.group,
|
|
6255
|
-
topology: draft.topology,
|
|
6256
|
-
cycle: draft.cycle,
|
|
6257
|
-
subjects: draft.subjects.map((subject) => ({ ...subject })),
|
|
6258
|
-
deciderRunId: draft.deciderRunId,
|
|
6259
|
-
finalOutput: draft.finalOutput,
|
|
6260
|
-
...draft.terminalCycle !== void 0 ? { terminalCycle: draft.terminalCycle } : {},
|
|
6261
|
-
...draft.resourceRoot !== void 0 ? { resourceRoot: draft.resourceRoot } : {},
|
|
6262
|
-
createdAt: draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
6263
|
-
};
|
|
6264
|
-
const record = {
|
|
6265
|
-
...withoutIntegrity,
|
|
6266
|
-
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
6267
|
-
};
|
|
6268
|
-
if (existsSync8(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
|
|
6269
|
-
return persistPendingGateDecision(record, stateDir, false);
|
|
6270
|
-
}
|
|
6271
|
-
function stagePendingGateDecision(draft, options = {}) {
|
|
6272
|
-
const stateDir = options.stateDir ?? clioStateDir();
|
|
6273
|
-
const id = newDecisionId(draft.group);
|
|
6274
|
-
const createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
6275
|
-
const decision = buildGateDecisionArtifact(draft, id, createdAt);
|
|
6276
|
-
const withoutIntegrity = {
|
|
6277
|
-
version: 1,
|
|
6278
|
-
kind: "decision",
|
|
6279
|
-
id,
|
|
6280
|
-
decision,
|
|
6281
|
-
...options.finalOutput !== void 0 ? { finalOutput: options.finalOutput } : {},
|
|
6282
|
-
...options.resourceRoot !== void 0 ? { resourceRoot: options.resourceRoot } : {},
|
|
6283
|
-
createdAt
|
|
6284
|
-
};
|
|
6285
|
-
const record = {
|
|
6286
|
-
...withoutIntegrity,
|
|
6287
|
-
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
6288
|
-
};
|
|
6289
|
-
if (existsSync8(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
|
|
6290
|
-
return persistPendingGateDecision(record, stateDir, false);
|
|
6291
|
-
}
|
|
6292
|
-
function resolvePendingGateDecision(handle, draft) {
|
|
6293
|
-
const loaded = loadPendingGateDecision(handle);
|
|
6294
|
-
if (loaded === null) throw new Error(`pending gate decision is missing: ${handle.record.id}`);
|
|
6295
|
-
if (loaded.record.kind === "decision") {
|
|
6296
|
-
const expected = buildGateDecisionArtifact(draft, loaded.record.id, loaded.record.createdAt);
|
|
6297
|
-
if (expected.integrity.digest !== loaded.record.decision.integrity.digest) {
|
|
6298
|
-
throw new Error("pending gate decision was already resolved to a different artifact");
|
|
6299
|
-
}
|
|
6300
|
-
return loaded;
|
|
6301
|
-
}
|
|
6302
|
-
const pending = loaded.record;
|
|
6303
|
-
if (draft.group !== pending.group || draft.topology !== pending.topology || draft.cycle !== pending.cycle || !sameSubjectRefs(draft.subjects, pending.subjects)) {
|
|
6304
|
-
throw new Error("resolved gate decision does not match staged output context");
|
|
6305
|
-
}
|
|
6306
|
-
if (draft.decider === void 0 || draft.decider.runId !== pending.deciderRunId) {
|
|
6307
|
-
throw new Error("resolved gate decision does not match staged decider run");
|
|
6308
|
-
}
|
|
6309
|
-
if (draft.createdAt !== void 0 && draft.createdAt !== pending.createdAt) {
|
|
6310
|
-
throw new Error("resolved gate decision cannot change the staged timestamp");
|
|
6311
|
-
}
|
|
6312
|
-
const decision = buildGateDecisionArtifact(draft, pending.id, pending.createdAt);
|
|
6313
|
-
const withoutIntegrity = {
|
|
6314
|
-
version: 1,
|
|
6315
|
-
kind: "decision",
|
|
6316
|
-
id: pending.id,
|
|
6317
|
-
decision,
|
|
6318
|
-
finalOutput: pending.finalOutput,
|
|
6319
|
-
...pending.resourceRoot !== void 0 ? { resourceRoot: pending.resourceRoot } : {},
|
|
6320
|
-
createdAt: pending.createdAt
|
|
6321
|
-
};
|
|
6322
|
-
const resolvedRecord = {
|
|
6323
|
-
...withoutIntegrity,
|
|
6324
|
-
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
6325
|
-
};
|
|
6326
|
-
return persistPendingGateDecision(resolvedRecord, loaded.stateDir, true);
|
|
6327
|
-
}
|
|
6328
|
-
function materializePendingGateDecision(handle) {
|
|
6329
|
-
const loaded = loadPendingGateDecision(handle);
|
|
6330
|
-
if (loaded === null) {
|
|
6331
|
-
if (handle.record.kind !== "decision") {
|
|
6332
|
-
throw new Error(`pending gate output is missing before resolution: ${handle.record.id}`);
|
|
6333
|
-
}
|
|
6334
|
-
const path2 = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
|
|
6335
|
-
if (!existsSync8(path2)) throw new Error(`pending gate decision and artifact are both missing: ${handle.record.id}`);
|
|
6336
|
-
const artifact = readVerifiedArtifact(path2);
|
|
6337
|
-
if (artifact.integrity.digest !== handle.record.decision.integrity.digest) {
|
|
6338
|
-
throw new Error(`gate decision artifact conflicts with completed pending record: ${handle.record.id}`);
|
|
6339
|
-
}
|
|
6340
|
-
return { artifact, path: path2 };
|
|
6341
|
-
}
|
|
6342
|
-
if (loaded.record.kind !== "decision") {
|
|
6343
|
-
throw new Error(`pending gate output requires receipt resolution: ${loaded.record.id}`);
|
|
6344
|
-
}
|
|
6345
|
-
const written = persistGateDecisionArtifact(loaded.record.decision, loaded.stateDir, true);
|
|
6346
|
-
const persisted = readVerifiedArtifact(written.path);
|
|
6347
|
-
if (persisted.integrity.digest !== loaded.record.decision.integrity.digest) {
|
|
6348
|
-
throw new Error(`materialized gate decision does not match pending record: ${loaded.record.id}`);
|
|
6349
|
-
}
|
|
6350
|
-
clearPendingGateDecision(loaded);
|
|
6351
|
-
return { artifact: persisted, path: written.path };
|
|
6352
|
-
}
|
|
6353
|
-
function finalizePendingGateDecision(handle, draft) {
|
|
6354
|
-
return materializePendingGateDecision(resolvePendingGateDecision(handle, draft));
|
|
6355
|
-
}
|
|
6356
|
-
function readPendingGateDecisions(stateDir = clioStateDir()) {
|
|
6357
|
-
const directory = pendingDecisionsDirectory(stateDir);
|
|
6358
|
-
if (!existsSync8(directory)) return { records: [], errors: [] };
|
|
6359
|
-
const records = [];
|
|
6360
|
-
const errors = [];
|
|
6361
|
-
for (const name of readdirSync2(directory).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
6362
|
-
const path2 = join10(directory, name);
|
|
6363
|
-
try {
|
|
6364
|
-
const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync8(path2, "utf8")));
|
|
6365
|
-
if (name !== `${record.id}.json`) throw new Error("pending gate decision filename does not match its id");
|
|
6366
|
-
records.push({ record, path: path2, stateDir });
|
|
6367
|
-
} catch (error) {
|
|
6368
|
-
errors.push({ path: path2, message: error instanceof Error ? error.message : String(error) });
|
|
6369
|
-
}
|
|
6370
|
-
}
|
|
6371
|
-
return { records, errors };
|
|
6372
|
-
}
|
|
6373
|
-
function preflightPendingGateDecisionMaterialization(handles) {
|
|
6374
|
-
for (const handle of handles) {
|
|
6375
|
-
if (handle.record.kind !== "decision") continue;
|
|
6376
|
-
const path2 = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
|
|
6377
|
-
if (!existsSync8(path2)) continue;
|
|
6378
|
-
const existing = readVerifiedArtifact(path2);
|
|
6379
|
-
if (existing.integrity.digest !== handle.record.decision.integrity.digest) {
|
|
6380
|
-
throw new Error(`gate decision artifact conflicts with pending record: ${handle.record.id}`);
|
|
6381
|
-
}
|
|
6382
|
-
}
|
|
6383
|
-
}
|
|
6384
|
-
function preparePendingGateDecisionRecovery(stateDir = clioStateDir()) {
|
|
6385
|
-
const pending = readPendingGateDecisions(stateDir);
|
|
6386
|
-
if (pending.errors.length > 0) {
|
|
6387
|
-
throw new Error(
|
|
6388
|
-
`pending gate decision journal is untrustworthy: ${pending.errors.map((entry) => `${entry.path}: ${entry.message}`).join("; ")}`
|
|
6389
|
-
);
|
|
6390
|
-
}
|
|
6391
|
-
const ready = pending.records.filter((handle) => handle.record.kind === "decision");
|
|
6392
|
-
preflightPendingGateDecisionMaterialization(ready);
|
|
6393
|
-
return {
|
|
6394
|
-
ready,
|
|
6395
|
-
unresolved: pending.records.filter((handle) => handle.record.kind === "output")
|
|
6396
|
-
};
|
|
6397
|
-
}
|
|
6398
|
-
function readGateDecisionArtifacts(group, stateDir = clioStateDir()) {
|
|
6399
|
-
const directory = decisionsDirectory(stateDir);
|
|
6400
|
-
if (!existsSync8(directory)) return [];
|
|
6401
|
-
const out = [];
|
|
6402
|
-
for (const name of readdirSync2(directory).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
6403
|
-
const path2 = join10(directory, name);
|
|
6404
|
-
try {
|
|
6405
|
-
const artifact = JSON.parse(readFileSync8(path2, "utf8"));
|
|
6406
|
-
if (group !== void 0 && artifact.group !== group) continue;
|
|
6407
|
-
if (!verifyGateDecisionArtifact(artifact).ok) continue;
|
|
6408
|
-
out.push({ artifact, path: path2 });
|
|
6409
|
-
} catch {
|
|
5626
|
+
statusHash: status === null ? null : sha2564(status)
|
|
5627
|
+
},
|
|
5628
|
+
safetyPolicy: {
|
|
5629
|
+
version: safety?.version ?? 1,
|
|
5630
|
+
rulePackHash: safety?.rulePackHash ?? null,
|
|
5631
|
+
rulePackVersion: safety?.rulePackVersion ?? null,
|
|
5632
|
+
projectPolicyPath: safety?.projectPolicyPath ?? null,
|
|
5633
|
+
projectPolicyHash: safety?.projectPolicyHash ?? null,
|
|
5634
|
+
projectPolicyValid: safety?.projectPolicyValid ?? null
|
|
6410
5635
|
}
|
|
6411
|
-
}
|
|
6412
|
-
return out;
|
|
5636
|
+
};
|
|
6413
5637
|
}
|
|
6414
|
-
function
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
5638
|
+
function git(cwd, args) {
|
|
5639
|
+
const result = spawnSync("git", [...args], {
|
|
5640
|
+
cwd,
|
|
5641
|
+
encoding: "utf8",
|
|
5642
|
+
timeout: 1e3,
|
|
5643
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
6420
5644
|
});
|
|
5645
|
+
if (result.status !== 0 || typeof result.stdout !== "string") return null;
|
|
5646
|
+
const trimmed = result.stdout.trim();
|
|
5647
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
5648
|
+
}
|
|
5649
|
+
function sha2564(input) {
|
|
5650
|
+
return createHash5("sha256").update(input, "utf8").digest("hex");
|
|
6421
5651
|
}
|
|
6422
5652
|
|
|
6423
|
-
// src/domains/dispatch/route-
|
|
5653
|
+
// src/domains/dispatch/route-observer.ts
|
|
6424
5654
|
init_esm_shims();
|
|
6425
|
-
import { existsSync as existsSync9, readFileSync as readFileSync9, renameSync as
|
|
5655
|
+
import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync9, renameSync as renameSync4, statSync } from "node:fs";
|
|
6426
5656
|
import { join as join11 } from "node:path";
|
|
5657
|
+
|
|
5658
|
+
// src/domains/dispatch/route-history.ts
|
|
5659
|
+
init_esm_shims();
|
|
5660
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, renameSync as renameSync3 } from "node:fs";
|
|
5661
|
+
import { join as join10 } from "node:path";
|
|
6427
5662
|
var ROUTE_HISTORY_VERSION = 3;
|
|
6428
5663
|
var DEFAULT_MAX_RECORDS = 4096;
|
|
6429
5664
|
function historyPath(stateDir) {
|
|
6430
|
-
return
|
|
5665
|
+
return join10(stateDir, "route-history.json");
|
|
6431
5666
|
}
|
|
6432
5667
|
function clone2(record) {
|
|
6433
5668
|
return structuredClone(record);
|
|
@@ -6436,7 +5671,7 @@ function compareRecords(left, right) {
|
|
|
6436
5671
|
return left.settledAt.localeCompare(right.settledAt) || left.receiptDigest.localeCompare(right.receiptDigest);
|
|
6437
5672
|
}
|
|
6438
5673
|
function validateRecord(value) {
|
|
6439
|
-
if (!
|
|
5674
|
+
if (!isRecord5(value) || value.version !== ROUTE_HISTORY_VERSION)
|
|
6440
5675
|
throw new Error("route history record has unsupported version");
|
|
6441
5676
|
if (!isDigest(value.receiptDigest)) throw new Error("route history receipt digest invalid");
|
|
6442
5677
|
if (typeof value.assignmentId !== "string" || value.assignmentId.length === 0)
|
|
@@ -6480,8 +5715,8 @@ function validateRecord(value) {
|
|
|
6480
5715
|
};
|
|
6481
5716
|
}
|
|
6482
5717
|
function readHistory(path2) {
|
|
6483
|
-
if (!
|
|
6484
|
-
const raw =
|
|
5718
|
+
if (!existsSync8(path2)) return [];
|
|
5719
|
+
const raw = readFileSync8(path2, "utf8").trim();
|
|
6485
5720
|
if (raw.length === 0) return [];
|
|
6486
5721
|
let parsed;
|
|
6487
5722
|
try {
|
|
@@ -6489,7 +5724,7 @@ function readHistory(path2) {
|
|
|
6489
5724
|
} catch (error) {
|
|
6490
5725
|
throw new Error(`route history unreadable: ${error instanceof Error ? error.message : String(error)}`);
|
|
6491
5726
|
}
|
|
6492
|
-
if (!
|
|
5727
|
+
if (!isRecord5(parsed) || !Array.isArray(parsed.records)) throw new Error("route history has unsupported format");
|
|
6493
5728
|
if (parsed.version !== ROUTE_HISTORY_VERSION) {
|
|
6494
5729
|
retireHistory(path2, parsed.version);
|
|
6495
5730
|
return [];
|
|
@@ -6549,14 +5784,14 @@ function createRouteHistoryStore(options = {}) {
|
|
|
6549
5784
|
}
|
|
6550
5785
|
};
|
|
6551
5786
|
}
|
|
6552
|
-
function
|
|
5787
|
+
function isRecord5(value) {
|
|
6553
5788
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6554
5789
|
}
|
|
6555
5790
|
function isDigest(value) {
|
|
6556
5791
|
return typeof value === "string" && /^[0-9a-f]{64}$/u.test(value);
|
|
6557
5792
|
}
|
|
6558
5793
|
function isRouteCandidate(value) {
|
|
6559
|
-
if (!
|
|
5794
|
+
if (!isRecord5(value)) return false;
|
|
6560
5795
|
if (!isExecutionRole(value.executionRole)) return false;
|
|
6561
5796
|
return [
|
|
6562
5797
|
value.agentId,
|
|
@@ -6572,7 +5807,7 @@ function isRouteCandidate(value) {
|
|
|
6572
5807
|
].every((field) => typeof field === "string");
|
|
6573
5808
|
}
|
|
6574
5809
|
function isPhaseTiming(value) {
|
|
6575
|
-
if (!
|
|
5810
|
+
if (!isRecord5(value)) return false;
|
|
6576
5811
|
return [
|
|
6577
5812
|
"requestToDecisionMs",
|
|
6578
5813
|
"decisionMs",
|
|
@@ -6588,7 +5823,7 @@ function isPhaseTiming(value) {
|
|
|
6588
5823
|
|
|
6589
5824
|
// src/domains/dispatch/route-quality.ts
|
|
6590
5825
|
init_esm_shims();
|
|
6591
|
-
import { createHash as
|
|
5826
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
6592
5827
|
function compareStrings(left, right) {
|
|
6593
5828
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
6594
5829
|
}
|
|
@@ -6703,7 +5938,7 @@ function reduceRouteQuality(input) {
|
|
|
6703
5938
|
return { label, checks, correlatedGates, sourceDigests: [...sourceDigests].sort(compareStrings) };
|
|
6704
5939
|
}
|
|
6705
5940
|
function routeQualityEvalDigest(artifact) {
|
|
6706
|
-
return
|
|
5941
|
+
return createHash6("sha256").update(canonicalJson2(artifact), "utf8").digest("hex");
|
|
6707
5942
|
}
|
|
6708
5943
|
function canonicalJson2(value) {
|
|
6709
5944
|
if (value === null) return "null";
|
|
@@ -6776,28 +6011,28 @@ function createRouteLearner(capacity = LEARNER_CAPACITY) {
|
|
|
6776
6011
|
}
|
|
6777
6012
|
var OBSERVATION_LOG_MAX_BYTES = 1024 * 1024;
|
|
6778
6013
|
function durableQualitySources(stateDir) {
|
|
6779
|
-
const runsPath2 =
|
|
6780
|
-
if (!
|
|
6014
|
+
const runsPath2 = join11(stateDir, "runs.json");
|
|
6015
|
+
if (!existsSync9(runsPath2)) return { receipts: [], gates: [], evals: [] };
|
|
6781
6016
|
try {
|
|
6782
|
-
const parsed = JSON.parse(
|
|
6017
|
+
const parsed = JSON.parse(readFileSync9(runsPath2, "utf8"));
|
|
6783
6018
|
if (!Array.isArray(parsed)) return { receipts: [], gates: [], evals: [] };
|
|
6784
6019
|
const receipts = [];
|
|
6785
6020
|
for (const envelope of parsed) {
|
|
6786
6021
|
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) continue;
|
|
6787
6022
|
const run = envelope;
|
|
6788
|
-
const path2 = run.receiptPath ??
|
|
6789
|
-
if (!
|
|
6790
|
-
const receipt = JSON.parse(
|
|
6023
|
+
const path2 = run.receiptPath ?? join11(stateDir, "receipts", `${run.id}.json`);
|
|
6024
|
+
if (!existsSync9(path2)) continue;
|
|
6025
|
+
const receipt = JSON.parse(readFileSync9(path2, "utf8"));
|
|
6791
6026
|
if (typeof receipt === "object" && receipt !== null && !Array.isArray(receipt)) {
|
|
6792
6027
|
receipts.push({ receipt, envelope: run });
|
|
6793
6028
|
}
|
|
6794
6029
|
}
|
|
6795
6030
|
const evals = [];
|
|
6796
|
-
const evalDirectory =
|
|
6797
|
-
if (
|
|
6798
|
-
for (const name of
|
|
6031
|
+
const evalDirectory = join11(clioDataDir(), "evals");
|
|
6032
|
+
if (existsSync9(evalDirectory)) {
|
|
6033
|
+
for (const name of readdirSync2(evalDirectory).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
6799
6034
|
try {
|
|
6800
|
-
const artifact = parseEvalArtifactV4(JSON.parse(
|
|
6035
|
+
const artifact = parseEvalArtifactV4(JSON.parse(readFileSync9(join11(evalDirectory, name), "utf8")), name);
|
|
6801
6036
|
evals.push({ artifact, digest: routeQualityEvalDigest(artifact) });
|
|
6802
6037
|
} catch {
|
|
6803
6038
|
}
|
|
@@ -6809,8 +6044,8 @@ function durableQualitySources(stateDir) {
|
|
|
6809
6044
|
}
|
|
6810
6045
|
}
|
|
6811
6046
|
function appendObservationLine(dir, record) {
|
|
6812
|
-
|
|
6813
|
-
const path2 =
|
|
6047
|
+
mkdirSync4(dir, { recursive: true });
|
|
6048
|
+
const path2 = join11(dir, "observations.jsonl");
|
|
6814
6049
|
try {
|
|
6815
6050
|
if (statSync(path2).size > OBSERVATION_LOG_MAX_BYTES) {
|
|
6816
6051
|
renameSync4(path2, `${path2}.1`);
|
|
@@ -6842,7 +6077,7 @@ function createRouteObserver(options) {
|
|
|
6842
6077
|
const PENDING_LIMIT = 512;
|
|
6843
6078
|
let totalObservations = 0;
|
|
6844
6079
|
let sequence = 0;
|
|
6845
|
-
const logDir = () => options.logDir ??
|
|
6080
|
+
const logDir = () => options.logDir ?? join11(clioStateDir(), "route-decisions");
|
|
6846
6081
|
const reconcileHistory = () => {
|
|
6847
6082
|
const sources = durableQualitySources(options.stateDir ?? clioStateDir());
|
|
6848
6083
|
if (sources.receipts.length === 0) return;
|
|
@@ -7013,6 +6248,326 @@ function createRouteObserver(options) {
|
|
|
7013
6248
|
};
|
|
7014
6249
|
}
|
|
7015
6250
|
|
|
6251
|
+
// src/domains/dispatch/run-event-journal-bridge.ts
|
|
6252
|
+
init_esm_shims();
|
|
6253
|
+
|
|
6254
|
+
// src/tools/dispatch-run-events.ts
|
|
6255
|
+
init_esm_shims();
|
|
6256
|
+
|
|
6257
|
+
// src/tools/dispatch-event-text.ts
|
|
6258
|
+
init_esm_shims();
|
|
6259
|
+
function assistantTextFromEvent(event) {
|
|
6260
|
+
return durableAssistantTextFromEvent(event).trim();
|
|
6261
|
+
}
|
|
6262
|
+
function receiptResponseModelIdObservationLabel(receipt) {
|
|
6263
|
+
const responses = receipt.upstreamResponses ?? [];
|
|
6264
|
+
if (responses.length === 0) return null;
|
|
6265
|
+
const labels = responses.map((response) => {
|
|
6266
|
+
const observation = responseModelIdObservationFromRecord(
|
|
6267
|
+
response,
|
|
6268
|
+
"legacy-difference-only"
|
|
6269
|
+
);
|
|
6270
|
+
if (observation.state === "reported") return `reported:${observation.reportedModelId}`;
|
|
6271
|
+
if (observation.state === "not-reported") return "not-reported";
|
|
6272
|
+
if (observation.state === "not-observed") return "not-observed";
|
|
6273
|
+
return `legacy-difference-only:${observation.differingModelId ?? "none"}`;
|
|
6274
|
+
});
|
|
6275
|
+
return `response_model_id_observation=${labels.join(",")}`;
|
|
6276
|
+
}
|
|
6277
|
+
|
|
6278
|
+
// src/tools/dispatch-run-events.ts
|
|
6279
|
+
var RUN_TAIL_ENTRY_LIMIT = 100;
|
|
6280
|
+
var RUN_TAIL_RUN_LIMIT = 64;
|
|
6281
|
+
var RUN_TAIL_TEXT_LIMIT = 600;
|
|
6282
|
+
function isRecord6(value) {
|
|
6283
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6284
|
+
}
|
|
6285
|
+
function eventDetail(event) {
|
|
6286
|
+
const text = assistantTextFromEvent(event);
|
|
6287
|
+
if (text.length > 0) return truncateUtf8(text, RUN_TAIL_TEXT_LIMIT, "...");
|
|
6288
|
+
if (!isRecord6(event)) return void 0;
|
|
6289
|
+
if (event.type === "clio_tool_finish" && isRecord6(event.payload)) {
|
|
6290
|
+
const tool = typeof event.payload.tool === "string" ? event.payload.tool : "tool";
|
|
6291
|
+
const outcome = typeof event.payload.outcome === "string" ? event.payload.outcome : "";
|
|
6292
|
+
return `${tool} ${outcome}`.trim();
|
|
6293
|
+
}
|
|
6294
|
+
if (event.type === "attempt_start") {
|
|
6295
|
+
const attempt = typeof event.attempt === "number" ? event.attempt : "?";
|
|
6296
|
+
const runId = typeof event.runId === "string" ? event.runId : "?";
|
|
6297
|
+
const reason = typeof event.reason === "string" ? event.reason : "retry";
|
|
6298
|
+
return truncateUtf8(`attempt ${attempt} -> ${runId}: ${reason}`, RUN_TAIL_TEXT_LIMIT, "...");
|
|
6299
|
+
}
|
|
6300
|
+
return void 0;
|
|
6301
|
+
}
|
|
6302
|
+
function runTailEntryFromEvent(event, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
6303
|
+
const type = isRecord6(event) && typeof event.type === "string" ? event.type : "unknown";
|
|
6304
|
+
if (type === "heartbeat" || type === "message_update") return null;
|
|
6305
|
+
const entry = { at, type };
|
|
6306
|
+
const detail = eventDetail(event);
|
|
6307
|
+
if (detail !== void 0) entry.detail = detail;
|
|
6308
|
+
return entry;
|
|
6309
|
+
}
|
|
6310
|
+
var REGISTRY_FAILURE_OUTCOME = "failed";
|
|
6311
|
+
var REGISTRY_UNKNOWN_OUTCOME = "unknown";
|
|
6312
|
+
function errorText(error) {
|
|
6313
|
+
return error instanceof Error ? error.message : String(error);
|
|
6314
|
+
}
|
|
6315
|
+
function createDispatchRunEventRegistry(options = {}) {
|
|
6316
|
+
const runTails = /* @__PURE__ */ new Map();
|
|
6317
|
+
const activeRuns = /* @__PURE__ */ new Set();
|
|
6318
|
+
const activeBatches = /* @__PURE__ */ new Set();
|
|
6319
|
+
const journal = options.journal === void 0 ? defaultRunEventJournal() : options.journal;
|
|
6320
|
+
const journalSeal = (logicalRunId, receipt) => {
|
|
6321
|
+
if (journal === null || !isRecord6(receipt)) return;
|
|
6322
|
+
const digest = receipt.integrity?.digest;
|
|
6323
|
+
const outcome = typeof receipt.outcome === "string" ? receipt.outcome : REGISTRY_UNKNOWN_OUTCOME;
|
|
6324
|
+
journal.receipt(logicalRunId, {
|
|
6325
|
+
outcome,
|
|
6326
|
+
exitCode: typeof receipt.exitCode === "number" ? receipt.exitCode : null,
|
|
6327
|
+
...typeof digest === "string" ? { digest } : {},
|
|
6328
|
+
...receipt.runId !== logicalRunId ? { attemptRunId: receipt.runId } : {}
|
|
6329
|
+
});
|
|
6330
|
+
journal.terminal(logicalRunId, outcome, receipt.outcomeDetail ?? void 0);
|
|
6331
|
+
};
|
|
6332
|
+
const sealBatchJournals = (assignmentIds, receipts) => {
|
|
6333
|
+
if (journal === null || !Array.isArray(receipts)) return;
|
|
6334
|
+
if (assignmentIds.length === receipts.length) {
|
|
6335
|
+
for (const [index, runId] of assignmentIds.entries()) {
|
|
6336
|
+
const receipt = receipts[index];
|
|
6337
|
+
if (receipt !== void 0) journalSeal(runId, receipt);
|
|
6338
|
+
}
|
|
6339
|
+
return;
|
|
6340
|
+
}
|
|
6341
|
+
for (const receipt of receipts) {
|
|
6342
|
+
if (receipt != null && typeof receipt.runId === "string") journalSeal(receipt.runId, receipt);
|
|
6343
|
+
}
|
|
6344
|
+
};
|
|
6345
|
+
const pruneRunTails = () => {
|
|
6346
|
+
while (runTails.size > RUN_TAIL_RUN_LIMIT) {
|
|
6347
|
+
let oldestKey = null;
|
|
6348
|
+
let oldestSeen = Number.POSITIVE_INFINITY;
|
|
6349
|
+
for (const [key, state] of runTails) {
|
|
6350
|
+
if (activeRuns.has(key) || state.lastSeenAt >= oldestSeen) continue;
|
|
6351
|
+
oldestKey = key;
|
|
6352
|
+
oldestSeen = state.lastSeenAt;
|
|
6353
|
+
}
|
|
6354
|
+
if (oldestKey === null) break;
|
|
6355
|
+
runTails.delete(oldestKey);
|
|
6356
|
+
}
|
|
6357
|
+
};
|
|
6358
|
+
const recordRunEvent = (runId, agentId, event) => {
|
|
6359
|
+
const entry = runTailEntryFromEvent(event);
|
|
6360
|
+
if (entry === null) return;
|
|
6361
|
+
const state = runTails.get(runId) ?? { agentId, entries: [], lastSeenAt: Date.now() };
|
|
6362
|
+
state.lastSeenAt = Date.now();
|
|
6363
|
+
state.entries.push(entry);
|
|
6364
|
+
if (state.entries.length > RUN_TAIL_ENTRY_LIMIT) {
|
|
6365
|
+
state.entries.splice(0, state.entries.length - RUN_TAIL_ENTRY_LIMIT);
|
|
6366
|
+
}
|
|
6367
|
+
runTails.set(runId, state);
|
|
6368
|
+
pruneRunTails();
|
|
6369
|
+
journal?.append(runId, entry);
|
|
6370
|
+
};
|
|
6371
|
+
const drainSingle = async (runId, agentId, events, bus) => {
|
|
6372
|
+
const summary = {
|
|
6373
|
+
count: 0,
|
|
6374
|
+
types: [],
|
|
6375
|
+
lastAssistantText: "",
|
|
6376
|
+
terminalAttemptRunId: runId
|
|
6377
|
+
};
|
|
6378
|
+
for await (const event of events) {
|
|
6379
|
+
summary.count += 1;
|
|
6380
|
+
const type = isRecord6(event) && typeof event.type === "string" ? event.type : "unknown";
|
|
6381
|
+
summary.types.push(type);
|
|
6382
|
+
if (type === "attempt_start") summary.lastAssistantText = "";
|
|
6383
|
+
const text = durableAssistantTextFromEvent(event);
|
|
6384
|
+
if (text.trim().length > 0) summary.lastAssistantText = text;
|
|
6385
|
+
recordRunEvent(runId, agentId, event);
|
|
6386
|
+
if (type !== "heartbeat") bus?.emit(BusChannels.DispatchProgress, { runId, agentId, event });
|
|
6387
|
+
}
|
|
6388
|
+
return summary;
|
|
6389
|
+
};
|
|
6390
|
+
const drainBatch = async (batchId, events, bus) => {
|
|
6391
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
6392
|
+
for await (const event of events) {
|
|
6393
|
+
if (!isRecord6(event) || event.type !== "batch_run_event") continue;
|
|
6394
|
+
const runId = typeof event.runId === "string" ? event.runId : batchId;
|
|
6395
|
+
const agentId = typeof event.agentId === "string" ? event.agentId : "batch";
|
|
6396
|
+
const inner = event.event;
|
|
6397
|
+
const summary = summaries.get(runId) ?? {
|
|
6398
|
+
count: 0,
|
|
6399
|
+
types: [],
|
|
6400
|
+
lastAssistantText: "",
|
|
6401
|
+
terminalAttemptRunId: runId
|
|
6402
|
+
};
|
|
6403
|
+
summary.count += 1;
|
|
6404
|
+
const type = isRecord6(inner) && typeof inner.type === "string" ? inner.type : "unknown";
|
|
6405
|
+
summary.types.push(type);
|
|
6406
|
+
const text = durableAssistantTextFromEvent(inner);
|
|
6407
|
+
if (text.trim().length > 0) summary.lastAssistantText = text;
|
|
6408
|
+
summaries.set(runId, summary);
|
|
6409
|
+
recordRunEvent(runId, agentId, inner);
|
|
6410
|
+
if (type !== "heartbeat") bus?.emit(BusChannels.DispatchProgress, { runId, agentId, event: inner });
|
|
6411
|
+
}
|
|
6412
|
+
return summaries;
|
|
6413
|
+
};
|
|
6414
|
+
return {
|
|
6415
|
+
registerSingle(handle, agentId, bus) {
|
|
6416
|
+
if (activeRuns.has(handle.runId)) {
|
|
6417
|
+
throw new Error(`dispatch event registry: run '${handle.runId}' is already registered`);
|
|
6418
|
+
}
|
|
6419
|
+
activeRuns.add(handle.runId);
|
|
6420
|
+
journal?.open(handle.runId, agentId);
|
|
6421
|
+
const summaryPromise = drainSingle(handle.runId, agentId, handle.events, bus);
|
|
6422
|
+
const completion = Promise.allSettled([summaryPromise, handle.finalPromise]).then(
|
|
6423
|
+
([summaryResult, receiptResult]) => {
|
|
6424
|
+
if (summaryResult.status === "rejected") throw summaryResult.reason;
|
|
6425
|
+
if (receiptResult.status === "rejected") throw receiptResult.reason;
|
|
6426
|
+
return { receipt: receiptResult.value, summary: summaryResult.value };
|
|
6427
|
+
}
|
|
6428
|
+
);
|
|
6429
|
+
const releaseSingle = () => {
|
|
6430
|
+
activeRuns.delete(handle.runId);
|
|
6431
|
+
pruneRunTails();
|
|
6432
|
+
};
|
|
6433
|
+
void completion.then(
|
|
6434
|
+
({ receipt }) => {
|
|
6435
|
+
journalSeal(handle.runId, receipt);
|
|
6436
|
+
releaseSingle();
|
|
6437
|
+
},
|
|
6438
|
+
(error) => {
|
|
6439
|
+
journal?.terminal(handle.runId, REGISTRY_FAILURE_OUTCOME, errorText(error));
|
|
6440
|
+
releaseSingle();
|
|
6441
|
+
}
|
|
6442
|
+
);
|
|
6443
|
+
return { runId: handle.runId, completion };
|
|
6444
|
+
},
|
|
6445
|
+
registerBatch(handle, agentIds, bus) {
|
|
6446
|
+
if (activeBatches.has(handle.batchId)) {
|
|
6447
|
+
throw new Error(`dispatch event registry: batch '${handle.batchId}' is already registered`);
|
|
6448
|
+
}
|
|
6449
|
+
const duplicateRunId = handle.assignmentIds.find(
|
|
6450
|
+
(runId, index) => handle.assignmentIds.slice(0, index).includes(runId)
|
|
6451
|
+
);
|
|
6452
|
+
if (duplicateRunId !== void 0) {
|
|
6453
|
+
throw new Error(`dispatch event registry: batch '${handle.batchId}' repeats run '${duplicateRunId}'`);
|
|
6454
|
+
}
|
|
6455
|
+
const activeRunId = handle.assignmentIds.find((runId) => activeRuns.has(runId));
|
|
6456
|
+
if (activeRunId !== void 0) {
|
|
6457
|
+
throw new Error(`dispatch event registry: run '${activeRunId}' is already registered`);
|
|
6458
|
+
}
|
|
6459
|
+
activeBatches.add(handle.batchId);
|
|
6460
|
+
for (const runId of handle.assignmentIds) activeRuns.add(runId);
|
|
6461
|
+
for (const [index, runId] of handle.assignmentIds.entries()) {
|
|
6462
|
+
journal?.open(runId, agentIds[index] ?? "unknown");
|
|
6463
|
+
}
|
|
6464
|
+
const completion = Promise.allSettled([drainBatch(handle.batchId, handle.events, bus), handle.finalPromise]).then(
|
|
6465
|
+
([summariesResult, receiptsResult]) => {
|
|
6466
|
+
if (summariesResult.status === "rejected") throw summariesResult.reason;
|
|
6467
|
+
if (receiptsResult.status === "rejected") throw receiptsResult.reason;
|
|
6468
|
+
return { receipts: receiptsResult.value, summaries: summariesResult.value };
|
|
6469
|
+
}
|
|
6470
|
+
);
|
|
6471
|
+
const releaseBatch = () => {
|
|
6472
|
+
activeBatches.delete(handle.batchId);
|
|
6473
|
+
for (const runId of handle.assignmentIds) activeRuns.delete(runId);
|
|
6474
|
+
pruneRunTails();
|
|
6475
|
+
};
|
|
6476
|
+
void completion.then(
|
|
6477
|
+
({ receipts }) => {
|
|
6478
|
+
sealBatchJournals(handle.assignmentIds, receipts);
|
|
6479
|
+
releaseBatch();
|
|
6480
|
+
},
|
|
6481
|
+
(error) => {
|
|
6482
|
+
const detail = errorText(error);
|
|
6483
|
+
for (const runId of handle.assignmentIds) {
|
|
6484
|
+
journal?.terminal(runId, REGISTRY_FAILURE_OUTCOME, detail);
|
|
6485
|
+
}
|
|
6486
|
+
releaseBatch();
|
|
6487
|
+
}
|
|
6488
|
+
);
|
|
6489
|
+
for (const [index, runId] of handle.assignmentIds.entries()) {
|
|
6490
|
+
if (!runTails.has(runId)) {
|
|
6491
|
+
runTails.set(runId, {
|
|
6492
|
+
agentId: agentIds[index] ?? "unknown",
|
|
6493
|
+
entries: [],
|
|
6494
|
+
lastSeenAt: Date.now()
|
|
6495
|
+
});
|
|
6496
|
+
}
|
|
6497
|
+
}
|
|
6498
|
+
return { batchId: handle.batchId, assignmentIds: handle.assignmentIds, completion };
|
|
6499
|
+
},
|
|
6500
|
+
recordEvent: recordRunEvent,
|
|
6501
|
+
eventTail(runId) {
|
|
6502
|
+
const state = runTails.get(runId);
|
|
6503
|
+
return state === void 0 ? null : { agentId: state.agentId, entries: [...state.entries] };
|
|
6504
|
+
}
|
|
6505
|
+
};
|
|
6506
|
+
}
|
|
6507
|
+
|
|
6508
|
+
// src/domains/dispatch/run-event-journal-bridge.ts
|
|
6509
|
+
var OPENED_RUN_LIMIT = 512;
|
|
6510
|
+
function isRecord7(value) {
|
|
6511
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6512
|
+
}
|
|
6513
|
+
function runIdentity(payload) {
|
|
6514
|
+
if (!isRecord7(payload)) return null;
|
|
6515
|
+
if (typeof payload.runId !== "string" || payload.runId.length === 0) return null;
|
|
6516
|
+
return { runId: payload.runId, agentId: typeof payload.agentId === "string" ? payload.agentId : "unknown" };
|
|
6517
|
+
}
|
|
6518
|
+
function attachRunEventJournalBridge(bus, options = {}) {
|
|
6519
|
+
const journal = options.journal ?? defaultRunEventJournal();
|
|
6520
|
+
const opened = /* @__PURE__ */ new Set();
|
|
6521
|
+
const ensureOpen = (runId, agentId) => {
|
|
6522
|
+
if (opened.has(runId)) return;
|
|
6523
|
+
opened.add(runId);
|
|
6524
|
+
while (opened.size > OPENED_RUN_LIMIT) {
|
|
6525
|
+
const oldest = opened.values().next();
|
|
6526
|
+
if (oldest.done === true) break;
|
|
6527
|
+
opened.delete(oldest.value);
|
|
6528
|
+
}
|
|
6529
|
+
journal.open(runId, agentId);
|
|
6530
|
+
};
|
|
6531
|
+
const seal = (outcome, detail, payload) => {
|
|
6532
|
+
const identity = runIdentity(payload);
|
|
6533
|
+
if (identity === null) return;
|
|
6534
|
+
ensureOpen(identity.runId, identity.agentId);
|
|
6535
|
+
const exitCode = isRecord7(payload) && typeof payload.exitCode === "number" ? payload.exitCode : null;
|
|
6536
|
+
journal.receipt(identity.runId, { outcome, exitCode });
|
|
6537
|
+
journal.terminal(identity.runId, outcome, detail ?? void 0);
|
|
6538
|
+
opened.delete(identity.runId);
|
|
6539
|
+
};
|
|
6540
|
+
const unsubscribes = [
|
|
6541
|
+
bus.on(BusChannels.DispatchProgress, (payload) => {
|
|
6542
|
+
const identity = runIdentity(payload);
|
|
6543
|
+
if (identity === null) return;
|
|
6544
|
+
const entry = runTailEntryFromEvent(payload.event);
|
|
6545
|
+
if (entry === null) return;
|
|
6546
|
+
ensureOpen(identity.runId, identity.agentId);
|
|
6547
|
+
const message = isRecord7(payload.event) && typeof payload.event.message === "string" ? payload.event.message : void 0;
|
|
6548
|
+
journal.append(
|
|
6549
|
+
identity.runId,
|
|
6550
|
+
entry.detail === void 0 && message !== void 0 ? { ...entry, detail: message } : entry
|
|
6551
|
+
);
|
|
6552
|
+
}),
|
|
6553
|
+
bus.on(BusChannels.DispatchCompleted, (payload) => {
|
|
6554
|
+
seal(payload.outcome, payload.outcomeDetail, payload);
|
|
6555
|
+
}),
|
|
6556
|
+
bus.on(BusChannels.DispatchFailed, (payload) => {
|
|
6557
|
+
seal(payload.outcome, payload.outcomeDetail, payload);
|
|
6558
|
+
})
|
|
6559
|
+
];
|
|
6560
|
+
let stopped = false;
|
|
6561
|
+
return {
|
|
6562
|
+
stop() {
|
|
6563
|
+
if (stopped) return;
|
|
6564
|
+
stopped = true;
|
|
6565
|
+
for (const unsubscribe of unsubscribes) unsubscribe();
|
|
6566
|
+
opened.clear();
|
|
6567
|
+
}
|
|
6568
|
+
};
|
|
6569
|
+
}
|
|
6570
|
+
|
|
7016
6571
|
// src/domains/dispatch/run-identity.ts
|
|
7017
6572
|
init_esm_shims();
|
|
7018
6573
|
import { hostname as hostname3, userInfo } from "node:os";
|
|
@@ -7062,27 +6617,27 @@ function detectRunIdentity(env = process.env) {
|
|
|
7062
6617
|
|
|
7063
6618
|
// src/domains/dispatch/state.ts
|
|
7064
6619
|
init_esm_shims();
|
|
7065
|
-
import { randomBytes as
|
|
7066
|
-
import { existsSync as
|
|
7067
|
-
import { join as
|
|
6620
|
+
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
6621
|
+
import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync10 } from "node:fs";
|
|
6622
|
+
import { join as join12 } from "node:path";
|
|
7068
6623
|
function newRunId() {
|
|
7069
|
-
const n = BigInt(`0x${
|
|
6624
|
+
const n = BigInt(`0x${randomBytes4(8).toString("hex")}`);
|
|
7070
6625
|
const raw = n.toString(36);
|
|
7071
6626
|
if (raw.length >= 12) return raw.slice(0, 12);
|
|
7072
6627
|
return raw.padStart(12, "0");
|
|
7073
6628
|
}
|
|
7074
6629
|
function runsPath() {
|
|
7075
|
-
return
|
|
6630
|
+
return join12(clioStateDir(), "runs.json");
|
|
7076
6631
|
}
|
|
7077
6632
|
function receiptPathFor(runId) {
|
|
7078
|
-
return
|
|
6633
|
+
return join12(clioStateDir(), "receipts", `${runId}.json`);
|
|
7079
6634
|
}
|
|
7080
6635
|
function fleetRunPath(runId) {
|
|
7081
|
-
return
|
|
6636
|
+
return join12(clioStateDir(), "fleet-runs", `${runId}.json`);
|
|
7082
6637
|
}
|
|
7083
6638
|
function readFleetRun(runId) {
|
|
7084
6639
|
try {
|
|
7085
|
-
const parsed = JSON.parse(
|
|
6640
|
+
const parsed = JSON.parse(readFileSync10(fleetRunPath(runId), "utf8"));
|
|
7086
6641
|
return parsed.version === 1 && parsed.id === runId ? structuredClone(parsed) : null;
|
|
7087
6642
|
} catch {
|
|
7088
6643
|
return null;
|
|
@@ -7092,10 +6647,27 @@ async function writeFleetRun(record) {
|
|
|
7092
6647
|
await atomicWrite(fleetRunPath(record.id), `${JSON.stringify(record, null, 2)}
|
|
7093
6648
|
`);
|
|
7094
6649
|
}
|
|
6650
|
+
var MAX_FLEET_RUN_SCAN = 64;
|
|
6651
|
+
function listFleetRuns(limit = MAX_FLEET_RUN_SCAN) {
|
|
6652
|
+
let entries;
|
|
6653
|
+
try {
|
|
6654
|
+
entries = readdirSync3(join12(clioStateDir(), "fleet-runs"));
|
|
6655
|
+
} catch {
|
|
6656
|
+
return [];
|
|
6657
|
+
}
|
|
6658
|
+
const records = [];
|
|
6659
|
+
for (const name of entries.slice(0, MAX_FLEET_RUN_SCAN)) {
|
|
6660
|
+
if (!name.endsWith(".json")) continue;
|
|
6661
|
+
const record = readFleetRun(name.slice(0, -".json".length));
|
|
6662
|
+
if (record !== null) records.push(record);
|
|
6663
|
+
}
|
|
6664
|
+
records.sort((a, b) => (Date.parse(b.startedAt) || 0) - (Date.parse(a.startedAt) || 0));
|
|
6665
|
+
return records.slice(0, Math.max(0, limit));
|
|
6666
|
+
}
|
|
7095
6667
|
function readRuns() {
|
|
7096
6668
|
const path2 = runsPath();
|
|
7097
|
-
if (!
|
|
7098
|
-
const raw =
|
|
6669
|
+
if (!existsSync10(path2)) return [];
|
|
6670
|
+
const raw = readFileSync10(path2, "utf8").trim();
|
|
7099
6671
|
if (raw.length === 0) return [];
|
|
7100
6672
|
const parsed = JSON.parse(raw);
|
|
7101
6673
|
if (!Array.isArray(parsed)) return [];
|
|
@@ -7253,6 +6825,10 @@ function openLedger(opts) {
|
|
|
7253
6825
|
const capped = capRuns(merged, maxRuns);
|
|
7254
6826
|
runs = capped;
|
|
7255
6827
|
atomicWrite(target, JSON.stringify(capped, null, 2));
|
|
6828
|
+
if (merged.length > capped.length) {
|
|
6829
|
+
const kept = new Set(capped.map((run) => run.id));
|
|
6830
|
+
removeRunEventJournals(merged.filter((run) => !kept.has(run.id)).map((run) => run.id));
|
|
6831
|
+
}
|
|
7256
6832
|
dirty.clear();
|
|
7257
6833
|
});
|
|
7258
6834
|
},
|
|
@@ -7421,7 +6997,7 @@ function requestOriginFor(req) {
|
|
|
7421
6997
|
return req.requestOrigin ?? "agent";
|
|
7422
6998
|
}
|
|
7423
6999
|
function sha2565(input) {
|
|
7424
|
-
return
|
|
7000
|
+
return createHash7("sha256").update(input, "utf8").digest("hex");
|
|
7425
7001
|
}
|
|
7426
7002
|
function promptHash(systemPrompt) {
|
|
7427
7003
|
return systemPrompt.length > 0 ? sha2565(systemPrompt) : null;
|
|
@@ -7563,8 +7139,8 @@ var DISPATCH_DRAIN_GRACE_MS = 2e3;
|
|
|
7563
7139
|
var RUN_WRITE_TARGET_HISTORY = 512;
|
|
7564
7140
|
async function awaitEventDrain(drained, graceMs = DISPATCH_DRAIN_GRACE_MS) {
|
|
7565
7141
|
let timer;
|
|
7566
|
-
const grace = new Promise((
|
|
7567
|
-
timer = setTimeout(() =>
|
|
7142
|
+
const grace = new Promise((resolve4) => {
|
|
7143
|
+
timer = setTimeout(() => resolve4(false), graceMs);
|
|
7568
7144
|
});
|
|
7569
7145
|
try {
|
|
7570
7146
|
return await Promise.race([drained.then(() => true), grace]);
|
|
@@ -8648,6 +8224,7 @@ function createDispatchBundle(context, options) {
|
|
|
8648
8224
|
let ledger = null;
|
|
8649
8225
|
let heartbeatTimer = null;
|
|
8650
8226
|
const active = /* @__PURE__ */ new Map();
|
|
8227
|
+
const pendingCapacity = /* @__PURE__ */ new Map();
|
|
8651
8228
|
const targetCooldowns = /* @__PURE__ */ new Map();
|
|
8652
8229
|
const ownedReservations = /* @__PURE__ */ new Set();
|
|
8653
8230
|
const runWriteAttributions = /* @__PURE__ */ new Map();
|
|
@@ -8675,18 +8252,23 @@ function createDispatchBundle(context, options) {
|
|
|
8675
8252
|
onError: (error) => reportDispatchDiagnostic("read capacity lease usage", error)
|
|
8676
8253
|
})
|
|
8677
8254
|
);
|
|
8255
|
+
function configuredEndpointCapacities() {
|
|
8256
|
+
return resolveEndpointCapacities({
|
|
8257
|
+
statuses: providers.list(),
|
|
8258
|
+
targets: getEffectiveSettings()?.targets ?? [],
|
|
8259
|
+
runtimeFor: (runtimeId) => providers.getRuntime(runtimeId)
|
|
8260
|
+
});
|
|
8261
|
+
}
|
|
8678
8262
|
function configuredEndpointLimits() {
|
|
8679
|
-
return Object.fromEntries(
|
|
8680
|
-
Object.entries(endpointCapacitiesForStatuses(providers.list())).map(([key, value]) => [key, value.limit])
|
|
8681
|
-
);
|
|
8263
|
+
return Object.fromEntries(Object.entries(configuredEndpointCapacities()).map(([key, value]) => [key, value.limit]));
|
|
8682
8264
|
}
|
|
8683
8265
|
function endpointCapacityForTarget(targetId) {
|
|
8684
8266
|
const status = providers.list().find((entry) => entry.target.id === targetId);
|
|
8685
|
-
|
|
8686
|
-
|
|
8267
|
+
const target = status?.target ?? providers.getTarget(targetId);
|
|
8268
|
+
if (target === null || target === void 0) return null;
|
|
8269
|
+
const endpoint = status === void 0 ? endpointCapacityFor({ target, runtime: providers.getRuntime(target.runtime) }) : endpointCapacityForStatus(status);
|
|
8687
8270
|
if (endpoint === null) return null;
|
|
8688
|
-
|
|
8689
|
-
return configured ?? endpoint;
|
|
8271
|
+
return configuredEndpointCapacities()[endpoint.key] ?? endpoint;
|
|
8690
8272
|
}
|
|
8691
8273
|
function reservationCapacitySnapshot(settings) {
|
|
8692
8274
|
const preflight = scheduling.preflight();
|
|
@@ -8763,10 +8345,24 @@ function createDispatchBundle(context, options) {
|
|
|
8763
8345
|
const configured = settings?.budget.concurrency;
|
|
8764
8346
|
return scheduling.maxWorkers?.() ?? (configured === "auto" || configured === void 0 ? 4 : Math.max(1, configured));
|
|
8765
8347
|
}
|
|
8348
|
+
function publishCapacityQueued(identity, timing, node) {
|
|
8349
|
+
pendingCapacity.set(identity.runId, { identity, timing, node });
|
|
8350
|
+
context.bus.emit(BusChannels.DispatchEnqueued, identity);
|
|
8351
|
+
}
|
|
8352
|
+
function publishCapacityAdmissionFailure(identity, error) {
|
|
8353
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
8354
|
+
const outcome = error instanceof AdmissionCanceledError ? "canceled" : /admission timed out/u.test(detail) ? "timed_out" : "denied_by_policy";
|
|
8355
|
+
context.bus.emit(BusChannels.DispatchFailed, {
|
|
8356
|
+
...identity,
|
|
8357
|
+
outcome,
|
|
8358
|
+
outcomeDetail: detail,
|
|
8359
|
+
reason: outcome
|
|
8360
|
+
});
|
|
8361
|
+
}
|
|
8766
8362
|
async function admitAssignmentCapacity(req, nodeId, timing, endpoint) {
|
|
8767
8363
|
const queuedAt = now();
|
|
8768
8364
|
timing.queuedAt = new Date(queuedAt).toISOString();
|
|
8769
|
-
const assignmentId = req.lineage?.rootRunId ?? `pending-${queuedAt.toString(36)}-${
|
|
8365
|
+
const assignmentId = req.lineage?.rootRunId ?? req.runIdHint ?? `pending-${queuedAt.toString(36)}-${randomBytes5(6).toString("hex")}`;
|
|
8770
8366
|
const requestedAt = Date.parse(timing.requestedAt ?? timing.queuedAt);
|
|
8771
8367
|
const deadlineAt = req.assignmentDeadlineAt ?? requestedAt + (req.routingIntent?.deadlineMs ?? 6e4);
|
|
8772
8368
|
if (req.lineage === void 0) await registerAssignment(assignmentId);
|
|
@@ -9010,6 +8606,7 @@ function createDispatchBundle(context, options) {
|
|
|
9010
8606
|
depth: run.lineage.depth
|
|
9011
8607
|
}
|
|
9012
8608
|
};
|
|
8609
|
+
delete retryReq.runIdHint;
|
|
9013
8610
|
const reasonKey = retryReasonKey(run.lineage.rootRunId, attempt);
|
|
9014
8611
|
retryReasons.set(reasonKey, reason);
|
|
9015
8612
|
try {
|
|
@@ -9536,7 +9133,26 @@ function createDispatchBundle(context, options) {
|
|
|
9536
9133
|
const wireModelId = lifecycle.agentConfig.id;
|
|
9537
9134
|
assertTargetNotCoolingDown(req, targetId, runtimeId, wireModelId);
|
|
9538
9135
|
assertBudgetAdmitsRoute(req, { rates: null, provenance: "unknown" }, settings);
|
|
9539
|
-
const
|
|
9136
|
+
const queuedIdentity = req.lineage === void 0 && req.runIdHint !== void 0 ? {
|
|
9137
|
+
runId: req.runIdHint,
|
|
9138
|
+
agentId: req.agentId,
|
|
9139
|
+
task: req.task,
|
|
9140
|
+
requestOrigin: lifecycle.requestOrigin,
|
|
9141
|
+
targetId,
|
|
9142
|
+
wireModelId,
|
|
9143
|
+
runtimeId,
|
|
9144
|
+
runtimeKind: "acp-delegation"
|
|
9145
|
+
} : null;
|
|
9146
|
+
if (queuedIdentity !== null) publishCapacityQueued(queuedIdentity, timing, null);
|
|
9147
|
+
let capacityLease;
|
|
9148
|
+
try {
|
|
9149
|
+
capacityLease = await admitAssignmentCapacity(req, "local", timing, null);
|
|
9150
|
+
} catch (error) {
|
|
9151
|
+
if (queuedIdentity !== null) publishCapacityAdmissionFailure(queuedIdentity, error);
|
|
9152
|
+
throw error;
|
|
9153
|
+
} finally {
|
|
9154
|
+
if (queuedIdentity !== null) pendingCapacity.delete(queuedIdentity.runId);
|
|
9155
|
+
}
|
|
9540
9156
|
const leaseSlot = createLeaseSlotGuard(capacityAdmission, capacityLease.leaseId, req.lineage !== void 0);
|
|
9541
9157
|
const ledgerRef = (() => {
|
|
9542
9158
|
try {
|
|
@@ -9705,8 +9321,10 @@ function createDispatchBundle(context, options) {
|
|
|
9705
9321
|
runIdForPermissionAudit = envelope.id;
|
|
9706
9322
|
lineage = lineageFor(req, envelope.id);
|
|
9707
9323
|
if (req.lineage === void 0) {
|
|
9708
|
-
|
|
9709
|
-
|
|
9324
|
+
if (capacityLease.assignmentId !== lineage.rootRunId) {
|
|
9325
|
+
capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
|
|
9326
|
+
await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
|
|
9327
|
+
}
|
|
9710
9328
|
leaseSlot.transferToAssignment();
|
|
9711
9329
|
}
|
|
9712
9330
|
identity = detectRunIdentity();
|
|
@@ -9730,16 +9348,18 @@ function createDispatchBundle(context, options) {
|
|
|
9730
9348
|
runtimeKind: "acp-delegation"
|
|
9731
9349
|
});
|
|
9732
9350
|
await ledgerRef.persist();
|
|
9733
|
-
|
|
9734
|
-
|
|
9735
|
-
|
|
9736
|
-
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9351
|
+
if (req.lineage !== void 0) {
|
|
9352
|
+
context.bus.emit(BusChannels.DispatchEnqueued, {
|
|
9353
|
+
runId: envelope.id,
|
|
9354
|
+
agentId: req.agentId,
|
|
9355
|
+
task: req.task,
|
|
9356
|
+
requestOrigin: lifecycle.requestOrigin,
|
|
9357
|
+
targetId,
|
|
9358
|
+
wireModelId,
|
|
9359
|
+
runtimeId,
|
|
9360
|
+
runtimeKind: "acp-delegation"
|
|
9361
|
+
});
|
|
9362
|
+
}
|
|
9743
9363
|
context.bus.emit(BusChannels.DispatchStarted, {
|
|
9744
9364
|
runId: envelope.id,
|
|
9745
9365
|
agentId: req.agentId,
|
|
@@ -10146,6 +9766,7 @@ function createDispatchBundle(context, options) {
|
|
|
10146
9766
|
throw new Error(`dispatch: invalid spec: ${validated.errors.join("; ")}`);
|
|
10147
9767
|
}
|
|
10148
9768
|
req = validation.restore(validated.spec);
|
|
9769
|
+
if (req.lineage === void 0 && req.runIdHint === void 0) req = { ...req, runIdHint: newRunId() };
|
|
10149
9770
|
let activeRouteObservation = null;
|
|
10150
9771
|
if (req.delegationAgentId === void 0) {
|
|
10151
9772
|
const recipe = agents.get(req.agentId);
|
|
@@ -10264,7 +9885,34 @@ function createDispatchBundle(context, options) {
|
|
|
10264
9885
|
},
|
|
10265
9886
|
shadow: () => observeShadowRoute(req, placed, settings)
|
|
10266
9887
|
});
|
|
10267
|
-
const
|
|
9888
|
+
const queuedIdentity = req.lineage === void 0 && req.runIdHint !== void 0 ? {
|
|
9889
|
+
runId: req.runIdHint,
|
|
9890
|
+
agentId: req.agentId,
|
|
9891
|
+
task: req.task,
|
|
9892
|
+
agentAudience: lifecycle.agentAudience,
|
|
9893
|
+
requestOrigin: lifecycle.requestOrigin,
|
|
9894
|
+
targetId: lifecycle.target.target.id,
|
|
9895
|
+
wireModelId: lifecycle.target.wireModelId,
|
|
9896
|
+
runtimeId: lifecycle.target.runtime.id,
|
|
9897
|
+
runtimeKind: lifecycle.runtimeKind,
|
|
9898
|
+
budget: lifecycle.budgetEnvelope,
|
|
9899
|
+
...endpoint !== null ? { endpoint: { key: endpoint.key, label: endpoint.label, limit: endpoint.limit } } : {},
|
|
9900
|
+
...placement !== null ? { node: placement.node.id } : {},
|
|
9901
|
+
...req.gate !== void 0 ? { gate: { role: req.gate.role, cycle: req.gate.cycle } } : {},
|
|
9902
|
+
...req.council !== void 0 ? { council: req.council } : {},
|
|
9903
|
+
...req.reroutes !== void 0 && req.reroutes.length > 0 ? { rerouteCount: req.reroutes.length } : {},
|
|
9904
|
+
...lifecycle.target.modelCapabilities !== void 0 && lifecycle.target.modelCapabilities !== null && lifecycle.target.modelCapabilities.contextWindow > 0 ? { contextWindow: lifecycle.target.modelCapabilities.contextWindow } : {}
|
|
9905
|
+
} : null;
|
|
9906
|
+
if (queuedIdentity !== null) publishCapacityQueued(queuedIdentity, timing, placement?.node ?? null);
|
|
9907
|
+
let capacityLease;
|
|
9908
|
+
try {
|
|
9909
|
+
capacityLease = await admitAssignmentCapacity(req, placement?.node.id ?? "local", timing, endpoint);
|
|
9910
|
+
} catch (error) {
|
|
9911
|
+
if (queuedIdentity !== null) publishCapacityAdmissionFailure(queuedIdentity, error);
|
|
9912
|
+
throw error;
|
|
9913
|
+
} finally {
|
|
9914
|
+
if (queuedIdentity !== null) pendingCapacity.delete(queuedIdentity.runId);
|
|
9915
|
+
}
|
|
10268
9916
|
const leaseSlot = createLeaseSlotGuard(capacityAdmission, capacityLease.leaseId, req.lineage !== void 0);
|
|
10269
9917
|
const ledgerRef = (() => {
|
|
10270
9918
|
try {
|
|
@@ -10462,6 +10110,7 @@ function createDispatchBundle(context, options) {
|
|
|
10462
10110
|
...ruleId !== null ? { ruleId } : {},
|
|
10463
10111
|
...policySource !== null ? { policySource } : {},
|
|
10464
10112
|
...typeof event.payload.timeoutMs === "number" ? { timeoutMs: event.payload.timeoutMs } : {},
|
|
10113
|
+
fallback: spec.escalation?.fallback ?? "deny",
|
|
10465
10114
|
escalation: true
|
|
10466
10115
|
});
|
|
10467
10116
|
}
|
|
@@ -10519,6 +10168,7 @@ function createDispatchBundle(context, options) {
|
|
|
10519
10168
|
decidedBy,
|
|
10520
10169
|
actionClass,
|
|
10521
10170
|
reason,
|
|
10171
|
+
...source === "timeout" ? { fallback: spec.escalation?.fallback ?? "deny" } : {},
|
|
10522
10172
|
...runIdForPermissionAudit !== null ? { requestedBy: runIdForPermissionAudit } : {}
|
|
10523
10173
|
});
|
|
10524
10174
|
}
|
|
@@ -10571,8 +10221,10 @@ function createDispatchBundle(context, options) {
|
|
|
10571
10221
|
runIdForPermissionAudit = envelope.id;
|
|
10572
10222
|
lineage = lineageFor(req, envelope.id);
|
|
10573
10223
|
if (req.lineage === void 0) {
|
|
10574
|
-
|
|
10575
|
-
|
|
10224
|
+
if (capacityLease.assignmentId !== lineage.rootRunId) {
|
|
10225
|
+
capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
|
|
10226
|
+
await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
|
|
10227
|
+
}
|
|
10576
10228
|
leaseSlot.transferToAssignment();
|
|
10577
10229
|
}
|
|
10578
10230
|
if (agentLedgerId !== null) {
|
|
@@ -10621,18 +10273,20 @@ function createDispatchBundle(context, options) {
|
|
|
10621
10273
|
...req.reroutes !== void 0 && req.reroutes.length > 0 ? { rerouteCount: req.reroutes.length } : {},
|
|
10622
10274
|
...lifecycle.target.modelCapabilities !== void 0 && lifecycle.target.modelCapabilities !== null && lifecycle.target.modelCapabilities.contextWindow > 0 ? { contextWindow: lifecycle.target.modelCapabilities.contextWindow } : {}
|
|
10623
10275
|
};
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
|
|
10276
|
+
if (req.lineage !== void 0) {
|
|
10277
|
+
context.bus.emit(BusChannels.DispatchEnqueued, {
|
|
10278
|
+
runId: envelope.id,
|
|
10279
|
+
agentId: req.agentId,
|
|
10280
|
+
task: req.task,
|
|
10281
|
+
agentAudience: lifecycle.agentAudience,
|
|
10282
|
+
requestOrigin: lifecycle.requestOrigin,
|
|
10283
|
+
targetId: lifecycle.target.target.id,
|
|
10284
|
+
wireModelId: lifecycle.target.wireModelId,
|
|
10285
|
+
runtimeId: lifecycle.target.runtime.id,
|
|
10286
|
+
runtimeKind: lifecycle.runtimeKind,
|
|
10287
|
+
...fleetIdentity
|
|
10288
|
+
});
|
|
10289
|
+
}
|
|
10636
10290
|
context.bus.emit(BusChannels.DispatchStarted, {
|
|
10637
10291
|
runId: envelope.id,
|
|
10638
10292
|
agentId: req.agentId,
|
|
@@ -10737,10 +10391,10 @@ function createDispatchBundle(context, options) {
|
|
|
10737
10391
|
const fleetGate = (() => {
|
|
10738
10392
|
if (req.fleetGateReceipt === void 0) return null;
|
|
10739
10393
|
try {
|
|
10740
|
-
const content =
|
|
10741
|
-
return { path: req.fleetGateReceipt.path, pathHash:
|
|
10394
|
+
const content = readFileSync11(resolvePath(lifecycle.cwd, req.fleetGateReceipt.path));
|
|
10395
|
+
return { path: req.fleetGateReceipt.path, pathHash: createHash7("sha256").update(content).digest("hex") };
|
|
10742
10396
|
} catch {
|
|
10743
|
-
return { path: req.fleetGateReceipt.path, pathHash:
|
|
10397
|
+
return { path: req.fleetGateReceipt.path, pathHash: createHash7("sha256").update("").digest("hex") };
|
|
10744
10398
|
}
|
|
10745
10399
|
})();
|
|
10746
10400
|
const ledgerContribution = (() => {
|
|
@@ -10995,18 +10649,7 @@ function createDispatchBundle(context, options) {
|
|
|
10995
10649
|
cwd: lifecycle.cwd,
|
|
10996
10650
|
networkAllowed: lifecycle.admission.allowedTools.includes(ToolNames.WebFetch),
|
|
10997
10651
|
observedRunEffects,
|
|
10998
|
-
filesystem:
|
|
10999
|
-
readFile(filePath) {
|
|
11000
|
-
try {
|
|
11001
|
-
return readFileSync12(filePath, "utf8");
|
|
11002
|
-
} catch {
|
|
11003
|
-
return null;
|
|
11004
|
-
}
|
|
11005
|
-
},
|
|
11006
|
-
pathExists(filePath) {
|
|
11007
|
-
return existsSync12(filePath);
|
|
11008
|
-
}
|
|
11009
|
-
}
|
|
10652
|
+
filesystem: nodeResultContractFilesystem()
|
|
11010
10653
|
});
|
|
11011
10654
|
const resultValidation = resultContract?.applicable === true ? resultContract.validation : null;
|
|
11012
10655
|
if (finalOutcome === "succeeded" && resultValidation?.conformance === "fail") {
|
|
@@ -11715,8 +11358,10 @@ function createDispatchBundle(context, options) {
|
|
|
11715
11358
|
});
|
|
11716
11359
|
return receipt;
|
|
11717
11360
|
}
|
|
11361
|
+
let journalBridge = null;
|
|
11718
11362
|
const extension = {
|
|
11719
11363
|
async start() {
|
|
11364
|
+
if (options?.journalRunEvents === true) journalBridge = attachRunEventJournalBridge(context.bus);
|
|
11720
11365
|
cleanupDispatchReservations({ startup: true, nowMs: now() });
|
|
11721
11366
|
ledger = openLedger();
|
|
11722
11367
|
try {
|
|
@@ -11768,6 +11413,8 @@ function createDispatchBundle(context, options) {
|
|
|
11768
11413
|
for (const ownerId of ownedReservations) rollbackDispatchReservation(ownerId, now());
|
|
11769
11414
|
ownedReservations.clear();
|
|
11770
11415
|
await Promise.allSettled([...assignmentWrites]);
|
|
11416
|
+
journalBridge?.stop();
|
|
11417
|
+
journalBridge = null;
|
|
11771
11418
|
}
|
|
11772
11419
|
};
|
|
11773
11420
|
function emitRunAborted(run, source) {
|
|
@@ -11788,6 +11435,26 @@ function createDispatchBundle(context, options) {
|
|
|
11788
11435
|
const running = [];
|
|
11789
11436
|
const totals = { ...finalizedTotals };
|
|
11790
11437
|
const costAmounts = [...finalizedCosts];
|
|
11438
|
+
for (const pending of pendingCapacity.values()) {
|
|
11439
|
+
const startedAt = pending.timing.queuedAt ?? pending.timing.requestedAt ?? new Date(tickNow).toISOString();
|
|
11440
|
+
running.push({
|
|
11441
|
+
runId: pending.identity.runId,
|
|
11442
|
+
agentId: pending.identity.agentId,
|
|
11443
|
+
...pending.identity.task !== void 0 ? { task: pending.identity.task } : {},
|
|
11444
|
+
...pending.identity.budget !== void 0 ? { budget: pending.identity.budget } : {},
|
|
11445
|
+
runtimeKind: pending.identity.runtimeKind,
|
|
11446
|
+
outcomePhase: "queued",
|
|
11447
|
+
heartbeat: "n/a",
|
|
11448
|
+
lineage: { parentRunId: null, rootRunId: pending.identity.runId, attempt: 0, depth: 0 },
|
|
11449
|
+
startedAt,
|
|
11450
|
+
elapsedMs: 0,
|
|
11451
|
+
timing: deriveRunPhaseDurations(pending.timing, startedAt, new Date(tickNow).toISOString()),
|
|
11452
|
+
tokens: { input: 0, output: 0, total: 0 },
|
|
11453
|
+
costUsd: 0,
|
|
11454
|
+
costProvenance: "unknown",
|
|
11455
|
+
node: pending.node === null ? null : { ...pending.node }
|
|
11456
|
+
});
|
|
11457
|
+
}
|
|
11791
11458
|
for (const run of active.values()) {
|
|
11792
11459
|
let heartbeat = "n/a";
|
|
11793
11460
|
if (run.heartbeatAt && Number.isFinite(heartbeatMonotonicAt(run.heartbeatAt))) {
|
|
@@ -11952,6 +11619,17 @@ function createDispatchBundle(context, options) {
|
|
|
11952
11619
|
},
|
|
11953
11620
|
abort(runId, reason) {
|
|
11954
11621
|
const rootRunId = assignmentRootFor(runId);
|
|
11622
|
+
const queued = pendingCapacity.get(rootRunId);
|
|
11623
|
+
if (queued !== void 0 && capacityAdmission.cancel(rootRunId)) {
|
|
11624
|
+
persistAssignment(cancelStoredAssignment(rootRunId), `${rootRunId}:cancel-queued`);
|
|
11625
|
+
context.bus.emit(BusChannels.RunAborted, {
|
|
11626
|
+
source: "dispatch_abort",
|
|
11627
|
+
runId: rootRunId,
|
|
11628
|
+
startedAt: null,
|
|
11629
|
+
elapsedMs: null,
|
|
11630
|
+
reason: reason?.detail ?? "operator abort while waiting for an endpoint slot"
|
|
11631
|
+
});
|
|
11632
|
+
}
|
|
11955
11633
|
const assignment = assignments.get(rootRunId);
|
|
11956
11634
|
if (assignment?.status === "running") {
|
|
11957
11635
|
assignments.cancel(assignment.id);
|
|
@@ -12052,12 +11730,12 @@ var DispatchManifest = {
|
|
|
12052
11730
|
|
|
12053
11731
|
// src/domains/dispatch/code-step-store.ts
|
|
12054
11732
|
init_esm_shims();
|
|
12055
|
-
import { join as
|
|
11733
|
+
import { join as join13 } from "node:path";
|
|
12056
11734
|
function codeStepDir(rootId) {
|
|
12057
|
-
return
|
|
11735
|
+
return join13(clioStateDir(), "code-steps", rootId);
|
|
12058
11736
|
}
|
|
12059
11737
|
function codeStepRecordPath(rootId, runId) {
|
|
12060
|
-
return
|
|
11738
|
+
return join13(codeStepDir(rootId), `${runId}.json`);
|
|
12061
11739
|
}
|
|
12062
11740
|
async function writeCodeStepRecord(rootId, record) {
|
|
12063
11741
|
const path2 = codeStepRecordPath(rootId, record.runId);
|
|
@@ -12068,7 +11746,7 @@ async function writeCodeStepRecord(rootId, record) {
|
|
|
12068
11746
|
|
|
12069
11747
|
// src/domains/dispatch/delegation-plan.ts
|
|
12070
11748
|
init_esm_shims();
|
|
12071
|
-
import { createHash as
|
|
11749
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
12072
11750
|
var DELEGATION_PROPOSAL_BRIEFING_MAX_BYTES = 12e3;
|
|
12073
11751
|
function buildDelegationProposalBriefing(proposals) {
|
|
12074
11752
|
const value = proposals.map((proposal) => `PROPOSAL ${proposal.agent}
|
|
@@ -12176,7 +11854,7 @@ function validateDelegationPlan(input) {
|
|
|
12176
11854
|
}
|
|
12177
11855
|
}
|
|
12178
11856
|
const plan = { tasks };
|
|
12179
|
-
return { ok: true, plan, hash:
|
|
11857
|
+
return { ok: true, plan, hash: createHash8("sha256").update(JSON.stringify(plan)).digest("hex") };
|
|
12180
11858
|
}
|
|
12181
11859
|
|
|
12182
11860
|
// src/domains/dispatch/execution-scheduler.ts
|
|
@@ -12604,9 +12282,125 @@ function gateFailureLines(output) {
|
|
|
12604
12282
|
|
|
12605
12283
|
// src/domains/dispatch/fleet-run.ts
|
|
12606
12284
|
init_esm_shims();
|
|
12607
|
-
import { createHash as
|
|
12608
|
-
import { readFileSync as
|
|
12609
|
-
import { join as
|
|
12285
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
12286
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
12287
|
+
import { join as join14 } from "node:path";
|
|
12288
|
+
|
|
12289
|
+
// src/domains/observability/cost.ts
|
|
12290
|
+
init_esm_shims();
|
|
12291
|
+
function emptyCostAggregate() {
|
|
12292
|
+
return { knownUsd: 0, hasEstimated: false, hasUnknown: false, allKnownFree: false, calls: 0 };
|
|
12293
|
+
}
|
|
12294
|
+
function costWasMeasured(cost) {
|
|
12295
|
+
return cost !== null && cost !== void 0 && cost.calls > 0;
|
|
12296
|
+
}
|
|
12297
|
+
function accumulateCostAmount(aggregate, amount, first) {
|
|
12298
|
+
return {
|
|
12299
|
+
knownUsd: aggregate.knownUsd + (amount.provenance === "unknown" ? 0 : amount.usd),
|
|
12300
|
+
hasEstimated: aggregate.hasEstimated || amount.provenance === "estimated",
|
|
12301
|
+
hasUnknown: aggregate.hasUnknown || amount.provenance === "unknown",
|
|
12302
|
+
allKnownFree: amount.provenance === "known_free" && (first || aggregate.allKnownFree),
|
|
12303
|
+
calls: aggregate.calls + 1
|
|
12304
|
+
};
|
|
12305
|
+
}
|
|
12306
|
+
function aggregateCostAmounts(amounts) {
|
|
12307
|
+
return amounts.reduce(
|
|
12308
|
+
(aggregate, amount, index) => accumulateCostAmount(aggregate, amount, index === 0),
|
|
12309
|
+
emptyCostAggregate()
|
|
12310
|
+
);
|
|
12311
|
+
}
|
|
12312
|
+
function formatUsdAmount(value) {
|
|
12313
|
+
if (!Number.isFinite(value) || value <= 0) return "$0.00";
|
|
12314
|
+
return value < 0.01 ? `$${value.toFixed(4)}` : `$${value.toFixed(2)}`;
|
|
12315
|
+
}
|
|
12316
|
+
function formatCostAggregate(cost) {
|
|
12317
|
+
if (!costWasMeasured(cost)) return null;
|
|
12318
|
+
if (cost.allKnownFree) return "$0.00 local";
|
|
12319
|
+
if (cost.hasUnknown) return cost.knownUsd > 0 ? `${formatUsdAmount(cost.knownUsd)} +?` : null;
|
|
12320
|
+
if (cost.hasEstimated) return `~${formatUsdAmount(cost.knownUsd)} est`;
|
|
12321
|
+
return formatUsdAmount(cost.knownUsd);
|
|
12322
|
+
}
|
|
12323
|
+
var COST_NOT_MEASURED = "not measured";
|
|
12324
|
+
function costAggregateForAmount(usd, provenance) {
|
|
12325
|
+
return aggregateCostAmounts([{ usd, provenance: normalizeCostProvenance(provenance) }]);
|
|
12326
|
+
}
|
|
12327
|
+
function renderCostAggregate(cost) {
|
|
12328
|
+
return formatCostAggregate(cost) ?? COST_NOT_MEASURED;
|
|
12329
|
+
}
|
|
12330
|
+
function renderCostAmount(usd, provenance) {
|
|
12331
|
+
return renderCostAggregate(costAggregateForAmount(usd, provenance));
|
|
12332
|
+
}
|
|
12333
|
+
function emptyBreakdown() {
|
|
12334
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoningTokens: 0, totalTokens: 0 };
|
|
12335
|
+
}
|
|
12336
|
+
function createCostTracker() {
|
|
12337
|
+
const log = [];
|
|
12338
|
+
let total = 0;
|
|
12339
|
+
const totals = emptyBreakdown();
|
|
12340
|
+
return {
|
|
12341
|
+
accumulate(providerId, attributedModelId, tokens, usd, breakdown, costProvenance, modelIdFacts, label) {
|
|
12342
|
+
const resolvedUsd = usd ?? 0;
|
|
12343
|
+
const provenance = normalizeCostProvenance(costProvenance);
|
|
12344
|
+
const input = breakdown?.input ?? 0;
|
|
12345
|
+
const output = breakdown?.output ?? 0;
|
|
12346
|
+
const cacheRead = breakdown?.cacheRead ?? 0;
|
|
12347
|
+
const cacheWrite = breakdown?.cacheWrite ?? 0;
|
|
12348
|
+
const reasoningTokens = breakdown?.reasoningTokens ?? 0;
|
|
12349
|
+
const apiCalls = breakdown?.apiCalls;
|
|
12350
|
+
log.push({
|
|
12351
|
+
providerId,
|
|
12352
|
+
attributedModelId,
|
|
12353
|
+
requestedModelIds: [...modelIdFacts?.requestedModelIds ?? [attributedModelId]],
|
|
12354
|
+
responseModelIdObservationCounts: modelIdFacts ? { ...modelIdFacts.responseModelIdObservationCounts } : {
|
|
12355
|
+
reportedCalls: 0,
|
|
12356
|
+
notReportedCalls: 0,
|
|
12357
|
+
notObservedCalls: apiCalls ?? 1,
|
|
12358
|
+
legacyDifferenceOnlyCalls: 0
|
|
12359
|
+
},
|
|
12360
|
+
tokens,
|
|
12361
|
+
usd: resolvedUsd,
|
|
12362
|
+
provenance,
|
|
12363
|
+
input,
|
|
12364
|
+
output,
|
|
12365
|
+
cacheRead,
|
|
12366
|
+
cacheWrite,
|
|
12367
|
+
reasoningTokens,
|
|
12368
|
+
...apiCalls !== void 0 ? { apiCalls } : {},
|
|
12369
|
+
...label !== void 0 ? { label } : {}
|
|
12370
|
+
});
|
|
12371
|
+
total += resolvedUsd;
|
|
12372
|
+
totals.input += input;
|
|
12373
|
+
totals.output += output;
|
|
12374
|
+
totals.cacheRead += cacheRead;
|
|
12375
|
+
totals.cacheWrite += cacheWrite;
|
|
12376
|
+
totals.reasoningTokens += reasoningTokens;
|
|
12377
|
+
totals.totalTokens += tokens;
|
|
12378
|
+
return resolvedUsd;
|
|
12379
|
+
},
|
|
12380
|
+
sessionTotal() {
|
|
12381
|
+
return total;
|
|
12382
|
+
},
|
|
12383
|
+
sessionCost() {
|
|
12384
|
+
return aggregateCostAmounts(log.map((entry) => ({ usd: entry.usd, provenance: entry.provenance })));
|
|
12385
|
+
},
|
|
12386
|
+
sessionTokens() {
|
|
12387
|
+
return { ...totals };
|
|
12388
|
+
},
|
|
12389
|
+
entries() {
|
|
12390
|
+
return log;
|
|
12391
|
+
},
|
|
12392
|
+
reset() {
|
|
12393
|
+
log.length = 0;
|
|
12394
|
+
total = 0;
|
|
12395
|
+
totals.input = 0;
|
|
12396
|
+
totals.output = 0;
|
|
12397
|
+
totals.cacheRead = 0;
|
|
12398
|
+
totals.cacheWrite = 0;
|
|
12399
|
+
totals.reasoningTokens = 0;
|
|
12400
|
+
totals.totalTokens = 0;
|
|
12401
|
+
}
|
|
12402
|
+
};
|
|
12403
|
+
}
|
|
12610
12404
|
|
|
12611
12405
|
// src/domains/dispatch/fleet-commit-attribution.ts
|
|
12612
12406
|
init_esm_shims();
|
|
@@ -12698,6 +12492,11 @@ function fleetGateCorrelation(subject, decider) {
|
|
|
12698
12492
|
);
|
|
12699
12493
|
return { agent, target, modelFamily: modelFamily2, runtime, node, independent };
|
|
12700
12494
|
}
|
|
12495
|
+
function fleetStepIntent(writes) {
|
|
12496
|
+
if (writes === void 0 || writes.length === 0) return null;
|
|
12497
|
+
const built = declaredScopeIntent({ relevantPaths: writes });
|
|
12498
|
+
return built.ok ? built.intent : null;
|
|
12499
|
+
}
|
|
12701
12500
|
function fleetPlanWaveIndex(plan, stepId) {
|
|
12702
12501
|
return plan.waves.findIndex((wave) => wave.includes(stepId));
|
|
12703
12502
|
}
|
|
@@ -12769,7 +12568,7 @@ async function executeFleetRun(input) {
|
|
|
12769
12568
|
for (const [stepId, replayedResult] of replayed) {
|
|
12770
12569
|
try {
|
|
12771
12570
|
const receipt = JSON.parse(
|
|
12772
|
-
|
|
12571
|
+
readFileSync12(join14(clioStateDir(), "receipts", `${replayedResult.terminalRunId}.json`), "utf8")
|
|
12773
12572
|
);
|
|
12774
12573
|
receiptsByStep.set(stepId, receipt);
|
|
12775
12574
|
} catch {
|
|
@@ -12790,6 +12589,9 @@ async function executeFleetRun(input) {
|
|
|
12790
12589
|
succeeded: true,
|
|
12791
12590
|
terminalRunId: replayedResult.terminalRunId,
|
|
12792
12591
|
costUsd: receiptsByStep.get(stepId)?.costUsd ?? 0,
|
|
12592
|
+
// A replay whose receipt no longer exists on disk has no cost claim at
|
|
12593
|
+
// all, which is `unknown` rather than a zero the projection invented.
|
|
12594
|
+
costProvenance: receiptsByStep.get(stepId)?.costProvenance ?? "unknown",
|
|
12793
12595
|
result: replayedResult
|
|
12794
12596
|
});
|
|
12795
12597
|
await fileStepAttempt(replayedResult.terminalRunId);
|
|
@@ -12859,11 +12661,13 @@ async function executeFleetRun(input) {
|
|
|
12859
12661
|
if (step.planParentId !== void 0 && parentReceipt === void 0) {
|
|
12860
12662
|
throw new Error(`fleet dynamic step '${step.id}' has no terminal plan-step receipt`);
|
|
12861
12663
|
}
|
|
12664
|
+
const stepIntent = fleetStepIntent(step.writes);
|
|
12862
12665
|
const request = {
|
|
12863
12666
|
agentId: step.agentId,
|
|
12864
12667
|
executionRole: step.executionRole,
|
|
12865
12668
|
task: step.task,
|
|
12866
12669
|
cwd: workspaceRoot,
|
|
12670
|
+
...stepIntent === null ? {} : { intent: stepIntent },
|
|
12867
12671
|
predecessorHandoffs: handoffs,
|
|
12868
12672
|
requestOrigin: "user",
|
|
12869
12673
|
lineage: {
|
|
@@ -12951,11 +12755,11 @@ async function executeFleetRun(input) {
|
|
|
12951
12755
|
if (step.gate !== void 0 && succeeded) {
|
|
12952
12756
|
let gateBytes = "";
|
|
12953
12757
|
try {
|
|
12954
|
-
gateBytes =
|
|
12758
|
+
gateBytes = readFileSync12(join14(workspaceRoot, step.gate.path), "utf8");
|
|
12955
12759
|
} catch {
|
|
12956
12760
|
gateBytes = "";
|
|
12957
12761
|
}
|
|
12958
|
-
gatePathHash =
|
|
12762
|
+
gatePathHash = createHash9("sha256").update(gateBytes).digest("hex");
|
|
12959
12763
|
const command = input.commands?.commands.get(step.gate.commandId);
|
|
12960
12764
|
if (gateBytes.length === 0 || command === void 0) {
|
|
12961
12765
|
stepSucceeded = false;
|
|
@@ -13007,11 +12811,12 @@ async function executeFleetRun(input) {
|
|
|
13007
12811
|
succeeded: stepSucceeded,
|
|
13008
12812
|
terminalRunId: receipt.runId,
|
|
13009
12813
|
costUsd: receipt.costUsd,
|
|
12814
|
+
costProvenance: receipt.costProvenance,
|
|
13010
12815
|
receipt,
|
|
13011
12816
|
...failureReason !== void 0 ? { failureReason } : {}
|
|
13012
12817
|
});
|
|
13013
12818
|
notice(
|
|
13014
|
-
`step ${step.id} ${step.agentId}: ${stepSucceeded ? "succeeded" : "failed"}${failureReason !== void 0 ? ` reason=${failureReason}` : ""} assignment=${handle.runId} terminal-run=${receipt.runId} cost
|
|
12819
|
+
`step ${step.id} ${step.agentId}: ${stepSucceeded ? "succeeded" : "failed"}${failureReason !== void 0 ? ` reason=${failureReason}` : ""} assignment=${handle.runId} terminal-run=${receipt.runId} cost=${renderCostAmount(receipt.costUsd, receipt.costProvenance)}`
|
|
13015
12820
|
);
|
|
13016
12821
|
return {
|
|
13017
12822
|
stepId: step.id,
|
|
@@ -13070,6 +12875,8 @@ async function executeFleetRun(input) {
|
|
|
13070
12875
|
succeeded: outcome.report.passed,
|
|
13071
12876
|
terminalRunId: outcome.record.runId,
|
|
13072
12877
|
costUsd: 0,
|
|
12878
|
+
// No model ran, so nothing needed pricing. This zero was observed.
|
|
12879
|
+
costProvenance: "known_free",
|
|
13073
12880
|
codeStep: outcome.record,
|
|
13074
12881
|
recordPath
|
|
13075
12882
|
});
|
|
@@ -13193,6 +13000,9 @@ async function executeFleetRun(input) {
|
|
|
13193
13000
|
result,
|
|
13194
13001
|
receipts,
|
|
13195
13002
|
totalCostUsd: receipts.reduce((sum, receipt) => sum + receipt.costUsd, 0),
|
|
13003
|
+
totalCost: aggregateCostAmounts(
|
|
13004
|
+
receipts.map((receipt) => ({ usd: receipt.costUsd, provenance: receipt.costProvenance }))
|
|
13005
|
+
),
|
|
13196
13006
|
requiredStepCount: required.length,
|
|
13197
13007
|
succeededStepCount,
|
|
13198
13008
|
resolvedLoopCount: result.loops.length - failedLoops.length,
|
|
@@ -13420,6 +13230,37 @@ init_esm_shims();
|
|
|
13420
13230
|
// src/domains/evidence/types.ts
|
|
13421
13231
|
init_esm_shims();
|
|
13422
13232
|
var EVIDENCE_VERSION = 1;
|
|
13233
|
+
var EVIDENCE_TAGS = [
|
|
13234
|
+
"audit-linked",
|
|
13235
|
+
"audit-missing",
|
|
13236
|
+
"best-effort-link",
|
|
13237
|
+
"timeout",
|
|
13238
|
+
"context-overflow",
|
|
13239
|
+
"provider-transient",
|
|
13240
|
+
"missing-dependency",
|
|
13241
|
+
"wrong-runtime",
|
|
13242
|
+
"proxy-validation",
|
|
13243
|
+
"no-validation",
|
|
13244
|
+
"destructive-cleanup",
|
|
13245
|
+
"blocked-tool",
|
|
13246
|
+
"escalation",
|
|
13247
|
+
"external-bypass",
|
|
13248
|
+
"external-approximation",
|
|
13249
|
+
"independent-review",
|
|
13250
|
+
"context-provenance",
|
|
13251
|
+
"completion-evidence",
|
|
13252
|
+
"receipt-integrity",
|
|
13253
|
+
"receipt-retired",
|
|
13254
|
+
"protected-artifact",
|
|
13255
|
+
"tool-loop",
|
|
13256
|
+
"test-failure",
|
|
13257
|
+
"build-failure",
|
|
13258
|
+
"cwd-missing",
|
|
13259
|
+
"session-linked",
|
|
13260
|
+
"session-missing",
|
|
13261
|
+
"auth-failure",
|
|
13262
|
+
"unknown"
|
|
13263
|
+
];
|
|
13423
13264
|
var FAILURE_CAUSE_TAG_ORDER = [
|
|
13424
13265
|
"timeout",
|
|
13425
13266
|
"auth-failure",
|
|
@@ -13484,7 +13325,7 @@ function latestGateDecisionForRun(decisions, runId) {
|
|
|
13484
13325
|
// src/domains/evidence/store.ts
|
|
13485
13326
|
init_esm_shims();
|
|
13486
13327
|
import { readdir, readFile } from "node:fs/promises";
|
|
13487
|
-
import { join as
|
|
13328
|
+
import { join as join15 } from "node:path";
|
|
13488
13329
|
var EVIDENCE_FILES = [
|
|
13489
13330
|
"overview.json",
|
|
13490
13331
|
"transcript.md",
|
|
@@ -13500,11 +13341,11 @@ var EVIDENCE_FILES = [
|
|
|
13500
13341
|
"findings.md"
|
|
13501
13342
|
];
|
|
13502
13343
|
function evidenceRoot(dataDir) {
|
|
13503
|
-
return
|
|
13344
|
+
return join15(dataDir, "evidence");
|
|
13504
13345
|
}
|
|
13505
13346
|
function evidenceDirectory(dataDir, evidenceId) {
|
|
13506
13347
|
assertSafeId(evidenceId, "evidence");
|
|
13507
|
-
return
|
|
13348
|
+
return join15(evidenceRoot(dataDir), evidenceId);
|
|
13508
13349
|
}
|
|
13509
13350
|
var EvidenceNotFoundError = class extends Error {
|
|
13510
13351
|
constructor(evidenceId) {
|
|
@@ -13520,7 +13361,7 @@ function isMissingFile(error) {
|
|
|
13520
13361
|
async function loadEvidenceOverview(dataDir, evidenceId) {
|
|
13521
13362
|
let raw;
|
|
13522
13363
|
try {
|
|
13523
|
-
raw = await readFile(
|
|
13364
|
+
raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "overview.json"), "utf8");
|
|
13524
13365
|
} catch (error) {
|
|
13525
13366
|
if (isMissingFile(error)) throw new EvidenceNotFoundError(evidenceId);
|
|
13526
13367
|
throw error;
|
|
@@ -13532,7 +13373,7 @@ async function inspectEvidence(dataDir, evidenceId) {
|
|
|
13532
13373
|
const overview = await loadEvidenceOverview(dataDir, evidenceId);
|
|
13533
13374
|
let findingsRaw;
|
|
13534
13375
|
try {
|
|
13535
|
-
findingsRaw = await readFile(
|
|
13376
|
+
findingsRaw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "findings.json"), "utf8");
|
|
13536
13377
|
} catch (error) {
|
|
13537
13378
|
if (isMissingFile(error)) throw new Error(`evidence artifact ${evidenceId} is missing findings.json`);
|
|
13538
13379
|
throw error;
|
|
@@ -13544,7 +13385,7 @@ async function inspectEvidence(dataDir, evidenceId) {
|
|
|
13544
13385
|
async function loadEvidenceTrustStatus(dataDir, evidenceId) {
|
|
13545
13386
|
let raw;
|
|
13546
13387
|
try {
|
|
13547
|
-
raw = await readFile(
|
|
13388
|
+
raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "trust-status.json"), "utf8");
|
|
13548
13389
|
} catch (error) {
|
|
13549
13390
|
if (isMissingFile(error)) {
|
|
13550
13391
|
return { version: 1, evidenceId, projection: "historical_format", runs: [] };
|
|
@@ -13577,7 +13418,7 @@ async function loadEvidenceTrustStatus(dataDir, evidenceId) {
|
|
|
13577
13418
|
async function loadEvidenceRunProvenance(dataDir, evidenceId) {
|
|
13578
13419
|
let raw;
|
|
13579
13420
|
try {
|
|
13580
|
-
raw = await readFile(
|
|
13421
|
+
raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "receipt.json"), "utf8");
|
|
13581
13422
|
} catch (error) {
|
|
13582
13423
|
const err = error;
|
|
13583
13424
|
if (err.code === "ENOENT") return [];
|
|
@@ -13631,6 +13472,7 @@ function parseOverview(value, source) {
|
|
|
13631
13472
|
const totals = readTotals(value.totals, `${source}.totals`);
|
|
13632
13473
|
const tags = readStringArray(value, source, "tags");
|
|
13633
13474
|
const files = readStringArray(value, source, "files");
|
|
13475
|
+
const redactionCount = typeof value.redactionCount === "number" && Number.isFinite(value.redactionCount) ? value.redactionCount : void 0;
|
|
13634
13476
|
return {
|
|
13635
13477
|
version: 1,
|
|
13636
13478
|
evidenceId,
|
|
@@ -13649,7 +13491,8 @@ function parseOverview(value, source) {
|
|
|
13649
13491
|
modelIds,
|
|
13650
13492
|
totals,
|
|
13651
13493
|
tags,
|
|
13652
|
-
files
|
|
13494
|
+
files,
|
|
13495
|
+
...redactionCount === void 0 ? {} : { redactionCount }
|
|
13653
13496
|
};
|
|
13654
13497
|
}
|
|
13655
13498
|
function parseFindingsFile(value, source) {
|
|
@@ -14149,22 +13992,22 @@ function finding(index, severity, tag, runId, message) {
|
|
|
14149
13992
|
}
|
|
14150
13993
|
async function writeEvidenceFiles(directory, overview, runSources, findings, sessionLinks, auditLinks, toolEventRows, gateDecisions, trustStatus, protectedArtifacts, transcript) {
|
|
14151
13994
|
await mkdir(directory, { recursive: true });
|
|
14152
|
-
await writeJson(
|
|
13995
|
+
await writeJson(join16(directory, "overview.json"), overview);
|
|
14153
13996
|
await writeFile(
|
|
14154
|
-
|
|
13997
|
+
join16(directory, "transcript.md"),
|
|
14155
13998
|
transcript ?? renderTranscript(overview, runSources, sessionLinks, trustStatus),
|
|
14156
13999
|
"utf8"
|
|
14157
14000
|
);
|
|
14158
|
-
await writeJsonl(
|
|
14159
|
-
await writeJsonl(
|
|
14160
|
-
await writeJsonl(
|
|
14161
|
-
await writeJsonl(
|
|
14162
|
-
await writeJson(
|
|
14163
|
-
await writeJson(
|
|
14164
|
-
await writeJson(
|
|
14165
|
-
await writeJson(
|
|
14166
|
-
await writeJson(
|
|
14167
|
-
await writeFile(
|
|
14001
|
+
await writeJsonl(join16(directory, "trace.raw.jsonl"), rawTraceRows(runSources));
|
|
14002
|
+
await writeJsonl(join16(directory, "trace.cleaned.jsonl"), cleanedTraceRows(runSources, findings, toolEventRows));
|
|
14003
|
+
await writeJsonl(join16(directory, "tool-events.jsonl"), toolEventRows);
|
|
14004
|
+
await writeJsonl(join16(directory, "audit-linked.jsonl"), auditLinks.rows);
|
|
14005
|
+
await writeJson(join16(directory, "receipt.json"), receiptsFile(runSources));
|
|
14006
|
+
await writeJson(join16(directory, "gate-decisions.json"), gateDecisions);
|
|
14007
|
+
await writeJson(join16(directory, "trust-status.json"), trustStatus);
|
|
14008
|
+
await writeJson(join16(directory, "protected-artifacts.json"), protectedArtifacts);
|
|
14009
|
+
await writeJson(join16(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
|
|
14010
|
+
await writeFile(join16(directory, "findings.md"), renderEvidenceFindingsMarkdown(findings, trustStatus), "utf8");
|
|
14168
14011
|
}
|
|
14169
14012
|
function rawTraceRows(runSources) {
|
|
14170
14013
|
const rows = [];
|
|
@@ -14842,7 +14685,7 @@ function axisFindings(offset, source, status) {
|
|
|
14842
14685
|
return out;
|
|
14843
14686
|
}
|
|
14844
14687
|
async function readRunLedger(stateDir) {
|
|
14845
|
-
const target =
|
|
14688
|
+
const target = join16(stateDir, "runs.json");
|
|
14846
14689
|
let raw;
|
|
14847
14690
|
try {
|
|
14848
14691
|
raw = await readFile2(target, "utf8");
|
|
@@ -14863,7 +14706,7 @@ function selectRunEnvelopes(ledger, source) {
|
|
|
14863
14706
|
});
|
|
14864
14707
|
}
|
|
14865
14708
|
async function readReceipt(stateDir, envelope) {
|
|
14866
|
-
const receiptPath = envelope.receiptPath ??
|
|
14709
|
+
const receiptPath = envelope.receiptPath ?? join16(stateDir, "receipts", `${envelope.id}.json`);
|
|
14867
14710
|
let raw;
|
|
14868
14711
|
try {
|
|
14869
14712
|
raw = await readFile2(receiptPath, "utf8");
|
|
@@ -15152,7 +14995,7 @@ function sanitizeEvidenceId(value) {
|
|
|
15152
14995
|
// src/domains/evidence/eval.ts
|
|
15153
14996
|
init_esm_shims();
|
|
15154
14997
|
import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
15155
|
-
import { join as
|
|
14998
|
+
import { join as join17 } from "node:path";
|
|
15156
14999
|
|
|
15157
15000
|
// src/domains/eval/index.ts
|
|
15158
15001
|
init_esm_shims();
|
|
@@ -15353,19 +15196,19 @@ async function writeEvalEvidenceFiles(directory, artifact, overview, findings, t
|
|
|
15353
15196
|
};
|
|
15354
15197
|
const redactedArtifact = redactArtifactForStorage(artifact);
|
|
15355
15198
|
await mkdir2(directory, { recursive: true });
|
|
15356
|
-
await writeJson2(
|
|
15357
|
-
await writeFile2(
|
|
15358
|
-
await writeJsonl2(
|
|
15359
|
-
await writeJsonl2(
|
|
15360
|
-
await writeJsonl2(
|
|
15361
|
-
await writeJsonl2(
|
|
15362
|
-
await writeJson2(
|
|
15363
|
-
await writeJson2(
|
|
15364
|
-
await writeJson2(
|
|
15365
|
-
await writeJson2(
|
|
15366
|
-
await writeJson2(
|
|
15367
|
-
await writeJson2(
|
|
15368
|
-
await writeFile2(
|
|
15199
|
+
await writeJson2(join17(directory, "overview.json"), overview);
|
|
15200
|
+
await writeFile2(join17(directory, "transcript.md"), renderEvalTranscript(redactedArtifact, overview), "utf8");
|
|
15201
|
+
await writeJsonl2(join17(directory, "trace.raw.jsonl"), rawEvalTraceRows(redactedArtifact));
|
|
15202
|
+
await writeJsonl2(join17(directory, "trace.cleaned.jsonl"), cleanedEvalTraceRows(redactedArtifact, findings));
|
|
15203
|
+
await writeJsonl2(join17(directory, "tool-events.jsonl"), redactArtifactForStorage(toolEventRows));
|
|
15204
|
+
await writeJsonl2(join17(directory, "audit-linked.jsonl"), linkedRuns.auditRows);
|
|
15205
|
+
await writeJson2(join17(directory, "receipt.json"), receiptsFile2);
|
|
15206
|
+
await writeJson2(join17(directory, "gate-decisions.json"), gateDecisions);
|
|
15207
|
+
await writeJson2(join17(directory, "trust-status.json"), trustStatus);
|
|
15208
|
+
await writeJson2(join17(directory, "protected-artifacts.json"), emptyProtected);
|
|
15209
|
+
await writeJson2(join17(directory, "eval-result.json"), redactedArtifact);
|
|
15210
|
+
await writeJson2(join17(directory, "findings.json"), findingsFile(overview.evidenceId, [...findings]));
|
|
15211
|
+
await writeFile2(join17(directory, "findings.md"), renderEvidenceFindingsMarkdown(findings, trustStatus), "utf8");
|
|
15369
15212
|
}
|
|
15370
15213
|
function rawEvalTraceRows(artifact) {
|
|
15371
15214
|
return artifact.results.map((result) => ({
|
|
@@ -15506,7 +15349,7 @@ async function linkEvalRuns(stateDir, artifact) {
|
|
|
15506
15349
|
}
|
|
15507
15350
|
async function readRunLedger2(stateDir) {
|
|
15508
15351
|
try {
|
|
15509
|
-
const raw = await readFile3(
|
|
15352
|
+
const raw = await readFile3(join17(stateDir, "runs.json"), "utf8");
|
|
15510
15353
|
const parsed = JSON.parse(raw);
|
|
15511
15354
|
return Array.isArray(parsed) ? parsed.filter(isRecord12) : [];
|
|
15512
15355
|
} catch {
|
|
@@ -15517,7 +15360,7 @@ function evalRunMatches(artifact, envelope) {
|
|
|
15517
15360
|
return artifact.results.some((result) => result.runId === envelope.id);
|
|
15518
15361
|
}
|
|
15519
15362
|
async function readReceiptForRun(stateDir, envelope) {
|
|
15520
|
-
const path2 = envelope.receiptPath ??
|
|
15363
|
+
const path2 = envelope.receiptPath ?? join17(stateDir, "receipts", `${envelope.id}.json`);
|
|
15521
15364
|
try {
|
|
15522
15365
|
const parsed = JSON.parse(await readFile3(path2, "utf8"));
|
|
15523
15366
|
return isRecord12(parsed) ? parsed : null;
|
|
@@ -15546,7 +15389,7 @@ async function countSessionEntries(stateDir, sessionIds) {
|
|
|
15546
15389
|
return count;
|
|
15547
15390
|
}
|
|
15548
15391
|
async function findSessionLedgerPath(stateDir, sessionId) {
|
|
15549
|
-
const root =
|
|
15392
|
+
const root = join17(stateDir, "sessions");
|
|
15550
15393
|
let cwdHashes;
|
|
15551
15394
|
try {
|
|
15552
15395
|
cwdHashes = await readdir2(root);
|
|
@@ -15554,7 +15397,7 @@ async function findSessionLedgerPath(stateDir, sessionId) {
|
|
|
15554
15397
|
return null;
|
|
15555
15398
|
}
|
|
15556
15399
|
for (const cwdHash of cwdHashes) {
|
|
15557
|
-
const path2 =
|
|
15400
|
+
const path2 = join17(root, cwdHash, sessionId, "current.jsonl");
|
|
15558
15401
|
try {
|
|
15559
15402
|
await readFile3(path2, "utf8");
|
|
15560
15403
|
return path2;
|
|
@@ -15564,7 +15407,7 @@ async function findSessionLedgerPath(stateDir, sessionId) {
|
|
|
15564
15407
|
return null;
|
|
15565
15408
|
}
|
|
15566
15409
|
async function linkedEvalAuditRows(stateDir, runIds, artifact) {
|
|
15567
|
-
const root =
|
|
15410
|
+
const root = join17(stateDir, "audit");
|
|
15568
15411
|
let files;
|
|
15569
15412
|
try {
|
|
15570
15413
|
files = await readdir2(root);
|
|
@@ -15573,7 +15416,7 @@ async function linkedEvalAuditRows(stateDir, runIds, artifact) {
|
|
|
15573
15416
|
}
|
|
15574
15417
|
const rows = [];
|
|
15575
15418
|
for (const file of files.filter((name) => name.endsWith(".jsonl")).sort(compareCodepoints)) {
|
|
15576
|
-
const raw = await readFile3(
|
|
15419
|
+
const raw = await readFile3(join17(root, file), "utf8").catch(() => "");
|
|
15577
15420
|
const lines = raw.split("\n");
|
|
15578
15421
|
for (let index = 0; index < lines.length; index += 1) {
|
|
15579
15422
|
const line = lines[index];
|
|
@@ -15684,12 +15527,12 @@ function canonicalJson3(value) {
|
|
|
15684
15527
|
throw new Error(`response schema digest cannot represent ${typeof value}`);
|
|
15685
15528
|
}
|
|
15686
15529
|
function canonicalResponseSchemaDigest(schema) {
|
|
15687
|
-
return
|
|
15530
|
+
return createHash10("sha256").update(canonicalJson3(schema), "utf8").digest("hex");
|
|
15688
15531
|
}
|
|
15689
15532
|
function typedValidationFactsFromToolStats(toolStats) {
|
|
15690
15533
|
return toolStats.filter((stat) => stat.tool === "verify" && stat.count > 0).map((stat) => ({
|
|
15691
15534
|
sourceId: "tool:verify",
|
|
15692
|
-
validatorDigest:
|
|
15535
|
+
validatorDigest: createHash10("sha256").update(canonicalJson3(stat), "utf8").digest("hex"),
|
|
15693
15536
|
passed: stat.ok === stat.count && stat.errors === 0 && stat.blocked === 0
|
|
15694
15537
|
}));
|
|
15695
15538
|
}
|
|
@@ -15812,14 +15655,13 @@ export {
|
|
|
15812
15655
|
createStdioServerTransport,
|
|
15813
15656
|
ACP_USAGE_META_KEY,
|
|
15814
15657
|
ACP_SESSION_META_KEY,
|
|
15658
|
+
ACP_AGENT_META_KEY,
|
|
15815
15659
|
ACP_MAX_STRING_BYTES,
|
|
15816
15660
|
ACP_MAX_RAW_RECORD_BYTES,
|
|
15817
15661
|
ACP_MAX_CHUNK_BYTES,
|
|
15818
15662
|
ACP_MAX_TOOL_CALL_ID_BYTES,
|
|
15819
15663
|
compile,
|
|
15820
15664
|
compileWorker,
|
|
15821
|
-
WORKER_OUTPUT_MAX_BYTES,
|
|
15822
|
-
durableAssistantTextFromEvent,
|
|
15823
15665
|
setCapacityDraining,
|
|
15824
15666
|
capacityDrain,
|
|
15825
15667
|
capacityLeaseUsage,
|
|
@@ -15829,20 +15671,20 @@ export {
|
|
|
15829
15671
|
renderDispatchReviewerTask,
|
|
15830
15672
|
createRunReceiptQuality,
|
|
15831
15673
|
UNVERIFIABLE_RECEIPT_VERIFICATION,
|
|
15832
|
-
|
|
15833
|
-
|
|
15834
|
-
|
|
15835
|
-
stagePendingGateDecision,
|
|
15836
|
-
resolvePendingGateDecision,
|
|
15837
|
-
materializePendingGateDecision,
|
|
15838
|
-
finalizePendingGateDecision,
|
|
15839
|
-
readPendingGateDecisions,
|
|
15840
|
-
preflightPendingGateDecisionMaterialization,
|
|
15841
|
-
preparePendingGateDecisionRecovery,
|
|
15842
|
-
readGateDecisionArtifacts,
|
|
15674
|
+
assistantTextFromEvent,
|
|
15675
|
+
receiptResponseModelIdObservationLabel,
|
|
15676
|
+
createDispatchRunEventRegistry,
|
|
15843
15677
|
readFleetRun,
|
|
15678
|
+
listFleetRuns,
|
|
15844
15679
|
openLedger,
|
|
15845
15680
|
executePlan,
|
|
15681
|
+
aggregateCostAmounts,
|
|
15682
|
+
formatCostAggregate,
|
|
15683
|
+
COST_NOT_MEASURED,
|
|
15684
|
+
costAggregateForAmount,
|
|
15685
|
+
renderCostAggregate,
|
|
15686
|
+
renderCostAmount,
|
|
15687
|
+
createCostTracker,
|
|
15846
15688
|
planFleetResume,
|
|
15847
15689
|
executeFleetRun,
|
|
15848
15690
|
DispatchDomainModule,
|
|
@@ -15850,14 +15692,16 @@ export {
|
|
|
15850
15692
|
extractRunProvenance,
|
|
15851
15693
|
provenanceTranscriptLines,
|
|
15852
15694
|
provenanceCompactSuffix,
|
|
15695
|
+
EVIDENCE_TAGS,
|
|
15853
15696
|
FAILURE_CAUSE_TAGS,
|
|
15854
15697
|
evidenceDirectory,
|
|
15855
15698
|
EvidenceNotFoundError,
|
|
15856
15699
|
inspectEvidence,
|
|
15700
|
+
loadEvidenceTrustStatus,
|
|
15857
15701
|
loadEvidenceRunProvenance,
|
|
15858
15702
|
listEvidenceOverviews,
|
|
15859
15703
|
buildEvidence,
|
|
15860
15704
|
summarizeEvalResults,
|
|
15861
15705
|
buildEvalEvidence
|
|
15862
15706
|
};
|
|
15863
|
-
//# sourceMappingURL=chunk-
|
|
15707
|
+
//# sourceMappingURL=chunk-BUMFYQFY.js.map
|