@iowarp/clio-coder 0.3.4 → 0.3.7
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 +65 -2
- package/CONTRIBUTING.md +6 -6
- package/README.md +16 -5
- package/dist/{acp-S5R4RR5B.js → acp-SK4MD6MM.js} +11 -11
- package/dist/{agents-P6DMMVZY.js → agents-2FN2K6ME.js} +33 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-2XCZLPKS.js → auth-QIYZWM5I.js} +15 -15
- package/dist/{chunk-EKMEHE4H.js → chunk-33YXPOE3.js} +2 -3
- package/dist/{chunk-VAWWTKDP.js → chunk-3HAPLH5M.js} +11 -11
- package/dist/{chunk-YCWGATWI.js → chunk-465YSENW.js} +3 -3
- package/dist/{chunk-4OC57DA6.js → chunk-4DGYLA73.js} +53 -2
- package/dist/{chunk-UZHIZC5S.js → chunk-4DWFMQDR.js} +61 -76
- package/dist/{chunk-ZWMF7253.js → chunk-5C3AQNDW.js} +328 -9
- package/dist/{chunk-22NAGB7X.js → chunk-5C77SEEY.js} +5 -94
- package/dist/{chunk-WPQLXFOZ.js → chunk-5FR74PWO.js} +3 -2
- package/dist/{chunk-35MKKU5R.js → chunk-5UJ6ECTS.js} +18 -10
- package/dist/{chunk-BRXQQJFP.js → chunk-6M7VS3J3.js} +571 -50
- package/dist/{chunk-QQK64KLB.js → chunk-6TUKSZVF.js} +141 -23
- package/dist/{chunk-N4CZJQRK.js → chunk-AB4XIIVB.js} +8 -6
- package/dist/{chunk-KRPY7NTG.js → chunk-BMWK7ZIZ.js} +14 -20
- package/dist/{chunk-4BPJXDWC.js → chunk-C4JBQ5SR.js} +30 -14
- package/dist/{chunk-ZYKPLLNQ.js → chunk-CEYBNUGC.js} +821 -83
- package/dist/{chunk-VEZEGCGW.js → chunk-D4MDIG46.js} +20 -18
- package/dist/chunk-DJNLUABN.js +843 -0
- package/dist/{chunk-BP4OYD6A.js → chunk-DMD2AGVS.js} +21 -2
- package/dist/{chunk-KOHPCX4K.js → chunk-DOOEX22V.js} +2 -2
- package/dist/chunk-DQA7QLMD.js +123 -0
- package/dist/chunk-DR52UMZW.js +21 -0
- package/dist/{chunk-3HZ5RWN2.js → chunk-EBEFWSGL.js} +9 -7
- package/dist/{chunk-EDRHSCIE.js → chunk-EELBMBT6.js} +128 -13
- package/dist/{chunk-HV5X7OR2.js → chunk-EOOQZZDE.js} +16 -14
- package/dist/{chunk-WR67VIZY.js → chunk-FOT2FX5J.js} +63 -5
- package/dist/{chunk-BPGS2WCQ.js → chunk-GEYXPTRF.js} +2 -1
- package/dist/{chunk-FYYLNIL5.js → chunk-GH5622CP.js} +2 -2
- package/dist/{chunk-BEY543CS.js → chunk-GOXNB3AO.js} +5 -2
- package/dist/chunk-GWS3VEIW.js +195 -0
- package/dist/{chunk-G4BMMOKF.js → chunk-HVDIIIQW.js} +2 -2
- package/dist/chunk-HWUFFB6L.js +83 -0
- package/dist/{chunk-X6COSD2O.js → chunk-J7PIKKWC.js} +8 -436
- package/dist/{chunk-NILBFAPG.js → chunk-JNXPYBB4.js} +2 -2
- package/dist/{chunk-4VP4KH3K.js → chunk-JRIO5UD2.js} +4 -4
- package/dist/{chunk-K6WL7QZT.js → chunk-JTSEDYVQ.js} +7 -7
- package/dist/{chunk-QKMUKYO7.js → chunk-KCMKRQX4.js} +236 -84
- package/dist/chunk-KZ2H5X4G.js +1026 -0
- package/dist/{chunk-A2GZF7DC.js → chunk-LADCF22A.js} +13 -13
- package/dist/chunk-LCGCVYZ4.js +57 -0
- package/dist/chunk-M4AKACEO.js +382 -0
- package/dist/{chunk-POHLU5DW.js → chunk-M6L6IDJG.js} +3 -3
- package/dist/{chunk-4JUF2NNX.js → chunk-MXI6J5JF.js} +7 -7
- package/dist/{chunk-X4RCMKVQ.js → chunk-NDINPTJ4.js} +2 -2
- package/dist/{chunk-TTNYS3EA.js → chunk-OB5HIGJY.js} +1 -1
- package/dist/{chunk-7RXG6QRZ.js → chunk-OBMAI2DP.js} +61 -840
- package/dist/{chunk-5M54SPOL.js → chunk-ODFEOB4F.js} +161 -5
- package/dist/chunk-PD3MESLB.js +242 -0
- package/dist/{chunk-ED4KHGC3.js → chunk-PPAMZ32Z.js} +9 -2
- package/dist/{chunk-VMNQ6OZA.js → chunk-QCTRSGHQ.js} +963 -786
- package/dist/chunk-RVG5JXAL.js +41 -0
- package/dist/{chunk-RD5U66HV.js → chunk-SROCI7ZU.js} +7 -7
- package/dist/{chunk-MFFY33HR.js → chunk-THKY7CD7.js} +466 -205
- package/dist/{chunk-34475P3I.js → chunk-TSHXZTOQ.js} +5 -4
- package/dist/{chunk-PCZJO5TI.js → chunk-UFQ3F4FW.js} +13 -178
- package/dist/{chunk-AD2SYQYC.js → chunk-UHXRNZ2J.js} +121 -3
- package/dist/chunk-UND3GU2L.js +103 -0
- package/dist/{chunk-QQL5RT5M.js → chunk-UUANF5CR.js} +2323 -2114
- package/dist/{chunk-VJWL6YS5.js → chunk-UUVG37B4.js} +2 -2
- package/dist/chunk-UVDSQ6LW.js +472 -0
- package/dist/{chunk-QWU7ZBO7.js → chunk-VQNODYQ4.js} +215 -56
- package/dist/chunk-VREKEFLL.js +37 -0
- package/dist/{chunk-2TZWSW76.js → chunk-WHGPSPT5.js} +2 -2
- package/dist/{chunk-TW3WDMVS.js → chunk-WHJYKASB.js} +2 -2
- package/dist/{chunk-MEQ45TQ4.js → chunk-WJHBC77E.js} +21 -7
- package/dist/{chunk-HXG4IURW.js → chunk-X2KV5FXT.js} +2 -2
- package/dist/{chunk-YHZX5GEU.js → chunk-XAKHZX5N.js} +2 -2
- package/dist/{chunk-2LZI5CAG.js → chunk-XEGB6BCN.js} +228 -36
- package/dist/{chunk-E25LMLRW.js → chunk-YD734TPH.js} +2 -2
- package/dist/{verifiers-4UUM6TEE.js → chunk-YTYFXUI3.js} +121 -372
- package/dist/{chunk-3JLKSKD7.js → chunk-ZGH7FGS5.js} +17 -7
- package/dist/{chunk-VSNATDE6.js → chunk-ZZMN5OM4.js} +2 -2
- package/dist/cli/index.js +34 -32
- package/dist/{clio-J5JIOIDS.js → clio-WBVQEBKO.js} +7 -7
- package/dist/{code-nav-AXCXSBHX.js → code-nav-FGGFIE7L.js} +7 -7
- package/dist/codewiki/build-worker.js +4 -4
- package/dist/{components-KELWS457.js → components-F7OEATSO.js} +5 -5
- package/dist/{config-OEBMIN2U.js → config-TRBL3RCF.js} +48 -41
- package/dist/{configure-PUQOSIXQ.js → configure-OLCVPHNM.js} +17 -17
- package/dist/{context-URSXPBCK.js → context-MJIJ6GOX.js} +12 -12
- package/dist/{context-EKDCKUUZ.js → context-WFPKQSM6.js} +26 -9
- package/dist/{context-MGSE4Z2T.js → context-XEWE3MOJ.js} +44 -37
- package/dist/{context-clear-KDAJRNUK.js → context-clear-KNOS2JPB.js} +44 -37
- package/dist/{context-index-BZ4UYMTC.js → context-index-SSR5ECNE.js} +3 -3
- package/dist/{context-working-set-SBKMPPI2.js → context-working-set-EUXAZI6N.js} +14 -13
- package/dist/{dispatch-runner-MSWN72NK.js → dispatch-runner-B7MTOVKL.js} +321 -60
- package/dist/{docs-2C2LTVT2.js → docs-FLJTIDSE.js} +5 -5
- package/dist/{doctor-7BSE27PJ.js → doctor-RN4YKO2X.js} +15 -15
- package/dist/{eval-IZGDOO4H.js → eval-RUBJVSNQ.js} +52 -236
- package/dist/{evidence-SR7WXB5B.js → evidence-JZNBUOQZ.js} +39 -33
- package/dist/{evolve-K7VE2CBX.js → evolve-FJVC4KKI.js} +39 -33
- package/dist/{extensions-QVDOHDGJ.js → extensions-IQL36S7K.js} +5 -5
- package/dist/{fleet-7XMJNQNF.js → fleet-BDKYJFCP.js} +243 -370
- package/dist/fleet-commands-ZFIWZSB3.js +70 -0
- package/dist/fleet-graph-Y6HPXIVF.js +125 -0
- package/dist/fleet-new-RDVJLHHH.js +48 -0
- package/dist/{fleet-preflight-AQNAH644.js → fleet-preflight-BHSNPBMH.js} +2 -2
- package/dist/fleet-validate-BIYREGIK.js +79 -0
- package/dist/{init-JGNPAYXT.js → init-LQUB5COQ.js} +57 -48
- package/dist/library-NJAHIGG4.js +217 -0
- package/dist/memory-OG6HOYKM.js +472 -0
- package/dist/{models-ZMMLFJNN.js → models-5ZG5XY7J.js} +23 -22
- package/dist/{monitor-2F3T5KHP.js → monitor-TJ7AMTGB.js} +69 -35
- package/dist/{orchestrator-ORHT43JB.js → orchestrator-WZYB54DM.js} +4868 -1189
- package/dist/{paths-UXLN5YYZ.js → paths-XUC7GS6E.js} +5 -5
- package/dist/{reset-NXGTYNUO.js → reset-PXQT45IY.js} +8 -8
- package/dist/{run-RF4WJGMT.js → run-FQ74YF62.js} +82 -62
- package/dist/{share-UT3W6E4M.js → share-FW7SVCL3.js} +34 -10
- package/dist/{skills-PSACKC5Q.js → skills-7E7IRB3R.js} +25 -9
- package/dist/{skills-eval-WJSI55RZ.js → skills-eval-LI75W6OK.js} +43 -35
- package/dist/{targets-PIIRAOYS.js → targets-4CIFKCTW.js} +27 -24
- package/dist/{terminal-lease-ULWXWNVY.js → terminal-lease-WUZY7ZV5.js} +5 -4
- package/dist/{uninstall-FZCQCDKC.js → uninstall-7FV7IP4E.js} +5 -5
- package/dist/{upgrade-346TZ6AV.js → upgrade-K2HVIVMQ.js} +21 -20
- package/dist/{usage-6KKXR32N.js → usage-GTZELZQX.js} +159 -59
- package/dist/verifiers-RLAHT27O.js +336 -0
- package/dist/{verify-X5HDROLA.js → verify-BX3BRKH5.js} +7 -6
- package/dist/{wiki-generate-7STOCIFZ.js → wiki-generate-ASIFASCN.js} +58 -48
- package/dist/worker/entry.js +98 -84
- package/dist/{workspace-G4ZWUIPR.js → workspace-ZJ6BFM3Q.js} +4 -4
- package/docs/README.md +4 -3
- 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 +10 -6
- package/docs/built-in-agents.md +26 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +90 -8
- package/docs/configuration-and-targets.md +90 -2
- package/docs/context-engine.md +4 -2
- package/docs/context-working-set.md +4 -4
- package/docs/development-pipeline.md +1 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +4 -4
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +4 -45
- package/docs/evidence-and-memory.md +70 -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 +224 -11
- package/docs/git-commit-provenance.md +2 -2
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +2 -2
- package/docs/middleware-and-components.md +20 -2
- package/docs/model-catalog.md +1 -1
- package/docs/observability.md +55 -8
- package/docs/proactive-memory.md +26 -16
- 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 +29 -7
- 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 +38 -4
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +7 -4
- package/src/cli/agents.ts +2 -3
- package/src/cli/argv.ts +14 -1
- 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 +121 -0
- package/src/cli/fleet-validate.ts +30 -0
- package/src/cli/fleet.ts +188 -335
- package/src/cli/index.ts +4 -2
- package/src/cli/library.ts +190 -0
- 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/share.ts +13 -1
- package/src/cli/targets.ts +12 -3
- package/src/cli/usage.ts +160 -20
- package/src/core/bus-events.ts +7 -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/response-model-id.ts +134 -0
- package/src/core/toml.ts +62 -0
- package/src/core/workspace-files.ts +0 -1
- package/src/domains/agents/builtins/architect.md +2 -1
- package/src/domains/agents/builtins/oracle.md +33 -0
- package/src/domains/agents/catalog.ts +18 -5
- package/src/domains/agents/fleet-contract.ts +278 -16
- package/src/domains/agents/index.ts +14 -0
- package/src/domains/agents/recipe.ts +54 -14
- package/src/domains/agents/result-contract.ts +242 -5
- package/src/domains/config/classify.ts +4 -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/policies/index.ts +3 -4
- package/src/domains/dispatch/active-route-planner.ts +14 -0
- package/src/domains/dispatch/backoff.ts +2 -1
- package/src/domains/dispatch/budget-envelope.ts +396 -0
- 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 +36 -0
- package/src/domains/dispatch/delegation-plan.ts +167 -0
- package/src/domains/dispatch/execution-plan.ts +76 -5
- package/src/domains/dispatch/execution-role.ts +3 -1
- package/src/domains/dispatch/execution-scheduler.ts +183 -67
- package/src/domains/dispatch/extension.ts +339 -36
- 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 +737 -0
- package/src/domains/dispatch/gate-role-prompts.ts +9 -0
- package/src/domains/dispatch/host-verification.ts +178 -0
- package/src/domains/dispatch/index.ts +38 -0
- package/src/domains/dispatch/intent.ts +159 -0
- package/src/domains/dispatch/orphan-recovery.ts +1 -0
- package/src/domains/dispatch/receipt-integrity.ts +12 -4
- package/src/domains/dispatch/state.ts +37 -3
- package/src/domains/dispatch/types.ts +61 -9
- package/src/domains/dispatch/validation.ts +80 -6
- 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/trust-status.ts +10 -1
- 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/index.ts +15 -0
- package/src/domains/middleware/memory-intervention.ts +35 -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 +43 -1
- package/src/domains/middleware/types.ts +10 -0
- package/src/domains/middleware/watchdog.ts +281 -0
- package/src/domains/observability/contract.ts +9 -2
- package/src/domains/observability/cost.ts +31 -4
- 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/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/resources/index.ts +20 -0
- package/src/domains/resources/library.ts +326 -0
- package/src/domains/resources/skills/marketplace.ts +37 -12
- package/src/domains/safety/call-target.ts +211 -14
- package/src/domains/safety/decision-presentation.ts +268 -0
- package/src/domains/safety/redaction.ts +73 -0
- package/src/domains/session/context-ledger.ts +10 -1
- package/src/domains/session/decision-board.ts +4 -0
- package/src/domains/session/entries.ts +3 -0
- package/src/domains/session/handoff.ts +629 -0
- package/src/domains/session/history.ts +68 -19
- package/src/domains/session/usage.ts +24 -7
- package/src/domains/share/archive.ts +67 -2
- package/src/engine/acp/event-mapper.ts +7 -0
- package/src/engine/acp/server.ts +29 -2
- 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/worker-events.ts +4 -3
- package/src/engine/worker-runtime.ts +59 -54
- package/src/entry/orchestrator.ts +55 -1
- package/src/interactive/bus-notices.ts +26 -0
- package/src/interactive/chat-loop-messages.ts +22 -0
- package/src/interactive/chat-loop.ts +248 -1
- package/src/interactive/chat-renderer.ts +41 -3
- package/src/interactive/clio-editor.ts +44 -7
- package/src/interactive/context-overlay.ts +43 -5
- package/src/interactive/cost-overlay.ts +70 -11
- 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 +471 -50
- package/src/interactive/fleet-run-preview.ts +307 -0
- package/src/interactive/footer/notifications.ts +219 -0
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/handoff-round.ts +56 -0
- package/src/interactive/interactive-application.ts +49 -2
- package/src/interactive/interactive-event-projection.ts +9 -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 +52 -2
- package/src/interactive/interactive-subscriptions.ts +14 -2
- package/src/interactive/memory-overlay.ts +89 -4
- package/src/interactive/oracle.ts +179 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +7 -1
- package/src/interactive/overlay-frame.ts +5 -2
- package/src/interactive/overlay-general-openers.ts +230 -2
- package/src/interactive/overlay-key-routing.ts +58 -2
- package/src/interactive/overlay-lifecycle.ts +52 -5
- package/src/interactive/overlay-permission-lifecycle.ts +33 -8
- package/src/interactive/overlay-resource-openers.ts +11 -3
- package/src/interactive/overlay-session-lifecycle.ts +234 -2
- 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/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 +101 -4
- package/src/interactive/overlays/side-question.ts +139 -0
- package/src/interactive/overlays/skills-hub.ts +401 -15
- package/src/interactive/permission-hint.ts +35 -0
- package/src/interactive/permission-overlay.ts +95 -45
- package/src/interactive/renderers/tool-execution.ts +19 -49
- package/src/interactive/session-last-turn.ts +8 -1
- package/src/interactive/session-usage-reseed.ts +36 -10
- package/src/interactive/side-question.ts +171 -0
- package/src/interactive/slash-commands.ts +434 -7
- package/src/interactive/slash-spec.ts +19 -6
- 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/theme/tokens.ts +30 -0
- package/src/interactive/turn-context.ts +96 -23
- package/src/interactive/turn-middleware.ts +16 -1
- package/src/interactive/turn-runtime.ts +37 -8
- package/src/interactive/turn-state.ts +3 -0
- package/src/interactive/watchdog-run.ts +75 -0
- package/src/interactive/worker-progress.ts +440 -0
- package/src/interactive/worker-share.ts +56 -1
- package/src/interactive/worker-stream.ts +58 -110
- package/src/tools/agent-tools.ts +28 -3
- package/src/tools/ask-user.ts +21 -1
- package/src/tools/bootstrap.ts +3 -0
- package/src/tools/compete-worktrees.ts +13 -79
- package/src/tools/context/index.ts +2 -2
- package/src/tools/dispatch-admission.ts +242 -8
- package/src/tools/dispatch-arguments.ts +65 -1
- package/src/tools/dispatch-event-text.ts +19 -0
- package/src/tools/dispatch-plan.ts +136 -6
- package/src/tools/dispatch-runner.ts +319 -13
- package/src/tools/dispatch-types.ts +20 -1
- package/src/tools/dispatch.ts +96 -3
- package/src/tools/monitor.ts +31 -0
- package/src/tools/profiles.ts +18 -4
- package/src/tools/registry.ts +15 -5
- package/src/tools/result-disposition.ts +156 -0
- package/src/tools/result-shaping.ts +59 -1
- package/src/tools/task-worktree.ts +238 -0
- package/src/tools/verify/authoring.ts +116 -55
- package/src/tools/verify/scripts.ts +62 -0
- package/src/tools/worker-evidence.ts +21 -1
- package/src/worker/spec-contract.ts +44 -3
- package/dist/chunk-EFADSJET.js +0 -18
- package/dist/chunk-HC4CLZ2Y.js +0 -68
- package/dist/memory-4ALKDJ4Q.js +0 -246
- package/src/domains/eval/metrics/chaos-stream.ts +0 -93
|
@@ -119,3 +119,33 @@ export function createClioTheme(options: { truecolor?: boolean; color?: boolean
|
|
|
119
119
|
fgSequence: (token) => (color ? `\u001b[${fgCode(TOKENS[token], truecolor)}m` : ""),
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
|
+
|
|
123
|
+
/** True when `value` names one of the theme's own tokens, so it can be painted as one. */
|
|
124
|
+
export function isClioToken(value: string): value is ClioToken {
|
|
125
|
+
return Object.hasOwn(TOKENS, value);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const HEX_COLOR = /^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/u;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Paint text in a configured `#rrggbb` color.
|
|
132
|
+
*
|
|
133
|
+
* A council roster member may carry one. A roster color is the operator's own
|
|
134
|
+
* choice rather than a token from the palette, which is why a literal color
|
|
135
|
+
* reaches the screen here and nowhere else. Returns the text unchanged when
|
|
136
|
+
* color is disabled or the value is not a six-digit hex color, so a caller can
|
|
137
|
+
* fall back to a token without inspecting the string twice. A terminal without
|
|
138
|
+
* truecolor gets the nearest color in the 6x6x6 xterm cube.
|
|
139
|
+
*/
|
|
140
|
+
export function paintHex(text: string, hex: string, options: { truecolor?: boolean; color?: boolean } = {}): string {
|
|
141
|
+
const match = HEX_COLOR.exec(hex);
|
|
142
|
+
if (match === null) return text;
|
|
143
|
+
if (!(options.color ?? !colorDisabled())) return text;
|
|
144
|
+
const truecolor = options.truecolor ?? detectTruecolor();
|
|
145
|
+
const red = Number.parseInt(match[1] ?? "0", 16);
|
|
146
|
+
const green = Number.parseInt(match[2] ?? "0", 16);
|
|
147
|
+
const blue = Number.parseInt(match[3] ?? "0", 16);
|
|
148
|
+
if (truecolor) return `\u001b[38;2;${red};${green};${blue}m${text}${SGR_RESET}`;
|
|
149
|
+
const cube = (channel: number): number => Math.round((channel / 255) * 5);
|
|
150
|
+
return `\u001b[38;5;${16 + 36 * cube(red) + 6 * cube(green) + cube(blue)}m${text}${SGR_RESET}`;
|
|
151
|
+
}
|
|
@@ -23,7 +23,12 @@ import { selectVisibleEntries } from "../domains/context/working-set/visible.js"
|
|
|
23
23
|
import type { ObservabilityContract } from "../domains/observability/contract.js";
|
|
24
24
|
import type { CompiledSessionPrompt, SessionPromptInputs } from "../domains/prompts/compiler.js";
|
|
25
25
|
import type { PromptsContract } from "../domains/prompts/contract.js";
|
|
26
|
-
import
|
|
26
|
+
import {
|
|
27
|
+
type ContextWindowDetails,
|
|
28
|
+
type ContextWindowSource,
|
|
29
|
+
type ProvidersContract,
|
|
30
|
+
resolveRuntimeTarget,
|
|
31
|
+
} from "../domains/providers/index.js";
|
|
27
32
|
import type { LocalModelQuirks } from "../domains/providers/types/local-model-quirks.js";
|
|
28
33
|
import {
|
|
29
34
|
AutoCompactionTrigger,
|
|
@@ -309,6 +314,75 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
309
314
|
return ceilChars(snapshot.pendingUserInput.length);
|
|
310
315
|
};
|
|
311
316
|
|
|
317
|
+
/**
|
|
318
|
+
* The window the next turn will resolve to, read the way ensureRuntime
|
|
319
|
+
* reads it but without building an agent. Before the first turn of a
|
|
320
|
+
* process, /resume included, state.runtime is null, and the ledger and the
|
|
321
|
+
* footer meter said `context window unknown · 0 tokens` until a turn ran
|
|
322
|
+
* (issue #189). Null when no target is configured or it does not resolve,
|
|
323
|
+
* and the overlay's "unknown" is then true.
|
|
324
|
+
*/
|
|
325
|
+
const resolveWindowWithoutRuntime = (): ContextWindowDetails | null => {
|
|
326
|
+
const settings = deps.getSettings();
|
|
327
|
+
const targetId = settings.orchestrator?.target?.trim();
|
|
328
|
+
const wireModelId = settings.orchestrator?.model?.trim();
|
|
329
|
+
if (!targetId || !wireModelId) return null;
|
|
330
|
+
const resolved = resolveRuntimeTarget(deps.providers, {
|
|
331
|
+
targetId,
|
|
332
|
+
wireModelId,
|
|
333
|
+
requestedThinkingLevel: settings.orchestrator?.thinkingLevel ?? "off",
|
|
334
|
+
use: "orchestrator",
|
|
335
|
+
requireTools: false,
|
|
336
|
+
requireOutputBudget: true,
|
|
337
|
+
});
|
|
338
|
+
return resolved.ok ? resolved.target.contextWindowDetails : null;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const CONTEXT_WINDOW_SOURCES: ReadonlySet<string> = new Set<ContextWindowSource>([
|
|
342
|
+
"catalog",
|
|
343
|
+
"probe",
|
|
344
|
+
"loaded",
|
|
345
|
+
"target-override",
|
|
346
|
+
"model-hint",
|
|
347
|
+
"descriptor-default",
|
|
348
|
+
"unknown",
|
|
349
|
+
]);
|
|
350
|
+
|
|
351
|
+
/** The snapshot stores its source as a plain string; only a known label is worth repeating. */
|
|
352
|
+
const snapshotWindowSource = (snapshot: ContextSnapshot): ContextWindowSource | null =>
|
|
353
|
+
CONTEXT_WINDOW_SOURCES.has(snapshot.contextWindowSource)
|
|
354
|
+
? (snapshot.contextWindowSource as ContextWindowSource)
|
|
355
|
+
: null;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Window facts while no runtime exists: the live resolution first, then the
|
|
359
|
+
* resumed snapshot's recorded window, which is what the previous process
|
|
360
|
+
* measured the same messages against.
|
|
361
|
+
*/
|
|
362
|
+
const windowWithoutRuntime = (): {
|
|
363
|
+
contextWindow: number;
|
|
364
|
+
contextWindowSource: ContextWindowSource | null;
|
|
365
|
+
contextWindowSlots: ContextWindowDetails["contextWindowSlots"];
|
|
366
|
+
} => {
|
|
367
|
+
const details = resolveWindowWithoutRuntime();
|
|
368
|
+
if (details) {
|
|
369
|
+
return {
|
|
370
|
+
contextWindow: details.effectiveContextWindow,
|
|
371
|
+
contextWindowSource: details.contextWindowSource,
|
|
372
|
+
contextWindowSlots: details.contextWindowSlots,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
const snapshot = currentContextSnapshot;
|
|
376
|
+
if (snapshot && snapshot.effectiveContextWindow > 0) {
|
|
377
|
+
return {
|
|
378
|
+
contextWindow: snapshot.effectiveContextWindow,
|
|
379
|
+
contextWindowSource: snapshotWindowSource(snapshot),
|
|
380
|
+
contextWindowSlots: null,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
return { contextWindow: 0, contextWindowSource: null, contextWindowSlots: null };
|
|
384
|
+
};
|
|
385
|
+
|
|
312
386
|
const liveContextEstimate = (agentRuntime: AgentRuntime, pendingUserText?: string): LiveContextEstimate => {
|
|
313
387
|
const contextWindow = agentRuntime.runtimeResolution.contextWindowDetails.effectiveContextWindow;
|
|
314
388
|
const estimateInput = {
|
|
@@ -846,8 +920,9 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
846
920
|
},
|
|
847
921
|
|
|
848
922
|
contextUsage(): ContextUsageSnapshot {
|
|
849
|
-
|
|
850
|
-
|
|
923
|
+
const effectiveWindow = state.runtime
|
|
924
|
+
? state.runtime.runtimeResolution.contextWindowDetails.effectiveContextWindow
|
|
925
|
+
: windowWithoutRuntime().contextWindow;
|
|
851
926
|
if (!currentContextSnapshot) {
|
|
852
927
|
return contextUsageSnapshot(null, effectiveWindow);
|
|
853
928
|
}
|
|
@@ -867,28 +942,27 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
867
942
|
const settings = deps.getSettings();
|
|
868
943
|
const compactionThreshold = settings.compaction?.threshold ?? null;
|
|
869
944
|
const compactionAuto = settings.compaction?.auto !== false;
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
const
|
|
883
|
-
const
|
|
945
|
+
// Without a runtime (before the first turn of this process, /resume
|
|
946
|
+
// included) the window comes from the live resolution or the resumed
|
|
947
|
+
// snapshot, and the token facts from the snapshot: the resumed
|
|
948
|
+
// messages are the ones it measured.
|
|
949
|
+
const window = state.runtime
|
|
950
|
+
? {
|
|
951
|
+
contextWindow: state.runtime.runtimeResolution.contextWindowDetails.effectiveContextWindow,
|
|
952
|
+
contextWindowSource: state.runtime.runtimeResolution.contextWindowDetails.contextWindowSource,
|
|
953
|
+
contextWindowSlots: state.runtime.runtimeResolution.contextWindowDetails.contextWindowSlots,
|
|
954
|
+
}
|
|
955
|
+
: windowWithoutRuntime();
|
|
956
|
+
const provider = state.runtime?.targetId ?? settings.orchestrator?.target ?? null;
|
|
957
|
+
const model = state.runtime?.wireModelId ?? settings.orchestrator?.model ?? null;
|
|
958
|
+
const liveToolCount = state.runtime?.agent.state.tools.length ?? 0;
|
|
884
959
|
|
|
885
960
|
if (!currentContextSnapshot) {
|
|
886
961
|
return buildContextLedger({
|
|
887
962
|
provider,
|
|
888
963
|
model,
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
toolCount: state.runtime.agent.state.tools.length,
|
|
964
|
+
...window,
|
|
965
|
+
toolCount: liveToolCount,
|
|
892
966
|
compactionThreshold,
|
|
893
967
|
compactionAuto,
|
|
894
968
|
promptCache: lastPromptCache,
|
|
@@ -903,15 +977,14 @@ export function createTurnContext(deps: TurnContextDeps): TurnContext {
|
|
|
903
977
|
return buildContextLedger({
|
|
904
978
|
provider,
|
|
905
979
|
model,
|
|
906
|
-
|
|
907
|
-
contextWindowSource: windowDetails.contextWindowSource,
|
|
980
|
+
...window,
|
|
908
981
|
compactionThreshold,
|
|
909
982
|
compactionAuto,
|
|
910
983
|
systemPromptTokens: currentContextSnapshot.categories.system,
|
|
911
984
|
toolSchemaTokens: currentContextSnapshot.categories.tools,
|
|
912
985
|
// Persisted snapshots strip the captured schemas; fall back to
|
|
913
986
|
// the live agent state after a session resume.
|
|
914
|
-
toolCount: currentContextSnapshot.activeToolSchemas?.length ??
|
|
987
|
+
toolCount: currentContextSnapshot.activeToolSchemas?.length ?? liveToolCount,
|
|
915
988
|
messageTokens: currentContextSnapshot.categories.messages,
|
|
916
989
|
agentsTokens: currentContextSnapshot.categories.agents,
|
|
917
990
|
skillsTokens: currentContextSnapshot.categories.skills,
|
|
@@ -25,7 +25,7 @@ export interface TurnMiddlewareDeps {
|
|
|
25
25
|
middleware?: MiddlewareContract | undefined;
|
|
26
26
|
session?: SessionContract | undefined;
|
|
27
27
|
middlewareToolChoice: MiddlewareToolChoiceControl;
|
|
28
|
-
emitNotice: (text: string) => void;
|
|
28
|
+
emitNotice: (text: string, level?: "info" | "warning" | "error") => void;
|
|
29
29
|
emitFooterNotice: (level: "info" | "success" | "warning" | "error", text: string, key: string) => void;
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -55,6 +55,14 @@ export interface TurnMiddleware {
|
|
|
55
55
|
* turn_end reminder takes.
|
|
56
56
|
*/
|
|
57
57
|
injectDeferredReminder(message: string, severity?: MiddlewareReminderSeverity): void;
|
|
58
|
+
/**
|
|
59
|
+
* Deliver an operator-facing finding produced after its turn boundary closed.
|
|
60
|
+
* The watchdog seam: its run settles well after the turn it reviewed, and
|
|
61
|
+
* what it found is for the person, not the model. Unlike a deferred
|
|
62
|
+
* reminder, this never joins the pending-reminder buffer and never appends a
|
|
63
|
+
* `middlewareReminder` entry, so nothing it says can enter the next request.
|
|
64
|
+
*/
|
|
65
|
+
emitDeferredNotice(text: string, level?: "info" | "warning"): void;
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
export function createTurnMiddleware(deps: TurnMiddlewareDeps): TurnMiddleware {
|
|
@@ -205,6 +213,7 @@ export function createTurnMiddleware(deps: TurnMiddlewareDeps): TurnMiddleware {
|
|
|
205
213
|
runtimeTier: agentRuntime.runtimeResolution.runtimeTier ?? "",
|
|
206
214
|
activeToolNames: toolNamesFromAgentState(agentRuntime.agent.state.tools).join(","),
|
|
207
215
|
turnToolCalls: state.turnToolCalls,
|
|
216
|
+
turnToolNames: state.turnToolNames.join(","),
|
|
208
217
|
sharedWorkerNote: state.turnSharedWorkerNote,
|
|
209
218
|
};
|
|
210
219
|
if (terminalToolResult !== undefined) {
|
|
@@ -279,5 +288,11 @@ export function createTurnMiddleware(deps: TurnMiddlewareDeps): TurnMiddleware {
|
|
|
279
288
|
appendMiddlewareReminderEntry(text, level);
|
|
280
289
|
deps.emitNotice(text);
|
|
281
290
|
},
|
|
291
|
+
|
|
292
|
+
emitDeferredNotice(text, level = "warning"): void {
|
|
293
|
+
const message = text.trim();
|
|
294
|
+
if (message.length === 0) return;
|
|
295
|
+
deps.emitNotice(message, level);
|
|
296
|
+
},
|
|
282
297
|
};
|
|
283
298
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { performance } from "node:perf_hooks";
|
|
9
9
|
import type { ClioSettings } from "../core/config.js";
|
|
10
|
+
import { attributedModelId } from "../core/response-model-id.js";
|
|
10
11
|
import type { MiddlewareToolChoiceControl } from "../domains/middleware/index.js";
|
|
11
12
|
import type { ObservabilityContract } from "../domains/observability/contract.js";
|
|
12
13
|
import {
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
type ProvidersContract,
|
|
16
17
|
refineRuntimeTargetWithModelHints,
|
|
17
18
|
resolveRuntimeTarget,
|
|
18
|
-
|
|
19
|
+
runtimeResolutionWarningsBesideThinkingNotice,
|
|
19
20
|
type TargetStatus,
|
|
20
21
|
targetRequiresAuth,
|
|
21
22
|
} from "../domains/providers/index.js";
|
|
@@ -199,7 +200,12 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
199
200
|
failure?.code ?? "admission-failed",
|
|
200
201
|
);
|
|
201
202
|
}
|
|
202
|
-
|
|
203
|
+
// emitThinkingClampNotice prints the one combined thinking line when the
|
|
204
|
+
// dial takes effect; the thinking diagnostics are its two halves.
|
|
205
|
+
for (const message of runtimeResolutionWarningsBesideThinkingNotice(
|
|
206
|
+
resolved.diagnostics,
|
|
207
|
+
resolved.target.modelRuntime.thinking.notice,
|
|
208
|
+
)) {
|
|
203
209
|
const key = `${targetId}|${wireModelId}|${message}`;
|
|
204
210
|
if (announcedResolutionWarnings.has(key)) continue;
|
|
205
211
|
announcedResolutionWarnings.add(key);
|
|
@@ -229,6 +235,7 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
229
235
|
*/
|
|
230
236
|
const TARGET_PROBE_TTL_MS = 5 * 60 * 1000;
|
|
231
237
|
let lastTargetProbe: { key: string; at: number } | null = null;
|
|
238
|
+
const targetProbesInFlight = new Map<string, Promise<void>>();
|
|
232
239
|
const ensureLiveCapabilitiesForSelectedModel = async (): Promise<void> => {
|
|
233
240
|
const settings = deps.getSettings();
|
|
234
241
|
const targetId = settings.orchestrator.target?.trim();
|
|
@@ -239,16 +246,29 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
239
246
|
const runtimeDesc = deps.providers.getRuntime(target.runtime);
|
|
240
247
|
if (!runtimeDesc || runtimeDesc.tier === "cloud") return;
|
|
241
248
|
const key = `${targetId}|${wireModelId}`;
|
|
249
|
+
const inFlight = targetProbesInFlight.get(key);
|
|
250
|
+
if (inFlight) {
|
|
251
|
+
await inFlight;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
242
254
|
const now = Date.now();
|
|
243
255
|
if (lastTargetProbe?.key === key && now - lastTargetProbe.at < TARGET_PROBE_TTL_MS) return;
|
|
244
256
|
lastTargetProbe = { key, at: now };
|
|
245
|
-
|
|
257
|
+
const probe = (async (): Promise<void> => {
|
|
258
|
+
let status: Awaited<ReturnType<ProvidersContract["probeTarget"]>> = null;
|
|
259
|
+
try {
|
|
260
|
+
status = await deps.providers.probeTarget(targetId);
|
|
261
|
+
} catch {
|
|
262
|
+
// Fall back to the last known target state.
|
|
263
|
+
}
|
|
264
|
+
announceColdModel(status, targetId, wireModelId);
|
|
265
|
+
})();
|
|
266
|
+
targetProbesInFlight.set(key, probe);
|
|
246
267
|
try {
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
268
|
+
await probe;
|
|
269
|
+
} finally {
|
|
270
|
+
if (targetProbesInFlight.get(key) === probe) targetProbesInFlight.delete(key);
|
|
250
271
|
}
|
|
251
|
-
announceColdModel(status, targetId, wireModelId);
|
|
252
272
|
};
|
|
253
273
|
|
|
254
274
|
/** One notice per target+model+state, so a repeated probe stays quiet. */
|
|
@@ -589,6 +609,7 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
589
609
|
middlewareToolChoice.toolStarted(event.toolName);
|
|
590
610
|
deps.toolStartTimes.set(event.toolCallId, eventClock);
|
|
591
611
|
state.turnToolCalls += 1;
|
|
612
|
+
state.turnToolNames.push(event.toolName);
|
|
592
613
|
} else if (event.type === "tool_execution_end") {
|
|
593
614
|
toolsInFlight = Math.max(0, toolsInFlight - 1);
|
|
594
615
|
const startedAt = deps.toolStartTimes.get(event.toolCallId);
|
|
@@ -713,7 +734,11 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
713
734
|
if (summary.hadUsage && (summary.tokens > 0 || summary.costUsd > 0)) {
|
|
714
735
|
deps.observability.recordTokens(
|
|
715
736
|
localRuntime.targetId,
|
|
716
|
-
|
|
737
|
+
attributedModelId(
|
|
738
|
+
summary.lastResponseModelIdObservation,
|
|
739
|
+
localRuntime.wireModelId,
|
|
740
|
+
summary.lastDifferingResponseModelId,
|
|
741
|
+
),
|
|
717
742
|
summary.tokens,
|
|
718
743
|
summary.costUsd,
|
|
719
744
|
{
|
|
@@ -726,6 +751,10 @@ export function createTurnRuntime(deps: TurnRuntimeDeps): TurnRuntime {
|
|
|
726
751
|
apiCalls: summary.apiCalls,
|
|
727
752
|
},
|
|
728
753
|
localRuntime.runtimeResolution.costProvenance,
|
|
754
|
+
{
|
|
755
|
+
requestedModelIds: [localRuntime.wireModelId],
|
|
756
|
+
responseModelIdObservationCounts: summary.responseModelIdObservationCounts,
|
|
757
|
+
},
|
|
729
758
|
);
|
|
730
759
|
}
|
|
731
760
|
if (summary.output > 0 && firstAssistantDeltaAt !== null) {
|
|
@@ -97,6 +97,8 @@ export interface ChatTurnState {
|
|
|
97
97
|
toolProseAssessedChars: number;
|
|
98
98
|
/** Tool calls observed in the current turn; feeds turn_end metadata. */
|
|
99
99
|
turnToolCalls: number;
|
|
100
|
+
/** Names of those calls, in order, so turn_end can tell a listing-only turn from a working one. */
|
|
101
|
+
turnToolNames: string[];
|
|
100
102
|
/** A `[worker result]` note the operator shared entered this turn, as the prompt or as a steer; feeds turn_end metadata. */
|
|
101
103
|
turnSharedWorkerNote: boolean;
|
|
102
104
|
/** One stalled-turn nudge per user prompt; reset when a real prompt arrives. */
|
|
@@ -123,6 +125,7 @@ export function createTurnState(initialThinkingLevel: ThinkingLevel): ChatTurnSt
|
|
|
123
125
|
streamStallReason: null,
|
|
124
126
|
toolProseAssessedChars: 0,
|
|
125
127
|
turnToolCalls: 0,
|
|
128
|
+
turnToolNames: [],
|
|
126
129
|
turnSharedWorkerNote: false,
|
|
127
130
|
stalledTurnNudgeSpent: false,
|
|
128
131
|
pendingRequestContinuation: false,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The watchdog's run: one read-only verifier dispatch, one transcript notice.
|
|
3
|
+
*
|
|
4
|
+
* The middleware registration decides when to fire and what the turn changed;
|
|
5
|
+
* this decides nothing. It dispatches through the ordinary path so admission,
|
|
6
|
+
* the receipt, and the Fleet Runs island treat a watchdog run exactly as they
|
|
7
|
+
* treat any other, reads the failed checks out of the `verifier-report`
|
|
8
|
+
* contract, and hands the operator one line. A passing report produces nothing
|
|
9
|
+
* at all.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { BusChannels } from "../core/bus-events.js";
|
|
13
|
+
import type { SafeEventBus } from "../core/event-bus.js";
|
|
14
|
+
import { parseVerifierResult } from "../domains/agents/index.js";
|
|
15
|
+
import type { DispatchContract, DispatchRequest } from "../domains/dispatch/contract.js";
|
|
16
|
+
import { type AgentRoleFactsResolver, requestExecutionRole } from "../domains/dispatch/execution-role.js";
|
|
17
|
+
import { WATCHDOG_TASK, type WatchdogTrigger, watchdogBriefing } from "../domains/middleware/index.js";
|
|
18
|
+
import { watchdogBlockersNotice } from "./bus-notices.js";
|
|
19
|
+
|
|
20
|
+
/** The builtin recipe the watchdog reviews with. */
|
|
21
|
+
export const WATCHDOG_AGENT_ID = "verifier";
|
|
22
|
+
|
|
23
|
+
export interface WatchdogRunDeps {
|
|
24
|
+
dispatch: DispatchContract;
|
|
25
|
+
bus?: SafeEventBus;
|
|
26
|
+
getAgentRoleFacts?: AgentRoleFactsResolver;
|
|
27
|
+
/** `watchdog.target` when the operator set one; the session's active target otherwise. */
|
|
28
|
+
target?: string | undefined;
|
|
29
|
+
/** One transcript line for the operator. Absent means the finding has nowhere to go and the run is skipped. */
|
|
30
|
+
emitNotice?: (text: string) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Dispatch one watchdog review and report what it found.
|
|
35
|
+
*
|
|
36
|
+
* Resolves when the run has settled, whatever the outcome. A watchdog that
|
|
37
|
+
* failed is not a turn that failed: the review is advisory, so a broken run
|
|
38
|
+
* stays silent rather than raising an alarm about itself in the middle of the
|
|
39
|
+
* operator's work.
|
|
40
|
+
*/
|
|
41
|
+
export async function runWatchdogReview(trigger: WatchdogTrigger, deps: WatchdogRunDeps): Promise<void> {
|
|
42
|
+
if (!deps.emitNotice) return;
|
|
43
|
+
const request: DispatchRequest = {
|
|
44
|
+
agentId: WATCHDOG_AGENT_ID,
|
|
45
|
+
task: WATCHDOG_TASK,
|
|
46
|
+
briefing: watchdogBriefing(trigger),
|
|
47
|
+
executionRole: requestExecutionRole({
|
|
48
|
+
agentId: WATCHDOG_AGENT_ID,
|
|
49
|
+
...(deps.getAgentRoleFacts ? { resolveFacts: deps.getAgentRoleFacts } : {}),
|
|
50
|
+
}),
|
|
51
|
+
requestOrigin: "internal",
|
|
52
|
+
// Narrowed below whatever the session holds. A reviewer that could write
|
|
53
|
+
// would be a second builder nobody admitted.
|
|
54
|
+
autonomy: "read-only",
|
|
55
|
+
...(deps.target ? { target: deps.target } : {}),
|
|
56
|
+
};
|
|
57
|
+
const progressBus = deps.dispatch.ownsProgressBus?.(deps.bus) === true ? undefined : deps.bus;
|
|
58
|
+
try {
|
|
59
|
+
const handle = await deps.dispatch.dispatch(request);
|
|
60
|
+
for await (const event of handle.events) {
|
|
61
|
+
const typed = event as { type?: string };
|
|
62
|
+
if (!typed.type || typed.type === "heartbeat") continue;
|
|
63
|
+
progressBus?.emit(BusChannels.DispatchProgress, { runId: handle.runId, agentId: WATCHDOG_AGENT_ID, event });
|
|
64
|
+
}
|
|
65
|
+
const receipt = await handle.finalPromise;
|
|
66
|
+
const report = parseVerifierResult(receipt.output?.text ?? null);
|
|
67
|
+
if (report === null) return;
|
|
68
|
+
const notice = watchdogBlockersNotice(report.checks);
|
|
69
|
+
if (notice === null) return;
|
|
70
|
+
deps.emitNotice(notice.text);
|
|
71
|
+
} catch {
|
|
72
|
+
// An advisory review that could not run says nothing. The receipt, if one
|
|
73
|
+
// was written at all, is in the dispatch board like every other run.
|
|
74
|
+
}
|
|
75
|
+
}
|