@iowarp/clio-coder 0.3.7 → 0.3.9
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 +80 -0
- package/README.md +13 -4
- package/dist/{acp-SK4MD6MM.js → acp-7LOELQFP.js} +13 -13
- package/dist/{agents-2FN2K6ME.js → agents-FIBG2SHA.js} +41 -37
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-QIYZWM5I.js → auth-OI4LIH2I.js} +31 -24
- package/dist/builtins-AD25UL3C.js +17 -0
- package/dist/{chunk-5FR74PWO.js → chunk-2JDWVJND.js} +2 -2
- package/dist/chunk-3DPEIQKN.js +113 -0
- package/dist/{chunk-EOOQZZDE.js → chunk-3DUR4WUA.js} +19 -19
- package/dist/{chunk-WHJYKASB.js → chunk-3MRC2YSQ.js} +2 -2
- package/dist/{chunk-EBEFWSGL.js → chunk-3UUY7R3Z.js} +14 -10
- package/dist/{chunk-LADCF22A.js → chunk-3V5AYSEQ.js} +113 -54
- package/dist/{chunk-BMWK7ZIZ.js → chunk-465CC7FK.js} +16 -13
- package/dist/{chunk-5WIGXA4T.js → chunk-47CMYGET.js} +111 -4
- package/dist/{chunk-CEYBNUGC.js → chunk-4H6ULJ3H.js} +378 -36
- package/dist/{chunk-YTYFXUI3.js → chunk-4LJX2PUC.js} +9 -9
- package/dist/{chunk-DOOEX22V.js → chunk-56KB5IJP.js} +5 -5
- package/dist/{chunk-SPULKLCF.js → chunk-5DQRIYDZ.js} +2 -2
- package/dist/{chunk-TSHXZTOQ.js → chunk-5HFBWUMU.js} +23 -11
- package/dist/{chunk-5UJ6ECTS.js → chunk-5PVQ4SRS.js} +80 -8
- package/dist/{chunk-ZWLZP4ZT.js → chunk-5QKCQQ3E.js} +359 -17
- package/dist/{chunk-6M7VS3J3.js → chunk-5T7RBWN2.js} +111 -5
- package/dist/chunk-774ILSRL.js +172 -0
- package/dist/chunk-7C6RYZGQ.js +391 -0
- package/dist/{chunk-GH5622CP.js → chunk-A2NJGIB3.js} +2 -2
- package/dist/{chunk-C4JBQ5SR.js → chunk-AD7Y7STJ.js} +6 -6
- package/dist/{chunk-GEYXPTRF.js → chunk-AEYBF3TB.js} +33 -12
- package/dist/{chunk-2SFS6XQE.js → chunk-AMKHQW3C.js} +3 -2
- package/dist/{chunk-D4MDIG46.js → chunk-B5CSFE7B.js} +7 -7
- package/dist/{chunk-MXI6J5JF.js → chunk-B5XRQOLB.js} +10 -10
- package/dist/{chunk-X2KV5FXT.js → chunk-BVDVID7E.js} +2 -2
- package/dist/{chunk-JNXPYBB4.js → chunk-CA42X6KT.js} +3 -3
- package/dist/{chunk-VREKEFLL.js → chunk-D73KXYPF.js} +3 -3
- package/dist/{chunk-JTSEDYVQ.js → chunk-DG4M6ZUE.js} +7 -7
- package/dist/{chunk-DQA7QLMD.js → chunk-EBOC7MT3.js} +10 -25
- package/dist/{chunk-KZ2H5X4G.js → chunk-ECUO3KDP.js} +129 -14
- package/dist/{chunk-JRIO5UD2.js → chunk-EQ63NRB7.js} +5 -5
- package/dist/{chunk-YD734TPH.js → chunk-FALJGAWU.js} +2 -2
- package/dist/{chunk-GWS3VEIW.js → chunk-FWDFM5ZU.js} +24 -3
- package/dist/{chunk-XEGB6BCN.js → chunk-GAYUJ7LE.js} +68 -14
- package/dist/{chunk-UND3GU2L.js → chunk-H7IXIC72.js} +2 -2
- package/dist/{chunk-IR4CFBFN.js → chunk-HAY4ZE2P.js} +12 -12
- package/dist/{chunk-UVDSQ6LW.js → chunk-HCBCAYZU.js} +74 -147
- package/dist/{chunk-4DWFMQDR.js → chunk-HJB5IUKP.js} +89 -145
- package/dist/{chunk-M4AKACEO.js → chunk-HKO36JWF.js} +33 -5
- package/dist/{chunk-KCMKRQX4.js → chunk-HPCTNZM2.js} +45 -82
- package/dist/{chunk-465YSENW.js → chunk-IFBNV6H6.js} +3 -3
- package/dist/{chunk-FJ3H4MN5.js → chunk-IHKBWSXF.js} +2 -2
- package/dist/chunk-JEQQR47K.js +3025 -0
- package/dist/{chunk-FO5ZOVUY.js → chunk-KV2AOLDF.js} +27 -7
- package/dist/chunk-LU7P4LHA.js +33 -0
- package/dist/{chunk-6TUKSZVF.js → chunk-LXPJXFM5.js} +11 -11
- package/dist/{chunk-VQNODYQ4.js → chunk-MIX5N5AC.js} +488 -3668
- package/dist/chunk-MLOK6ZOS.js +2888 -0
- package/dist/{chunk-ZZMN5OM4.js → chunk-MV2VUEJC.js} +2 -2
- package/dist/{chunk-MVVUPGPW.js → chunk-MXHC5QYU.js} +6 -6
- package/dist/{chunk-OBMAI2DP.js → chunk-N3PBVRTZ.js} +12 -388
- package/dist/{chunk-WJHBC77E.js → chunk-N5XKWMDW.js} +17 -7
- package/dist/{chunk-5C3AQNDW.js → chunk-NNNWO6F2.js} +124 -36
- package/dist/{chunk-UFQ3F4FW.js → chunk-NQ6UCCOD.js} +4 -4
- package/dist/chunk-NUGM5KR6.js +165 -0
- package/dist/{chunk-DMD2AGVS.js → chunk-NZU6YDNV.js} +20 -18
- package/dist/{chunk-WHGPSPT5.js → chunk-O6I4CIEU.js} +151 -13
- package/dist/{chunk-XN3L4EYL.js → chunk-OEDBCISO.js} +2 -2
- package/dist/{chunk-PD3MESLB.js → chunk-P3JGPQFL.js} +4 -4
- package/dist/{chunk-UHXRNZ2J.js → chunk-PNY46YEY.js} +23 -6
- package/dist/{chunk-THKY7CD7.js → chunk-PZ4I4JE2.js} +134 -29
- package/dist/{chunk-SROCI7ZU.js → chunk-QQ7EKM72.js} +5 -5
- package/dist/{chunk-QCTRSGHQ.js → chunk-R7LNVMCS.js} +91 -53
- package/dist/{chunk-GOXNB3AO.js → chunk-RAPCMZL4.js} +75 -4
- package/dist/chunk-RKKLTLYB.js +45 -0
- package/dist/{chunk-OB5HIGJY.js → chunk-RKRLDWD3.js} +4 -1
- package/dist/{chunk-DJNLUABN.js → chunk-S4COXYBG.js} +588 -32
- package/dist/{chunk-3HAPLH5M.js → chunk-T3Z6VAAF.js} +172 -11
- package/dist/{chunk-FOT2FX5J.js → chunk-TD7UE2L5.js} +12 -10
- package/dist/{chunk-UUANF5CR.js → chunk-TEO2TLVN.js} +856 -967
- package/dist/{chunk-FCSXB6T2.js → chunk-UOSL25KY.js} +14 -2
- package/dist/{chunk-EELBMBT6.js → chunk-VKBMFOYV.js} +74 -15
- package/dist/chunk-VO2LKSTM.js +165 -0
- package/dist/{chunk-5C77SEEY.js → chunk-VPTUJU4P.js} +3 -3
- package/dist/{chunk-WEH5XRJQ.js → chunk-WIE7ZOSW.js} +2 -2
- package/dist/{chunk-J7PIKKWC.js → chunk-WXCJ7VME.js} +8 -8
- package/dist/{chunk-4DGYLA73.js → chunk-XDOQXGFO.js} +22 -7
- package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
- package/dist/{chunk-AB4XIIVB.js → chunk-YKOFT37S.js} +6 -6
- package/dist/chunk-YSEHGPCT.js +127 -0
- package/dist/{chunk-HFSBBKSQ.js → chunk-YW7UVM5V.js} +138 -3
- package/dist/cli/index.js +32 -32
- package/dist/{clio-WBVQEBKO.js → clio-LT5V7SSZ.js} +9 -9
- package/dist/{code-nav-FGGFIE7L.js → code-nav-LMW275PA.js} +5 -5
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-F7OEATSO.js → components-ZFA3SAER.js} +8 -8
- package/dist/{config-TRBL3RCF.js → config-RXS5T3JT.js} +98 -65
- package/dist/{configure-OLCVPHNM.js → configure-2WYWSCSD.js} +26 -22
- package/dist/{context-MJIJ6GOX.js → context-I3BTOTCS.js} +12 -12
- package/dist/{context-XEWE3MOJ.js → context-MVOORGMF.js} +54 -47
- package/dist/{context-WFPKQSM6.js → context-PALKKQYL.js} +28 -28
- package/dist/{context-clear-KNOS2JPB.js → context-clear-N2WOYZ2K.js} +53 -46
- package/dist/{context-index-SSR5ECNE.js → context-index-HNG3MOME.js} +6 -6
- package/dist/{context-working-set-EUXAZI6N.js → context-working-set-MIEVECVZ.js} +17 -18
- package/dist/{dispatch-runner-B7MTOVKL.js → dispatch-runner-VVA4SRRH.js} +90 -61
- package/dist/{docs-FLJTIDSE.js → docs-7LQ23DLM.js} +8 -8
- package/dist/doctor-TWBWFK5V.js +165 -0
- package/dist/eval-IJ5VEZDJ.js +4483 -0
- package/dist/{evidence-JZNBUOQZ.js → evidence-L5APPXNV.js} +68 -61
- package/dist/{evolve-FJVC4KKI.js → evolve-RGNKFJ52.js} +47 -40
- package/dist/{extensions-IQL36S7K.js → extensions-7WYWUX5A.js} +13 -7
- package/dist/{fleet-BDKYJFCP.js → fleet-6CNVBZZP.js} +113 -76
- package/dist/{fleet-commands-ZFIWZSB3.js → fleet-commands-L2SXSYEI.js} +10 -10
- package/dist/{fleet-graph-Y6HPXIVF.js → fleet-graph-2J3OOIPO.js} +17 -15
- package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-CZRJ4JP5.js} +5 -6
- package/dist/{fleet-validate-BIYREGIK.js → fleet-validate-C5RI6DP7.js} +20 -19
- package/dist/{init-LQUB5COQ.js → init-VBN2ACVA.js} +70 -63
- package/dist/{library-NJAHIGG4.js → library-JHGUMLY2.js} +22 -20
- package/dist/{memory-OG6HOYKM.js → memory-K4OQIYWG.js} +49 -42
- package/dist/{models-5ZG5XY7J.js → models-2NCZUWDD.js} +35 -29
- package/dist/{monitor-TJ7AMTGB.js → monitor-MMVTJABD.js} +64 -45
- package/dist/{orchestrator-WZYB54DM.js → orchestrator-ZKBPCHW6.js} +1971 -520
- package/dist/{paths-XUC7GS6E.js → paths-DBXMZMDU.js} +5 -5
- package/dist/registry-LG64LTF4.js +11 -0
- package/dist/{reset-PXQT45IY.js → reset-DD5JGOY3.js} +11 -11
- package/dist/{run-FQ74YF62.js → run-QEGNX7FL.js} +89 -83
- package/dist/{share-FW7SVCL3.js → share-JKD3BQMW.js} +20 -18
- package/dist/{skills-7E7IRB3R.js → skills-LMQIKDOZ.js} +23 -21
- package/dist/{skills-eval-LI75W6OK.js → skills-eval-I7X2774U.js} +59 -52
- package/dist/{steer-GGWFUJUD.js → steer-CF5TDANS.js} +3 -3
- package/dist/support-I7LOJLIF.js +38 -0
- package/dist/{targets-4CIFKCTW.js → targets-RUSR6B5Z.js} +77 -42
- package/dist/{terminal-lease-WUZY7ZV5.js → terminal-lease-QYVORFR4.js} +6 -4
- package/dist/{trace-PNCASAXC.js → trace-ODOQIVIW.js} +61 -6
- package/dist/{uninstall-7FV7IP4E.js → uninstall-ZJF5H5ZN.js} +8 -8
- package/dist/{upgrade-K2HVIVMQ.js → upgrade-XANW3FXB.js} +29 -26
- package/dist/{usage-GTZELZQX.js → usage-4H7ZRXQT.js} +110 -61
- package/dist/{verifiers-RLAHT27O.js → verifiers-UZXNBZEB.js} +13 -13
- package/dist/{verify-BX3BRKH5.js → verify-BVKWTNDL.js} +9 -9
- package/dist/{wiki-generate-ASIFASCN.js → wiki-generate-MY7WV2QI.js} +76 -69
- package/dist/worker/entry.js +69 -66
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +1 -1
- package/docs/artifact-versions.md +11 -5
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +23 -2
- package/docs/commands-and-modes.md +2 -2
- package/docs/configuration-and-targets.md +37 -5
- package/docs/context-engine.md +63 -4
- package/docs/documentation-coverage.md +3 -3
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +2 -0
- package/docs/eval-runner.md +262 -11
- package/docs/evals-internal.md +72 -2
- package/docs/evidence-and-memory.md +77 -12
- package/docs/evolution.md +1 -1
- package/docs/extensions-and-sharing.md +3 -1
- package/docs/fleet-dispatch.md +34 -9
- package/docs/glossary.md +21 -1
- package/docs/installation-and-lifecycle.md +1 -1
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +54 -3
- package/docs/proactive-memory.md +127 -14
- package/docs/prompt-envelope-and-tools.md +22 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +60 -41
- package/docs/safety-model.md +1 -1
- package/docs/scientific-validation.md +1 -1
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +1 -1
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +87 -0
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +2 -2
- package/src/cli/agents.ts +1 -1
- package/src/cli/argv.ts +5 -0
- package/src/cli/config-inspect.ts +33 -6
- package/src/cli/config.ts +1 -1
- package/src/cli/configure.ts +107 -23
- package/src/cli/doctor-state-size.ts +82 -0
- package/src/cli/doctor.ts +7 -1
- package/src/cli/eval.ts +80 -16
- package/src/cli/evidence.ts +30 -25
- package/src/cli/extensions.ts +5 -1
- package/src/cli/fleet-preflight.ts +2 -12
- package/src/cli/fleet.ts +32 -3
- package/src/cli/shared.ts +1 -0
- package/src/cli/targets.ts +45 -11
- package/src/cli/trace.ts +63 -4
- package/src/cli/usage.ts +63 -14
- package/src/cli/validate-model.ts +60 -5
- package/src/core/bus-events.ts +54 -1
- package/src/core/cache-telemetry.ts +42 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +18 -0
- package/src/core/defaults.ts +36 -6
- package/src/core/endpoint-key.ts +27 -0
- package/src/core/path-boundary.ts +100 -0
- package/src/core/residency-target-key.ts +25 -0
- package/src/core/response-schema.ts +36 -2
- package/src/domains/agents/extension.ts +2 -11
- package/src/domains/agents/fleet-contract.ts +30 -12
- package/src/domains/agents/recipe.ts +7 -1
- package/src/domains/agents/registry.ts +73 -5
- package/src/domains/agents/result-contract.ts +128 -17
- package/src/domains/agents/write-boundary.ts +15 -50
- package/src/domains/config/classify.ts +3 -0
- package/src/domains/context/codewiki/coordinator.ts +12 -4
- package/src/domains/context/project-rules.ts +51 -1
- package/src/domains/dispatch/admission.ts +40 -3
- package/src/domains/dispatch/assignment-reconcile.ts +22 -5
- package/src/domains/dispatch/assignment-store.ts +151 -14
- package/src/domains/dispatch/capacity-lease.ts +98 -9
- package/src/domains/dispatch/contract.ts +26 -1
- package/src/domains/dispatch/delegation-plan.ts +2 -5
- package/src/domains/dispatch/execution-plan.ts +44 -4
- package/src/domains/dispatch/execution-role.ts +9 -1
- package/src/domains/dispatch/extension.ts +309 -96
- package/src/domains/dispatch/fleet-run.ts +78 -4
- package/src/domains/dispatch/gate-role-prompts.ts +38 -0
- package/src/domains/dispatch/heartbeat.ts +32 -8
- package/src/domains/dispatch/index.ts +6 -1
- package/src/domains/dispatch/intent-requirements.ts +40 -0
- package/src/domains/dispatch/intent.ts +84 -8
- package/src/domains/dispatch/orphan-recovery.ts +5 -0
- package/src/domains/dispatch/path-scope.ts +370 -0
- package/src/domains/dispatch/receipt-integrity.ts +2 -1
- package/src/domains/dispatch/reservation-store.ts +116 -8
- package/src/domains/dispatch/state.ts +4 -0
- package/src/domains/dispatch/types.ts +14 -7
- package/src/domains/dispatch/validation.ts +6 -3
- package/src/domains/dispatch/worker-spawn.ts +25 -11
- package/src/domains/dispatch/write-boundary-enforcer.ts +62 -0
- package/src/domains/dispatch/write-boundary.ts +262 -22
- 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 +355 -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/metrics/aggregate.ts +136 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +112 -0
- package/src/domains/eval/metrics/evidence.ts +79 -2
- 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 +139 -2
- 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 +74 -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 +68 -21
- package/src/domains/evidence/eval.ts +2 -12
- package/src/domains/evidence/findings-markdown.ts +33 -0
- package/src/domains/evidence/index.ts +21 -0
- package/src/domains/evidence/provenance.ts +46 -11
- package/src/domains/evidence/run-trust.ts +7 -113
- package/src/domains/evidence/trust-projection.ts +274 -0
- package/src/domains/evidence/trust-status.ts +145 -17
- package/src/domains/evidence/types.ts +4 -0
- package/src/domains/extensions/compatibility.ts +285 -0
- package/src/domains/extensions/discovery.ts +126 -4
- package/src/domains/extensions/resources.ts +21 -9
- package/src/domains/extensions/state.ts +18 -5
- package/src/domains/extensions/types.ts +6 -1
- package/src/domains/lifecycle/doctor.ts +209 -2
- package/src/domains/memory/index.ts +14 -0
- package/src/domains/memory/task-bank-promotion.ts +64 -0
- package/src/domains/memory/task-memory-policy.ts +77 -8
- 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 +2 -0
- package/src/domains/middleware/index.ts +1 -0
- package/src/domains/middleware/memory-intervention.ts +69 -5
- package/src/domains/middleware/memory-step-endpoint.ts +71 -0
- package/src/domains/observability/background-memory-usage.ts +140 -0
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/index.ts +7 -0
- package/src/domains/observability/out-of-turn-usage.ts +51 -2
- package/src/domains/observability/trace-store.ts +192 -2
- package/src/domains/prompts/compiler.ts +100 -13
- package/src/domains/prompts/contract.ts +3 -5
- package/src/domains/providers/endpoint-capacity.ts +96 -0
- package/src/domains/providers/extension.ts +30 -2
- package/src/domains/providers/index.ts +10 -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/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/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/target-descriptor.ts +2 -0
- package/src/domains/resources/common-loader.ts +3 -0
- package/src/domains/resources/prompts/loader.ts +184 -17
- package/src/domains/safety/call-target.ts +52 -0
- package/src/domains/safety/policy-engine.ts +5 -5
- package/src/domains/safety/run-effects.ts +96 -2
- package/src/domains/safety/scope.ts +7 -12
- 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/engine/acp/adapter.ts +18 -3
- package/src/engine/acp/server.ts +4 -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/prompt-templates.ts +18 -1
- package/src/engine/provider-payload.ts +29 -1
- package/src/engine/worker-runtime.ts +6 -3
- package/src/entry/orchestrator.ts +176 -30
- 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 +40 -10
- package/src/interactive/cost-overlay.ts +64 -6
- package/src/interactive/dispatch-board.ts +127 -5
- package/src/interactive/fleet-run-preview.ts +41 -15
- package/src/interactive/handoff-round.ts +41 -2
- package/src/interactive/interactive-application.ts +24 -1
- package/src/interactive/interactive-event-projection.ts +14 -0
- package/src/interactive/interactive-input-runtime.ts +8 -0
- package/src/interactive/interactive-presentation.ts +4 -0
- package/src/interactive/interactive-shell.ts +20 -17
- package/src/interactive/interactive-slash-runtime.ts +27 -4
- package/src/interactive/memory-overlay.ts +8 -0
- package/src/interactive/mutation-preview.ts +295 -0
- package/src/interactive/overlay-general-openers.ts +16 -0
- package/src/interactive/overlay-key-routing.ts +38 -0
- package/src/interactive/overlay-lifecycle.ts +38 -5
- package/src/interactive/overlay-permission-lifecycle.ts +22 -2
- package/src/interactive/overlay-session-lifecycle.ts +73 -9
- package/src/interactive/overlays/ask-user.ts +91 -19
- package/src/interactive/overlays/help-reference.ts +4 -0
- package/src/interactive/overlays/prompts.ts +11 -1
- package/src/interactive/overlays/settings.ts +176 -48
- 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/tool-execution.ts +4 -0
- package/src/interactive/side-question.ts +58 -1
- package/src/interactive/slash-commands.ts +7 -2
- 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/terminal-lease.ts +2 -0
- package/src/interactive/turn-context.ts +299 -31
- 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 +42 -9
- package/src/interactive/view/view-overlay.ts +43 -6
- package/src/interactive/worker-receipts.ts +14 -2
- package/src/interactive/worker-stream.ts +8 -0
- package/src/tools/ask-user.ts +43 -2
- package/src/tools/dispatch-admission.ts +12 -13
- package/src/tools/dispatch-arguments.ts +27 -0
- package/src/tools/dispatch-plan.ts +46 -9
- package/src/tools/dispatch-runner.ts +48 -13
- package/src/tools/dispatch-scout.ts +1 -1
- package/src/tools/monitor.ts +13 -0
- package/src/tools/registry.ts +16 -0
- package/src/tools/worker-evidence.ts +19 -13
- package/src/worker/spec-contract.ts +2 -1
- package/dist/chunk-AOCYTWAV.js +0 -449
- package/dist/chunk-HWUFFB6L.js +0 -83
- package/dist/chunk-R346GLFC.js +0 -31
- package/dist/chunk-ZGH7FGS5.js +0 -1079
- package/dist/doctor-RN4YKO2X.js +0 -87
- package/dist/eval-RUBJVSNQ.js +0 -2557
|
@@ -21,6 +21,7 @@ import type { FleetCommandRegistry } from "../agents/fleet-commands.js";
|
|
|
21
21
|
import type { FleetContract } from "../agents/fleet-contract.js";
|
|
22
22
|
import { resultContractAuthorship } from "../agents/result-contract.js";
|
|
23
23
|
import type { AgentSpec } from "../agents/spec.js";
|
|
24
|
+
import { claimAssignmentVerdict, recordAssignmentAttempt, settleStoredAssignment } from "./assignment-store.js";
|
|
24
25
|
import { runCodeStep } from "./code-step.js";
|
|
25
26
|
import { codeStepDir, writeCodeStepRecord } from "./code-step-store.js";
|
|
26
27
|
import type { DispatchContract, DispatchRequest } from "./contract.js";
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
import { verifyReceiptIntegrity } from "./receipt-integrity.js";
|
|
46
47
|
import { type FleetRunRecord, writeFleetRun } from "./state.js";
|
|
47
48
|
import type { RunReceipt } from "./types.js";
|
|
49
|
+
import type { WriteBoundaryAttribution } from "./write-boundary.js";
|
|
48
50
|
import { createWriteBoundaryEnforcer } from "./write-boundary-enforcer.js";
|
|
49
51
|
|
|
50
52
|
/** Owner id for a plan with no model runs; it holds nothing to release. */
|
|
@@ -247,13 +249,66 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
247
249
|
dynamicPlans: [],
|
|
248
250
|
};
|
|
249
251
|
await writeFleetRun(fleetRunRecord);
|
|
252
|
+
// Every step of this run dispatches under `fleetRootId` as its lineage root,
|
|
253
|
+
// so every agent step also settles the assignment row of that id. One step is
|
|
254
|
+
// not the run, and letting the last one to finish write the row reported a
|
|
255
|
+
// green step of a run that aborted at step 2 of 7 as `succeeded`. The run
|
|
256
|
+
// claims the verdict here and answers for itself at the end.
|
|
257
|
+
await claimAssignmentVerdict(fleetRootId, "fleet");
|
|
258
|
+
/** File one step's terminal run id, whichever kind produced it. */
|
|
259
|
+
const fileStepAttempt = (terminalRunId: string): Promise<unknown> =>
|
|
260
|
+
recordAssignmentAttempt(fleetRootId, terminalRunId);
|
|
261
|
+
/**
|
|
262
|
+
* The run's own word on its ledger row. A settle that cannot be written
|
|
263
|
+
* leaves the row `running`, which startup reconciliation resolves to failed,
|
|
264
|
+
* so a lost write never becomes a false success.
|
|
265
|
+
*/
|
|
266
|
+
const settleFleetAssignment = (cleanRun: boolean): Promise<unknown> =>
|
|
267
|
+
settleStoredAssignment(
|
|
268
|
+
fleetRootId,
|
|
269
|
+
fleetRunRecord.steps.at(-1)?.result.terminalRunId ?? fleetRootId,
|
|
270
|
+
cleanRun ? "succeeded" : "failed",
|
|
271
|
+
"fleet",
|
|
272
|
+
).catch(() => undefined);
|
|
250
273
|
const boundaryEnforcer = createWriteBoundaryEnforcer({
|
|
251
274
|
root: workspaceRoot,
|
|
252
275
|
rootId: fleetRootId,
|
|
253
276
|
boundaryFor: (stepId) => livePlan.steps.find((step) => step.id === stepId)?.writes,
|
|
277
|
+
recordedWritesFor: (stepId) => {
|
|
278
|
+
const step = livePlan.steps.find((entry) => entry.id === stepId);
|
|
279
|
+
// A code step runs a registered command in a subprocess. Nothing
|
|
280
|
+
// enumerates what that command wrote, so the step contributes no record
|
|
281
|
+
// and its window falls back to blaming the whole diff.
|
|
282
|
+
if (step === undefined) return null;
|
|
283
|
+
if (step.kind !== "agent") {
|
|
284
|
+
return {
|
|
285
|
+
recorded: [],
|
|
286
|
+
complete: false,
|
|
287
|
+
downgrades: [
|
|
288
|
+
{
|
|
289
|
+
reason: "code_step_untracked",
|
|
290
|
+
tool: null,
|
|
291
|
+
toolCallId: null,
|
|
292
|
+
runId: null,
|
|
293
|
+
stepId,
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
} satisfies WriteBoundaryAttribution;
|
|
297
|
+
}
|
|
298
|
+
const receipt = receiptsByStep.get(stepId);
|
|
299
|
+
if (receipt === undefined) return null;
|
|
300
|
+
if (dispatch.observedRunWriteAttribution !== undefined) {
|
|
301
|
+
return dispatch.observedRunWriteAttribution(receipt.runId);
|
|
302
|
+
}
|
|
303
|
+
const recorded = dispatch.observedRunWrites?.(receipt.runId) ?? null;
|
|
304
|
+
return recorded === null ? null : { recorded, complete: true, downgrades: [] };
|
|
305
|
+
},
|
|
254
306
|
onVerdict(verdict, path) {
|
|
255
|
-
|
|
256
|
-
|
|
307
|
+
// Concurrent changes are reported too. The window did not fail for them
|
|
308
|
+
// and nothing was touched, and an operator whose file changed under a
|
|
309
|
+
// running fleet should hear it from the fleet.
|
|
310
|
+
if (verdict.detail === null) return;
|
|
311
|
+
notice(`write boundary ${verdict.window}: ${verdict.detail} record=${path}`, "write-boundary");
|
|
257
312
|
},
|
|
258
313
|
});
|
|
259
314
|
const receipts: RunReceipt[] = [];
|
|
@@ -285,6 +340,7 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
285
340
|
costUsd: receiptsByStep.get(stepId)?.costUsd ?? 0,
|
|
286
341
|
result: replayedResult,
|
|
287
342
|
});
|
|
343
|
+
await fileStepAttempt(replayedResult.terminalRunId);
|
|
288
344
|
}
|
|
289
345
|
const planStep = (stepId: string) => livePlan.steps.find((entry) => entry.id === stepId);
|
|
290
346
|
|
|
@@ -322,6 +378,9 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
322
378
|
try {
|
|
323
379
|
result = await executePlan(livePlan, {
|
|
324
380
|
preflight(step) {
|
|
381
|
+
// The fleet write boundary is deliberately enforced after the step. The enforcer in
|
|
382
|
+
// write-boundary-enforcer.ts snapshots and verifies the step window. Pre-emptive
|
|
383
|
+
// confinement for declared commands would require a command sandbox, which does not exist.
|
|
325
384
|
const request: DispatchRequest = {
|
|
326
385
|
agentId: step.agentId,
|
|
327
386
|
executionRole: step.executionRole,
|
|
@@ -372,6 +431,9 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
372
431
|
if (step.planParentId !== undefined && parentReceipt === undefined) {
|
|
373
432
|
throw new Error(`fleet dynamic step '${step.id}' has no terminal plan-step receipt`);
|
|
374
433
|
}
|
|
434
|
+
// The fleet write boundary is deliberately enforced after the step. The enforcer in
|
|
435
|
+
// write-boundary-enforcer.ts snapshots and verifies the step window. Pre-emptive
|
|
436
|
+
// confinement for declared commands would require a command sandbox, which does not exist.
|
|
375
437
|
const request: DispatchRequest = {
|
|
376
438
|
agentId: step.agentId,
|
|
377
439
|
executionRole: step.executionRole,
|
|
@@ -662,7 +724,7 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
662
724
|
cancel: (assignmentId) => dispatch.abort(assignmentId),
|
|
663
725
|
release: (ownerId) => {
|
|
664
726
|
if (ownerId === NO_WORKER_RESERVATION) return;
|
|
665
|
-
dispatch.reservations?.
|
|
727
|
+
dispatch.reservations?.release(ownerId);
|
|
666
728
|
},
|
|
667
729
|
releaseUnconsumed: (ownerId) => {
|
|
668
730
|
if (ownerId === NO_WORKER_RESERVATION) return;
|
|
@@ -671,6 +733,11 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
671
733
|
onStepSettled: async (step, stepResult) => {
|
|
672
734
|
fleetRunRecord.steps.push({ stepId: step.id, result: stepResult });
|
|
673
735
|
await writeFleetRun(fleetRunRecord);
|
|
736
|
+
// The scheduler settles both kinds of step here, so this is where a
|
|
737
|
+
// deterministic step enters the assignment: a code step's `code-*` run
|
|
738
|
+
// id reads exactly like an agent receipt id, and its evidence sits under
|
|
739
|
+
// `code-steps/<fleetRootId>/`.
|
|
740
|
+
await fileStepAttempt(stepResult.terminalRunId);
|
|
674
741
|
},
|
|
675
742
|
spliceAfter(currentPlan, step, stepResult) {
|
|
676
743
|
if (stepResult.delegationPlan === undefined) return null;
|
|
@@ -712,6 +779,9 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
712
779
|
} catch (error) {
|
|
713
780
|
fleetRunRecord.endedAt = new Date().toISOString();
|
|
714
781
|
await writeFleetRun(fleetRunRecord);
|
|
782
|
+
// A run the scheduler could not carry to the end never reached a verdict,
|
|
783
|
+
// and a fleet that threw is not a fleet that worked.
|
|
784
|
+
await settleFleetAssignment(false);
|
|
715
785
|
throw error;
|
|
716
786
|
}
|
|
717
787
|
fleetRunRecord.endedAt = new Date().toISOString();
|
|
@@ -723,6 +793,10 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
723
793
|
const required = livePlan.steps.filter((step) => step.loop === undefined && !result.unneeded.includes(step.id));
|
|
724
794
|
const failedLoops = result.loops.filter((loop) => !loop.resolved);
|
|
725
795
|
const succeededStepCount = required.filter((step) => result.results.get(step.id)?.succeeded === true).length;
|
|
796
|
+
// A step a stop policy left unrun is counted but never succeeded, so a run
|
|
797
|
+
// that halted early can never reach the required count.
|
|
798
|
+
const cleanRun = failedLoops.length === 0 && result.skipped.length === 0 && succeededStepCount === required.length;
|
|
799
|
+
await settleFleetAssignment(cleanRun);
|
|
726
800
|
return {
|
|
727
801
|
rootId: fleetRootId,
|
|
728
802
|
planHash: input.plan.hash,
|
|
@@ -732,6 +806,6 @@ export async function executeFleetRun(input: ExecuteFleetRunInput): Promise<Flee
|
|
|
732
806
|
requiredStepCount: required.length,
|
|
733
807
|
succeededStepCount,
|
|
734
808
|
resolvedLoopCount: result.loops.length - failedLoops.length,
|
|
735
|
-
cleanRun
|
|
809
|
+
cleanRun,
|
|
736
810
|
};
|
|
737
811
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Bounded role prompts shared by dispatch topology construction and ACP admission. */
|
|
2
2
|
|
|
3
|
+
import { COUNCIL_BALLOT_SHAPE, COUNCIL_BALLOT_VERDICT_MAX_BYTES } from "../agents/result-contract.js";
|
|
4
|
+
|
|
3
5
|
export const REVIEWER_GATE_PROMPT = [
|
|
4
6
|
"You are a strict, read-only reviewer of one implementation run.",
|
|
5
7
|
"Inspect the supplied result and repository state with read-only tools.",
|
|
@@ -26,6 +28,42 @@ export const COUNCIL_JUDGE_PROMPT = [
|
|
|
26
28
|
'End with a JSON object only: {"verdict":"...","text":"the supported synthesis"}.',
|
|
27
29
|
].join("\n");
|
|
28
30
|
|
|
31
|
+
/**
|
|
32
|
+
* What a council member is told when the synthesis is `vote`.
|
|
33
|
+
*
|
|
34
|
+
* The tally is a strict majority over the members' `verdict` fields, and until
|
|
35
|
+
* this directive existed nothing ever asked a member for one (#230). It rides
|
|
36
|
+
* on the member's task rather than on a system prompt, so the seated recipe
|
|
37
|
+
* keeps its own persona: a council's point is running *that* agent across
|
|
38
|
+
* several targets, and replacing its body with a ballot prompt would run a
|
|
39
|
+
* different agent under the same name. The matching `council-ballot` contract
|
|
40
|
+
* travels with it as a `resultContractOverride`, so the postcondition the run
|
|
41
|
+
* seals is the one this text asks for, and a member that answers in its
|
|
42
|
+
* recipe's shape instead gets the ordinary bounded repair rounds rather than a
|
|
43
|
+
* silent absence from the tally.
|
|
44
|
+
*
|
|
45
|
+
* The precedence line is not decoration. A recipe body states its own result
|
|
46
|
+
* shape (`researcher` asks for findings), so without it the member holds two
|
|
47
|
+
* contradictory instructions and small local models resolve the conflict by
|
|
48
|
+
* burying a verdict inside the recipe's shape, which is exactly what the 0.3.7
|
|
49
|
+
* release test observed and read as correct behavior.
|
|
50
|
+
*/
|
|
51
|
+
export const COUNCIL_VOTE_MEMBER_DIRECTIVE = [
|
|
52
|
+
"This council round is a vote. Do the work the task asks for, then cast one ballot on it.",
|
|
53
|
+
`The verdict is a short comparable token the other members can match exactly, such as "yes", "no", "keep", or the name of an option you were given. It must be a single line of at most ${COUNCIL_BALLOT_VERDICT_MAX_BYTES} bytes and is lower-cased before the tally. Anything longer is reasoning: put that in text, along with the evidence behind it.`,
|
|
54
|
+
"Your recipe's own result shape does not apply to this run. The council reads the ballot and nothing else.",
|
|
55
|
+
`End with a JSON object only: ${COUNCIL_BALLOT_SHAPE}`,
|
|
56
|
+
].join("\n");
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The task a council member is given under `synthesis: "vote"`. Plan admission
|
|
60
|
+
* composes it here once, then the runner reuses the task pinned by that plan so
|
|
61
|
+
* the approval artifact shows the exact ask the member receives.
|
|
62
|
+
*/
|
|
63
|
+
export function renderCouncilVoteMemberTask(originalTask: string): string {
|
|
64
|
+
return [originalTask, COUNCIL_VOTE_MEMBER_DIRECTIVE].join("\n\n");
|
|
65
|
+
}
|
|
66
|
+
|
|
29
67
|
/**
|
|
30
68
|
* Posture a compete candidate runs under. Candidates otherwise differ only by
|
|
31
69
|
* worktree, and identical agents produce correlated output, so each candidate
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure heartbeat watchdog classifier (Phase 6 slice 3).
|
|
3
3
|
*
|
|
4
|
-
* Maps a last-seen
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Maps a last-seen monotonic stamp to one of three states. The dispatch domain
|
|
5
|
+
* drives this on each scheduler tick; the orchestrator uses `stale` to surface
|
|
6
|
+
* a warning in the UI and `dead` to reap a subprocess whose event stream has
|
|
7
|
+
* gone quiet for too long.
|
|
8
8
|
*
|
|
9
|
-
* No I/O, no clocks of its own. Callers pass
|
|
10
|
-
* and easy to test.
|
|
9
|
+
* No I/O, no clocks of its own. Callers pass both monotonic values to keep the
|
|
10
|
+
* function pure and easy to test.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
export interface HeartbeatSpec {
|
|
@@ -17,10 +17,34 @@ export interface HeartbeatSpec {
|
|
|
17
17
|
|
|
18
18
|
export type HeartbeatStatus = "alive" | "stale" | "dead";
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Mutable heartbeat facts shared by a transport and the dispatch watchdog.
|
|
22
|
+
* `current` is an absolute wall-clock instant for display and persistence.
|
|
23
|
+
* `monotonic` is from this process's monotonic clock and is the only value
|
|
24
|
+
* liveness code may compare with a later clock read.
|
|
25
|
+
*
|
|
26
|
+
* The monotonic field is optional only for injected legacy test handles. Real
|
|
27
|
+
* transports always provide it. Treating an old handle's `current` as its
|
|
28
|
+
* monotonic stamp preserves the structural test seam without reintroducing a
|
|
29
|
+
* subtraction between two wall-clock reads in the product path.
|
|
30
|
+
*/
|
|
31
|
+
export interface HeartbeatStamp {
|
|
32
|
+
current: number;
|
|
33
|
+
monotonic?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
20
36
|
export const DEFAULT_HEARTBEAT_SPEC: HeartbeatSpec = { windowMs: 5000, graceMs: 10000 };
|
|
21
37
|
|
|
22
|
-
export function
|
|
23
|
-
|
|
38
|
+
export function heartbeatMonotonicAt(heartbeat: HeartbeatStamp): number {
|
|
39
|
+
return heartbeat.monotonic ?? heartbeat.current;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function classifyHeartbeat(
|
|
43
|
+
heartbeatMonotonicAt: number,
|
|
44
|
+
monotonicNow: number,
|
|
45
|
+
spec: HeartbeatSpec,
|
|
46
|
+
): HeartbeatStatus {
|
|
47
|
+
const age = monotonicNow - heartbeatMonotonicAt;
|
|
24
48
|
if (age <= spec.windowMs) return "alive";
|
|
25
49
|
if (age <= spec.windowMs + spec.graceMs) return "stale";
|
|
26
50
|
return "dead";
|
|
@@ -21,7 +21,7 @@ export type {
|
|
|
21
21
|
AttemptRef,
|
|
22
22
|
DispatchAssignment,
|
|
23
23
|
} from "./assignment.js";
|
|
24
|
-
export type { DurableAssignmentRecord } from "./assignment-store.js";
|
|
24
|
+
export type { AssignmentVerdictOwner, DurableAssignmentRecord } from "./assignment-store.js";
|
|
25
25
|
export type { CodeStepOutcome, CodeStepRecord, CodeStepRunInput } from "./code-step.js";
|
|
26
26
|
export {
|
|
27
27
|
canonicalCodeReport,
|
|
@@ -160,11 +160,16 @@ export {
|
|
|
160
160
|
} from "./validation.js";
|
|
161
161
|
export type {
|
|
162
162
|
WorkspaceSnapshot,
|
|
163
|
+
WriteBoundaryAttribution,
|
|
164
|
+
WriteBoundaryAttributionDowngrade,
|
|
165
|
+
WriteBoundaryAttributionDowngradeReason,
|
|
163
166
|
WriteBoundaryStatus,
|
|
164
167
|
WriteBoundaryVerdict,
|
|
165
168
|
} from "./write-boundary.js";
|
|
166
169
|
export {
|
|
170
|
+
assertWriteBoundaryVisibleToGit,
|
|
167
171
|
captureWorkspaceSnapshot,
|
|
172
|
+
describeWriteBoundaryAttributionDowngrade,
|
|
168
173
|
diffWorkspace,
|
|
169
174
|
enforceWriteBoundary,
|
|
170
175
|
WRITE_BOUNDARY_VIOLATION_REASON,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { DispatchIntent } from "./intent.js";
|
|
2
|
+
|
|
3
|
+
/** Render intent fields that describe required results rather than observed facts. */
|
|
4
|
+
export function renderDispatchIntentRequirements(intent: DispatchIntent | undefined): string | null {
|
|
5
|
+
if (intent === undefined || (intent.expectedOutputs.length === 0 && intent.verification.length === 0)) return null;
|
|
6
|
+
const lines = [
|
|
7
|
+
"# Declared Result Requirements",
|
|
8
|
+
"These entries are requirements to satisfy and verify. They are not evidence that an output exists or a check passed.",
|
|
9
|
+
];
|
|
10
|
+
if (intent.expectedOutputs.length > 0) {
|
|
11
|
+
lines.push("", "Expected outputs:", ...intent.expectedOutputs.map((output) => `- ${output}`));
|
|
12
|
+
}
|
|
13
|
+
if (intent.verification.length > 0) {
|
|
14
|
+
lines.push(
|
|
15
|
+
"",
|
|
16
|
+
"Verification requirements:",
|
|
17
|
+
...intent.verification.map(
|
|
18
|
+
(entry) => `- ${entry.check} must pass within its declared timeout of ${entry.timeoutMs}ms`,
|
|
19
|
+
),
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return lines.join("\n");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Build the reviewer assignment from the same requirements the builder received. */
|
|
26
|
+
export function renderDispatchReviewerTask(
|
|
27
|
+
originalTask: string,
|
|
28
|
+
builderRunId: string,
|
|
29
|
+
cycle: number,
|
|
30
|
+
intent: DispatchIntent | undefined,
|
|
31
|
+
): string {
|
|
32
|
+
const requirements = renderDispatchIntentRequirements(intent);
|
|
33
|
+
return [
|
|
34
|
+
`Review the work of builder run ${builderRunId} (review cycle ${cycle}).`,
|
|
35
|
+
"The builder's final answer is provided as input data; verify it against the workspace, do not trust it blindly.",
|
|
36
|
+
"Original task the builder was given:",
|
|
37
|
+
originalTask,
|
|
38
|
+
...(requirements === null ? [] : [requirements]),
|
|
39
|
+
].join("\n\n");
|
|
40
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { normalizePathBoundaryEntry, PATH_BOUNDARY_MAX_ENTRIES, PathBoundaryError } from "../../core/path-boundary.js";
|
|
3
|
+
import { type DispatchPathProvenanceEntry, declaredIntentPathProvenance } from "./path-scope.js";
|
|
2
4
|
|
|
3
|
-
export const DISPATCH_INTENT_PATH_LIST_CAP =
|
|
5
|
+
export const DISPATCH_INTENT_PATH_LIST_CAP = PATH_BOUNDARY_MAX_ENTRIES;
|
|
4
6
|
export const DISPATCH_INTENT_PATH_ENTRY_BYTES_CAP = 512;
|
|
5
7
|
export const DISPATCH_INTENT_VERIFICATION_CAP = 8;
|
|
6
8
|
export const DISPATCH_INTENT_TIMEOUT_MIN_MS = 1_000;
|
|
@@ -11,10 +13,12 @@ export interface DispatchIntentVerification {
|
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export interface DispatchIntent {
|
|
14
|
-
version:
|
|
16
|
+
version: 2;
|
|
15
17
|
readRoots: string[];
|
|
16
18
|
writeRoots: string[];
|
|
17
19
|
relevantPaths: string[];
|
|
20
|
+
/** Integrity-sealed source and confidence for every policy-bearing path. */
|
|
21
|
+
pathProvenance: DispatchPathProvenanceEntry[];
|
|
18
22
|
expectedOutputs: string[];
|
|
19
23
|
verification: DispatchIntentVerification[];
|
|
20
24
|
}
|
|
@@ -42,7 +46,7 @@ function fail(reason: string, message: string): DispatchIntentNormalizationResul
|
|
|
42
46
|
return { ok: false, reason, message };
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
function
|
|
49
|
+
function checkedPathText(value: unknown, field: string, index: number): string | DispatchIntentNormalizationResult {
|
|
46
50
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
47
51
|
return fail("intent_path_malformed", `${field}[${index}] must be a non-empty repository-relative POSIX path`);
|
|
48
52
|
}
|
|
@@ -53,6 +57,42 @@ function normalizePathEntry(value: unknown, field: string, index: number): strin
|
|
|
53
57
|
`${field}[${index}] exceeds the ${DISPATCH_INTENT_PATH_ENTRY_BYTES_CAP}-byte cap`,
|
|
54
58
|
);
|
|
55
59
|
}
|
|
60
|
+
return trimmed;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function normalizeScopePathEntry(
|
|
64
|
+
value: unknown,
|
|
65
|
+
field: string,
|
|
66
|
+
index: number,
|
|
67
|
+
): string | DispatchIntentNormalizationResult {
|
|
68
|
+
const checked = checkedPathText(value, field, index);
|
|
69
|
+
if (typeof checked !== "string") return checked;
|
|
70
|
+
try {
|
|
71
|
+
return normalizePathBoundaryEntry(checked);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (error instanceof PathBoundaryError) {
|
|
74
|
+
if (error.code === "absolute") {
|
|
75
|
+
return fail("intent_path_absolute", `${field}[${index}] must be a repository-relative POSIX path`);
|
|
76
|
+
}
|
|
77
|
+
if (error.code === "parent") {
|
|
78
|
+
return fail("intent_path_escapes_root", `${field}[${index}] escapes the repository root`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return fail(
|
|
82
|
+
"intent_path_malformed",
|
|
83
|
+
`${field}[${index}] does not follow the repository path boundary grammar: ${error instanceof Error ? error.message : String(error)}`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function normalizeExpectedOutputEntry(
|
|
89
|
+
value: unknown,
|
|
90
|
+
field: string,
|
|
91
|
+
index: number,
|
|
92
|
+
): string | DispatchIntentNormalizationResult {
|
|
93
|
+
const checked = checkedPathText(value, field, index);
|
|
94
|
+
if (typeof checked !== "string") return checked;
|
|
95
|
+
const trimmed = checked;
|
|
56
96
|
if (trimmed.includes("\\") || path.posix.isAbsolute(trimmed) || path.win32.isAbsolute(trimmed)) {
|
|
57
97
|
return fail("intent_path_absolute", `${field}[${index}] must be a repository-relative POSIX path`);
|
|
58
98
|
}
|
|
@@ -66,7 +106,15 @@ function normalizePathEntry(value: unknown, field: string, index: number): strin
|
|
|
66
106
|
return normalized;
|
|
67
107
|
}
|
|
68
108
|
|
|
69
|
-
function normalizePathList(
|
|
109
|
+
function normalizePathList(
|
|
110
|
+
value: unknown,
|
|
111
|
+
field: string,
|
|
112
|
+
normalizeEntry: (
|
|
113
|
+
value: unknown,
|
|
114
|
+
field: string,
|
|
115
|
+
index: number,
|
|
116
|
+
) => string | DispatchIntentNormalizationResult = normalizeScopePathEntry,
|
|
117
|
+
): string[] | DispatchIntentNormalizationResult {
|
|
70
118
|
if (value === undefined) return [];
|
|
71
119
|
if (!Array.isArray(value)) return fail("intent_path_malformed", `${field} must be an array`);
|
|
72
120
|
if (value.length > DISPATCH_INTENT_PATH_LIST_CAP) {
|
|
@@ -74,7 +122,7 @@ function normalizePathList(value: unknown, field: string): string[] | DispatchIn
|
|
|
74
122
|
}
|
|
75
123
|
const normalized: string[] = [];
|
|
76
124
|
for (const [index, entry] of value.entries()) {
|
|
77
|
-
const result =
|
|
125
|
+
const result = normalizeEntry(entry, field, index);
|
|
78
126
|
if (typeof result !== "string") return result;
|
|
79
127
|
normalized.push(result);
|
|
80
128
|
}
|
|
@@ -82,10 +130,26 @@ function normalizePathList(value: unknown, field: string): string[] | DispatchIn
|
|
|
82
130
|
}
|
|
83
131
|
|
|
84
132
|
export function isDispatchIntent(value: unknown): value is DispatchIntent {
|
|
85
|
-
if (!isRecord(value) || value.version !==
|
|
133
|
+
if (!isRecord(value) || value.version !== 2) return false;
|
|
86
134
|
for (const field of ["readRoots", "writeRoots", "relevantPaths", "expectedOutputs"] as const) {
|
|
87
135
|
if (!Array.isArray(value[field]) || !value[field].every((entry) => typeof entry === "string")) return false;
|
|
88
136
|
}
|
|
137
|
+
const readRoots = value.readRoots as string[];
|
|
138
|
+
const writeRoots = value.writeRoots as string[];
|
|
139
|
+
const relevantPaths = value.relevantPaths as string[];
|
|
140
|
+
if (
|
|
141
|
+
!Array.isArray(value.pathProvenance) ||
|
|
142
|
+
JSON.stringify(value.pathProvenance) !==
|
|
143
|
+
JSON.stringify(
|
|
144
|
+
declaredIntentPathProvenance({
|
|
145
|
+
readRoots,
|
|
146
|
+
writeRoots,
|
|
147
|
+
relevantPaths,
|
|
148
|
+
}),
|
|
149
|
+
)
|
|
150
|
+
) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
89
153
|
return (
|
|
90
154
|
Array.isArray(value.verification) &&
|
|
91
155
|
value.verification.every(
|
|
@@ -115,7 +179,11 @@ export function normalizeDispatchIntent(
|
|
|
115
179
|
if (!Array.isArray(writeRoots)) return writeRoots;
|
|
116
180
|
const relevantPaths = normalizePathList(raw.relevant_paths, "intent.relevant_paths");
|
|
117
181
|
if (!Array.isArray(relevantPaths)) return relevantPaths;
|
|
118
|
-
const expectedOutputs = normalizePathList(
|
|
182
|
+
const expectedOutputs = normalizePathList(
|
|
183
|
+
raw.expected_outputs,
|
|
184
|
+
"intent.expected_outputs",
|
|
185
|
+
normalizeExpectedOutputEntry,
|
|
186
|
+
);
|
|
119
187
|
if (!Array.isArray(expectedOutputs)) return expectedOutputs;
|
|
120
188
|
const rawVerification = raw.verification ?? [];
|
|
121
189
|
if (!Array.isArray(rawVerification)) {
|
|
@@ -154,6 +222,14 @@ export function normalizeDispatchIntent(
|
|
|
154
222
|
}
|
|
155
223
|
return {
|
|
156
224
|
ok: true,
|
|
157
|
-
intent: {
|
|
225
|
+
intent: {
|
|
226
|
+
version: 2,
|
|
227
|
+
readRoots,
|
|
228
|
+
writeRoots,
|
|
229
|
+
relevantPaths,
|
|
230
|
+
pathProvenance: declaredIntentPathProvenance({ readRoots, writeRoots, relevantPaths }),
|
|
231
|
+
expectedOutputs,
|
|
232
|
+
verification,
|
|
233
|
+
},
|
|
158
234
|
};
|
|
159
235
|
}
|
|
@@ -172,6 +172,11 @@ function sealedEnvelopeFor(runId: string): RunEnvelope | null {
|
|
|
172
172
|
* whole orchestrator downtime, which is not a measurement of anything. The
|
|
173
173
|
* last heartbeat is the honest bound; a row that never heartbeat has only its
|
|
174
174
|
* own start, which reads as a zero-length run rather than an invented one.
|
|
175
|
+
*
|
|
176
|
+
* A restart has no shared monotonic origin with the process that owned the
|
|
177
|
+
* worker, so recovery never estimates heartbeat age. It first adjudicates the
|
|
178
|
+
* host-scoped pid and uses the persisted wall-clock heartbeat only as this
|
|
179
|
+
* display/evidence bound after that process is known to be gone.
|
|
175
180
|
*/
|
|
176
181
|
function closeAbandonedRows(ledger: Ledger): { closed: number; sealed: number } {
|
|
177
182
|
let closed = 0;
|