@iowarp/clio-coder 0.3.3 → 0.3.6
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 +74 -0
- package/CONTRIBUTING.md +7 -7
- package/README.md +3 -3
- package/dist/{acp-P2AQILE2.js → acp-2BEHC4DL.js} +9 -8
- package/dist/{agents-72W3BI7I.js → agents-LNNFTM53.js} +29 -24
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-5TWEIYDN.js → auth-KXXFI2VS.js} +14 -10
- package/dist/{chunk-GGXXDWE4.js → chunk-22NAGB7X.js} +2 -2
- package/dist/{chunk-YCWGATWI.js → chunk-24I7BN55.js} +2 -2
- package/dist/{chunk-EKMEHE4H.js → chunk-33YXPOE3.js} +2 -3
- package/dist/chunk-3BPUFZDL.js +37 -0
- package/dist/chunk-43AOLP7E.js +375 -0
- package/dist/{chunk-ZDOOVTXZ.js → chunk-4OC57DA6.js} +27 -4
- package/dist/{chunk-6SGHMWE3.js → chunk-5JGRAMKL.js} +5 -5
- package/dist/{chunk-V6RTAOC2.js → chunk-6US73PDB.js} +572 -51
- package/dist/{chunk-5UFT4SUX.js → chunk-6XXKFVSN.js} +3 -3
- package/dist/{chunk-A3CYT5EX.js → chunk-AD2SYQYC.js} +55 -2
- package/dist/chunk-AOCYTWAV.js +449 -0
- package/dist/chunk-CFGTUFWB.js +67 -0
- package/dist/chunk-CJUB2JJ2.js +1478 -0
- package/dist/{chunk-FNTMWMX5.js → chunk-CKXWIANG.js} +14 -12
- package/dist/{chunk-PIWWS5BL.js → chunk-CYQKWTG3.js} +63 -78
- package/dist/{chunk-LZSJBIVT.js → chunk-DJVECN66.js} +271 -762
- package/dist/{chunk-CBCAPZAA.js → chunk-E25LMLRW.js} +2 -2
- package/dist/{chunk-ZWMF7253.js → chunk-E2ER4LJF.js} +304 -9
- package/dist/{chunk-STBPMHSX.js → chunk-EKY57CSP.js} +51 -84
- package/dist/{chunk-DUYJ5IO6.js → chunk-EYPA3EGJ.js} +12 -4
- package/dist/{chunk-M6SHUN7Q.js → chunk-FO5ZOVUY.js} +2 -2
- package/dist/chunk-FYYLNIL5.js +313 -0
- package/dist/{chunk-OQ33BKR3.js → chunk-G7MUEIGA.js} +3 -60
- package/dist/chunk-GEYXPTRF.js +613 -0
- package/dist/chunk-GOXNB3AO.js +261 -0
- package/dist/{chunk-G4BMMOKF.js → chunk-HVDIIIQW.js} +2 -2
- package/dist/chunk-HWUFFB6L.js +83 -0
- package/dist/{chunk-4XUGQOHA.js → chunk-K7T3E2SR.js} +15 -8
- package/dist/chunk-K7VKOLQQ.js +15 -0
- package/dist/{chunk-UFIIWP2H.js → chunk-KHSFENX2.js} +8 -8
- package/dist/{chunk-BMEMKKIT.js → chunk-KOHPCX4K.js} +2 -2
- package/dist/chunk-LCGCVYZ4.js +57 -0
- package/dist/chunk-LL4KHSZI.js +22 -0
- package/dist/{chunk-PAJK6MAQ.js → chunk-LYF7OHWH.js} +42 -15
- package/dist/{chunk-POHLU5DW.js → chunk-M6L6IDJG.js} +3 -3
- package/dist/{chunk-5UUP6MWO.js → chunk-MV3K5QF2.js} +5 -436
- package/dist/{chunk-X4RCMKVQ.js → chunk-NDINPTJ4.js} +2 -2
- package/dist/{chunk-TZK7PACC.js → chunk-NILBFAPG.js} +14 -8
- package/dist/chunk-ODFEOB4F.js +1082 -0
- package/dist/{chunk-AGYYIBLL.js → chunk-OH3TOQTB.js} +6 -2
- package/dist/chunk-OZNBF4L3.js +23 -0
- package/dist/{chunk-DSELYM6W.js → chunk-PBTHKCPN.js} +30 -10
- package/dist/{verify-375KUB3Y.js → chunk-PCZJO5TI.js} +127 -42
- package/dist/{chunk-ED4KHGC3.js → chunk-PPAMZ32Z.js} +9 -2
- package/dist/{chunk-SRDMMSEP.js → chunk-QM3F2GKX.js} +1063 -1645
- package/dist/{chunk-X6IAEBZR.js → chunk-QNQHSOLF.js} +7 -7
- package/dist/{chunk-OC7FIQPC.js → chunk-R46L2BIR.js} +10 -7
- package/dist/{chunk-2TLUCQVG.js → chunk-RD5U66HV.js} +3 -3
- package/dist/{chunk-6N5PTWMY.js → chunk-RY3LY4J5.js} +50 -13
- package/dist/{chunk-OKGUZO2U.js → chunk-SPULKLCF.js} +4 -3
- package/dist/{chunk-OOJYHWRB.js → chunk-TSHXZTOQ.js} +6 -5
- package/dist/chunk-TZSKNMZG.js +434 -0
- package/dist/{chunk-7MNJORFF.js → chunk-UL3WSD3F.js} +6 -1
- package/dist/{chunk-VJWL6YS5.js → chunk-UUVG37B4.js} +2 -2
- package/dist/{chunk-COU2UHX6.js → chunk-VEZEGCGW.js} +170 -2
- package/dist/chunk-W6GROXXM.js +69 -0
- package/dist/{chunk-OAO4GE4M.js → chunk-WHGPSPT5.js} +2 -2
- package/dist/chunk-WHJYKASB.js +677 -0
- package/dist/{chunk-ORBHGJC5.js → chunk-WR67VIZY.js} +3 -3
- package/dist/{chunk-YHZX5GEU.js → chunk-XAKHZX5N.js} +2 -2
- package/dist/{chunk-TZTZS7QK.js → chunk-XE2VEJHX.js} +5 -3
- package/dist/{chunk-LM5TQCJZ.js → chunk-XF5N4U5A.js} +8 -7
- package/dist/{chunk-LWLEKMDQ.js → chunk-XXQNGV4M.js} +1073 -552
- package/dist/{chunk-KZWTDYJF.js → chunk-XYDYPRZI.js} +7 -7
- package/dist/chunk-ZGVHUX3M.js +66 -0
- package/dist/{chunk-LW6DSM3M.js → chunk-ZRGEBJ4T.js} +1192 -1119
- package/dist/{chunk-2DJ2KNFG.js → chunk-ZXF4XRKW.js} +202 -40
- package/dist/chunk-ZZMN5OM4.js +122 -0
- package/dist/cli/index.js +34 -30
- package/dist/{clio-JOU4FXVA.js → clio-M2KGYUFZ.js} +7 -6
- package/dist/{code-nav-7AX6FYE6.js → code-nav-GQNL7XA6.js} +8 -6
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-KELWS457.js → components-5TTYYX6G.js} +3 -3
- package/dist/{config-XCDVKR23.js → config-XUUYQIWO.js} +47 -35
- package/dist/{configure-4GAP54ZW.js → configure-IHJ7YOMV.js} +18 -15
- package/dist/{context-77FM5DV5.js → context-74JLXAWD.js} +18 -10
- package/dist/{context-4UOGGLQ5.js → context-75MIWW3U.js} +41 -29
- package/dist/{context-5VKGUVJJ.js → context-ZQ7SIFJV.js} +85 -9
- package/dist/{context-clear-XXJRLCJJ.js → context-clear-GYKWNUML.js} +41 -29
- package/dist/{context-index-BZ4UYMTC.js → context-index-SSR5ECNE.js} +3 -3
- package/dist/context-working-set-UX5KEP4J.js +1553 -0
- package/dist/{dispatch-runner-QPRDDBDX.js → dispatch-runner-GIJBHNFL.js} +47 -32
- package/dist/{docs-2C2LTVT2.js → docs-6FZSCG5B.js} +3 -3
- package/dist/{doctor-HR46URBJ.js → doctor-SVJ5BZCW.js} +12 -12
- package/dist/{eval-XSSNATB4.js → eval-CG6LLBLD.js} +54 -238
- package/dist/{evidence-6HG2PY2B.js → evidence-ZYFIEN42.js} +57 -28
- package/dist/{evolve-K7YU3NCY.js → evolve-QGEXEMDW.js} +36 -25
- package/dist/{extensions-QVDOHDGJ.js → extensions-ADGNCJJD.js} +3 -3
- package/dist/{fleet-VY3HHKN6.js → fleet-S5R4ZOQY.js} +73 -44
- package/dist/{fleet-preflight-DDN536IT.js → fleet-preflight-BHSNPBMH.js} +3 -3
- package/dist/{init-JYGXI3FK.js → init-5DRU55YR.js} +49 -37
- package/dist/memory-7YKKR6UC.js +467 -0
- package/dist/{models-I5QWSEOM.js → models-ZPOLRU2C.js} +24 -21
- package/dist/{monitor-GE4ID3IA.js → monitor-US5F5YGZ.js} +73 -46
- package/dist/{orchestrator-EM5MC3HM.js → orchestrator-E2AL4T5N.js} +1624 -1007
- package/dist/{paths-UXLN5YYZ.js → paths-E7KYAQWE.js} +3 -3
- package/dist/{reset-L2FQEE3E.js → reset-KZ652EK6.js} +6 -5
- package/dist/{run-ZU3QMZPZ.js → run-SRNBKDWD.js} +76 -54
- package/dist/{share-S5BZQC5I.js → share-CGZE33UP.js} +7 -6
- package/dist/{skills-X5VXCRNQ.js → skills-S2X4DLY5.js} +4 -4
- package/dist/{skills-eval-WKIHWTHR.js → skills-eval-W2GGIC4R.js} +40 -29
- package/dist/{targets-SNCPI2NR.js → targets-54SWINWB.js} +28 -23
- package/dist/{terminal-lease-BNAHVHBS.js → terminal-lease-SAIF2OGY.js} +6 -4
- package/dist/{uninstall-FZCQCDKC.js → uninstall-BVLWXKBT.js} +3 -3
- package/dist/{upgrade-JQHHPQ4K.js → upgrade-JKAR27XC.js} +20 -19
- package/dist/{usage-OR4O5SMZ.js → usage-MSAWCLX4.js} +79 -36
- package/dist/verifiers-NCBTHHN2.js +1220 -0
- package/dist/verify-X5HDROLA.js +25 -0
- package/dist/{wiki-generate-UEXP2ARI.js → wiki-generate-GUSOQ6ZP.js} +50 -37
- package/dist/worker/entry.js +90 -70
- package/dist/{workspace-G4ZWUIPR.js → workspace-ZJ6BFM3Q.js} +4 -4
- package/docs/README.md +8 -7
- package/docs/acp.md +1 -1
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/artifact-placement.md +1 -2
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +60 -26
- package/docs/config-knobs-audit.md +1 -2
- package/docs/configuration-and-targets.md +26 -1
- package/docs/context-engine.md +67 -13
- package/docs/context-working-set.md +194 -0
- package/docs/development-pipeline.md +1 -1
- package/docs/documentation-coverage.md +6 -6
- package/docs/documentation-guide.md +7 -6
- package/docs/environment-variables.md +2 -1
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +4 -32
- package/docs/evidence-and-memory.md +139 -7
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +2 -2
- package/docs/fleet-dispatch.md +49 -8
- package/docs/glossary.md +21 -1
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +19 -2
- package/docs/model-catalog.md +7 -9
- package/docs/observability.md +4 -4
- package/docs/proactive-memory.md +26 -16
- package/docs/prompt-envelope-and-tools.md +7 -5
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +43 -40
- package/docs/safety-model.md +49 -8
- package/docs/scientific-validation.md +21 -3
- package/docs/session-lifecycle.md +3 -3
- package/docs/skills-marketplace.md +1 -1
- package/docs/tool-usage.md +79 -12
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +38 -4
- package/docs/worker-dispatch-mechanics.md +11 -1
- package/package.json +13 -13
- package/skills/meta/clio-test/SKILL.md +20 -17
- package/skills/meta/clio-test/evals.md +3 -3
- package/skills/meta/clio-test/references/harness.md +35 -6
- package/skills/meta/clio-test/references/test-map.md +20 -10
- package/skills/registry.yaml +2 -2
- package/skills/skill-marketplace.json +1 -1
- package/src/cli/agents.ts +2 -3
- package/src/cli/argv.ts +14 -1
- package/src/cli/context-working-set.ts +513 -0
- package/src/cli/context.ts +8 -0
- package/src/cli/evidence.ts +20 -2
- package/src/cli/fleet.ts +15 -0
- package/src/cli/index.ts +5 -1
- package/src/cli/memory.ts +272 -10
- package/src/cli/modes/json-stream.ts +2 -2
- package/src/cli/modes/print.ts +12 -1
- package/src/cli/run.ts +22 -2
- package/src/cli/targets.ts +12 -3
- package/src/cli/usage.ts +55 -7
- package/src/cli/verifiers.ts +325 -0
- package/src/core/bash-exec.ts +39 -14
- package/src/core/bus-events.ts +22 -4
- package/src/core/config.ts +54 -0
- package/src/core/defaults.ts +50 -3
- package/src/core/response-model-id.ts +134 -0
- package/src/core/toml.ts +62 -0
- package/src/core/verification-scripts.ts +6 -0
- package/src/core/workspace-files.ts +0 -1
- package/src/domains/agents/builtins/architect.md +1 -1
- package/src/domains/agents/builtins/verifier.md +3 -0
- package/src/domains/agents/catalog.ts +5 -4
- package/src/domains/agents/recipe.ts +54 -14
- package/src/domains/agents/result-contract.ts +7 -4
- package/src/domains/config/classify.ts +1 -0
- package/src/domains/context/bootstrap.ts +36 -27
- package/src/domains/context/project-metadata.ts +19 -63
- package/src/domains/context/prompt-context.ts +8 -0
- package/src/domains/context/working-set/contract.ts +161 -0
- package/src/domains/context/working-set/defaults.ts +28 -0
- package/src/domains/context/working-set/engine.ts +203 -0
- package/src/domains/context/working-set/fold.ts +62 -0
- package/src/domains/context/working-set/horizon.ts +38 -0
- package/src/domains/context/working-set/marker.ts +103 -0
- package/src/domains/context/working-set/path-index.ts +436 -0
- package/src/domains/context/working-set/payload.ts +152 -0
- package/src/domains/context/working-set/policies/age-horizon.ts +55 -0
- package/src/domains/context/working-set/policies/index.ts +20 -0
- package/src/domains/context/working-set/policies/structural.ts +160 -0
- package/src/domains/context/working-set/project.ts +132 -0
- package/src/domains/context/working-set/protect.ts +109 -0
- package/src/domains/context/working-set/recall.ts +177 -0
- package/src/domains/context/working-set/replay/controls.ts +112 -0
- package/src/domains/context/working-set/replay/load-clio.ts +199 -0
- package/src/domains/context/working-set/replay/metrics.ts +185 -0
- package/src/domains/context/working-set/replay/reference-graph.ts +79 -0
- package/src/domains/context/working-set/replay/report.ts +139 -0
- package/src/domains/context/working-set/replay/runner.ts +325 -0
- package/src/domains/context/working-set/replay/synthetic.ts +422 -0
- package/src/domains/context/working-set/replay/trace.ts +21 -0
- package/src/domains/context/working-set/visible.ts +54 -0
- package/src/domains/dispatch/budget-envelope.ts +396 -0
- package/src/domains/dispatch/contract.ts +2 -0
- package/src/domains/dispatch/extension.ts +81 -27
- package/src/domains/dispatch/orphan-recovery.ts +1 -0
- package/src/domains/dispatch/receipt-integrity.ts +4 -0
- package/src/domains/dispatch/state.ts +1 -0
- package/src/domains/dispatch/types.ts +10 -3
- package/src/domains/dispatch/validation.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +14 -3
- package/src/domains/eval/metrics/evidence.ts +0 -116
- package/src/domains/eval/metrics/invariants.ts +1 -1
- package/src/domains/eval/runners/clio-run.ts +1 -10
- package/src/domains/eval/runners/external-command.ts +2 -29
- package/src/domains/eval/schema/suite.ts +0 -7
- package/src/domains/eval/suites/run.ts +1 -7
- package/src/domains/evidence/build.ts +112 -45
- package/src/domains/evidence/eval.ts +24 -7
- package/src/domains/evidence/index.ts +53 -0
- package/src/domains/evidence/ordering.ts +12 -0
- package/src/domains/evidence/run-trust.ts +221 -0
- package/src/domains/evidence/store.ts +46 -6
- package/src/domains/evidence/trust-status.ts +854 -0
- package/src/domains/evidence/types.ts +26 -0
- package/src/domains/memory/index.ts +22 -0
- package/src/domains/memory/operations.ts +58 -1
- package/src/domains/memory/promotion.ts +281 -0
- package/src/domains/memory/prompt-section.ts +25 -5
- package/src/domains/memory/proposal.ts +51 -7
- package/src/domains/memory/task-bank.ts +3 -2
- package/src/domains/memory/task-memory-handoff.ts +181 -24
- package/src/domains/memory/task-memory-policy.ts +3 -1
- package/src/domains/memory/types.ts +37 -0
- package/src/domains/memory/validate.ts +178 -0
- package/src/domains/middleware/memory-intervention.ts +38 -25
- package/src/domains/middleware/runtime.ts +6 -0
- package/src/domains/middleware/skills-reminder.ts +19 -4
- package/src/domains/middleware/stalled-turn.ts +208 -5
- package/src/domains/middleware/types.ts +10 -0
- package/src/domains/observability/contract.ts +6 -1
- package/src/domains/observability/cost.ts +20 -4
- package/src/domains/observability/extension.ts +2 -2
- package/src/domains/providers/index.ts +3 -0
- package/src/domains/providers/model-discovery.ts +9 -0
- package/src/domains/providers/runtime-resolution.ts +38 -1
- package/src/domains/providers/runtimes/common/probe-helpers.ts +97 -16
- package/src/domains/providers/types/context-window-slots.ts +18 -0
- package/src/domains/providers/types/runtime-descriptor.ts +3 -1
- package/src/domains/safety/autonomy.ts +1 -1
- package/src/domains/safety/call-target.ts +211 -14
- package/src/domains/safety/decision-presentation.ts +268 -0
- package/src/domains/safety/default-path-policy.ts +8 -0
- package/src/domains/safety/finish-contract.ts +4 -3
- package/src/domains/safety/policy-engine.ts +48 -6
- package/src/domains/safety/redaction.ts +73 -0
- package/src/domains/session/compaction/compact.ts +23 -1
- package/src/domains/session/compaction/cut-point.ts +2 -0
- package/src/domains/session/compaction/tokens.ts +16 -1
- package/src/domains/session/context-ledger.ts +12 -1
- package/src/domains/session/decision-board.ts +4 -0
- package/src/domains/session/entries.ts +110 -1
- package/src/domains/session/history.ts +68 -19
- package/src/domains/session/manager.ts +9 -2
- package/src/domains/session/migrations/index.ts +22 -3
- package/src/domains/session/usage.ts +24 -7
- package/src/engine/acp/event-mapper.ts +7 -0
- package/src/engine/acp/server.ts +32 -2
- package/src/engine/agent.ts +18 -1
- package/src/engine/apis/lmstudio.ts +25 -4
- package/src/engine/apis/openai-completions.ts +147 -22
- package/src/engine/claude/sdk-runtime.ts +8 -2
- package/src/engine/claude/tool-safety.ts +13 -0
- package/src/engine/loop-guard.ts +27 -3
- package/src/engine/session.ts +9 -3
- package/src/engine/worker-events.ts +4 -3
- package/src/engine/worker-runtime.ts +59 -54
- package/src/entry/orchestrator.ts +34 -5
- package/src/interactive/chat-loop-messages.ts +40 -6
- package/src/interactive/chat-loop.ts +13 -0
- package/src/interactive/chat-panel.ts +17 -1
- package/src/interactive/chat-renderer.ts +49 -24
- package/src/interactive/clio-editor.ts +44 -7
- package/src/interactive/context-meter.ts +10 -0
- package/src/interactive/context-overlay.ts +120 -7
- package/src/interactive/context-recall-command.ts +110 -0
- package/src/interactive/cost-overlay.ts +39 -8
- package/src/interactive/dispatch-board.ts +212 -35
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/interactive-application.ts +6 -1
- package/src/interactive/interactive-input-runtime.ts +11 -1
- package/src/interactive/interactive-presentation.ts +11 -1
- package/src/interactive/interactive-slash-runtime.ts +37 -1
- package/src/interactive/memory-overlay.ts +89 -4
- package/src/interactive/model-session-replay.ts +21 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +1 -1
- package/src/interactive/overlay-frame.ts +5 -2
- package/src/interactive/overlay-general-openers.ts +46 -1
- package/src/interactive/overlay-key-routing.ts +41 -1
- package/src/interactive/overlay-lifecycle.ts +11 -4
- package/src/interactive/overlay-permission-lifecycle.ts +23 -8
- package/src/interactive/overlay-session-lifecycle.ts +8 -4
- package/src/interactive/overlay-transitions.ts +11 -0
- package/src/interactive/overlays/ask-user.ts +74 -30
- package/src/interactive/overlays/decisions.ts +3 -1
- package/src/interactive/permission-hint.ts +35 -0
- package/src/interactive/permission-overlay.ts +95 -45
- package/src/interactive/renderers/tool-execution.ts +37 -51
- package/src/interactive/session-last-turn.ts +8 -1
- package/src/interactive/session-transcript.ts +2 -2
- package/src/interactive/session-usage-reseed.ts +36 -10
- package/src/interactive/slash-commands.ts +31 -4
- package/src/interactive/status/summary.ts +5 -0
- package/src/interactive/status/types.ts +5 -0
- package/src/interactive/terminal-lease.ts +1 -0
- package/src/interactive/turn-context.ts +333 -110
- package/src/interactive/turn-middleware.ts +7 -6
- package/src/interactive/turn-runtime.ts +37 -8
- package/src/interactive/turn-state.ts +3 -0
- package/src/interactive/worker-progress.ts +440 -0
- package/src/interactive/worker-stream.ts +51 -110
- package/src/tools/agent-tools.ts +39 -7
- package/src/tools/ask-user.ts +21 -1
- package/src/tools/bash.ts +144 -82
- package/src/tools/builtin-tool-catalog.ts +11 -5
- package/src/tools/context/index.ts +107 -5
- package/src/tools/context/surface.ts +3 -2
- package/src/tools/core-bootstrap.ts +21 -0
- package/src/tools/dispatch-arguments.ts +8 -0
- package/src/tools/dispatch-event-text.ts +19 -0
- package/src/tools/dispatch-runner.ts +9 -7
- package/src/tools/dispatch.ts +24 -1
- package/src/tools/monitor.ts +43 -20
- package/src/tools/registry.ts +72 -10
- package/src/tools/result-disposition.ts +706 -0
- package/src/tools/result-shaping.ts +321 -20
- package/src/tools/safe-exec.ts +2 -0
- package/src/tools/verify/authoring.ts +1120 -0
- package/src/tools/verify/catalog.ts +346 -0
- package/src/tools/verify/index.ts +13 -3
- package/src/tools/verify/scripts.ts +135 -37
- package/src/tools/verify/surface.ts +9 -5
- package/src/tools/worker-evidence.ts +54 -12
- package/src/worker/spec-contract.ts +43 -3
- package/dist/chunk-J7CWMCQD.js +0 -255
- package/dist/chunk-T6YILFSB.js +0 -80
- package/dist/chunk-VAKQQHWR.js +0 -434
- package/dist/chunk-VPAYEGVX.js +0 -184
- package/dist/chunk-XBXAASKX.js +0 -18
- package/dist/memory-WFZMGYHX.js +0 -236
- package/src/domains/eval/metrics/chaos-stream.ts +0 -93
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { SAFE_EXEC_DEFAULT_TIMEOUT_MS } from "../core/safe-exec.js";
|
|
2
|
+
import {
|
|
3
|
+
createVerifierDraft,
|
|
4
|
+
discoverVerifierAuthoring,
|
|
5
|
+
previewVerifierDraft,
|
|
6
|
+
runVerifierAuthoringWorkflow,
|
|
7
|
+
type VerifierRevision,
|
|
8
|
+
} from "../tools/verify/authoring.js";
|
|
9
|
+
import { loadProjectVerifierCatalog, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH } from "../tools/verify/catalog.js";
|
|
10
|
+
import { verifyTool } from "../tools/verify/index.js";
|
|
11
|
+
import { printError, printOk } from "./argv.js";
|
|
12
|
+
|
|
13
|
+
const HELP = `Project verifier authoring
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
clio-coder verifiers discover
|
|
17
|
+
clio-coder verifiers author [--exclude <id>] [--rename <old>=<new>] [--dry-run <id>] [--yes]
|
|
18
|
+
clio-coder verifiers validate
|
|
19
|
+
clio-coder verifiers dry-run <id>
|
|
20
|
+
clio-coder verifiers add --id <id> --description <text> --command <json-argv> [fields] [--yes]
|
|
21
|
+
clio-coder verifiers edit <id> [--description <text>] [--command <json-argv>] [fields] [--yes]
|
|
22
|
+
clio-coder verifiers rename <old> <new> [--yes]
|
|
23
|
+
clio-coder verifiers remove <id> [--yes]
|
|
24
|
+
|
|
25
|
+
Fields:
|
|
26
|
+
--cwd <path> repository-relative working directory (default .)
|
|
27
|
+
--timeout-ms <number> bounded timeout in milliseconds (default 120000)
|
|
28
|
+
--tags <a,b> comma-separated catalog tags
|
|
29
|
+
|
|
30
|
+
Discovery and every preview are read-only. Mutating commands write only with
|
|
31
|
+
--yes after printing the exact argv, cwd, timeout, tags, source provenance, and
|
|
32
|
+
effective execution authority. dry-run invokes the production verify path.
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const VALUE_OPTIONS = new Set([
|
|
36
|
+
"--id",
|
|
37
|
+
"--description",
|
|
38
|
+
"--command",
|
|
39
|
+
"--cwd",
|
|
40
|
+
"--timeout-ms",
|
|
41
|
+
"--tags",
|
|
42
|
+
"--exclude",
|
|
43
|
+
"--rename",
|
|
44
|
+
"--dry-run",
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
interface ParsedAuthoringArgs {
|
|
48
|
+
yes: boolean;
|
|
49
|
+
help: boolean;
|
|
50
|
+
positional: string[];
|
|
51
|
+
values: Map<string, string[]>;
|
|
52
|
+
error?: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function parseAuthoringArgs(argv: ReadonlyArray<string>): ParsedAuthoringArgs {
|
|
56
|
+
const positional: string[] = [];
|
|
57
|
+
const values = new Map<string, string[]>();
|
|
58
|
+
let yes = false;
|
|
59
|
+
let help = false;
|
|
60
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
61
|
+
const arg = argv[index];
|
|
62
|
+
if (arg === "--yes") {
|
|
63
|
+
yes = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (arg === "--help" || arg === "-h") {
|
|
67
|
+
help = true;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (arg?.startsWith("--") === true) {
|
|
71
|
+
if (!VALUE_OPTIONS.has(arg)) return { yes, help, positional, values, error: `unknown option: ${arg}` };
|
|
72
|
+
const value = argv[index + 1];
|
|
73
|
+
if (value === undefined || value.startsWith("--")) {
|
|
74
|
+
return { yes, help, positional, values, error: `${arg} requires a value` };
|
|
75
|
+
}
|
|
76
|
+
const prior = values.get(arg) ?? [];
|
|
77
|
+
prior.push(value);
|
|
78
|
+
values.set(arg, prior);
|
|
79
|
+
index += 1;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (arg !== undefined) positional.push(arg);
|
|
83
|
+
}
|
|
84
|
+
return { yes, help, positional, values };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function oneValue(parsed: ParsedAuthoringArgs, option: string): string | undefined {
|
|
88
|
+
return parsed.values.get(option)?.at(-1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function parseCommand(value: string | undefined): string[] | Error {
|
|
92
|
+
if (value === undefined) return new Error("--command is required and must be a JSON argv array");
|
|
93
|
+
let parsed: unknown;
|
|
94
|
+
try {
|
|
95
|
+
parsed = JSON.parse(value) as unknown;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
return new Error(`--command must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
98
|
+
}
|
|
99
|
+
if (!Array.isArray(parsed) || parsed.length === 0 || parsed.some((entry) => typeof entry !== "string")) {
|
|
100
|
+
return new Error("--command must be a non-empty JSON string array");
|
|
101
|
+
}
|
|
102
|
+
return parsed as string[];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function parseTimeout(value: string | undefined): number | Error {
|
|
106
|
+
if (value === undefined) return SAFE_EXEC_DEFAULT_TIMEOUT_MS;
|
|
107
|
+
const parsed = Number(value);
|
|
108
|
+
if (!Number.isInteger(parsed) || parsed <= 0) return new Error("--timeout-ms must be a positive integer");
|
|
109
|
+
return parsed;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function tags(value: string | undefined): string[] {
|
|
113
|
+
return value === undefined
|
|
114
|
+
? []
|
|
115
|
+
: value
|
|
116
|
+
.split(",")
|
|
117
|
+
.map((tag) => tag.trim())
|
|
118
|
+
.filter((tag) => tag.length > 0);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function requiredValue(parsed: ParsedAuthoringArgs, option: string): string | Error {
|
|
122
|
+
const value = oneValue(parsed, option);
|
|
123
|
+
return value === undefined || value.length === 0 ? new Error(`${option} is required`) : value;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function authorRevisions(parsed: ParsedAuthoringArgs): VerifierRevision[] | Error {
|
|
127
|
+
const revisions: VerifierRevision[] = [];
|
|
128
|
+
for (const id of parsed.values.get("--exclude") ?? []) revisions.push({ kind: "remove", id });
|
|
129
|
+
for (const rename of parsed.values.get("--rename") ?? []) {
|
|
130
|
+
const separator = rename.indexOf("=");
|
|
131
|
+
if (separator <= 0 || separator === rename.length - 1) {
|
|
132
|
+
return new Error("--rename must use <old>=<new>");
|
|
133
|
+
}
|
|
134
|
+
revisions.push({ kind: "rename", id: rename.slice(0, separator), newId: rename.slice(separator + 1) });
|
|
135
|
+
}
|
|
136
|
+
return revisions;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function addRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
|
|
140
|
+
const id = requiredValue(parsed, "--id");
|
|
141
|
+
if (id instanceof Error) return id;
|
|
142
|
+
const description = requiredValue(parsed, "--description");
|
|
143
|
+
if (description instanceof Error) return description;
|
|
144
|
+
const command = parseCommand(oneValue(parsed, "--command"));
|
|
145
|
+
if (command instanceof Error) return command;
|
|
146
|
+
const timeoutMs = parseTimeout(oneValue(parsed, "--timeout-ms"));
|
|
147
|
+
if (timeoutMs instanceof Error) return timeoutMs;
|
|
148
|
+
return {
|
|
149
|
+
kind: "add",
|
|
150
|
+
check: {
|
|
151
|
+
id,
|
|
152
|
+
description,
|
|
153
|
+
command,
|
|
154
|
+
cwd: oneValue(parsed, "--cwd") ?? ".",
|
|
155
|
+
timeoutMs,
|
|
156
|
+
tags: tags(oneValue(parsed, "--tags")),
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function editRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
|
|
162
|
+
const id = parsed.positional[1];
|
|
163
|
+
if (id === undefined) return new Error("edit requires a check ID");
|
|
164
|
+
const changes: Extract<VerifierRevision, { kind: "edit" }>["changes"] = {};
|
|
165
|
+
const description = oneValue(parsed, "--description");
|
|
166
|
+
if (description !== undefined) changes.description = description;
|
|
167
|
+
const commandValue = oneValue(parsed, "--command");
|
|
168
|
+
if (commandValue !== undefined) {
|
|
169
|
+
const command = parseCommand(commandValue);
|
|
170
|
+
if (command instanceof Error) return command;
|
|
171
|
+
changes.command = command;
|
|
172
|
+
}
|
|
173
|
+
const cwd = oneValue(parsed, "--cwd");
|
|
174
|
+
if (cwd !== undefined) changes.cwd = cwd;
|
|
175
|
+
const timeoutValue = oneValue(parsed, "--timeout-ms");
|
|
176
|
+
if (timeoutValue !== undefined) {
|
|
177
|
+
const timeoutMs = parseTimeout(timeoutValue);
|
|
178
|
+
if (timeoutMs instanceof Error) return timeoutMs;
|
|
179
|
+
changes.timeoutMs = timeoutMs;
|
|
180
|
+
}
|
|
181
|
+
const tagValue = oneValue(parsed, "--tags");
|
|
182
|
+
if (tagValue !== undefined) changes.tags = tags(tagValue);
|
|
183
|
+
if (Object.keys(changes).length === 0) return new Error("edit requires at least one changed field");
|
|
184
|
+
return { kind: "edit", id, changes };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function mutationRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
|
|
188
|
+
const command = parsed.positional[0];
|
|
189
|
+
if (command === "add") return addRevision(parsed);
|
|
190
|
+
if (command === "edit") return editRevision(parsed);
|
|
191
|
+
if (command === "rename") {
|
|
192
|
+
const id = parsed.positional[1];
|
|
193
|
+
const newId = parsed.positional[2];
|
|
194
|
+
if (id === undefined || newId === undefined) return new Error("rename requires <old> and <new> IDs");
|
|
195
|
+
return { kind: "rename", id, newId };
|
|
196
|
+
}
|
|
197
|
+
if (command === "remove") {
|
|
198
|
+
const id = parsed.positional[1];
|
|
199
|
+
if (id === undefined) return new Error("remove requires a check ID");
|
|
200
|
+
return { kind: "remove", id };
|
|
201
|
+
}
|
|
202
|
+
return new Error(`unknown verifiers command: ${command ?? "(none)"}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function printDryRun(id: string, result: Awaited<ReturnType<typeof verifyTool.run>>): number {
|
|
206
|
+
if (result.kind === "error") {
|
|
207
|
+
printError(`dry-run '${id}' failed: ${result.message}`);
|
|
208
|
+
return 1;
|
|
209
|
+
}
|
|
210
|
+
process.stdout.write(`Dry run '${id}':\n${result.output}${result.output.endsWith("\n") ? "" : "\n"}`);
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function executeWorkflow(
|
|
215
|
+
parsed: ParsedAuthoringArgs,
|
|
216
|
+
options: { includeProposals: boolean; revisions: VerifierRevision[] },
|
|
217
|
+
): Promise<number> {
|
|
218
|
+
let printedPreview = false;
|
|
219
|
+
const dryRunCheckIds = parsed.values.get("--dry-run") ?? [];
|
|
220
|
+
const result = await runVerifierAuthoringWorkflow({
|
|
221
|
+
includeProposals: options.includeProposals,
|
|
222
|
+
initialRevisions: options.revisions,
|
|
223
|
+
confirmed: parsed.yes,
|
|
224
|
+
decide(context) {
|
|
225
|
+
process.stdout.write(`${context.preview}\n`);
|
|
226
|
+
printedPreview = true;
|
|
227
|
+
if (!parsed.yes || (context.draft.checks.length === 0 && options.revisions.length === 0)) {
|
|
228
|
+
return { kind: "reject" };
|
|
229
|
+
}
|
|
230
|
+
return { kind: "confirm", dryRunCheckIds };
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
if (result.status === "invalid") {
|
|
234
|
+
if (!printedPreview && result.preview !== undefined) process.stdout.write(`${result.preview}\n`);
|
|
235
|
+
printError(result.reason);
|
|
236
|
+
if (result.wrote && result.path !== undefined) {
|
|
237
|
+
process.stderr.write(` ${result.path} was written; repair or remove it before running a check.\n`);
|
|
238
|
+
}
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
if (result.status === "rejected") {
|
|
242
|
+
if (!parsed.yes) {
|
|
243
|
+
process.stdout.write("Review complete. Nothing changed; rerun the same command with --yes to write this preview.\n");
|
|
244
|
+
} else {
|
|
245
|
+
process.stdout.write(
|
|
246
|
+
"Nothing changed because the preview contains no catalog checks. Package checks remain active; unsupported commands can be added with `clio-coder verifiers add`.\n",
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
printOk(`wrote ${result.path}; production parser accepted the catalog`);
|
|
252
|
+
let code = 0;
|
|
253
|
+
for (const dryRun of result.dryRuns) code = Math.max(code, printDryRun(dryRun.id, dryRun.result));
|
|
254
|
+
return code;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async function discoverCommand(): Promise<number> {
|
|
258
|
+
const discovery = discoverVerifierAuthoring();
|
|
259
|
+
if (!discovery.ok) {
|
|
260
|
+
printError(discovery.reason);
|
|
261
|
+
process.stderr.write(`${discovery.manualEntry}\n`);
|
|
262
|
+
return 1;
|
|
263
|
+
}
|
|
264
|
+
process.stdout.write(`${previewVerifierDraft(createVerifierDraft(discovery))}\n`);
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function validateCommand(): number {
|
|
269
|
+
const loaded = loadProjectVerifierCatalog(process.cwd());
|
|
270
|
+
if (!loaded.ok) {
|
|
271
|
+
printError(`production catalog parser rejected ${loaded.reason}`);
|
|
272
|
+
return 1;
|
|
273
|
+
}
|
|
274
|
+
if (loaded.source === null) {
|
|
275
|
+
process.stdout.write(`No ${PROJECT_VERIFIER_CATALOG_RELATIVE_PATH} exists. Run \`clio-coder verifiers author\`.\n`);
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
printOk(
|
|
279
|
+
`production catalog parser accepted ${PROJECT_VERIFIER_CATALOG_RELATIVE_PATH} (${loaded.source.checks.length} check${loaded.source.checks.length === 1 ? "" : "s"})`,
|
|
280
|
+
);
|
|
281
|
+
return 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export async function runVerifiersCommand(argv: string[]): Promise<number> {
|
|
285
|
+
const parsed = parseAuthoringArgs(argv);
|
|
286
|
+
if (parsed.error !== undefined) {
|
|
287
|
+
printError(parsed.error);
|
|
288
|
+
process.stderr.write(HELP);
|
|
289
|
+
return 2;
|
|
290
|
+
}
|
|
291
|
+
if (parsed.help || parsed.positional.length === 0) {
|
|
292
|
+
process.stdout.write(HELP);
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
const command = parsed.positional[0];
|
|
296
|
+
if (command === "discover") return discoverCommand();
|
|
297
|
+
if (command === "validate") return validateCommand();
|
|
298
|
+
if (command === "dry-run") {
|
|
299
|
+
const id = parsed.positional[1];
|
|
300
|
+
if (id === undefined) {
|
|
301
|
+
printError("dry-run requires a check ID");
|
|
302
|
+
return 2;
|
|
303
|
+
}
|
|
304
|
+
return printDryRun(id, await verifyTool.run({ check: id }));
|
|
305
|
+
}
|
|
306
|
+
if (command === "author") {
|
|
307
|
+
const revisions = authorRevisions(parsed);
|
|
308
|
+
if (revisions instanceof Error) {
|
|
309
|
+
printError(revisions.message);
|
|
310
|
+
return 2;
|
|
311
|
+
}
|
|
312
|
+
return executeWorkflow(parsed, { includeProposals: true, revisions });
|
|
313
|
+
}
|
|
314
|
+
if (["add", "edit", "rename", "remove"].includes(command ?? "")) {
|
|
315
|
+
const revision = mutationRevision(parsed);
|
|
316
|
+
if (revision instanceof Error) {
|
|
317
|
+
printError(revision.message);
|
|
318
|
+
return 2;
|
|
319
|
+
}
|
|
320
|
+
return executeWorkflow(parsed, { includeProposals: false, revisions: [revision] });
|
|
321
|
+
}
|
|
322
|
+
printError(`unknown verifiers command: ${command}`);
|
|
323
|
+
process.stderr.write(HELP);
|
|
324
|
+
return 2;
|
|
325
|
+
}
|
package/src/core/bash-exec.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { StringDecoder } from "node:string_decoder";
|
|
2
3
|
import { AI_AGENT_NAME } from "./agent-environment.js";
|
|
3
4
|
import {
|
|
4
5
|
gitCommitAttributionEnabled,
|
|
@@ -28,6 +29,8 @@ export interface BashCommandResult {
|
|
|
28
29
|
aborted: boolean;
|
|
29
30
|
timedOut: boolean;
|
|
30
31
|
outputCapped: boolean;
|
|
32
|
+
/** Exact bytes retained from stdout and stderr, never above the hard cap. */
|
|
33
|
+
outputBytes: number;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
export interface BashCommandProgress {
|
|
@@ -151,6 +154,9 @@ export async function runBashCommand(command: string, options: RunBashCommandOpt
|
|
|
151
154
|
let killSent = false;
|
|
152
155
|
let stdout = "";
|
|
153
156
|
let stderr = "";
|
|
157
|
+
const stdoutDecoder = new StringDecoder("utf8");
|
|
158
|
+
const stderrDecoder = new StringDecoder("utf8");
|
|
159
|
+
let decodersFinished = false;
|
|
154
160
|
let outputBytes = 0;
|
|
155
161
|
let outputCapped = false;
|
|
156
162
|
let updateTimer: ReturnType<typeof setTimeout> | null = null;
|
|
@@ -164,6 +170,16 @@ export async function runBashCommand(command: string, options: RunBashCommandOpt
|
|
|
164
170
|
stdio: ["ignore", "pipe", "pipe"],
|
|
165
171
|
});
|
|
166
172
|
|
|
173
|
+
const finishDecoders = (): void => {
|
|
174
|
+
if (decodersFinished) return;
|
|
175
|
+
decodersFinished = true;
|
|
176
|
+
// A hard byte cap may bisect a multibyte code point. Discard the
|
|
177
|
+
// decoder's incomplete suffix instead of manufacturing U+FFFD.
|
|
178
|
+
if (outputCapped) return;
|
|
179
|
+
stdout += stdoutDecoder.end();
|
|
180
|
+
stderr += stderrDecoder.end();
|
|
181
|
+
};
|
|
182
|
+
|
|
167
183
|
const emitUpdate = (): void => {
|
|
168
184
|
if (options.onUpdate === undefined || !updateDirty) return;
|
|
169
185
|
updateDirty = false;
|
|
@@ -250,24 +266,20 @@ export async function runBashCommand(command: string, options: RunBashCommandOpt
|
|
|
250
266
|
|
|
251
267
|
const appendChunk = (target: "stdout" | "stderr", chunk: Buffer): void => {
|
|
252
268
|
if (outputCapped) return;
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
else stderr += slice;
|
|
263
|
-
}
|
|
269
|
+
const remaining = BASH_HARD_CAP_BYTES - outputBytes;
|
|
270
|
+
const accepted = chunk.byteLength <= remaining ? chunk : chunk.subarray(0, Math.max(0, remaining));
|
|
271
|
+
outputBytes += accepted.byteLength;
|
|
272
|
+
if (accepted.byteLength > 0) {
|
|
273
|
+
const decoded = target === "stdout" ? stdoutDecoder.write(accepted) : stderrDecoder.write(accepted);
|
|
274
|
+
if (target === "stdout") stdout += decoded;
|
|
275
|
+
else stderr += decoded;
|
|
276
|
+
}
|
|
277
|
+
if (accepted.byteLength < chunk.byteLength) {
|
|
264
278
|
outputCapped = true;
|
|
265
279
|
scheduleUpdate();
|
|
266
280
|
killChild();
|
|
267
281
|
return;
|
|
268
282
|
}
|
|
269
|
-
if (target === "stdout") stdout += chunk.toString("utf8");
|
|
270
|
-
else stderr += chunk.toString("utf8");
|
|
271
283
|
scheduleUpdate();
|
|
272
284
|
};
|
|
273
285
|
|
|
@@ -278,6 +290,7 @@ export async function runBashCommand(command: string, options: RunBashCommandOpt
|
|
|
278
290
|
settled = true;
|
|
279
291
|
if (timeoutId) clearTimeout(timeoutId);
|
|
280
292
|
clearKillGraceTimer();
|
|
293
|
+
finishDecoders();
|
|
281
294
|
finishUpdates();
|
|
282
295
|
options.signal?.removeEventListener("abort", onAbort);
|
|
283
296
|
resolve({
|
|
@@ -289,6 +302,7 @@ export async function runBashCommand(command: string, options: RunBashCommandOpt
|
|
|
289
302
|
aborted,
|
|
290
303
|
timedOut,
|
|
291
304
|
outputCapped,
|
|
305
|
+
outputBytes,
|
|
292
306
|
});
|
|
293
307
|
});
|
|
294
308
|
child.on("close", (code, signalName) => {
|
|
@@ -296,6 +310,7 @@ export async function runBashCommand(command: string, options: RunBashCommandOpt
|
|
|
296
310
|
settled = true;
|
|
297
311
|
if (timeoutId) clearTimeout(timeoutId);
|
|
298
312
|
clearKillGraceTimer();
|
|
313
|
+
finishDecoders();
|
|
299
314
|
finishUpdates();
|
|
300
315
|
options.signal?.removeEventListener("abort", onAbort);
|
|
301
316
|
const error =
|
|
@@ -307,7 +322,17 @@ export async function runBashCommand(command: string, options: RunBashCommandOpt
|
|
|
307
322
|
code: code ?? undefined,
|
|
308
323
|
signal: signalName ?? undefined,
|
|
309
324
|
} as NodeJS.ErrnoException);
|
|
310
|
-
resolve({
|
|
325
|
+
resolve({
|
|
326
|
+
error,
|
|
327
|
+
stdout,
|
|
328
|
+
stderr,
|
|
329
|
+
exitCode: code,
|
|
330
|
+
signal: signalName,
|
|
331
|
+
aborted,
|
|
332
|
+
timedOut,
|
|
333
|
+
outputCapped,
|
|
334
|
+
outputBytes,
|
|
335
|
+
});
|
|
311
336
|
});
|
|
312
337
|
});
|
|
313
338
|
}
|
package/src/core/bus-events.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import type { AgentAudience } from "../domains/agents/spec.js";
|
|
16
16
|
import type { ConfigDiff } from "../domains/config/classify.js";
|
|
17
|
+
import type { RunToolBudgetEnvelope } from "../domains/dispatch/budget-envelope.js";
|
|
17
18
|
import type {
|
|
18
19
|
DispatchRequestOrigin,
|
|
19
20
|
RunKind,
|
|
@@ -61,6 +62,7 @@ export const BusChannels = {
|
|
|
61
62
|
ContextActivity: "context.activity",
|
|
62
63
|
ContextWarning: "context.warning",
|
|
63
64
|
ContextPruned: "context.pruned",
|
|
65
|
+
ContextRecalled: "context.recalled",
|
|
64
66
|
AgentStatusChanged: "agent.status.changed",
|
|
65
67
|
RunAborted: "run.aborted",
|
|
66
68
|
BudgetAlert: "budget.alert",
|
|
@@ -253,21 +255,34 @@ export function isRunAbortedPayload(value: unknown): value is RunAbortedPayload
|
|
|
253
255
|
return true;
|
|
254
256
|
}
|
|
255
257
|
|
|
256
|
-
/** Payload published on {@link BusChannels.ContextPruned} after
|
|
258
|
+
/** Payload published on {@link BusChannels.ContextPruned} after projected or summarized context shrinks. */
|
|
257
259
|
export interface ContextPrunedPayload {
|
|
258
|
-
stage: "mask_observations" | "llm_summary";
|
|
260
|
+
stage: "mask_observations" | "working_set" | "llm_summary";
|
|
259
261
|
tokensBefore: number;
|
|
260
262
|
tokensAfter: number;
|
|
261
263
|
trigger: string;
|
|
262
264
|
snapshotIdBefore: string | null;
|
|
263
265
|
snapshotIdAfter: string;
|
|
264
266
|
at: number;
|
|
265
|
-
/** Used/window ratio at trigger time; mask
|
|
267
|
+
/** Used/window ratio at trigger time; working-set and legacy-mask stages only. */
|
|
266
268
|
pressure?: number | null;
|
|
269
|
+
/** Legacy destructive-mask count. */
|
|
267
270
|
maskedObservations?: number;
|
|
268
|
-
/** Thinking blocks stripped from stale assistant messages; mask
|
|
271
|
+
/** Thinking blocks stripped from stale assistant messages; legacy mask only. */
|
|
269
272
|
maskedThinkingBlocks?: number;
|
|
270
273
|
maskedThinkingChars?: number;
|
|
274
|
+
/** Working-set policy that selected an applied eviction event. */
|
|
275
|
+
policyId?: string;
|
|
276
|
+
/** Number of working-set units evicted by the event. */
|
|
277
|
+
evictedItems?: number;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Payload published on {@link BusChannels.ContextRecalled} after an exact working-set recall. */
|
|
281
|
+
export interface ContextRecalledPayload {
|
|
282
|
+
ref: string;
|
|
283
|
+
trigger: "tool" | "operator";
|
|
284
|
+
tokensReadmitted: number;
|
|
285
|
+
at: number;
|
|
271
286
|
}
|
|
272
287
|
|
|
273
288
|
// ---------------------------------------------------------------------------
|
|
@@ -466,6 +481,8 @@ export interface DispatchRunIdentity {
|
|
|
466
481
|
wireModelId: string;
|
|
467
482
|
runtimeId: string;
|
|
468
483
|
runtimeKind: RunKind;
|
|
484
|
+
/** Admitted invocation budget provenance for native workers. */
|
|
485
|
+
budget?: RunToolBudgetEnvelope | undefined;
|
|
469
486
|
/** Fleet node id the run was placed on; absent renders as the local node. */
|
|
470
487
|
node?: string | undefined;
|
|
471
488
|
/** Review/compete gate role and cycle, for fleet board badges. */
|
|
@@ -727,6 +744,7 @@ export type BusPayloadMap = {
|
|
|
727
744
|
[BusChannels.ContextActivity]: ContextActivityPayload;
|
|
728
745
|
[BusChannels.ContextWarning]: ContextWarningPayload;
|
|
729
746
|
[BusChannels.ContextPruned]: ContextPrunedPayload;
|
|
747
|
+
[BusChannels.ContextRecalled]: ContextRecalledPayload;
|
|
730
748
|
[BusChannels.AgentStatusChanged]: AgentStatusChangedPayload;
|
|
731
749
|
[BusChannels.RunAborted]: RunAbortedPayload;
|
|
732
750
|
[BusChannels.BudgetAlert]: BudgetAlertPayload;
|
package/src/core/config.ts
CHANGED
|
@@ -968,6 +968,7 @@ const TOP_LEVEL_KEYS = [
|
|
|
968
968
|
"delegation",
|
|
969
969
|
"keybindings",
|
|
970
970
|
"compaction",
|
|
971
|
+
"context",
|
|
971
972
|
"retry",
|
|
972
973
|
"guardrails",
|
|
973
974
|
] as const;
|
|
@@ -1405,6 +1406,59 @@ export function validateSettings(raw: unknown): SettingsValidationResult {
|
|
|
1405
1406
|
}
|
|
1406
1407
|
}
|
|
1407
1408
|
|
|
1409
|
+
if ("context" in raw) {
|
|
1410
|
+
if (!isPlainObject(raw.context)) {
|
|
1411
|
+
issues.add("context", `expected a map, got ${describe(raw.context)}`);
|
|
1412
|
+
} else {
|
|
1413
|
+
issues.unknownKeys("context", raw.context, ["workingSet"]);
|
|
1414
|
+
if ("workingSet" in raw.context) {
|
|
1415
|
+
if (!isPlainObject(raw.context.workingSet)) {
|
|
1416
|
+
issues.add("context.workingSet", `expected a map, got ${describe(raw.context.workingSet)}`);
|
|
1417
|
+
} else {
|
|
1418
|
+
const workingSet = raw.context.workingSet;
|
|
1419
|
+
issues.unknownKeys("context.workingSet", workingSet, [
|
|
1420
|
+
"enabled",
|
|
1421
|
+
"policy",
|
|
1422
|
+
"target",
|
|
1423
|
+
"protectLastTurns",
|
|
1424
|
+
"minEvictableTokens",
|
|
1425
|
+
]);
|
|
1426
|
+
if ("enabled" in workingSet) {
|
|
1427
|
+
const v = expectBoolean(issues, "context.workingSet.enabled", workingSet.enabled);
|
|
1428
|
+
if (v !== undefined) settings.context.workingSet.enabled = v;
|
|
1429
|
+
}
|
|
1430
|
+
if ("policy" in workingSet) {
|
|
1431
|
+
const v = expectEnum(issues, "context.workingSet.policy", workingSet.policy, [
|
|
1432
|
+
"age-horizon",
|
|
1433
|
+
"structural-v1",
|
|
1434
|
+
] as const);
|
|
1435
|
+
if (v !== undefined) settings.context.workingSet.policy = v;
|
|
1436
|
+
}
|
|
1437
|
+
if ("target" in workingSet) {
|
|
1438
|
+
const v = expectNumber(issues, "context.workingSet.target", workingSet.target);
|
|
1439
|
+
if (v !== undefined && (v <= 0 || v >= 1)) {
|
|
1440
|
+
issues.add("context.workingSet.target", `expected a number > 0 and < 1, got ${v}`);
|
|
1441
|
+
} else if (v !== undefined) {
|
|
1442
|
+
settings.context.workingSet.target = v;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
if ("protectLastTurns" in workingSet) {
|
|
1446
|
+
const v = expectInteger(issues, "context.workingSet.protectLastTurns", workingSet.protectLastTurns, {
|
|
1447
|
+
min: 1,
|
|
1448
|
+
});
|
|
1449
|
+
if (v !== undefined) settings.context.workingSet.protectLastTurns = v;
|
|
1450
|
+
}
|
|
1451
|
+
if ("minEvictableTokens" in workingSet) {
|
|
1452
|
+
const v = expectInteger(issues, "context.workingSet.minEvictableTokens", workingSet.minEvictableTokens, {
|
|
1453
|
+
min: 0,
|
|
1454
|
+
});
|
|
1455
|
+
if (v !== undefined) settings.context.workingSet.minEvictableTokens = v;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1408
1462
|
if ("retry" in raw) {
|
|
1409
1463
|
if (!isPlainObject(raw.retry)) {
|
|
1410
1464
|
issues.add("retry", `expected a map, got ${describe(raw.retry)}`);
|
package/src/core/defaults.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* exist. Users edit the file directly or through TUI overlays.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { DEFAULT_WORKING_SET_SETTINGS } from "../domains/context/working-set/defaults.js";
|
|
7
8
|
import type { TargetDescriptor } from "../domains/providers/types/target-descriptor.js";
|
|
8
9
|
import type { AutonomyLevel } from "../domains/safety/autonomy.js";
|
|
9
10
|
import { GUARDRAIL_DEFAULTS, type GuardrailValues } from "./guardrails.js";
|
|
@@ -98,6 +99,32 @@ export interface CompactionSettings {
|
|
|
98
99
|
systemPrompt?: string;
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Working-set layer settings (`context.workingSet`). The layer decides which
|
|
104
|
+
* tool-result bodies and thinking blocks leave the model's working set when
|
|
105
|
+
* pressure crosses `compaction.threshold`; it records evictions as ledger
|
|
106
|
+
* entries and never rewrites history. Defaults and prose live in
|
|
107
|
+
* src/domains/context/working-set/defaults.ts.
|
|
108
|
+
*
|
|
109
|
+
* - enabled: master switch. Off skips eviction and goes straight to summary
|
|
110
|
+
* compaction (the legacy destructive mask is only reachable through
|
|
111
|
+
* CLIO_CODER_LEGACY_MASK=1).
|
|
112
|
+
* - policy: candidate selection rule set.
|
|
113
|
+
* - target: used/window ratio an applied event batches down to.
|
|
114
|
+
* - protectLastTurns: recent user turns whose observations are never evicted.
|
|
115
|
+
* - minEvictableTokens: results below this estimate are never evicted; the
|
|
116
|
+
* marker would cost more than it saves.
|
|
117
|
+
*/
|
|
118
|
+
export type WorkingSetPolicyId = "age-horizon" | "structural-v1";
|
|
119
|
+
|
|
120
|
+
export interface WorkingSetSettings {
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
policy: WorkingSetPolicyId;
|
|
123
|
+
target: number;
|
|
124
|
+
protectLastTurns: number;
|
|
125
|
+
minEvictableTokens: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
101
128
|
/**
|
|
102
129
|
* Transient provider retry controls for the interactive chat loop. These are
|
|
103
130
|
* intentionally small and mirror the session retry helper defaults. Dispatched
|
|
@@ -357,6 +384,9 @@ export const DEFAULT_SETTINGS = {
|
|
|
357
384
|
threshold: 0.8,
|
|
358
385
|
excludeLastTurns: 6,
|
|
359
386
|
} as CompactionSettings,
|
|
387
|
+
context: {
|
|
388
|
+
workingSet: DEFAULT_WORKING_SET_SETTINGS,
|
|
389
|
+
},
|
|
360
390
|
retry: {
|
|
361
391
|
enabled: true,
|
|
362
392
|
maxRetries: 3,
|
|
@@ -610,9 +640,9 @@ keybindings: {}
|
|
|
610
640
|
# auto master switch for the pre-request compaction trigger.
|
|
611
641
|
# Manual /context compact always runs the LLM summary.
|
|
612
642
|
# threshold pressure = estimated_tokens / context_window. Crossing
|
|
613
|
-
# it
|
|
614
|
-
#
|
|
615
|
-
# excludeLastTurns recent
|
|
643
|
+
# it evicts from the working set first, then runs a full
|
|
644
|
+
# LLM summary if pressure stays above the threshold.
|
|
645
|
+
# excludeLastTurns recent turns protected only by the temporary legacy mask.
|
|
616
646
|
# model optional pattern (e.g. provider/summary-model-id) for a
|
|
617
647
|
# dedicated summarization model. Absent ⇒ orchestrator target.
|
|
618
648
|
# systemPrompt optional path to a prompt-override file.
|
|
@@ -623,6 +653,23 @@ compaction:
|
|
|
623
653
|
# model: provider/summary-model-id
|
|
624
654
|
# systemPrompt: ~/.config/clio-coder/prompts/compaction.md
|
|
625
655
|
|
|
656
|
+
# Non-destructive working-set eviction before summary compaction.
|
|
657
|
+
# enabled false skips eviction and goes directly to the summary stage.
|
|
658
|
+
# policy structural-v1 evicts by what the session did since
|
|
659
|
+
# (re-reads, edits, resolved failures, consumed listings)
|
|
660
|
+
# and falls back to age only under pressure;
|
|
661
|
+
# age-horizon is the previous age-based selection.
|
|
662
|
+
# target pressure ratio an applied eviction batches down to.
|
|
663
|
+
# protectLastTurns recent user turns whose observations remain in the working set.
|
|
664
|
+
# minEvictableTokens entries below this estimate remain in the working set.
|
|
665
|
+
context:
|
|
666
|
+
workingSet:
|
|
667
|
+
enabled: true
|
|
668
|
+
policy: structural-v1
|
|
669
|
+
target: 0.6
|
|
670
|
+
protectLastTurns: 6
|
|
671
|
+
minEvictableTokens: 200
|
|
672
|
+
|
|
626
673
|
# Transient provider/stream retry controls for interactive chat.
|
|
627
674
|
# Retryable errors include overloads, rate limits, 5xx responses, network
|
|
628
675
|
# resets, and timeouts. Context overflow uses compaction recovery instead.
|