@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
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { performance } from "node:perf_hooks";
|
|
3
|
-
import {
|
|
4
|
-
addChaosObservations,
|
|
5
|
-
chaosMetricEntries,
|
|
6
|
-
createChaosFold,
|
|
7
|
-
EMPTY_CHAOS_OBSERVATION,
|
|
8
|
-
type EvalChaosObservation,
|
|
9
|
-
parseChaosMarker,
|
|
10
|
-
} from "../metrics/chaos-stream.js";
|
|
11
3
|
import {
|
|
12
4
|
addFleetLoopObservations,
|
|
13
5
|
createFleetLoopFold,
|
|
@@ -53,8 +45,6 @@ export interface ShellCommandResult {
|
|
|
53
45
|
usage: EvalTokenStreamUsage;
|
|
54
46
|
/** Wire-stream structural invariants folded live, for the same reason. */
|
|
55
47
|
streamInvariants: EvalStreamInvariants;
|
|
56
|
-
/** Strict SIGINT harness marker folded live from stdout. */
|
|
57
|
-
chaos: EvalChaosObservation;
|
|
58
48
|
fleetLoops: EvalFleetLoopObservation;
|
|
59
49
|
stderr: string;
|
|
60
50
|
wallTimeMs: number;
|
|
@@ -84,7 +74,6 @@ export async function runExternalCommandRunner(
|
|
|
84
74
|
// is reported as unmeasured, never as zero cost.
|
|
85
75
|
let usage = UNMEASURED_TOKEN_USAGE;
|
|
86
76
|
let streamInvariants = EMPTY_STREAM_INVARIANTS;
|
|
87
|
-
let chaos = EMPTY_CHAOS_OBSERVATION;
|
|
88
77
|
let fleetLoops = EMPTY_FLEET_LOOP_OBSERVATION;
|
|
89
78
|
for (const command of commands) {
|
|
90
79
|
const result = await runShellCommand(command, cwd, runner.timeoutMs ?? timeoutMs, env);
|
|
@@ -93,7 +82,6 @@ export async function runExternalCommandRunner(
|
|
|
93
82
|
wallTimeMs += result.wallTimeMs;
|
|
94
83
|
usage = addTokenStreamUsage(usage, result.usage);
|
|
95
84
|
streamInvariants = addStreamInvariants(streamInvariants, result.streamInvariants);
|
|
96
|
-
chaos = addChaosObservations(chaos, result.chaos);
|
|
97
85
|
fleetLoops = addFleetLoopObservations(fleetLoops, result.fleetLoops);
|
|
98
86
|
if (result.exitCode !== 0) {
|
|
99
87
|
return {
|
|
@@ -107,11 +95,10 @@ export async function runExternalCommandRunner(
|
|
|
107
95
|
"latency.wallMs": wallTimeMs,
|
|
108
96
|
...tokenMetricEntries(usage),
|
|
109
97
|
...streamInvariantMetrics(streamInvariants),
|
|
110
|
-
...chaosMetricEntries(chaos),
|
|
111
98
|
...fleetLoopMetricEntries(fleetLoops),
|
|
112
99
|
"verifier.exitCode": result.exitCode,
|
|
113
100
|
},
|
|
114
|
-
artifacts:
|
|
101
|
+
artifacts: {},
|
|
115
102
|
};
|
|
116
103
|
}
|
|
117
104
|
}
|
|
@@ -126,11 +113,10 @@ export async function runExternalCommandRunner(
|
|
|
126
113
|
"latency.wallMs": wallTimeMs,
|
|
127
114
|
...tokenMetricEntries(usage),
|
|
128
115
|
...streamInvariantMetrics(streamInvariants),
|
|
129
|
-
...chaosMetricEntries(chaos),
|
|
130
116
|
...fleetLoopMetricEntries(fleetLoops),
|
|
131
117
|
"verifier.exitCode": 0,
|
|
132
118
|
},
|
|
133
|
-
artifacts:
|
|
119
|
+
artifacts: {},
|
|
134
120
|
};
|
|
135
121
|
}
|
|
136
122
|
|
|
@@ -150,7 +136,6 @@ export function runShellCommand(
|
|
|
150
136
|
const metricCapture = createJsonlMetricCapture();
|
|
151
137
|
const usageFold = createTokenUsageFold();
|
|
152
138
|
const streamFold = createStreamInvariantFold();
|
|
153
|
-
const chaosFold = createChaosFold();
|
|
154
139
|
const fleetLoopFold = createFleetLoopFold();
|
|
155
140
|
let timedOut = false;
|
|
156
141
|
let settled = false;
|
|
@@ -169,7 +154,6 @@ export function runShellCommand(
|
|
|
169
154
|
metricCapture.push(chunk);
|
|
170
155
|
usageFold.push(chunk);
|
|
171
156
|
streamFold.push(chunk);
|
|
172
|
-
chaosFold.push(chunk);
|
|
173
157
|
fleetLoopFold.push(chunk);
|
|
174
158
|
});
|
|
175
159
|
child.stderr.on("data", (chunk: string) => {
|
|
@@ -191,7 +175,6 @@ export function runShellCommand(
|
|
|
191
175
|
metricJsonl: metricCapture.finish(),
|
|
192
176
|
usage: usageFold.usage(),
|
|
193
177
|
streamInvariants: streamFold.invariants(),
|
|
194
|
-
chaos: chaosFold.observation(),
|
|
195
178
|
fleetLoops: fleetLoopFold.observation(),
|
|
196
179
|
stderr,
|
|
197
180
|
wallTimeMs: Math.round(performance.now() - started),
|
|
@@ -290,10 +273,6 @@ export function createJsonlMetricCapture(): JsonlMetricCapture {
|
|
|
290
273
|
|
|
291
274
|
function compactMetricEvent(event: Record<string, unknown>): Record<string, unknown> | null {
|
|
292
275
|
const type = event.type;
|
|
293
|
-
if (type === "clio_soak_chaos") {
|
|
294
|
-
const marker = parseChaosMarker(event);
|
|
295
|
-
return marker === null ? null : { type, ...marker };
|
|
296
|
-
}
|
|
297
276
|
if (type === "tool_execution_start") {
|
|
298
277
|
const toolName = stringField(event, "toolName");
|
|
299
278
|
if (toolName !== "dispatch" && toolName !== "code_nav" && toolName !== "read" && toolName !== "grep") {
|
|
@@ -334,12 +313,6 @@ function compactMetricEvent(event: Record<string, unknown>): Record<string, unkn
|
|
|
334
313
|
};
|
|
335
314
|
}
|
|
336
315
|
|
|
337
|
-
function chaosArtifacts(observation: EvalChaosObservation): Record<string, string> {
|
|
338
|
-
return observation.markerCount === 1 && observation.marker !== null
|
|
339
|
-
? { chaosSeed: String(observation.marker.seed) }
|
|
340
|
-
: {};
|
|
341
|
-
}
|
|
342
|
-
|
|
343
316
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
344
317
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
345
318
|
}
|
|
@@ -43,13 +43,6 @@ export const CANONICAL_METRICS = [
|
|
|
43
43
|
"evidence.verification",
|
|
44
44
|
"evidence.firstPassSuccess",
|
|
45
45
|
"cost.usd",
|
|
46
|
-
// Behavioral checkpoints for the bounded reconnaissance live suite.
|
|
47
|
-
"dispatch.count",
|
|
48
|
-
"wiki.staleAcknowledged",
|
|
49
|
-
// SIGINT chaos-harness facts folded live from its one strict stdout marker.
|
|
50
|
-
"chaos.seed",
|
|
51
|
-
"chaos.faultInjected",
|
|
52
|
-
"chaos.exitCode",
|
|
53
46
|
// Invariant checks: what Clio promised about its own machinery, read from
|
|
54
47
|
// the journal the item's run left behind. These are true or false about
|
|
55
48
|
// Clio and say nothing about whether the model solved the task. A check
|
|
@@ -126,7 +126,7 @@ async function runMatrixItem(
|
|
|
126
126
|
CLIO_CODER_ENTRY: clioEntry,
|
|
127
127
|
});
|
|
128
128
|
const patch = collectPatchMetrics(workspace.dir);
|
|
129
|
-
const receiptExitCode =
|
|
129
|
+
const receiptExitCode = runner.exitCode;
|
|
130
130
|
// Read after the runner returned and before the journal is removed: what
|
|
131
131
|
// Clio sealed for this item, judged against its own ledger, and whether
|
|
132
132
|
// the workers it attested are still running.
|
|
@@ -193,12 +193,6 @@ async function runMatrixItem(
|
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
/** A SIGINT harness exits cleanly after checking the nested Clio process; reconcile its receipt to that nested exit. */
|
|
197
|
-
export function receiptProcessExitCode(runner: Pick<EvalRunnerOutput, "exitCode" | "metrics">): number {
|
|
198
|
-
const chaosExitCode = runner.metrics["chaos.exitCode"];
|
|
199
|
-
return typeof chaosExitCode === "number" && Number.isInteger(chaosExitCode) ? chaosExitCode : runner.exitCode;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
196
|
/** Journal-derived invariants for one finished item, read from its isolated state directory. */
|
|
203
197
|
function invariantMetrics(stateDir: string, runnerExitCode: number): Record<string, number | boolean> {
|
|
204
198
|
const journal = readRunJournal(stateDir);
|
|
@@ -418,6 +418,7 @@ export type PersistedRunReceiptTrustFacts = Pick<RunReceipt, "runId"> &
|
|
|
418
418
|
RunReceipt,
|
|
419
419
|
| "integrity"
|
|
420
420
|
| "verification"
|
|
421
|
+
| "hostVerification"
|
|
421
422
|
| "quality"
|
|
422
423
|
| "validationGrounding"
|
|
423
424
|
| "briefing"
|
|
@@ -536,6 +537,12 @@ export function adaptRunReceiptValidationStatus(
|
|
|
536
537
|
): ValidationGroundingStatus {
|
|
537
538
|
if (receipt === null || receipt === undefined) return absentTrustStatus("artifact_missing");
|
|
538
539
|
const artifacts = validationArtifacts(receipt);
|
|
540
|
+
if (receipt.hostVerification?.status === "rejected") {
|
|
541
|
+
return attributed("failed", receiptSource(receipt), { kind: "validator", id: "host-verification" }, artifacts);
|
|
542
|
+
}
|
|
543
|
+
if (receipt.hostVerification?.status === "verified") {
|
|
544
|
+
return attributed("validated", receiptSource(receipt), { kind: "validator", id: "host-verification" }, artifacts);
|
|
545
|
+
}
|
|
539
546
|
if (qualityHasFailure(receipt.quality)) {
|
|
540
547
|
return attributed("failed", receiptSource(receipt), { kind: "validator", id: "receipt-quality" }, artifacts);
|
|
541
548
|
}
|
|
@@ -549,7 +556,9 @@ export function adaptRunReceiptValidationStatus(
|
|
|
549
556
|
if (qualityHasValidation(receipt.quality)) {
|
|
550
557
|
return attributed("validated", receiptSource(receipt), { kind: "validator", id: "receipt-quality" }, artifacts);
|
|
551
558
|
}
|
|
552
|
-
if (receipt.verification !== undefined)
|
|
559
|
+
if (receipt.verification !== undefined) {
|
|
560
|
+
return verificationStatus(receipt.verification, receipt, artifacts);
|
|
561
|
+
}
|
|
553
562
|
return attributed("unknown", compatibilitySource(receipt, "verification"), COMPATIBILITY_AUTHORITY, artifacts);
|
|
554
563
|
}
|
|
555
564
|
|
|
@@ -6,6 +6,20 @@ export {
|
|
|
6
6
|
rejectMemoryRecord,
|
|
7
7
|
selectApprovedMemory,
|
|
8
8
|
} from "./operations.js";
|
|
9
|
+
export {
|
|
10
|
+
applyScopeIdentity,
|
|
11
|
+
MEMORY_PROMOTION_SCOPES,
|
|
12
|
+
type MemoryPromotionScope,
|
|
13
|
+
type MemoryPromotionSource,
|
|
14
|
+
type MemoryPromotionSourceRedaction,
|
|
15
|
+
type MemoryScopeSelection,
|
|
16
|
+
memoryAgentIdentity,
|
|
17
|
+
memoryRecordFromPromotion,
|
|
18
|
+
memoryRuntimeIdentity,
|
|
19
|
+
memoryScopeIdentityKey,
|
|
20
|
+
proposeMemoryPromotion,
|
|
21
|
+
validateMemoryScopeSelection,
|
|
22
|
+
} from "./promotion.js";
|
|
9
23
|
export {
|
|
10
24
|
buildMemoryPromptSection,
|
|
11
25
|
MEMORY_PROMPT_DEFAULT_MAX_ITEMS,
|
|
@@ -46,7 +60,9 @@ export {
|
|
|
46
60
|
type TaskMemorySnapshot,
|
|
47
61
|
} from "./task-bank.js";
|
|
48
62
|
export {
|
|
63
|
+
type LegacyTaskMemoryHandoffSnapshot,
|
|
49
64
|
parseTaskMemoryHandoffSnapshot,
|
|
65
|
+
type ReviewedTaskMemoryHandoffSnapshot,
|
|
50
66
|
readNewestTaskMemoryHandoff,
|
|
51
67
|
renderTaskMemoryHandoffSnapshot,
|
|
52
68
|
renderTaskMemoryHandoffSource,
|
|
@@ -57,9 +73,11 @@ export {
|
|
|
57
73
|
type TaskMemoryHandoffArtifact,
|
|
58
74
|
type TaskMemoryHandoffEntry,
|
|
59
75
|
type TaskMemoryHandoffOffer,
|
|
76
|
+
type TaskMemoryHandoffRedaction,
|
|
60
77
|
type TaskMemoryHandoffSeedOutcome,
|
|
61
78
|
type TaskMemoryHandoffSeedResult,
|
|
62
79
|
type TaskMemoryHandoffSnapshot,
|
|
80
|
+
type TaskMemoryHandoffSourceProvenance,
|
|
63
81
|
taskMemoryHandoffSeedOffer,
|
|
64
82
|
taskMemoryHandoffSnapshot,
|
|
65
83
|
} from "./task-memory-handoff.js";
|
|
@@ -112,12 +130,16 @@ export {
|
|
|
112
130
|
taskMemoryTracePath,
|
|
113
131
|
} from "./task-memory-trace.js";
|
|
114
132
|
export type {
|
|
133
|
+
MemoryAgentIdentity,
|
|
134
|
+
MemoryPromotionRedaction,
|
|
115
135
|
MemoryProposalResult,
|
|
116
136
|
MemoryPruneResult,
|
|
117
137
|
MemoryRecord,
|
|
138
|
+
MemoryRecordProvenance,
|
|
118
139
|
MemoryRecordValidationResult,
|
|
119
140
|
MemoryRepositoryIdentity,
|
|
120
141
|
MemoryRetrievalOptions,
|
|
142
|
+
MemoryRuntimeIdentity,
|
|
121
143
|
MemoryScope,
|
|
122
144
|
MemoryStatus,
|
|
123
145
|
MemoryStoreFile,
|
|
@@ -2,7 +2,13 @@ import { isAbsolute } from "node:path";
|
|
|
2
2
|
import { canonicalizeExistingPath } from "../../core/path-canonical.js";
|
|
3
3
|
import { ceilChars } from "../session/context-accounting.js";
|
|
4
4
|
import { pruneStaleMemoryRecords, sortMemoryRecords, updateMemoryRecord } from "./store.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
MemoryAgentIdentity,
|
|
7
|
+
MemoryRecord,
|
|
8
|
+
MemoryRepositoryIdentity,
|
|
9
|
+
MemoryRetrievalOptions,
|
|
10
|
+
MemoryRuntimeIdentity,
|
|
11
|
+
} from "./types.js";
|
|
6
12
|
|
|
7
13
|
export async function approveMemoryRecord(
|
|
8
14
|
dataDir: string,
|
|
@@ -31,12 +37,16 @@ export function selectApprovedMemory(
|
|
|
31
37
|
if (options.tokenBudget <= 0) return [];
|
|
32
38
|
const allowedScopes = options.scopes === undefined ? null : new Set(options.scopes);
|
|
33
39
|
const activeRepository = canonicalActiveRepository(options.activeRepository);
|
|
40
|
+
const activeRuntime = validActiveNamedIdentity(options.activeRuntime, "runtime");
|
|
41
|
+
const activeAgent = validActiveNamedIdentity(options.activeAgent, "agent");
|
|
34
42
|
const candidates = sortMemoryRecords(records)
|
|
35
43
|
.filter((record) => record.approved)
|
|
36
44
|
.filter((record) => record.evidenceRefs.length > 0)
|
|
37
45
|
.filter((record) => record.regressions === undefined || record.regressions.length === 0)
|
|
38
46
|
.filter((record) => allowedScopes === null || allowedScopes.has(record.scope))
|
|
39
47
|
.filter((record) => repositoryApplies(record, activeRepository))
|
|
48
|
+
.filter((record) => runtimeApplies(record, activeRuntime))
|
|
49
|
+
.filter((record) => agentApplies(record, activeAgent))
|
|
40
50
|
.sort(compareRetrievalPriority);
|
|
41
51
|
const selected: MemoryRecord[] = [];
|
|
42
52
|
let spent = 0;
|
|
@@ -55,6 +65,8 @@ export function estimateMemoryTokens(record: MemoryRecord): number {
|
|
|
55
65
|
record.key,
|
|
56
66
|
record.lesson,
|
|
57
67
|
...(record.repository === undefined ? [] : [record.repository.kind, record.repository.key]),
|
|
68
|
+
...(record.runtime === undefined ? [] : [record.runtime.kind, record.runtime.key]),
|
|
69
|
+
...(record.agent === undefined ? [] : [record.agent.kind, record.agent.key]),
|
|
58
70
|
...record.evidenceRefs,
|
|
59
71
|
...record.appliesWhen,
|
|
60
72
|
...record.avoidWhen,
|
|
@@ -80,6 +92,21 @@ function cloneRecord(record: MemoryRecord): MemoryRecord {
|
|
|
80
92
|
if (record.regressions !== undefined) next.regressions = [...record.regressions];
|
|
81
93
|
if (record.rejectedAt !== undefined) next.rejectedAt = record.rejectedAt;
|
|
82
94
|
if (record.repository !== undefined) next.repository = { ...record.repository };
|
|
95
|
+
if (record.runtime !== undefined) next.runtime = { ...record.runtime };
|
|
96
|
+
if (record.agent !== undefined) next.agent = { ...record.agent };
|
|
97
|
+
if (record.provenance !== undefined) {
|
|
98
|
+
next.provenance = {
|
|
99
|
+
...record.provenance,
|
|
100
|
+
...(record.provenance.redaction === undefined
|
|
101
|
+
? {}
|
|
102
|
+
: {
|
|
103
|
+
redaction: {
|
|
104
|
+
...record.provenance.redaction,
|
|
105
|
+
sourceFields: [...record.provenance.redaction.sourceFields],
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
83
110
|
return next;
|
|
84
111
|
}
|
|
85
112
|
|
|
@@ -115,6 +142,36 @@ function repositoryApplies(record: MemoryRecord, activeRepository: MemoryReposit
|
|
|
115
142
|
return record.repository.kind === activeRepository.kind && record.repository.key === activeRepository.key;
|
|
116
143
|
}
|
|
117
144
|
|
|
145
|
+
function runtimeApplies(record: MemoryRecord, activeRuntime: MemoryRuntimeIdentity | null): boolean {
|
|
146
|
+
if (record.scope !== "runtime") return true;
|
|
147
|
+
if (activeRuntime === null || record.runtime === undefined) return false;
|
|
148
|
+
return record.runtime.kind === activeRuntime.kind && record.runtime.key === activeRuntime.key;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function agentApplies(record: MemoryRecord, activeAgent: MemoryAgentIdentity | null): boolean {
|
|
152
|
+
if (record.scope !== "agent") return true;
|
|
153
|
+
if (activeAgent === null || record.agent === undefined) return false;
|
|
154
|
+
return record.agent.kind === activeAgent.kind && record.agent.key === activeAgent.key;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function validActiveNamedIdentity<T extends "runtime" | "agent">(
|
|
158
|
+
identity: { kind: T; key: string } | null | undefined,
|
|
159
|
+
kind: T,
|
|
160
|
+
): { kind: T; key: string } | null {
|
|
161
|
+
if (
|
|
162
|
+
identity === null ||
|
|
163
|
+
identity === undefined ||
|
|
164
|
+
identity.kind !== kind ||
|
|
165
|
+
identity.key.length === 0 ||
|
|
166
|
+
identity.key.length > 256 ||
|
|
167
|
+
identity.key.trim() !== identity.key ||
|
|
168
|
+
/[\0\r\n\t ]/u.test(identity.key)
|
|
169
|
+
) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
return { kind, key: identity.key };
|
|
173
|
+
}
|
|
174
|
+
|
|
118
175
|
function isUsableAbsoluteRepositoryPath(value: string): boolean {
|
|
119
176
|
return value.length > 0 && !/[\0\r\n]/u.test(value) && isAbsolute(value);
|
|
120
177
|
}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createRedactionTally, redactSecretsText } from "../evidence/redact.js";
|
|
3
|
+
import { canonicalMemoryRepositoryIdentity } from "./operations.js";
|
|
4
|
+
import { loadMemoryRecords, upsertMemoryRecord } from "./store.js";
|
|
5
|
+
import type { TaskMemoryEntry, TaskMemoryRenderableClass } from "./task-bank.js";
|
|
6
|
+
import type {
|
|
7
|
+
MemoryAgentIdentity,
|
|
8
|
+
MemoryProposalResult,
|
|
9
|
+
MemoryRecord,
|
|
10
|
+
MemoryRepositoryIdentity,
|
|
11
|
+
MemoryRuntimeIdentity,
|
|
12
|
+
} from "./types.js";
|
|
13
|
+
import { validateMemoryRecord } from "./validate.js";
|
|
14
|
+
|
|
15
|
+
export const MEMORY_PROMOTION_SCOPES = ["repo", "global", "runtime", "agent"] as const;
|
|
16
|
+
export type MemoryPromotionScope = (typeof MEMORY_PROMOTION_SCOPES)[number];
|
|
17
|
+
|
|
18
|
+
export type MemoryScopeSelection =
|
|
19
|
+
| { scope: "repo"; repository: MemoryRepositoryIdentity }
|
|
20
|
+
| { scope: "global"; acknowledgeGlobal: true }
|
|
21
|
+
| { scope: "runtime"; runtime: MemoryRuntimeIdentity }
|
|
22
|
+
| { scope: "agent"; agent: MemoryAgentIdentity };
|
|
23
|
+
|
|
24
|
+
export interface MemoryPromotionSourceRedaction {
|
|
25
|
+
replacementCount: number;
|
|
26
|
+
sourceFields: ReadonlyArray<string>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface MemoryPromotionSource {
|
|
30
|
+
kind: "task-bank-entry" | "handoff-snapshot";
|
|
31
|
+
sessionId: string;
|
|
32
|
+
evidenceRefs: ReadonlyArray<string>;
|
|
33
|
+
entry: TaskMemoryEntry;
|
|
34
|
+
runtimeIds?: ReadonlyArray<string>;
|
|
35
|
+
agentIds?: ReadonlyArray<string>;
|
|
36
|
+
redaction?: MemoryPromotionSourceRedaction;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface ScopeSourceIdentities {
|
|
40
|
+
runtimeIds?: ReadonlyArray<string>;
|
|
41
|
+
agentIds?: ReadonlyArray<string>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Validate an operator-selected scope without inferring or widening it.
|
|
46
|
+
* Runtime and agent scopes must name identities carried by the source.
|
|
47
|
+
*/
|
|
48
|
+
export function validateMemoryScopeSelection(
|
|
49
|
+
selection: MemoryScopeSelection,
|
|
50
|
+
source: ScopeSourceIdentities,
|
|
51
|
+
): MemoryScopeSelection {
|
|
52
|
+
switch (selection.scope) {
|
|
53
|
+
case "repo": {
|
|
54
|
+
const repository = canonicalMemoryRepositoryIdentity(selection.repository.key);
|
|
55
|
+
if (
|
|
56
|
+
selection.repository.kind !== "canonical-path" ||
|
|
57
|
+
repository === null ||
|
|
58
|
+
repository.key !== selection.repository.key
|
|
59
|
+
) {
|
|
60
|
+
throw new Error("repo scope requires an existing canonical absolute repository identity");
|
|
61
|
+
}
|
|
62
|
+
return { scope: "repo", repository };
|
|
63
|
+
}
|
|
64
|
+
case "global":
|
|
65
|
+
if (selection.acknowledgeGlobal !== true) {
|
|
66
|
+
throw new Error("global scope requires a separate operator acknowledgement");
|
|
67
|
+
}
|
|
68
|
+
return selection;
|
|
69
|
+
case "runtime": {
|
|
70
|
+
const runtime = normalizeNamedIdentity(selection.runtime, "runtime");
|
|
71
|
+
if (!(source.runtimeIds ?? []).includes(runtime.key)) {
|
|
72
|
+
throw new Error(`runtime identity '${runtime.key}' does not match the promotion source`);
|
|
73
|
+
}
|
|
74
|
+
return { scope: "runtime", runtime };
|
|
75
|
+
}
|
|
76
|
+
case "agent": {
|
|
77
|
+
const agent = normalizeNamedIdentity(selection.agent, "agent");
|
|
78
|
+
if (!(source.agentIds ?? []).includes(agent.key)) {
|
|
79
|
+
throw new Error(`agent identity '${agent.key}' does not match the promotion source`);
|
|
80
|
+
}
|
|
81
|
+
return { scope: "agent", agent };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function memoryRuntimeIdentity(key: string): MemoryRuntimeIdentity {
|
|
87
|
+
return normalizeNamedIdentity({ kind: "runtime", key }, "runtime");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function memoryAgentIdentity(key: string): MemoryAgentIdentity {
|
|
91
|
+
return normalizeNamedIdentity({ kind: "agent", key }, "agent");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Create one reviewable proposal from a selected non-private task-bank entry. */
|
|
95
|
+
export async function proposeMemoryPromotion(
|
|
96
|
+
dataDir: string,
|
|
97
|
+
source: MemoryPromotionSource,
|
|
98
|
+
selection: MemoryScopeSelection,
|
|
99
|
+
now: Date = new Date(),
|
|
100
|
+
): Promise<MemoryProposalResult> {
|
|
101
|
+
validatePromotionSource(source);
|
|
102
|
+
const validatedScope = validateMemoryScopeSelection(selection, {
|
|
103
|
+
runtimeIds: source.runtimeIds ?? [],
|
|
104
|
+
agentIds: source.agentIds ?? [],
|
|
105
|
+
});
|
|
106
|
+
const record = memoryRecordFromPromotion(source, validatedScope, now);
|
|
107
|
+
const existing = (await loadMemoryRecords(dataDir)).find((candidate) => candidate.id === record.id);
|
|
108
|
+
if (existing !== undefined) return { record: existing, created: false };
|
|
109
|
+
await upsertMemoryRecord(dataDir, record);
|
|
110
|
+
return { record, created: true };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function memoryRecordFromPromotion(
|
|
114
|
+
source: MemoryPromotionSource,
|
|
115
|
+
selection: MemoryScopeSelection,
|
|
116
|
+
now: Date = new Date(),
|
|
117
|
+
): MemoryRecord {
|
|
118
|
+
validatePromotionSource(source);
|
|
119
|
+
const entryKind = source.entry.kind;
|
|
120
|
+
if (entryKind === "status") throw new Error("private task-memory status cannot be promoted");
|
|
121
|
+
const validatedScope = validateMemoryScopeSelection(selection, {
|
|
122
|
+
runtimeIds: source.runtimeIds ?? [],
|
|
123
|
+
agentIds: source.agentIds ?? [],
|
|
124
|
+
});
|
|
125
|
+
const tally = createRedactionTally();
|
|
126
|
+
const lesson = redactPromotionText(source.entry.content, tally).replace(/\s+/gu, " ").trim();
|
|
127
|
+
const sourceFields = new Set(source.redaction?.sourceFields ?? []);
|
|
128
|
+
if (lesson !== source.entry.content) sourceFields.add("content");
|
|
129
|
+
const replacementCount = (source.redaction?.replacementCount ?? 0) + tally.count;
|
|
130
|
+
const scopeKey = memoryScopeIdentityKey(validatedScope);
|
|
131
|
+
const record: MemoryRecord = {
|
|
132
|
+
id: promotedMemoryId({
|
|
133
|
+
sourceKind: source.kind,
|
|
134
|
+
sessionId: source.sessionId,
|
|
135
|
+
entryId: source.entry.id,
|
|
136
|
+
entryKind,
|
|
137
|
+
evidenceRefs: uniqueStrings(source.evidenceRefs),
|
|
138
|
+
lesson,
|
|
139
|
+
scopeKey,
|
|
140
|
+
}),
|
|
141
|
+
scope: validatedScope.scope,
|
|
142
|
+
key: `promotion:${source.kind}:${source.sessionId}:${source.entry.id}`,
|
|
143
|
+
lesson,
|
|
144
|
+
evidenceRefs: uniqueStrings(source.evidenceRefs),
|
|
145
|
+
appliesWhen: scopeApplicability(validatedScope),
|
|
146
|
+
avoidWhen: [],
|
|
147
|
+
confidence: 0.6,
|
|
148
|
+
createdAt: now.toISOString(),
|
|
149
|
+
approved: false,
|
|
150
|
+
provenance: {
|
|
151
|
+
sourceKind: source.kind,
|
|
152
|
+
sourceSessionId: source.sessionId,
|
|
153
|
+
sourceEntryId: source.entry.id,
|
|
154
|
+
sourceEntryKind: entryKind,
|
|
155
|
+
sourceEntryCreatedAt: source.entry.createdAt,
|
|
156
|
+
sourceEntryLastTouchedAt: source.entry.lastTouchedAt,
|
|
157
|
+
redaction: {
|
|
158
|
+
appliedBeforePersistence: true,
|
|
159
|
+
replacementCount,
|
|
160
|
+
sourceFields: [...sourceFields].sort(compareStrings),
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
applyScopeIdentity(record, validatedScope);
|
|
165
|
+
const validated = validateMemoryRecord(record);
|
|
166
|
+
if (!validated.valid) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
`promoted memory record invalid: ${validated.issues.map((issue) => `${issue.path}: ${issue.message}`).join("; ")}`,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
return validated.record;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function applyScopeIdentity(record: MemoryRecord, selection: MemoryScopeSelection): void {
|
|
175
|
+
if (selection.scope === "repo") record.repository = { ...selection.repository };
|
|
176
|
+
if (selection.scope === "runtime") record.runtime = { ...selection.runtime };
|
|
177
|
+
if (selection.scope === "agent") record.agent = { ...selection.agent };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function memoryScopeIdentityKey(selection: MemoryScopeSelection): string {
|
|
181
|
+
switch (selection.scope) {
|
|
182
|
+
case "repo":
|
|
183
|
+
return `repo:${selection.repository.kind}:${selection.repository.key}`;
|
|
184
|
+
case "global":
|
|
185
|
+
return "global:acknowledged";
|
|
186
|
+
case "runtime":
|
|
187
|
+
return `runtime:${selection.runtime.key}`;
|
|
188
|
+
case "agent":
|
|
189
|
+
return `agent:${selection.agent.key}`;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function validatePromotionSource(source: MemoryPromotionSource): void {
|
|
194
|
+
if (!validSourceValue(source.sessionId)) throw new Error("promotion requires a valid source session id");
|
|
195
|
+
if (source.evidenceRefs.length === 0 || source.evidenceRefs.some((value) => !validSourceValue(value))) {
|
|
196
|
+
throw new Error("promotion requires at least one valid source evidence ref");
|
|
197
|
+
}
|
|
198
|
+
if (source.entry.kind === "status") throw new Error("private task-memory status cannot be promoted");
|
|
199
|
+
if (source.entry.kind !== "knowledge" && source.entry.kind !== "procedural") {
|
|
200
|
+
throw new Error("promotion requires a knowledge or procedural task-memory entry");
|
|
201
|
+
}
|
|
202
|
+
if (!validSourceValue(source.entry.id) || source.entry.content.trim().length === 0) {
|
|
203
|
+
throw new Error("promotion requires a valid task-memory entry");
|
|
204
|
+
}
|
|
205
|
+
for (const runtimeId of source.runtimeIds ?? []) memoryRuntimeIdentity(runtimeId);
|
|
206
|
+
for (const agentId of source.agentIds ?? []) memoryAgentIdentity(agentId);
|
|
207
|
+
if (source.redaction !== undefined) {
|
|
208
|
+
if (!Number.isInteger(source.redaction.replacementCount) || source.redaction.replacementCount < 0) {
|
|
209
|
+
throw new Error("promotion source redaction count must be a non-negative integer");
|
|
210
|
+
}
|
|
211
|
+
if (source.redaction.sourceFields.some((field) => !validSourceValue(field))) {
|
|
212
|
+
throw new Error("promotion source redaction fields must be valid non-empty strings");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function normalizeNamedIdentity<T extends "runtime" | "agent">(
|
|
218
|
+
identity: { kind: T; key: string },
|
|
219
|
+
kind: T,
|
|
220
|
+
): { kind: T; key: string } {
|
|
221
|
+
if (identity.kind !== kind || !validNamedIdentityKey(identity.key)) {
|
|
222
|
+
throw new Error(`${kind} scope requires a valid ${kind} identity`);
|
|
223
|
+
}
|
|
224
|
+
return { kind, key: identity.key };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function validNamedIdentityKey(value: string): boolean {
|
|
228
|
+
return value.length > 0 && value.length <= 256 && value.trim() === value && !/[\0\r\n\t ]/u.test(value);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function validSourceValue(value: string): boolean {
|
|
232
|
+
return value.length > 0 && value.length <= 1_024 && value.trim() === value && !/[\0\r\n]/u.test(value);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function scopeApplicability(selection: MemoryScopeSelection): string[] {
|
|
236
|
+
switch (selection.scope) {
|
|
237
|
+
case "repo":
|
|
238
|
+
return [`repository:${selection.repository.kind}:${selection.repository.key}`];
|
|
239
|
+
case "global":
|
|
240
|
+
return [];
|
|
241
|
+
case "runtime":
|
|
242
|
+
return [`runtime:${selection.runtime.key}`];
|
|
243
|
+
case "agent":
|
|
244
|
+
return [`agent:${selection.agent.key}`];
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function promotedMemoryId(value: {
|
|
249
|
+
sourceKind: MemoryPromotionSource["kind"];
|
|
250
|
+
sessionId: string;
|
|
251
|
+
entryId: string;
|
|
252
|
+
entryKind: TaskMemoryRenderableClass;
|
|
253
|
+
evidenceRefs: string[];
|
|
254
|
+
lesson: string;
|
|
255
|
+
scopeKey: string;
|
|
256
|
+
}): string {
|
|
257
|
+
const digest = createHash("sha256").update(JSON.stringify(value), "utf8").digest("hex").slice(0, 16);
|
|
258
|
+
return `mem-${digest}`;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function uniqueStrings(values: ReadonlyArray<string>): string[] {
|
|
262
|
+
return [...new Set(values)].sort(compareStrings);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function redactPromotionText(text: string, tally: ReturnType<typeof createRedactionTally>): string {
|
|
266
|
+
const markers: string[] = [];
|
|
267
|
+
const masked = text.replace(/\[redacted:[a-z-]+\]/gu, (marker) => {
|
|
268
|
+
const token = `\uE000${String.fromCharCode(0xe100 + markers.length)}`;
|
|
269
|
+
markers.push(marker);
|
|
270
|
+
return token;
|
|
271
|
+
});
|
|
272
|
+
let redacted = redactSecretsText(masked, tally);
|
|
273
|
+
for (let index = 0; index < markers.length; index += 1) {
|
|
274
|
+
redacted = redacted.replaceAll(`\uE000${String.fromCharCode(0xe100 + index)}`, markers[index] ?? "");
|
|
275
|
+
}
|
|
276
|
+
return redacted;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function compareStrings(left: string, right: string): number {
|
|
280
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
281
|
+
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { estimateMemoryTokens, selectApprovedMemory } from "./operations.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
MemoryAgentIdentity,
|
|
4
|
+
MemoryRecord,
|
|
5
|
+
MemoryRepositoryIdentity,
|
|
6
|
+
MemoryRuntimeIdentity,
|
|
7
|
+
MemoryScope,
|
|
8
|
+
} from "./types.js";
|
|
3
9
|
|
|
4
10
|
export const MEMORY_PROMPT_DEFAULT_TOKEN_BUDGET = 400;
|
|
5
11
|
export const MEMORY_PROMPT_DEFAULT_MAX_ITEMS = 5;
|
|
@@ -20,6 +26,10 @@ export interface MemoryPromptOptions {
|
|
|
20
26
|
maxItems?: number;
|
|
21
27
|
/** Missing or unknown identity leaves global memory eligible but excludes repo memory. */
|
|
22
28
|
activeRepository?: MemoryRepositoryIdentity | null;
|
|
29
|
+
/** Missing or unknown identity excludes runtime-scoped memory. */
|
|
30
|
+
activeRuntime?: MemoryRuntimeIdentity | null;
|
|
31
|
+
/** Missing or unknown identity excludes agent-scoped memory. */
|
|
32
|
+
activeAgent?: MemoryAgentIdentity | null;
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
/**
|
|
@@ -40,6 +50,8 @@ export function selectMemoryForPrompt(
|
|
|
40
50
|
scopes,
|
|
41
51
|
tokenBudget,
|
|
42
52
|
activeRepository: options.activeRepository ?? null,
|
|
53
|
+
activeRuntime: options.activeRuntime ?? null,
|
|
54
|
+
activeAgent: options.activeAgent ?? null,
|
|
43
55
|
});
|
|
44
56
|
return selected.slice(0, maxItems);
|
|
45
57
|
}
|
|
@@ -67,11 +79,19 @@ export function renderMemoryPromptSection(records: ReadonlyArray<MemoryRecord>):
|
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
function renderApplicability(record: MemoryRecord): string {
|
|
70
|
-
if (record.scope
|
|
71
|
-
|
|
72
|
-
|
|
82
|
+
if (record.scope === "repo") {
|
|
83
|
+
if (record.repository !== undefined) {
|
|
84
|
+
return `scope=repo, repository=${JSON.stringify(`${record.repository.kind}:${record.repository.key}`)}`;
|
|
85
|
+
}
|
|
86
|
+
return "scope=repo, repository=unknown";
|
|
73
87
|
}
|
|
74
|
-
|
|
88
|
+
if (record.scope === "runtime") {
|
|
89
|
+
return `scope=runtime, runtime=${JSON.stringify(record.runtime?.key ?? "unknown")}`;
|
|
90
|
+
}
|
|
91
|
+
if (record.scope === "agent") {
|
|
92
|
+
return `scope=agent, agent=${JSON.stringify(record.agent?.key ?? "unknown")}`;
|
|
93
|
+
}
|
|
94
|
+
return `scope=${record.scope}`;
|
|
75
95
|
}
|
|
76
96
|
|
|
77
97
|
/** Convenience for callers that want a single end-to-end build step. */
|