@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
package/src/tools/monitor.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type RunReceipt,
|
|
18
18
|
type RunReceiptVerification,
|
|
19
19
|
} from "../domains/dispatch/types.js";
|
|
20
|
+
import { summarizeTrustStatus } from "../domains/evidence/trust-projection.js";
|
|
20
21
|
import {
|
|
21
22
|
adaptRunReceiptTrustStatus,
|
|
22
23
|
type CanonicalTrustStatus,
|
|
@@ -123,6 +124,11 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
|
|
|
123
124
|
`started=${run.startedAt} ended=${run.endedAt ?? "n/a"} exit=${run.exitCode ?? "n/a"}`,
|
|
124
125
|
`tokens=${run.tokenCount} cost=${formatCostAggregate(costAggregateForAmount(run.costUsd, run.costProvenance)) ?? COST_NOT_MEASURED} receipt=${run.receiptPath ?? "n/a"}`,
|
|
125
126
|
];
|
|
127
|
+
if (run.council !== undefined || run.gate?.role === "synthesis") {
|
|
128
|
+
lines.push(
|
|
129
|
+
`council: role=${run.gate?.role === "synthesis" ? "synthesis" : "member"} group=${run.council?.group ?? run.gate?.group ?? "unknown"}${run.council?.label ? ` label=${run.council.label}` : ""}`,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
126
132
|
if (run.budget !== undefined) {
|
|
127
133
|
lines.push(
|
|
128
134
|
`recipe policy: ${formatBudgetPolicy(run.budget)}`,
|
|
@@ -158,6 +164,15 @@ function runStatus(deps: MonitorToolDeps, runId: string): ToolResult {
|
|
|
158
164
|
costUsd: run.costUsd,
|
|
159
165
|
costProvenance: run.costProvenance ?? "unknown",
|
|
160
166
|
budget: run.budget ?? null,
|
|
167
|
+
...(run.council !== undefined || run.gate?.role === "synthesis"
|
|
168
|
+
? {
|
|
169
|
+
council: {
|
|
170
|
+
role: run.gate?.role === "synthesis" ? "synthesis" : "member",
|
|
171
|
+
group: run.council?.group ?? run.gate?.group ?? null,
|
|
172
|
+
...(run.council !== undefined ? { label: run.council.label, round: run.council.round } : {}),
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
: {}),
|
|
161
176
|
receiptPath: run.receiptPath,
|
|
162
177
|
running: live !== null,
|
|
163
178
|
},
|
|
@@ -375,9 +390,11 @@ function runReceipt(deps: MonitorToolDeps, runId: string): ToolResult {
|
|
|
375
390
|
receiptPath: run.receiptPath,
|
|
376
391
|
receiptIntegrity,
|
|
377
392
|
trustStatus,
|
|
393
|
+
trust: summarizeTrustStatus(trustStatus),
|
|
378
394
|
...(receipt !== null && receiptIntegrity.ok
|
|
379
395
|
? {
|
|
380
396
|
evidenceVerification: receipt.verification,
|
|
397
|
+
hostVerification: receipt.hostVerification ?? null,
|
|
381
398
|
briefing: receipt.briefing ?? null,
|
|
382
399
|
projectContext: receipt.projectContext ?? null,
|
|
383
400
|
}
|
|
@@ -440,6 +457,17 @@ function durableRunEvidence(run: RunEnvelope | null): DurableRunEvidence {
|
|
|
440
457
|
const inspection = inspectRunReceiptTrustStatus(receipt, run);
|
|
441
458
|
const integrity = inspection.integrity;
|
|
442
459
|
if (!integrity.ok) {
|
|
460
|
+
// A retired seal is set aside unread, as a missing receipt is. It is
|
|
461
|
+
// not a failed one, so it never reads as tampering here either.
|
|
462
|
+
if (integrity.retired !== undefined) {
|
|
463
|
+
return {
|
|
464
|
+
...unavailableRunEvidence(
|
|
465
|
+
integrity.reason,
|
|
466
|
+
`${integrity.reason}; worker text is unavailable and validation is unknown.`,
|
|
467
|
+
),
|
|
468
|
+
trustStatus: inspection.status,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
443
471
|
return {
|
|
444
472
|
...unavailableRunEvidence(
|
|
445
473
|
integrity.reason,
|
|
@@ -717,6 +745,7 @@ async function runCollect(
|
|
|
717
745
|
receiptIntegrity: row.evidence.integrity,
|
|
718
746
|
trustStatus: row.evidence.trustStatus,
|
|
719
747
|
evidenceVerification: row.evidence.verification,
|
|
748
|
+
hostVerification: row.evidence.receipt?.hostVerification ?? null,
|
|
720
749
|
briefing: row.evidence.receipt?.briefing ?? null,
|
|
721
750
|
projectContext: row.evidence.receipt?.projectContext ?? null,
|
|
722
751
|
...(output ? { output: { state: output.state, bytes: output.bytes, truncated: output.truncated } } : {}),
|
package/src/tools/profiles.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { type BuiltinToolName, isBuiltinToolName, type ToolName, ToolNames } from "../core/tool-names.js";
|
|
2
2
|
|
|
3
|
-
export type ToolProfileName = "minimal-local" | "science-local" | "full-agent";
|
|
3
|
+
export type ToolProfileName = "minimal-local" | "science-local" | "full-agent" | "council-read-only";
|
|
4
4
|
|
|
5
|
-
export const TOOL_PROFILE_NAMES: ReadonlyArray<ToolProfileName
|
|
5
|
+
export const TOOL_PROFILE_NAMES: ReadonlyArray<Exclude<ToolProfileName, "council-read-only">> = [
|
|
6
|
+
"minimal-local",
|
|
7
|
+
"science-local",
|
|
8
|
+
"full-agent",
|
|
9
|
+
];
|
|
10
|
+
const ALL_TOOL_PROFILE_NAMES: ReadonlyArray<ToolProfileName> = [...TOOL_PROFILE_NAMES, "council-read-only"];
|
|
6
11
|
const CODEWIKI_TOOL_NAMES: ReadonlyArray<BuiltinToolName> = [ToolNames.CodeNav];
|
|
7
12
|
|
|
8
13
|
export interface ToolProfileContext {
|
|
@@ -24,14 +29,23 @@ const MINIMAL_LOCAL_TOOLS: ReadonlyArray<BuiltinToolName> = [
|
|
|
24
29
|
];
|
|
25
30
|
|
|
26
31
|
const SCIENCE_LOCAL_TOOLS: ReadonlyArray<BuiltinToolName> = [...MINIMAL_LOCAL_TOOLS, ToolNames.Verify];
|
|
32
|
+
const COUNCIL_READ_ONLY_TOOLS: ReadonlyArray<BuiltinToolName> = [
|
|
33
|
+
ToolNames.Read,
|
|
34
|
+
ToolNames.Grep,
|
|
35
|
+
ToolNames.Find,
|
|
36
|
+
ToolNames.Ls,
|
|
37
|
+
ToolNames.CodeNav,
|
|
38
|
+
ToolNames.Context,
|
|
39
|
+
];
|
|
27
40
|
|
|
28
41
|
const NARROW_TOOL_PROFILES: Readonly<Record<Exclude<ToolProfileName, "full-agent">, ReadonlySet<BuiltinToolName>>> = {
|
|
29
42
|
"minimal-local": new Set(MINIMAL_LOCAL_TOOLS),
|
|
30
43
|
"science-local": new Set(SCIENCE_LOCAL_TOOLS),
|
|
44
|
+
"council-read-only": new Set(COUNCIL_READ_ONLY_TOOLS),
|
|
31
45
|
};
|
|
32
46
|
|
|
33
47
|
export function isToolProfileName(value: string): value is ToolProfileName {
|
|
34
|
-
return (
|
|
48
|
+
return (ALL_TOOL_PROFILE_NAMES as ReadonlyArray<string>).includes(value);
|
|
35
49
|
}
|
|
36
50
|
|
|
37
51
|
/**
|
|
@@ -72,7 +86,7 @@ export function applyToolProfile(
|
|
|
72
86
|
const allowed = NARROW_TOOL_PROFILES[profile];
|
|
73
87
|
profiled = unique.filter((tool): tool is BuiltinToolName => isBuiltinToolName(tool) && allowed.has(tool));
|
|
74
88
|
}
|
|
75
|
-
return applyCodewikiWorkerPolicy(profiled, context);
|
|
89
|
+
return profile === "council-read-only" ? profiled : applyCodewikiWorkerPolicy(profiled, context);
|
|
76
90
|
}
|
|
77
91
|
|
|
78
92
|
function uniquePreservingOrder(tools: ReadonlyArray<ToolName>): ToolName[] {
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
3
|
+
import { existsSync, mkdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
|
+
|
|
6
|
+
export type TaskWorktreeApply = "merge" | "preserve";
|
|
7
|
+
|
|
8
|
+
export interface TaskWorktree {
|
|
9
|
+
root: string;
|
|
10
|
+
runId: string;
|
|
11
|
+
path: string;
|
|
12
|
+
branch: string;
|
|
13
|
+
base: string;
|
|
14
|
+
ownerToken: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TaskWorktreeReceipt {
|
|
18
|
+
path: string;
|
|
19
|
+
branch: string;
|
|
20
|
+
diffHash: string;
|
|
21
|
+
apply: TaskWorktreeApply;
|
|
22
|
+
applied: boolean;
|
|
23
|
+
reason?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const SAFE_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
|
|
27
|
+
const OWNER_FILE_SUFFIX = ".task-owner.json";
|
|
28
|
+
const COMMIT_IDENTITY = "clio-task";
|
|
29
|
+
|
|
30
|
+
function gitBytes(root: string, args: string[]): Buffer {
|
|
31
|
+
return execFileSync("git", ["-C", root, ...args], {
|
|
32
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
33
|
+
timeout: 30_000,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function git(root: string, args: string[]): string {
|
|
38
|
+
return gitBytes(root, args).toString("utf8").trim();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isCanonicalWorktreePathInside(parent: string, candidate: string): boolean {
|
|
42
|
+
let canonicalParent: string;
|
|
43
|
+
let canonicalCandidate: string;
|
|
44
|
+
try {
|
|
45
|
+
canonicalParent = realpathSync(parent);
|
|
46
|
+
} catch {
|
|
47
|
+
canonicalParent = resolve(parent);
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
canonicalCandidate = realpathSync(candidate);
|
|
51
|
+
} catch {
|
|
52
|
+
canonicalCandidate = resolve(candidate);
|
|
53
|
+
}
|
|
54
|
+
const rel = relative(canonicalParent, canonicalCandidate);
|
|
55
|
+
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function commitWorktreePath(path: string, identity: string, message: string): boolean {
|
|
59
|
+
git(path, ["add", "-A"]);
|
|
60
|
+
if (git(path, ["status", "--porcelain"]).length === 0) return false;
|
|
61
|
+
git(path, [
|
|
62
|
+
"-c",
|
|
63
|
+
`user.name=${identity}`,
|
|
64
|
+
"-c",
|
|
65
|
+
`user.email=${identity}@local`,
|
|
66
|
+
"commit",
|
|
67
|
+
"-m",
|
|
68
|
+
message,
|
|
69
|
+
"--no-verify",
|
|
70
|
+
]);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function worktreeBranchDiffStat(root: string, branch: string): string {
|
|
75
|
+
try {
|
|
76
|
+
return git(root, ["diff", "--shortstat", `HEAD...${branch}`]) || "no changes";
|
|
77
|
+
} catch {
|
|
78
|
+
return "diff unavailable";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function protectedPathsChangedByWorktreeBranch(
|
|
83
|
+
root: string,
|
|
84
|
+
branch: string,
|
|
85
|
+
protectedPaths: ReadonlyArray<string>,
|
|
86
|
+
): string[] {
|
|
87
|
+
const canonical = realpathSync(root);
|
|
88
|
+
const protectedInside = protectedPaths
|
|
89
|
+
.map((path) => resolve(path))
|
|
90
|
+
.filter((path) => {
|
|
91
|
+
const rel = relative(canonical, path);
|
|
92
|
+
return rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
|
|
93
|
+
});
|
|
94
|
+
if (protectedInside.length === 0) return [];
|
|
95
|
+
const changed = git(canonical, ["diff", "--name-only", "-z", "--no-renames", `HEAD...${branch}`])
|
|
96
|
+
.split("\0")
|
|
97
|
+
.filter((path) => path.length > 0)
|
|
98
|
+
.map((path) => resolve(canonical, path));
|
|
99
|
+
const blocked = new Set<string>();
|
|
100
|
+
for (const candidate of changed) {
|
|
101
|
+
for (const protectedPath of protectedInside) {
|
|
102
|
+
const rel = relative(protectedPath, candidate);
|
|
103
|
+
if (
|
|
104
|
+
candidate === protectedPath ||
|
|
105
|
+
(rel.length > 0 && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel))
|
|
106
|
+
) {
|
|
107
|
+
blocked.add(protectedPath);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return [...blocked].sort();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function mergeWorktreeBranch(
|
|
115
|
+
root: string,
|
|
116
|
+
branch: string,
|
|
117
|
+
identity: string,
|
|
118
|
+
): { ok: true } | { ok: false; reason: string } {
|
|
119
|
+
try {
|
|
120
|
+
git(root, [
|
|
121
|
+
"-c",
|
|
122
|
+
`user.name=${identity}`,
|
|
123
|
+
"-c",
|
|
124
|
+
`user.email=${identity}@local`,
|
|
125
|
+
"merge",
|
|
126
|
+
"--no-edit",
|
|
127
|
+
"--no-verify",
|
|
128
|
+
branch,
|
|
129
|
+
]);
|
|
130
|
+
return { ok: true };
|
|
131
|
+
} catch (error) {
|
|
132
|
+
try {
|
|
133
|
+
git(root, ["merge", "--abort"]);
|
|
134
|
+
} catch {
|
|
135
|
+
// No merge remains to abort.
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
ok: false,
|
|
139
|
+
reason: error instanceof Error ? (error.message.split("\n")[0] ?? "merge failed") : String(error),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function validateRunId(runId: string): void {
|
|
145
|
+
if (!SAFE_RUN_ID.test(runId) || runId === "." || runId === "..")
|
|
146
|
+
throw new Error(`invalid task worktree run id '${runId}'`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function gitCheckoutRoot(cwd: string): string | null {
|
|
150
|
+
try {
|
|
151
|
+
return realpathSync(git(cwd, ["rev-parse", "--show-toplevel"]));
|
|
152
|
+
} catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function createTaskWorktree(root: string, runId: string, base?: string): TaskWorktree {
|
|
158
|
+
validateRunId(runId);
|
|
159
|
+
const canonical = realpathSync(root);
|
|
160
|
+
const resolvedBase = base ?? git(canonical, ["rev-parse", "HEAD"]);
|
|
161
|
+
const parent = join(canonical, ".clio-coder", "worktrees");
|
|
162
|
+
const path = join(parent, runId);
|
|
163
|
+
const branch = `clio/task/${runId}`;
|
|
164
|
+
mkdirSync(parent, { recursive: true });
|
|
165
|
+
if (!isCanonicalWorktreePathInside(parent, path))
|
|
166
|
+
throw new Error(`task worktree path escapes its parent for run ${runId}`);
|
|
167
|
+
git(canonical, ["worktree", "add", "-b", branch, path, resolvedBase]);
|
|
168
|
+
const ownerToken = randomBytes(16).toString("hex");
|
|
169
|
+
writeFileSync(
|
|
170
|
+
`${path}${OWNER_FILE_SUFFIX}`,
|
|
171
|
+
`${JSON.stringify({ version: 1, kind: "clio-task-worktree", root: canonical, runId, branch, base: resolvedBase, ownerToken }, null, 2)}\n`,
|
|
172
|
+
{ encoding: "utf8", flag: "wx" },
|
|
173
|
+
);
|
|
174
|
+
return { root: canonical, runId, path, branch, base: resolvedBase, ownerToken };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function assertOwnership(worktree: TaskWorktree): void {
|
|
178
|
+
const expected = join(worktree.root, ".clio-coder", "worktrees", worktree.runId);
|
|
179
|
+
if (
|
|
180
|
+
resolve(worktree.path) !== resolve(expected) ||
|
|
181
|
+
!isCanonicalWorktreePathInside(join(worktree.root, ".clio-coder", "worktrees"), worktree.path)
|
|
182
|
+
) {
|
|
183
|
+
throw new Error(`task worktree ${worktree.runId} has an invalid ownership path`);
|
|
184
|
+
}
|
|
185
|
+
if (!existsSync(`${worktree.path}${OWNER_FILE_SUFFIX}`))
|
|
186
|
+
throw new Error(`task worktree ${worktree.runId} has no ownership file`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function commitTaskWorktree(worktree: TaskWorktree, message = `Clio task ${worktree.runId}`): boolean {
|
|
190
|
+
assertOwnership(worktree);
|
|
191
|
+
return commitWorktreePath(worktree.path, COMMIT_IDENTITY, message);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function taskWorktreeDiffHash(worktree: Pick<TaskWorktree, "root" | "base" | "branch">): string {
|
|
195
|
+
const bytes = gitBytes(worktree.root, ["diff", `${worktree.base}..${worktree.branch}`]);
|
|
196
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function protectedPathsChangedByTaskBranch(
|
|
200
|
+
worktree: Pick<TaskWorktree, "root" | "branch">,
|
|
201
|
+
protectedPaths: ReadonlyArray<string>,
|
|
202
|
+
): string[] {
|
|
203
|
+
return protectedPathsChangedByWorktreeBranch(worktree.root, worktree.branch, protectedPaths);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function applyTaskWorktree(input: {
|
|
207
|
+
worktree: TaskWorktree;
|
|
208
|
+
apply: TaskWorktreeApply;
|
|
209
|
+
protectedPaths?: ReadonlyArray<string>;
|
|
210
|
+
}): TaskWorktreeReceipt {
|
|
211
|
+
assertOwnership(input.worktree);
|
|
212
|
+
commitTaskWorktree(input.worktree);
|
|
213
|
+
const receipt: TaskWorktreeReceipt = {
|
|
214
|
+
path: input.worktree.path,
|
|
215
|
+
branch: input.worktree.branch,
|
|
216
|
+
diffHash: taskWorktreeDiffHash(input.worktree),
|
|
217
|
+
apply: input.apply,
|
|
218
|
+
applied: false,
|
|
219
|
+
};
|
|
220
|
+
if (input.apply === "preserve") return receipt;
|
|
221
|
+
const protectedChanges = protectedPathsChangedByTaskBranch(input.worktree, input.protectedPaths ?? []);
|
|
222
|
+
if (protectedChanges.length > 0) return { ...receipt, reason: "protected_artifact_changed" };
|
|
223
|
+
const merged = mergeWorktreeBranch(input.worktree.root, input.worktree.branch, COMMIT_IDENTITY);
|
|
224
|
+
if (!merged.ok) return { ...receipt, reason: "worktree_merge_conflict" };
|
|
225
|
+
return { ...receipt, applied: true };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function cleanupTaskWorktree(worktree: TaskWorktree, deleteBranch: boolean): void {
|
|
229
|
+
assertOwnership(worktree);
|
|
230
|
+
try {
|
|
231
|
+
git(worktree.root, ["worktree", "remove", "--force", worktree.path]);
|
|
232
|
+
} catch {
|
|
233
|
+
if (existsSync(worktree.path)) rmSync(worktree.path, { recursive: true, force: true });
|
|
234
|
+
git(worktree.root, ["worktree", "prune"]);
|
|
235
|
+
}
|
|
236
|
+
if (deleteBranch) git(worktree.root, ["branch", "-D", worktree.branch]);
|
|
237
|
+
rmSync(`${worktree.path}${OWNER_FILE_SUFFIX}`, { force: true });
|
|
238
|
+
}
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
parseProjectVerifierCatalogText,
|
|
25
25
|
} from "./catalog.js";
|
|
26
26
|
import { verifyTool } from "./index.js";
|
|
27
|
-
import { discoverDeclaredChecksAtRoot } from "./scripts.js";
|
|
27
|
+
import { discoverDeclaredChecksAtRoot, discoverDeclaredProjectEntriesAtRoot } from "./scripts.js";
|
|
28
28
|
|
|
29
29
|
export type VerifierProposalAuthority = "project-declared" | "toolchain-defined";
|
|
30
30
|
|
|
@@ -34,6 +34,8 @@ export type VerifierSignalKind =
|
|
|
34
34
|
| "cargo"
|
|
35
35
|
| "cmake-preset"
|
|
36
36
|
| "python-runner"
|
|
37
|
+
| "just-recipe"
|
|
38
|
+
| "make-target"
|
|
37
39
|
| "go-module"
|
|
38
40
|
| "validation-contract"
|
|
39
41
|
| "manual-entry";
|
|
@@ -149,6 +151,12 @@ export interface VerifierAuthoringWorkflowOptions {
|
|
|
149
151
|
runCheck?: (id: string) => Promise<ToolResult>;
|
|
150
152
|
}
|
|
151
153
|
|
|
154
|
+
export interface DeclaredProjectCommand {
|
|
155
|
+
id: string;
|
|
156
|
+
command: string[];
|
|
157
|
+
provenance: VerifierProvenance;
|
|
158
|
+
}
|
|
159
|
+
|
|
152
160
|
interface RawProposal {
|
|
153
161
|
preferredId: string;
|
|
154
162
|
description: string;
|
|
@@ -466,6 +474,58 @@ function pythonProposals(workspaceRoot: string, diagnostics: string[]): RawPropo
|
|
|
466
474
|
return proposals;
|
|
467
475
|
}
|
|
468
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Discover exact invocation vectors from project declarations for fleet command
|
|
479
|
+
* authoring. This shares the verifier authoring readers and provenance model,
|
|
480
|
+
* while retaining entries that are not verification-family names.
|
|
481
|
+
*/
|
|
482
|
+
export function discoverDeclaredProjectCommands(workspaceRoot = process.cwd()): DeclaredProjectCommand[] {
|
|
483
|
+
const commands: DeclaredProjectCommand[] = [];
|
|
484
|
+
const add = (id: string, command: string[], pathValue: string, detail: string, kind: VerifierSignalKind): void => {
|
|
485
|
+
commands.push({
|
|
486
|
+
id,
|
|
487
|
+
command,
|
|
488
|
+
provenance: { kind, path: pathValue, detail, authority: "project-declared" },
|
|
489
|
+
});
|
|
490
|
+
};
|
|
491
|
+
for (const entry of discoverDeclaredProjectEntriesAtRoot(workspaceRoot)) {
|
|
492
|
+
add(entry.id, entry.command, entry.path, entry.detail, entry.kind);
|
|
493
|
+
}
|
|
494
|
+
const pyprojectText = regularFileText(path.join(workspaceRoot, "pyproject.toml"), workspaceRoot);
|
|
495
|
+
if (typeof pyprojectText === "string") {
|
|
496
|
+
const document = parseTomlDocument(pyprojectText);
|
|
497
|
+
if (document !== null) {
|
|
498
|
+
for (const [tablePath, label] of [
|
|
499
|
+
[["project", "scripts"], "project.scripts"],
|
|
500
|
+
[["tool", "poetry", "scripts"], "tool.poetry.scripts"],
|
|
501
|
+
] as const) {
|
|
502
|
+
const scripts = tomlTableAt(document, tablePath);
|
|
503
|
+
if (scripts === null) continue;
|
|
504
|
+
for (const [name, target] of Object.entries(scripts).sort(([left], [right]) => compareCodepoints(left, right))) {
|
|
505
|
+
if (typeof target === "string") add(name, [name], "pyproject.toml", `[${label}] entry '${name}'`, "python-runner");
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
for (const [tablePath, module, id, label] of [
|
|
509
|
+
[["tool", "pytest", "ini_options"], "pytest", "pytest", "tool.pytest.ini_options"],
|
|
510
|
+
[["tool", "tox"], "tox", "tox", "tool.tox"],
|
|
511
|
+
[["tool", "nox"], "nox", "nox", "tool.nox"],
|
|
512
|
+
] as const) {
|
|
513
|
+
if (tomlTableAt(document, tablePath) !== null)
|
|
514
|
+
add(id, ["python", "-m", module], "pyproject.toml", `[${label}]`, "python-runner");
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
const seen = new Set<string>();
|
|
519
|
+
return commands.filter((entry) => {
|
|
520
|
+
let id = slug(entry.id, "command");
|
|
521
|
+
let suffix = 2;
|
|
522
|
+
while (seen.has(id)) id = `${slug(entry.id, "command")}-${suffix++}`;
|
|
523
|
+
seen.add(id);
|
|
524
|
+
entry.id = id;
|
|
525
|
+
return true;
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
469
529
|
function goProposals(workspaceRoot: string, diagnostics: string[]): RawProposal[] {
|
|
470
530
|
const relative = "go.mod";
|
|
471
531
|
const text = regularFileText(path.join(workspaceRoot, relative), workspaceRoot);
|
|
@@ -21,6 +21,14 @@ import {
|
|
|
21
21
|
|
|
22
22
|
export type DeclaredCheckDiscoveryResult = { ok: true; sources: DeclaredCheckSource[] } | { ok: false; reason: string };
|
|
23
23
|
|
|
24
|
+
export interface DeclaredProjectEntry {
|
|
25
|
+
id: string;
|
|
26
|
+
command: string[];
|
|
27
|
+
path: string;
|
|
28
|
+
detail: string;
|
|
29
|
+
kind: "package-script" | "just-recipe" | "make-target";
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
function repositoryRelativeCwd(workspaceRoot: string, resolved: string): string {
|
|
25
33
|
const relative = path.relative(workspaceRoot, resolved);
|
|
26
34
|
return relative.length === 0 ? "." : relative.split(path.sep).join("/");
|
|
@@ -43,6 +51,60 @@ function packageCheckSource(packageRoot: string, workspaceRoot: string): Declare
|
|
|
43
51
|
return { kind: "package.json", path: packagePath, checks };
|
|
44
52
|
}
|
|
45
53
|
|
|
54
|
+
/** Discover every exact project-declared entry without promoting it to a verifier check. */
|
|
55
|
+
export function discoverDeclaredProjectEntriesAtRoot(workspaceRoot: string): DeclaredProjectEntry[] {
|
|
56
|
+
const entries: DeclaredProjectEntry[] = [];
|
|
57
|
+
const packagePath = path.join(workspaceRoot, "package.json");
|
|
58
|
+
if (existsSync(packagePath)) {
|
|
59
|
+
const pkg = parsePackageJson(packagePath);
|
|
60
|
+
if (pkg.ok) {
|
|
61
|
+
for (const name of Object.keys(pkg.scripts).sort()) {
|
|
62
|
+
if (typeof pkg.scripts[name] !== "string") continue;
|
|
63
|
+
entries.push({
|
|
64
|
+
id: name,
|
|
65
|
+
command: ["npm", "run", name],
|
|
66
|
+
path: "package.json",
|
|
67
|
+
detail: `package.json script '${name}'`,
|
|
68
|
+
kind: "package-script",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const relative of ["justfile", "Justfile"] as const) {
|
|
74
|
+
const filePath = path.join(workspaceRoot, relative);
|
|
75
|
+
if (!existsSync(filePath)) continue;
|
|
76
|
+
const text = readFileSync(filePath, "utf8");
|
|
77
|
+
for (const match of text.matchAll(/^([A-Za-z0-9][A-Za-z0-9_-]*)\s*(?:[^:=\n]*)?:\s*(?:#.*)?$/gmu)) {
|
|
78
|
+
const name = match[1];
|
|
79
|
+
if (name === undefined || name.startsWith("_")) continue;
|
|
80
|
+
entries.push({
|
|
81
|
+
id: name,
|
|
82
|
+
command: ["just", name],
|
|
83
|
+
path: relative,
|
|
84
|
+
detail: `just recipe '${name}'`,
|
|
85
|
+
kind: "just-recipe",
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
const makePath = path.join(workspaceRoot, "Makefile");
|
|
91
|
+
if (existsSync(makePath)) {
|
|
92
|
+
const text = readFileSync(makePath, "utf8");
|
|
93
|
+
for (const match of text.matchAll(/^([A-Za-z0-9][A-Za-z0-9_.-]*)\s*:(?![=])[^\n]*$/gmu)) {
|
|
94
|
+
const name = match[1];
|
|
95
|
+
if (name === undefined || name.startsWith(".")) continue;
|
|
96
|
+
entries.push({
|
|
97
|
+
id: name,
|
|
98
|
+
command: ["make", name],
|
|
99
|
+
path: "Makefile",
|
|
100
|
+
detail: `Makefile target '${name}'`,
|
|
101
|
+
kind: "make-target",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return entries;
|
|
106
|
+
}
|
|
107
|
+
|
|
46
108
|
function providerCollision(sources: ReadonlyArray<DeclaredCheckSource>): string | null {
|
|
47
109
|
const seen = new Map<string, DeclaredCheck>();
|
|
48
110
|
for (const source of sources) {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "../domains/dispatch/budget-envelope.js";
|
|
8
8
|
import type { ReceiptIntegrityResult } from "../domains/dispatch/receipt-integrity.js";
|
|
9
9
|
import type { RunReceipt, RunReceiptVerification } from "../domains/dispatch/types.js";
|
|
10
|
+
import { formatTrustAxes, formatTrustSummary } from "../domains/evidence/trust-projection.js";
|
|
10
11
|
import { adaptRunReceiptTrustStatus, type CanonicalTrustStatus } from "../domains/evidence/trust-status.js";
|
|
11
12
|
import { receiptResponseModelIdObservationLabel } from "./dispatch-event-text.js";
|
|
12
13
|
|
|
@@ -127,10 +128,10 @@ export function receiptEvidenceLabels(
|
|
|
127
128
|
verification: RunReceiptVerification,
|
|
128
129
|
integrity: ReceiptIntegrityResult,
|
|
129
130
|
): string[] {
|
|
130
|
-
const status = adaptRunReceiptTrustStatus({ ...receipt, verification }, { integrity });
|
|
131
|
-
const canonical =
|
|
131
|
+
const status = adaptRunReceiptTrustStatus({ ...receipt, verification: verification }, { integrity });
|
|
132
|
+
const canonical = canonicalTrustLabels(status);
|
|
132
133
|
if (!integrity.ok) {
|
|
133
|
-
return [canonical, `receipt_integrity=FAILED reason=${JSON.stringify(integrity.reason)}`];
|
|
134
|
+
return [...canonical, `receipt_integrity=FAILED reason=${JSON.stringify(integrity.reason)}`];
|
|
134
135
|
}
|
|
135
136
|
const briefing =
|
|
136
137
|
receipt.briefing === undefined
|
|
@@ -154,9 +155,10 @@ export function receiptEvidenceLabels(
|
|
|
154
155
|
`budget_reason=${JSON.stringify(formatBudgetReasons(receipt.budget))}`,
|
|
155
156
|
];
|
|
156
157
|
return [
|
|
157
|
-
canonical,
|
|
158
|
+
...canonical,
|
|
158
159
|
`receipt_integrity=verified/v${receipt.integrity.version}/${receipt.integrity.algorithm}`,
|
|
159
160
|
`evidence_verification=${verification.state}/${verification.basis}`,
|
|
161
|
+
`host_verification=${receipt.hostVerification?.status ?? "not_requested"}`,
|
|
160
162
|
...(responseModelIdObservation ? [responseModelIdObservation] : []),
|
|
161
163
|
...budget,
|
|
162
164
|
...receiptAdmissionLabels(receipt),
|
|
@@ -166,16 +168,13 @@ export function receiptEvidenceLabels(
|
|
|
166
168
|
];
|
|
167
169
|
}
|
|
168
170
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
`autonomyEnforcement:${status.autonomyEnforcement.state}`,
|
|
177
|
-
`completionEvidence:${status.completionEvidence.state}`,
|
|
178
|
-
].join(" ");
|
|
171
|
+
/**
|
|
172
|
+
* The compact projection first, then the canonical axis line, both from the
|
|
173
|
+
* shared projection so the dispatch and monitor text can never spell a state
|
|
174
|
+
* differently from `evidence inspect` or the board.
|
|
175
|
+
*/
|
|
176
|
+
function canonicalTrustLabels(status: CanonicalTrustStatus): string[] {
|
|
177
|
+
return [`trust=${JSON.stringify(formatTrustSummary(status))}`, formatTrustAxes(status)];
|
|
179
178
|
}
|
|
180
179
|
|
|
181
180
|
/**
|
|
@@ -191,6 +190,14 @@ export function workerTextLabel(status: CanonicalTrustStatus): string {
|
|
|
191
190
|
return "reconnaissance output (advisory leads, not validation evidence):";
|
|
192
191
|
case "unknown":
|
|
193
192
|
return "worker claims (validation not observable at this layer):";
|
|
193
|
+
// The three remaining states were one label. The evidence bundle tells
|
|
194
|
+
// a failed check, an inferred claim, and no validation at all apart, so
|
|
195
|
+
// the terminal must too or it hands the operator a coarser verdict than
|
|
196
|
+
// the report for the same run.
|
|
197
|
+
case "failed":
|
|
198
|
+
return "worker claims (validation failed; a check ran and did not pass):";
|
|
199
|
+
case "ungrounded":
|
|
200
|
+
return "worker claims (inferred; validation claimed, none observed):";
|
|
194
201
|
default:
|
|
195
202
|
return "worker claims (unverified prose):";
|
|
196
203
|
}
|
|
@@ -162,7 +162,8 @@ interface WorkerSpecFields {
|
|
|
162
162
|
*/
|
|
163
163
|
autonomy?: AutonomyLevel;
|
|
164
164
|
/**
|
|
165
|
-
* Absolute
|
|
165
|
+
* Absolute path boundaries write-class tool calls are confined to for this run.
|
|
166
|
+
* Exact files omit a trailing slash and subtrees retain one.
|
|
166
167
|
* Enforced at the shared worker safety seam so a write/edit target outside
|
|
167
168
|
* every root is a final block. Only set on runtimes that mediate per-tool
|
|
168
169
|
* calls (native, claude-sdk); dispatch refuses it on subprocess runtimes.
|
|
@@ -225,6 +226,7 @@ const TOOL_PROFILE_NAMES = [
|
|
|
225
226
|
"minimal-local",
|
|
226
227
|
"science-local",
|
|
227
228
|
"full-agent",
|
|
229
|
+
"council-read-only",
|
|
228
230
|
] as const satisfies ReadonlyArray<ToolProfileName>;
|
|
229
231
|
const WORKER_PRODUCTS = ["orientation"] as const satisfies ReadonlyArray<AgentProduct>;
|
|
230
232
|
const TARGET_LIFECYCLES = ["user-managed", "clio-managed"] as const;
|
package/dist/chunk-HC4CLZ2Y.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { createRequire as __clioCreateRequire } from "node:module"; const require = __clioCreateRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
withStateFileLock
|
|
4
|
-
} from "./chunk-IKCO5N3L.js";
|
|
5
|
-
import {
|
|
6
|
-
safeResourceWrite
|
|
7
|
-
} from "./chunk-WEPFGWHJ.js";
|
|
8
|
-
import {
|
|
9
|
-
init_esm_shims
|
|
10
|
-
} from "./chunk-3R73A4XB.js";
|
|
11
|
-
|
|
12
|
-
// src/domains/observability/evidence-index.ts
|
|
13
|
-
init_esm_shims();
|
|
14
|
-
import { readFileSync } from "node:fs";
|
|
15
|
-
import { join } from "node:path";
|
|
16
|
-
var MAX_EVIDENCE_INDEX_ROWS = 1e3;
|
|
17
|
-
var EVIDENCE_INDEX_FILE = "evidence-index.json";
|
|
18
|
-
var evidenceIndexWriteQueue = Promise.resolve();
|
|
19
|
-
function indexPath(stateDir) {
|
|
20
|
-
return join(stateDir, EVIDENCE_INDEX_FILE);
|
|
21
|
-
}
|
|
22
|
-
function isEvidenceIndexRow(value) {
|
|
23
|
-
if (typeof value !== "object" || value === null) return false;
|
|
24
|
-
const row = value;
|
|
25
|
-
return typeof row.runId === "string" && typeof row.evidenceId === "string" && Array.isArray(row.tags) && row.tags.every((tag) => typeof tag === "string") && typeof row.firstPassSuccess === "boolean" && typeof row.findingCount === "number" && typeof row.generatedAt === "string";
|
|
26
|
-
}
|
|
27
|
-
function readEvidenceIndex(stateDir) {
|
|
28
|
-
let raw;
|
|
29
|
-
try {
|
|
30
|
-
raw = readFileSync(indexPath(stateDir), "utf8");
|
|
31
|
-
} catch {
|
|
32
|
-
return [];
|
|
33
|
-
}
|
|
34
|
-
let parsed;
|
|
35
|
-
try {
|
|
36
|
-
parsed = JSON.parse(raw);
|
|
37
|
-
} catch {
|
|
38
|
-
return [];
|
|
39
|
-
}
|
|
40
|
-
if (!Array.isArray(parsed)) return [];
|
|
41
|
-
return parsed.filter(isEvidenceIndexRow);
|
|
42
|
-
}
|
|
43
|
-
async function writeEvidenceIndexRow(stateDir, row) {
|
|
44
|
-
let bounded = [];
|
|
45
|
-
await withStateFileLock(indexPath(stateDir), () => {
|
|
46
|
-
const existing = readEvidenceIndex(stateDir).filter((entry) => entry.runId !== row.runId);
|
|
47
|
-
existing.push(row);
|
|
48
|
-
bounded = existing.length > MAX_EVIDENCE_INDEX_ROWS ? existing.slice(-MAX_EVIDENCE_INDEX_ROWS) : existing;
|
|
49
|
-
safeResourceWrite(indexPath(stateDir), `${JSON.stringify(bounded, null, 2)}
|
|
50
|
-
`, { encoding: "utf8" });
|
|
51
|
-
});
|
|
52
|
-
return bounded;
|
|
53
|
-
}
|
|
54
|
-
async function writeEvidenceIndexRowQueued(stateDir, row) {
|
|
55
|
-
let written = [];
|
|
56
|
-
const write = evidenceIndexWriteQueue.then(async () => {
|
|
57
|
-
written = await writeEvidenceIndexRow(stateDir, row);
|
|
58
|
-
});
|
|
59
|
-
evidenceIndexWriteQueue = write.catch(() => void 0);
|
|
60
|
-
await write;
|
|
61
|
-
return written;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export {
|
|
65
|
-
readEvidenceIndex,
|
|
66
|
-
writeEvidenceIndexRowQueued
|
|
67
|
-
};
|
|
68
|
-
//# sourceMappingURL=chunk-HC4CLZ2Y.js.map
|