@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
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
parseJsonObjectPayload,
|
|
4
|
+
parseVerifierResult
|
|
5
|
+
} from "./chunk-DYJP44XW.js";
|
|
6
|
+
import {
|
|
7
|
+
atomicWrite
|
|
8
|
+
} from "./chunk-76ONBSIA.js";
|
|
9
|
+
import {
|
|
10
|
+
clioStateDir
|
|
11
|
+
} from "./chunk-BYP5D4HI.js";
|
|
12
|
+
import {
|
|
13
|
+
init_esm_shims
|
|
14
|
+
} from "./chunk-3R73A4XB.js";
|
|
15
|
+
|
|
16
|
+
// src/domains/dispatch/gate-decisions.ts
|
|
17
|
+
init_esm_shims();
|
|
18
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
19
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
|
20
|
+
import { dirname, join, resolve } from "node:path";
|
|
21
|
+
function parseReviewGateResult(output) {
|
|
22
|
+
const result = parseVerifierResult(output);
|
|
23
|
+
return result === null ? { ok: false, reason: "reviewer did not return a valid verifier report" } : { ok: true, result };
|
|
24
|
+
}
|
|
25
|
+
function decideReviewGate(input) {
|
|
26
|
+
const base = {
|
|
27
|
+
group: input.group,
|
|
28
|
+
topology: "review",
|
|
29
|
+
cycle: input.cycle,
|
|
30
|
+
subjects: input.subjects,
|
|
31
|
+
decider: input.decider,
|
|
32
|
+
correlation: input.correlation
|
|
33
|
+
};
|
|
34
|
+
const parsed = parseReviewGateResult(input.output);
|
|
35
|
+
if (!parsed.ok) {
|
|
36
|
+
return {
|
|
37
|
+
draft: { ...base, outcome: "exhausted", detail: parsed.reason },
|
|
38
|
+
verdict: null,
|
|
39
|
+
findings: null,
|
|
40
|
+
needsDecision: `review gate produced no structured verdict in cycle ${input.cycle}: ${parsed.reason}`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (parsed.result.verdict === "pass" || input.terminalCycle) {
|
|
44
|
+
return {
|
|
45
|
+
draft: { ...base, outcome: parsed.result.verdict },
|
|
46
|
+
verdict: parsed.result.verdict,
|
|
47
|
+
findings: null,
|
|
48
|
+
needsDecision: null
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const failed = parsed.result.checks.filter((check) => !check.passed);
|
|
52
|
+
return {
|
|
53
|
+
draft: { ...base, outcome: "revise", detail: `reviewer reported ${failed.length} failed check(s)` },
|
|
54
|
+
verdict: null,
|
|
55
|
+
findings: JSON.stringify({ verdict: "fail", checks: failed }),
|
|
56
|
+
needsDecision: null
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function parseGateChecks(value) {
|
|
60
|
+
if (!Array.isArray(value) || value.length === 0) return null;
|
|
61
|
+
const checks = [];
|
|
62
|
+
for (const entry of value) {
|
|
63
|
+
if (!isRecord(entry)) return null;
|
|
64
|
+
const keys = Object.keys(entry);
|
|
65
|
+
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) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
checks.push({ name: entry.name, passed: entry.passed, evidence: entry.evidence });
|
|
69
|
+
}
|
|
70
|
+
return checks;
|
|
71
|
+
}
|
|
72
|
+
function parseCompeteGateResult(output, candidateCount) {
|
|
73
|
+
const parsed = parseJsonObjectPayload(output);
|
|
74
|
+
if (!parsed.ok) {
|
|
75
|
+
return {
|
|
76
|
+
ok: false,
|
|
77
|
+
reason: parsed.reason === "not-object" ? "judge result must be a JSON object" : "judge result must be valid JSON"
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const value = parsed.value;
|
|
81
|
+
if (Object.keys(value).some((key) => key !== "winner" && key !== "checks")) {
|
|
82
|
+
return { ok: false, reason: "judge result has unknown fields" };
|
|
83
|
+
}
|
|
84
|
+
const winner = value.winner;
|
|
85
|
+
if (typeof winner !== "number" || !Number.isSafeInteger(winner) || winner < 1 || winner > candidateCount) {
|
|
86
|
+
return { ok: false, reason: `judge winner must be an integer 1..${candidateCount}` };
|
|
87
|
+
}
|
|
88
|
+
const checks = parseGateChecks(value.checks);
|
|
89
|
+
if (checks === null) return { ok: false, reason: "judge result must carry typed checks with evidence" };
|
|
90
|
+
return { ok: true, result: { winner, checks } };
|
|
91
|
+
}
|
|
92
|
+
function gateDecisionsDirectory(stateDir = clioStateDir()) {
|
|
93
|
+
return join(stateDir, "gate-decisions");
|
|
94
|
+
}
|
|
95
|
+
function decisionsDirectory(stateDir = clioStateDir()) {
|
|
96
|
+
return gateDecisionsDirectory(stateDir);
|
|
97
|
+
}
|
|
98
|
+
function pendingDecisionsDirectory(stateDir = clioStateDir()) {
|
|
99
|
+
return join(decisionsDirectory(stateDir), "pending");
|
|
100
|
+
}
|
|
101
|
+
function isRecord(value) {
|
|
102
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
103
|
+
}
|
|
104
|
+
function isSubjectRef(value) {
|
|
105
|
+
if (!isRecord(value) || typeof value.runId !== "string" || value.runId.trim().length === 0) return false;
|
|
106
|
+
return typeof value.digest === "string" && /^[0-9a-f]{64}$/.test(value.digest);
|
|
107
|
+
}
|
|
108
|
+
function isSafeDecisionId(value) {
|
|
109
|
+
return typeof value === "string" && value.length > 0 && value.length <= 256 && /^[A-Za-z0-9._-]+$/.test(value);
|
|
110
|
+
}
|
|
111
|
+
function isCorrelation(value) {
|
|
112
|
+
if (!isRecord(value)) return false;
|
|
113
|
+
const fields = ["agent", "target", "modelFamily", "runtime", "node", "independent"];
|
|
114
|
+
if (Object.keys(value).some((key) => !fields.includes(key))) return false;
|
|
115
|
+
if (!fields.every((field) => typeof value[field] === "boolean")) return false;
|
|
116
|
+
return value.independent === (!value.agent && !value.modelFamily);
|
|
117
|
+
}
|
|
118
|
+
function semanticError(value) {
|
|
119
|
+
if (!isRecord(value)) return "gate decision is not an object";
|
|
120
|
+
if (value.version !== 2) return "unsupported gate decision version";
|
|
121
|
+
if (!isSafeDecisionId(value.id)) return "gate decision id invalid";
|
|
122
|
+
if (typeof value.group !== "string" || value.group.length === 0) return "gate decision group invalid";
|
|
123
|
+
if (value.topology !== "review" && value.topology !== "compete") return "gate decision topology invalid";
|
|
124
|
+
if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
|
|
125
|
+
return "gate decision cycle invalid";
|
|
126
|
+
}
|
|
127
|
+
const reviewOutcome = value.outcome === "pass" || value.outcome === "fail" || value.outcome === "revise" || value.outcome === "exhausted";
|
|
128
|
+
const competeOutcome = value.outcome === "winner" || value.outcome === "no-winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
129
|
+
if (value.topology === "review" && !reviewOutcome || value.topology === "compete" && !competeOutcome) {
|
|
130
|
+
return "gate decision outcome is incompatible with topology";
|
|
131
|
+
}
|
|
132
|
+
if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
|
|
133
|
+
return "gate decision subjects invalid";
|
|
134
|
+
}
|
|
135
|
+
if (value.decider !== void 0 && !isSubjectRef(value.decider)) return "gate decision decider invalid";
|
|
136
|
+
if (value.decider === void 0) {
|
|
137
|
+
if (value.correlation !== void 0) return "gate decision correlation requires a decider";
|
|
138
|
+
} else if (!isCorrelation(value.correlation)) {
|
|
139
|
+
return "gate decision correlation invalid";
|
|
140
|
+
}
|
|
141
|
+
if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
|
|
142
|
+
return "gate decision timestamp invalid";
|
|
143
|
+
}
|
|
144
|
+
const needsWinner = value.outcome === "winner" || value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
145
|
+
if (needsWinner) {
|
|
146
|
+
if (!isRecord(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}`) {
|
|
147
|
+
return "gate decision winner invalid";
|
|
148
|
+
}
|
|
149
|
+
const winnerSubject = value.winner.subject;
|
|
150
|
+
if (!value.subjects.some((subject) => subject.runId === winnerSubject.runId)) {
|
|
151
|
+
return "gate decision winner is not a subject";
|
|
152
|
+
}
|
|
153
|
+
} else if (value.winner !== void 0) {
|
|
154
|
+
return "gate decision winner is not valid for this outcome";
|
|
155
|
+
}
|
|
156
|
+
const needsConfirmation = value.outcome === "operator-confirmed" || value.outcome === "full-auto-applied";
|
|
157
|
+
if (needsConfirmation) {
|
|
158
|
+
if (!isRecord(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)) {
|
|
159
|
+
return "gate decision confirmation invalid";
|
|
160
|
+
}
|
|
161
|
+
} else if (value.confirmation !== void 0) {
|
|
162
|
+
return "gate decision confirmation is not valid for this outcome";
|
|
163
|
+
}
|
|
164
|
+
if (value.detail !== void 0 && typeof value.detail !== "string") return "gate decision detail invalid";
|
|
165
|
+
if (!isRecord(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string") {
|
|
166
|
+
return "gate decision integrity invalid";
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
function safeGroup(group) {
|
|
171
|
+
const safe = group.replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 128);
|
|
172
|
+
return safe.length > 0 ? safe : "gate";
|
|
173
|
+
}
|
|
174
|
+
function newDecisionId(group) {
|
|
175
|
+
return `${safeGroup(group)}-${Date.now().toString(36)}-${randomBytes(6).toString("hex")}`;
|
|
176
|
+
}
|
|
177
|
+
function decisionArtifactPath(id, stateDir = clioStateDir()) {
|
|
178
|
+
return join(decisionsDirectory(stateDir), `${id}.json`);
|
|
179
|
+
}
|
|
180
|
+
function pendingDecisionPath(id, stateDir = clioStateDir()) {
|
|
181
|
+
return join(pendingDecisionsDirectory(stateDir), `${id}.json`);
|
|
182
|
+
}
|
|
183
|
+
function decisionPayload(decision) {
|
|
184
|
+
return {
|
|
185
|
+
contract: "clio.gateDecision.integrity",
|
|
186
|
+
version: decision.version,
|
|
187
|
+
id: decision.id,
|
|
188
|
+
group: decision.group,
|
|
189
|
+
topology: decision.topology,
|
|
190
|
+
cycle: decision.cycle,
|
|
191
|
+
outcome: decision.outcome,
|
|
192
|
+
subjects: decision.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
|
|
193
|
+
...decision.decider !== void 0 ? { decider: { runId: decision.decider.runId, digest: decision.decider.digest } } : {},
|
|
194
|
+
...decision.correlation !== void 0 ? { correlation: { ...decision.correlation } } : {},
|
|
195
|
+
...decision.winner !== void 0 ? {
|
|
196
|
+
winner: {
|
|
197
|
+
index: decision.winner.index,
|
|
198
|
+
subject: {
|
|
199
|
+
runId: decision.winner.subject.runId,
|
|
200
|
+
digest: decision.winner.subject.digest
|
|
201
|
+
},
|
|
202
|
+
branch: decision.winner.branch
|
|
203
|
+
}
|
|
204
|
+
} : {},
|
|
205
|
+
...decision.confirmation !== void 0 ? { confirmation: { id: decision.confirmation.id, digest: decision.confirmation.digest } } : {},
|
|
206
|
+
...decision.detail !== void 0 ? { detail: decision.detail } : {},
|
|
207
|
+
createdAt: decision.createdAt
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function decisionDigest(decision) {
|
|
211
|
+
return createHash("sha256").update(JSON.stringify(decisionPayload(decision)), "utf8").digest("hex");
|
|
212
|
+
}
|
|
213
|
+
function artifactWithoutIntegrity(artifact) {
|
|
214
|
+
const result = {
|
|
215
|
+
version: artifact.version,
|
|
216
|
+
id: artifact.id,
|
|
217
|
+
group: artifact.group,
|
|
218
|
+
topology: artifact.topology,
|
|
219
|
+
cycle: artifact.cycle,
|
|
220
|
+
outcome: artifact.outcome,
|
|
221
|
+
subjects: artifact.subjects.map((subject) => ({ ...subject })),
|
|
222
|
+
createdAt: artifact.createdAt
|
|
223
|
+
};
|
|
224
|
+
if (artifact.decider !== void 0) result.decider = { ...artifact.decider };
|
|
225
|
+
if (artifact.correlation !== void 0) result.correlation = { ...artifact.correlation };
|
|
226
|
+
if (artifact.winner !== void 0) {
|
|
227
|
+
result.winner = {
|
|
228
|
+
index: artifact.winner.index,
|
|
229
|
+
subject: { ...artifact.winner.subject },
|
|
230
|
+
branch: artifact.winner.branch
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (artifact.confirmation !== void 0) result.confirmation = { ...artifact.confirmation };
|
|
234
|
+
if (artifact.detail !== void 0) result.detail = artifact.detail;
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
function verifyGateDecisionArtifact(artifact) {
|
|
238
|
+
const invalid = semanticError(artifact);
|
|
239
|
+
if (invalid !== null) return { ok: false, reason: invalid };
|
|
240
|
+
if (!/^[0-9a-f]{64}$/.test(artifact.integrity.digest)) return { ok: false, reason: "gate decision integrity invalid" };
|
|
241
|
+
return decisionDigest(artifactWithoutIntegrity(artifact)) === artifact.integrity.digest ? { ok: true } : { ok: false, reason: "gate decision integrity mismatch" };
|
|
242
|
+
}
|
|
243
|
+
function buildGateDecisionArtifact(draft, id = newDecisionId(draft.group), createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()) {
|
|
244
|
+
if (draft.group.trim().length === 0) throw new Error("gate decision group is required");
|
|
245
|
+
if (!Number.isInteger(draft.cycle) || draft.cycle < 1)
|
|
246
|
+
throw new Error("gate decision cycle must be a positive integer");
|
|
247
|
+
if (draft.subjects.length === 0) throw new Error("gate decision requires at least one subject receipt");
|
|
248
|
+
const withoutIntegrity = {
|
|
249
|
+
version: 2,
|
|
250
|
+
id,
|
|
251
|
+
group: draft.group,
|
|
252
|
+
topology: draft.topology,
|
|
253
|
+
cycle: draft.cycle,
|
|
254
|
+
outcome: draft.outcome,
|
|
255
|
+
subjects: draft.subjects.map((subject) => ({ ...subject })),
|
|
256
|
+
createdAt
|
|
257
|
+
};
|
|
258
|
+
if (draft.decider !== void 0) withoutIntegrity.decider = { ...draft.decider };
|
|
259
|
+
if (draft.correlation !== void 0) withoutIntegrity.correlation = { ...draft.correlation };
|
|
260
|
+
if (draft.winner !== void 0) {
|
|
261
|
+
withoutIntegrity.winner = {
|
|
262
|
+
index: draft.winner.index,
|
|
263
|
+
subject: { ...draft.winner.subject },
|
|
264
|
+
branch: draft.winner.branch
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (draft.confirmation !== void 0) withoutIntegrity.confirmation = { ...draft.confirmation };
|
|
268
|
+
if (draft.detail !== void 0) withoutIntegrity.detail = draft.detail;
|
|
269
|
+
const artifact = {
|
|
270
|
+
...withoutIntegrity,
|
|
271
|
+
integrity: { algorithm: "sha256", digest: decisionDigest(withoutIntegrity) }
|
|
272
|
+
};
|
|
273
|
+
const verification = verifyGateDecisionArtifact(artifact);
|
|
274
|
+
if (!verification.ok) throw new Error(verification.reason);
|
|
275
|
+
return artifact;
|
|
276
|
+
}
|
|
277
|
+
function readVerifiedArtifact(path) {
|
|
278
|
+
let value;
|
|
279
|
+
try {
|
|
280
|
+
value = JSON.parse(readFileSync(path, "utf8"));
|
|
281
|
+
} catch (error) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
`gate decision artifact is unreadable at ${path}: ${error instanceof Error ? error.message : String(error)}`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
const artifact = value;
|
|
287
|
+
const verification = verifyGateDecisionArtifact(artifact);
|
|
288
|
+
if (!verification.ok) throw new Error(`gate decision artifact is invalid at ${path}: ${verification.reason}`);
|
|
289
|
+
return artifact;
|
|
290
|
+
}
|
|
291
|
+
function persistGateDecisionArtifact(artifact, stateDir, allowIdenticalExisting) {
|
|
292
|
+
const verification = verifyGateDecisionArtifact(artifact);
|
|
293
|
+
if (!verification.ok) throw new Error(verification.reason);
|
|
294
|
+
const directory = decisionsDirectory(stateDir);
|
|
295
|
+
mkdirSync(directory, { recursive: true });
|
|
296
|
+
const path = decisionArtifactPath(artifact.id, stateDir);
|
|
297
|
+
if (existsSync(path)) {
|
|
298
|
+
const existing = readVerifiedArtifact(path);
|
|
299
|
+
if (allowIdenticalExisting && existing.id === artifact.id && existing.integrity.digest === artifact.integrity.digest) {
|
|
300
|
+
return { artifact: existing, path };
|
|
301
|
+
}
|
|
302
|
+
throw new Error(`gate decision artifact collision: ${artifact.id}`);
|
|
303
|
+
}
|
|
304
|
+
atomicWrite(path, JSON.stringify(artifact, null, 2));
|
|
305
|
+
return { artifact, path };
|
|
306
|
+
}
|
|
307
|
+
function cloneGateDecisionArtifact(artifact) {
|
|
308
|
+
return {
|
|
309
|
+
...artifactWithoutIntegrity(artifact),
|
|
310
|
+
integrity: { ...artifact.integrity }
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function pendingRecordPayload(record) {
|
|
314
|
+
if (record.kind === "output") {
|
|
315
|
+
return {
|
|
316
|
+
contract: "clio.gateDecision.pending",
|
|
317
|
+
version: record.version,
|
|
318
|
+
kind: record.kind,
|
|
319
|
+
id: record.id,
|
|
320
|
+
group: record.group,
|
|
321
|
+
topology: record.topology,
|
|
322
|
+
cycle: record.cycle,
|
|
323
|
+
subjects: record.subjects.map((subject) => ({ runId: subject.runId, digest: subject.digest })),
|
|
324
|
+
deciderRunId: record.deciderRunId,
|
|
325
|
+
finalOutput: record.finalOutput,
|
|
326
|
+
...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
|
|
327
|
+
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
328
|
+
createdAt: record.createdAt
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
const decisionWithoutIntegrity = artifactWithoutIntegrity(record.decision);
|
|
332
|
+
return {
|
|
333
|
+
contract: "clio.gateDecision.pending",
|
|
334
|
+
version: record.version,
|
|
335
|
+
kind: record.kind,
|
|
336
|
+
id: record.id,
|
|
337
|
+
decision: {
|
|
338
|
+
...decisionPayload(decisionWithoutIntegrity),
|
|
339
|
+
integrity: { ...record.decision.integrity }
|
|
340
|
+
},
|
|
341
|
+
...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
|
|
342
|
+
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
343
|
+
createdAt: record.createdAt
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function pendingRecordDigest(record) {
|
|
347
|
+
return createHash("sha256").update(JSON.stringify(pendingRecordPayload(record)), "utf8").digest("hex");
|
|
348
|
+
}
|
|
349
|
+
function pendingRecordWithoutIntegrity(record) {
|
|
350
|
+
if (record.kind === "output") {
|
|
351
|
+
return {
|
|
352
|
+
version: record.version,
|
|
353
|
+
kind: record.kind,
|
|
354
|
+
id: record.id,
|
|
355
|
+
group: record.group,
|
|
356
|
+
topology: record.topology,
|
|
357
|
+
cycle: record.cycle,
|
|
358
|
+
subjects: record.subjects.map((subject) => ({ ...subject })),
|
|
359
|
+
deciderRunId: record.deciderRunId,
|
|
360
|
+
finalOutput: record.finalOutput,
|
|
361
|
+
...record.terminalCycle !== void 0 ? { terminalCycle: record.terminalCycle } : {},
|
|
362
|
+
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
363
|
+
createdAt: record.createdAt
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
return {
|
|
367
|
+
version: record.version,
|
|
368
|
+
kind: record.kind,
|
|
369
|
+
id: record.id,
|
|
370
|
+
decision: cloneGateDecisionArtifact(record.decision),
|
|
371
|
+
...record.finalOutput !== void 0 ? { finalOutput: record.finalOutput } : {},
|
|
372
|
+
...record.resourceRoot !== void 0 ? { resourceRoot: record.resourceRoot } : {},
|
|
373
|
+
createdAt: record.createdAt
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function pendingSemanticError(value) {
|
|
377
|
+
if (!isRecord(value)) return "pending gate decision is not an object";
|
|
378
|
+
if (value.version !== 1) return "unsupported pending gate decision version";
|
|
379
|
+
if (!isSafeDecisionId(value.id)) return "pending gate decision id invalid";
|
|
380
|
+
if (typeof value.createdAt !== "string" || !Number.isFinite(Date.parse(value.createdAt))) {
|
|
381
|
+
return "pending gate decision timestamp invalid";
|
|
382
|
+
}
|
|
383
|
+
if (!isRecord(value.integrity) || value.integrity.algorithm !== "sha256" || typeof value.integrity.digest !== "string" || !/^[0-9a-f]{64}$/.test(value.integrity.digest)) {
|
|
384
|
+
return "pending gate decision integrity invalid";
|
|
385
|
+
}
|
|
386
|
+
if (value.kind === "output") {
|
|
387
|
+
if (typeof value.group !== "string" || value.group.trim().length === 0) {
|
|
388
|
+
return "pending gate output group invalid";
|
|
389
|
+
}
|
|
390
|
+
if (value.topology !== "review" && value.topology !== "compete") {
|
|
391
|
+
return "pending gate output topology invalid";
|
|
392
|
+
}
|
|
393
|
+
if (typeof value.cycle !== "number" || !Number.isInteger(value.cycle) || value.cycle < 1) {
|
|
394
|
+
return "pending gate output cycle invalid";
|
|
395
|
+
}
|
|
396
|
+
if (!Array.isArray(value.subjects) || value.subjects.length === 0 || !value.subjects.every(isSubjectRef)) {
|
|
397
|
+
return "pending gate output subjects invalid";
|
|
398
|
+
}
|
|
399
|
+
if (typeof value.deciderRunId !== "string" || value.deciderRunId.trim().length === 0) {
|
|
400
|
+
return "pending gate output decider run id invalid";
|
|
401
|
+
}
|
|
402
|
+
if (typeof value.finalOutput !== "string") return "pending gate output text invalid";
|
|
403
|
+
if (value.terminalCycle !== void 0 && typeof value.terminalCycle !== "boolean") {
|
|
404
|
+
return "pending gate output terminal-cycle marker invalid";
|
|
405
|
+
}
|
|
406
|
+
if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
|
|
407
|
+
return "pending gate output resource root invalid";
|
|
408
|
+
}
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
if (value.kind !== "decision") return "pending gate decision kind invalid";
|
|
412
|
+
if (!isRecord(value.decision)) return "pending gate decision artifact invalid";
|
|
413
|
+
const verification = verifyGateDecisionArtifact(value.decision);
|
|
414
|
+
if (!verification.ok) return `pending gate decision artifact invalid: ${verification.reason}`;
|
|
415
|
+
if (value.decision.id !== value.id) return "pending gate decision artifact id mismatch";
|
|
416
|
+
if (value.decision.createdAt !== value.createdAt) return "pending gate decision artifact timestamp mismatch";
|
|
417
|
+
if (value.finalOutput !== void 0 && typeof value.finalOutput !== "string") {
|
|
418
|
+
return "pending gate decision output invalid";
|
|
419
|
+
}
|
|
420
|
+
if (value.resourceRoot !== void 0 && (typeof value.resourceRoot !== "string" || value.resourceRoot.length === 0)) {
|
|
421
|
+
return "pending gate decision resource root invalid";
|
|
422
|
+
}
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
function verifyPendingGateDecisionRecord(record) {
|
|
426
|
+
const invalid = pendingSemanticError(record);
|
|
427
|
+
if (invalid !== null) return { ok: false, reason: invalid };
|
|
428
|
+
return pendingRecordDigest(pendingRecordWithoutIntegrity(record)) === record.integrity.digest ? { ok: true } : { ok: false, reason: "pending gate decision integrity mismatch" };
|
|
429
|
+
}
|
|
430
|
+
function clonePendingGateDecisionRecord(record) {
|
|
431
|
+
const without = pendingRecordWithoutIntegrity(record);
|
|
432
|
+
return {
|
|
433
|
+
...without,
|
|
434
|
+
integrity: { ...record.integrity }
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function parsePendingGateDecisionRecord(value) {
|
|
438
|
+
const invalid = pendingSemanticError(value);
|
|
439
|
+
if (invalid !== null) throw new Error(invalid);
|
|
440
|
+
const record = clonePendingGateDecisionRecord(value);
|
|
441
|
+
const verification = verifyPendingGateDecisionRecord(record);
|
|
442
|
+
if (!verification.ok) throw new Error(verification.reason);
|
|
443
|
+
return record;
|
|
444
|
+
}
|
|
445
|
+
function assertPendingHandlePath(handle) {
|
|
446
|
+
const expected = pendingDecisionPath(handle.record.id, handle.stateDir);
|
|
447
|
+
if (resolve(handle.path) !== resolve(expected)) {
|
|
448
|
+
throw new Error(`pending gate decision path does not match id ${handle.record.id}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
function pendingHandle(record, stateDir) {
|
|
452
|
+
return {
|
|
453
|
+
record: clonePendingGateDecisionRecord(record),
|
|
454
|
+
path: pendingDecisionPath(record.id, stateDir),
|
|
455
|
+
stateDir
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function persistPendingGateDecision(record, stateDir, allowReplace) {
|
|
459
|
+
const verification = verifyPendingGateDecisionRecord(record);
|
|
460
|
+
if (!verification.ok) throw new Error(verification.reason);
|
|
461
|
+
const path = pendingDecisionPath(record.id, stateDir);
|
|
462
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
463
|
+
if (!allowReplace && existsSync(path)) throw new Error(`pending gate decision collision: ${record.id}`);
|
|
464
|
+
atomicWrite(path, JSON.stringify(record, null, 2));
|
|
465
|
+
return pendingHandle(record, stateDir);
|
|
466
|
+
}
|
|
467
|
+
function loadPendingGateDecision(handle) {
|
|
468
|
+
assertPendingHandlePath(handle);
|
|
469
|
+
if (!existsSync(handle.path)) return null;
|
|
470
|
+
const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync(handle.path, "utf8")));
|
|
471
|
+
if (record.id !== handle.record.id) throw new Error("pending gate decision changed identity on disk");
|
|
472
|
+
return pendingHandle(record, handle.stateDir);
|
|
473
|
+
}
|
|
474
|
+
function fsyncDirectoryBestEffort(path) {
|
|
475
|
+
let fd = null;
|
|
476
|
+
try {
|
|
477
|
+
fd = openSync(path, "r");
|
|
478
|
+
fsyncSync(fd);
|
|
479
|
+
} catch {
|
|
480
|
+
} finally {
|
|
481
|
+
if (fd !== null) closeSync(fd);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
function clearPendingGateDecision(handle) {
|
|
485
|
+
assertPendingHandlePath(handle);
|
|
486
|
+
rmSync(handle.path, { force: true });
|
|
487
|
+
fsyncDirectoryBestEffort(dirname(handle.path));
|
|
488
|
+
}
|
|
489
|
+
function sameSubjectRefs(left, right) {
|
|
490
|
+
return left.length === right.length && left.every((subject, index) => {
|
|
491
|
+
const other = right[index];
|
|
492
|
+
return other !== void 0 && subject.runId === other.runId && subject.digest === other.digest;
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function stagePendingGateOutput(draft, stateDir = clioStateDir()) {
|
|
496
|
+
const id = newDecisionId(draft.group);
|
|
497
|
+
const withoutIntegrity = {
|
|
498
|
+
version: 1,
|
|
499
|
+
kind: "output",
|
|
500
|
+
id,
|
|
501
|
+
group: draft.group,
|
|
502
|
+
topology: draft.topology,
|
|
503
|
+
cycle: draft.cycle,
|
|
504
|
+
subjects: draft.subjects.map((subject) => ({ ...subject })),
|
|
505
|
+
deciderRunId: draft.deciderRunId,
|
|
506
|
+
finalOutput: draft.finalOutput,
|
|
507
|
+
...draft.terminalCycle !== void 0 ? { terminalCycle: draft.terminalCycle } : {},
|
|
508
|
+
...draft.resourceRoot !== void 0 ? { resourceRoot: draft.resourceRoot } : {},
|
|
509
|
+
createdAt: draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
510
|
+
};
|
|
511
|
+
const record = {
|
|
512
|
+
...withoutIntegrity,
|
|
513
|
+
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
514
|
+
};
|
|
515
|
+
if (existsSync(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
|
|
516
|
+
return persistPendingGateDecision(record, stateDir, false);
|
|
517
|
+
}
|
|
518
|
+
function stagePendingGateDecision(draft, options = {}) {
|
|
519
|
+
const stateDir = options.stateDir ?? clioStateDir();
|
|
520
|
+
const id = newDecisionId(draft.group);
|
|
521
|
+
const createdAt = draft.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
522
|
+
const decision = buildGateDecisionArtifact(draft, id, createdAt);
|
|
523
|
+
const withoutIntegrity = {
|
|
524
|
+
version: 1,
|
|
525
|
+
kind: "decision",
|
|
526
|
+
id,
|
|
527
|
+
decision,
|
|
528
|
+
...options.finalOutput !== void 0 ? { finalOutput: options.finalOutput } : {},
|
|
529
|
+
...options.resourceRoot !== void 0 ? { resourceRoot: options.resourceRoot } : {},
|
|
530
|
+
createdAt
|
|
531
|
+
};
|
|
532
|
+
const record = {
|
|
533
|
+
...withoutIntegrity,
|
|
534
|
+
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
535
|
+
};
|
|
536
|
+
if (existsSync(decisionArtifactPath(id, stateDir))) throw new Error(`gate decision artifact collision: ${id}`);
|
|
537
|
+
return persistPendingGateDecision(record, stateDir, false);
|
|
538
|
+
}
|
|
539
|
+
function resolvePendingGateDecision(handle, draft) {
|
|
540
|
+
const loaded = loadPendingGateDecision(handle);
|
|
541
|
+
if (loaded === null) throw new Error(`pending gate decision is missing: ${handle.record.id}`);
|
|
542
|
+
if (loaded.record.kind === "decision") {
|
|
543
|
+
const expected = buildGateDecisionArtifact(draft, loaded.record.id, loaded.record.createdAt);
|
|
544
|
+
if (expected.integrity.digest !== loaded.record.decision.integrity.digest) {
|
|
545
|
+
throw new Error("pending gate decision was already resolved to a different artifact");
|
|
546
|
+
}
|
|
547
|
+
return loaded;
|
|
548
|
+
}
|
|
549
|
+
const pending = loaded.record;
|
|
550
|
+
if (draft.group !== pending.group || draft.topology !== pending.topology || draft.cycle !== pending.cycle || !sameSubjectRefs(draft.subjects, pending.subjects)) {
|
|
551
|
+
throw new Error("resolved gate decision does not match staged output context");
|
|
552
|
+
}
|
|
553
|
+
if (draft.decider === void 0 || draft.decider.runId !== pending.deciderRunId) {
|
|
554
|
+
throw new Error("resolved gate decision does not match staged decider run");
|
|
555
|
+
}
|
|
556
|
+
if (draft.createdAt !== void 0 && draft.createdAt !== pending.createdAt) {
|
|
557
|
+
throw new Error("resolved gate decision cannot change the staged timestamp");
|
|
558
|
+
}
|
|
559
|
+
const decision = buildGateDecisionArtifact(draft, pending.id, pending.createdAt);
|
|
560
|
+
const withoutIntegrity = {
|
|
561
|
+
version: 1,
|
|
562
|
+
kind: "decision",
|
|
563
|
+
id: pending.id,
|
|
564
|
+
decision,
|
|
565
|
+
finalOutput: pending.finalOutput,
|
|
566
|
+
...pending.resourceRoot !== void 0 ? { resourceRoot: pending.resourceRoot } : {},
|
|
567
|
+
createdAt: pending.createdAt
|
|
568
|
+
};
|
|
569
|
+
const resolvedRecord = {
|
|
570
|
+
...withoutIntegrity,
|
|
571
|
+
integrity: { algorithm: "sha256", digest: pendingRecordDigest(withoutIntegrity) }
|
|
572
|
+
};
|
|
573
|
+
return persistPendingGateDecision(resolvedRecord, loaded.stateDir, true);
|
|
574
|
+
}
|
|
575
|
+
function materializePendingGateDecision(handle) {
|
|
576
|
+
const loaded = loadPendingGateDecision(handle);
|
|
577
|
+
if (loaded === null) {
|
|
578
|
+
if (handle.record.kind !== "decision") {
|
|
579
|
+
throw new Error(`pending gate output is missing before resolution: ${handle.record.id}`);
|
|
580
|
+
}
|
|
581
|
+
const path = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
|
|
582
|
+
if (!existsSync(path)) throw new Error(`pending gate decision and artifact are both missing: ${handle.record.id}`);
|
|
583
|
+
const artifact = readVerifiedArtifact(path);
|
|
584
|
+
if (artifact.integrity.digest !== handle.record.decision.integrity.digest) {
|
|
585
|
+
throw new Error(`gate decision artifact conflicts with completed pending record: ${handle.record.id}`);
|
|
586
|
+
}
|
|
587
|
+
return { artifact, path };
|
|
588
|
+
}
|
|
589
|
+
if (loaded.record.kind !== "decision") {
|
|
590
|
+
throw new Error(`pending gate output requires receipt resolution: ${loaded.record.id}`);
|
|
591
|
+
}
|
|
592
|
+
const written = persistGateDecisionArtifact(loaded.record.decision, loaded.stateDir, true);
|
|
593
|
+
const persisted = readVerifiedArtifact(written.path);
|
|
594
|
+
if (persisted.integrity.digest !== loaded.record.decision.integrity.digest) {
|
|
595
|
+
throw new Error(`materialized gate decision does not match pending record: ${loaded.record.id}`);
|
|
596
|
+
}
|
|
597
|
+
clearPendingGateDecision(loaded);
|
|
598
|
+
return { artifact: persisted, path: written.path };
|
|
599
|
+
}
|
|
600
|
+
function finalizePendingGateDecision(handle, draft) {
|
|
601
|
+
return materializePendingGateDecision(resolvePendingGateDecision(handle, draft));
|
|
602
|
+
}
|
|
603
|
+
function readPendingGateDecisions(stateDir = clioStateDir()) {
|
|
604
|
+
const directory = pendingDecisionsDirectory(stateDir);
|
|
605
|
+
if (!existsSync(directory)) return { records: [], errors: [] };
|
|
606
|
+
const records = [];
|
|
607
|
+
const errors = [];
|
|
608
|
+
for (const name of readdirSync(directory).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
609
|
+
const path = join(directory, name);
|
|
610
|
+
try {
|
|
611
|
+
const record = parsePendingGateDecisionRecord(JSON.parse(readFileSync(path, "utf8")));
|
|
612
|
+
if (name !== `${record.id}.json`) throw new Error("pending gate decision filename does not match its id");
|
|
613
|
+
records.push({ record, path, stateDir });
|
|
614
|
+
} catch (error) {
|
|
615
|
+
errors.push({ path, message: error instanceof Error ? error.message : String(error) });
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return { records, errors };
|
|
619
|
+
}
|
|
620
|
+
function preflightPendingGateDecisionMaterialization(handles) {
|
|
621
|
+
for (const handle of handles) {
|
|
622
|
+
if (handle.record.kind !== "decision") continue;
|
|
623
|
+
const path = decisionArtifactPath(handle.record.decision.id, handle.stateDir);
|
|
624
|
+
if (!existsSync(path)) continue;
|
|
625
|
+
const existing = readVerifiedArtifact(path);
|
|
626
|
+
if (existing.integrity.digest !== handle.record.decision.integrity.digest) {
|
|
627
|
+
throw new Error(`gate decision artifact conflicts with pending record: ${handle.record.id}`);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function preparePendingGateDecisionRecovery(stateDir = clioStateDir()) {
|
|
632
|
+
const pending = readPendingGateDecisions(stateDir);
|
|
633
|
+
if (pending.errors.length > 0) {
|
|
634
|
+
throw new Error(
|
|
635
|
+
`pending gate decision journal is untrustworthy: ${pending.errors.map((entry) => `${entry.path}: ${entry.message}`).join("; ")}`
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
const ready = pending.records.filter((handle) => handle.record.kind === "decision");
|
|
639
|
+
preflightPendingGateDecisionMaterialization(ready);
|
|
640
|
+
return {
|
|
641
|
+
ready,
|
|
642
|
+
unresolved: pending.records.filter((handle) => handle.record.kind === "output")
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function readGateDecisionArtifacts(group, stateDir = clioStateDir()) {
|
|
646
|
+
const directory = decisionsDirectory(stateDir);
|
|
647
|
+
if (!existsSync(directory)) return [];
|
|
648
|
+
const out = [];
|
|
649
|
+
for (const name of readdirSync(directory).filter((entry) => entry.endsWith(".json")).sort()) {
|
|
650
|
+
const path = join(directory, name);
|
|
651
|
+
try {
|
|
652
|
+
const artifact = JSON.parse(readFileSync(path, "utf8"));
|
|
653
|
+
if (group !== void 0 && artifact.group !== group) continue;
|
|
654
|
+
if (!verifyGateDecisionArtifact(artifact).ok) continue;
|
|
655
|
+
out.push({ artifact, path });
|
|
656
|
+
} catch {
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return out;
|
|
660
|
+
}
|
|
661
|
+
function readGateDecisionArtifactsForRunIds(runIds, stateDir = clioStateDir()) {
|
|
662
|
+
if (runIds.size === 0) return [];
|
|
663
|
+
return readGateDecisionArtifacts(void 0, stateDir).filter(({ artifact }) => {
|
|
664
|
+
if (artifact.subjects.some((subject) => runIds.has(subject.runId))) return true;
|
|
665
|
+
if (artifact.decider !== void 0 && runIds.has(artifact.decider.runId)) return true;
|
|
666
|
+
return artifact.winner !== void 0 && runIds.has(artifact.winner.subject.runId);
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export {
|
|
671
|
+
decideReviewGate,
|
|
672
|
+
parseCompeteGateResult,
|
|
673
|
+
gateDecisionsDirectory,
|
|
674
|
+
verifyGateDecisionArtifact,
|
|
675
|
+
stagePendingGateOutput,
|
|
676
|
+
stagePendingGateDecision,
|
|
677
|
+
resolvePendingGateDecision,
|
|
678
|
+
materializePendingGateDecision,
|
|
679
|
+
finalizePendingGateDecision,
|
|
680
|
+
readPendingGateDecisions,
|
|
681
|
+
preflightPendingGateDecisionMaterialization,
|
|
682
|
+
preparePendingGateDecisionRecovery,
|
|
683
|
+
readGateDecisionArtifacts,
|
|
684
|
+
readGateDecisionArtifactsForRunIds
|
|
685
|
+
};
|
|
686
|
+
//# sourceMappingURL=chunk-X75E3D2N.js.map
|