@iowarp/clio-coder 0.3.8 → 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 +102 -0
- package/NOTICE +33 -0
- package/README.md +12 -3
- package/dist/{acp-U67UHUK2.js → acp-G5WJBNCT.js} +13 -12
- package/dist/{agents-YU6SGALZ.js → agents-FMV2Q5G4.js} +41 -36
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-5ZPJOIVG.js → auth-3IDSJEIK.js} +18 -18
- package/dist/{builtins-C6JMZVV6.js → builtins-XCZWXSC7.js} +5 -5
- package/dist/{chunk-IFBNV6H6.js → chunk-2ANTL7MR.js} +3 -3
- package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
- package/dist/{chunk-XWSF374K.js → chunk-2OQE55CK.js} +3 -3
- package/dist/{chunk-5H3GB5BO.js → chunk-32KWKNSF.js} +8 -384
- package/dist/{chunk-KTYTFRMB.js → chunk-36EJLSQQ.js} +34 -36
- package/dist/{chunk-FHJEP5SW.js → chunk-3BT2XMV4.js} +19 -13
- package/dist/chunk-3DPEIQKN.js +113 -0
- package/dist/{chunk-GU2UIAFZ.js → chunk-3URVFKWK.js} +7 -7
- package/dist/{chunk-WEH5XRJQ.js → chunk-3XML7CDN.js} +3 -3
- package/dist/chunk-42FMPA75.js +101 -0
- package/dist/{chunk-A2NJGIB3.js → chunk-5LXZXPKX.js} +2 -2
- package/dist/{chunk-VCBR6CU7.js → chunk-5PSMVOLM.js} +2 -2
- package/dist/{chunk-NMPKI6XL.js → chunk-6DB53AJS.js} +203 -25
- package/dist/{chunk-3BINW3FP.js → chunk-76ONBSIA.js} +2 -2
- package/dist/{chunk-26LEYJZH.js → chunk-7MCTRUCE.js} +2 -2
- package/dist/{chunk-TYPGUK6W.js → chunk-AB44T6BB.js} +111 -5
- package/dist/{chunk-K4XHGFR5.js → chunk-B7OBL7PK.js} +317 -721
- package/dist/{chunk-B5CSFE7B.js → chunk-BBVJUZHB.js} +2 -2
- package/dist/{chunk-EQ63NRB7.js → chunk-BBVYXMFO.js} +2 -2
- package/dist/{chunk-ZVJ5BLO2.js → chunk-BKFJHQCA.js} +154 -16
- package/dist/chunk-BKFM6EJV.js +462 -0
- package/dist/chunk-BMS5RKQY.js +27 -0
- package/dist/{chunk-ZNLWCMVZ.js → chunk-BPKCPIL7.js} +2 -2
- package/dist/{chunk-TLQJPP24.js → chunk-BUMFYQFY.js} +1394 -1349
- package/dist/{chunk-BNAZZHFG.js → chunk-BYP5D4HI.js} +1 -1
- package/dist/chunk-C2LTL2W6.js +2447 -0
- package/dist/{chunk-ME6CCNFO.js → chunk-CODPRO7Q.js} +8 -8
- package/dist/{chunk-E77JEWSD.js → chunk-CTJ4RNAA.js} +7 -37
- package/dist/{chunk-ODFEOB4F.js → chunk-CY6FY24N.js} +26 -8
- package/dist/{chunk-7RFXX52T.js → chunk-DQITNCXG.js} +642 -172
- package/dist/{chunk-TTHACPOM.js → chunk-DYJP44XW.js} +578 -117
- package/dist/{chunk-2HFZQUHL.js → chunk-F4CKPOEQ.js} +18 -8
- package/dist/{chunk-DGSYXYMX.js → chunk-FEFIFZTL.js} +3 -3
- package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
- package/dist/{chunk-MV3K5QF2.js → chunk-GCSMB2KY.js} +2 -2
- package/dist/chunk-GKF55TAZ.js +391 -0
- package/dist/{chunk-VWZOAB7K.js → chunk-GR5G2PVF.js} +9 -8
- package/dist/{chunk-4DGYLA73.js → chunk-GXNLGKAB.js} +80 -9
- package/dist/chunk-HHV2GANA.js +88 -0
- package/dist/{chunk-IIZWH4XA.js → chunk-HI63TFOG.js} +5 -4
- package/dist/{chunk-WLFILSD5.js → chunk-HJJTYUHX.js} +113 -83
- package/dist/{chunk-TT36MB5S.js → chunk-HLW2MRKE.js} +3 -1
- package/dist/{chunk-PMDBGQSJ.js → chunk-HWHKMHUA.js} +7 -7
- package/dist/chunk-HZHHCK24.js +1631 -0
- package/dist/{chunk-WSB3FPX7.js → chunk-I5VEOC6I.js} +39 -143
- package/dist/chunk-IBEBSCYA.js +564 -0
- package/dist/chunk-IQ7KR472.js +362 -0
- package/dist/{chunk-A3WNZD3P.js → chunk-J4W7KFM7.js} +949 -972
- package/dist/{chunk-TB5666IT.js → chunk-JDG2WCRO.js} +5 -5
- package/dist/{chunk-N22QMJKY.js → chunk-K5C3NCBD.js} +4 -4
- package/dist/{chunk-CGKSTWHD.js → chunk-K6BSR66V.js} +2 -1
- package/dist/{chunk-5C3AQNDW.js → chunk-KFZI4NIL.js} +216 -38
- package/dist/chunk-KMVISBZR.js +132 -0
- package/dist/{chunk-WXY7KU3G.js → chunk-LDQ2ZF2M.js} +2 -2
- package/dist/{chunk-XN3L4EYL.js → chunk-LQ3DZAMX.js} +3 -3
- package/dist/{chunk-U6MBIEMB.js → chunk-LY4S7GJC.js} +173 -144
- package/dist/{chunk-4SPRNWDE.js → chunk-MLKNTWH2.js} +19 -19
- package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
- package/dist/chunk-NEKRRTYW.js +56 -0
- package/dist/{chunk-SPULKLCF.js → chunk-NHCZP4K7.js} +3 -3
- package/dist/chunk-NHLBIGRH.js +1506 -0
- package/dist/chunk-NQQH3YT7.js +302 -0
- package/dist/chunk-NYS75XW5.js +15 -0
- package/dist/{chunk-GN57SG4G.js → chunk-O4XIVISU.js} +10 -8
- package/dist/{chunk-EMYUUSFG.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-J3YUBZWY.js → chunk-QBJA7R7N.js} +62 -6
- package/dist/chunk-QDC3K2U3.js +262 -0
- package/dist/{chunk-2HEJ2F35.js → chunk-QLFS5GO2.js} +22 -10
- package/dist/{chunk-7RGZWPB6.js → chunk-QLL7ILRG.js} +95 -32
- package/dist/{chunk-YS5VLNH5.js → chunk-QREDIESB.js} +6 -6
- package/dist/chunk-QSNYB6ZV.js +195 -0
- package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
- package/dist/chunk-RKKLTLYB.js +45 -0
- package/dist/{chunk-P43ETTHK.js → chunk-SJ5ZKQ4S.js} +2 -2
- package/dist/{chunk-GPIEI3LY.js → chunk-SP2RXXYO.js} +6 -54
- package/dist/chunk-SUCTJL45.js +45 -0
- package/dist/{chunk-DYIM5TJT.js → chunk-SUW5DORT.js} +263 -7
- package/dist/chunk-T56WDKA5.js +183 -0
- package/dist/chunk-TVHHYFHE.js +255 -0
- package/dist/{chunk-FJ3H4MN5.js → chunk-TZ3SGWZZ.js} +3 -3
- package/dist/{chunk-MXKJU4JB.js → chunk-U77AMWDL.js} +91 -10
- package/dist/{chunk-5DHKRSMQ.js → chunk-ULC6OTWO.js} +11 -7
- package/dist/{chunk-RWSI4YD7.js → chunk-UM7N4G5A.js} +33 -12
- package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
- package/dist/{chunk-IGWKHNIQ.js → chunk-UXMFQ54G.js} +44 -37
- package/dist/{chunk-HFSBBKSQ.js → chunk-V5DHCITQ.js} +171 -3
- package/dist/{chunk-5WIGXA4T.js → chunk-VAZSBTKF.js} +111 -4
- package/dist/{chunk-VHN4MY6O.js → chunk-VEO4AP2K.js} +2 -2
- package/dist/{chunk-IJ7RPIYJ.js → chunk-VFA6GDY5.js} +65 -4
- package/dist/{chunk-PT7HYKEM.js → chunk-VO2LKSTM.js} +2 -2
- package/dist/chunk-VO67MWHC.js +75 -0
- package/dist/{chunk-XK56QHLX.js → chunk-VPKWYKEY.js} +19 -5
- package/dist/{chunk-TANS5ZJS.js → chunk-VYMXRQI6.js} +36 -22
- package/dist/{chunk-WWCZ5F23.js → chunk-W5VSYASO.js} +77 -16
- package/dist/{chunk-WNIJTQQK.js → chunk-WZR7K7ZX.js} +72 -116
- package/dist/{chunk-5Q2VVUKB.js → chunk-X3YGUTOB.js} +4 -4
- package/dist/chunk-X75E3D2N.js +686 -0
- package/dist/{chunk-VAWNZU7Z.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-Z2RR6MAK.js +127 -0
- package/dist/{chunk-FBVTI2TJ.js → chunk-Z4TXYIEG.js} +12 -131
- package/dist/cli/index.js +47 -36
- package/dist/{clio-QVTYJ57A.js → clio-2JXHBBY5.js} +7 -7
- package/dist/{code-nav-FGGFIE7L.js → code-nav-3YYRMYNF.js} +8 -8
- 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-LW5IJFQN.js → config-QZPCMYSO.js} +99 -63
- package/dist/{configure-7XIZCOU4.js → configure-TEGEBYCA.js} +23 -22
- package/dist/{context-Y6Y7QPR6.js → context-AV7OEZ4D.js} +12 -12
- package/dist/{context-L3WL3X7K.js → context-E6H5RNMC.js} +56 -47
- package/dist/{context-N52ZA626.js → context-GSXUE4CT.js} +29 -27
- package/dist/{context-clear-MBQRLSDQ.js → context-clear-SHIBYK6T.js} +55 -46
- package/dist/{context-index-HVMFQHK3.js → context-index-HNG3MOME.js} +2 -2
- package/dist/{context-working-set-GS6DSO7F.js → context-working-set-5ZGKPGZQ.js} +13 -13
- package/dist/{dispatch-runner-22ZCNOM3.js → dispatch-runner-EFMJT4LD.js} +93 -64
- package/dist/{docs-7LQ23DLM.js → docs-23KQS3XK.js} +5 -5
- package/dist/doctor-QOA5FNY5.js +313 -0
- package/dist/{eval-BEC2WHDA.js → eval-TFBYQH4H.js} +2032 -156
- package/dist/eval-inventory-SXH7PDKX.js +316 -0
- package/dist/{evidence-REJUMSKM.js → evidence-ERGESKGN.js} +203 -48
- package/dist/{evolve-PY5ZBA5K.js → evolve-VDXTSYCJ.js} +52 -43
- package/dist/{extensions-HVKU65YU.js → extensions-7BGBHN57.js} +13 -7
- package/dist/{fleet-7WZEWRFA.js → fleet-2RRVDF2V.js} +228 -108
- package/dist/{fleet-commands-UVHWM76J.js → fleet-commands-VJ726XIA.js} +11 -11
- package/dist/fleet-decisions-EPAPM3XJ.js +157 -0
- package/dist/{fleet-graph-6ULH7PES.js → fleet-graph-JF5QOATM.js} +18 -15
- package/dist/fleet-inspect-VLY4S7QM.js +442 -0
- package/dist/{fleet-preflight-J53T6CCE.js → fleet-preflight-AIZUEJOY.js} +5 -5
- package/dist/{fleet-validate-72PC4SLA.js → fleet-validate-AJRPDMDV.js} +22 -19
- package/dist/fleet-verify-JFEL2L3H.js +175 -0
- package/dist/fleet-view-ZCON35AG.js +102 -0
- package/dist/{init-OG3TPGQG.js → init-DN2WWLFE.js} +72 -62
- package/dist/install-XGLBQY5E.js +13 -0
- package/dist/interop-OZBKXAYL.js +114 -0
- package/dist/{library-CNTMPLRF.js → library-YWZG7IMW.js} +21 -18
- package/dist/{memory-6IS7F275.js → memory-I4C4HMLW.js} +54 -45
- package/dist/{models-ENRJDA5W.js → models-CEYXJBO6.js} +33 -30
- package/dist/{monitor-XLDVO7TN.js → monitor-NZ6GCI3P.js} +59 -52
- package/dist/{orchestrator-6KSPYRHA.js → orchestrator-GCGQ4N5I.js} +7827 -7328
- 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-RZ4ER727.js → reset-DQ6FGCSH.js} +13 -11
- package/dist/resources-BB3MVJMD.js +111 -0
- package/dist/{run-Y2CNK5RU.js → run-H2GQDUER.js} +119 -87
- package/dist/{share-A55GYP6Z.js → share-GTJN6A5O.js} +20 -17
- package/dist/{skills-ALC5J6AT.js → skills-L55TEW6R.js} +33 -24
- package/dist/{skills-eval-JPBEBYQU.js → skills-eval-XVXPH2JI.js} +67 -56
- package/dist/skills-inventory-S4MXPJFV.js +126 -0
- package/dist/slash-commands-ZSGASKJC.js +77 -0
- package/dist/{steer-GGWFUJUD.js → steer-RZGSCY4R.js} +4 -4
- package/dist/{support-MIETYA5E.js → support-PKEUNNQL.js} +6 -6
- package/dist/{targets-VGNXIR3S.js → targets-NCPZ644J.js} +68 -40
- package/dist/{terminal-lease-WOBR64YA.js → terminal-lease-44SV3YCN.js} +6 -4
- package/dist/tools-DAF3DI3C.js +27 -0
- package/dist/{trace-PNCASAXC.js → trace-FYVW2MQA.js} +207 -10
- package/dist/tui-primitives-2AKXQNZK.js +13 -0
- package/dist/{uninstall-ZJF5H5ZN.js → uninstall-DW2PNOIC.js} +5 -5
- package/dist/{upgrade-FUSUAGHR.js → upgrade-3XPP6OQL.js} +27 -24
- package/dist/{usage-N4MKVHKD.js → usage-3NLHGTU2.js} +114 -62
- package/dist/{verifiers-YAWOJ3H2.js → verifiers-SSQONKRT.js} +172 -13
- package/dist/{verify-LTDHYBGY.js → verify-3U6J7FZI.js} +10 -10
- package/dist/{web-fetch-2YHJ3KTG.js → web-fetch-S7RR6GZ7.js} +3 -3
- package/dist/{wiki-generate-6M7GHTBJ.js → wiki-generate-CEHYGPGQ.js} +75 -65
- package/dist/with-panes-MKB46MPQ.js +782 -0
- package/dist/worker/entry.js +106 -75
- 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 +9 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +62 -3
- package/docs/commands-and-modes.md +31 -2
- package/docs/configuration-and-targets.md +69 -12
- package/docs/context-engine.md +63 -4
- package/docs/development-pipeline.md +19 -0
- package/docs/dispatch-typed-intent.md +385 -0
- package/docs/documentation-coverage.md +5 -5
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +3 -0
- package/docs/eval-runner.md +262 -11
- package/docs/evals-internal.md +72 -2
- package/docs/evidence-and-memory.md +12 -11
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +27 -1
- package/docs/fleet-dispatch.md +25 -4
- 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 +55 -4
- package/docs/proactive-memory.md +127 -14
- package/docs/prompt-envelope-and-tools.md +19 -1
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +19 -3
- 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 +88 -1
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +5 -2
- package/src/cli/acp.ts +6 -2
- package/src/cli/agents.ts +1 -1
- package/src/cli/argv.ts +25 -0
- package/src/cli/config-inspect.ts +33 -6
- package/src/cli/config.ts +1 -1
- package/src/cli/configure.ts +23 -21
- package/src/cli/doctor-panes.ts +124 -0
- package/src/cli/doctor-state-size.ts +82 -0
- package/src/cli/doctor-toolchain.ts +57 -0
- package/src/cli/doctor.ts +22 -1
- package/src/cli/eval-inventory.ts +436 -0
- package/src/cli/eval.ts +93 -16
- 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/extensions.ts +5 -1
- 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 +179 -39
- 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/targets.ts +44 -13
- package/src/cli/tools.ts +321 -0
- package/src/cli/trace-inspect.ts +252 -0
- package/src/cli/trace.ts +85 -5
- package/src/cli/usage.ts +63 -14
- package/src/cli/verifiers-inspect.ts +347 -0
- package/src/cli/verifiers.ts +9 -0
- package/src/core/bus-events.ts +33 -1
- package/src/core/cache-telemetry.ts +42 -0
- package/src/core/config.ts +67 -0
- package/src/core/defaults.ts +124 -8
- package/src/core/endpoint-key.ts +27 -0
- package/src/core/residency-target-key.ts +25 -0
- package/src/core/response-schema.ts +80 -6
- 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 +6 -0
- package/src/domains/context/codewiki/coordinator.ts +12 -4
- package/src/domains/dispatch/admission-error.ts +9 -0
- package/src/domains/dispatch/admission.ts +52 -14
- package/src/domains/dispatch/capacity-lease.ts +118 -9
- package/src/domains/dispatch/contract.ts +11 -0
- package/src/domains/dispatch/council-topology.ts +398 -0
- package/src/domains/dispatch/execution-plan.ts +44 -4
- package/src/domains/dispatch/extension.ts +378 -82
- 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 +87 -4
- 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/heartbeat.ts +32 -8
- package/src/domains/dispatch/index.ts +22 -0
- package/src/domains/dispatch/intent-compatibility.ts +330 -0
- package/src/domains/dispatch/intent.ts +85 -1
- package/src/domains/dispatch/orphan-recovery.ts +5 -0
- package/src/domains/dispatch/reservation-store.ts +139 -11
- 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 +49 -1
- package/src/domains/dispatch/types.ts +13 -0
- package/src/domains/dispatch/validation.ts +33 -8
- package/src/domains/dispatch/worker-spawn.ts +25 -11
- package/src/domains/dispatch/write-boundary-enforcer.ts +20 -3
- package/src/domains/dispatch/write-boundary.ts +62 -1
- package/src/domains/eval/artifacts/store.ts +62 -0
- package/src/domains/eval/compare/behavioral.ts +224 -0
- package/src/domains/eval/compare/compare.ts +342 -2
- package/src/domains/eval/compare/envelope.ts +128 -0
- package/src/domains/eval/compare/gates.ts +24 -6
- package/src/domains/eval/compare/thresholds.ts +30 -3
- package/src/domains/eval/execution-provenance.ts +240 -0
- package/src/domains/eval/inventory.ts +113 -0
- package/src/domains/eval/metrics/aggregate.ts +136 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
- package/src/domains/eval/metrics/tracked.ts +413 -0
- package/src/domains/eval/provenance.ts +117 -0
- package/src/domains/eval/reports/comparison.ts +128 -0
- package/src/domains/eval/reports/junit.ts +17 -3
- package/src/domains/eval/reports/markdown.ts +3 -3
- package/src/domains/eval/reports/text.ts +14 -0
- package/src/domains/eval/run-compare.ts +20 -0
- package/src/domains/eval/runners/clio-run.ts +127 -0
- package/src/domains/eval/runners/external-command.ts +28 -3
- package/src/domains/eval/schema/adapter.ts +111 -0
- package/src/domains/eval/schema/artifact.ts +20 -0
- package/src/domains/eval/schema/behavioral-metrics.ts +204 -0
- package/src/domains/eval/schema/behavioral.ts +520 -0
- package/src/domains/eval/schema/execution-envelope.ts +194 -0
- package/src/domains/eval/schema/serving.ts +105 -0
- package/src/domains/eval/schema/suite.ts +38 -8
- package/src/domains/eval/schema/validate.ts +58 -3
- package/src/domains/eval/schema/verdict.ts +237 -0
- package/src/domains/eval/suites/resolve.ts +2 -0
- package/src/domains/eval/suites/run.ts +264 -33
- package/src/domains/eval/verifiers/command.ts +2 -1
- package/src/domains/eval/workspaces/temp-copy.ts +145 -13
- package/src/domains/evidence/build.ts +2 -13
- package/src/domains/evidence/eval.ts +2 -12
- package/src/domains/evidence/findings-markdown.ts +33 -0
- package/src/domains/evidence/run-trust.ts +7 -113
- package/src/domains/evidence/store.ts +6 -0
- package/src/domains/evidence/trust-projection.ts +2 -2
- package/src/domains/extensions/compatibility.ts +285 -0
- package/src/domains/extensions/discovery.ts +38 -3
- package/src/domains/extensions/resources.ts +1 -1
- package/src/domains/extensions/state.ts +12 -3
- package/src/domains/extensions/types.ts +2 -0
- package/src/domains/lifecycle/doctor.ts +69 -1
- package/src/domains/memory/index.ts +14 -1
- package/src/domains/memory/task-bank-promotion.ts +64 -0
- package/src/domains/memory/task-memory-policy.ts +82 -17
- package/src/domains/memory/task-memory-spend.ts +131 -0
- package/src/domains/memory/task-memory-status.ts +7 -0
- package/src/domains/memory/task-memory-telemetry.ts +3 -0
- package/src/domains/middleware/index.ts +1 -0
- package/src/domains/middleware/memory-intervention.ts +97 -21
- package/src/domains/middleware/memory-step-endpoint.ts +71 -0
- 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/background-memory-usage.ts +140 -0
- package/src/domains/observability/cost.ts +22 -1
- package/src/domains/observability/index.ts +9 -0
- package/src/domains/observability/out-of-turn-usage.ts +51 -2
- package/src/domains/observability/trace-store.ts +234 -2
- package/src/domains/prompts/compiler.ts +100 -13
- package/src/domains/providers/endpoint-capacity.ts +228 -0
- package/src/domains/providers/endpoint-slots-store.ts +189 -0
- package/src/domains/providers/extension.ts +20 -3
- package/src/domains/providers/index.ts +32 -0
- package/src/domains/providers/model-runtime-capabilities.ts +32 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +243 -1
- package/src/domains/providers/runtime-resolution.ts +8 -1
- package/src/domains/providers/runtimes/boot-manifest.ts +1 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +31 -9
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +1 -1
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +4 -1
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +4 -1
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +6 -1
- 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/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/target-descriptor.ts +2 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/prompts/loader.ts +95 -33
- package/src/domains/resources/skills/loader.ts +33 -0
- package/src/domains/safety/action-classifier.ts +6 -0
- package/src/domains/safety/call-target.ts +52 -0
- package/src/domains/safety/run-effects.ts +35 -4
- package/src/domains/session/context-accounting.ts +52 -1
- package/src/domains/session/context-ledger.ts +37 -13
- package/src/domains/session/index.ts +6 -0
- package/src/domains/session/prompt-cache.ts +140 -0
- package/src/domains/session/prompt-manifest.ts +42 -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/adapter.ts +18 -3
- package/src/engine/acp/server.ts +413 -70
- package/src/engine/acp/types.ts +19 -1
- package/src/engine/ai.ts +35 -0
- package/src/engine/apis/llamacpp-residency.ts +55 -3
- package/src/engine/apis/lmstudio.ts +25 -5
- package/src/engine/apis/ollama-native.ts +2 -1
- package/src/engine/apis/openai-completions.ts +80 -17
- package/src/engine/apis/residency-lock.ts +3 -1
- package/src/engine/apis/residency.ts +34 -1
- package/src/engine/claude/sdk-module.ts +98 -0
- package/src/engine/claude/sdk-runtime.ts +19 -11
- package/src/engine/provider-payload.ts +29 -1
- 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 +279 -35
- package/src/entry/panes-activation.ts +31 -0
- package/src/entry/with-panes.ts +20 -0
- package/src/interactive/chat-loop-messages.ts +26 -7
- package/src/interactive/chat-loop.ts +318 -41
- package/src/interactive/chat-panel.ts +62 -8
- package/src/interactive/clio-editor.ts +45 -8
- package/src/interactive/context-activity.ts +5 -1
- package/src/interactive/context-meter.ts +1 -1
- package/src/interactive/context-overlay.ts +41 -10
- package/src/interactive/cost-overlay.ts +66 -6
- package/src/interactive/council-grid.ts +1 -3
- package/src/interactive/council.ts +11 -0
- package/src/interactive/dispatch-board.ts +102 -20
- package/src/interactive/fleet-run-preview.ts +41 -15
- package/src/interactive/handoff-round.ts +41 -2
- package/src/interactive/interactive-application.ts +177 -7
- package/src/interactive/interactive-input-runtime.ts +15 -0
- package/src/interactive/interactive-presentation.ts +4 -0
- package/src/interactive/interactive-shell.ts +20 -17
- package/src/interactive/interactive-slash-runtime.ts +63 -10
- package/src/interactive/memory-overlay.ts +9 -0
- package/src/interactive/modal-marker.ts +170 -0
- package/src/interactive/mutation-preview.ts +295 -0
- package/src/interactive/mux-bridge.ts +214 -0
- package/src/interactive/overlay-frame.ts +58 -2
- package/src/interactive/overlay-general-openers.ts +17 -0
- package/src/interactive/overlay-key-routing.ts +52 -3
- package/src/interactive/overlay-lifecycle.ts +56 -7
- package/src/interactive/overlay-model-selectors.ts +40 -3
- package/src/interactive/overlay-permission-lifecycle.ts +112 -24
- package/src/interactive/overlay-session-lifecycle.ts +73 -9
- package/src/interactive/overlay-transitions.ts +18 -4
- package/src/interactive/overlays/agents.ts +1 -0
- package/src/interactive/overlays/ask-user.ts +227 -49
- 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 +6 -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 +12 -1
- package/src/interactive/overlays/session-selector.ts +1 -0
- package/src/interactive/overlays/settings-sections.ts +30 -0
- package/src/interactive/overlays/settings.ts +614 -45
- 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/permission-hint.ts +34 -2
- package/src/interactive/permission-overlay.ts +159 -9
- package/src/interactive/prewarm.ts +197 -0
- package/src/interactive/render-trace.ts +162 -15
- package/src/interactive/renderers/compaction-summary.ts +29 -0
- package/src/interactive/renderers/tool-execution.ts +4 -0
- package/src/interactive/renderers/worker-entry.ts +122 -14
- package/src/interactive/side-question.ts +58 -1
- package/src/interactive/slash-commands.ts +251 -15
- package/src/interactive/status/controller.ts +11 -0
- package/src/interactive/status/state-machine.ts +54 -2
- package/src/interactive/status/types.ts +7 -0
- package/src/interactive/tasks-overlay.ts +1 -0
- package/src/interactive/terminal-lease.ts +2 -0
- package/src/interactive/theme/tokens.ts +3 -14
- package/src/interactive/turn-context.ts +346 -33
- package/src/interactive/turn-persistence.ts +14 -4
- package/src/interactive/turn-prewarm.ts +364 -0
- package/src/interactive/turn-queues.ts +7 -4
- package/src/interactive/turn-runtime.ts +8 -1
- package/src/interactive/turn-state.ts +23 -0
- package/src/interactive/view/artifacts.ts +109 -1
- package/src/interactive/view/view-overlay.ts +29 -3
- 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/ask-user.ts +43 -2
- 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-plan.ts +17 -9
- package/src/tools/dispatch-run-events.ts +134 -19
- package/src/tools/dispatch-runner.ts +29 -7
- package/src/tools/dispatch-scout.ts +1 -1
- 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/src/tools/registry.ts +16 -0
- package/dist/chunk-AOCYTWAV.js +0 -449
- package/dist/chunk-HLE42MG7.js +0 -37
- package/dist/chunk-HWUFFB6L.js +0 -83
- package/dist/chunk-JOZYP4GM.js +0 -279
- package/dist/doctor-M7YEDGAE.js +0 -91
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
decideReviewGate,
|
|
4
|
+
materializePendingGateDecision,
|
|
5
|
+
readGateDecisionArtifacts,
|
|
6
|
+
readGateDecisionArtifactsForRunIds,
|
|
7
|
+
stagePendingGateDecision,
|
|
8
|
+
verifyGateDecisionArtifact
|
|
9
|
+
} from "./chunk-X75E3D2N.js";
|
|
9
10
|
import {
|
|
10
11
|
RUN_RECEIPT_INTEGRITY_ALGORITHM,
|
|
11
12
|
RUN_RECEIPT_INTEGRITY_VERSION,
|
|
12
|
-
adaptFinishContractCompletionStatus,
|
|
13
13
|
adaptGateDecisionReviewStatus,
|
|
14
14
|
adaptGroundedEvidenceValidationStatus,
|
|
15
15
|
composeTrustStatus,
|
|
16
|
+
formatTrustAxes,
|
|
17
|
+
formatTrustSummary,
|
|
16
18
|
inspectRunReceiptTrustStatus,
|
|
17
19
|
isReceiptIntegrity,
|
|
18
20
|
isTrustStatusIdentifier,
|
|
19
|
-
loadEvalArtifact,
|
|
20
21
|
normalizeTrustStatus,
|
|
21
|
-
parseEvalArtifactV4,
|
|
22
|
-
redactArtifactForStorage,
|
|
23
22
|
retiredIntegrityVersionOf,
|
|
24
|
-
|
|
23
|
+
sha256,
|
|
24
|
+
trustVerdict,
|
|
25
25
|
verifyReceiptIntegrity,
|
|
26
26
|
withReceiptIntegrity
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-B7OBL7PK.js";
|
|
28
|
+
import {
|
|
29
|
+
protectedArtifactFromSessionEntry,
|
|
30
|
+
protectedArtifactStateFromSessionEntries,
|
|
31
|
+
readAuditRows,
|
|
32
|
+
readSessionEntriesForId,
|
|
33
|
+
responseModelIdObservationFromRecord
|
|
34
|
+
} from "./chunk-QREDIESB.js";
|
|
28
35
|
import {
|
|
29
36
|
applyTaskWorktree,
|
|
30
37
|
captureWorkspaceSnapshot,
|
|
@@ -32,19 +39,32 @@ import {
|
|
|
32
39
|
createTaskWorktree,
|
|
33
40
|
createWriteBoundaryEnforcer,
|
|
34
41
|
gitCheckoutRoot
|
|
35
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-U77AMWDL.js";
|
|
36
43
|
import {
|
|
37
44
|
executionPlanAncestors,
|
|
38
45
|
spliceExecutionPlan
|
|
39
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-QBJA7R7N.js";
|
|
40
47
|
import {
|
|
41
48
|
parseRigorOverride,
|
|
42
49
|
resolveRigor
|
|
43
50
|
} from "./chunk-RVG5JXAL.js";
|
|
44
51
|
import {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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";
|
|
48
68
|
import {
|
|
49
69
|
LOCAL_NODE_ID,
|
|
50
70
|
computeSettingsFingerprint,
|
|
@@ -55,9 +75,14 @@ import {
|
|
|
55
75
|
receiptAttestationFields,
|
|
56
76
|
routeFactVerdict,
|
|
57
77
|
spawnNativeWorker
|
|
58
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-QLFS5GO2.js";
|
|
79
|
+
import {
|
|
80
|
+
FLEET_COMMAND_BASE_ENV,
|
|
81
|
+
normalizeWriteBoundary
|
|
82
|
+
} from "./chunk-CTJ4RNAA.js";
|
|
59
83
|
import {
|
|
60
84
|
AGENT_LEDGER_PROMPT_MAX_CHARS,
|
|
85
|
+
COUNCIL_MIN_MEMBERS,
|
|
61
86
|
RETRYABLE_OUTCOMES,
|
|
62
87
|
UnsupportedResponseSchemaError,
|
|
63
88
|
WORKER_EXIT_PERMISSION_REQUIRED,
|
|
@@ -67,24 +92,23 @@ import {
|
|
|
67
92
|
agentRoleReadinessReport,
|
|
68
93
|
agentRouteCandidates,
|
|
69
94
|
antigravitySubprocessConfigForAutonomy,
|
|
70
|
-
applyToolProfile,
|
|
71
95
|
approvedRouteCandidates,
|
|
72
96
|
assertApprovedAssignmentRoute,
|
|
73
97
|
assertApprovedRecoveryCapability,
|
|
74
|
-
assertToolProfileEnforceable,
|
|
75
98
|
claimConflicts,
|
|
76
99
|
classifyAgentTask,
|
|
77
100
|
claudeSubprocessPermissionConfigForAutonomy,
|
|
78
101
|
competeStanceLiner,
|
|
79
102
|
createRunEffectsRecorder,
|
|
103
|
+
declaredScopeIntent,
|
|
80
104
|
declaredScopeReplacementDiagnostic,
|
|
81
105
|
declaredScopeReplacementNotice,
|
|
82
|
-
describeCallAction,
|
|
83
106
|
isBoundedGateRolePrompt,
|
|
84
107
|
isClaudeCanonicalTool,
|
|
85
108
|
isResponseSchemaRejection,
|
|
86
109
|
isRunOutcomeCode,
|
|
87
110
|
networkToolsDisabled,
|
|
111
|
+
nodeResultContractFilesystem,
|
|
88
112
|
projectExecutionHandoffs,
|
|
89
113
|
renderAgentLedger,
|
|
90
114
|
resolveDispatchPathScope,
|
|
@@ -95,7 +119,7 @@ import {
|
|
|
95
119
|
serializeWorkerRuntimeDescriptor,
|
|
96
120
|
toolPromptHintsForNames,
|
|
97
121
|
validateJobSpec
|
|
98
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-J4W7KFM7.js";
|
|
99
123
|
import {
|
|
100
124
|
decideRoute,
|
|
101
125
|
defaultRoutingIntent,
|
|
@@ -113,7 +137,20 @@ import {
|
|
|
113
137
|
routingIntentRejection,
|
|
114
138
|
sameRouteIdentity,
|
|
115
139
|
toRouteCandidate
|
|
116
|
-
} 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";
|
|
117
154
|
import {
|
|
118
155
|
appliesRecipeResultContract,
|
|
119
156
|
gateRouteCorrelation,
|
|
@@ -122,94 +159,93 @@ import {
|
|
|
122
159
|
routeCorrelationFactsForRun,
|
|
123
160
|
withAttemptRole
|
|
124
161
|
} from "./chunk-H7IXIC72.js";
|
|
125
|
-
import {
|
|
126
|
-
WRITE_ROOT_REFUSED_TOOLS,
|
|
127
|
-
assessFinishContract
|
|
128
|
-
} from "./chunk-5H3GB5BO.js";
|
|
129
162
|
import {
|
|
130
163
|
compareCodepoints
|
|
131
|
-
} from "./chunk-
|
|
132
|
-
import {
|
|
133
|
-
isSkillActivation
|
|
134
|
-
} from "./chunk-GOXNB3AO.js";
|
|
164
|
+
} from "./chunk-5LXZXPKX.js";
|
|
135
165
|
import {
|
|
136
166
|
DEFAULT_AUTONOMY_LEVEL,
|
|
137
167
|
autonomyDenyRejection,
|
|
168
|
+
isSkillActivation,
|
|
138
169
|
mapAutonomy
|
|
139
|
-
} from "./chunk-
|
|
170
|
+
} from "./chunk-RAPCMZL4.js";
|
|
140
171
|
import {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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";
|
|
147
187
|
import {
|
|
148
188
|
agentSpecFingerprint,
|
|
149
189
|
assertAgentSpecPolicy,
|
|
150
190
|
classify,
|
|
151
191
|
isUserVisibleAgent,
|
|
152
192
|
normalizeAgentSpec,
|
|
153
|
-
|
|
154
|
-
|
|
193
|
+
parseJsonObjectPayload,
|
|
194
|
+
resolveAgentToolCompatibility,
|
|
195
|
+
resultContractAuthorship,
|
|
196
|
+
validateRecipeResult
|
|
197
|
+
} from "./chunk-DYJP44XW.js";
|
|
155
198
|
import {
|
|
156
199
|
detectValidationCommand
|
|
157
|
-
} from "./chunk-
|
|
200
|
+
} from "./chunk-GCSMB2KY.js";
|
|
158
201
|
import {
|
|
159
202
|
isProjectVerifierCheckId,
|
|
160
203
|
isVerificationScriptName
|
|
161
204
|
} from "./chunk-UL3WSD3F.js";
|
|
162
|
-
import {
|
|
163
|
-
createRedactionTally,
|
|
164
|
-
redactSecretsDeep,
|
|
165
|
-
redactSecretsText
|
|
166
|
-
} from "./chunk-4BJ5BYCE.js";
|
|
167
205
|
import {
|
|
168
206
|
canonicalizeExistingPath
|
|
169
207
|
} from "./chunk-ECH6PKUQ.js";
|
|
170
|
-
import {
|
|
171
|
-
canonicalJson,
|
|
172
|
-
endpointIdentityHash,
|
|
173
|
-
parseAgentLedgerBody
|
|
174
|
-
} from "./chunk-CMZWFGD2.js";
|
|
175
|
-
import {
|
|
176
|
-
truncateUtf8
|
|
177
|
-
} from "./chunk-6XLNIQDB.js";
|
|
178
208
|
import {
|
|
179
209
|
ToolNames,
|
|
180
210
|
isBuiltinToolName
|
|
181
|
-
} from "./chunk-
|
|
211
|
+
} from "./chunk-K6BSR66V.js";
|
|
182
212
|
import {
|
|
183
213
|
canonicalizeWireModelId,
|
|
214
|
+
endpointCapacityFor,
|
|
215
|
+
endpointCapacityForStatus,
|
|
216
|
+
endpointLabel,
|
|
184
217
|
firstRuntimeResolutionError,
|
|
218
|
+
foregroundStreamUsage,
|
|
185
219
|
isDispatchEligibleRuntime,
|
|
220
|
+
normalizeCostProvenance,
|
|
221
|
+
resolveEndpointCapacities,
|
|
186
222
|
resolveModelCapabilities,
|
|
187
223
|
resolveRuntimeTarget,
|
|
188
224
|
runtimeResolutionWarnings,
|
|
189
225
|
runtimeTargetSnapshot
|
|
190
|
-
} from "./chunk-
|
|
226
|
+
} from "./chunk-DQITNCXG.js";
|
|
191
227
|
import {
|
|
192
228
|
ceilChars
|
|
193
|
-
} 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";
|
|
194
239
|
import {
|
|
195
240
|
attributeCommitMessage,
|
|
196
241
|
gitCommitAttributionEnabled,
|
|
197
242
|
reportCommitAttributionDiagnostic,
|
|
198
243
|
withManagedGitCommitAttributionEnvironment
|
|
199
|
-
} from "./chunk-
|
|
244
|
+
} from "./chunk-BBVJUZHB.js";
|
|
200
245
|
import {
|
|
201
246
|
MAX_TIMER_DELAY_MS,
|
|
202
247
|
rawDurationMs
|
|
203
248
|
} from "./chunk-FQ4SKYE4.js";
|
|
204
|
-
import {
|
|
205
|
-
BusChannels
|
|
206
|
-
} from "./chunk-TT36MB5S.js";
|
|
207
|
-
import {
|
|
208
|
-
atomicWrite
|
|
209
|
-
} from "./chunk-3BINW3FP.js";
|
|
210
|
-
import {
|
|
211
|
-
assertSafeId
|
|
212
|
-
} from "./chunk-R346GLFC.js";
|
|
213
249
|
import {
|
|
214
250
|
AI_AGENT_NAME
|
|
215
251
|
} from "./chunk-6EJMN2Y3.js";
|
|
@@ -223,14 +259,14 @@ import {
|
|
|
223
259
|
DEFAULT_DELEGATION_TURN_TIMEOUT_MS,
|
|
224
260
|
DEFAULT_SETTINGS,
|
|
225
261
|
THINKING_LEVELS
|
|
226
|
-
} from "./chunk-
|
|
262
|
+
} from "./chunk-GXNLGKAB.js";
|
|
227
263
|
import {
|
|
228
264
|
GUARDRAIL_DEFAULTS,
|
|
229
265
|
resolveGuardrail
|
|
230
266
|
} from "./chunk-4ZG3XFUR.js";
|
|
231
267
|
import {
|
|
232
268
|
targetRequiresAuth
|
|
233
|
-
} from "./chunk-
|
|
269
|
+
} from "./chunk-BBVYXMFO.js";
|
|
234
270
|
import {
|
|
235
271
|
FILE_LOCK_ACQUIRE_TIMEOUT_MS,
|
|
236
272
|
withStateFileLock,
|
|
@@ -245,10 +281,10 @@ import {
|
|
|
245
281
|
clioDataDir,
|
|
246
282
|
clioStateDir,
|
|
247
283
|
stateRootRemoved
|
|
248
|
-
} from "./chunk-
|
|
284
|
+
} from "./chunk-BYP5D4HI.js";
|
|
249
285
|
import {
|
|
250
286
|
resolveEffectivePricing
|
|
251
|
-
} from "./chunk-
|
|
287
|
+
} from "./chunk-VO2LKSTM.js";
|
|
252
288
|
import {
|
|
253
289
|
init_esm_shims
|
|
254
290
|
} from "./chunk-3R73A4XB.js";
|
|
@@ -406,8 +442,8 @@ var StdioJsonRpcTransport = class {
|
|
|
406
442
|
constructor(command, args, options = {}) {
|
|
407
443
|
this.terminationGraceMs = boundedMilliseconds(options.terminationGraceMs, 500);
|
|
408
444
|
this.terminationWaitMs = boundedMilliseconds(options.terminationWaitMs, 2e3);
|
|
409
|
-
this.childClosePromise = new Promise((
|
|
410
|
-
this.resolveChildClose =
|
|
445
|
+
this.childClosePromise = new Promise((resolve4) => {
|
|
446
|
+
this.resolveChildClose = resolve4;
|
|
411
447
|
});
|
|
412
448
|
const childEnvironment = options.env ? { ...process.env, ...options.env } : process.env;
|
|
413
449
|
const attribution = withManagedGitCommitAttributionEnvironment(childEnvironment, {
|
|
@@ -464,10 +500,10 @@ var StdioJsonRpcTransport = class {
|
|
|
464
500
|
const requestTimeoutMs = validateRequestTimeout(method, timeoutMs);
|
|
465
501
|
const id = this.nextId++;
|
|
466
502
|
const message = { jsonrpc: "2.0", id, method, params };
|
|
467
|
-
const promise = new Promise((
|
|
503
|
+
const promise = new Promise((resolve4, reject) => {
|
|
468
504
|
const pending = {
|
|
469
505
|
method,
|
|
470
|
-
resolve: (value) =>
|
|
506
|
+
resolve: (value) => resolve4(value),
|
|
471
507
|
reject
|
|
472
508
|
};
|
|
473
509
|
if (requestTimeoutMs !== void 0) {
|
|
@@ -654,9 +690,9 @@ var StdioJsonRpcTransport = class {
|
|
|
654
690
|
if (remaining <= 0) return this.terminationObserved();
|
|
655
691
|
const interval = Math.min(10, remaining);
|
|
656
692
|
if (this.childHandlesClosed) {
|
|
657
|
-
await new Promise((
|
|
693
|
+
await new Promise((resolve4) => setTimeout(resolve4, interval));
|
|
658
694
|
} else {
|
|
659
|
-
await Promise.race([this.childClosePromise, new Promise((
|
|
695
|
+
await Promise.race([this.childClosePromise, new Promise((resolve4) => setTimeout(resolve4, interval))]);
|
|
660
696
|
}
|
|
661
697
|
}
|
|
662
698
|
return true;
|
|
@@ -721,10 +757,10 @@ var StreamJsonRpcPeerTransport = class {
|
|
|
721
757
|
const requestTimeoutMs = validateRequestTimeout(method, timeoutMs);
|
|
722
758
|
const id = this.nextId++;
|
|
723
759
|
const message = { jsonrpc: "2.0", id, method, params };
|
|
724
|
-
const promise = new Promise((
|
|
760
|
+
const promise = new Promise((resolve4, reject) => {
|
|
725
761
|
const pending = {
|
|
726
762
|
method,
|
|
727
|
-
resolve: (value) =>
|
|
763
|
+
resolve: (value) => resolve4(value),
|
|
728
764
|
reject
|
|
729
765
|
};
|
|
730
766
|
if (requestTimeoutMs !== void 0) {
|
|
@@ -888,162 +924,6 @@ function createStdioServerTransport(options = {}) {
|
|
|
888
924
|
return new StreamJsonRpcPeerTransport(options);
|
|
889
925
|
}
|
|
890
926
|
|
|
891
|
-
// src/domains/dispatch/event-pump.ts
|
|
892
|
-
init_esm_shims();
|
|
893
|
-
var EVENT_TEE_LIMIT = 1024;
|
|
894
|
-
function startDispatchEventPump(source, fold, options = {}) {
|
|
895
|
-
const limit = options.limit ?? EVENT_TEE_LIMIT;
|
|
896
|
-
const pending = [...options.prelude ?? []];
|
|
897
|
-
const waiters = [];
|
|
898
|
-
let finished = false;
|
|
899
|
-
let abandoned = false;
|
|
900
|
-
let dropped = 0;
|
|
901
|
-
const push = (value) => {
|
|
902
|
-
if (abandoned) return;
|
|
903
|
-
const waiter = waiters.shift();
|
|
904
|
-
if (waiter) {
|
|
905
|
-
waiter({ value, done: false });
|
|
906
|
-
return;
|
|
907
|
-
}
|
|
908
|
-
pending.push(value);
|
|
909
|
-
while (pending.length > limit) {
|
|
910
|
-
pending.shift();
|
|
911
|
-
dropped += 1;
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
const end = () => {
|
|
915
|
-
finished = true;
|
|
916
|
-
while (waiters.length > 0) {
|
|
917
|
-
waiters.shift()?.({ value: void 0, done: true });
|
|
918
|
-
}
|
|
919
|
-
};
|
|
920
|
-
const notify = (event) => {
|
|
921
|
-
try {
|
|
922
|
-
options.onEvent?.(event);
|
|
923
|
-
} catch (error) {
|
|
924
|
-
options.onError?.(error);
|
|
925
|
-
}
|
|
926
|
-
};
|
|
927
|
-
const done = (async () => {
|
|
928
|
-
try {
|
|
929
|
-
for (const event of options.prelude ?? []) notify(event);
|
|
930
|
-
for await (const event of source) {
|
|
931
|
-
try {
|
|
932
|
-
fold(event);
|
|
933
|
-
} catch (error) {
|
|
934
|
-
options.onError?.(error);
|
|
935
|
-
}
|
|
936
|
-
notify(event);
|
|
937
|
-
push(event);
|
|
938
|
-
}
|
|
939
|
-
} catch (error) {
|
|
940
|
-
options.onError?.(error);
|
|
941
|
-
} finally {
|
|
942
|
-
end();
|
|
943
|
-
}
|
|
944
|
-
})();
|
|
945
|
-
const events = {
|
|
946
|
-
next() {
|
|
947
|
-
if (pending.length > 0) {
|
|
948
|
-
return Promise.resolve({ value: pending.shift(), done: false });
|
|
949
|
-
}
|
|
950
|
-
if (finished || abandoned) return Promise.resolve({ value: void 0, done: true });
|
|
951
|
-
return new Promise((resolve5) => {
|
|
952
|
-
waiters.push(resolve5);
|
|
953
|
-
});
|
|
954
|
-
},
|
|
955
|
-
return() {
|
|
956
|
-
abandoned = true;
|
|
957
|
-
pending.length = 0;
|
|
958
|
-
while (waiters.length > 0) {
|
|
959
|
-
waiters.shift()?.({ value: void 0, done: true });
|
|
960
|
-
}
|
|
961
|
-
return Promise.resolve({ value: void 0, done: true });
|
|
962
|
-
},
|
|
963
|
-
[Symbol.asyncIterator]() {
|
|
964
|
-
return this;
|
|
965
|
-
}
|
|
966
|
-
};
|
|
967
|
-
return { events, done, droppedEvents: () => dropped };
|
|
968
|
-
}
|
|
969
|
-
var WORKER_OUTPUT_MAX_BYTES = 8192;
|
|
970
|
-
var WORKER_OUTPUT_TRUNCATION_MARKER = "\n[worker output truncated]";
|
|
971
|
-
function isRecord2(value) {
|
|
972
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
973
|
-
}
|
|
974
|
-
function assistantTextFromContent(content) {
|
|
975
|
-
if (typeof content === "string") return content;
|
|
976
|
-
if (!Array.isArray(content)) return "";
|
|
977
|
-
return content.map((block) => {
|
|
978
|
-
if (typeof block === "string") return block;
|
|
979
|
-
if (!isRecord2(block)) return "";
|
|
980
|
-
return typeof block.text === "string" ? block.text : "";
|
|
981
|
-
}).join("");
|
|
982
|
-
}
|
|
983
|
-
function isDurableAssistantMessage(message) {
|
|
984
|
-
const stopReason = message.stopReason;
|
|
985
|
-
if (stopReason === "toolUse" || stopReason === "error" || stopReason === "aborted" || stopReason === "cancelled") {
|
|
986
|
-
return false;
|
|
987
|
-
}
|
|
988
|
-
if (!Array.isArray(message.content)) return true;
|
|
989
|
-
return !message.content.some((block) => isRecord2(block) && block.type === "toolCall");
|
|
990
|
-
}
|
|
991
|
-
function durableAssistantTextFromEvent(event) {
|
|
992
|
-
if (!isRecord2(event) || event.type !== "message_end" || !isRecord2(event.message)) return "";
|
|
993
|
-
if (event.message.role !== "assistant" || !isDurableAssistantMessage(event.message)) return "";
|
|
994
|
-
return assistantTextFromContent(event.message.content);
|
|
995
|
-
}
|
|
996
|
-
function boundedOutput(state, text) {
|
|
997
|
-
const bytes = Buffer.byteLength(text, "utf8");
|
|
998
|
-
const bounded = truncateUtf8(text, WORKER_OUTPUT_MAX_BYTES, WORKER_OUTPUT_TRUNCATION_MARKER);
|
|
999
|
-
return { state, text: bounded, bytes, truncated: bounded !== text };
|
|
1000
|
-
}
|
|
1001
|
-
function createWorkerOutputCapture() {
|
|
1002
|
-
let finalText = null;
|
|
1003
|
-
let partialText = "";
|
|
1004
|
-
let partialBytes = 0;
|
|
1005
|
-
let partialStored = 0;
|
|
1006
|
-
return {
|
|
1007
|
-
observe(event) {
|
|
1008
|
-
if (!isRecord2(event)) return;
|
|
1009
|
-
if (event.type === "message_end") {
|
|
1010
|
-
const message = isRecord2(event.message) ? event.message : null;
|
|
1011
|
-
partialText = "";
|
|
1012
|
-
partialBytes = 0;
|
|
1013
|
-
partialStored = 0;
|
|
1014
|
-
if (message === null || message.role !== "assistant") return;
|
|
1015
|
-
if (!isDurableAssistantMessage(message)) return;
|
|
1016
|
-
const text = assistantTextFromContent(message.content).trim();
|
|
1017
|
-
if (text.length > 0) finalText = text;
|
|
1018
|
-
return;
|
|
1019
|
-
}
|
|
1020
|
-
if (event.type !== "message_update") return;
|
|
1021
|
-
const assistantEvent = isRecord2(event.assistantMessageEvent) ? event.assistantMessageEvent : null;
|
|
1022
|
-
if (assistantEvent === null || assistantEvent.type !== "text_delta") return;
|
|
1023
|
-
const delta = assistantEvent.delta;
|
|
1024
|
-
if (typeof delta !== "string" || delta.length === 0) return;
|
|
1025
|
-
partialBytes += Buffer.byteLength(delta, "utf8");
|
|
1026
|
-
if (partialStored < WORKER_OUTPUT_MAX_BYTES) {
|
|
1027
|
-
partialText += delta;
|
|
1028
|
-
partialStored += Buffer.byteLength(delta, "utf8");
|
|
1029
|
-
}
|
|
1030
|
-
},
|
|
1031
|
-
snapshot() {
|
|
1032
|
-
if (partialBytes > 0 && partialText.trim().length > 0) {
|
|
1033
|
-
const bounded = truncateUtf8(partialText.trim(), WORKER_OUTPUT_MAX_BYTES, WORKER_OUTPUT_TRUNCATION_MARKER);
|
|
1034
|
-
return {
|
|
1035
|
-
state: "partial",
|
|
1036
|
-
text: bounded,
|
|
1037
|
-
bytes: partialBytes,
|
|
1038
|
-
truncated: bounded !== partialText.trim() || partialBytes > partialStored
|
|
1039
|
-
};
|
|
1040
|
-
}
|
|
1041
|
-
if (finalText !== null) return boundedOutput("final", finalText);
|
|
1042
|
-
return void 0;
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
927
|
// src/domains/dispatch/capacity-lease.ts
|
|
1048
928
|
init_esm_shims();
|
|
1049
929
|
import { randomBytes } from "node:crypto";
|
|
@@ -1069,7 +949,7 @@ function clone(lease) {
|
|
|
1069
949
|
function valid(value) {
|
|
1070
950
|
if (typeof value !== "object" || value === null) return false;
|
|
1071
951
|
const lease = value;
|
|
1072
|
-
return typeof lease.leaseId === "string" && typeof lease.assignmentId === "string" && typeof lease.nodeId === "string" && (lease.host === void 0 || typeof lease.host === "string") && Number.isInteger(lease.ownerPid) && typeof lease.processBirthToken === "string" && typeof lease.acquiredAt === "string" && typeof lease.expiresAt === "string" && typeof lease.heartbeatAt === "string" && (lease.reservationOwnerId === null || typeof lease.reservationOwnerId === "string") && (lease.reservationMemberId === null || typeof lease.reservationMemberId === "string");
|
|
952
|
+
return typeof lease.leaseId === "string" && typeof lease.assignmentId === "string" && typeof lease.nodeId === "string" && (lease.endpointKey === void 0 || typeof lease.endpointKey === "string") && (lease.host === void 0 || typeof lease.host === "string") && Number.isInteger(lease.ownerPid) && typeof lease.processBirthToken === "string" && typeof lease.acquiredAt === "string" && typeof lease.expiresAt === "string" && typeof lease.heartbeatAt === "string" && (lease.reservationOwnerId === null || typeof lease.reservationOwnerId === "string") && (lease.reservationMemberId === null || typeof lease.reservationMemberId === "string");
|
|
1073
953
|
}
|
|
1074
954
|
function validTimestamp(value) {
|
|
1075
955
|
if (typeof value !== "string") return false;
|
|
@@ -1133,6 +1013,7 @@ var MEMBER_STATUSES = /* @__PURE__ */ new Set(["held", "consumed", "released"]);
|
|
|
1133
1013
|
function heldReservationUsage(values) {
|
|
1134
1014
|
let global = 0;
|
|
1135
1015
|
const nodes = {};
|
|
1016
|
+
const endpoints = {};
|
|
1136
1017
|
for (const value of values) {
|
|
1137
1018
|
if (typeof value !== "object" || value === null)
|
|
1138
1019
|
throw new Error("dispatch capacity store has invalid reservation records");
|
|
@@ -1142,6 +1023,7 @@ function heldReservationUsage(values) {
|
|
|
1142
1023
|
if (record.status !== "active") continue;
|
|
1143
1024
|
const byWave = /* @__PURE__ */ new Map();
|
|
1144
1025
|
const byNodeWave = /* @__PURE__ */ new Map();
|
|
1026
|
+
const byEndpointWave = /* @__PURE__ */ new Map();
|
|
1145
1027
|
for (const raw of record.members) {
|
|
1146
1028
|
if (typeof raw !== "object" || raw === null)
|
|
1147
1029
|
throw new Error("dispatch capacity store has invalid reservation records");
|
|
@@ -1154,13 +1036,39 @@ function heldReservationUsage(values) {
|
|
|
1154
1036
|
const nodeWaves = byNodeWave.get(member.nodeId) ?? /* @__PURE__ */ new Map();
|
|
1155
1037
|
nodeWaves.set(wave, (nodeWaves.get(wave) ?? 0) + 1);
|
|
1156
1038
|
byNodeWave.set(member.nodeId, nodeWaves);
|
|
1039
|
+
if (member.endpointKey !== void 0 && typeof member.endpointKey !== "string")
|
|
1040
|
+
throw new Error("dispatch capacity store has invalid reservation records");
|
|
1041
|
+
if (typeof member.endpointKey === "string") {
|
|
1042
|
+
const endpointWaves = byEndpointWave.get(member.endpointKey) ?? /* @__PURE__ */ new Map();
|
|
1043
|
+
endpointWaves.set(wave, (endpointWaves.get(wave) ?? 0) + 1);
|
|
1044
|
+
byEndpointWave.set(member.endpointKey, endpointWaves);
|
|
1045
|
+
}
|
|
1157
1046
|
}
|
|
1158
1047
|
global += Math.max(0, ...byWave.values());
|
|
1159
1048
|
for (const [id, waves] of byNodeWave) nodes[id] = (nodes[id] ?? 0) + Math.max(0, ...waves.values());
|
|
1049
|
+
for (const [key, waves] of byEndpointWave) endpoints[key] = (endpoints[key] ?? 0) + Math.max(0, ...waves.values());
|
|
1160
1050
|
}
|
|
1161
|
-
return { global, nodes };
|
|
1051
|
+
return { global, nodes, endpoints };
|
|
1162
1052
|
}
|
|
1163
|
-
function
|
|
1053
|
+
function describeEndpointCapacityHolders(holders) {
|
|
1054
|
+
const parts = [];
|
|
1055
|
+
const add = (count, singular, plural) => {
|
|
1056
|
+
if (count > 0) parts.push(`${count} ${count === 1 ? singular : plural}`);
|
|
1057
|
+
};
|
|
1058
|
+
add(holders.leases, "active lease", "active leases");
|
|
1059
|
+
add(holders.reservations, "held reservation", "held reservations");
|
|
1060
|
+
add(holders.foregroundStreams, "foreground stream", "foreground streams");
|
|
1061
|
+
if (parts.length === 0) return "no active lease, held reservation, or foreground stream currently holds a slot";
|
|
1062
|
+
const named = parts.length === 1 ? parts[0] : parts.length === 2 ? `${parts[0]} and ${parts[1]}` : `${parts.slice(0, -1).join(", ")}, and ${parts.at(-1)}`;
|
|
1063
|
+
const total = holders.leases + holders.reservations + holders.foregroundStreams;
|
|
1064
|
+
return `${named} ${total === 1 ? "holds" : "hold"} ${total === 1 ? "the slot" : "the slots"}`;
|
|
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
|
+
}
|
|
1071
|
+
function assertCapacity(file, nodeId, endpointKey, limits) {
|
|
1164
1072
|
const held2 = heldReservationUsage(file.reservations);
|
|
1165
1073
|
const globalUsed = file.leases.length + held2.global;
|
|
1166
1074
|
if (globalUsed >= limits.global) {
|
|
@@ -1175,6 +1083,23 @@ function assertCapacity(file, nodeId, limits) {
|
|
|
1175
1083
|
if (used >= nodeLimit)
|
|
1176
1084
|
throw new Error(`dispatch: admission denied: node '${nodeId}' capacity reached (${used}/${nodeLimit})`);
|
|
1177
1085
|
}
|
|
1086
|
+
if (endpointKey !== void 0) {
|
|
1087
|
+
const endpointLimit = limits.endpoints[endpointKey];
|
|
1088
|
+
if (endpointLimit !== void 0) {
|
|
1089
|
+
if (endpointLimit < 1)
|
|
1090
|
+
throw new Error(`dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity unavailable`);
|
|
1091
|
+
const holders = {
|
|
1092
|
+
leases: file.leases.filter((lease) => lease.endpointKey === endpointKey).length,
|
|
1093
|
+
reservations: held2.endpoints[endpointKey] ?? 0,
|
|
1094
|
+
foregroundStreams: foregroundStreamUsage()[endpointKey] ?? 0
|
|
1095
|
+
};
|
|
1096
|
+
const used = holders.leases + holders.reservations + holders.foregroundStreams;
|
|
1097
|
+
if (used >= endpointLimit)
|
|
1098
|
+
throw new Error(
|
|
1099
|
+
`dispatch: admission denied: endpoint '${endpointLabel(endpointKey)}' capacity reached (${used}/${endpointLimit} slots): ${describeEndpointCapacityHolders(holders)}; ${endpointCapacityRemedy()}`
|
|
1100
|
+
);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1178
1103
|
}
|
|
1179
1104
|
function acquireCapacityLease(input) {
|
|
1180
1105
|
return withStateFileLockSync(capacityStateLockPath(), () => {
|
|
@@ -1188,10 +1113,12 @@ function acquireCapacityLease(input) {
|
|
|
1188
1113
|
);
|
|
1189
1114
|
const existing = file.leases.find((lease2) => lease2.assignmentId === input.assignmentId);
|
|
1190
1115
|
if (existing) {
|
|
1191
|
-
if (existing.nodeId !== input.nodeId) {
|
|
1116
|
+
if (existing.nodeId !== input.nodeId || existing.endpointKey !== input.endpointKey) {
|
|
1192
1117
|
const without = { ...file, leases: file.leases.filter((lease2) => lease2 !== existing) };
|
|
1193
|
-
assertCapacity(without, input.nodeId, input.limits);
|
|
1118
|
+
assertCapacity(without, input.nodeId, input.endpointKey, input.limits);
|
|
1194
1119
|
existing.nodeId = input.nodeId;
|
|
1120
|
+
if (input.endpointKey === void 0) delete existing.endpointKey;
|
|
1121
|
+
else existing.endpointKey = input.endpointKey;
|
|
1195
1122
|
}
|
|
1196
1123
|
existing.heartbeatAt = new Date(nowMs).toISOString();
|
|
1197
1124
|
existing.expiresAt = new Date(nowMs + (input.ttlMs ?? DEFAULT_CAPACITY_LEASE_TTL_MS)).toISOString();
|
|
@@ -1199,7 +1126,7 @@ function acquireCapacityLease(input) {
|
|
|
1199
1126
|
return clone(existing);
|
|
1200
1127
|
}
|
|
1201
1128
|
input.onAcquiredUnderLock?.(file);
|
|
1202
|
-
assertCapacity(file, input.nodeId, input.limits);
|
|
1129
|
+
assertCapacity(file, input.nodeId, input.endpointKey, input.limits);
|
|
1203
1130
|
const token = input.processBirthToken ?? processBirthToken(input.ownerPid ?? process.pid);
|
|
1204
1131
|
if (!token) throw new Error("dispatch: cannot establish process birth token");
|
|
1205
1132
|
const at = new Date(nowMs).toISOString();
|
|
@@ -1207,6 +1134,7 @@ function acquireCapacityLease(input) {
|
|
|
1207
1134
|
leaseId: `lease-${nowMs.toString(36)}-${randomBytes(6).toString("hex")}`,
|
|
1208
1135
|
assignmentId: input.assignmentId,
|
|
1209
1136
|
nodeId: input.nodeId,
|
|
1137
|
+
...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
|
|
1210
1138
|
host: hostname(),
|
|
1211
1139
|
ownerPid: input.ownerPid ?? process.pid,
|
|
1212
1140
|
processBirthToken: token,
|
|
@@ -1278,8 +1206,23 @@ function capacityDrain(nowMs = Date.now()) {
|
|
|
1278
1206
|
function capacityLeaseUsage(options) {
|
|
1279
1207
|
const leases = listCapacityLeases(options);
|
|
1280
1208
|
const nodes = {};
|
|
1281
|
-
|
|
1282
|
-
|
|
1209
|
+
const foreground = foregroundStreamUsage();
|
|
1210
|
+
const endpoints = { ...foreground };
|
|
1211
|
+
const endpointHolders = Object.fromEntries(
|
|
1212
|
+
Object.entries(foreground).map(([endpointKey, foregroundStreams]) => [
|
|
1213
|
+
endpointKey,
|
|
1214
|
+
{ leases: 0, reservations: 0, foregroundStreams }
|
|
1215
|
+
])
|
|
1216
|
+
);
|
|
1217
|
+
for (const lease of leases) {
|
|
1218
|
+
nodes[lease.nodeId] = (nodes[lease.nodeId] ?? 0) + 1;
|
|
1219
|
+
if (lease.endpointKey !== void 0) {
|
|
1220
|
+
endpoints[lease.endpointKey] = (endpoints[lease.endpointKey] ?? 0) + 1;
|
|
1221
|
+
const holders = endpointHolders[lease.endpointKey] ?? { leases: 0, reservations: 0, foregroundStreams: 0 };
|
|
1222
|
+
endpointHolders[lease.endpointKey] = { ...holders, leases: holders.leases + 1 };
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
return { global: leases.length, nodes, endpoints, endpointHolders };
|
|
1283
1226
|
}
|
|
1284
1227
|
function createNodeLeaseUsageReader(options) {
|
|
1285
1228
|
const cacheMs = options.cacheMs ?? 200;
|
|
@@ -1487,7 +1430,7 @@ function renderDispatchReviewerTask(originalTask, builderRunId, cycle, intent) {
|
|
|
1487
1430
|
|
|
1488
1431
|
// src/domains/dispatch/receipt-findings.ts
|
|
1489
1432
|
init_esm_shims();
|
|
1490
|
-
import { createHash as
|
|
1433
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
1491
1434
|
|
|
1492
1435
|
// src/domains/evidence/index.ts
|
|
1493
1436
|
init_esm_shims();
|
|
@@ -1495,37 +1438,39 @@ init_esm_shims();
|
|
|
1495
1438
|
// src/domains/evidence/build.ts
|
|
1496
1439
|
init_esm_shims();
|
|
1497
1440
|
import { mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
|
|
1498
|
-
import { join as
|
|
1441
|
+
import { join as join16 } from "node:path";
|
|
1499
1442
|
|
|
1500
1443
|
// src/domains/dispatch/index.ts
|
|
1501
1444
|
init_esm_shims();
|
|
1502
1445
|
|
|
1503
1446
|
// src/domains/dispatch/extension.ts
|
|
1504
1447
|
init_esm_shims();
|
|
1505
|
-
import { createHash as
|
|
1506
|
-
import {
|
|
1448
|
+
import { createHash as createHash7, randomBytes as randomBytes5 } from "node:crypto";
|
|
1449
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync11 } from "node:fs";
|
|
1507
1450
|
import { isAbsolute as isAbsolute2, relative, resolve as resolvePath, sep } from "node:path";
|
|
1451
|
+
import { performance as performance5 } from "node:perf_hooks";
|
|
1508
1452
|
|
|
1509
1453
|
// src/engine/acp/adapter.ts
|
|
1510
1454
|
init_esm_shims();
|
|
1455
|
+
import { performance as performance4 } from "node:perf_hooks";
|
|
1511
1456
|
|
|
1512
1457
|
// src/engine/acp/event-mapper.ts
|
|
1513
1458
|
init_esm_shims();
|
|
1514
1459
|
import { performance as performance2 } from "node:perf_hooks";
|
|
1515
|
-
function
|
|
1460
|
+
function isRecord2(value) {
|
|
1516
1461
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1517
1462
|
}
|
|
1518
1463
|
function textFromContent(value) {
|
|
1519
1464
|
if (typeof value === "string") return value;
|
|
1520
|
-
if (!
|
|
1465
|
+
if (!isRecord2(value)) return "";
|
|
1521
1466
|
if (value.type === "text" && typeof value.text === "string") return value.text;
|
|
1522
|
-
if (
|
|
1467
|
+
if (isRecord2(value.content)) return textFromContent(value.content);
|
|
1523
1468
|
return "";
|
|
1524
1469
|
}
|
|
1525
1470
|
function toolContentText(value) {
|
|
1526
1471
|
if (typeof value === "string") return value;
|
|
1527
1472
|
if (Array.isArray(value)) return value.map(toolContentText).filter(Boolean).join("\n");
|
|
1528
|
-
if (!
|
|
1473
|
+
if (!isRecord2(value)) return "";
|
|
1529
1474
|
const direct = textFromContent(value);
|
|
1530
1475
|
if (direct.length > 0) return direct;
|
|
1531
1476
|
return "";
|
|
@@ -1548,8 +1493,8 @@ var AcpEventMapper = class {
|
|
|
1548
1493
|
/** Tool-call id to its `performance.now()` start mark; spans only, never an instant. */
|
|
1549
1494
|
toolStarts = /* @__PURE__ */ new Map();
|
|
1550
1495
|
mapUpdate(params) {
|
|
1551
|
-
const record =
|
|
1552
|
-
const update =
|
|
1496
|
+
const record = isRecord2(params) ? params : {};
|
|
1497
|
+
const update = isRecord2(record.update) ? record.update : {};
|
|
1553
1498
|
const kind = typeof update.sessionUpdate === "string" ? update.sessionUpdate : "";
|
|
1554
1499
|
if (kind === "agent_message_chunk" || kind === "user_message_chunk") {
|
|
1555
1500
|
const text = textFromContent(update.content);
|
|
@@ -1716,7 +1661,7 @@ var MOVE_DESTINATION_PATH_KEYS = [
|
|
|
1716
1661
|
"new_path",
|
|
1717
1662
|
"target"
|
|
1718
1663
|
];
|
|
1719
|
-
function
|
|
1664
|
+
function isRecord3(value) {
|
|
1720
1665
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1721
1666
|
}
|
|
1722
1667
|
function stringField(record, ...keys) {
|
|
@@ -1850,7 +1795,7 @@ function extractLocationPaths(locations, cwd) {
|
|
|
1850
1795
|
const paths = [];
|
|
1851
1796
|
const errors = [];
|
|
1852
1797
|
for (const value of locations) {
|
|
1853
|
-
if (!
|
|
1798
|
+
if (!isRecord3(value)) {
|
|
1854
1799
|
errors.push("locations contains a non-object entry");
|
|
1855
1800
|
continue;
|
|
1856
1801
|
}
|
|
@@ -1865,11 +1810,11 @@ function extractLocationPaths(locations, cwd) {
|
|
|
1865
1810
|
return { paths, provided: true, errors };
|
|
1866
1811
|
}
|
|
1867
1812
|
function mutationTargets(toolCall, kind, cwd) {
|
|
1868
|
-
const rawInput =
|
|
1813
|
+
const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
|
|
1869
1814
|
const raw = extractRawMutationPaths(rawInput, kind, cwd);
|
|
1870
1815
|
const locations = extractLocationPaths(toolCall?.locations, cwd);
|
|
1871
1816
|
const errors = [...raw.errors, ...locations.errors];
|
|
1872
|
-
if (toolCall?.rawInput !== void 0 && !
|
|
1817
|
+
if (toolCall?.rawInput !== void 0 && !isRecord3(toolCall.rawInput)) {
|
|
1873
1818
|
errors.push("rawInput must be an object");
|
|
1874
1819
|
}
|
|
1875
1820
|
if (raw.provided && locations.provided && !samePathSet(raw.paths, locations.paths)) {
|
|
@@ -1939,11 +1884,11 @@ function mapMutationToolCall(toolCall, kind, displayTool, cwd, metadataError) {
|
|
|
1939
1884
|
};
|
|
1940
1885
|
}
|
|
1941
1886
|
function mapPathBearingToolCall(toolCall, tool, displayTool, cwd, targetRequired) {
|
|
1942
|
-
const rawInput =
|
|
1887
|
+
const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
|
|
1943
1888
|
const raw = extractPathFields(rawInput, SINGLE_MUTATION_PATH_KEYS, MULTI_MUTATION_PATH_KEYS, cwd, "rawInput");
|
|
1944
1889
|
const locations = extractLocationPaths(toolCall?.locations, cwd);
|
|
1945
1890
|
const errors = [...raw.errors, ...locations.errors];
|
|
1946
|
-
if (toolCall?.rawInput !== void 0 && !
|
|
1891
|
+
if (toolCall?.rawInput !== void 0 && !isRecord3(toolCall.rawInput)) errors.push("rawInput must be an object");
|
|
1947
1892
|
if (raw.provided && locations.provided && !samePathSet(raw.paths, locations.paths)) {
|
|
1948
1893
|
errors.push("rawInput and locations contain conflicting path targets");
|
|
1949
1894
|
}
|
|
@@ -1964,7 +1909,7 @@ function mapPathBearingToolCall(toolCall, tool, displayTool, cwd, targetRequired
|
|
|
1964
1909
|
}
|
|
1965
1910
|
function mapToolCall(toolCall, cwd) {
|
|
1966
1911
|
const kind = typeof toolCall?.kind === "string" ? toolCall.kind.toLowerCase() : "";
|
|
1967
|
-
const rawInput =
|
|
1912
|
+
const rawInput = isRecord3(toolCall?.rawInput) ? toolCall.rawInput : {};
|
|
1968
1913
|
const rawTool = stringField(rawInput, "tool", "toolName", "tool_name", "name");
|
|
1969
1914
|
const title = typeof toolCall?.title === "string" ? toolCall.title : void 0;
|
|
1970
1915
|
const displayTool = rawTool ?? kind ?? title ?? "unknown";
|
|
@@ -2068,9 +2013,9 @@ var AcpToolMediator = class {
|
|
|
2068
2013
|
async handle(params) {
|
|
2069
2014
|
const startedAt = performance3.now();
|
|
2070
2015
|
this.requested += 1;
|
|
2071
|
-
const parsed =
|
|
2016
|
+
const parsed = isRecord3(params) ? params : {};
|
|
2072
2017
|
const options = Array.isArray(parsed.options) ? parsed.options : [];
|
|
2073
|
-
const toolCall =
|
|
2018
|
+
const toolCall = isRecord3(parsed.toolCall) ? parsed.toolCall : void 0;
|
|
2074
2019
|
const mapped = mapToolCall(toolCall, this.input.cwd);
|
|
2075
2020
|
let decision = "denied";
|
|
2076
2021
|
let reason;
|
|
@@ -2173,6 +2118,7 @@ var AcpToolMediator = class {
|
|
|
2173
2118
|
init_esm_shims();
|
|
2174
2119
|
var ACP_USAGE_META_KEY = "clio-coder/usage";
|
|
2175
2120
|
var ACP_SESSION_META_KEY = "clio-coder/session";
|
|
2121
|
+
var ACP_AGENT_META_KEY = "clio-coder/agent";
|
|
2176
2122
|
var ACP_MAX_STRING_BYTES = 4096;
|
|
2177
2123
|
var ACP_MAX_RAW_RECORD_BYTES = 32768;
|
|
2178
2124
|
var ACP_MAX_CHUNK_BYTES = 16384;
|
|
@@ -2191,7 +2137,7 @@ var AsyncEventQueue = class {
|
|
|
2191
2137
|
const value = this.values.shift();
|
|
2192
2138
|
if (value !== void 0) return Promise.resolve({ done: false, value });
|
|
2193
2139
|
if (this.done) return Promise.resolve({ done: true, value: void 0 });
|
|
2194
|
-
return new Promise((
|
|
2140
|
+
return new Promise((resolve4) => this.waiters.push(resolve4));
|
|
2195
2141
|
}
|
|
2196
2142
|
push(value) {
|
|
2197
2143
|
if (this.done) return;
|
|
@@ -2211,22 +2157,22 @@ var AsyncEventQueue = class {
|
|
|
2211
2157
|
}
|
|
2212
2158
|
}
|
|
2213
2159
|
};
|
|
2214
|
-
function
|
|
2160
|
+
function isRecord4(value) {
|
|
2215
2161
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2216
2162
|
}
|
|
2217
2163
|
function sessionIdFrom(value) {
|
|
2218
2164
|
if (typeof value === "string" && value.length > 0) return value;
|
|
2219
|
-
if (!
|
|
2165
|
+
if (!isRecord4(value)) return null;
|
|
2220
2166
|
const sessionId = value.sessionId ?? value.id;
|
|
2221
2167
|
return typeof sessionId === "string" && sessionId.length > 0 ? sessionId : null;
|
|
2222
2168
|
}
|
|
2223
2169
|
function supportsSessionClose(init) {
|
|
2224
2170
|
const caps = init?.agentCapabilities;
|
|
2225
|
-
if (!
|
|
2226
|
-
const meta =
|
|
2227
|
-
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;
|
|
2228
2174
|
const sessionCaps = caps.sessionCapabilities;
|
|
2229
|
-
return
|
|
2175
|
+
return isRecord4(sessionCaps) && isRecord4(sessionCaps.close);
|
|
2230
2176
|
}
|
|
2231
2177
|
function flattenPrompt(input) {
|
|
2232
2178
|
const parts = [
|
|
@@ -2250,7 +2196,7 @@ function finite(value) {
|
|
|
2250
2196
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
2251
2197
|
}
|
|
2252
2198
|
function mergeUsage(into, raw) {
|
|
2253
|
-
if (!
|
|
2199
|
+
if (!isRecord4(raw)) return;
|
|
2254
2200
|
into.inputTokens += finite(raw.input) + finite(raw.inputTokens) + finite(raw.input_tokens);
|
|
2255
2201
|
into.outputTokens += finite(raw.output) + finite(raw.outputTokens) + finite(raw.output_tokens);
|
|
2256
2202
|
into.cacheReadTokens += finite(raw.cacheRead) + finite(raw.cacheReadTokens) + finite(raw.cache_read_tokens);
|
|
@@ -2276,7 +2222,14 @@ function errorEvents(messageText2) {
|
|
|
2276
2222
|
function startAcpDelegationRun(input) {
|
|
2277
2223
|
const connectTimeoutMs = input.agent.connectTimeoutMs ?? DEFAULT_DELEGATION_CONNECT_TIMEOUT_MS;
|
|
2278
2224
|
const turnTimeoutMs = input.agent.turnTimeoutMs ?? DEFAULT_DELEGATION_TURN_TIMEOUT_MS;
|
|
2279
|
-
const
|
|
2225
|
+
const now = input.now ?? Date.now;
|
|
2226
|
+
const monotonicNow = input.monotonicNow ?? (() => performance4.now());
|
|
2227
|
+
const heartbeatWallAnchor = now();
|
|
2228
|
+
const heartbeatMonotonicAnchor = monotonicNow();
|
|
2229
|
+
const heartbeatAt = {
|
|
2230
|
+
current: heartbeatWallAnchor,
|
|
2231
|
+
monotonic: heartbeatMonotonicAnchor
|
|
2232
|
+
};
|
|
2280
2233
|
const queue = new AsyncEventQueue();
|
|
2281
2234
|
const usage = emptyUsage();
|
|
2282
2235
|
const mapper = new AcpEventMapper();
|
|
@@ -2303,7 +2256,9 @@ function startAcpDelegationRun(input) {
|
|
|
2303
2256
|
cancelTimer = null;
|
|
2304
2257
|
};
|
|
2305
2258
|
const emit = (event) => {
|
|
2306
|
-
|
|
2259
|
+
const stamp = monotonicNow();
|
|
2260
|
+
heartbeatAt.monotonic = stamp;
|
|
2261
|
+
heartbeatAt.current = heartbeatWallAnchor + (stamp - heartbeatMonotonicAnchor);
|
|
2307
2262
|
queue.push(event);
|
|
2308
2263
|
};
|
|
2309
2264
|
const mediator = new AcpToolMediator({
|
|
@@ -2387,7 +2342,7 @@ function startAcpDelegationRun(input) {
|
|
|
2387
2342
|
},
|
|
2388
2343
|
turnTimeoutMs
|
|
2389
2344
|
);
|
|
2390
|
-
const metaUsage =
|
|
2345
|
+
const metaUsage = isRecord4(promptResponse?._meta) ? promptResponse._meta[ACP_USAGE_META_KEY] : void 0;
|
|
2391
2346
|
if (metaUsage !== void 0) {
|
|
2392
2347
|
mergeUsage(usage, metaUsage);
|
|
2393
2348
|
} else {
|
|
@@ -2478,62 +2433,6 @@ function startAcpDelegationRun(input) {
|
|
|
2478
2433
|
// src/domains/prompts/compiler.ts
|
|
2479
2434
|
init_esm_shims();
|
|
2480
2435
|
import { join as join3 } from "node:path";
|
|
2481
|
-
|
|
2482
|
-
// src/domains/prompts/hash.ts
|
|
2483
|
-
init_esm_shims();
|
|
2484
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
2485
|
-
function sha256(input) {
|
|
2486
|
-
return createHash2("sha256").update(input, "utf8").digest("hex");
|
|
2487
|
-
}
|
|
2488
|
-
function canonicalJson2(value) {
|
|
2489
|
-
return serialize(value);
|
|
2490
|
-
}
|
|
2491
|
-
function serialize(value) {
|
|
2492
|
-
if (value === null) return "null";
|
|
2493
|
-
if (typeof value === "number") {
|
|
2494
|
-
if (!Number.isFinite(value)) {
|
|
2495
|
-
throw new Error(`canonicalJson: non-finite number ${String(value)} is not representable`);
|
|
2496
|
-
}
|
|
2497
|
-
return JSON.stringify(value);
|
|
2498
|
-
}
|
|
2499
|
-
if (typeof value === "string" || typeof value === "boolean") {
|
|
2500
|
-
return JSON.stringify(value);
|
|
2501
|
-
}
|
|
2502
|
-
if (typeof value === "bigint") {
|
|
2503
|
-
throw new Error("canonicalJson: bigint is not representable");
|
|
2504
|
-
}
|
|
2505
|
-
if (typeof value === "symbol" || typeof value === "function") {
|
|
2506
|
-
throw new Error(`canonicalJson: ${typeof value} is not representable`);
|
|
2507
|
-
}
|
|
2508
|
-
if (value === void 0) {
|
|
2509
|
-
throw new Error("canonicalJson: undefined is not representable at root");
|
|
2510
|
-
}
|
|
2511
|
-
if (Array.isArray(value)) {
|
|
2512
|
-
const parts = [];
|
|
2513
|
-
for (let i = 0; i < value.length; i++) {
|
|
2514
|
-
if (!(i in value) || value[i] === void 0) {
|
|
2515
|
-
parts.push("null");
|
|
2516
|
-
continue;
|
|
2517
|
-
}
|
|
2518
|
-
parts.push(serialize(value[i]));
|
|
2519
|
-
}
|
|
2520
|
-
return `[${parts.join(",")}]`;
|
|
2521
|
-
}
|
|
2522
|
-
if (typeof value === "object") {
|
|
2523
|
-
const obj = value;
|
|
2524
|
-
const keys = Object.keys(obj).sort();
|
|
2525
|
-
const parts = [];
|
|
2526
|
-
for (const key of keys) {
|
|
2527
|
-
const child = obj[key];
|
|
2528
|
-
if (child === void 0) continue;
|
|
2529
|
-
parts.push(`${JSON.stringify(key)}:${serialize(child)}`);
|
|
2530
|
-
}
|
|
2531
|
-
return `{${parts.join(",")}}`;
|
|
2532
|
-
}
|
|
2533
|
-
throw new Error(`canonicalJson: unsupported value of type ${typeof value}`);
|
|
2534
|
-
}
|
|
2535
|
-
|
|
2536
|
-
// src/domains/prompts/compiler.ts
|
|
2537
2436
|
var FLEET_ROUTING_GUIDANCE = 'Fleet routing: pin the `agent` id from the Fleet section; agent:"auto" baselines from the task text and is a fallback, not a router.';
|
|
2538
2437
|
var WORKER_CLAIM_GUIDANCE = 'Never claim a completion, a validation, or a file change that no tool call in this run supports. If you did not run it or write it here, say "not verified" and report what you did do.';
|
|
2539
2438
|
function lookupFragment(table, id, role) {
|
|
@@ -2745,15 +2644,45 @@ function renderProjectBlock(contextFiles) {
|
|
|
2745
2644
|
|
|
2746
2645
|
${trimmedFiles}`;
|
|
2747
2646
|
}
|
|
2748
|
-
function renderMemoryBlock(memorySection) {
|
|
2647
|
+
function renderMemoryBlock(memorySection, legacyDuplicateHeader = false) {
|
|
2749
2648
|
const trimmed = memorySection?.trim() ?? "";
|
|
2750
|
-
|
|
2649
|
+
if (trimmed.length === 0) return "";
|
|
2650
|
+
if (legacyDuplicateHeader) return `# Memory
|
|
2651
|
+
|
|
2652
|
+
${trimmed}`;
|
|
2653
|
+
return /^#\s+Memory\s*$/.test(trimmed.split("\n", 1)[0] ?? "") ? trimmed : `# Memory
|
|
2751
2654
|
|
|
2752
2655
|
${trimmed}`;
|
|
2753
2656
|
}
|
|
2754
2657
|
function estimatePromptTokens(text) {
|
|
2755
2658
|
return ceilChars(text.trim().length);
|
|
2756
2659
|
}
|
|
2660
|
+
var SESSION_PROMPT_SECTION_ORDER = [
|
|
2661
|
+
"identity",
|
|
2662
|
+
"operating-contract",
|
|
2663
|
+
"delegation",
|
|
2664
|
+
"skills",
|
|
2665
|
+
"safety",
|
|
2666
|
+
"tool-contract",
|
|
2667
|
+
"fleet",
|
|
2668
|
+
"retrieval-hints",
|
|
2669
|
+
"project-context",
|
|
2670
|
+
"memory",
|
|
2671
|
+
"runtime"
|
|
2672
|
+
];
|
|
2673
|
+
var LEGACY_SESSION_PROMPT_SECTION_ORDER = [
|
|
2674
|
+
"identity",
|
|
2675
|
+
"operating-contract",
|
|
2676
|
+
"delegation",
|
|
2677
|
+
"skills",
|
|
2678
|
+
"safety",
|
|
2679
|
+
"runtime",
|
|
2680
|
+
"tool-contract",
|
|
2681
|
+
"fleet",
|
|
2682
|
+
"retrieval-hints",
|
|
2683
|
+
"memory",
|
|
2684
|
+
"project-context"
|
|
2685
|
+
];
|
|
2757
2686
|
function compile(table, inputs) {
|
|
2758
2687
|
const identity = lookupFragment(table, inputs.identity, "identity");
|
|
2759
2688
|
const operatingContract = lookupFragment(table, inputs.operatingContract, "operating contract");
|
|
@@ -2773,24 +2702,29 @@ function compile(table, inputs) {
|
|
|
2773
2702
|
const docsRouting = selfAwareness && sessionHasContext(session) ? table.byId.get("identity.docs-routing") : void 0;
|
|
2774
2703
|
if (selfAwareness) {
|
|
2775
2704
|
const packageRoot = resolvePackageRoot();
|
|
2776
|
-
const
|
|
2777
|
-
identityBody = [identity.body.trim(),
|
|
2705
|
+
const rendered2 = selfAwareness.body.replace("{CLIO_DOCS_PATH}", join3(packageRoot, "docs")).replace("{CLIO_SRC_PATH}", join3(packageRoot, "src")).replace("{CLIO_CODEWIKI_PATH}", join3(packageRoot, "dist", "assets", "codewiki.json"));
|
|
2706
|
+
identityBody = [identity.body.trim(), rendered2.trim(), ...docsRouting ? [docsRouting.body.trim()] : []].join(
|
|
2778
2707
|
"\n\n"
|
|
2779
2708
|
);
|
|
2780
2709
|
}
|
|
2781
2710
|
const delegation = sessionCanDispatch(session) ? table.byId.get("operating.delegation") : void 0;
|
|
2782
2711
|
const skills = sessionHasContext(session) ? table.byId.get("operating.skills") : void 0;
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2712
|
+
const legacy = inputs.sectionOrder === "legacy-0.3.8";
|
|
2713
|
+
const rendered = /* @__PURE__ */ new Map([
|
|
2714
|
+
["identity", identityBody],
|
|
2715
|
+
["operating-contract", operatingContract.body],
|
|
2716
|
+
["delegation", delegation?.body ?? ""],
|
|
2717
|
+
["skills", skills?.body ?? ""],
|
|
2718
|
+
["safety", renderSafetySection(safety, autonomyLevel)],
|
|
2719
|
+
["runtime", renderRuntimeBlock(session)],
|
|
2720
|
+
["tool-contract", renderToolContractBlock(session)],
|
|
2721
|
+
["fleet", renderFleetBlock(session)],
|
|
2722
|
+
["retrieval-hints", renderRetrievalHintsBlock(session)],
|
|
2723
|
+
["memory", renderMemoryBlock(session.memorySection, legacy)],
|
|
2724
|
+
["project-context", renderProjectBlock(session.contextFiles)]
|
|
2725
|
+
]);
|
|
2726
|
+
const order = legacy ? LEGACY_SESSION_PROMPT_SECTION_ORDER : SESSION_PROMPT_SECTION_ORDER;
|
|
2727
|
+
for (const id of order) push(id, rendered.get(id) ?? "");
|
|
2794
2728
|
for (const fragment of inputs.additionalFragments ?? []) {
|
|
2795
2729
|
push(fragment.id, fragment.body);
|
|
2796
2730
|
}
|
|
@@ -2926,8 +2860,8 @@ function createAssignmentEventStream(options = {}) {
|
|
|
2926
2860
|
return Promise.resolve({ value: pending.shift(), done: false });
|
|
2927
2861
|
}
|
|
2928
2862
|
if (finished || abandoned) return Promise.resolve({ value: void 0, done: true });
|
|
2929
|
-
return new Promise((
|
|
2930
|
-
waiters.push(
|
|
2863
|
+
return new Promise((resolve4) => {
|
|
2864
|
+
waiters.push(resolve4);
|
|
2931
2865
|
});
|
|
2932
2866
|
},
|
|
2933
2867
|
return() {
|
|
@@ -3031,10 +2965,10 @@ var AssignmentRegistry = class {
|
|
|
3031
2965
|
const id = asAssignmentId(rootRunId);
|
|
3032
2966
|
const existing = this.#assignments.get(id);
|
|
3033
2967
|
if (existing) return this.#snapshot(existing);
|
|
3034
|
-
let
|
|
2968
|
+
let resolve4;
|
|
3035
2969
|
let reject;
|
|
3036
2970
|
const terminal = new Promise((resolvePromise, rejectPromise) => {
|
|
3037
|
-
|
|
2971
|
+
resolve4 = resolvePromise;
|
|
3038
2972
|
reject = rejectPromise;
|
|
3039
2973
|
});
|
|
3040
2974
|
const assignment = {
|
|
@@ -3049,7 +2983,7 @@ var AssignmentRegistry = class {
|
|
|
3049
2983
|
outcomeDetail: null,
|
|
3050
2984
|
terminal,
|
|
3051
2985
|
stream: createAssignmentEventStream(this.#onStreamError !== void 0 ? { onError: this.#onStreamError } : {}),
|
|
3052
|
-
resolve:
|
|
2986
|
+
resolve: resolve4,
|
|
3053
2987
|
reject
|
|
3054
2988
|
};
|
|
3055
2989
|
this.#assignments.set(id, assignment);
|
|
@@ -3289,10 +3223,10 @@ function createAdmissionQueue(options) {
|
|
|
3289
3223
|
const effectiveDeadline = Math.min(request.deadlineAt, request.queuedAt + options.finiteCeilingMs);
|
|
3290
3224
|
if (!Number.isFinite(effectiveDeadline))
|
|
3291
3225
|
return Promise.reject(new Error("dispatch: queued request requires a finite deadline"));
|
|
3292
|
-
return new Promise((
|
|
3226
|
+
return new Promise((resolve4, reject) => {
|
|
3293
3227
|
const bounded = { ...request, deadlineAt: effectiveDeadline };
|
|
3294
3228
|
const timer = setTimeout(() => remove(request.requestId, "timed_out"), Math.max(0, effectiveDeadline - now()));
|
|
3295
|
-
entries.set(request.requestId, { request: bounded, resolve:
|
|
3229
|
+
entries.set(request.requestId, { request: bounded, resolve: resolve4, reject, timer });
|
|
3296
3230
|
});
|
|
3297
3231
|
},
|
|
3298
3232
|
cancel(requestId) {
|
|
@@ -3355,14 +3289,18 @@ init_esm_shims();
|
|
|
3355
3289
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
3356
3290
|
var MAX_RESERVATION_RECORDS = 500;
|
|
3357
3291
|
var DEFAULT_RESERVATION_TTL_MS = 15 * 6e4;
|
|
3292
|
+
function endpointCapacityDenial(input) {
|
|
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}`;
|
|
3295
|
+
}
|
|
3358
3296
|
function copyRecord(record) {
|
|
3359
3297
|
return { ...record, members: record.members.map((member) => ({ ...member })) };
|
|
3360
3298
|
}
|
|
3361
3299
|
function validRecord(value) {
|
|
3362
3300
|
if (typeof value !== "object" || value === null) return false;
|
|
3363
3301
|
const record = value;
|
|
3364
|
-
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(
|
|
3365
|
-
(member) => typeof member.memberId === "string" && Number.isInteger(member.wave) && typeof member.nodeId === "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")
|
|
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(
|
|
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")
|
|
3366
3304
|
);
|
|
3367
3305
|
}
|
|
3368
3306
|
function parseReservations(values) {
|
|
@@ -3399,9 +3337,13 @@ function reservationAllocation(tasks) {
|
|
|
3399
3337
|
)
|
|
3400
3338
|
);
|
|
3401
3339
|
const nodeSlots = peakBy(tasks.map((task) => ({ wave: task.wave, key: task.nodeId })));
|
|
3340
|
+
const endpointSlots = peakBy(
|
|
3341
|
+
tasks.flatMap((task) => task.endpointKey === void 0 ? [] : [{ wave: task.wave, key: task.endpointKey }])
|
|
3342
|
+
);
|
|
3402
3343
|
return {
|
|
3403
3344
|
globalSlots,
|
|
3404
3345
|
nodeSlots,
|
|
3346
|
+
endpointSlots,
|
|
3405
3347
|
budgetUsd: tasks.reduce((sum, task) => sum + task.costUpperBoundUsd, 0)
|
|
3406
3348
|
};
|
|
3407
3349
|
}
|
|
@@ -3411,7 +3353,7 @@ function outstandingTasks(record) {
|
|
|
3411
3353
|
function outstandingBudget(record) {
|
|
3412
3354
|
return record.members.filter((member) => member.status === "held" || member.status === "consumed").reduce((sum, member) => sum + member.costUpperBoundUsd, 0);
|
|
3413
3355
|
}
|
|
3414
|
-
function allocateReservation(tasks, existing, capacity) {
|
|
3356
|
+
function allocateReservation(tasks, existing, capacity, topology) {
|
|
3415
3357
|
if (tasks.length === 0) return { ok: false, reason: "reservation requires at least one task" };
|
|
3416
3358
|
const duplicate = tasks.find((task, index) => tasks.slice(0, index).some((entry) => entry.memberId === task.memberId));
|
|
3417
3359
|
if (duplicate) return { ok: false, reason: `duplicate reservation member '${duplicate.memberId}'` };
|
|
@@ -3434,6 +3376,27 @@ function allocateReservation(tasks, existing, capacity) {
|
|
|
3434
3376
|
return { ok: false, reason: `node '${nodeId}' capacity exceeded (${used + slots}/${node.limit})` };
|
|
3435
3377
|
}
|
|
3436
3378
|
}
|
|
3379
|
+
for (const [endpointKey, slots] of Object.entries(requested.endpointSlots)) {
|
|
3380
|
+
const endpoint = capacity.endpoints[endpointKey];
|
|
3381
|
+
if (!endpoint || !Number.isFinite(endpoint.limit)) continue;
|
|
3382
|
+
const heldSlots = held2.reduce((sum, allocation) => sum + (allocation.endpointSlots[endpointKey] ?? 0), 0);
|
|
3383
|
+
const used = endpoint.active + heldSlots;
|
|
3384
|
+
if (used + slots > endpoint.limit) {
|
|
3385
|
+
return {
|
|
3386
|
+
ok: false,
|
|
3387
|
+
reason: endpointCapacityDenial({
|
|
3388
|
+
endpointKey,
|
|
3389
|
+
limit: endpoint.limit,
|
|
3390
|
+
used,
|
|
3391
|
+
requested: slots,
|
|
3392
|
+
leases: endpoint.leases ?? endpoint.active - (endpoint.foregroundStreams ?? 0),
|
|
3393
|
+
reservations: heldSlots,
|
|
3394
|
+
foregroundStreams: endpoint.foregroundStreams ?? 0,
|
|
3395
|
+
...topology === void 0 ? {} : { topology }
|
|
3396
|
+
})
|
|
3397
|
+
};
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3437
3400
|
const existingBudget = activeRecords.reduce((sum, record) => sum + outstandingBudget(record), 0);
|
|
3438
3401
|
const projected = capacity.budget.currentUsd + existingBudget + requested.budgetUsd;
|
|
3439
3402
|
if (projected >= capacity.budget.ceilingUsd) {
|
|
@@ -3457,11 +3420,13 @@ function createDispatchReservation(input) {
|
|
|
3457
3420
|
`dispatch: reservation denied: capacity is draining (requested by pid ${drain.requestedByPid} at ${drain.requestedAt})`
|
|
3458
3421
|
);
|
|
3459
3422
|
}
|
|
3460
|
-
const planned = allocateReservation(input.tasks, records, input.capacity);
|
|
3423
|
+
const planned = allocateReservation(input.tasks, records, input.capacity, input.topology);
|
|
3461
3424
|
if (!planned.ok) {
|
|
3462
3425
|
replaceReservations(state, records);
|
|
3463
3426
|
writeCapacityStateUnsafe(state);
|
|
3464
|
-
throw new Error(
|
|
3427
|
+
throw new Error(
|
|
3428
|
+
planned.reason.startsWith("dispatch:") ? planned.reason : `dispatch: reservation denied: ${planned.reason}`
|
|
3429
|
+
);
|
|
3465
3430
|
}
|
|
3466
3431
|
const createdAt = new Date(nowMs).toISOString();
|
|
3467
3432
|
const record = {
|
|
@@ -3484,6 +3449,7 @@ function transferDispatchReservationToLease(input) {
|
|
|
3484
3449
|
return acquireCapacityLease({
|
|
3485
3450
|
assignmentId: input.assignmentId,
|
|
3486
3451
|
nodeId: input.nodeId,
|
|
3452
|
+
...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
|
|
3487
3453
|
limits: input.limits,
|
|
3488
3454
|
nowMs,
|
|
3489
3455
|
...input.ttlMs !== void 0 ? { ttlMs: input.ttlMs } : {},
|
|
@@ -3511,10 +3477,37 @@ function rebindDispatchReservationMember(input) {
|
|
|
3511
3477
|
if (member.status === "released") {
|
|
3512
3478
|
throw new Error(`dispatch: reservation member '${input.memberId}' was already released`);
|
|
3513
3479
|
}
|
|
3514
|
-
if (member.nodeId === input.nodeId && member.costUpperBoundUsd === input.costUpperBoundUsd) {
|
|
3480
|
+
if (member.nodeId === input.nodeId && member.endpointKey === input.endpointKey && member.costUpperBoundUsd === input.costUpperBoundUsd) {
|
|
3515
3481
|
return copyRecord(record);
|
|
3516
3482
|
}
|
|
3517
3483
|
const others = records.filter((entry) => entry.status === "active" && entry.ownerId !== input.ownerId);
|
|
3484
|
+
if (member.endpointKey !== input.endpointKey && input.endpointKey !== void 0) {
|
|
3485
|
+
const endpointKey = input.endpointKey;
|
|
3486
|
+
const endpoint = input.capacity.endpoints[endpointKey];
|
|
3487
|
+
if (endpoint !== void 0 && Number.isFinite(endpoint.limit)) {
|
|
3488
|
+
const siblingSlots = record.members.filter(
|
|
3489
|
+
(entry) => entry !== member && entry.status !== "released" && entry.endpointKey === endpointKey
|
|
3490
|
+
).length;
|
|
3491
|
+
const otherHeld = others.reduce(
|
|
3492
|
+
(sum, entry) => sum + (reservationAllocation(outstandingTasks(entry)).endpointSlots[endpointKey] ?? 0),
|
|
3493
|
+
0
|
|
3494
|
+
);
|
|
3495
|
+
const used = endpoint.active + otherHeld + siblingSlots;
|
|
3496
|
+
if (used + 1 > endpoint.limit) {
|
|
3497
|
+
throw new Error(
|
|
3498
|
+
endpointCapacityDenial({
|
|
3499
|
+
endpointKey,
|
|
3500
|
+
limit: endpoint.limit,
|
|
3501
|
+
used,
|
|
3502
|
+
requested: 1,
|
|
3503
|
+
leases: endpoint.leases ?? endpoint.active - (endpoint.foregroundStreams ?? 0),
|
|
3504
|
+
reservations: otherHeld + siblingSlots,
|
|
3505
|
+
foregroundStreams: endpoint.foregroundStreams ?? 0
|
|
3506
|
+
})
|
|
3507
|
+
);
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3518
3511
|
if (member.nodeId !== input.nodeId) {
|
|
3519
3512
|
const node = input.capacity.nodes[input.nodeId];
|
|
3520
3513
|
if (node !== void 0 && Number.isFinite(node.limit)) {
|
|
@@ -3542,6 +3535,8 @@ function rebindDispatchReservationMember(input) {
|
|
|
3542
3535
|
);
|
|
3543
3536
|
}
|
|
3544
3537
|
member.nodeId = input.nodeId;
|
|
3538
|
+
if (input.endpointKey === void 0) delete member.endpointKey;
|
|
3539
|
+
else member.endpointKey = input.endpointKey;
|
|
3545
3540
|
member.costUpperBoundUsd = Math.max(0, input.costUpperBoundUsd);
|
|
3546
3541
|
writeStore2(records);
|
|
3547
3542
|
return copyRecord(record);
|
|
@@ -3564,6 +3559,24 @@ function releaseDispatchReservationMember(ownerId, memberId, nowMs = Date.now())
|
|
|
3564
3559
|
return copyRecord(record);
|
|
3565
3560
|
});
|
|
3566
3561
|
}
|
|
3562
|
+
function releaseDispatchReservation(ownerId, nowMs = Date.now()) {
|
|
3563
|
+
return withStateFileLockSync(capacityStateLockPath(), () => {
|
|
3564
|
+
const records = readStore2();
|
|
3565
|
+
const record = records.find((entry) => entry.ownerId === ownerId);
|
|
3566
|
+
if (!record) return null;
|
|
3567
|
+
if (record.status !== "active") return copyRecord(record);
|
|
3568
|
+
const settledAt = new Date(nowMs).toISOString();
|
|
3569
|
+
for (const member of record.members) {
|
|
3570
|
+
if (member.status === "released") continue;
|
|
3571
|
+
member.status = "released";
|
|
3572
|
+
member.releasedAt = settledAt;
|
|
3573
|
+
}
|
|
3574
|
+
record.status = "released";
|
|
3575
|
+
record.settledAt = settledAt;
|
|
3576
|
+
writeStore2(records);
|
|
3577
|
+
return copyRecord(record);
|
|
3578
|
+
});
|
|
3579
|
+
}
|
|
3567
3580
|
function rollbackDispatchReservation(ownerId, nowMs = Date.now()) {
|
|
3568
3581
|
return withStateFileLockSync(capacityStateLockPath(), () => {
|
|
3569
3582
|
const records = readStore2();
|
|
@@ -3668,6 +3681,20 @@ var PUMP_MIN_MS = 10;
|
|
|
3668
3681
|
var PUMP_MAX_MS = 500;
|
|
3669
3682
|
function describeAdmissionFailure(input) {
|
|
3670
3683
|
if (input.state === "canceled") return "dispatch: admission canceled before a capacity slot opened";
|
|
3684
|
+
if (input.endpointKey !== void 0) {
|
|
3685
|
+
const endpointLimit = input.limits.endpoints[input.endpointKey];
|
|
3686
|
+
const endpointActive = input.usage.endpoints[input.endpointKey] ?? 0;
|
|
3687
|
+
if (endpointLimit !== void 0 && endpointActive >= endpointLimit) {
|
|
3688
|
+
const holders = input.usage.endpointHolders?.[input.endpointKey];
|
|
3689
|
+
const occupancy = holders === void 0 ? "the supplied capacity snapshot does not attribute the occupied slots" : describeEndpointCapacityHolders(holders);
|
|
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("");
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3671
3698
|
const nodeLimit = input.limits.nodes[input.nodeId];
|
|
3672
3699
|
const nodeActive = input.usage.nodes[input.nodeId] ?? 0;
|
|
3673
3700
|
const where = nodeLimit === void 0 ? `${input.usage.global}/${input.limits.global} worker slots in use` : `${nodeActive}/${nodeLimit} worker slots in use on '${input.nodeId}', ${input.usage.global}/${input.limits.global} globally`;
|
|
@@ -3759,11 +3786,13 @@ function createCapacityAdmissionController(options) {
|
|
|
3759
3786
|
memberId: input.reservation.memberId,
|
|
3760
3787
|
assignmentId: input.assignmentId,
|
|
3761
3788
|
nodeId: input.nodeId,
|
|
3789
|
+
...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
|
|
3762
3790
|
limits: options.limits(),
|
|
3763
3791
|
nowMs: now()
|
|
3764
3792
|
}) : acquireCapacityLease({
|
|
3765
3793
|
assignmentId: input.assignmentId,
|
|
3766
3794
|
nodeId: input.nodeId,
|
|
3795
|
+
...input.endpointKey !== void 0 ? { endpointKey: input.endpointKey } : {},
|
|
3767
3796
|
limits: options.limits(),
|
|
3768
3797
|
nowMs: now()
|
|
3769
3798
|
})
|
|
@@ -3771,17 +3800,18 @@ function createCapacityAdmissionController(options) {
|
|
|
3771
3800
|
pumpNow();
|
|
3772
3801
|
const outcome = await outcomePromise;
|
|
3773
3802
|
if (outcome.state !== "admitted") {
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
);
|
|
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);
|
|
3785
3815
|
}
|
|
3786
3816
|
const lease = acquired.get(input.assignmentId);
|
|
3787
3817
|
if (!lease) throw new Error("dispatch: admitted request has no capacity lease");
|
|
@@ -4344,7 +4374,7 @@ function assessCapabilityMismatch(input) {
|
|
|
4344
4374
|
|
|
4345
4375
|
// src/domains/dispatch/checkout-writer-lease.ts
|
|
4346
4376
|
init_esm_shims();
|
|
4347
|
-
import { createHash as
|
|
4377
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
4348
4378
|
import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync5, realpathSync, unlinkSync } from "node:fs";
|
|
4349
4379
|
import { dirname, join as join6 } from "node:path";
|
|
4350
4380
|
var held = /* @__PURE__ */ new Map();
|
|
@@ -4354,7 +4384,7 @@ function canonicalCheckout(checkout) {
|
|
|
4354
4384
|
}
|
|
4355
4385
|
function checkoutWriterLeasePath(checkout) {
|
|
4356
4386
|
const canonical = canonicalCheckout(checkout);
|
|
4357
|
-
const key =
|
|
4387
|
+
const key = createHash2("sha256").update(canonical, "utf8").digest("hex");
|
|
4358
4388
|
return join6(clioStateDir(), "checkout-writer-leases", `${key}.json`);
|
|
4359
4389
|
}
|
|
4360
4390
|
function validRecord3(value) {
|
|
@@ -4554,8 +4584,11 @@ function isInfrastructureFailure(failureClass) {
|
|
|
4554
4584
|
// src/domains/dispatch/heartbeat.ts
|
|
4555
4585
|
init_esm_shims();
|
|
4556
4586
|
var DEFAULT_HEARTBEAT_SPEC = { windowMs: 5e3, graceMs: 1e4 };
|
|
4557
|
-
function
|
|
4558
|
-
|
|
4587
|
+
function heartbeatMonotonicAt(heartbeat) {
|
|
4588
|
+
return heartbeat.monotonic ?? heartbeat.current;
|
|
4589
|
+
}
|
|
4590
|
+
function classifyHeartbeat(heartbeatMonotonicAt2, monotonicNow, spec) {
|
|
4591
|
+
const age = monotonicNow - heartbeatMonotonicAt2;
|
|
4559
4592
|
if (age <= spec.windowMs) return "alive";
|
|
4560
4593
|
if (age <= spec.windowMs + spec.graceMs) return "stale";
|
|
4561
4594
|
return "dead";
|
|
@@ -4564,14 +4597,14 @@ function classifyHeartbeat(heartbeatAt, now, spec) {
|
|
|
4564
4597
|
// src/domains/dispatch/host-verification.ts
|
|
4565
4598
|
init_esm_shims();
|
|
4566
4599
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
4567
|
-
import { createHash as
|
|
4600
|
+
import { createHash as createHash4, randomUUID } from "node:crypto";
|
|
4568
4601
|
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4569
4602
|
import { dirname as dirname2, join as join8, resolve as resolve3 } from "node:path";
|
|
4570
4603
|
|
|
4571
4604
|
// src/domains/dispatch/code-step.ts
|
|
4572
4605
|
init_esm_shims();
|
|
4573
4606
|
import { execFileSync, spawn as spawn2 } from "node:child_process";
|
|
4574
|
-
import { createHash as
|
|
4607
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
4575
4608
|
import { mkdirSync as mkdirSync2, writeFileSync } from "node:fs";
|
|
4576
4609
|
import { isAbsolute, join as join7, resolve as resolve2 } from "node:path";
|
|
4577
4610
|
var CODE_STEP_CAPTURE_MAX_BYTES = 1048576;
|
|
@@ -4591,10 +4624,10 @@ function canonicalCodeReport(report) {
|
|
|
4591
4624
|
});
|
|
4592
4625
|
}
|
|
4593
4626
|
function codeReportDigest(report) {
|
|
4594
|
-
return
|
|
4627
|
+
return createHash3("sha256").update(canonicalCodeReport(report), "utf8").digest("hex");
|
|
4595
4628
|
}
|
|
4596
4629
|
function sha2562(value) {
|
|
4597
|
-
return
|
|
4630
|
+
return createHash3("sha256").update(value, "utf8").digest("hex");
|
|
4598
4631
|
}
|
|
4599
4632
|
function tailUtf8(value, limit, marker) {
|
|
4600
4633
|
if (value.length <= limit) return { text: value.toString("utf8"), truncated: false };
|
|
@@ -4644,7 +4677,7 @@ function workspaceHasChanges(root) {
|
|
|
4644
4677
|
return status.trim().length > 0;
|
|
4645
4678
|
}
|
|
4646
4679
|
function newCodeRunId() {
|
|
4647
|
-
return `code-${
|
|
4680
|
+
return `code-${createHash3("sha256").update(`${process.pid}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 12)}`;
|
|
4648
4681
|
}
|
|
4649
4682
|
async function spawnCommand(input, cwd, argv) {
|
|
4650
4683
|
const command = input.command;
|
|
@@ -4808,7 +4841,7 @@ ${spawned.spawnError}
|
|
|
4808
4841
|
var OUTPUT_TAIL_BYTES = 2048;
|
|
4809
4842
|
var MEMO_VERSION = 1;
|
|
4810
4843
|
function sha2563(value) {
|
|
4811
|
-
return
|
|
4844
|
+
return createHash4("sha256").update(value, "utf8").digest("hex");
|
|
4812
4845
|
}
|
|
4813
4846
|
function outputTail(value) {
|
|
4814
4847
|
const bytes = Buffer.from(value, "utf8");
|
|
@@ -5577,7 +5610,7 @@ function selectApprovedRecoveryCandidates(input) {
|
|
|
5577
5610
|
// src/domains/dispatch/reproducibility.ts
|
|
5578
5611
|
init_esm_shims();
|
|
5579
5612
|
import { spawnSync } from "node:child_process";
|
|
5580
|
-
import { createHash as
|
|
5613
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
5581
5614
|
function collectReproducibilityMetadata(cwd, safety) {
|
|
5582
5615
|
const branch = git(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
5583
5616
|
const commit = git(cwd, ["rev-parse", "HEAD"]);
|
|
@@ -5614,673 +5647,22 @@ function git(cwd, args) {
|
|
|
5614
5647
|
return trimmed.length > 0 ? trimmed : null;
|
|
5615
5648
|
}
|
|
5616
5649
|
function sha2564(input) {
|
|
5617
|
-
return
|
|
5650
|
+
return createHash5("sha256").update(input, "utf8").digest("hex");
|
|
5618
5651
|
}
|
|
5619
5652
|
|
|
5620
5653
|
// src/domains/dispatch/route-observer.ts
|
|
5621
5654
|
init_esm_shims();
|
|
5622
|
-
import { appendFileSync, existsSync as
|
|
5623
|
-
import { join as
|
|
5624
|
-
|
|
5625
|
-
// src/domains/dispatch/gate-decisions.ts
|
|
5626
|
-
init_esm_shims();
|
|
5627
|
-
import { createHash as createHash7, randomBytes as randomBytes4 } from "node:crypto";
|
|
5628
|
-
import { closeSync, existsSync as existsSync8, fsyncSync, mkdirSync as mkdirSync4, openSync, readdirSync as readdirSync2, readFileSync as readFileSync8, rmSync } from "node:fs";
|
|
5629
|
-
import { dirname as dirname3, join as join10, resolve as resolve4 } from "node:path";
|
|
5630
|
-
function parseReviewGateResult(output) {
|
|
5631
|
-
const result = parseVerifierResult(output);
|
|
5632
|
-
return result === null ? { ok: false, reason: "reviewer did not return a valid verifier report" } : { ok: true, result };
|
|
5633
|
-
}
|
|
5634
|
-
function decideReviewGate(input) {
|
|
5635
|
-
const base = {
|
|
5636
|
-
group: input.group,
|
|
5637
|
-
topology: "review",
|
|
5638
|
-
cycle: input.cycle,
|
|
5639
|
-
subjects: input.subjects,
|
|
5640
|
-
decider: input.decider,
|
|
5641
|
-
correlation: input.correlation
|
|
5642
|
-
};
|
|
5643
|
-
const parsed = parseReviewGateResult(input.output);
|
|
5644
|
-
if (!parsed.ok) {
|
|
5645
|
-
return {
|
|
5646
|
-
draft: { ...base, outcome: "exhausted", detail: parsed.reason },
|
|
5647
|
-
verdict: null,
|
|
5648
|
-
findings: null,
|
|
5649
|
-
needsDecision: `review gate produced no structured verdict in cycle ${input.cycle}: ${parsed.reason}`
|
|
5650
|
-
};
|
|
5651
|
-
}
|
|
5652
|
-
if (parsed.result.verdict === "pass" || input.terminalCycle) {
|
|
5653
|
-
return {
|
|
5654
|
-
draft: { ...base, outcome: parsed.result.verdict },
|
|
5655
|
-
verdict: parsed.result.verdict,
|
|
5656
|
-
findings: null,
|
|
5657
|
-
needsDecision: null
|
|
5658
|
-
};
|
|
5659
|
-
}
|
|
5660
|
-
const failed = parsed.result.checks.filter((check) => !check.passed);
|
|
5661
|
-
return {
|
|
5662
|
-
draft: { ...base, outcome: "revise", detail: `reviewer reported ${failed.length} failed check(s)` },
|
|
5663
|
-
verdict: null,
|
|
5664
|
-
findings: JSON.stringify({ verdict: "fail", checks: failed }),
|
|
5665
|
-
needsDecision: null
|
|
5666
|
-
};
|
|
5667
|
-
}
|
|
5668
|
-
function parseGateChecks(value) {
|
|
5669
|
-
if (!Array.isArray(value) || value.length === 0) return null;
|
|
5670
|
-
const checks = [];
|
|
5671
|
-
for (const entry of value) {
|
|
5672
|
-
if (!isRecord6(entry)) return null;
|
|
5673
|
-
const keys = Object.keys(entry);
|
|
5674
|
-
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) {
|
|
5675
|
-
return null;
|
|
5676
|
-
}
|
|
5677
|
-
checks.push({ name: entry.name, passed: entry.passed, evidence: entry.evidence });
|
|
5678
|
-
}
|
|
5679
|
-
return checks;
|
|
5680
|
-
}
|
|
5681
|
-
function parseCompeteGateResult(output, candidateCount) {
|
|
5682
|
-
const parsed = parseJsonObjectPayload(output);
|
|
5683
|
-
if (!parsed.ok) {
|
|
5684
|
-
return {
|
|
5685
|
-
ok: false,
|
|
5686
|
-
reason: parsed.reason === "not-object" ? "judge result must be a JSON object" : "judge result must be valid JSON"
|
|
5687
|
-
};
|
|
5688
|
-
}
|
|
5689
|
-
const value = parsed.value;
|
|
5690
|
-
if (Object.keys(value).some((key) => key !== "winner" && key !== "checks")) {
|
|
5691
|
-
return { ok: false, reason: "judge result has unknown fields" };
|
|
5692
|
-
}
|
|
5693
|
-
const winner = value.winner;
|
|
5694
|
-
if (typeof winner !== "number" || !Number.isSafeInteger(winner) || winner < 1 || winner > candidateCount) {
|
|
5695
|
-
return { ok: false, reason: `judge winner must be an integer 1..${candidateCount}` };
|
|
5696
|
-
}
|
|
5697
|
-
const checks = parseGateChecks(value.checks);
|
|
5698
|
-
if (checks === null) return { ok: false, reason: "judge result must carry typed checks with evidence" };
|
|
5699
|
-
return { ok: true, result: { winner, checks } };
|
|
5700
|
-
}
|
|
5701
|
-
function decisionsDirectory(stateDir = clioStateDir()) {
|
|
5702
|
-
return join10(stateDir, "gate-decisions");
|
|
5703
|
-
}
|
|
5704
|
-
function pendingDecisionsDirectory(stateDir = clioStateDir()) {
|
|
5705
|
-
return join10(decisionsDirectory(stateDir), "pending");
|
|
5706
|
-
}
|
|
5707
|
-
function isRecord6(value) {
|
|
5708
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5709
|
-
}
|
|
5710
|
-
function isSubjectRef(value) {
|
|
5711
|
-
if (!isRecord6(value) || typeof value.runId !== "string" || value.runId.trim().length === 0) return false;
|
|
5712
|
-
return typeof value.digest === "string" && /^[0-9a-f]{64}$/.test(value.digest);
|
|
5713
|
-
}
|
|
5714
|
-
function isSafeDecisionId(value) {
|
|
5715
|
-
return typeof value === "string" && value.length > 0 && value.length <= 256 && /^[A-Za-z0-9._-]+$/.test(value);
|
|
5716
|
-
}
|
|
5717
|
-
function isCorrelation(value) {
|
|
5718
|
-
if (!isRecord6(value)) return false;
|
|
5719
|
-
const fields = ["agent", "target", "modelFamily", "runtime", "node", "independent"];
|
|
5720
|
-
if (Object.keys(value).some((key) => !fields.includes(key))) return false;
|
|
5721
|
-
if (!fields.every((field) => typeof value[field] === "boolean")) return false;
|
|
5722
|
-
return value.independent === (!value.agent && !value.modelFamily);
|
|
5723
|
-
}
|
|
5724
|
-
function semanticError(value) {
|
|
5725
|
-
if (!isRecord6(value)) return "gate decision is not an object";
|
|
5726
|
-
if (value.version !== 2) return "unsupported gate decision version";
|
|
5727
|
-
if (!isSafeDecisionId(value.id)) return "gate decision id invalid";
|
|
5728
|
-
if (typeof value.group !== "string" || value.group.length === 0) return "gate decision group invalid";
|
|
5729
|
-
if (value.topology !== "review" && value.topology !== "compete") return "gate decision topology invalid";
|
|
5730
|
-
if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
|
|
5731
|
-
return "gate decision cycle invalid";
|
|
5732
|
-
}
|
|
5733
|
-
const reviewOutcome = value.outcome === "pass" || value.outcome === "fail" || value.outcome === "revise" || value.outcome === "exhausted";
|
|
5734
|
-
const competeOutcome = value.outcome === "winner" || value.outcome === "no-winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
5735
|
-
if (value.topology === "review" && !reviewOutcome || value.topology === "compete" && !competeOutcome) {
|
|
5736
|
-
return "gate decision outcome is incompatible with topology";
|
|
5737
|
-
}
|
|
5738
|
-
if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
|
|
5739
|
-
return "gate decision subjects invalid";
|
|
5740
|
-
}
|
|
5741
|
-
if (value.decider !== void 0 && !isSubjectRef(value.decider)) return "gate decision decider invalid";
|
|
5742
|
-
if (value.decider === void 0) {
|
|
5743
|
-
if (value.correlation !== void 0) return "gate decision correlation requires a decider";
|
|
5744
|
-
} else if (!isCorrelation(value.correlation)) {
|
|
5745
|
-
return "gate decision correlation invalid";
|
|
5746
|
-
}
|
|
5747
|
-
if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
|
|
5748
|
-
return "gate decision timestamp invalid";
|
|
5749
|
-
}
|
|
5750
|
-
const needsWinner = value.outcome === "winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
5751
|
-
if (needsWinner) {
|
|
5752
|
-
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}`) {
|
|
5753
|
-
return "gate decision winner invalid";
|
|
5754
|
-
}
|
|
5755
|
-
const winnerSubject = value.winner.subject;
|
|
5756
|
-
if (!value.subjects.some((subject) => subject.runId === winnerSubject.runId)) {
|
|
5757
|
-
return "gate decision winner is not a subject";
|
|
5758
|
-
}
|
|
5759
|
-
} else if (value.winner !== void 0) {
|
|
5760
|
-
return "gate decision winner is not valid for this outcome";
|
|
5761
|
-
}
|
|
5762
|
-
const needsConfirmation = value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
5763
|
-
if (needsConfirmation) {
|
|
5764
|
-
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)) {
|
|
5765
|
-
return "gate decision confirmation invalid";
|
|
5766
|
-
}
|
|
5767
|
-
} else if (value.confirmation !== void 0) {
|
|
5768
|
-
return "gate decision confirmation is not valid for this outcome";
|
|
5769
|
-
}
|
|
5770
|
-
if (value.detail !== void 0 && typeof value.detail !== "string") return "gate decision detail invalid";
|
|
5771
|
-
if (!isRecord6(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string") {
|
|
5772
|
-
return "gate decision integrity invalid";
|
|
5773
|
-
}
|
|
5774
|
-
return null;
|
|
5775
|
-
}
|
|
5776
|
-
function safeGroup(group) {
|
|
5777
|
-
const safe = group.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 128);
|
|
5778
|
-
return safe.length > 0 ? safe : "gate";
|
|
5779
|
-
}
|
|
5780
|
-
function newDecisionId(group) {
|
|
5781
|
-
return `${safeGroup(group)}-${Date.now().toString(36)}-${randomBytes4(6).toString("hex")}`;
|
|
5782
|
-
}
|
|
5783
|
-
function decisionArtifactPath(id, stateDir = clioStateDir()) {
|
|
5784
|
-
return join10(decisionsDirectory(stateDir), `${id}.json`);
|
|
5785
|
-
}
|
|
5786
|
-
function pendingDecisionPath(id, stateDir = clioStateDir()) {
|
|
5787
|
-
return join10(pendingDecisionsDirectory(stateDir), `${id}.json`);
|
|
5788
|
-
}
|
|
5789
|
-
function decisionPayload(decision) {
|
|
5790
|
-
return {
|
|
5791
|
-
contract: "clio.gateDecision.integrity",
|
|
5792
|
-
version: decision.version,
|
|
5793
|
-
id: decision.id,
|
|
5794
|
-
group: decision.group,
|
|
5795
|
-
topology: decision.topology,
|
|
5796
|
-
cycle: decision.cycle,
|
|
5797
|
-
outcome: decision.outcome,
|
|
5798
|
-
subjects: decision.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
|
|
5799
|
-
...decision.decider !== void 0 ? { decider: { runId: decision.decider.runId, digest: decision.decider.digest } } : {},
|
|
5800
|
-
...decision.correlation !== void 0 ? { correlation: { ...decision.correlation } } : {},
|
|
5801
|
-
...decision.winner !== void 0 ? {
|
|
5802
|
-
winner: {
|
|
5803
|
-
index: decision.winner.index,
|
|
5804
|
-
subject: {
|
|
5805
|
-
runId: decision.winner.subject.runId,
|
|
5806
|
-
digest: decision.winner.subject.digest
|
|
5807
|
-
},
|
|
5808
|
-
branch: decision.winner.branch
|
|
5809
|
-
}
|
|
5810
|
-
} : {},
|
|
5811
|
-
...decision.confirmation !== void 0 ? { confirmation: { id: decision.confirmation.id, digest: decision.confirmation.digest } } : {},
|
|
5812
|
-
...decision.detail !== void 0 ? { detail: decision.detail } : {},
|
|
5813
|
-
createdAt: decision.createdAt
|
|
5814
|
-
};
|
|
5815
|
-
}
|
|
5816
|
-
function decisionDigest(decision) {
|
|
5817
|
-
return createHash7("sha256").update(JSON.stringify(decisionPayload(decision)), "utf8").digest("hex");
|
|
5818
|
-
}
|
|
5819
|
-
function artifactWithoutIntegrity(artifact) {
|
|
5820
|
-
const result = {
|
|
5821
|
-
version: artifact.version,
|
|
5822
|
-
id: artifact.id,
|
|
5823
|
-
group: artifact.group,
|
|
5824
|
-
topology: artifact.topology,
|
|
5825
|
-
cycle: artifact.cycle,
|
|
5826
|
-
outcome: artifact.outcome,
|
|
5827
|
-
subjects: artifact.subjects.map((subject) => ({ ...subject })),
|
|
5828
|
-
createdAt: artifact.createdAt
|
|
5829
|
-
};
|
|
5830
|
-
if (artifact.decider !== void 0) result.decider = { ...artifact.decider };
|
|
5831
|
-
if (artifact.correlation !== void 0) result.correlation = { ...artifact.correlation };
|
|
5832
|
-
if (artifact.winner !== void 0) {
|
|
5833
|
-
result.winner = {
|
|
5834
|
-
index: artifact.winner.index,
|
|
5835
|
-
subject: { ...artifact.winner.subject },
|
|
5836
|
-
branch: artifact.winner.branch
|
|
5837
|
-
};
|
|
5838
|
-
}
|
|
5839
|
-
if (artifact.confirmation !== void 0) result.confirmation = { ...artifact.confirmation };
|
|
5840
|
-
if (artifact.detail !== void 0) result.detail = artifact.detail;
|
|
5841
|
-
return result;
|
|
5842
|
-
}
|
|
5843
|
-
function verifyGateDecisionArtifact(artifact) {
|
|
5844
|
-
const invalid = semanticError(artifact);
|
|
5845
|
-
if (invalid !== null) return { ok: false, reason: invalid };
|
|
5846
|
-
if (!/^[0-9a-f]{64}$/.test(artifact.integrity.digest)) return { ok: false, reason: "gate decision integrity invalid" };
|
|
5847
|
-
return decisionDigest(artifactWithoutIntegrity(artifact)) === artifact.integrity.digest ? { ok: true } : { ok: false, reason: "gate decision integrity mismatch" };
|
|
5848
|
-
}
|
|
5849
|
-
function buildGateDecisionArtifact(draft, id = newDecisionId(draft.group), createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()) {
|
|
5850
|
-
if (draft.group.trim().length === 0) throw new Error("gate decision group is required");
|
|
5851
|
-
if (!Number.isInteger(draft.cycle) || draft.cycle < 1)
|
|
5852
|
-
throw new Error("gate decision cycle must be a positive integer");
|
|
5853
|
-
if (draft.subjects.length === 0) throw new Error("gate decision requires at least one subject receipt");
|
|
5854
|
-
const withoutIntegrity = {
|
|
5855
|
-
version: 2,
|
|
5856
|
-
id,
|
|
5857
|
-
group: draft.group,
|
|
5858
|
-
topology: draft.topology,
|
|
5859
|
-
cycle: draft.cycle,
|
|
5860
|
-
outcome: draft.outcome,
|
|
5861
|
-
subjects: draft.subjects.map((subject) => ({ ...subject })),
|
|
5862
|
-
createdAt
|
|
5863
|
-
};
|
|
5864
|
-
if (draft.decider !== void 0) withoutIntegrity.decider = { ...draft.decider };
|
|
5865
|
-
if (draft.correlation !== void 0) withoutIntegrity.correlation = { ...draft.correlation };
|
|
5866
|
-
if (draft.winner !== void 0) {
|
|
5867
|
-
withoutIntegrity.winner = {
|
|
5868
|
-
index: draft.winner.index,
|
|
5869
|
-
subject: { ...draft.winner.subject },
|
|
5870
|
-
branch: draft.winner.branch
|
|
5871
|
-
};
|
|
5872
|
-
}
|
|
5873
|
-
if (draft.confirmation !== void 0) withoutIntegrity.confirmation = { ...draft.confirmation };
|
|
5874
|
-
if (draft.detail !== void 0) withoutIntegrity.detail = draft.detail;
|
|
5875
|
-
const artifact = {
|
|
5876
|
-
...withoutIntegrity,
|
|
5877
|
-
integrity: { algorithm: "sha256", digest: decisionDigest(withoutIntegrity) }
|
|
5878
|
-
};
|
|
5879
|
-
const verification = verifyGateDecisionArtifact(artifact);
|
|
5880
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
5881
|
-
return artifact;
|
|
5882
|
-
}
|
|
5883
|
-
function readVerifiedArtifact(path2) {
|
|
5884
|
-
let value;
|
|
5885
|
-
try {
|
|
5886
|
-
value = JSON.parse(readFileSync8(path2, "utf8"));
|
|
5887
|
-
} catch (error) {
|
|
5888
|
-
throw new Error(
|
|
5889
|
-
`gate decision artifact is unreadable at ${path2}: ${error instanceof Error ? error.message : String(error)}`
|
|
5890
|
-
);
|
|
5891
|
-
}
|
|
5892
|
-
const artifact = value;
|
|
5893
|
-
const verification = verifyGateDecisionArtifact(artifact);
|
|
5894
|
-
if (!verification.ok) throw new Error(`gate decision artifact is invalid at ${path2}: ${verification.reason}`);
|
|
5895
|
-
return artifact;
|
|
5896
|
-
}
|
|
5897
|
-
function persistGateDecisionArtifact(artifact, stateDir, allowIdenticalExisting) {
|
|
5898
|
-
const verification = verifyGateDecisionArtifact(artifact);
|
|
5899
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
5900
|
-
const directory = decisionsDirectory(stateDir);
|
|
5901
|
-
mkdirSync4(directory, { recursive: true });
|
|
5902
|
-
const path2 = decisionArtifactPath(artifact.id, stateDir);
|
|
5903
|
-
if (existsSync8(path2)) {
|
|
5904
|
-
const existing = readVerifiedArtifact(path2);
|
|
5905
|
-
if (allowIdenticalExisting && existing.id === artifact.id && existing.integrity.digest === artifact.integrity.digest) {
|
|
5906
|
-
return { artifact: existing, path: path2 };
|
|
5907
|
-
}
|
|
5908
|
-
throw new Error(`gate decision artifact collision: ${artifact.id}`);
|
|
5909
|
-
}
|
|
5910
|
-
atomicWrite(path2, JSON.stringify(artifact, null, 2));
|
|
5911
|
-
return { artifact, path: path2 };
|
|
5912
|
-
}
|
|
5913
|
-
function cloneGateDecisionArtifact(artifact) {
|
|
5914
|
-
return {
|
|
5915
|
-
...artifactWithoutIntegrity(artifact),
|
|
5916
|
-
integrity: { ...artifact.integrity }
|
|
5917
|
-
};
|
|
5918
|
-
}
|
|
5919
|
-
function pendingRecordPayload(record) {
|
|
5920
|
-
if (record.kind === "output") {
|
|
5921
|
-
return {
|
|
5922
|
-
contract: "clio.gateDecision.pending",
|
|
5923
|
-
version: record.version,
|
|
5924
|
-
kind: record.kind,
|
|
5925
|
-
id: record.id,
|
|
5926
|
-
group: record.group,
|
|
5927
|
-
topology: record.topology,
|
|
5928
|
-
cycle: record.cycle,
|
|
5929
|
-
subjects: record.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
|
|
5930
|
-
deciderRunId: record.deciderRunId,
|
|
5931
|
-
finalOutput: record.finalOutput,
|
|
5932
|
-
...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
|
|
5933
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
5934
|
-
createdAt: record.createdAt
|
|
5935
|
-
};
|
|
5936
|
-
}
|
|
5937
|
-
const decisionWithoutIntegrity = artifactWithoutIntegrity(record.decision);
|
|
5938
|
-
return {
|
|
5939
|
-
contract: "clio.gateDecision.pending",
|
|
5940
|
-
version: record.version,
|
|
5941
|
-
kind: record.kind,
|
|
5942
|
-
id: record.id,
|
|
5943
|
-
decision: {
|
|
5944
|
-
...decisionPayload(decisionWithoutIntegrity),
|
|
5945
|
-
integrity: { ...record.decision.integrity }
|
|
5946
|
-
},
|
|
5947
|
-
...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
|
|
5948
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
5949
|
-
createdAt: record.createdAt
|
|
5950
|
-
};
|
|
5951
|
-
}
|
|
5952
|
-
function pendingRecordDigest(record) {
|
|
5953
|
-
return createHash7("sha256").update(JSON.stringify(pendingRecordPayload(record)), "utf8").digest("hex");
|
|
5954
|
-
}
|
|
5955
|
-
function pendingRecordWithoutIntegrity(record) {
|
|
5956
|
-
if (record.kind === "output") {
|
|
5957
|
-
return {
|
|
5958
|
-
version: record.version,
|
|
5959
|
-
kind: record.kind,
|
|
5960
|
-
id: record.id,
|
|
5961
|
-
group: record.group,
|
|
5962
|
-
topology: record.topology,
|
|
5963
|
-
cycle: record.cycle,
|
|
5964
|
-
subjects: record.subjects.map((subject) => ({ ...subject })),
|
|
5965
|
-
deciderRunId: record.deciderRunId,
|
|
5966
|
-
finalOutput: record.finalOutput,
|
|
5967
|
-
...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
|
|
5968
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
5969
|
-
createdAt: record.createdAt
|
|
5970
|
-
};
|
|
5971
|
-
}
|
|
5972
|
-
return {
|
|
5973
|
-
version: record.version,
|
|
5974
|
-
kind: record.kind,
|
|
5975
|
-
id: record.id,
|
|
5976
|
-
decision: cloneGateDecisionArtifact(record.decision),
|
|
5977
|
-
...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
|
|
5978
|
-
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
5979
|
-
createdAt: record.createdAt
|
|
5980
|
-
};
|
|
5981
|
-
}
|
|
5982
|
-
function pendingSemanticError(value) {
|
|
5983
|
-
if (!isRecord6(value)) return "pending gate decision is not an object";
|
|
5984
|
-
if (value.version !== 1) return "unsupported pending gate decision version";
|
|
5985
|
-
if (!isSafeDecisionId(value.id)) return "pending gate decision id invalid";
|
|
5986
|
-
if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
|
|
5987
|
-
return "pending gate decision timestamp invalid";
|
|
5988
|
-
}
|
|
5989
|
-
if (!isRecord6(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string" || !/^[0-9a-f]{64}$/.test(value.integrity.digest)) {
|
|
5990
|
-
return "pending gate decision integrity invalid";
|
|
5991
|
-
}
|
|
5992
|
-
if (value.kind === "output") {
|
|
5993
|
-
if (typeof value.group !== "string" || value.group.trim().length === 0) {
|
|
5994
|
-
return "pending gate output group invalid";
|
|
5995
|
-
}
|
|
5996
|
-
if (value.topology !== "review" && value.topology !== "compete") {
|
|
5997
|
-
return "pending gate output topology invalid";
|
|
5998
|
-
}
|
|
5999
|
-
if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
|
|
6000
|
-
return "pending gate output cycle invalid";
|
|
6001
|
-
}
|
|
6002
|
-
if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
|
|
6003
|
-
return "pending gate output subjects invalid";
|
|
6004
|
-
}
|
|
6005
|
-
if (typeof value.deciderRunId !== "string" || value.deciderRunId.trim().length === 0) {
|
|
6006
|
-
return "pending gate output decider run id invalid";
|
|
6007
|
-
}
|
|
6008
|
-
if (typeof value.finalOutput !== "string") return "pending gate output text invalid";
|
|
6009
|
-
if (value.terminalCycle !== void 0 && typeof value.terminalCycle !== "boolean") {
|
|
6010
|
-
return "pending gate output terminal-cycle marker invalid";
|
|
6011
|
-
}
|
|
6012
|
-
if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
|
|
6013
|
-
return "pending gate output resource root invalid";
|
|
6014
|
-
}
|
|
6015
|
-
return null;
|
|
6016
|
-
}
|
|
6017
|
-
if (value.kind !== "decision") return "pending gate decision kind invalid";
|
|
6018
|
-
if (!isRecord6(value.decision)) return "pending gate decision artifact invalid";
|
|
6019
|
-
const verification = verifyGateDecisionArtifact(value.decision);
|
|
6020
|
-
if (!verification.ok) return `pending gate decision artifact invalid: ${verification.reason}`;
|
|
6021
|
-
if (value.decision.id !== value.id) return "pending gate decision artifact id mismatch";
|
|
6022
|
-
if (value.decision.createdAt !== value.createdAt) return "pending gate decision artifact timestamp mismatch";
|
|
6023
|
-
if (value.finalOutput !== void 0 && typeof value.finalOutput !== "string") {
|
|
6024
|
-
return "pending gate decision output invalid";
|
|
6025
|
-
}
|
|
6026
|
-
if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
|
|
6027
|
-
return "pending gate decision resource root invalid";
|
|
6028
|
-
}
|
|
6029
|
-
return null;
|
|
6030
|
-
}
|
|
6031
|
-
function verifyPendingGateDecisionRecord(record) {
|
|
6032
|
-
const invalid = pendingSemanticError(record);
|
|
6033
|
-
if (invalid !== null) return { ok: false, reason: invalid };
|
|
6034
|
-
return pendingRecordDigest(pendingRecordWithoutIntegrity(record)) === record.integrity.digest ? { ok: true } : { ok: false, reason: "pending gate decision integrity mismatch" };
|
|
6035
|
-
}
|
|
6036
|
-
function clonePendingGateDecisionRecord(record) {
|
|
6037
|
-
const without = pendingRecordWithoutIntegrity(record);
|
|
6038
|
-
return {
|
|
6039
|
-
...without,
|
|
6040
|
-
integrity: { ...record.integrity }
|
|
6041
|
-
};
|
|
6042
|
-
}
|
|
6043
|
-
function parsePendingGateDecisionRecord(value) {
|
|
6044
|
-
const invalid = pendingSemanticError(value);
|
|
6045
|
-
if (invalid !== null) throw new Error(invalid);
|
|
6046
|
-
const record = clonePendingGateDecisionRecord(value);
|
|
6047
|
-
const verification = verifyPendingGateDecisionRecord(record);
|
|
6048
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
6049
|
-
return record;
|
|
6050
|
-
}
|
|
6051
|
-
function assertPendingHandlePath(handle) {
|
|
6052
|
-
const expected = pendingDecisionPath(handle.record.id, handle.stateDir);
|
|
6053
|
-
if (resolve4(handle.path) !== resolve4(expected)) {
|
|
6054
|
-
throw new Error(`pending gate decision path does not match id ${handle.record.id}`);
|
|
6055
|
-
}
|
|
6056
|
-
}
|
|
6057
|
-
function pendingHandle(record, stateDir) {
|
|
6058
|
-
return {
|
|
6059
|
-
record: clonePendingGateDecisionRecord(record),
|
|
6060
|
-
path: pendingDecisionPath(record.id, stateDir),
|
|
6061
|
-
stateDir
|
|
6062
|
-
};
|
|
6063
|
-
}
|
|
6064
|
-
function persistPendingGateDecision(record, stateDir, allowReplace) {
|
|
6065
|
-
const verification = verifyPendingGateDecisionRecord(record);
|
|
6066
|
-
if (!verification.ok) throw new Error(verification.reason);
|
|
6067
|
-
const path2 = pendingDecisionPath(record.id, stateDir);
|
|
6068
|
-
mkdirSync4(dirname3(path2), { recursive: true });
|
|
6069
|
-
if (!allowReplace && existsSync8(path2)) throw new Error(`pending gate decision collision: ${record.id}`);
|
|
6070
|
-
atomicWrite(path2, JSON.stringify(record, null, 2));
|
|
6071
|
-
return pendingHandle(record, stateDir);
|
|
6072
|
-
}
|
|
6073
|
-
function loadPendingGateDecision(handle) {
|
|
6074
|
-
assertPendingHandlePath(handle);
|
|
6075
|
-
if (!existsSync8(handle.path)) return null;
|
|
6076
|
-
const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync8(handle.path, "utf8")));
|
|
6077
|
-
if (record.id !== handle.record.id) throw new Error("pending gate decision changed identity on disk");
|
|
6078
|
-
return pendingHandle(record, handle.stateDir);
|
|
6079
|
-
}
|
|
6080
|
-
function fsyncDirectoryBestEffort(path2) {
|
|
6081
|
-
let fd = null;
|
|
6082
|
-
try {
|
|
6083
|
-
fd = openSync(path2, "r");
|
|
6084
|
-
fsyncSync(fd);
|
|
6085
|
-
} catch {
|
|
6086
|
-
} finally {
|
|
6087
|
-
if (fd !== null) closeSync(fd);
|
|
6088
|
-
}
|
|
6089
|
-
}
|
|
6090
|
-
function clearPendingGateDecision(handle) {
|
|
6091
|
-
assertPendingHandlePath(handle);
|
|
6092
|
-
rmSync(handle.path, { force: true });
|
|
6093
|
-
fsyncDirectoryBestEffort(dirname3(handle.path));
|
|
6094
|
-
}
|
|
6095
|
-
function sameSubjectRefs(left, right) {
|
|
6096
|
-
return left.length === right.length && left.every((subject, index) => {
|
|
6097
|
-
const other = right[index];
|
|
6098
|
-
return other !== void 0 && subject.runId === other.runId && subject.digest === other.digest;
|
|
6099
|
-
});
|
|
6100
|
-
}
|
|
6101
|
-
function stagePendingGateOutput(draft, stateDir = clioStateDir()) {
|
|
6102
|
-
const id = newDecisionId(draft.group);
|
|
6103
|
-
const withoutIntegrity = {
|
|
6104
|
-
version: 1,
|
|
6105
|
-
kind: "output",
|
|
6106
|
-
id,
|
|
6107
|
-
group: draft.group,
|
|
6108
|
-
topology: draft.topology,
|
|
6109
|
-
cycle: draft.cycle,
|
|
6110
|
-
subjects: draft.subjects.map((subject) => ({ ...subject })),
|
|
6111
|
-
deciderRunId: draft.deciderRunId,
|
|
6112
|
-
finalOutput: draft.finalOutput,
|
|
6113
|
-
...draft.terminalCycle !== void 0 ? { terminalCycle: draft.terminalCycle } : {},
|
|
6114
|
-
...draft.resourceRoot !== void 0 ? { resourceRoot: draft.resourceRoot } : {},
|
|
6115
|
-
createdAt: draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
6116
|
-
};
|
|
6117
|
-
const record = {
|
|
6118
|
-
...withoutIntegrity,
|
|
6119
|
-
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
6120
|
-
};
|
|
6121
|
-
if (existsSync8(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
|
|
6122
|
-
return persistPendingGateDecision(record, stateDir, false);
|
|
6123
|
-
}
|
|
6124
|
-
function stagePendingGateDecision(draft, options = {}) {
|
|
6125
|
-
const stateDir = options.stateDir ?? clioStateDir();
|
|
6126
|
-
const id = newDecisionId(draft.group);
|
|
6127
|
-
const createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
6128
|
-
const decision = buildGateDecisionArtifact(draft, id, createdAt);
|
|
6129
|
-
const withoutIntegrity = {
|
|
6130
|
-
version: 1,
|
|
6131
|
-
kind: "decision",
|
|
6132
|
-
id,
|
|
6133
|
-
decision,
|
|
6134
|
-
...options.finalOutput !== void 0 ? { finalOutput: options.finalOutput } : {},
|
|
6135
|
-
...options.resourceRoot !== void 0 ? { resourceRoot: options.resourceRoot } : {},
|
|
6136
|
-
createdAt
|
|
6137
|
-
};
|
|
6138
|
-
const record = {
|
|
6139
|
-
...withoutIntegrity,
|
|
6140
|
-
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
6141
|
-
};
|
|
6142
|
-
if (existsSync8(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
|
|
6143
|
-
return persistPendingGateDecision(record, stateDir, false);
|
|
6144
|
-
}
|
|
6145
|
-
function resolvePendingGateDecision(handle, draft) {
|
|
6146
|
-
const loaded = loadPendingGateDecision(handle);
|
|
6147
|
-
if (loaded === null) throw new Error(`pending gate decision is missing: ${handle.record.id}`);
|
|
6148
|
-
if (loaded.record.kind === "decision") {
|
|
6149
|
-
const expected = buildGateDecisionArtifact(draft, loaded.record.id, loaded.record.createdAt);
|
|
6150
|
-
if (expected.integrity.digest !== loaded.record.decision.integrity.digest) {
|
|
6151
|
-
throw new Error("pending gate decision was already resolved to a different artifact");
|
|
6152
|
-
}
|
|
6153
|
-
return loaded;
|
|
6154
|
-
}
|
|
6155
|
-
const pending = loaded.record;
|
|
6156
|
-
if (draft.group !== pending.group || draft.topology !== pending.topology || draft.cycle !== pending.cycle || !sameSubjectRefs(draft.subjects, pending.subjects)) {
|
|
6157
|
-
throw new Error("resolved gate decision does not match staged output context");
|
|
6158
|
-
}
|
|
6159
|
-
if (draft.decider === void 0 || draft.decider.runId !== pending.deciderRunId) {
|
|
6160
|
-
throw new Error("resolved gate decision does not match staged decider run");
|
|
6161
|
-
}
|
|
6162
|
-
if (draft.createdAt !== void 0 && draft.createdAt !== pending.createdAt) {
|
|
6163
|
-
throw new Error("resolved gate decision cannot change the staged timestamp");
|
|
6164
|
-
}
|
|
6165
|
-
const decision = buildGateDecisionArtifact(draft, pending.id, pending.createdAt);
|
|
6166
|
-
const withoutIntegrity = {
|
|
6167
|
-
version: 1,
|
|
6168
|
-
kind: "decision",
|
|
6169
|
-
id: pending.id,
|
|
6170
|
-
decision,
|
|
6171
|
-
finalOutput: pending.finalOutput,
|
|
6172
|
-
...pending.resourceRoot !== void 0 ? { resourceRoot: pending.resourceRoot } : {},
|
|
6173
|
-
createdAt: pending.createdAt
|
|
6174
|
-
};
|
|
6175
|
-
const resolvedRecord = {
|
|
6176
|
-
...withoutIntegrity,
|
|
6177
|
-
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
6178
|
-
};
|
|
6179
|
-
return persistPendingGateDecision(resolvedRecord, loaded.stateDir, true);
|
|
6180
|
-
}
|
|
6181
|
-
function materializePendingGateDecision(handle) {
|
|
6182
|
-
const loaded = loadPendingGateDecision(handle);
|
|
6183
|
-
if (loaded === null) {
|
|
6184
|
-
if (handle.record.kind !== "decision") {
|
|
6185
|
-
throw new Error(`pending gate output is missing before resolution: ${handle.record.id}`);
|
|
6186
|
-
}
|
|
6187
|
-
const path2 = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
|
|
6188
|
-
if (!existsSync8(path2)) throw new Error(`pending gate decision and artifact are both missing: ${handle.record.id}`);
|
|
6189
|
-
const artifact = readVerifiedArtifact(path2);
|
|
6190
|
-
if (artifact.integrity.digest !== handle.record.decision.integrity.digest) {
|
|
6191
|
-
throw new Error(`gate decision artifact conflicts with completed pending record: ${handle.record.id}`);
|
|
6192
|
-
}
|
|
6193
|
-
return { artifact, path: path2 };
|
|
6194
|
-
}
|
|
6195
|
-
if (loaded.record.kind !== "decision") {
|
|
6196
|
-
throw new Error(`pending gate output requires receipt resolution: ${loaded.record.id}`);
|
|
6197
|
-
}
|
|
6198
|
-
const written = persistGateDecisionArtifact(loaded.record.decision, loaded.stateDir, true);
|
|
6199
|
-
const persisted = readVerifiedArtifact(written.path);
|
|
6200
|
-
if (persisted.integrity.digest !== loaded.record.decision.integrity.digest) {
|
|
6201
|
-
throw new Error(`materialized gate decision does not match pending record: ${loaded.record.id}`);
|
|
6202
|
-
}
|
|
6203
|
-
clearPendingGateDecision(loaded);
|
|
6204
|
-
return { artifact: persisted, path: written.path };
|
|
6205
|
-
}
|
|
6206
|
-
function finalizePendingGateDecision(handle, draft) {
|
|
6207
|
-
return materializePendingGateDecision(resolvePendingGateDecision(handle, draft));
|
|
6208
|
-
}
|
|
6209
|
-
function readPendingGateDecisions(stateDir = clioStateDir()) {
|
|
6210
|
-
const directory = pendingDecisionsDirectory(stateDir);
|
|
6211
|
-
if (!existsSync8(directory)) return { records: [], errors: [] };
|
|
6212
|
-
const records = [];
|
|
6213
|
-
const errors = [];
|
|
6214
|
-
for (const name of readdirSync2(directory).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
6215
|
-
const path2 = join10(directory, name);
|
|
6216
|
-
try {
|
|
6217
|
-
const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync8(path2, "utf8")));
|
|
6218
|
-
if (name !== `${record.id}.json`) throw new Error("pending gate decision filename does not match its id");
|
|
6219
|
-
records.push({ record, path: path2, stateDir });
|
|
6220
|
-
} catch (error) {
|
|
6221
|
-
errors.push({ path: path2, message: error instanceof Error ? error.message : String(error) });
|
|
6222
|
-
}
|
|
6223
|
-
}
|
|
6224
|
-
return { records, errors };
|
|
6225
|
-
}
|
|
6226
|
-
function preflightPendingGateDecisionMaterialization(handles) {
|
|
6227
|
-
for (const handle of handles) {
|
|
6228
|
-
if (handle.record.kind !== "decision") continue;
|
|
6229
|
-
const path2 = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
|
|
6230
|
-
if (!existsSync8(path2)) continue;
|
|
6231
|
-
const existing = readVerifiedArtifact(path2);
|
|
6232
|
-
if (existing.integrity.digest !== handle.record.decision.integrity.digest) {
|
|
6233
|
-
throw new Error(`gate decision artifact conflicts with pending record: ${handle.record.id}`);
|
|
6234
|
-
}
|
|
6235
|
-
}
|
|
6236
|
-
}
|
|
6237
|
-
function preparePendingGateDecisionRecovery(stateDir = clioStateDir()) {
|
|
6238
|
-
const pending = readPendingGateDecisions(stateDir);
|
|
6239
|
-
if (pending.errors.length > 0) {
|
|
6240
|
-
throw new Error(
|
|
6241
|
-
`pending gate decision journal is untrustworthy: ${pending.errors.map((entry) => `${entry.path}: ${entry.message}`).join("; ")}`
|
|
6242
|
-
);
|
|
6243
|
-
}
|
|
6244
|
-
const ready = pending.records.filter((handle) => handle.record.kind === "decision");
|
|
6245
|
-
preflightPendingGateDecisionMaterialization(ready);
|
|
6246
|
-
return {
|
|
6247
|
-
ready,
|
|
6248
|
-
unresolved: pending.records.filter((handle) => handle.record.kind === "output")
|
|
6249
|
-
};
|
|
6250
|
-
}
|
|
6251
|
-
function readGateDecisionArtifacts(group, stateDir = clioStateDir()) {
|
|
6252
|
-
const directory = decisionsDirectory(stateDir);
|
|
6253
|
-
if (!existsSync8(directory)) return [];
|
|
6254
|
-
const out = [];
|
|
6255
|
-
for (const name of readdirSync2(directory).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
6256
|
-
const path2 = join10(directory, name);
|
|
6257
|
-
try {
|
|
6258
|
-
const artifact = JSON.parse(readFileSync8(path2, "utf8"));
|
|
6259
|
-
if (group !== void 0 && artifact.group !== group) continue;
|
|
6260
|
-
if (!verifyGateDecisionArtifact(artifact).ok) continue;
|
|
6261
|
-
out.push({ artifact, path: path2 });
|
|
6262
|
-
} catch {
|
|
6263
|
-
}
|
|
6264
|
-
}
|
|
6265
|
-
return out;
|
|
6266
|
-
}
|
|
6267
|
-
function readGateDecisionArtifactsForRunIds(runIds, stateDir = clioStateDir()) {
|
|
6268
|
-
if (runIds.size === 0) return [];
|
|
6269
|
-
return readGateDecisionArtifacts(void 0, stateDir).filter(({ artifact }) => {
|
|
6270
|
-
if (artifact.subjects.some((subject) => runIds.has(subject.runId))) return true;
|
|
6271
|
-
if (artifact.decider !== void 0 && runIds.has(artifact.decider.runId)) return true;
|
|
6272
|
-
return artifact.winner !== void 0 && runIds.has(artifact.winner.subject.runId);
|
|
6273
|
-
});
|
|
6274
|
-
}
|
|
5655
|
+
import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync9, renameSync as renameSync4, statSync } from "node:fs";
|
|
5656
|
+
import { join as join11 } from "node:path";
|
|
6275
5657
|
|
|
6276
5658
|
// src/domains/dispatch/route-history.ts
|
|
6277
5659
|
init_esm_shims();
|
|
6278
|
-
import { existsSync as
|
|
6279
|
-
import { join as
|
|
5660
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, renameSync as renameSync3 } from "node:fs";
|
|
5661
|
+
import { join as join10 } from "node:path";
|
|
6280
5662
|
var ROUTE_HISTORY_VERSION = 3;
|
|
6281
5663
|
var DEFAULT_MAX_RECORDS = 4096;
|
|
6282
5664
|
function historyPath(stateDir) {
|
|
6283
|
-
return
|
|
5665
|
+
return join10(stateDir, "route-history.json");
|
|
6284
5666
|
}
|
|
6285
5667
|
function clone2(record) {
|
|
6286
5668
|
return structuredClone(record);
|
|
@@ -6289,7 +5671,7 @@ function compareRecords(left, right) {
|
|
|
6289
5671
|
return left.settledAt.localeCompare(right.settledAt) || left.receiptDigest.localeCompare(right.receiptDigest);
|
|
6290
5672
|
}
|
|
6291
5673
|
function validateRecord(value) {
|
|
6292
|
-
if (!
|
|
5674
|
+
if (!isRecord5(value) || value.version !== ROUTE_HISTORY_VERSION)
|
|
6293
5675
|
throw new Error("route history record has unsupported version");
|
|
6294
5676
|
if (!isDigest(value.receiptDigest)) throw new Error("route history receipt digest invalid");
|
|
6295
5677
|
if (typeof value.assignmentId !== "string" || value.assignmentId.length === 0)
|
|
@@ -6333,8 +5715,8 @@ function validateRecord(value) {
|
|
|
6333
5715
|
};
|
|
6334
5716
|
}
|
|
6335
5717
|
function readHistory(path2) {
|
|
6336
|
-
if (!
|
|
6337
|
-
const raw =
|
|
5718
|
+
if (!existsSync8(path2)) return [];
|
|
5719
|
+
const raw = readFileSync8(path2, "utf8").trim();
|
|
6338
5720
|
if (raw.length === 0) return [];
|
|
6339
5721
|
let parsed;
|
|
6340
5722
|
try {
|
|
@@ -6342,7 +5724,7 @@ function readHistory(path2) {
|
|
|
6342
5724
|
} catch (error) {
|
|
6343
5725
|
throw new Error(`route history unreadable: ${error instanceof Error ? error.message : String(error)}`);
|
|
6344
5726
|
}
|
|
6345
|
-
if (!
|
|
5727
|
+
if (!isRecord5(parsed) || !Array.isArray(parsed.records)) throw new Error("route history has unsupported format");
|
|
6346
5728
|
if (parsed.version !== ROUTE_HISTORY_VERSION) {
|
|
6347
5729
|
retireHistory(path2, parsed.version);
|
|
6348
5730
|
return [];
|
|
@@ -6402,14 +5784,14 @@ function createRouteHistoryStore(options = {}) {
|
|
|
6402
5784
|
}
|
|
6403
5785
|
};
|
|
6404
5786
|
}
|
|
6405
|
-
function
|
|
5787
|
+
function isRecord5(value) {
|
|
6406
5788
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6407
5789
|
}
|
|
6408
5790
|
function isDigest(value) {
|
|
6409
5791
|
return typeof value === "string" && /^[0-9a-f]{64}$/u.test(value);
|
|
6410
5792
|
}
|
|
6411
5793
|
function isRouteCandidate(value) {
|
|
6412
|
-
if (!
|
|
5794
|
+
if (!isRecord5(value)) return false;
|
|
6413
5795
|
if (!isExecutionRole(value.executionRole)) return false;
|
|
6414
5796
|
return [
|
|
6415
5797
|
value.agentId,
|
|
@@ -6425,7 +5807,7 @@ function isRouteCandidate(value) {
|
|
|
6425
5807
|
].every((field) => typeof field === "string");
|
|
6426
5808
|
}
|
|
6427
5809
|
function isPhaseTiming(value) {
|
|
6428
|
-
if (!
|
|
5810
|
+
if (!isRecord5(value)) return false;
|
|
6429
5811
|
return [
|
|
6430
5812
|
"requestToDecisionMs",
|
|
6431
5813
|
"decisionMs",
|
|
@@ -6441,7 +5823,7 @@ function isPhaseTiming(value) {
|
|
|
6441
5823
|
|
|
6442
5824
|
// src/domains/dispatch/route-quality.ts
|
|
6443
5825
|
init_esm_shims();
|
|
6444
|
-
import { createHash as
|
|
5826
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
6445
5827
|
function compareStrings(left, right) {
|
|
6446
5828
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
6447
5829
|
}
|
|
@@ -6556,19 +5938,19 @@ function reduceRouteQuality(input) {
|
|
|
6556
5938
|
return { label, checks, correlatedGates, sourceDigests: [...sourceDigests].sort(compareStrings) };
|
|
6557
5939
|
}
|
|
6558
5940
|
function routeQualityEvalDigest(artifact) {
|
|
6559
|
-
return
|
|
5941
|
+
return createHash6("sha256").update(canonicalJson2(artifact), "utf8").digest("hex");
|
|
6560
5942
|
}
|
|
6561
|
-
function
|
|
5943
|
+
function canonicalJson2(value) {
|
|
6562
5944
|
if (value === null) return "null";
|
|
6563
5945
|
if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
|
|
6564
5946
|
if (typeof value === "number") {
|
|
6565
5947
|
if (!Number.isFinite(value)) throw new Error("route quality eval digest requires finite numbers");
|
|
6566
5948
|
return JSON.stringify(value);
|
|
6567
5949
|
}
|
|
6568
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
5950
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson2).join(",")}]`;
|
|
6569
5951
|
if (typeof value === "object") {
|
|
6570
5952
|
const record = value;
|
|
6571
|
-
return `{${Object.keys(record).sort(compareStrings).map((key) => `${JSON.stringify(key)}:${
|
|
5953
|
+
return `{${Object.keys(record).sort(compareStrings).map((key) => `${JSON.stringify(key)}:${canonicalJson2(record[key])}`).join(",")}}`;
|
|
6572
5954
|
}
|
|
6573
5955
|
throw new Error(`route quality eval digest cannot represent ${typeof value}`);
|
|
6574
5956
|
}
|
|
@@ -6629,28 +6011,28 @@ function createRouteLearner(capacity = LEARNER_CAPACITY) {
|
|
|
6629
6011
|
}
|
|
6630
6012
|
var OBSERVATION_LOG_MAX_BYTES = 1024 * 1024;
|
|
6631
6013
|
function durableQualitySources(stateDir) {
|
|
6632
|
-
const runsPath2 =
|
|
6633
|
-
if (!
|
|
6014
|
+
const runsPath2 = join11(stateDir, "runs.json");
|
|
6015
|
+
if (!existsSync9(runsPath2)) return { receipts: [], gates: [], evals: [] };
|
|
6634
6016
|
try {
|
|
6635
|
-
const parsed = JSON.parse(
|
|
6017
|
+
const parsed = JSON.parse(readFileSync9(runsPath2, "utf8"));
|
|
6636
6018
|
if (!Array.isArray(parsed)) return { receipts: [], gates: [], evals: [] };
|
|
6637
6019
|
const receipts = [];
|
|
6638
6020
|
for (const envelope of parsed) {
|
|
6639
6021
|
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) continue;
|
|
6640
6022
|
const run = envelope;
|
|
6641
|
-
const path2 = run.receiptPath ??
|
|
6642
|
-
if (!
|
|
6643
|
-
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"));
|
|
6644
6026
|
if (typeof receipt === "object" && receipt !== null && !Array.isArray(receipt)) {
|
|
6645
6027
|
receipts.push({ receipt, envelope: run });
|
|
6646
6028
|
}
|
|
6647
6029
|
}
|
|
6648
6030
|
const evals = [];
|
|
6649
|
-
const evalDirectory =
|
|
6650
|
-
if (
|
|
6651
|
-
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()) {
|
|
6652
6034
|
try {
|
|
6653
|
-
const artifact = parseEvalArtifactV4(JSON.parse(
|
|
6035
|
+
const artifact = parseEvalArtifactV4(JSON.parse(readFileSync9(join11(evalDirectory, name), "utf8")), name);
|
|
6654
6036
|
evals.push({ artifact, digest: routeQualityEvalDigest(artifact) });
|
|
6655
6037
|
} catch {
|
|
6656
6038
|
}
|
|
@@ -6662,8 +6044,8 @@ function durableQualitySources(stateDir) {
|
|
|
6662
6044
|
}
|
|
6663
6045
|
}
|
|
6664
6046
|
function appendObservationLine(dir, record) {
|
|
6665
|
-
|
|
6666
|
-
const path2 =
|
|
6047
|
+
mkdirSync4(dir, { recursive: true });
|
|
6048
|
+
const path2 = join11(dir, "observations.jsonl");
|
|
6667
6049
|
try {
|
|
6668
6050
|
if (statSync(path2).size > OBSERVATION_LOG_MAX_BYTES) {
|
|
6669
6051
|
renameSync4(path2, `${path2}.1`);
|
|
@@ -6695,7 +6077,7 @@ function createRouteObserver(options) {
|
|
|
6695
6077
|
const PENDING_LIMIT = 512;
|
|
6696
6078
|
let totalObservations = 0;
|
|
6697
6079
|
let sequence = 0;
|
|
6698
|
-
const logDir = () => options.logDir ??
|
|
6080
|
+
const logDir = () => options.logDir ?? join11(clioStateDir(), "route-decisions");
|
|
6699
6081
|
const reconcileHistory = () => {
|
|
6700
6082
|
const sources = durableQualitySources(options.stateDir ?? clioStateDir());
|
|
6701
6083
|
if (sources.receipts.length === 0) return;
|
|
@@ -6860,8 +6242,328 @@ function createRouteObserver(options) {
|
|
|
6860
6242
|
} catch {
|
|
6861
6243
|
}
|
|
6862
6244
|
},
|
|
6863
|
-
summary() {
|
|
6864
|
-
return learner.summary(totalObservations);
|
|
6245
|
+
summary() {
|
|
6246
|
+
return learner.summary(totalObservations);
|
|
6247
|
+
}
|
|
6248
|
+
};
|
|
6249
|
+
}
|
|
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();
|
|
6865
6567
|
}
|
|
6866
6568
|
};
|
|
6867
6569
|
}
|
|
@@ -6915,27 +6617,27 @@ function detectRunIdentity(env = process.env) {
|
|
|
6915
6617
|
|
|
6916
6618
|
// src/domains/dispatch/state.ts
|
|
6917
6619
|
init_esm_shims();
|
|
6918
|
-
import { randomBytes as
|
|
6919
|
-
import { existsSync as
|
|
6920
|
-
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";
|
|
6921
6623
|
function newRunId() {
|
|
6922
|
-
const n = BigInt(`0x${
|
|
6624
|
+
const n = BigInt(`0x${randomBytes4(8).toString("hex")}`);
|
|
6923
6625
|
const raw = n.toString(36);
|
|
6924
6626
|
if (raw.length >= 12) return raw.slice(0, 12);
|
|
6925
6627
|
return raw.padStart(12, "0");
|
|
6926
6628
|
}
|
|
6927
6629
|
function runsPath() {
|
|
6928
|
-
return
|
|
6630
|
+
return join12(clioStateDir(), "runs.json");
|
|
6929
6631
|
}
|
|
6930
6632
|
function receiptPathFor(runId) {
|
|
6931
|
-
return
|
|
6633
|
+
return join12(clioStateDir(), "receipts", `${runId}.json`);
|
|
6932
6634
|
}
|
|
6933
6635
|
function fleetRunPath(runId) {
|
|
6934
|
-
return
|
|
6636
|
+
return join12(clioStateDir(), "fleet-runs", `${runId}.json`);
|
|
6935
6637
|
}
|
|
6936
6638
|
function readFleetRun(runId) {
|
|
6937
6639
|
try {
|
|
6938
|
-
const parsed = JSON.parse(
|
|
6640
|
+
const parsed = JSON.parse(readFileSync10(fleetRunPath(runId), "utf8"));
|
|
6939
6641
|
return parsed.version === 1 && parsed.id === runId ? structuredClone(parsed) : null;
|
|
6940
6642
|
} catch {
|
|
6941
6643
|
return null;
|
|
@@ -6945,10 +6647,27 @@ async function writeFleetRun(record) {
|
|
|
6945
6647
|
await atomicWrite(fleetRunPath(record.id), `${JSON.stringify(record, null, 2)}
|
|
6946
6648
|
`);
|
|
6947
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
|
+
}
|
|
6948
6667
|
function readRuns() {
|
|
6949
6668
|
const path2 = runsPath();
|
|
6950
|
-
if (!
|
|
6951
|
-
const raw =
|
|
6669
|
+
if (!existsSync10(path2)) return [];
|
|
6670
|
+
const raw = readFileSync10(path2, "utf8").trim();
|
|
6952
6671
|
if (raw.length === 0) return [];
|
|
6953
6672
|
const parsed = JSON.parse(raw);
|
|
6954
6673
|
if (!Array.isArray(parsed)) return [];
|
|
@@ -7106,6 +6825,10 @@ function openLedger(opts) {
|
|
|
7106
6825
|
const capped = capRuns(merged, maxRuns);
|
|
7107
6826
|
runs = capped;
|
|
7108
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
|
+
}
|
|
7109
6832
|
dirty.clear();
|
|
7110
6833
|
});
|
|
7111
6834
|
},
|
|
@@ -7274,7 +6997,7 @@ function requestOriginFor(req) {
|
|
|
7274
6997
|
return req.requestOrigin ?? "agent";
|
|
7275
6998
|
}
|
|
7276
6999
|
function sha2565(input) {
|
|
7277
|
-
return
|
|
7000
|
+
return createHash7("sha256").update(input, "utf8").digest("hex");
|
|
7278
7001
|
}
|
|
7279
7002
|
function promptHash(systemPrompt) {
|
|
7280
7003
|
return systemPrompt.length > 0 ? sha2565(systemPrompt) : null;
|
|
@@ -7416,8 +7139,8 @@ var DISPATCH_DRAIN_GRACE_MS = 2e3;
|
|
|
7416
7139
|
var RUN_WRITE_TARGET_HISTORY = 512;
|
|
7417
7140
|
async function awaitEventDrain(drained, graceMs = DISPATCH_DRAIN_GRACE_MS) {
|
|
7418
7141
|
let timer;
|
|
7419
|
-
const grace = new Promise((
|
|
7420
|
-
timer = setTimeout(() =>
|
|
7142
|
+
const grace = new Promise((resolve4) => {
|
|
7143
|
+
timer = setTimeout(() => resolve4(false), graceMs);
|
|
7421
7144
|
});
|
|
7422
7145
|
try {
|
|
7423
7146
|
return await Promise.race([drained.then(() => true), grace]);
|
|
@@ -8496,19 +8219,21 @@ function createDispatchBundle(context, options) {
|
|
|
8496
8219
|
return DEFAULT_RESILIENCE_COOLDOWN_MS;
|
|
8497
8220
|
};
|
|
8498
8221
|
const now = options?.now ?? (() => Date.now());
|
|
8222
|
+
const monotonicNow = options?.monotonicNow ?? (() => performance5.now());
|
|
8499
8223
|
const routeObserver = options?.routeObserver ?? createRouteObserver({});
|
|
8500
8224
|
let ledger = null;
|
|
8501
8225
|
let heartbeatTimer = null;
|
|
8502
8226
|
const active = /* @__PURE__ */ new Map();
|
|
8227
|
+
const pendingCapacity = /* @__PURE__ */ new Map();
|
|
8503
8228
|
const targetCooldowns = /* @__PURE__ */ new Map();
|
|
8504
8229
|
const ownedReservations = /* @__PURE__ */ new Set();
|
|
8505
|
-
const
|
|
8506
|
-
const
|
|
8507
|
-
|
|
8508
|
-
while (
|
|
8509
|
-
const oldest =
|
|
8230
|
+
const runWriteAttributions = /* @__PURE__ */ new Map();
|
|
8231
|
+
const recordRunWriteAttribution = (runId, attribution) => {
|
|
8232
|
+
runWriteAttributions.set(runId, attribution);
|
|
8233
|
+
while (runWriteAttributions.size > RUN_WRITE_TARGET_HISTORY) {
|
|
8234
|
+
const oldest = runWriteAttributions.keys().next();
|
|
8510
8235
|
if (oldest.done === true) break;
|
|
8511
|
-
|
|
8236
|
+
runWriteAttributions.delete(oldest.value);
|
|
8512
8237
|
}
|
|
8513
8238
|
};
|
|
8514
8239
|
const capacityAdmission = createCapacityAdmissionController({
|
|
@@ -8516,7 +8241,7 @@ function createDispatchBundle(context, options) {
|
|
|
8516
8241
|
const settings = getEffectiveSettings();
|
|
8517
8242
|
const nodes = { local: configuredGlobalCapacity(settings) };
|
|
8518
8243
|
for (const node of settings?.fleet?.nodes ?? []) nodes[node.id] = node.maxWorkers;
|
|
8519
|
-
return { global: configuredGlobalCapacity(settings), nodes };
|
|
8244
|
+
return { global: configuredGlobalCapacity(settings), nodes, endpoints: configuredEndpointLimits() };
|
|
8520
8245
|
},
|
|
8521
8246
|
now,
|
|
8522
8247
|
reservedPlanPeak: (planId) => reservedPlanPeakSlots(planId, (error) => reportDispatchDiagnostic("read reserved plan peak", error))
|
|
@@ -8527,6 +8252,24 @@ function createDispatchBundle(context, options) {
|
|
|
8527
8252
|
onError: (error) => reportDispatchDiagnostic("read capacity lease usage", error)
|
|
8528
8253
|
})
|
|
8529
8254
|
);
|
|
8255
|
+
function configuredEndpointCapacities() {
|
|
8256
|
+
return resolveEndpointCapacities({
|
|
8257
|
+
statuses: providers.list(),
|
|
8258
|
+
targets: getEffectiveSettings()?.targets ?? [],
|
|
8259
|
+
runtimeFor: (runtimeId) => providers.getRuntime(runtimeId)
|
|
8260
|
+
});
|
|
8261
|
+
}
|
|
8262
|
+
function configuredEndpointLimits() {
|
|
8263
|
+
return Object.fromEntries(Object.entries(configuredEndpointCapacities()).map(([key, value]) => [key, value.limit]));
|
|
8264
|
+
}
|
|
8265
|
+
function endpointCapacityForTarget(targetId) {
|
|
8266
|
+
const status = providers.list().find((entry) => entry.target.id === targetId);
|
|
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);
|
|
8270
|
+
if (endpoint === null) return null;
|
|
8271
|
+
return configuredEndpointCapacities()[endpoint.key] ?? endpoint;
|
|
8272
|
+
}
|
|
8530
8273
|
function reservationCapacitySnapshot(settings) {
|
|
8531
8274
|
const preflight = scheduling.preflight();
|
|
8532
8275
|
const usage = capacityLeaseUsage();
|
|
@@ -8535,9 +8278,21 @@ function createDispatchBundle(context, options) {
|
|
|
8535
8278
|
};
|
|
8536
8279
|
for (const node of settings?.fleet?.nodes ?? [])
|
|
8537
8280
|
nodes[node.id] = { active: usage.nodes[node.id] ?? 0, limit: node.maxWorkers };
|
|
8281
|
+
const endpoints = Object.fromEntries(
|
|
8282
|
+
Object.entries(configuredEndpointLimits()).map(([key, limit]) => [
|
|
8283
|
+
key,
|
|
8284
|
+
{
|
|
8285
|
+
active: usage.endpoints[key] ?? 0,
|
|
8286
|
+
limit,
|
|
8287
|
+
leases: usage.endpointHolders[key]?.leases ?? 0,
|
|
8288
|
+
foregroundStreams: usage.endpointHolders[key]?.foregroundStreams ?? 0
|
|
8289
|
+
}
|
|
8290
|
+
])
|
|
8291
|
+
);
|
|
8538
8292
|
return {
|
|
8539
8293
|
global: { active: usage.global, limit: configuredGlobalCapacity(settings) },
|
|
8540
8294
|
nodes,
|
|
8295
|
+
endpoints,
|
|
8541
8296
|
budget: { currentUsd: preflight.currentUsd, ceilingUsd: preflight.ceilingUsd }
|
|
8542
8297
|
};
|
|
8543
8298
|
}
|
|
@@ -8548,6 +8303,7 @@ function createDispatchBundle(context, options) {
|
|
|
8548
8303
|
memberId: task.memberId,
|
|
8549
8304
|
wave: task.wave,
|
|
8550
8305
|
nodeId: task.resolution.node.id,
|
|
8306
|
+
...task.resolution.endpoint !== void 0 ? { endpointKey: task.resolution.endpoint.key } : {},
|
|
8551
8307
|
costUpperBoundUsd: task.resolution.routeApproval?.totalCostUpperBoundUsd ?? task.resolution.costUpperBoundUsd
|
|
8552
8308
|
})),
|
|
8553
8309
|
capacity: reservationCapacitySnapshot(getEffectiveSettings()),
|
|
@@ -8589,10 +8345,24 @@ function createDispatchBundle(context, options) {
|
|
|
8589
8345
|
const configured = settings?.budget.concurrency;
|
|
8590
8346
|
return scheduling.maxWorkers?.() ?? (configured === "auto" || configured === void 0 ? 4 : Math.max(1, configured));
|
|
8591
8347
|
}
|
|
8592
|
-
|
|
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
|
+
}
|
|
8362
|
+
async function admitAssignmentCapacity(req, nodeId, timing, endpoint) {
|
|
8593
8363
|
const queuedAt = now();
|
|
8594
8364
|
timing.queuedAt = new Date(queuedAt).toISOString();
|
|
8595
|
-
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")}`;
|
|
8596
8366
|
const requestedAt = Date.parse(timing.requestedAt ?? timing.queuedAt);
|
|
8597
8367
|
const deadlineAt = req.assignmentDeadlineAt ?? requestedAt + (req.routingIntent?.deadlineMs ?? 6e4);
|
|
8598
8368
|
if (req.lineage === void 0) await registerAssignment(assignmentId);
|
|
@@ -8605,9 +8375,14 @@ function createDispatchBundle(context, options) {
|
|
|
8605
8375
|
const admitted = await capacityAdmission.admit({
|
|
8606
8376
|
assignmentId,
|
|
8607
8377
|
nodeId,
|
|
8378
|
+
...endpoint !== null && endpoint !== void 0 ? { endpointKey: endpoint.key } : {},
|
|
8608
8379
|
deadlineAt,
|
|
8609
8380
|
...plan,
|
|
8610
|
-
|
|
8381
|
+
// A fleet's first attempt carries lineage and still owns the held
|
|
8382
|
+
// reservation member that admission must transfer into its lease.
|
|
8383
|
+
// Retries carry the same reservation identity after that member was
|
|
8384
|
+
// consumed, so they reacquire/rebind the assignment lease normally.
|
|
8385
|
+
...req.reservation !== void 0 && (req.lineage === void 0 || req.lineage.attempt === 0) ? { reservation: req.reservation } : {}
|
|
8611
8386
|
});
|
|
8612
8387
|
timing.admittedAt = new Date(admitted.admittedAt).toISOString();
|
|
8613
8388
|
return admitted.lease;
|
|
@@ -8619,12 +8394,13 @@ function createDispatchBundle(context, options) {
|
|
|
8619
8394
|
throw error;
|
|
8620
8395
|
}
|
|
8621
8396
|
}
|
|
8622
|
-
function rebindReservationSlot(req, nodeId, costUsd, settings) {
|
|
8397
|
+
function rebindReservationSlot(req, nodeId, endpoint, costUsd, settings) {
|
|
8623
8398
|
if (req.reservation === void 0 || req.lineage === void 0) return;
|
|
8624
8399
|
const capacity = reservationCapacitySnapshot(settings);
|
|
8625
8400
|
const rebind = {
|
|
8626
8401
|
...req.reservation,
|
|
8627
8402
|
nodeId,
|
|
8403
|
+
...endpoint !== null ? { endpointKey: endpoint.key } : {},
|
|
8628
8404
|
costUpperBoundUsd: req.routeApproval?.totalCostUpperBoundUsd ?? costUsd,
|
|
8629
8405
|
capacity,
|
|
8630
8406
|
nowMs: now()
|
|
@@ -8691,10 +8467,23 @@ function createDispatchBundle(context, options) {
|
|
|
8691
8467
|
persistAssignment(settleStoredAssignment(rootRunId, attemptRunId, "failed"), `${rootRunId}:finalize-error`);
|
|
8692
8468
|
capacityAdmission.releaseAssignment(rootRunId);
|
|
8693
8469
|
}
|
|
8470
|
+
function retryChainIsLive(run) {
|
|
8471
|
+
if (run.aborted) return false;
|
|
8472
|
+
const reservation = run.req.reservation;
|
|
8473
|
+
if (reservation === void 0) return assignments.get(run.lineage.rootRunId)?.status === "running";
|
|
8474
|
+
try {
|
|
8475
|
+
const record = getDispatchReservation(reservation.ownerId);
|
|
8476
|
+
const member = record?.members.find((entry) => entry.memberId === reservation.memberId);
|
|
8477
|
+
return record?.status === "active" && member !== void 0 && member.status !== "released";
|
|
8478
|
+
} catch (error) {
|
|
8479
|
+
reportDispatchDiagnostic(`read retry liveness for reservation member ${reservation.memberId}`, error);
|
|
8480
|
+
return false;
|
|
8481
|
+
}
|
|
8482
|
+
}
|
|
8694
8483
|
function maybeScheduleRetry(run, outcome, detail, receipt, failureClass) {
|
|
8695
8484
|
if (draining) return { scheduled: false };
|
|
8696
8485
|
const rootRunId = run.lineage.rootRunId;
|
|
8697
|
-
if (
|
|
8486
|
+
if (!retryChainIsLive(run)) return { scheduled: false };
|
|
8698
8487
|
if (!RETRYABLE_OUTCOMES.has(outcome)) {
|
|
8699
8488
|
retryBackoff.delete(rootRunId);
|
|
8700
8489
|
return { scheduled: false };
|
|
@@ -8803,7 +8592,7 @@ function createDispatchBundle(context, options) {
|
|
|
8803
8592
|
});
|
|
8804
8593
|
}
|
|
8805
8594
|
async function executeRetry(run, attempt, reason = "retry", decision = decideRetry("internal", run.lineage.attempt, assignmentPolicyFor(run.req).maxRetries)) {
|
|
8806
|
-
if (draining ||
|
|
8595
|
+
if (draining || !retryChainIsLive(run)) return;
|
|
8807
8596
|
const excludesNode = decision.excludedRouteParts.includes("node");
|
|
8808
8597
|
const rerouteHops = excludesNode && run.node !== null ? [...run.req.reroutes ?? [], { attempt, fromNode: run.node.id, toNode: "", reason }] : run.req.reroutes;
|
|
8809
8598
|
const retryReq = {
|
|
@@ -8817,6 +8606,7 @@ function createDispatchBundle(context, options) {
|
|
|
8817
8606
|
depth: run.lineage.depth
|
|
8818
8607
|
}
|
|
8819
8608
|
};
|
|
8609
|
+
delete retryReq.runIdHint;
|
|
8820
8610
|
const reasonKey = retryReasonKey(run.lineage.rootRunId, attempt);
|
|
8821
8611
|
retryReasons.set(reasonKey, reason);
|
|
8822
8612
|
try {
|
|
@@ -8959,8 +8749,8 @@ function createDispatchBundle(context, options) {
|
|
|
8959
8749
|
fleetRegistry.recordChannelSuccess(run.node.id);
|
|
8960
8750
|
}
|
|
8961
8751
|
}
|
|
8962
|
-
function heartbeatIso(
|
|
8963
|
-
return new Date(
|
|
8752
|
+
function heartbeatIso(heartbeat) {
|
|
8753
|
+
return new Date(heartbeat.current).toISOString();
|
|
8964
8754
|
}
|
|
8965
8755
|
function heartbeatRunStatus(status) {
|
|
8966
8756
|
return status === "alive" ? "running" : status;
|
|
@@ -8979,22 +8769,22 @@ function createDispatchBundle(context, options) {
|
|
|
8979
8769
|
event: {
|
|
8980
8770
|
type: "heartbeat_status",
|
|
8981
8771
|
status,
|
|
8982
|
-
heartbeatAt: run.heartbeatAt ? heartbeatIso(run.heartbeatAt
|
|
8772
|
+
heartbeatAt: run.heartbeatAt ? heartbeatIso(run.heartbeatAt) : null
|
|
8983
8773
|
}
|
|
8984
8774
|
});
|
|
8985
8775
|
}
|
|
8986
8776
|
function checkActiveHeartbeats() {
|
|
8987
8777
|
if (!ledger) return;
|
|
8988
|
-
const
|
|
8778
|
+
const tickMonotonic = monotonicNow();
|
|
8989
8779
|
for (const run of active.values()) {
|
|
8990
8780
|
if (run.aborted || run.stallKilled || !run.heartbeatAt) continue;
|
|
8991
|
-
const
|
|
8992
|
-
if (!Number.isFinite(
|
|
8781
|
+
const heartbeatMonotonic = heartbeatMonotonicAt(run.heartbeatAt);
|
|
8782
|
+
if (!Number.isFinite(heartbeatMonotonic) || !Number.isFinite(run.heartbeatAt.current)) continue;
|
|
8993
8783
|
if (run.runtimeKind === "acp-delegation") {
|
|
8994
|
-
ledger.update(run.runId, { heartbeatAt: heartbeatIso(
|
|
8784
|
+
ledger.update(run.runId, { heartbeatAt: heartbeatIso(run.heartbeatAt) });
|
|
8995
8785
|
const stallMs = run.stallTimeoutMs;
|
|
8996
8786
|
if (stallMs === null || stallMs <= 0) continue;
|
|
8997
|
-
if (
|
|
8787
|
+
if (tickMonotonic - heartbeatMonotonic <= stallMs) continue;
|
|
8998
8788
|
run.stallKilled = true;
|
|
8999
8789
|
run.heartbeatStatus = "dead";
|
|
9000
8790
|
emitHeartbeatStatus(run, "dead");
|
|
@@ -9004,10 +8794,10 @@ function createDispatchBundle(context, options) {
|
|
|
9004
8794
|
}
|
|
9005
8795
|
continue;
|
|
9006
8796
|
}
|
|
9007
|
-
const status = classifyHeartbeat(
|
|
8797
|
+
const status = classifyHeartbeat(heartbeatMonotonic, tickMonotonic, heartbeatSpec);
|
|
9008
8798
|
const patch = {
|
|
9009
8799
|
status: heartbeatRunStatus(status),
|
|
9010
|
-
heartbeatAt: heartbeatIso(
|
|
8800
|
+
heartbeatAt: heartbeatIso(run.heartbeatAt)
|
|
9011
8801
|
};
|
|
9012
8802
|
ledger.update(run.runId, patch);
|
|
9013
8803
|
if (status === "alive" && run.node !== null && run.node.kind === "ssh") {
|
|
@@ -9343,7 +9133,26 @@ function createDispatchBundle(context, options) {
|
|
|
9343
9133
|
const wireModelId = lifecycle.agentConfig.id;
|
|
9344
9134
|
assertTargetNotCoolingDown(req, targetId, runtimeId, wireModelId);
|
|
9345
9135
|
assertBudgetAdmitsRoute(req, { rates: null, provenance: "unknown" }, settings);
|
|
9346
|
-
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
|
+
}
|
|
9347
9156
|
const leaseSlot = createLeaseSlotGuard(capacityAdmission, capacityLease.leaseId, req.lineage !== void 0);
|
|
9348
9157
|
const ledgerRef = (() => {
|
|
9349
9158
|
try {
|
|
@@ -9365,7 +9174,9 @@ function createDispatchBundle(context, options) {
|
|
|
9365
9174
|
cwd: lifecycle.cwd,
|
|
9366
9175
|
safety,
|
|
9367
9176
|
autonomy: lifecycle.autonomy,
|
|
9368
|
-
clientVersion: readClioVersion()
|
|
9177
|
+
clientVersion: readClioVersion(),
|
|
9178
|
+
now,
|
|
9179
|
+
monotonicNow
|
|
9369
9180
|
});
|
|
9370
9181
|
} catch (error) {
|
|
9371
9182
|
leaseSlot.release();
|
|
@@ -9510,15 +9321,17 @@ function createDispatchBundle(context, options) {
|
|
|
9510
9321
|
runIdForPermissionAudit = envelope.id;
|
|
9511
9322
|
lineage = lineageFor(req, envelope.id);
|
|
9512
9323
|
if (req.lineage === void 0) {
|
|
9513
|
-
|
|
9514
|
-
|
|
9324
|
+
if (capacityLease.assignmentId !== lineage.rootRunId) {
|
|
9325
|
+
capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
|
|
9326
|
+
await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
|
|
9327
|
+
}
|
|
9515
9328
|
leaseSlot.transferToAssignment();
|
|
9516
9329
|
}
|
|
9517
9330
|
identity = detectRunIdentity();
|
|
9518
9331
|
ledgerRef.update(envelope.id, {
|
|
9519
9332
|
status: "running",
|
|
9520
9333
|
pid: acp.pid,
|
|
9521
|
-
heartbeatAt: heartbeatIso(acp.heartbeatAt
|
|
9334
|
+
heartbeatAt: heartbeatIso(acp.heartbeatAt),
|
|
9522
9335
|
lineage,
|
|
9523
9336
|
identity,
|
|
9524
9337
|
node: LOCAL_RUN_NODE,
|
|
@@ -9535,16 +9348,18 @@ function createDispatchBundle(context, options) {
|
|
|
9535
9348
|
runtimeKind: "acp-delegation"
|
|
9536
9349
|
});
|
|
9537
9350
|
await ledgerRef.persist();
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
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
|
+
}
|
|
9548
9363
|
context.bus.emit(BusChannels.DispatchStarted, {
|
|
9549
9364
|
runId: envelope.id,
|
|
9550
9365
|
agentId: req.agentId,
|
|
@@ -9878,7 +9693,7 @@ function createDispatchBundle(context, options) {
|
|
|
9878
9693
|
cacheReadTokenCount: receiptDraft.cacheReadTokenCount ?? 0,
|
|
9879
9694
|
cacheWriteTokenCount: receiptDraft.cacheWriteTokenCount ?? 0,
|
|
9880
9695
|
reasoningTokenCount: receiptDraft.reasoningTokenCount ?? 0,
|
|
9881
|
-
heartbeatAt: heartbeatIso(acp.heartbeatAt
|
|
9696
|
+
heartbeatAt: heartbeatIso(acp.heartbeatAt)
|
|
9882
9697
|
};
|
|
9883
9698
|
ledgerRef.update(envelope.id, ledgerPatch);
|
|
9884
9699
|
const receipt = ledgerRef.recordReceipt(envelope.id, sealRouteDecision(receiptDraft, routeDecision));
|
|
@@ -9951,6 +9766,7 @@ function createDispatchBundle(context, options) {
|
|
|
9951
9766
|
throw new Error(`dispatch: invalid spec: ${validated.errors.join("; ")}`);
|
|
9952
9767
|
}
|
|
9953
9768
|
req = validation.restore(validated.spec);
|
|
9769
|
+
if (req.lineage === void 0 && req.runIdHint === void 0) req = { ...req, runIdHint: newRunId() };
|
|
9954
9770
|
let activeRouteObservation = null;
|
|
9955
9771
|
if (req.delegationAgentId === void 0) {
|
|
9956
9772
|
const recipe = agents.get(req.agentId);
|
|
@@ -10015,7 +9831,7 @@ function createDispatchBundle(context, options) {
|
|
|
10015
9831
|
"dispatch: writeRoots cannot be enforced on an ACP delegation target; the external agent runs its own tool surface. Dispatch to a native or claude-sdk worker."
|
|
10016
9832
|
);
|
|
10017
9833
|
}
|
|
10018
|
-
rebindReservationSlot(req, "local", UNKNOWN_PRICING_ADMISSION_ESTIMATE_USD, settings);
|
|
9834
|
+
rebindReservationSlot(req, "local", null, UNKNOWN_PRICING_ADMISSION_ESTIMATE_USD, settings);
|
|
10019
9835
|
routeObservation = observeShadowRoute(req, void 0, settings);
|
|
10020
9836
|
return attachRouteObservation({
|
|
10021
9837
|
...await dispatchAcpDelegation(req, settings, timing, routeObservation.decision, observer),
|
|
@@ -10046,10 +9862,12 @@ function createDispatchBundle(context, options) {
|
|
|
10046
9862
|
model: lifecycle.target.wireModelId,
|
|
10047
9863
|
node: placement?.node?.id ?? "local"
|
|
10048
9864
|
};
|
|
9865
|
+
const endpoint = endpointCapacityForTarget(lifecycle.target.target.id);
|
|
10049
9866
|
assertRouteWithinApprovedEnvelope(req, effectiveRoute);
|
|
10050
9867
|
rebindReservationSlot(
|
|
10051
9868
|
req,
|
|
10052
9869
|
effectiveRoute.node,
|
|
9870
|
+
endpoint,
|
|
10053
9871
|
conservativeRouteAdmissionEstimateUsd(lifecycle.target.effectivePricing, admissionMaxOutputTokens(settings)),
|
|
10054
9872
|
settings
|
|
10055
9873
|
);
|
|
@@ -10067,7 +9885,34 @@ function createDispatchBundle(context, options) {
|
|
|
10067
9885
|
},
|
|
10068
9886
|
shadow: () => observeShadowRoute(req, placed, settings)
|
|
10069
9887
|
});
|
|
10070
|
-
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
|
+
}
|
|
10071
9916
|
const leaseSlot = createLeaseSlotGuard(capacityAdmission, capacityLease.leaseId, req.lineage !== void 0);
|
|
10072
9917
|
const ledgerRef = (() => {
|
|
10073
9918
|
try {
|
|
@@ -10125,6 +9970,8 @@ function createDispatchBundle(context, options) {
|
|
|
10125
9970
|
try {
|
|
10126
9971
|
worker = (placement?.spawn ?? spawnWorker)(spec, {
|
|
10127
9972
|
cwd: lifecycle.cwd,
|
|
9973
|
+
now,
|
|
9974
|
+
monotonicNow,
|
|
10128
9975
|
...agentLedgerId !== null ? { onLedgerPost } : {}
|
|
10129
9976
|
});
|
|
10130
9977
|
} catch (error) {
|
|
@@ -10174,7 +10021,18 @@ function createDispatchBundle(context, options) {
|
|
|
10174
10021
|
const upstreamResponses = [];
|
|
10175
10022
|
const skillActivations = [];
|
|
10176
10023
|
const finishContractEntries = [];
|
|
10177
|
-
|
|
10024
|
+
let runIdForPermissionAudit = null;
|
|
10025
|
+
const runEffects = createRunEffectsRecorder(lifecycle.cwd, {
|
|
10026
|
+
onWriteRecordDowngraded(downgrade) {
|
|
10027
|
+
const runId = runIdForPermissionAudit;
|
|
10028
|
+
if (runId === null) return;
|
|
10029
|
+
context.bus.emit(BusChannels.DispatchProgress, {
|
|
10030
|
+
runId,
|
|
10031
|
+
agentId: req.agentId,
|
|
10032
|
+
event: { type: "clio_write_record_downgraded", payload: downgrade }
|
|
10033
|
+
});
|
|
10034
|
+
}
|
|
10035
|
+
});
|
|
10178
10036
|
let finishContractAssistantText = "";
|
|
10179
10037
|
let finishContractAssistantTurnId = null;
|
|
10180
10038
|
let failureMessage;
|
|
@@ -10182,7 +10040,6 @@ function createDispatchBundle(context, options) {
|
|
|
10182
10040
|
const trustedOutcomeCodes = /* @__PURE__ */ new Set();
|
|
10183
10041
|
let reportedUntrustedOutcome = false;
|
|
10184
10042
|
const acceptsOutcomeCodeEvents = lifecycle.runtimeKind === "http" || lifecycle.runtimeKind === "sdk" && lifecycle.target.runtime.id === "claude-sdk";
|
|
10185
|
-
let runIdForPermissionAudit = null;
|
|
10186
10043
|
let workerPolicyPermissionCounter = 0;
|
|
10187
10044
|
const outputCapture = createWorkerOutputCapture();
|
|
10188
10045
|
const markObservedPhase = (field) => {
|
|
@@ -10253,6 +10110,7 @@ function createDispatchBundle(context, options) {
|
|
|
10253
10110
|
...ruleId !== null ? { ruleId } : {},
|
|
10254
10111
|
...policySource !== null ? { policySource } : {},
|
|
10255
10112
|
...typeof event.payload.timeoutMs === "number" ? { timeoutMs: event.payload.timeoutMs } : {},
|
|
10113
|
+
fallback: spec.escalation?.fallback ?? "deny",
|
|
10256
10114
|
escalation: true
|
|
10257
10115
|
});
|
|
10258
10116
|
}
|
|
@@ -10310,6 +10168,7 @@ function createDispatchBundle(context, options) {
|
|
|
10310
10168
|
decidedBy,
|
|
10311
10169
|
actionClass,
|
|
10312
10170
|
reason,
|
|
10171
|
+
...source === "timeout" ? { fallback: spec.escalation?.fallback ?? "deny" } : {},
|
|
10313
10172
|
...runIdForPermissionAudit !== null ? { requestedBy: runIdForPermissionAudit } : {}
|
|
10314
10173
|
});
|
|
10315
10174
|
}
|
|
@@ -10362,8 +10221,10 @@ function createDispatchBundle(context, options) {
|
|
|
10362
10221
|
runIdForPermissionAudit = envelope.id;
|
|
10363
10222
|
lineage = lineageFor(req, envelope.id);
|
|
10364
10223
|
if (req.lineage === void 0) {
|
|
10365
|
-
|
|
10366
|
-
|
|
10224
|
+
if (capacityLease.assignmentId !== lineage.rootRunId) {
|
|
10225
|
+
capacityAdmission.rename(capacityLease.leaseId, lineage.rootRunId);
|
|
10226
|
+
await renameStoredAssignment(capacityLease.assignmentId, lineage.rootRunId);
|
|
10227
|
+
}
|
|
10367
10228
|
leaseSlot.transferToAssignment();
|
|
10368
10229
|
}
|
|
10369
10230
|
if (agentLedgerId !== null) {
|
|
@@ -10395,7 +10256,7 @@ function createDispatchBundle(context, options) {
|
|
|
10395
10256
|
...req.council !== void 0 ? { council: req.council } : {},
|
|
10396
10257
|
...req.plan !== void 0 ? { plan: req.plan } : {},
|
|
10397
10258
|
...lifecycle.personaOverride ? { personaOverride: lifecycle.personaOverride } : {},
|
|
10398
|
-
...heartbeatAt ? { heartbeatAt: heartbeatIso(heartbeatAt
|
|
10259
|
+
...heartbeatAt ? { heartbeatAt: heartbeatIso(heartbeatAt) } : {}
|
|
10399
10260
|
});
|
|
10400
10261
|
observer?.onAdmitted({
|
|
10401
10262
|
runId: envelope.id,
|
|
@@ -10405,24 +10266,27 @@ function createDispatchBundle(context, options) {
|
|
|
10405
10266
|
await ledgerRef.persist();
|
|
10406
10267
|
const fleetIdentity = {
|
|
10407
10268
|
budget: lifecycle.budgetEnvelope,
|
|
10269
|
+
...endpoint !== null ? { endpoint: { key: endpoint.key, label: endpoint.label, limit: endpoint.limit } } : {},
|
|
10408
10270
|
...placement !== void 0 && placement !== null ? { node: placement.node.id } : {},
|
|
10409
10271
|
...req.gate !== void 0 ? { gate: { role: req.gate.role, cycle: req.gate.cycle } } : {},
|
|
10410
10272
|
...req.council !== void 0 ? { council: req.council } : {},
|
|
10411
10273
|
...req.reroutes !== void 0 && req.reroutes.length > 0 ? { rerouteCount: req.reroutes.length } : {},
|
|
10412
10274
|
...lifecycle.target.modelCapabilities !== void 0 && lifecycle.target.modelCapabilities !== null && lifecycle.target.modelCapabilities.contextWindow > 0 ? { contextWindow: lifecycle.target.modelCapabilities.contextWindow } : {}
|
|
10413
10275
|
};
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
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
|
+
}
|
|
10426
10290
|
context.bus.emit(BusChannels.DispatchStarted, {
|
|
10427
10291
|
runId: envelope.id,
|
|
10428
10292
|
agentId: req.agentId,
|
|
@@ -10527,10 +10391,10 @@ function createDispatchBundle(context, options) {
|
|
|
10527
10391
|
const fleetGate = (() => {
|
|
10528
10392
|
if (req.fleetGateReceipt === void 0) return null;
|
|
10529
10393
|
try {
|
|
10530
|
-
const content =
|
|
10531
|
-
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") };
|
|
10532
10396
|
} catch {
|
|
10533
|
-
return { path: req.fleetGateReceipt.path, pathHash:
|
|
10397
|
+
return { path: req.fleetGateReceipt.path, pathHash: createHash7("sha256").update("").digest("hex") };
|
|
10534
10398
|
}
|
|
10535
10399
|
})();
|
|
10536
10400
|
const ledgerContribution = (() => {
|
|
@@ -10785,18 +10649,7 @@ function createDispatchBundle(context, options) {
|
|
|
10785
10649
|
cwd: lifecycle.cwd,
|
|
10786
10650
|
networkAllowed: lifecycle.admission.allowedTools.includes(ToolNames.WebFetch),
|
|
10787
10651
|
observedRunEffects,
|
|
10788
|
-
filesystem:
|
|
10789
|
-
readFile(filePath) {
|
|
10790
|
-
try {
|
|
10791
|
-
return readFileSync12(filePath, "utf8");
|
|
10792
|
-
} catch {
|
|
10793
|
-
return null;
|
|
10794
|
-
}
|
|
10795
|
-
},
|
|
10796
|
-
pathExists(filePath) {
|
|
10797
|
-
return existsSync12(filePath);
|
|
10798
|
-
}
|
|
10799
|
-
}
|
|
10652
|
+
filesystem: nodeResultContractFilesystem()
|
|
10800
10653
|
});
|
|
10801
10654
|
const resultValidation = resultContract?.applicable === true ? resultContract.validation : null;
|
|
10802
10655
|
if (finalOutcome === "succeeded" && resultValidation?.conformance === "fail") {
|
|
@@ -10887,15 +10740,35 @@ function createDispatchBundle(context, options) {
|
|
|
10887
10740
|
dynamicHash: receiptDraft.dynamicHash ?? null,
|
|
10888
10741
|
...receiptDraft.cacheReadTokenCount !== void 0 ? { cacheReadTokenCount: receiptDraft.cacheReadTokenCount } : {},
|
|
10889
10742
|
...receiptDraft.cacheWriteTokenCount !== void 0 ? { cacheWriteTokenCount: receiptDraft.cacheWriteTokenCount } : {},
|
|
10890
|
-
...activeRun.heartbeatAt ? { heartbeatAt: heartbeatIso(activeRun.heartbeatAt
|
|
10743
|
+
...activeRun.heartbeatAt ? { heartbeatAt: heartbeatIso(activeRun.heartbeatAt) } : {}
|
|
10891
10744
|
};
|
|
10892
10745
|
if (receiptDraft.reasoningTokenCount !== void 0) {
|
|
10893
10746
|
ledgerPatch.reasoningTokenCount = receiptDraft.reasoningTokenCount;
|
|
10894
10747
|
}
|
|
10895
10748
|
ledgerRef.update(envelope.id, ledgerPatch);
|
|
10896
10749
|
const receipt = ledgerRef.recordReceipt(envelope.id, sealRouteDecision(receiptDraft, routeObservation.decision));
|
|
10897
|
-
const
|
|
10898
|
-
|
|
10750
|
+
const toolTelemetryComplete = receipt.safety?.toolTelemetry?.coverage === "complete";
|
|
10751
|
+
const downgrades = observedRunEffects.writeRecordDowngrades.map((entry) => ({
|
|
10752
|
+
reason: entry.reason,
|
|
10753
|
+
tool: entry.tool,
|
|
10754
|
+
toolCallId: entry.toolCallId,
|
|
10755
|
+
runId: envelope.id,
|
|
10756
|
+
stepId: null
|
|
10757
|
+
}));
|
|
10758
|
+
if (!toolTelemetryComplete) {
|
|
10759
|
+
downgrades.push({
|
|
10760
|
+
reason: "incomplete_tool_telemetry",
|
|
10761
|
+
tool: null,
|
|
10762
|
+
toolCallId: null,
|
|
10763
|
+
runId: envelope.id,
|
|
10764
|
+
stepId: null
|
|
10765
|
+
});
|
|
10766
|
+
}
|
|
10767
|
+
recordRunWriteAttribution(envelope.id, {
|
|
10768
|
+
recorded: [...observedRunEffects.mutatedPaths],
|
|
10769
|
+
complete: toolTelemetryComplete && observedRunEffects.writeRecordComplete,
|
|
10770
|
+
downgrades
|
|
10771
|
+
});
|
|
10899
10772
|
await ledgerRef.persist();
|
|
10900
10773
|
if (worktreeReceipt?.applied === true && req.taskWorktree !== void 0) {
|
|
10901
10774
|
try {
|
|
@@ -11136,12 +11009,14 @@ function createDispatchBundle(context, options) {
|
|
|
11136
11009
|
allowedTools: effectiveTools,
|
|
11137
11010
|
settings
|
|
11138
11011
|
});
|
|
11012
|
+
const endpoint = endpointCapacityForTarget(target.target.id);
|
|
11139
11013
|
return {
|
|
11140
11014
|
agentId: req.agentId,
|
|
11141
11015
|
specFingerprint: agentSpecFingerprint(agentSpec),
|
|
11142
11016
|
targetId: target.target.id,
|
|
11143
11017
|
wireModelId: target.wireModelId,
|
|
11144
11018
|
runtimeId: target.runtime.id,
|
|
11019
|
+
...endpoint !== null ? { endpoint: { key: endpoint.key, label: endpoint.label, limit: endpoint.limit } } : {},
|
|
11145
11020
|
node: previewNode(req).node,
|
|
11146
11021
|
thinkingLevel: target.thinkingLevel,
|
|
11147
11022
|
toolSignature: toolSignature(effectiveTools),
|
|
@@ -11483,8 +11358,10 @@ function createDispatchBundle(context, options) {
|
|
|
11483
11358
|
});
|
|
11484
11359
|
return receipt;
|
|
11485
11360
|
}
|
|
11361
|
+
let journalBridge = null;
|
|
11486
11362
|
const extension = {
|
|
11487
11363
|
async start() {
|
|
11364
|
+
if (options?.journalRunEvents === true) journalBridge = attachRunEventJournalBridge(context.bus);
|
|
11488
11365
|
cleanupDispatchReservations({ startup: true, nowMs: now() });
|
|
11489
11366
|
ledger = openLedger();
|
|
11490
11367
|
try {
|
|
@@ -11536,6 +11413,8 @@ function createDispatchBundle(context, options) {
|
|
|
11536
11413
|
for (const ownerId of ownedReservations) rollbackDispatchReservation(ownerId, now());
|
|
11537
11414
|
ownedReservations.clear();
|
|
11538
11415
|
await Promise.allSettled([...assignmentWrites]);
|
|
11416
|
+
journalBridge?.stop();
|
|
11417
|
+
journalBridge = null;
|
|
11539
11418
|
}
|
|
11540
11419
|
};
|
|
11541
11420
|
function emitRunAborted(run, source) {
|
|
@@ -11552,19 +11431,41 @@ function createDispatchBundle(context, options) {
|
|
|
11552
11431
|
}
|
|
11553
11432
|
function snapshot() {
|
|
11554
11433
|
const tickNow = now();
|
|
11434
|
+
const tickMonotonic = monotonicNow();
|
|
11555
11435
|
const running = [];
|
|
11556
11436
|
const totals = { ...finalizedTotals };
|
|
11557
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
|
+
}
|
|
11558
11458
|
for (const run of active.values()) {
|
|
11559
11459
|
let heartbeat = "n/a";
|
|
11560
|
-
if (run.heartbeatAt && Number.isFinite(run.heartbeatAt
|
|
11460
|
+
if (run.heartbeatAt && Number.isFinite(heartbeatMonotonicAt(run.heartbeatAt))) {
|
|
11461
|
+
const heartbeatMonotonic = heartbeatMonotonicAt(run.heartbeatAt);
|
|
11561
11462
|
if (run.runtimeKind === "acp-delegation") {
|
|
11562
11463
|
const stallMs = run.stallTimeoutMs;
|
|
11563
11464
|
if (stallMs !== null && stallMs > 0) {
|
|
11564
|
-
heartbeat =
|
|
11465
|
+
heartbeat = tickMonotonic - heartbeatMonotonic > stallMs ? "dead" : "alive";
|
|
11565
11466
|
}
|
|
11566
11467
|
} else {
|
|
11567
|
-
heartbeat = classifyHeartbeat(
|
|
11468
|
+
heartbeat = classifyHeartbeat(heartbeatMonotonic, tickMonotonic, heartbeatSpec);
|
|
11568
11469
|
}
|
|
11569
11470
|
}
|
|
11570
11471
|
const meter = run.meter;
|
|
@@ -11678,6 +11579,7 @@ function createDispatchBundle(context, options) {
|
|
|
11678
11579
|
routeCandidates,
|
|
11679
11580
|
reservations: {
|
|
11680
11581
|
prepare: prepareReservation,
|
|
11582
|
+
release: (ownerId) => releaseDispatchReservation(ownerId, now()),
|
|
11681
11583
|
rollback: (ownerId) => rollbackDispatchReservation(ownerId, now()),
|
|
11682
11584
|
rollbackUnconsumed: (ownerId) => rollbackUnconsumedDispatchReservation(ownerId, now()),
|
|
11683
11585
|
get: getDispatchReservation
|
|
@@ -11696,7 +11598,17 @@ function createDispatchBundle(context, options) {
|
|
|
11696
11598
|
return ledger.get(runId);
|
|
11697
11599
|
},
|
|
11698
11600
|
observedRunWrites(runId) {
|
|
11699
|
-
|
|
11601
|
+
const attribution = runWriteAttributions.get(runId);
|
|
11602
|
+
return attribution?.complete === true ? [...attribution.recorded] : null;
|
|
11603
|
+
},
|
|
11604
|
+
observedRunWriteAttribution(runId) {
|
|
11605
|
+
const attribution = runWriteAttributions.get(runId);
|
|
11606
|
+
if (attribution === void 0) return null;
|
|
11607
|
+
return {
|
|
11608
|
+
recorded: [...attribution.recorded],
|
|
11609
|
+
complete: attribution.complete,
|
|
11610
|
+
downgrades: attribution.downgrades?.map((entry) => ({ ...entry })) ?? []
|
|
11611
|
+
};
|
|
11700
11612
|
},
|
|
11701
11613
|
assignments: {
|
|
11702
11614
|
get: (id) => assignments.get(id),
|
|
@@ -11707,6 +11619,17 @@ function createDispatchBundle(context, options) {
|
|
|
11707
11619
|
},
|
|
11708
11620
|
abort(runId, reason) {
|
|
11709
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
|
+
}
|
|
11710
11633
|
const assignment = assignments.get(rootRunId);
|
|
11711
11634
|
if (assignment?.status === "running") {
|
|
11712
11635
|
assignments.cancel(assignment.id);
|
|
@@ -11807,12 +11730,12 @@ var DispatchManifest = {
|
|
|
11807
11730
|
|
|
11808
11731
|
// src/domains/dispatch/code-step-store.ts
|
|
11809
11732
|
init_esm_shims();
|
|
11810
|
-
import { join as
|
|
11733
|
+
import { join as join13 } from "node:path";
|
|
11811
11734
|
function codeStepDir(rootId) {
|
|
11812
|
-
return
|
|
11735
|
+
return join13(clioStateDir(), "code-steps", rootId);
|
|
11813
11736
|
}
|
|
11814
11737
|
function codeStepRecordPath(rootId, runId) {
|
|
11815
|
-
return
|
|
11738
|
+
return join13(codeStepDir(rootId), `${runId}.json`);
|
|
11816
11739
|
}
|
|
11817
11740
|
async function writeCodeStepRecord(rootId, record) {
|
|
11818
11741
|
const path2 = codeStepRecordPath(rootId, record.runId);
|
|
@@ -11823,7 +11746,7 @@ async function writeCodeStepRecord(rootId, record) {
|
|
|
11823
11746
|
|
|
11824
11747
|
// src/domains/dispatch/delegation-plan.ts
|
|
11825
11748
|
init_esm_shims();
|
|
11826
|
-
import { createHash as
|
|
11749
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
11827
11750
|
var DELEGATION_PROPOSAL_BRIEFING_MAX_BYTES = 12e3;
|
|
11828
11751
|
function buildDelegationProposalBriefing(proposals) {
|
|
11829
11752
|
const value = proposals.map((proposal) => `PROPOSAL ${proposal.agent}
|
|
@@ -11931,7 +11854,7 @@ function validateDelegationPlan(input) {
|
|
|
11931
11854
|
}
|
|
11932
11855
|
}
|
|
11933
11856
|
const plan = { tasks };
|
|
11934
|
-
return { ok: true, plan, hash:
|
|
11857
|
+
return { ok: true, plan, hash: createHash8("sha256").update(JSON.stringify(plan)).digest("hex") };
|
|
11935
11858
|
}
|
|
11936
11859
|
|
|
11937
11860
|
// src/domains/dispatch/execution-scheduler.ts
|
|
@@ -12359,9 +12282,125 @@ function gateFailureLines(output) {
|
|
|
12359
12282
|
|
|
12360
12283
|
// src/domains/dispatch/fleet-run.ts
|
|
12361
12284
|
init_esm_shims();
|
|
12362
|
-
import { createHash as
|
|
12363
|
-
import { readFileSync as
|
|
12364
|
-
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
|
+
}
|
|
12365
12404
|
|
|
12366
12405
|
// src/domains/dispatch/fleet-commit-attribution.ts
|
|
12367
12406
|
init_esm_shims();
|
|
@@ -12453,6 +12492,11 @@ function fleetGateCorrelation(subject, decider) {
|
|
|
12453
12492
|
);
|
|
12454
12493
|
return { agent, target, modelFamily: modelFamily2, runtime, node, independent };
|
|
12455
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
|
+
}
|
|
12456
12500
|
function fleetPlanWaveIndex(plan, stepId) {
|
|
12457
12501
|
return plan.waves.findIndex((wave) => wave.includes(stepId));
|
|
12458
12502
|
}
|
|
@@ -12490,10 +12534,29 @@ async function executeFleetRun(input) {
|
|
|
12490
12534
|
boundaryFor: (stepId) => livePlan.steps.find((step) => step.id === stepId)?.writes,
|
|
12491
12535
|
recordedWritesFor: (stepId) => {
|
|
12492
12536
|
const step = livePlan.steps.find((entry) => entry.id === stepId);
|
|
12493
|
-
if (step === void 0
|
|
12537
|
+
if (step === void 0) return null;
|
|
12538
|
+
if (step.kind !== "agent") {
|
|
12539
|
+
return {
|
|
12540
|
+
recorded: [],
|
|
12541
|
+
complete: false,
|
|
12542
|
+
downgrades: [
|
|
12543
|
+
{
|
|
12544
|
+
reason: "code_step_untracked",
|
|
12545
|
+
tool: null,
|
|
12546
|
+
toolCallId: null,
|
|
12547
|
+
runId: null,
|
|
12548
|
+
stepId
|
|
12549
|
+
}
|
|
12550
|
+
]
|
|
12551
|
+
};
|
|
12552
|
+
}
|
|
12494
12553
|
const receipt = receiptsByStep.get(stepId);
|
|
12495
12554
|
if (receipt === void 0) return null;
|
|
12496
|
-
|
|
12555
|
+
if (dispatch.observedRunWriteAttribution !== void 0) {
|
|
12556
|
+
return dispatch.observedRunWriteAttribution(receipt.runId);
|
|
12557
|
+
}
|
|
12558
|
+
const recorded = dispatch.observedRunWrites?.(receipt.runId) ?? null;
|
|
12559
|
+
return recorded === null ? null : { recorded, complete: true, downgrades: [] };
|
|
12497
12560
|
},
|
|
12498
12561
|
onVerdict(verdict, path2) {
|
|
12499
12562
|
if (verdict.detail === null) return;
|
|
@@ -12505,7 +12568,7 @@ async function executeFleetRun(input) {
|
|
|
12505
12568
|
for (const [stepId, replayedResult] of replayed) {
|
|
12506
12569
|
try {
|
|
12507
12570
|
const receipt = JSON.parse(
|
|
12508
|
-
|
|
12571
|
+
readFileSync12(join14(clioStateDir(), "receipts", `${replayedResult.terminalRunId}.json`), "utf8")
|
|
12509
12572
|
);
|
|
12510
12573
|
receiptsByStep.set(stepId, receipt);
|
|
12511
12574
|
} catch {
|
|
@@ -12526,6 +12589,9 @@ async function executeFleetRun(input) {
|
|
|
12526
12589
|
succeeded: true,
|
|
12527
12590
|
terminalRunId: replayedResult.terminalRunId,
|
|
12528
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",
|
|
12529
12595
|
result: replayedResult
|
|
12530
12596
|
});
|
|
12531
12597
|
await fileStepAttempt(replayedResult.terminalRunId);
|
|
@@ -12595,11 +12661,13 @@ async function executeFleetRun(input) {
|
|
|
12595
12661
|
if (step.planParentId !== void 0 && parentReceipt === void 0) {
|
|
12596
12662
|
throw new Error(`fleet dynamic step '${step.id}' has no terminal plan-step receipt`);
|
|
12597
12663
|
}
|
|
12664
|
+
const stepIntent = fleetStepIntent(step.writes);
|
|
12598
12665
|
const request = {
|
|
12599
12666
|
agentId: step.agentId,
|
|
12600
12667
|
executionRole: step.executionRole,
|
|
12601
12668
|
task: step.task,
|
|
12602
12669
|
cwd: workspaceRoot,
|
|
12670
|
+
...stepIntent === null ? {} : { intent: stepIntent },
|
|
12603
12671
|
predecessorHandoffs: handoffs,
|
|
12604
12672
|
requestOrigin: "user",
|
|
12605
12673
|
lineage: {
|
|
@@ -12687,11 +12755,11 @@ async function executeFleetRun(input) {
|
|
|
12687
12755
|
if (step.gate !== void 0 && succeeded) {
|
|
12688
12756
|
let gateBytes = "";
|
|
12689
12757
|
try {
|
|
12690
|
-
gateBytes =
|
|
12758
|
+
gateBytes = readFileSync12(join14(workspaceRoot, step.gate.path), "utf8");
|
|
12691
12759
|
} catch {
|
|
12692
12760
|
gateBytes = "";
|
|
12693
12761
|
}
|
|
12694
|
-
gatePathHash =
|
|
12762
|
+
gatePathHash = createHash9("sha256").update(gateBytes).digest("hex");
|
|
12695
12763
|
const command = input.commands?.commands.get(step.gate.commandId);
|
|
12696
12764
|
if (gateBytes.length === 0 || command === void 0) {
|
|
12697
12765
|
stepSucceeded = false;
|
|
@@ -12743,11 +12811,12 @@ async function executeFleetRun(input) {
|
|
|
12743
12811
|
succeeded: stepSucceeded,
|
|
12744
12812
|
terminalRunId: receipt.runId,
|
|
12745
12813
|
costUsd: receipt.costUsd,
|
|
12814
|
+
costProvenance: receipt.costProvenance,
|
|
12746
12815
|
receipt,
|
|
12747
12816
|
...failureReason !== void 0 ? { failureReason } : {}
|
|
12748
12817
|
});
|
|
12749
12818
|
notice(
|
|
12750
|
-
`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)}`
|
|
12751
12820
|
);
|
|
12752
12821
|
return {
|
|
12753
12822
|
stepId: step.id,
|
|
@@ -12806,6 +12875,8 @@ async function executeFleetRun(input) {
|
|
|
12806
12875
|
succeeded: outcome.report.passed,
|
|
12807
12876
|
terminalRunId: outcome.record.runId,
|
|
12808
12877
|
costUsd: 0,
|
|
12878
|
+
// No model ran, so nothing needed pricing. This zero was observed.
|
|
12879
|
+
costProvenance: "known_free",
|
|
12809
12880
|
codeStep: outcome.record,
|
|
12810
12881
|
recordPath
|
|
12811
12882
|
});
|
|
@@ -12864,7 +12935,7 @@ async function executeFleetRun(input) {
|
|
|
12864
12935
|
cancel: (assignmentId) => dispatch.abort(assignmentId),
|
|
12865
12936
|
release: (ownerId) => {
|
|
12866
12937
|
if (ownerId === NO_WORKER_RESERVATION) return;
|
|
12867
|
-
dispatch.reservations?.
|
|
12938
|
+
dispatch.reservations?.release(ownerId);
|
|
12868
12939
|
},
|
|
12869
12940
|
releaseUnconsumed: (ownerId) => {
|
|
12870
12941
|
if (ownerId === NO_WORKER_RESERVATION) return;
|
|
@@ -12929,6 +13000,9 @@ async function executeFleetRun(input) {
|
|
|
12929
13000
|
result,
|
|
12930
13001
|
receipts,
|
|
12931
13002
|
totalCostUsd: receipts.reduce((sum, receipt) => sum + receipt.costUsd, 0),
|
|
13003
|
+
totalCost: aggregateCostAmounts(
|
|
13004
|
+
receipts.map((receipt) => ({ usd: receipt.costUsd, provenance: receipt.costProvenance }))
|
|
13005
|
+
),
|
|
12932
13006
|
requiredStepCount: required.length,
|
|
12933
13007
|
succeededStepCount,
|
|
12934
13008
|
resolvedLoopCount: result.loops.length - failedLoops.length,
|
|
@@ -12977,6 +13051,36 @@ function attributeEvidenceFailure(facts) {
|
|
|
12977
13051
|
return "unknown";
|
|
12978
13052
|
}
|
|
12979
13053
|
|
|
13054
|
+
// src/domains/evidence/findings-markdown.ts
|
|
13055
|
+
init_esm_shims();
|
|
13056
|
+
function renderEvidenceFindingsMarkdown(findings, trustStatus) {
|
|
13057
|
+
const lines = ["# Findings", "", "## Canonical trust", ""];
|
|
13058
|
+
if (trustStatus.runs.length === 0) {
|
|
13059
|
+
lines.push("No linked run trust status.");
|
|
13060
|
+
} else {
|
|
13061
|
+
for (const run of trustStatus.runs) {
|
|
13062
|
+
lines.push(
|
|
13063
|
+
`- run=${run.runId}`,
|
|
13064
|
+
` tier: ${trustVerdict(run.status)}`,
|
|
13065
|
+
` summary: ${formatTrustSummary(run.status)}`,
|
|
13066
|
+
` axes: ${formatTrustAxes(run.status)}`
|
|
13067
|
+
);
|
|
13068
|
+
}
|
|
13069
|
+
}
|
|
13070
|
+
lines.push("", "## Finding records", "");
|
|
13071
|
+
if (findings.length === 0) {
|
|
13072
|
+
lines.push("No findings.");
|
|
13073
|
+
} else {
|
|
13074
|
+
for (const item of findings) {
|
|
13075
|
+
const run = item.runId === null ? "" : ` run=${item.runId}`;
|
|
13076
|
+
lines.push(`- ${item.id} [${item.severity}] ${item.tag}${run}: ${item.message}`);
|
|
13077
|
+
}
|
|
13078
|
+
}
|
|
13079
|
+
lines.push("");
|
|
13080
|
+
return `${lines.join("\n")}
|
|
13081
|
+
`;
|
|
13082
|
+
}
|
|
13083
|
+
|
|
12980
13084
|
// src/domains/evidence/provenance.ts
|
|
12981
13085
|
init_esm_shims();
|
|
12982
13086
|
var PERSONA_HASH_PREFIX_CHARS = 12;
|
|
@@ -13126,6 +13230,37 @@ init_esm_shims();
|
|
|
13126
13230
|
// src/domains/evidence/types.ts
|
|
13127
13231
|
init_esm_shims();
|
|
13128
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
|
+
];
|
|
13129
13264
|
var FAILURE_CAUSE_TAG_ORDER = [
|
|
13130
13265
|
"timeout",
|
|
13131
13266
|
"auth-failure",
|
|
@@ -13148,7 +13283,6 @@ function buildEvidenceTrustStatusFile(input) {
|
|
|
13148
13283
|
evidenceId: input.evidenceId,
|
|
13149
13284
|
source,
|
|
13150
13285
|
gateDecisions: input.gateDecisions,
|
|
13151
|
-
auditRows: input.auditRows,
|
|
13152
13286
|
validationEvidence: input.validationEvidence?.get(source.envelope.id) ?? []
|
|
13153
13287
|
})
|
|
13154
13288
|
}))
|
|
@@ -13156,7 +13290,6 @@ function buildEvidenceTrustStatusFile(input) {
|
|
|
13156
13290
|
}
|
|
13157
13291
|
function composeEvidenceRunTrustStatus(input) {
|
|
13158
13292
|
const inspection = inspectRunReceiptTrustStatus(input.source.receipt, input.source.envelope);
|
|
13159
|
-
const receiptRejected = inspection.status.artifactIntegrity.state === "failed";
|
|
13160
13293
|
let status = inspection.status;
|
|
13161
13294
|
const grounded = input.validationEvidence.filter((artifact) => isTrustStatusIdentifier(artifact.id));
|
|
13162
13295
|
if (grounded.length > 0 && (status.validationGrounding.state === "absent" || status.validationGrounding.state === "unknown")) {
|
|
@@ -13181,21 +13314,6 @@ function composeEvidenceRunTrustStatus(input) {
|
|
|
13181
13314
|
independentReview: adaptGateDecisionReviewStatus(gate, input.source.envelope.id, verification)
|
|
13182
13315
|
});
|
|
13183
13316
|
}
|
|
13184
|
-
const finish = latestFinishContractForRun(input.auditRows, input.source.envelope.id);
|
|
13185
|
-
if (finish !== null) {
|
|
13186
|
-
const completion = adaptFinishContractCompletionStatus(finish.assessment, {
|
|
13187
|
-
sourceId: finish.sourceId,
|
|
13188
|
-
artifacts: finish.artifacts
|
|
13189
|
-
});
|
|
13190
|
-
status = composeTrustStatus(status, {
|
|
13191
|
-
completionEvidence: receiptRejected && completion.state === "evidenced" ? {
|
|
13192
|
-
state: "unknown",
|
|
13193
|
-
source: { kind: "finish_contract", id: finish.sourceId },
|
|
13194
|
-
authority: { kind: "clio", id: "finish-contract" },
|
|
13195
|
-
artifacts: finish.artifacts
|
|
13196
|
-
} : completion
|
|
13197
|
-
});
|
|
13198
|
-
}
|
|
13199
13317
|
return status;
|
|
13200
13318
|
}
|
|
13201
13319
|
function latestGateDecisionForRun(decisions, runId) {
|
|
@@ -13203,60 +13321,11 @@ function latestGateDecisionForRun(decisions, runId) {
|
|
|
13203
13321
|
(left, right) => compareCodepoints(left.createdAt, right.createdAt) || left.cycle - right.cycle || compareCodepoints(left.id, right.id)
|
|
13204
13322
|
).at(-1) ?? null;
|
|
13205
13323
|
}
|
|
13206
|
-
function latestFinishContractForRun(rows, runId) {
|
|
13207
|
-
const candidates = rows.filter((row) => row.auditKind === "completion_contract" && row.runId === runId && row.confidence === "exact").flatMap((row) => {
|
|
13208
|
-
const assessment = finishContractAssessmentFromAudit(row.row);
|
|
13209
|
-
if (assessment === null) return [];
|
|
13210
|
-
const correlationId = readOptionalString(row.row.correlationId) ?? `${runId}:completion-contract`;
|
|
13211
|
-
if (!isTrustStatusIdentifier(correlationId)) return [];
|
|
13212
|
-
const turnId = readOptionalString(row.row.turnId);
|
|
13213
|
-
const artifacts = [
|
|
13214
|
-
{ kind: "finish_contract_evidence", id: correlationId },
|
|
13215
|
-
...turnId === null || !isTrustStatusIdentifier(turnId) ? [] : [{ kind: "session_entry", id: turnId }]
|
|
13216
|
-
];
|
|
13217
|
-
return [{ sourceId: correlationId, assessment, artifacts, timestamp: row.ts ?? "" }];
|
|
13218
|
-
}).sort(
|
|
13219
|
-
(left, right) => compareCodepoints(left.timestamp, right.timestamp) || compareCodepoints(left.sourceId, right.sourceId)
|
|
13220
|
-
);
|
|
13221
|
-
const latest2 = candidates.at(-1);
|
|
13222
|
-
return latest2 === void 0 ? null : { sourceId: latest2.sourceId, assessment: latest2.assessment, artifacts: latest2.artifacts };
|
|
13223
|
-
}
|
|
13224
|
-
function finishContractAssessmentFromAudit(row) {
|
|
13225
|
-
const reason = readOptionalString(row.reason);
|
|
13226
|
-
const decision = readOptionalString(row.decision);
|
|
13227
|
-
const mutatedPaths = Array.isArray(row.mutatedPaths) ? row.mutatedPaths.filter((entry) => typeof entry === "string") : [];
|
|
13228
|
-
const turnId = readOptionalString(row.turnId);
|
|
13229
|
-
const evidenceKinds = Array.isArray(row.evidenceKinds) ? row.evidenceKinds.filter(isFinishContractEvidenceKind) : [];
|
|
13230
|
-
const evidence = evidenceKinds.map((kind) => ({
|
|
13231
|
-
kind,
|
|
13232
|
-
summary: "recorded by the finish contract",
|
|
13233
|
-
...turnId === null ? {} : { turnId }
|
|
13234
|
-
}));
|
|
13235
|
-
if (decision === "ok" && reason === "no_mutation") {
|
|
13236
|
-
return { kind: "ok", reason, evidence: [], mutatedPaths };
|
|
13237
|
-
}
|
|
13238
|
-
if (decision === "ok" && reason === "validation_evidence") {
|
|
13239
|
-
return { kind: "ok", reason, evidence, mutatedPaths };
|
|
13240
|
-
}
|
|
13241
|
-
if (decision === "ok" && reason === "explicit_limitation") {
|
|
13242
|
-
return { kind: "ok", reason, evidence: [], mutatedPaths };
|
|
13243
|
-
}
|
|
13244
|
-
if (decision === "engage" && reason === "unvalidated_mutation") {
|
|
13245
|
-
return { kind: "engage", reason, message: "finish contract engaged", evidence: [], mutatedPaths };
|
|
13246
|
-
}
|
|
13247
|
-
return null;
|
|
13248
|
-
}
|
|
13249
|
-
function isFinishContractEvidenceKind(value) {
|
|
13250
|
-
return value === "validation_command" || value === "protected_artifact" || value === "dispatch_receipt";
|
|
13251
|
-
}
|
|
13252
|
-
function readOptionalString(value) {
|
|
13253
|
-
return typeof value === "string" && value.trim().length > 0 ? value : null;
|
|
13254
|
-
}
|
|
13255
13324
|
|
|
13256
13325
|
// src/domains/evidence/store.ts
|
|
13257
13326
|
init_esm_shims();
|
|
13258
13327
|
import { readdir, readFile } from "node:fs/promises";
|
|
13259
|
-
import { join as
|
|
13328
|
+
import { join as join15 } from "node:path";
|
|
13260
13329
|
var EVIDENCE_FILES = [
|
|
13261
13330
|
"overview.json",
|
|
13262
13331
|
"transcript.md",
|
|
@@ -13272,11 +13341,11 @@ var EVIDENCE_FILES = [
|
|
|
13272
13341
|
"findings.md"
|
|
13273
13342
|
];
|
|
13274
13343
|
function evidenceRoot(dataDir) {
|
|
13275
|
-
return
|
|
13344
|
+
return join15(dataDir, "evidence");
|
|
13276
13345
|
}
|
|
13277
13346
|
function evidenceDirectory(dataDir, evidenceId) {
|
|
13278
13347
|
assertSafeId(evidenceId, "evidence");
|
|
13279
|
-
return
|
|
13348
|
+
return join15(evidenceRoot(dataDir), evidenceId);
|
|
13280
13349
|
}
|
|
13281
13350
|
var EvidenceNotFoundError = class extends Error {
|
|
13282
13351
|
constructor(evidenceId) {
|
|
@@ -13292,7 +13361,7 @@ function isMissingFile(error) {
|
|
|
13292
13361
|
async function loadEvidenceOverview(dataDir, evidenceId) {
|
|
13293
13362
|
let raw;
|
|
13294
13363
|
try {
|
|
13295
|
-
raw = await readFile(
|
|
13364
|
+
raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "overview.json"), "utf8");
|
|
13296
13365
|
} catch (error) {
|
|
13297
13366
|
if (isMissingFile(error)) throw new EvidenceNotFoundError(evidenceId);
|
|
13298
13367
|
throw error;
|
|
@@ -13304,7 +13373,7 @@ async function inspectEvidence(dataDir, evidenceId) {
|
|
|
13304
13373
|
const overview = await loadEvidenceOverview(dataDir, evidenceId);
|
|
13305
13374
|
let findingsRaw;
|
|
13306
13375
|
try {
|
|
13307
|
-
findingsRaw = await readFile(
|
|
13376
|
+
findingsRaw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "findings.json"), "utf8");
|
|
13308
13377
|
} catch (error) {
|
|
13309
13378
|
if (isMissingFile(error)) throw new Error(`evidence artifact ${evidenceId} is missing findings.json`);
|
|
13310
13379
|
throw error;
|
|
@@ -13316,7 +13385,7 @@ async function inspectEvidence(dataDir, evidenceId) {
|
|
|
13316
13385
|
async function loadEvidenceTrustStatus(dataDir, evidenceId) {
|
|
13317
13386
|
let raw;
|
|
13318
13387
|
try {
|
|
13319
|
-
raw = await readFile(
|
|
13388
|
+
raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "trust-status.json"), "utf8");
|
|
13320
13389
|
} catch (error) {
|
|
13321
13390
|
if (isMissingFile(error)) {
|
|
13322
13391
|
return { version: 1, evidenceId, projection: "historical_format", runs: [] };
|
|
@@ -13349,7 +13418,7 @@ async function loadEvidenceTrustStatus(dataDir, evidenceId) {
|
|
|
13349
13418
|
async function loadEvidenceRunProvenance(dataDir, evidenceId) {
|
|
13350
13419
|
let raw;
|
|
13351
13420
|
try {
|
|
13352
|
-
raw = await readFile(
|
|
13421
|
+
raw = await readFile(join15(evidenceDirectory(dataDir, evidenceId), "receipt.json"), "utf8");
|
|
13353
13422
|
} catch (error) {
|
|
13354
13423
|
const err = error;
|
|
13355
13424
|
if (err.code === "ENOENT") return [];
|
|
@@ -13403,6 +13472,7 @@ function parseOverview(value, source) {
|
|
|
13403
13472
|
const totals = readTotals(value.totals, `${source}.totals`);
|
|
13404
13473
|
const tags = readStringArray(value, source, "tags");
|
|
13405
13474
|
const files = readStringArray(value, source, "files");
|
|
13475
|
+
const redactionCount = typeof value.redactionCount === "number" && Number.isFinite(value.redactionCount) ? value.redactionCount : void 0;
|
|
13406
13476
|
return {
|
|
13407
13477
|
version: 1,
|
|
13408
13478
|
evidenceId,
|
|
@@ -13421,7 +13491,8 @@ function parseOverview(value, source) {
|
|
|
13421
13491
|
modelIds,
|
|
13422
13492
|
totals,
|
|
13423
13493
|
tags,
|
|
13424
|
-
files
|
|
13494
|
+
files,
|
|
13495
|
+
...redactionCount === void 0 ? {} : { redactionCount }
|
|
13425
13496
|
};
|
|
13426
13497
|
}
|
|
13427
13498
|
function parseFindingsFile(value, source) {
|
|
@@ -13564,7 +13635,6 @@ async function buildEvidence(options) {
|
|
|
13564
13635
|
evidenceId,
|
|
13565
13636
|
runSources,
|
|
13566
13637
|
gateDecisions: gateDecisions.decisions,
|
|
13567
|
-
auditRows: auditLinks.rows,
|
|
13568
13638
|
validationEvidence
|
|
13569
13639
|
});
|
|
13570
13640
|
const findings = buildFindings(runSources, trustStatusRaw, sessionLinks, auditLinks, protectedArtifactsRaw);
|
|
@@ -13887,15 +13957,15 @@ function validationToolCallSummary(toolName, args) {
|
|
|
13887
13957
|
const parsed = parseMaybeJson(args);
|
|
13888
13958
|
const argRecord = isRecord11(parsed) ? parsed : null;
|
|
13889
13959
|
if (toolName === "bash") {
|
|
13890
|
-
const command =
|
|
13960
|
+
const command = readOptionalString(argRecord?.command);
|
|
13891
13961
|
if (command === null) return null;
|
|
13892
13962
|
const detected = detectValidationCommand(command);
|
|
13893
13963
|
return detected.kind === "validation" ? detected.matched : null;
|
|
13894
13964
|
}
|
|
13895
13965
|
if (toolName === "verify") {
|
|
13896
|
-
const check =
|
|
13966
|
+
const check = readOptionalString(argRecord?.check);
|
|
13897
13967
|
if (check === "frontend") {
|
|
13898
|
-
const target =
|
|
13968
|
+
const target = readOptionalString(argRecord?.path) ?? "artifact";
|
|
13899
13969
|
return `verify frontend ${target}`;
|
|
13900
13970
|
}
|
|
13901
13971
|
if (check === null) return null;
|
|
@@ -13922,22 +13992,22 @@ function finding(index, severity, tag, runId, message) {
|
|
|
13922
13992
|
}
|
|
13923
13993
|
async function writeEvidenceFiles(directory, overview, runSources, findings, sessionLinks, auditLinks, toolEventRows, gateDecisions, trustStatus, protectedArtifacts, transcript) {
|
|
13924
13994
|
await mkdir(directory, { recursive: true });
|
|
13925
|
-
await writeJson(
|
|
13995
|
+
await writeJson(join16(directory, "overview.json"), overview);
|
|
13926
13996
|
await writeFile(
|
|
13927
|
-
|
|
13997
|
+
join16(directory, "transcript.md"),
|
|
13928
13998
|
transcript ?? renderTranscript(overview, runSources, sessionLinks, trustStatus),
|
|
13929
13999
|
"utf8"
|
|
13930
14000
|
);
|
|
13931
|
-
await writeJsonl(
|
|
13932
|
-
await writeJsonl(
|
|
13933
|
-
await writeJsonl(
|
|
13934
|
-
await writeJsonl(
|
|
13935
|
-
await writeJson(
|
|
13936
|
-
await writeJson(
|
|
13937
|
-
await writeJson(
|
|
13938
|
-
await writeJson(
|
|
13939
|
-
await writeJson(
|
|
13940
|
-
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");
|
|
13941
14011
|
}
|
|
13942
14012
|
function rawTraceRows(runSources) {
|
|
13943
14013
|
const rows = [];
|
|
@@ -14082,12 +14152,12 @@ function attributionWindows(ledger, runSources, sessionIds) {
|
|
|
14082
14152
|
const linkedSessions = new Set(sessionIds);
|
|
14083
14153
|
for (const row of ledger.rows) {
|
|
14084
14154
|
if (!isRecord11(row)) continue;
|
|
14085
|
-
const id =
|
|
14086
|
-
const startedAt =
|
|
14087
|
-
const sessionId =
|
|
14155
|
+
const id = readOptionalString(row.id);
|
|
14156
|
+
const startedAt = readOptionalString(row.startedAt);
|
|
14157
|
+
const sessionId = readOptionalString(row.sessionId);
|
|
14088
14158
|
if (id === null || startedAt === null || sessionId === null) continue;
|
|
14089
14159
|
if (windows.has(id) || !linkedSessions.has(sessionId)) continue;
|
|
14090
|
-
windows.set(id, { runId: id, startedAt, endedAt:
|
|
14160
|
+
windows.set(id, { runId: id, startedAt, endedAt: readOptionalString(row.endedAt) });
|
|
14091
14161
|
}
|
|
14092
14162
|
return [...windows.values()].sort((left, right) => compareCodepoints(left.runId, right.runId));
|
|
14093
14163
|
}
|
|
@@ -14202,16 +14272,16 @@ function extractSessionToolCall(entry, linked) {
|
|
|
14202
14272
|
const payload = payloadObject(entry.payload);
|
|
14203
14273
|
const block = firstContentBlock(entry.payload, "toolCall");
|
|
14204
14274
|
const fn = payloadObject(payload?.function);
|
|
14205
|
-
const id =
|
|
14206
|
-
const tool =
|
|
14275
|
+
const id = readOptionalString(payload?.id) ?? readOptionalString(payload?.toolCallId) ?? readOptionalString(payload?.tool_call_id) ?? readOptionalString(block?.id) ?? entry.turnId;
|
|
14276
|
+
const tool = readOptionalString(payload?.name) ?? readOptionalString(payload?.toolName) ?? readOptionalString(payload?.tool) ?? readOptionalString(fn?.name) ?? readOptionalString(block?.name) ?? "tool";
|
|
14207
14277
|
const args = payload?.arguments ?? payload?.args ?? payload?.input ?? parseMaybeJson(fn?.arguments) ?? block?.arguments ?? block?.args ?? void 0;
|
|
14208
14278
|
return { id, tool, args, timestamp: entry.timestamp, link: linked.link, sessionId: linked.sessionId };
|
|
14209
14279
|
}
|
|
14210
14280
|
function extractSessionToolResult(entry, linked) {
|
|
14211
14281
|
const payload = payloadObject(entry.payload);
|
|
14212
14282
|
const contentText = extractTextFromPayload(entry.payload);
|
|
14213
|
-
const id =
|
|
14214
|
-
const tool =
|
|
14283
|
+
const id = readOptionalString(payload?.toolCallId) ?? readOptionalString(payload?.tool_call_id) ?? readOptionalString(payload?.id) ?? null;
|
|
14284
|
+
const tool = readOptionalString(payload?.toolName) ?? readOptionalString(payload?.name) ?? readOptionalString(payload?.tool) ?? "tool";
|
|
14215
14285
|
const result = payload?.result ?? payload?.output ?? payload?.out ?? payload?.content ?? (contentText.length > 0 ? contentText : entry.payload);
|
|
14216
14286
|
return {
|
|
14217
14287
|
id,
|
|
@@ -14238,12 +14308,12 @@ async function linkAuditRows(stateDir, source, runSources, sessionLinks) {
|
|
|
14238
14308
|
runSources.map((item) => [item.envelope.id, item.envelope.sessionId ?? item.receipt?.sessionId ?? null])
|
|
14239
14309
|
);
|
|
14240
14310
|
for (const audit of auditRows.rows) {
|
|
14241
|
-
const directRunId =
|
|
14311
|
+
const directRunId = readOptionalString(audit.row.runId);
|
|
14242
14312
|
if (directRunId !== null && runIds.has(directRunId)) {
|
|
14243
14313
|
rows.push(
|
|
14244
14314
|
auditLinkedRow(audit, {
|
|
14245
14315
|
runId: directRunId,
|
|
14246
|
-
sessionId:
|
|
14316
|
+
sessionId: readOptionalString(audit.row.sessionId) ?? runSessionIds.get(directRunId) ?? null,
|
|
14247
14317
|
linkKind: "run-id",
|
|
14248
14318
|
confidence: "exact",
|
|
14249
14319
|
reasons: ["audit runId matched run ledger"]
|
|
@@ -14251,7 +14321,7 @@ async function linkAuditRows(stateDir, source, runSources, sessionLinks) {
|
|
|
14251
14321
|
);
|
|
14252
14322
|
continue;
|
|
14253
14323
|
}
|
|
14254
|
-
const directSessionId =
|
|
14324
|
+
const directSessionId = readOptionalString(audit.row.sessionId);
|
|
14255
14325
|
if (directSessionId !== null && sessionIds.has(directSessionId)) {
|
|
14256
14326
|
rows.push(
|
|
14257
14327
|
auditLinkedRow(audit, {
|
|
@@ -14286,7 +14356,7 @@ function auditLinkedRow(audit, fields) {
|
|
|
14286
14356
|
}
|
|
14287
14357
|
function bestEffortAuditLink(audit, source, runSources, sessionIds) {
|
|
14288
14358
|
if (audit.auditKind !== "tool_call") return null;
|
|
14289
|
-
const tool =
|
|
14359
|
+
const tool = readOptionalString(audit.row.tool);
|
|
14290
14360
|
if (tool === null || audit.ts === null) return null;
|
|
14291
14361
|
const candidates = runSources.filter((item) => {
|
|
14292
14362
|
if (!timestampInRunWindow(audit.ts ?? "", item.envelope)) return false;
|
|
@@ -14350,9 +14420,9 @@ function auditToolEvents(rows) {
|
|
|
14350
14420
|
const events = [];
|
|
14351
14421
|
for (const row of rows) {
|
|
14352
14422
|
if (row.auditKind !== "tool_call") continue;
|
|
14353
|
-
const tool =
|
|
14423
|
+
const tool = readOptionalString(row.row.tool);
|
|
14354
14424
|
if (tool === null) continue;
|
|
14355
|
-
const decision =
|
|
14425
|
+
const decision = readOptionalString(row.row.decision);
|
|
14356
14426
|
if (decision === "classified") continue;
|
|
14357
14427
|
const event = {
|
|
14358
14428
|
source: "audit-row",
|
|
@@ -14369,7 +14439,7 @@ function auditToolEvents(rows) {
|
|
|
14369
14439
|
};
|
|
14370
14440
|
if (row.ts !== null) event.timestamp = row.ts;
|
|
14371
14441
|
if (decision !== null) event.decision = decision;
|
|
14372
|
-
const actionClass =
|
|
14442
|
+
const actionClass = readOptionalString(row.row.actionClass);
|
|
14373
14443
|
if (actionClass !== null) event.actionClass = actionClass;
|
|
14374
14444
|
events.push(event);
|
|
14375
14445
|
}
|
|
@@ -14380,8 +14450,8 @@ function compareAuditLinkedRows(a, b) {
|
|
|
14380
14450
|
if (byTs !== 0) return byTs;
|
|
14381
14451
|
const byKind = compareCodepoints(a.auditKind, b.auditKind);
|
|
14382
14452
|
if (byKind !== 0) return byKind;
|
|
14383
|
-
const aCorrelation =
|
|
14384
|
-
const bCorrelation =
|
|
14453
|
+
const aCorrelation = readOptionalString(a.row.correlationId) ?? "";
|
|
14454
|
+
const bCorrelation = readOptionalString(b.row.correlationId) ?? "";
|
|
14385
14455
|
if (aCorrelation !== bCorrelation) return compareCodepoints(aCorrelation, bCorrelation);
|
|
14386
14456
|
return compareCodepoints(JSON.stringify(a.row), JSON.stringify(b.row));
|
|
14387
14457
|
}
|
|
@@ -14614,19 +14684,8 @@ function axisFindings(offset, source, status) {
|
|
|
14614
14684
|
}
|
|
14615
14685
|
return out;
|
|
14616
14686
|
}
|
|
14617
|
-
function renderFindings(findings) {
|
|
14618
|
-
if (findings.length === 0) return "# Findings\n\nNo findings.\n";
|
|
14619
|
-
const lines = ["# Findings", ""];
|
|
14620
|
-
for (const item of findings) {
|
|
14621
|
-
const run = item.runId === null ? "" : ` run=${item.runId}`;
|
|
14622
|
-
lines.push(`- ${item.id} [${item.severity}] ${item.tag}${run}: ${item.message}`);
|
|
14623
|
-
}
|
|
14624
|
-
lines.push("");
|
|
14625
|
-
return `${lines.join("\n")}
|
|
14626
|
-
`;
|
|
14627
|
-
}
|
|
14628
14687
|
async function readRunLedger(stateDir) {
|
|
14629
|
-
const target =
|
|
14688
|
+
const target = join16(stateDir, "runs.json");
|
|
14630
14689
|
let raw;
|
|
14631
14690
|
try {
|
|
14632
14691
|
raw = await readFile2(target, "utf8");
|
|
@@ -14647,7 +14706,7 @@ function selectRunEnvelopes(ledger, source) {
|
|
|
14647
14706
|
});
|
|
14648
14707
|
}
|
|
14649
14708
|
async function readReceipt(stateDir, envelope) {
|
|
14650
|
-
const receiptPath = envelope.receiptPath ??
|
|
14709
|
+
const receiptPath = envelope.receiptPath ?? join16(stateDir, "receipts", `${envelope.id}.json`);
|
|
14651
14710
|
let raw;
|
|
14652
14711
|
try {
|
|
14653
14712
|
raw = await readFile2(receiptPath, "utf8");
|
|
@@ -14713,7 +14772,7 @@ function parseRunReceipt(value, source) {
|
|
|
14713
14772
|
const integrity = value.integrity;
|
|
14714
14773
|
if (!isRecord11(integrity)) throw new Error(`${source}.integrity: expected object`);
|
|
14715
14774
|
const reasoningTokenCount = readOptionalNumber2(value, source, "reasoningTokenCount");
|
|
14716
|
-
const failureMessage =
|
|
14775
|
+
const failureMessage = readOptionalString(value.failureMessage);
|
|
14717
14776
|
return {
|
|
14718
14777
|
...value,
|
|
14719
14778
|
runId: readString2(value, source, "runId"),
|
|
@@ -14805,7 +14864,7 @@ function readNullableNumber(record, source, field) {
|
|
|
14805
14864
|
throw new Error(`${source}.${field}: expected number or null`);
|
|
14806
14865
|
return value;
|
|
14807
14866
|
}
|
|
14808
|
-
function
|
|
14867
|
+
function readOptionalString(value) {
|
|
14809
14868
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
14810
14869
|
}
|
|
14811
14870
|
function parseJson2(raw, source) {
|
|
@@ -14936,7 +14995,7 @@ function sanitizeEvidenceId(value) {
|
|
|
14936
14995
|
// src/domains/evidence/eval.ts
|
|
14937
14996
|
init_esm_shims();
|
|
14938
14997
|
import { mkdir as mkdir2, readdir as readdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
14939
|
-
import { join as
|
|
14998
|
+
import { join as join17 } from "node:path";
|
|
14940
14999
|
|
|
14941
15000
|
// src/domains/eval/index.ts
|
|
14942
15001
|
init_esm_shims();
|
|
@@ -14947,9 +15006,6 @@ init_esm_shims();
|
|
|
14947
15006
|
// src/domains/eval/report.ts
|
|
14948
15007
|
init_esm_shims();
|
|
14949
15008
|
|
|
14950
|
-
// src/domains/eval/run-compare.ts
|
|
14951
|
-
init_esm_shims();
|
|
14952
|
-
|
|
14953
15009
|
// src/domains/eval/runner.ts
|
|
14954
15010
|
init_esm_shims();
|
|
14955
15011
|
function summarizeEvalResults(records) {
|
|
@@ -15018,8 +15074,7 @@ async function buildEvalEvidence(options) {
|
|
|
15018
15074
|
const trustStatus = buildEvidenceTrustStatusFile({
|
|
15019
15075
|
evidenceId,
|
|
15020
15076
|
runSources: linkedRuns.runSources,
|
|
15021
|
-
gateDecisions: gateDecisions.decisions
|
|
15022
|
-
auditRows: linkedRuns.auditRows
|
|
15077
|
+
gateDecisions: gateDecisions.decisions
|
|
15023
15078
|
});
|
|
15024
15079
|
await writeEvalEvidenceFiles(
|
|
15025
15080
|
directory,
|
|
@@ -15141,19 +15196,19 @@ async function writeEvalEvidenceFiles(directory, artifact, overview, findings, t
|
|
|
15141
15196
|
};
|
|
15142
15197
|
const redactedArtifact = redactArtifactForStorage(artifact);
|
|
15143
15198
|
await mkdir2(directory, { recursive: true });
|
|
15144
|
-
await writeJson2(
|
|
15145
|
-
await writeFile2(
|
|
15146
|
-
await writeJsonl2(
|
|
15147
|
-
await writeJsonl2(
|
|
15148
|
-
await writeJsonl2(
|
|
15149
|
-
await writeJsonl2(
|
|
15150
|
-
await writeJson2(
|
|
15151
|
-
await writeJson2(
|
|
15152
|
-
await writeJson2(
|
|
15153
|
-
await writeJson2(
|
|
15154
|
-
await writeJson2(
|
|
15155
|
-
await writeJson2(
|
|
15156
|
-
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");
|
|
15157
15212
|
}
|
|
15158
15213
|
function rawEvalTraceRows(artifact) {
|
|
15159
15214
|
return artifact.results.map((result) => ({
|
|
@@ -15243,16 +15298,6 @@ function renderEvalTranscript(artifact, overview) {
|
|
|
15243
15298
|
return `${lines.join("\n")}
|
|
15244
15299
|
`;
|
|
15245
15300
|
}
|
|
15246
|
-
function renderFindings2(findings) {
|
|
15247
|
-
if (findings.length === 0) return "No findings.\n";
|
|
15248
|
-
const lines = ["# Findings", ""];
|
|
15249
|
-
for (const finding2 of findings) {
|
|
15250
|
-
lines.push(`- ${finding2.id} [${finding2.severity}] ${finding2.tag}: ${finding2.message}`);
|
|
15251
|
-
}
|
|
15252
|
-
lines.push("");
|
|
15253
|
-
return `${lines.join("\n")}
|
|
15254
|
-
`;
|
|
15255
|
-
}
|
|
15256
15301
|
async function writeJson2(path2, value) {
|
|
15257
15302
|
await writeFile2(path2, `${JSON.stringify(value, null, 2)}
|
|
15258
15303
|
`, "utf8");
|
|
@@ -15304,7 +15349,7 @@ async function linkEvalRuns(stateDir, artifact) {
|
|
|
15304
15349
|
}
|
|
15305
15350
|
async function readRunLedger2(stateDir) {
|
|
15306
15351
|
try {
|
|
15307
|
-
const raw = await readFile3(
|
|
15352
|
+
const raw = await readFile3(join17(stateDir, "runs.json"), "utf8");
|
|
15308
15353
|
const parsed = JSON.parse(raw);
|
|
15309
15354
|
return Array.isArray(parsed) ? parsed.filter(isRecord12) : [];
|
|
15310
15355
|
} catch {
|
|
@@ -15315,7 +15360,7 @@ function evalRunMatches(artifact, envelope) {
|
|
|
15315
15360
|
return artifact.results.some((result) => result.runId === envelope.id);
|
|
15316
15361
|
}
|
|
15317
15362
|
async function readReceiptForRun(stateDir, envelope) {
|
|
15318
|
-
const path2 = envelope.receiptPath ??
|
|
15363
|
+
const path2 = envelope.receiptPath ?? join17(stateDir, "receipts", `${envelope.id}.json`);
|
|
15319
15364
|
try {
|
|
15320
15365
|
const parsed = JSON.parse(await readFile3(path2, "utf8"));
|
|
15321
15366
|
return isRecord12(parsed) ? parsed : null;
|
|
@@ -15344,7 +15389,7 @@ async function countSessionEntries(stateDir, sessionIds) {
|
|
|
15344
15389
|
return count;
|
|
15345
15390
|
}
|
|
15346
15391
|
async function findSessionLedgerPath(stateDir, sessionId) {
|
|
15347
|
-
const root =
|
|
15392
|
+
const root = join17(stateDir, "sessions");
|
|
15348
15393
|
let cwdHashes;
|
|
15349
15394
|
try {
|
|
15350
15395
|
cwdHashes = await readdir2(root);
|
|
@@ -15352,7 +15397,7 @@ async function findSessionLedgerPath(stateDir, sessionId) {
|
|
|
15352
15397
|
return null;
|
|
15353
15398
|
}
|
|
15354
15399
|
for (const cwdHash of cwdHashes) {
|
|
15355
|
-
const path2 =
|
|
15400
|
+
const path2 = join17(root, cwdHash, sessionId, "current.jsonl");
|
|
15356
15401
|
try {
|
|
15357
15402
|
await readFile3(path2, "utf8");
|
|
15358
15403
|
return path2;
|
|
@@ -15362,7 +15407,7 @@ async function findSessionLedgerPath(stateDir, sessionId) {
|
|
|
15362
15407
|
return null;
|
|
15363
15408
|
}
|
|
15364
15409
|
async function linkedEvalAuditRows(stateDir, runIds, artifact) {
|
|
15365
|
-
const root =
|
|
15410
|
+
const root = join17(stateDir, "audit");
|
|
15366
15411
|
let files;
|
|
15367
15412
|
try {
|
|
15368
15413
|
files = await readdir2(root);
|
|
@@ -15371,7 +15416,7 @@ async function linkedEvalAuditRows(stateDir, runIds, artifact) {
|
|
|
15371
15416
|
}
|
|
15372
15417
|
const rows = [];
|
|
15373
15418
|
for (const file of files.filter((name) => name.endsWith(".jsonl")).sort(compareCodepoints)) {
|
|
15374
|
-
const raw = await readFile3(
|
|
15419
|
+
const raw = await readFile3(join17(root, file), "utf8").catch(() => "");
|
|
15375
15420
|
const lines = raw.split("\n");
|
|
15376
15421
|
for (let index = 0; index < lines.length; index += 1) {
|
|
15377
15422
|
const line = lines[index];
|
|
@@ -15464,30 +15509,30 @@ init_esm_shims();
|
|
|
15464
15509
|
function lower(value) {
|
|
15465
15510
|
return (value ?? "").toLowerCase();
|
|
15466
15511
|
}
|
|
15467
|
-
function
|
|
15512
|
+
function canonicalJson3(value) {
|
|
15468
15513
|
if (value === null) return "null";
|
|
15469
15514
|
if (typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
|
|
15470
15515
|
if (typeof value === "number") {
|
|
15471
15516
|
if (!Number.isFinite(value)) throw new Error("response schema digest requires finite numbers");
|
|
15472
15517
|
return JSON.stringify(value);
|
|
15473
15518
|
}
|
|
15474
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
15519
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson3).join(",")}]`;
|
|
15475
15520
|
if (typeof value === "object") {
|
|
15476
15521
|
const record = value;
|
|
15477
15522
|
return `{${Object.keys(record).sort().map((key) => {
|
|
15478
15523
|
if (record[key] === void 0) throw new Error("response schema digest cannot contain undefined");
|
|
15479
|
-
return `${JSON.stringify(key)}:${
|
|
15524
|
+
return `${JSON.stringify(key)}:${canonicalJson3(record[key])}`;
|
|
15480
15525
|
}).join(",")}}`;
|
|
15481
15526
|
}
|
|
15482
15527
|
throw new Error(`response schema digest cannot represent ${typeof value}`);
|
|
15483
15528
|
}
|
|
15484
15529
|
function canonicalResponseSchemaDigest(schema) {
|
|
15485
|
-
return
|
|
15530
|
+
return createHash10("sha256").update(canonicalJson3(schema), "utf8").digest("hex");
|
|
15486
15531
|
}
|
|
15487
15532
|
function typedValidationFactsFromToolStats(toolStats) {
|
|
15488
15533
|
return toolStats.filter((stat) => stat.tool === "verify" && stat.count > 0).map((stat) => ({
|
|
15489
15534
|
sourceId: "tool:verify",
|
|
15490
|
-
validatorDigest:
|
|
15535
|
+
validatorDigest: createHash10("sha256").update(canonicalJson3(stat), "utf8").digest("hex"),
|
|
15491
15536
|
passed: stat.ok === stat.count && stat.errors === 0 && stat.blocked === 0
|
|
15492
15537
|
}));
|
|
15493
15538
|
}
|
|
@@ -15610,38 +15655,36 @@ export {
|
|
|
15610
15655
|
createStdioServerTransport,
|
|
15611
15656
|
ACP_USAGE_META_KEY,
|
|
15612
15657
|
ACP_SESSION_META_KEY,
|
|
15658
|
+
ACP_AGENT_META_KEY,
|
|
15613
15659
|
ACP_MAX_STRING_BYTES,
|
|
15614
15660
|
ACP_MAX_RAW_RECORD_BYTES,
|
|
15615
15661
|
ACP_MAX_CHUNK_BYTES,
|
|
15616
15662
|
ACP_MAX_TOOL_CALL_ID_BYTES,
|
|
15617
|
-
sha256,
|
|
15618
|
-
canonicalJson2 as canonicalJson,
|
|
15619
15663
|
compile,
|
|
15620
15664
|
compileWorker,
|
|
15621
|
-
WORKER_OUTPUT_MAX_BYTES,
|
|
15622
|
-
durableAssistantTextFromEvent,
|
|
15623
15665
|
setCapacityDraining,
|
|
15624
15666
|
capacityDrain,
|
|
15667
|
+
capacityLeaseUsage,
|
|
15625
15668
|
openAgentLedger,
|
|
15626
15669
|
renderAgentLedgerBoard,
|
|
15627
15670
|
closeAgentLedger,
|
|
15628
15671
|
renderDispatchReviewerTask,
|
|
15629
15672
|
createRunReceiptQuality,
|
|
15630
15673
|
UNVERIFIABLE_RECEIPT_VERIFICATION,
|
|
15631
|
-
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
stagePendingGateDecision,
|
|
15635
|
-
resolvePendingGateDecision,
|
|
15636
|
-
materializePendingGateDecision,
|
|
15637
|
-
finalizePendingGateDecision,
|
|
15638
|
-
readPendingGateDecisions,
|
|
15639
|
-
preflightPendingGateDecisionMaterialization,
|
|
15640
|
-
preparePendingGateDecisionRecovery,
|
|
15641
|
-
readGateDecisionArtifacts,
|
|
15674
|
+
assistantTextFromEvent,
|
|
15675
|
+
receiptResponseModelIdObservationLabel,
|
|
15676
|
+
createDispatchRunEventRegistry,
|
|
15642
15677
|
readFleetRun,
|
|
15678
|
+
listFleetRuns,
|
|
15643
15679
|
openLedger,
|
|
15644
15680
|
executePlan,
|
|
15681
|
+
aggregateCostAmounts,
|
|
15682
|
+
formatCostAggregate,
|
|
15683
|
+
COST_NOT_MEASURED,
|
|
15684
|
+
costAggregateForAmount,
|
|
15685
|
+
renderCostAggregate,
|
|
15686
|
+
renderCostAmount,
|
|
15687
|
+
createCostTracker,
|
|
15645
15688
|
planFleetResume,
|
|
15646
15689
|
executeFleetRun,
|
|
15647
15690
|
DispatchDomainModule,
|
|
@@ -15649,14 +15692,16 @@ export {
|
|
|
15649
15692
|
extractRunProvenance,
|
|
15650
15693
|
provenanceTranscriptLines,
|
|
15651
15694
|
provenanceCompactSuffix,
|
|
15695
|
+
EVIDENCE_TAGS,
|
|
15652
15696
|
FAILURE_CAUSE_TAGS,
|
|
15653
15697
|
evidenceDirectory,
|
|
15654
15698
|
EvidenceNotFoundError,
|
|
15655
15699
|
inspectEvidence,
|
|
15700
|
+
loadEvidenceTrustStatus,
|
|
15656
15701
|
loadEvidenceRunProvenance,
|
|
15657
15702
|
listEvidenceOverviews,
|
|
15658
15703
|
buildEvidence,
|
|
15659
15704
|
summarizeEvalResults,
|
|
15660
15705
|
buildEvalEvidence
|
|
15661
15706
|
};
|
|
15662
|
-
//# sourceMappingURL=chunk-
|
|
15707
|
+
//# sourceMappingURL=chunk-BUMFYQFY.js.map
|