@iowarp/clio-coder 0.3.6 → 0.3.8
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 +59 -0
- package/README.md +22 -6
- package/dist/{acp-2BEHC4DL.js → acp-U67UHUK2.js} +14 -14
- package/dist/{agents-LNNFTM53.js → agents-YU6SGALZ.js} +42 -35
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-KXXFI2VS.js → auth-5ZPJOIVG.js} +32 -24
- package/dist/builtins-C6JMZVV6.js +17 -0
- package/dist/{chunk-E25LMLRW.js → chunk-26LEYJZH.js} +2 -2
- package/dist/{chunk-TSHXZTOQ.js → chunk-2HEJ2F35.js} +5 -5
- package/dist/{chunk-PBTHKCPN.js → chunk-2HFZQUHL.js} +7 -7
- package/dist/{chunk-FO5ZOVUY.js → chunk-3BINW3FP.js} +5 -5
- package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
- package/dist/{chunk-CKXWIANG.js → chunk-4SPRNWDE.js} +18 -16
- package/dist/{chunk-E2ER4LJF.js → chunk-5C3AQNDW.js} +25 -1
- package/dist/{chunk-XF5N4U5A.js → chunk-5DHKRSMQ.js} +9 -8
- package/dist/{chunk-43AOLP7E.js → chunk-5FR74PWO.js} +2 -1
- package/dist/{chunk-EKY57CSP.js → chunk-5H3GB5BO.js} +68 -772
- package/dist/{chunk-6XXKFVSN.js → chunk-5Q2VVUKB.js} +4 -4
- package/dist/{chunk-DJVECN66.js → chunk-7RFXX52T.js} +295 -3705
- package/dist/{chunk-ZXF4XRKW.js → chunk-7RGZWPB6.js} +158 -8
- package/dist/{chunk-FYYLNIL5.js → chunk-A2NJGIB3.js} +2 -2
- package/dist/{chunk-XXQNGV4M.js → chunk-A3WNZD3P.js} +548 -72
- package/dist/{chunk-VEZEGCGW.js → chunk-B5CSFE7B.js} +23 -21
- package/dist/{chunk-2SFS6XQE.js → chunk-DGSYXYMX.js} +3 -2
- package/dist/chunk-DR52UMZW.js +21 -0
- package/dist/{chunk-ZWLZP4ZT.js → chunk-DYIM5TJT.js} +98 -12
- package/dist/{chunk-QKMUKYO7.js → chunk-E77JEWSD.js} +270 -125
- package/dist/{chunk-LYF7OHWH.js → chunk-EMYUUSFG.js} +12 -467
- package/dist/{chunk-4VP4KH3K.js → chunk-EQ63NRB7.js} +8 -8
- package/dist/chunk-FBVTI2TJ.js +518 -0
- package/dist/{chunk-R46L2BIR.js → chunk-FHJEP5SW.js} +19 -25
- package/dist/{chunk-WR67VIZY.js → chunk-GN57SG4G.js} +66 -8
- package/dist/{chunk-RD5U66HV.js → chunk-GPIEI3LY.js} +9 -9
- package/dist/{chunk-PCZJO5TI.js → chunk-GU2UIAFZ.js} +13 -178
- package/dist/chunk-GWS3VEIW.js +195 -0
- package/dist/chunk-H7IXIC72.js +103 -0
- package/dist/{chunk-3BPUFZDL.js → chunk-HLE42MG7.js} +3 -3
- package/dist/{chunk-24I7BN55.js → chunk-IFBNV6H6.js} +3 -3
- package/dist/{chunk-QNQHSOLF.js → chunk-IGWKHNIQ.js} +114 -55
- package/dist/chunk-IIZWH4XA.js +172 -0
- package/dist/{chunk-AD2SYQYC.js → chunk-IJ7RPIYJ.js} +124 -6
- package/dist/chunk-J3YUBZWY.js +382 -0
- package/dist/{chunk-5JGRAMKL.js → chunk-JOZYP4GM.js} +8 -6
- package/dist/{chunk-OH3TOQTB.js → chunk-K4XHGFR5.js} +751 -15
- package/dist/{chunk-EYPA3EGJ.js → chunk-KTYTFRMB.js} +178 -14
- package/dist/chunk-LU7P4LHA.js +33 -0
- package/dist/chunk-ME6CCNFO.js +108 -0
- package/dist/chunk-MXKJU4JB.js +1100 -0
- package/dist/{chunk-RY3LY4J5.js → chunk-N22QMJKY.js} +21 -18
- package/dist/chunk-NMPKI6XL.js +3006 -0
- package/dist/chunk-NUGM5KR6.js +165 -0
- package/dist/{chunk-22NAGB7X.js → chunk-P43ETTHK.js} +5 -94
- package/dist/{chunk-NILBFAPG.js → chunk-PMDBGQSJ.js} +2 -2
- package/dist/chunk-PT7HYKEM.js +165 -0
- package/dist/chunk-RVG5JXAL.js +41 -0
- package/dist/{chunk-GEYXPTRF.js → chunk-RWSI4YD7.js} +2 -2
- package/dist/{chunk-4BPJXDWC.js → chunk-TANS5ZJS.js} +35 -19
- package/dist/{verifiers-NCBTHHN2.js → chunk-TB5666IT.js} +67 -324
- package/dist/{chunk-QM3F2GKX.js → chunk-TLQJPP24.js} +7927 -8088
- package/dist/{chunk-G7MUEIGA.js → chunk-TT36MB5S.js} +2 -1
- package/dist/chunk-TTHACPOM.js +961 -0
- package/dist/{chunk-6US73PDB.js → chunk-TYPGUK6W.js} +7 -7
- package/dist/{chunk-MFFY33HR.js → chunk-U6MBIEMB.js} +554 -209
- package/dist/chunk-VAWNZU7Z.js +242 -0
- package/dist/{chunk-IR4CFBFN.js → chunk-VCBR6CU7.js} +12 -12
- package/dist/{chunk-WHJYKASB.js → chunk-VHN4MY6O.js} +2 -2
- package/dist/{chunk-XYDYPRZI.js → chunk-VWZOAB7K.js} +10 -10
- package/dist/{chunk-ZRGEBJ4T.js → chunk-WLFILSD5.js} +48 -48
- package/dist/{chunk-K7T3E2SR.js → chunk-WNIJTQQK.js} +12 -11
- package/dist/{chunk-CYQKWTG3.js → chunk-WSB3FPX7.js} +68 -20
- package/dist/{chunk-KHSFENX2.js → chunk-WWCZ5F23.js} +116 -14
- package/dist/{chunk-XE2VEJHX.js → chunk-WXY7KU3G.js} +2 -2
- package/dist/{chunk-PPAMZ32Z.js → chunk-XK56QHLX.js} +6 -1
- package/dist/{chunk-KOHPCX4K.js → chunk-XWSF374K.js} +5 -5
- package/dist/{chunk-CJUB2JJ2.js → chunk-YS5VLNH5.js} +10 -10
- package/dist/{chunk-ZZMN5OM4.js → chunk-ZNLWCMVZ.js} +2 -2
- package/dist/{chunk-WHGPSPT5.js → chunk-ZVJ5BLO2.js} +2 -2
- package/dist/cli/index.js +33 -31
- package/dist/{clio-M2KGYUFZ.js → clio-QVTYJ57A.js} +10 -10
- package/dist/{code-nav-GQNL7XA6.js → code-nav-FGGFIE7L.js} +5 -5
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-5TTYYX6G.js → components-ZFA3SAER.js} +9 -9
- package/dist/{config-XUUYQIWO.js → config-LW5IJFQN.js} +65 -55
- package/dist/{configure-IHJ7YOMV.js → configure-7XIZCOU4.js} +29 -24
- package/dist/{context-75MIWW3U.js → context-L3WL3X7K.js} +54 -43
- package/dist/{context-ZQ7SIFJV.js → context-N52ZA626.js} +30 -14
- package/dist/{context-74JLXAWD.js → context-Y6Y7QPR6.js} +12 -12
- package/dist/{context-clear-GYKWNUML.js → context-clear-MBQRLSDQ.js} +54 -43
- package/dist/{context-index-SSR5ECNE.js → context-index-HVMFQHK3.js} +5 -5
- package/dist/{context-working-set-UX5KEP4J.js → context-working-set-GS6DSO7F.js} +18 -18
- package/dist/{dispatch-runner-GIJBHNFL.js → dispatch-runner-22ZCNOM3.js} +367 -79
- package/dist/{docs-6FZSCG5B.js → docs-7LQ23DLM.js} +9 -9
- package/dist/{doctor-SVJ5BZCW.js → doctor-M7YEDGAE.js} +27 -23
- package/dist/{eval-CG6LLBLD.js → eval-BEC2WHDA.js} +73 -20
- package/dist/{evidence-ZYFIEN42.js → evidence-REJUMSKM.js} +70 -59
- package/dist/{evolve-QGEXEMDW.js → evolve-PY5ZBA5K.js} +50 -39
- package/dist/{extensions-ADGNCJJD.js → extensions-HVKU65YU.js} +7 -7
- package/dist/{fleet-S5R4ZOQY.js → fleet-7WZEWRFA.js} +236 -377
- package/dist/fleet-commands-UVHWM76J.js +70 -0
- package/dist/fleet-graph-6ULH7PES.js +125 -0
- package/dist/fleet-new-RDVJLHHH.js +48 -0
- package/dist/{fleet-preflight-BHSNPBMH.js → fleet-preflight-J53T6CCE.js} +5 -5
- package/dist/fleet-validate-72PC4SLA.js +79 -0
- package/dist/{init-5DRU55YR.js → init-OG3TPGQG.js} +69 -57
- package/dist/library-CNTMPLRF.js +217 -0
- package/dist/{memory-7YKKR6UC.js → memory-6IS7F275.js} +52 -41
- package/dist/{models-ZPOLRU2C.js → models-ENRJDA5W.js} +37 -31
- package/dist/{monitor-US5F5YGZ.js → monitor-XLDVO7TN.js} +79 -42
- package/dist/{orchestrator-E2AL4T5N.js → orchestrator-6KSPYRHA.js} +4126 -762
- package/dist/{paths-E7KYAQWE.js → paths-DBXMZMDU.js} +6 -6
- package/dist/registry-LG64LTF4.js +11 -0
- package/dist/{reset-KZ652EK6.js → reset-RZ4ER727.js} +12 -12
- package/dist/{run-SRNBKDWD.js → run-Y2CNK5RU.js} +89 -76
- package/dist/{share-CGZE33UP.js → share-A55GYP6Z.js} +37 -13
- package/dist/{skills-S2X4DLY5.js → skills-ALC5J6AT.js} +29 -13
- package/dist/{skills-eval-W2GGIC4R.js → skills-eval-JPBEBYQU.js} +60 -48
- package/dist/support-MIETYA5E.js +38 -0
- package/dist/{targets-54SWINWB.js → targets-VGNXIR3S.js} +46 -36
- package/dist/{terminal-lease-SAIF2OGY.js → terminal-lease-WOBR64YA.js} +4 -4
- package/dist/{uninstall-BVLWXKBT.js → uninstall-ZJF5H5ZN.js} +9 -9
- package/dist/{upgrade-JKAR27XC.js → upgrade-FUSUAGHR.js} +31 -28
- package/dist/{usage-MSAWCLX4.js → usage-N4MKVHKD.js} +140 -68
- package/dist/verifiers-YAWOJ3H2.js +336 -0
- package/dist/{verify-X5HDROLA.js → verify-LTDHYBGY.js} +10 -9
- package/dist/{wiki-generate-GUSOQ6ZP.js → wiki-generate-6M7GHTBJ.js} +75 -62
- package/dist/worker/entry.js +67 -57
- package/docs/README.md +3 -2
- package/docs/acp.md +1 -1
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-versions.md +11 -6
- package/docs/built-in-agents.md +26 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +83 -3
- package/docs/configuration-and-targets.md +86 -4
- package/docs/context-engine.md +1 -1
- package/docs/development-pipeline.md +1 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +3 -3
- package/docs/documentation-guide.md +3 -3
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +74 -10
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +4 -1
- package/docs/extensions-and-sharing.md +6 -2
- package/docs/fleet-demo-runbook.md +2 -2
- package/docs/fleet-dispatch.md +228 -16
- package/docs/git-commit-provenance.md +2 -2
- package/docs/glossary.md +22 -2
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +2 -1
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +56 -9
- package/docs/proactive-memory.md +1 -1
- package/docs/prompt-envelope-and-tools.md +4 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +83 -65
- package/docs/resource-library.md +59 -0
- package/docs/safety-model.md +2 -2
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +37 -1
- package/docs/skills-marketplace.md +16 -3
- package/docs/tool-usage.md +14 -7
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +1 -1
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +1 -2
- package/src/cli/argv.ts +5 -0
- package/src/cli/configure.ts +107 -23
- package/src/cli/doctor.ts +5 -1
- package/src/cli/evidence.ts +30 -25
- package/src/cli/fleet-commands.ts +37 -0
- package/src/cli/fleet-graph.ts +102 -0
- package/src/cli/fleet-new.ts +36 -0
- package/src/cli/fleet-preflight.ts +111 -0
- package/src/cli/fleet-validate.ts +30 -0
- package/src/cli/fleet.ts +173 -335
- package/src/cli/index.ts +3 -1
- package/src/cli/library.ts +190 -0
- package/src/cli/share.ts +13 -1
- package/src/cli/shared.ts +1 -0
- package/src/cli/targets.ts +4 -1
- package/src/cli/usage.ts +111 -19
- package/src/cli/validate-model.ts +60 -5
- package/src/core/bus-events.ts +29 -0
- package/src/core/commit-attribution.ts +4 -4
- package/src/core/config.ts +130 -0
- package/src/core/defaults.ts +81 -0
- package/src/core/path-boundary.ts +100 -0
- package/src/domains/agents/builtins/architect.md +1 -0
- package/src/domains/agents/builtins/oracle.md +33 -0
- package/src/domains/agents/catalog.ts +13 -1
- package/src/domains/agents/extension.ts +2 -11
- package/src/domains/agents/fleet-contract.ts +304 -24
- package/src/domains/agents/index.ts +14 -0
- package/src/domains/agents/recipe.ts +7 -1
- package/src/domains/agents/registry.ts +73 -5
- package/src/domains/agents/result-contract.ts +360 -15
- package/src/domains/agents/write-boundary.ts +15 -50
- package/src/domains/config/classify.ts +4 -0
- package/src/domains/context/project-rules.ts +51 -1
- package/src/domains/dispatch/active-route-planner.ts +14 -0
- package/src/domains/dispatch/assignment-reconcile.ts +22 -5
- package/src/domains/dispatch/assignment-store.ts +151 -14
- package/src/domains/dispatch/backoff.ts +2 -1
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/checkout-writer-lease.ts +175 -0
- package/src/domains/dispatch/contract.ts +48 -0
- package/src/domains/dispatch/delegation-plan.ts +164 -0
- package/src/domains/dispatch/execution-plan.ts +76 -5
- package/src/domains/dispatch/execution-role.ts +12 -2
- package/src/domains/dispatch/execution-scheduler.ts +183 -67
- package/src/domains/dispatch/extension.ts +412 -74
- package/src/domains/dispatch/fleet-gate.ts +14 -0
- package/src/domains/dispatch/fleet-plan.ts +63 -3
- package/src/domains/dispatch/fleet-run.ts +791 -0
- package/src/domains/dispatch/gate-role-prompts.ts +47 -0
- package/src/domains/dispatch/host-verification.ts +178 -0
- package/src/domains/dispatch/index.ts +41 -1
- package/src/domains/dispatch/intent-requirements.ts +40 -0
- package/src/domains/dispatch/intent.ts +235 -0
- package/src/domains/dispatch/path-scope.ts +370 -0
- package/src/domains/dispatch/receipt-integrity.ts +9 -4
- package/src/domains/dispatch/state.ts +36 -3
- package/src/domains/dispatch/types.ts +64 -12
- package/src/domains/dispatch/validation.ts +69 -6
- package/src/domains/dispatch/write-boundary-enforcer.ts +45 -0
- package/src/domains/dispatch/write-boundary.ts +201 -22
- package/src/domains/eval/metrics/evidence.ts +79 -2
- package/src/domains/eval/runners/clio-run.ts +12 -2
- package/src/domains/evidence/build.ts +69 -11
- package/src/domains/evidence/index.ts +21 -0
- package/src/domains/evidence/provenance.ts +46 -11
- package/src/domains/evidence/trust-projection.ts +274 -0
- package/src/domains/evidence/trust-status.ts +155 -18
- package/src/domains/evidence/types.ts +4 -0
- package/src/domains/extensions/discovery.ts +88 -1
- package/src/domains/extensions/resources.ts +20 -8
- package/src/domains/extensions/state.ts +6 -2
- package/src/domains/extensions/types.ts +4 -1
- package/src/domains/lifecycle/doctor.ts +140 -1
- package/src/domains/middleware/index.ts +15 -0
- package/src/domains/middleware/watchdog.ts +281 -0
- package/src/domains/observability/contract.ts +3 -1
- package/src/domains/observability/cost.ts +12 -1
- package/src/domains/observability/extension.ts +2 -2
- package/src/domains/observability/index.ts +10 -0
- package/src/domains/observability/out-of-turn-usage.ts +223 -0
- package/src/domains/prompts/contract.ts +3 -5
- package/src/domains/providers/extension.ts +30 -2
- package/src/domains/resources/common-loader.ts +3 -0
- package/src/domains/resources/index.ts +20 -0
- package/src/domains/resources/library.ts +326 -0
- package/src/domains/resources/prompts/loader.ts +119 -14
- package/src/domains/resources/skills/marketplace.ts +37 -12
- package/src/domains/safety/policy-engine.ts +5 -5
- package/src/domains/safety/run-effects.ts +64 -1
- package/src/domains/safety/scope.ts +7 -12
- package/src/domains/session/handoff.ts +629 -0
- package/src/domains/share/archive.ts +67 -2
- package/src/engine/acp/server.ts +4 -1
- package/src/engine/prompt-templates.ts +18 -1
- package/src/engine/worker-runtime.ts +6 -3
- package/src/entry/orchestrator.ts +37 -0
- package/src/interactive/bus-notices.ts +26 -0
- package/src/interactive/chat-loop.ts +235 -1
- package/src/interactive/chat-renderer.ts +22 -0
- package/src/interactive/cost-overlay.ts +31 -3
- package/src/interactive/council-dispatch.ts +30 -0
- package/src/interactive/council-grid.ts +213 -0
- package/src/interactive/council.ts +99 -0
- package/src/interactive/dispatch-board.ts +311 -17
- package/src/interactive/fleet-run-preview.ts +307 -0
- package/src/interactive/footer/notifications.ts +219 -0
- package/src/interactive/handoff-round.ts +56 -0
- package/src/interactive/interactive-application.ts +43 -1
- package/src/interactive/interactive-event-projection.ts +23 -1
- package/src/interactive/interactive-slash-runtime.ts +52 -2
- package/src/interactive/interactive-subscriptions.ts +14 -2
- package/src/interactive/oracle.ts +179 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +6 -0
- package/src/interactive/overlay-general-openers.ts +190 -1
- package/src/interactive/overlay-key-routing.ts +17 -1
- package/src/interactive/overlay-lifecycle.ts +41 -1
- package/src/interactive/overlay-permission-lifecycle.ts +10 -0
- package/src/interactive/overlay-resource-openers.ts +11 -3
- package/src/interactive/overlay-session-lifecycle.ts +234 -2
- package/src/interactive/overlays/fleet-run-approval.ts +208 -0
- package/src/interactive/overlays/handoff-review.ts +185 -0
- package/src/interactive/overlays/library-install-confirm.ts +151 -0
- package/src/interactive/overlays/list-overlay.ts +168 -2
- package/src/interactive/overlays/settings.ts +221 -30
- package/src/interactive/overlays/side-question.ts +139 -0
- package/src/interactive/overlays/skills-hub.ts +401 -15
- package/src/interactive/side-question.ts +171 -0
- package/src/interactive/slash-commands.ts +439 -7
- package/src/interactive/slash-spec.ts +19 -6
- package/src/interactive/theme/tokens.ts +30 -0
- package/src/interactive/turn-middleware.ts +15 -1
- package/src/interactive/view/artifacts.ts +42 -9
- package/src/interactive/view/view-overlay.ts +15 -3
- package/src/interactive/watchdog-run.ts +75 -0
- package/src/interactive/worker-receipts.ts +14 -2
- package/src/interactive/worker-share.ts +56 -1
- package/src/interactive/worker-stream.ts +15 -0
- package/src/tools/bootstrap.ts +3 -0
- package/src/tools/compete-worktrees.ts +13 -79
- package/src/tools/dispatch-admission.ts +251 -18
- package/src/tools/dispatch-arguments.ts +84 -1
- package/src/tools/dispatch-plan.ts +165 -6
- package/src/tools/dispatch-runner.ts +364 -23
- package/src/tools/dispatch-types.ts +20 -1
- package/src/tools/dispatch.ts +72 -2
- package/src/tools/monitor.ts +29 -0
- package/src/tools/profiles.ts +18 -4
- package/src/tools/task-worktree.ts +238 -0
- package/src/tools/verify/authoring.ts +61 -1
- package/src/tools/verify/scripts.ts +62 -0
- package/src/tools/worker-evidence.ts +21 -14
- package/src/worker/spec-contract.ts +3 -1
- package/dist/chunk-HC4CLZ2Y.js +0 -68
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import {
|
|
2
|
+
asDirectoryPathBoundary,
|
|
3
|
+
normalizePathBoundaryEntry,
|
|
4
|
+
PathBoundaryError,
|
|
5
|
+
pathBoundaryCovers,
|
|
6
|
+
resolvePathBoundary,
|
|
7
|
+
} from "../../core/path-boundary.js";
|
|
8
|
+
import type { DispatchRequest } from "./contract.js";
|
|
9
|
+
|
|
10
|
+
/** Path-like tokens retained for requests that do not carry typed intent. */
|
|
11
|
+
const DISPATCH_PATH_TOKEN_RE = /(?:[\w.-]+\/)+[\w.-]+|\b[\w-]+\.[A-Za-z0-9]{1,8}\b/g;
|
|
12
|
+
const HTTP_URL_RE = /\bhttps?:\/\/\S+/gu;
|
|
13
|
+
const POSIX_ABSOLUTE_TOKEN_RE = /(?:^|[\s("'])((?:\/[\w.~+-]+)+)/gu;
|
|
14
|
+
const WINDOWS_ABSOLUTE_TOKEN_RE = /(?:^|[\s("'])([A-Za-z]:[\\/][^\s"']+)/gu;
|
|
15
|
+
const BACKSLASH_PATH_RE = /\b[A-Za-z_.-][\w.-]*\\(?:(?:[\w.-]+\\)+[\w.-]+|[\w-]+\.[A-Za-z0-9]{1,8})\b/gu;
|
|
16
|
+
const DOUBLE_SEPARATOR_PATH_RE = /\b[\w.-]+\/\/[\w./-]+/gu;
|
|
17
|
+
|
|
18
|
+
export type DispatchPathProvenanceKind = "declared" | "derived" | "inferred";
|
|
19
|
+
export type DispatchPathConfidence = "certain" | "high" | "medium" | "low";
|
|
20
|
+
export type DispatchPathProvenanceSource =
|
|
21
|
+
| "intent.read_roots"
|
|
22
|
+
| "intent.write_roots"
|
|
23
|
+
| "intent.relevant_paths"
|
|
24
|
+
| "writeRoots"
|
|
25
|
+
| "task"
|
|
26
|
+
| "briefing";
|
|
27
|
+
export type DispatchPathProvenanceReason =
|
|
28
|
+
| "explicit_intent"
|
|
29
|
+
| "legacy_write_roots"
|
|
30
|
+
| "task_path_token"
|
|
31
|
+
| "briefing_path_token";
|
|
32
|
+
|
|
33
|
+
export interface DispatchPathProvenanceEvidence {
|
|
34
|
+
provenance: DispatchPathProvenanceKind;
|
|
35
|
+
source: DispatchPathProvenanceSource;
|
|
36
|
+
confidence: DispatchPathConfidence;
|
|
37
|
+
reason: DispatchPathProvenanceReason;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface DispatchPathProvenanceEntry {
|
|
41
|
+
path: string;
|
|
42
|
+
evidence: DispatchPathProvenanceEvidence[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface DispatchPathScopeProvenance {
|
|
46
|
+
version: 1;
|
|
47
|
+
mode: "declared" | "legacy-inferred";
|
|
48
|
+
workingContextPaths: DispatchPathProvenanceEntry[];
|
|
49
|
+
writeBoundaries: DispatchPathProvenanceEntry[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface DispatchPathScope {
|
|
53
|
+
source: "declared" | "inferred";
|
|
54
|
+
workingContextPaths: ReadonlyArray<string>;
|
|
55
|
+
writeBoundaries: ReadonlyArray<string>;
|
|
56
|
+
inferredOnlyPaths: ReadonlyArray<string>;
|
|
57
|
+
provenance: DispatchPathScopeProvenance;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface DeclaredScopeReplacementNotice {
|
|
61
|
+
code: "typed_scope_replaced_inferred_paths";
|
|
62
|
+
level: "warning";
|
|
63
|
+
omittedPaths: ReadonlyArray<string>;
|
|
64
|
+
message: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface LegacyScopeInferenceNotice {
|
|
68
|
+
code: "legacy_scope_inferred" | "legacy_scope_empty";
|
|
69
|
+
level: "warning";
|
|
70
|
+
paths: ReadonlyArray<{
|
|
71
|
+
path: string;
|
|
72
|
+
policy: "working-context" | "write-boundary";
|
|
73
|
+
provenance: DispatchPathProvenanceKind;
|
|
74
|
+
source: DispatchPathProvenanceSource;
|
|
75
|
+
confidence: DispatchPathConfidence;
|
|
76
|
+
}>;
|
|
77
|
+
message: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type DispatchPathScopeInferenceErrorCode = "legacy_scope_path_absolute" | "legacy_scope_path_malformed";
|
|
81
|
+
|
|
82
|
+
export class DispatchPathScopeInferenceError extends Error {
|
|
83
|
+
readonly code: DispatchPathScopeInferenceErrorCode;
|
|
84
|
+
readonly source: "task" | "briefing";
|
|
85
|
+
readonly token: string;
|
|
86
|
+
|
|
87
|
+
constructor(code: DispatchPathScopeInferenceErrorCode, source: "task" | "briefing", token: string, detail: string) {
|
|
88
|
+
super(`${code}: ${source} contains ${detail} '${token}'; declare intent explicitly`);
|
|
89
|
+
this.name = "DispatchPathScopeInferenceError";
|
|
90
|
+
this.code = code;
|
|
91
|
+
this.source = source;
|
|
92
|
+
this.token = token;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const DECLARED_EVIDENCE = {
|
|
97
|
+
readRoots: {
|
|
98
|
+
provenance: "declared",
|
|
99
|
+
source: "intent.read_roots",
|
|
100
|
+
confidence: "certain",
|
|
101
|
+
reason: "explicit_intent",
|
|
102
|
+
},
|
|
103
|
+
writeRoots: {
|
|
104
|
+
provenance: "declared",
|
|
105
|
+
source: "intent.write_roots",
|
|
106
|
+
confidence: "certain",
|
|
107
|
+
reason: "explicit_intent",
|
|
108
|
+
},
|
|
109
|
+
relevantPaths: {
|
|
110
|
+
provenance: "declared",
|
|
111
|
+
source: "intent.relevant_paths",
|
|
112
|
+
confidence: "certain",
|
|
113
|
+
reason: "explicit_intent",
|
|
114
|
+
},
|
|
115
|
+
} as const satisfies Record<"readRoots" | "writeRoots" | "relevantPaths", DispatchPathProvenanceEvidence>;
|
|
116
|
+
|
|
117
|
+
function cloneEvidence(evidence: DispatchPathProvenanceEvidence): DispatchPathProvenanceEvidence {
|
|
118
|
+
return { ...evidence };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function addProvenance(
|
|
122
|
+
entries: Map<string, DispatchPathProvenanceEntry>,
|
|
123
|
+
path: string,
|
|
124
|
+
evidence: DispatchPathProvenanceEvidence,
|
|
125
|
+
): void {
|
|
126
|
+
const current = entries.get(path);
|
|
127
|
+
if (current === undefined) {
|
|
128
|
+
entries.set(path, { path, evidence: [cloneEvidence(evidence)] });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (!current.evidence.some((entry) => entry.source === evidence.source)) {
|
|
132
|
+
current.evidence.push(cloneEvidence(evidence));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function sortedEntries(entries: Map<string, DispatchPathProvenanceEntry>): DispatchPathProvenanceEntry[] {
|
|
137
|
+
return [...entries.values()]
|
|
138
|
+
.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0))
|
|
139
|
+
.map((entry) => ({ path: entry.path, evidence: entry.evidence.map(cloneEvidence) }));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Build the required field-level provenance for normalized declared intent. */
|
|
143
|
+
export function declaredIntentPathProvenance(input: {
|
|
144
|
+
readRoots: ReadonlyArray<string>;
|
|
145
|
+
writeRoots: ReadonlyArray<string>;
|
|
146
|
+
relevantPaths: ReadonlyArray<string>;
|
|
147
|
+
}): DispatchPathProvenanceEntry[] {
|
|
148
|
+
const entries = new Map<string, DispatchPathProvenanceEntry>();
|
|
149
|
+
for (const path of input.readRoots) addProvenance(entries, path, DECLARED_EVIDENCE.readRoots);
|
|
150
|
+
for (const path of input.writeRoots) addProvenance(entries, path, DECLARED_EVIDENCE.writeRoots);
|
|
151
|
+
for (const path of input.relevantPaths) addProvenance(entries, path, DECLARED_EVIDENCE.relevantPaths);
|
|
152
|
+
return sortedEntries(entries);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function inferredPaths(req: Pick<DispatchRequest, "task" | "briefing">): string[] {
|
|
156
|
+
const paths = new Set<string>();
|
|
157
|
+
const text = `${req.task}\n${req.briefing ?? ""}`;
|
|
158
|
+
for (const match of text.matchAll(DISPATCH_PATH_TOKEN_RE)) {
|
|
159
|
+
const token = inferredPathToken(match[0]);
|
|
160
|
+
if (token.startsWith("http://") || token.startsWith("https://")) continue;
|
|
161
|
+
paths.add(token);
|
|
162
|
+
}
|
|
163
|
+
return [...paths];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function inferredPathToken(token: string): string {
|
|
167
|
+
return token.replace(/\.+$/u, "");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function failMalformedText(text: string, source: "task" | "briefing"): void {
|
|
171
|
+
const withoutUrls = text.replace(HTTP_URL_RE, (url) => " ".repeat(url.length));
|
|
172
|
+
const absolute = POSIX_ABSOLUTE_TOKEN_RE.exec(withoutUrls)?.[1];
|
|
173
|
+
POSIX_ABSOLUTE_TOKEN_RE.lastIndex = 0;
|
|
174
|
+
if (absolute !== undefined) {
|
|
175
|
+
throw new DispatchPathScopeInferenceError("legacy_scope_path_absolute", source, absolute, "an absolute path token");
|
|
176
|
+
}
|
|
177
|
+
const windowsAbsolute = WINDOWS_ABSOLUTE_TOKEN_RE.exec(withoutUrls)?.[1];
|
|
178
|
+
WINDOWS_ABSOLUTE_TOKEN_RE.lastIndex = 0;
|
|
179
|
+
if (windowsAbsolute !== undefined) {
|
|
180
|
+
throw new DispatchPathScopeInferenceError(
|
|
181
|
+
"legacy_scope_path_absolute",
|
|
182
|
+
source,
|
|
183
|
+
windowsAbsolute,
|
|
184
|
+
"an absolute path token",
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
for (const pattern of [BACKSLASH_PATH_RE, DOUBLE_SEPARATOR_PATH_RE]) {
|
|
188
|
+
const malformed = pattern.exec(withoutUrls)?.[0];
|
|
189
|
+
pattern.lastIndex = 0;
|
|
190
|
+
if (malformed !== undefined) {
|
|
191
|
+
throw new DispatchPathScopeInferenceError(
|
|
192
|
+
"legacy_scope_path_malformed",
|
|
193
|
+
source,
|
|
194
|
+
malformed,
|
|
195
|
+
"a malformed path token",
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function strictInferredPaths(
|
|
202
|
+
text: string,
|
|
203
|
+
source: "task" | "briefing",
|
|
204
|
+
): Array<{ path: string; evidence: DispatchPathProvenanceEvidence }> {
|
|
205
|
+
failMalformedText(text, source);
|
|
206
|
+
const withoutUrls = text.replace(HTTP_URL_RE, (url) => " ".repeat(url.length));
|
|
207
|
+
const evidence: DispatchPathProvenanceEvidence =
|
|
208
|
+
source === "task"
|
|
209
|
+
? { provenance: "inferred", source, confidence: "medium", reason: "task_path_token" }
|
|
210
|
+
: { provenance: "inferred", source, confidence: "low", reason: "briefing_path_token" };
|
|
211
|
+
const result: Array<{ path: string; evidence: DispatchPathProvenanceEvidence }> = [];
|
|
212
|
+
for (const match of withoutUrls.matchAll(DISPATCH_PATH_TOKEN_RE)) {
|
|
213
|
+
const token = inferredPathToken(match[0]);
|
|
214
|
+
try {
|
|
215
|
+
result.push({ path: normalizePathBoundaryEntry(token), evidence });
|
|
216
|
+
} catch (error) {
|
|
217
|
+
const code =
|
|
218
|
+
error instanceof PathBoundaryError && error.code === "absolute"
|
|
219
|
+
? "legacy_scope_path_absolute"
|
|
220
|
+
: "legacy_scope_path_malformed";
|
|
221
|
+
throw new DispatchPathScopeInferenceError(
|
|
222
|
+
code,
|
|
223
|
+
source,
|
|
224
|
+
token,
|
|
225
|
+
code === "legacy_scope_path_absolute" ? "an absolute path token" : "a malformed path token",
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function legacyPathScope(req: DispatchRequest, cwd: string): DispatchPathScope {
|
|
233
|
+
const workingEntries = new Map<string, DispatchPathProvenanceEntry>();
|
|
234
|
+
const writeEntries = new Map<string, DispatchPathProvenanceEntry>();
|
|
235
|
+
const writeEvidence: DispatchPathProvenanceEvidence = {
|
|
236
|
+
provenance: "derived",
|
|
237
|
+
source: "writeRoots",
|
|
238
|
+
confidence: "high",
|
|
239
|
+
reason: "legacy_write_roots",
|
|
240
|
+
};
|
|
241
|
+
for (const root of req.writeRoots ?? []) {
|
|
242
|
+
addProvenance(workingEntries, root, writeEvidence);
|
|
243
|
+
addProvenance(writeEntries, asDirectoryPathBoundary(resolvePathBoundary(cwd, root)), writeEvidence);
|
|
244
|
+
}
|
|
245
|
+
for (const candidate of strictInferredPaths(req.task, "task")) {
|
|
246
|
+
addProvenance(workingEntries, candidate.path, candidate.evidence);
|
|
247
|
+
}
|
|
248
|
+
if (req.briefing !== undefined) {
|
|
249
|
+
for (const candidate of strictInferredPaths(req.briefing, "briefing")) {
|
|
250
|
+
addProvenance(workingEntries, candidate.path, candidate.evidence);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const workingContext = [...workingEntries.values()].map((entry) => ({
|
|
254
|
+
path: entry.path,
|
|
255
|
+
evidence: entry.evidence.map(cloneEvidence),
|
|
256
|
+
}));
|
|
257
|
+
const writeBoundaries = [...writeEntries.values()].map((entry) => ({
|
|
258
|
+
path: entry.path,
|
|
259
|
+
evidence: entry.evidence.map(cloneEvidence),
|
|
260
|
+
}));
|
|
261
|
+
return {
|
|
262
|
+
source: "inferred",
|
|
263
|
+
workingContextPaths: workingContext.map((entry) => entry.path),
|
|
264
|
+
writeBoundaries: writeBoundaries.map((entry) => entry.path),
|
|
265
|
+
inferredOnlyPaths: [],
|
|
266
|
+
provenance: {
|
|
267
|
+
version: 1,
|
|
268
|
+
mode: "legacy-inferred",
|
|
269
|
+
workingContextPaths: workingContext,
|
|
270
|
+
writeBoundaries,
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** Resolve every policy-bearing path projection for one dispatch request. */
|
|
276
|
+
export function resolveDispatchPathScope(req: DispatchRequest): DispatchPathScope {
|
|
277
|
+
const cwd = req.cwd ?? process.cwd();
|
|
278
|
+
if (req.intent === undefined) return legacyPathScope(req, cwd);
|
|
279
|
+
|
|
280
|
+
const declaredProvenance = declaredIntentPathProvenance(req.intent);
|
|
281
|
+
const declaredPaths = declaredProvenance.map((entry) => entry.path);
|
|
282
|
+
const inferredOnlyPaths = inferredPaths(req).filter((candidate) => !pathBoundaryCovers(declaredPaths, candidate));
|
|
283
|
+
const writeEvidence = DECLARED_EVIDENCE.writeRoots;
|
|
284
|
+
const writeBoundaries = req.intent.writeRoots.map((root) => ({
|
|
285
|
+
path: resolvePathBoundary(cwd, root),
|
|
286
|
+
evidence: [cloneEvidence(writeEvidence)],
|
|
287
|
+
}));
|
|
288
|
+
return {
|
|
289
|
+
source: "declared",
|
|
290
|
+
workingContextPaths: declaredPaths,
|
|
291
|
+
writeBoundaries: writeBoundaries.map((entry) => entry.path),
|
|
292
|
+
inferredOnlyPaths,
|
|
293
|
+
provenance: {
|
|
294
|
+
version: 1,
|
|
295
|
+
mode: "declared",
|
|
296
|
+
workingContextPaths: declaredProvenance,
|
|
297
|
+
writeBoundaries,
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** Render the named diagnostic for the declared-scope replacement tradeoff. */
|
|
303
|
+
export function declaredScopeReplacementDiagnostic(scope: DispatchPathScope): string | null {
|
|
304
|
+
if (scope.source !== "declared" || scope.inferredOnlyPaths.length === 0) return null;
|
|
305
|
+
return `typed_scope_replaced_inferred_paths: typed intent omitted prose-inferred paths ${scope.inferredOnlyPaths.join(
|
|
306
|
+
", ",
|
|
307
|
+
)}; those paths did not select project rules or expand worker authority`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Render the interactive warning for the declared-scope replacement tradeoff. */
|
|
311
|
+
export function declaredScopeReplacementNotice(scope: DispatchPathScope): DeclaredScopeReplacementNotice | null {
|
|
312
|
+
if (scope.source !== "declared" || scope.inferredOnlyPaths.length === 0) return null;
|
|
313
|
+
const omittedPaths = [...scope.inferredOnlyPaths];
|
|
314
|
+
return {
|
|
315
|
+
code: "typed_scope_replaced_inferred_paths",
|
|
316
|
+
level: "warning",
|
|
317
|
+
omittedPaths,
|
|
318
|
+
message: `[dispatch scope] typed intent replaced prose path inference; omitted paths: ${omittedPaths.join(
|
|
319
|
+
", ",
|
|
320
|
+
)}. Those paths did not select project rules or expand worker authority.`,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function legacyNoticePaths(scope: DispatchPathScope): LegacyScopeInferenceNotice["paths"] {
|
|
325
|
+
const paths: Array<LegacyScopeInferenceNotice["paths"][number]> = [];
|
|
326
|
+
for (const [policy, entries] of [
|
|
327
|
+
["working-context", scope.provenance.workingContextPaths],
|
|
328
|
+
["write-boundary", scope.provenance.writeBoundaries],
|
|
329
|
+
] as const) {
|
|
330
|
+
for (const entry of entries) {
|
|
331
|
+
for (const evidence of entry.evidence) {
|
|
332
|
+
paths.push({
|
|
333
|
+
path: entry.path,
|
|
334
|
+
policy,
|
|
335
|
+
provenance: evidence.provenance,
|
|
336
|
+
source: evidence.source,
|
|
337
|
+
confidence: evidence.confidence,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return paths;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** Render the operator-visible warning for a legacy scope resolution. */
|
|
346
|
+
export function legacyScopeInferenceNotice(scope: DispatchPathScope): LegacyScopeInferenceNotice | null {
|
|
347
|
+
if (scope.source !== "inferred") return null;
|
|
348
|
+
const paths = legacyNoticePaths(scope);
|
|
349
|
+
if (paths.length === 0) {
|
|
350
|
+
return {
|
|
351
|
+
code: "legacy_scope_empty",
|
|
352
|
+
level: "warning",
|
|
353
|
+
paths,
|
|
354
|
+
message:
|
|
355
|
+
"[dispatch scope] legacy dispatch has no declared intent and inferred no policy-bearing paths. Path-scoped rules received no inferred match input, and worker authority did not expand.",
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
const rendered = paths
|
|
359
|
+
.map(
|
|
360
|
+
(entry) =>
|
|
361
|
+
`${entry.policy} ${entry.path} (provenance=${entry.provenance} source=${entry.source} confidence=${entry.confidence})`,
|
|
362
|
+
)
|
|
363
|
+
.join("; ");
|
|
364
|
+
return {
|
|
365
|
+
code: "legacy_scope_inferred",
|
|
366
|
+
level: "warning",
|
|
367
|
+
paths,
|
|
368
|
+
message: `[dispatch scope] legacy dispatch resolved policy-bearing scope without declared intent: ${rendered}. Review this scope before execution.`,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
@@ -10,7 +10,7 @@ import type { RunEnvelope, RunReceipt, RunReceiptDraft, RunReceiptIntegrity, Run
|
|
|
10
10
|
* base, so there are no historical receipts to keep verifying: a receipt is
|
|
11
11
|
* either this version or it is not a receipt.
|
|
12
12
|
*/
|
|
13
|
-
export const RUN_RECEIPT_INTEGRITY_VERSION: RunReceiptIntegrity["version"] =
|
|
13
|
+
export const RUN_RECEIPT_INTEGRITY_VERSION: RunReceiptIntegrity["version"] = 20;
|
|
14
14
|
export type ReceiptIntegrityVersion = RunReceiptIntegrity["version"];
|
|
15
15
|
export type ReceiptIntegrityField = keyof RunReceiptDraft;
|
|
16
16
|
export const RUN_RECEIPT_INTEGRITY_ALGORITHM = "sha256";
|
|
@@ -76,6 +76,8 @@ export const RECEIPT_INTEGRITY_FIELD_COVERAGE = {
|
|
|
76
76
|
agentAudience: true,
|
|
77
77
|
requestOrigin: true,
|
|
78
78
|
task: true,
|
|
79
|
+
intent: true,
|
|
80
|
+
pathScope: true,
|
|
79
81
|
// Historical receipts omit this field, so their receipt and ledger payloads remain unchanged.
|
|
80
82
|
budget: true,
|
|
81
83
|
targetId: true,
|
|
@@ -93,12 +95,13 @@ export const RECEIPT_INTEGRITY_FIELD_COVERAGE = {
|
|
|
93
95
|
reroutes: true,
|
|
94
96
|
pipeline: true,
|
|
95
97
|
gate: true,
|
|
98
|
+
council: true,
|
|
96
99
|
plan: true,
|
|
100
|
+
fleetGate: true,
|
|
97
101
|
personaOverride: true,
|
|
98
102
|
projectContext: true,
|
|
99
103
|
// Always set on receipts written after #104 landed; absent only on older
|
|
100
|
-
// receipts, which
|
|
101
|
-
// so the integrity version stays where it is.
|
|
104
|
+
// receipts, which omit these fields from canonical serialization.
|
|
102
105
|
rulesApplied: true,
|
|
103
106
|
operatorProfileApplied: true,
|
|
104
107
|
exitCode: true,
|
|
@@ -128,6 +131,8 @@ export const RECEIPT_INTEGRITY_FIELD_COVERAGE = {
|
|
|
128
131
|
toolStats: true,
|
|
129
132
|
toolActivity: true,
|
|
130
133
|
verification: true,
|
|
134
|
+
hostVerification: true,
|
|
135
|
+
worktree: true,
|
|
131
136
|
routingIntent: true,
|
|
132
137
|
quality: true,
|
|
133
138
|
skillActivations: true,
|
|
@@ -143,7 +148,7 @@ export const RECEIPT_INTEGRITY_FIELD_COVERAGE = {
|
|
|
143
148
|
validationGrounding: true,
|
|
144
149
|
capabilityMismatch: true,
|
|
145
150
|
// Same reasoning: absent unless the run had an agent ledger, so a receipt
|
|
146
|
-
// without one
|
|
151
|
+
// without one omits the field from canonical serialization.
|
|
147
152
|
ledgerContribution: true,
|
|
148
153
|
sessionId: true,
|
|
149
154
|
briefing: true,
|
|
@@ -25,10 +25,26 @@ import { resolveGuardrail } from "../../core/guardrails.js";
|
|
|
25
25
|
import { withStateFileLock } from "../../core/state-file-lock.js";
|
|
26
26
|
import { clioStateDir, stateRootRemoved } from "../../core/xdg.js";
|
|
27
27
|
import { atomicWrite } from "../../engine/session.js";
|
|
28
|
+
import type { ExecutionStepResult } from "./execution-scheduler.js";
|
|
28
29
|
import { computeReceiptFindingsSummary } from "./receipt-findings.js";
|
|
29
30
|
import { withReceiptIntegrity } from "./receipt-integrity.js";
|
|
30
31
|
import type { RunEnvelope, RunReceipt, RunReceiptDraft, RunStatus } from "./types.js";
|
|
31
32
|
|
|
33
|
+
export interface FleetRunRecord {
|
|
34
|
+
version: 1;
|
|
35
|
+
id: string;
|
|
36
|
+
fleet: string;
|
|
37
|
+
planHash: string;
|
|
38
|
+
stepIds: string[];
|
|
39
|
+
planSteps: unknown[];
|
|
40
|
+
vars: Record<string, string>;
|
|
41
|
+
startedAt: string;
|
|
42
|
+
endedAt: string | null;
|
|
43
|
+
resumedFrom: string | null;
|
|
44
|
+
steps: Array<{ stepId: string; result: ExecutionStepResult }>;
|
|
45
|
+
dynamicPlans?: Array<{ stepId: string; hash: string }>;
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
export interface LedgerOptions {
|
|
33
49
|
maxRuns?: number;
|
|
34
50
|
}
|
|
@@ -45,7 +61,7 @@ export type CreateRunInput = Omit<
|
|
|
45
61
|
| "receiptPath"
|
|
46
62
|
| "tokenCount"
|
|
47
63
|
| "costUsd"
|
|
48
|
-
|
|
64
|
+
> & { id?: string };
|
|
49
65
|
|
|
50
66
|
export interface Ledger {
|
|
51
67
|
create(input: CreateRunInput): RunEnvelope;
|
|
@@ -59,7 +75,7 @@ export interface Ledger {
|
|
|
59
75
|
reload(): void;
|
|
60
76
|
}
|
|
61
77
|
|
|
62
|
-
function newRunId(): string {
|
|
78
|
+
export function newRunId(): string {
|
|
63
79
|
const n = BigInt(`0x${randomBytes(8).toString("hex")}`);
|
|
64
80
|
const raw = n.toString(36);
|
|
65
81
|
if (raw.length >= 12) return raw.slice(0, 12);
|
|
@@ -74,6 +90,23 @@ function receiptPathFor(runId: string): string {
|
|
|
74
90
|
return join(clioStateDir(), "receipts", `${runId}.json`);
|
|
75
91
|
}
|
|
76
92
|
|
|
93
|
+
function fleetRunPath(runId: string): string {
|
|
94
|
+
return join(clioStateDir(), "fleet-runs", `${runId}.json`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function readFleetRun(runId: string): FleetRunRecord | null {
|
|
98
|
+
try {
|
|
99
|
+
const parsed = JSON.parse(readFileSync(fleetRunPath(runId), "utf8")) as FleetRunRecord;
|
|
100
|
+
return parsed.version === 1 && parsed.id === runId ? structuredClone(parsed) : null;
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export async function writeFleetRun(record: FleetRunRecord): Promise<void> {
|
|
107
|
+
await atomicWrite(fleetRunPath(record.id), `${JSON.stringify(record, null, 2)}\n`);
|
|
108
|
+
}
|
|
109
|
+
|
|
77
110
|
function readRuns(): RunEnvelope[] {
|
|
78
111
|
const path = runsPath();
|
|
79
112
|
if (!existsSync(path)) return [];
|
|
@@ -169,7 +202,7 @@ export function openLedger(opts?: LedgerOptions): Ledger {
|
|
|
169
202
|
return {
|
|
170
203
|
create(input: CreateRunInput): RunEnvelope {
|
|
171
204
|
const envelope: RunEnvelope = {
|
|
172
|
-
id: newRunId(),
|
|
205
|
+
id: input.id ?? newRunId(),
|
|
173
206
|
agentId: input.agentId,
|
|
174
207
|
executionRole: input.executionRole,
|
|
175
208
|
...(input.agentAudience !== undefined ? { agentAudience: input.agentAudience } : {}),
|
|
@@ -14,6 +14,8 @@ import type { EvidenceTag } from "../evidence/index.js";
|
|
|
14
14
|
import type { CostProvenance, RuntimeTargetSnapshot } from "../providers/index.js";
|
|
15
15
|
import type { RunToolBudgetEnvelope } from "./budget-envelope.js";
|
|
16
16
|
import type { ExecutionRole, GateTopologyRole } from "./execution-role.js";
|
|
17
|
+
import type { DispatchIntent } from "./intent.js";
|
|
18
|
+
import type { DispatchPathScopeProvenance } from "./path-scope.js";
|
|
17
19
|
import type { RouteDecisionV1 } from "./route-decision.js";
|
|
18
20
|
import type { RoutingIntent } from "./routing-intent.js";
|
|
19
21
|
|
|
@@ -41,7 +43,8 @@ export type RunOutcomeCode =
|
|
|
41
43
|
| "worker_tool_call_cap_exhausted"
|
|
42
44
|
| "loop_guard_tools_disabled_exhausted"
|
|
43
45
|
| "result_contract_exhausted"
|
|
44
|
-
| "worker_final_output_missing"
|
|
46
|
+
| "worker_final_output_missing"
|
|
47
|
+
| "host_verification_rejected";
|
|
45
48
|
|
|
46
49
|
export function isRunOutcomeCode(value: unknown): value is RunOutcomeCode {
|
|
47
50
|
return (
|
|
@@ -49,7 +52,8 @@ export function isRunOutcomeCode(value: unknown): value is RunOutcomeCode {
|
|
|
49
52
|
value === "worker_tool_call_cap_exhausted" ||
|
|
50
53
|
value === "loop_guard_tools_disabled_exhausted" ||
|
|
51
54
|
value === "result_contract_exhausted" ||
|
|
52
|
-
value === "worker_final_output_missing"
|
|
55
|
+
value === "worker_final_output_missing" ||
|
|
56
|
+
value === "host_verification_rejected"
|
|
53
57
|
);
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -122,12 +126,16 @@ export interface RunPersonaOverride {
|
|
|
122
126
|
|
|
123
127
|
/**
|
|
124
128
|
* Effective project-context decision for a run, recorded on every receipt so
|
|
125
|
-
* evidence can prove what a worker saw without rehashing. `tier
|
|
126
|
-
*
|
|
127
|
-
* pre-provenance receipt where the
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* (
|
|
129
|
+
* evidence can prove what a worker saw without rehashing. `tier` is the
|
|
130
|
+
* recipe's CLIO-CODER.md handbook policy and is written explicitly: `none`
|
|
131
|
+
* distinguishes "policy said none" from a pre-provenance receipt where the
|
|
132
|
+
* whole block is absent. `chars` and `contentHash` describe every structured
|
|
133
|
+
* message that was actually sent, whatever the tier, and `sections` names
|
|
134
|
+
* them: `workspace-root` (sent under both tiers, so a none-tier run still
|
|
135
|
+
* records characters), `clio-md` (bounded only), and
|
|
136
|
+
* `verification-expectations` (bounded only, never for ACP delegation). A
|
|
137
|
+
* none-tier block naming only `workspace-root` is a consistent record; the
|
|
138
|
+
* trust adapter treats any other none-tier content as contradictory.
|
|
131
139
|
*/
|
|
132
140
|
export interface RunProjectContextProvenance {
|
|
133
141
|
tier: "none" | "bounded";
|
|
@@ -238,6 +246,13 @@ export interface RunGateProvenance {
|
|
|
238
246
|
verdict?: "pass" | "fail" | "revise";
|
|
239
247
|
}
|
|
240
248
|
|
|
249
|
+
export interface RunCouncilProvenance {
|
|
250
|
+
group: string;
|
|
251
|
+
label: string;
|
|
252
|
+
color?: string;
|
|
253
|
+
round: number;
|
|
254
|
+
}
|
|
255
|
+
|
|
241
256
|
/**
|
|
242
257
|
* Plan-approval provenance for multi-task, compete, or remote dispatch.
|
|
243
258
|
* `approval: "operator"` records that a supervised autonomy level parked the
|
|
@@ -248,7 +263,7 @@ export interface RunGateProvenance {
|
|
|
248
263
|
*/
|
|
249
264
|
export interface RunPlanProvenance {
|
|
250
265
|
hash: string;
|
|
251
|
-
topology: "parallel" | "sequential" | "pipeline" | "review" | "compete" | "detached" | "fleet";
|
|
266
|
+
topology: "parallel" | "sequential" | "pipeline" | "review" | "compete" | "council" | "detached" | "fleet";
|
|
252
267
|
taskCount: number;
|
|
253
268
|
approval: "operator" | "full-auto";
|
|
254
269
|
source: null | {
|
|
@@ -311,7 +326,7 @@ export interface RunPhaseDurations {
|
|
|
311
326
|
* bumping one without the other is a compile error.
|
|
312
327
|
*/
|
|
313
328
|
export interface RunReceiptIntegrity {
|
|
314
|
-
version:
|
|
329
|
+
version: 20;
|
|
315
330
|
algorithm: "sha256";
|
|
316
331
|
digest: string;
|
|
317
332
|
}
|
|
@@ -449,6 +464,7 @@ export interface RunEnvelope {
|
|
|
449
464
|
pipeline?: RunPipelineProvenance;
|
|
450
465
|
/** Review/compete gate provenance; present only on runs of a gated dispatch. */
|
|
451
466
|
gate?: RunGateProvenance;
|
|
467
|
+
council?: RunCouncilProvenance;
|
|
452
468
|
/** Plan-approval provenance; present only on runs of an approval-gated plan. */
|
|
453
469
|
plan?: RunPlanProvenance;
|
|
454
470
|
/** Ad-hoc specialist provenance; present only when a persona override composed the stable prompt. */
|
|
@@ -674,6 +690,25 @@ export interface RunReceiptVerification {
|
|
|
674
690
|
| "receipt-unavailable";
|
|
675
691
|
}
|
|
676
692
|
|
|
693
|
+
export interface RunHostVerificationCheck {
|
|
694
|
+
check: string;
|
|
695
|
+
argv: string[];
|
|
696
|
+
cwd: string;
|
|
697
|
+
exitCode: number;
|
|
698
|
+
durationMs: number;
|
|
699
|
+
memo: boolean;
|
|
700
|
+
outputTail: string;
|
|
701
|
+
artifactPath?: string;
|
|
702
|
+
/** Original evidence owner on a memo hit. */
|
|
703
|
+
evidenceRunId?: string;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export interface RunHostVerification {
|
|
707
|
+
status: "verified" | "rejected" | "skipped";
|
|
708
|
+
reason?: string;
|
|
709
|
+
checks: RunHostVerificationCheck[];
|
|
710
|
+
}
|
|
711
|
+
|
|
677
712
|
export interface RunReceipt {
|
|
678
713
|
runId: string;
|
|
679
714
|
agentId: string;
|
|
@@ -682,6 +717,10 @@ export interface RunReceipt {
|
|
|
682
717
|
agentAudience?: AgentAudience;
|
|
683
718
|
requestOrigin?: DispatchRequestOrigin;
|
|
684
719
|
task: string;
|
|
720
|
+
/** Normalized dispatch intent admitted before worker execution. */
|
|
721
|
+
intent?: DispatchIntent;
|
|
722
|
+
/** Resolved policy-bearing paths with field source and confidence, without source prose. */
|
|
723
|
+
pathScope?: DispatchPathScopeProvenance;
|
|
685
724
|
/** Integrity-sealed recipe policy, invocation request, effective phase, and admission reasons. */
|
|
686
725
|
budget?: RunToolBudgetEnvelope;
|
|
687
726
|
/** Proof of briefing content without copying its prose into the receipt. */
|
|
@@ -714,8 +753,11 @@ export interface RunReceipt {
|
|
|
714
753
|
pipeline?: RunPipelineProvenance;
|
|
715
754
|
/** Review/compete gate provenance; present only on runs of a gated dispatch. */
|
|
716
755
|
gate?: RunGateProvenance;
|
|
756
|
+
council?: RunCouncilProvenance;
|
|
717
757
|
/** Plan-approval provenance; present only on runs of an approval-gated plan. */
|
|
718
758
|
plan?: RunPlanProvenance;
|
|
759
|
+
/** Version 5 fleet gate artifact authored by this run. */
|
|
760
|
+
fleetGate?: { path: string; pathHash: string };
|
|
719
761
|
/** Ad-hoc specialist provenance; present only when a persona override composed the stable prompt. */
|
|
720
762
|
personaOverride?: RunPersonaOverride;
|
|
721
763
|
/** Effective project-context tier for this run; absent on receipts written before this field landed. */
|
|
@@ -764,6 +806,17 @@ export interface RunReceipt {
|
|
|
764
806
|
toolActivity?: ToolActivitySummary;
|
|
765
807
|
/** Integrity-sealed evidence confidence. Sealed on every receipt. */
|
|
766
808
|
verification: RunReceiptVerification;
|
|
809
|
+
/** Orchestrator-executed declared checks. Worker self-report never populates this field. */
|
|
810
|
+
hostVerification?: RunHostVerification;
|
|
811
|
+
/** Isolated writer checkout and its collect-time application result. */
|
|
812
|
+
worktree?: {
|
|
813
|
+
path: string;
|
|
814
|
+
branch: string;
|
|
815
|
+
diffHash: string;
|
|
816
|
+
apply: "merge" | "preserve";
|
|
817
|
+
applied: boolean;
|
|
818
|
+
reason?: string;
|
|
819
|
+
};
|
|
767
820
|
/** Required normalized routing request, sealed without task or prompt data. */
|
|
768
821
|
routingIntent: RoutingIntent;
|
|
769
822
|
/** Required routing-quality facts known at receipt finalization. */
|
|
@@ -786,8 +839,7 @@ export interface RunReceipt {
|
|
|
786
839
|
* What this run contributed to its dispatch's agent ledger. Optional and
|
|
787
840
|
* absent unless the run had a ledger, following validationGrounding and
|
|
788
841
|
* capabilityMismatch: receiptDigestFields skips undefined, so a receipt
|
|
789
|
-
* without one
|
|
790
|
-
* RUN_RECEIPT_INTEGRITY_VERSION stays where it is.
|
|
842
|
+
* without one omits the field from canonical serialization.
|
|
791
843
|
*/
|
|
792
844
|
ledgerContribution?: RunLedgerContribution;
|
|
793
845
|
/**
|