@iowarp/clio-coder 0.3.0 → 0.3.1
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 +33 -0
- package/README.md +50 -53
- package/dist/acp-FPR54DGL.js +138 -0
- package/dist/{agents-Q4MYPMUW.js → agents-OGPIHPJH.js} +33 -25
- package/dist/assets/codewiki.json +1 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/LICENSE +21 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/cgmanifest.json +16 -0
- package/dist/assets/grammars/notices/tree-sitter-wasms/LICENSE +24 -0
- package/dist/assets/grammars/tree-sitter-c-sharp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-c.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-go.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-java.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-python.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-ruby.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter.wasm +0 -0
- package/dist/{auth-O6HYIJ6J.js → auth-IC3K6NIZ.js} +22 -15
- package/dist/{chunk-KKKPTZLM.js → chunk-2STGEDFV.js} +8 -1
- package/dist/chunk-3I7MS7N2.js +40 -0
- package/dist/chunk-3R73A4XB.js +69 -0
- package/dist/{chunk-26BZQOAD.js → chunk-474KN5II.js} +86 -115
- package/dist/{chunk-NI4DEJMC.js → chunk-4QKXUHSR.js} +26 -3
- package/dist/{chunk-X3BR7HWV.js → chunk-5WIGXA4T.js} +7 -1
- package/dist/{chunk-TFSSEXL6.js → chunk-673JJUWJ.js} +14 -4
- package/dist/{chunk-GNGDQYDU.js → chunk-7SS2CTV2.js} +27922 -1249
- package/dist/{chunk-7RBKDI66.js → chunk-ASND7OZK.js} +104 -12
- package/dist/{chunk-X3NE4WVW.js → chunk-BNAZZHFG.js} +7 -1
- package/dist/{chunk-RQDWMVRB.js → chunk-BSU2YIWB.js} +9 -3
- package/dist/{chunk-CLJ5HLUD.js → chunk-C4PTHK7P.js} +24 -5
- package/dist/{chunk-QV47YRF4.js → chunk-CGKSTWHD.js} +7 -1
- package/dist/{chunk-BYEU76JP.js → chunk-DKGKUHFA.js} +34 -9
- package/dist/chunk-EYOKLTMF.js +170 -0
- package/dist/{chunk-PS4PFJQP.js → chunk-FCIH3BIZ.js} +15258 -14130
- package/dist/{chunk-2J63S4SF.js → chunk-FST4FYJB.js} +82 -14
- package/dist/{chunk-3DANZDGR.js → chunk-G34LV2PF.js} +34 -9
- package/dist/{chunk-BBUH4VAA.js → chunk-GAEBEQVI.js} +34 -21
- package/dist/chunk-GB6QRBXN.js +8543 -0
- package/dist/chunk-GEP36Y4X.js +12796 -0
- package/dist/{chunk-TKHQ4DGZ.js → chunk-H6F6BYOH.js} +496 -121
- package/dist/{chunk-UGYAX5YI.js → chunk-HQQID6OA.js} +10 -5
- package/dist/chunk-IHXBNWMM.js +137 -0
- package/dist/{chunk-ME6DNWIU.js → chunk-IS3ONKU3.js} +7 -1
- package/dist/{chunk-DXQNI4PC.js → chunk-IWHMRKLL.js} +8 -1
- package/dist/chunk-K2ITRMHZ.js +642 -0
- package/dist/{chunk-KBR4MZZR.js → chunk-K5XEMXTI.js} +7 -1
- package/dist/{chunk-AMFR5YA3.js → chunk-KKNLWXI6.js} +24 -10
- package/dist/{chunk-JWHCJDCI.js → chunk-KY56HMHH.js} +145 -61
- package/dist/{chunk-E3NYWENM.js → chunk-LU4TK2PR.js} +52 -7
- package/dist/{chunk-UWIJNAOB.js → chunk-M5T5VO65.js} +109 -42
- package/dist/{chunk-JPOWPFCU.js → chunk-MAR7Y6HW.js} +38 -16
- package/dist/chunk-N6F52NLF.js +6951 -0
- package/dist/{chunk-UHTSULZS.js → chunk-NMOX6HFD.js} +20 -7
- package/dist/{chunk-WD6AJM35.js → chunk-OLBBMFRD.js} +30 -13
- package/dist/{chunk-VOO7NYPP.js → chunk-PFEFKVGL.js} +22 -6
- package/dist/{chunk-6CWDTGUC.js → chunk-PIUMUEMV.js} +7 -1
- package/dist/chunk-PV4JUBVJ.js +462 -0
- package/dist/{chunk-527KG6XR.js → chunk-Q3RUPKEJ.js} +22 -4
- package/dist/{chunk-D5YD55AR.js → chunk-Q5WJOSJ7.js} +11 -1
- package/dist/{chunk-5N2FG33Q.js → chunk-R346GLFC.js} +7 -1
- package/dist/{chunk-4UQA7NCT.js → chunk-R5KLMSBV.js} +7 -2
- package/dist/{chunk-PIDUD6M2.js → chunk-RDLVBZEO.js} +11 -6
- package/dist/{chunk-O4EJEDHO.js → chunk-RPTR2H26.js} +40 -31
- package/dist/{chunk-HBU5MTAM.js → chunk-SVNXH4L2.js} +7 -1
- package/dist/{chunk-XNISANGE.js → chunk-TEKV33Q5.js} +122 -57
- package/dist/chunk-TXOTCRLG.js +15 -0
- package/dist/{chunk-VPAWTYLY.js → chunk-WEPFGWHJ.js} +7 -1
- package/dist/{chunk-HMYNFFY4.js → chunk-XPLRXC72.js} +7 -2
- package/dist/{chunk-UU3R62TT.js → chunk-XYWBQRDM.js} +13 -4
- package/dist/{chunk-7BHLZB3A.js → chunk-ZPY3JZ5E.js} +32 -10
- package/dist/cli/index.js +39 -33
- package/dist/clio-BZVGEUFJ.js +58 -0
- package/dist/{components-JVHMUBEB.js → components-DMAOEKFB.js} +26 -9
- package/dist/{config-ZFCDBMDC.js → config-IRUQ7SE4.js} +42 -31
- package/dist/configure-S7S6F6CL.js +32 -0
- package/dist/{context-CDXTP2MP.js → context-3KWFLHJG.js} +17 -11
- package/dist/{context-E3KIFVXI.js → context-5RADCKTR.js} +33 -28
- package/dist/{context-clear-3F4PLXOS.js → context-clear-7TSNPAAI.js} +36 -28
- package/dist/{context-index-Q7YSYTR3.js → context-index-W4RLWOQH.js} +10 -4
- package/dist/{docs-YIETIWZI.js → docs-5AWSPS37.js} +16 -10
- package/dist/doctor-UC5NAJYQ.js +77 -0
- package/dist/{eval-B3KZZESM.js → eval-U6TJHRLX.js} +77 -24
- package/dist/{evidence-V67CHM35.js → evidence-YEGUW4L3.js} +34 -26
- package/dist/{evolve-YDZSUQYA.js → evolve-TXARCTPG.js} +39 -26
- package/dist/{extensions-SRG7XCAH.js → extensions-OZFJ3A3G.js} +13 -7
- package/dist/{fleet-CA2CRTVG.js → fleet-6G3DHNYE.js} +45 -37
- package/dist/fleet-preflight-DSNT37JK.js +23 -0
- package/dist/{init-2OZDJE2D.js → init-KZ5QTF6M.js} +42 -34
- package/dist/{memory-3PIQQAKX.js → memory-73ESV5YC.js} +35 -27
- package/dist/{models-DY35XI7Y.js → models-A4PVNWJK.js} +34 -23
- package/dist/{paths-5OMXW7Z4.js → paths-C4H6IV77.js} +12 -6
- package/dist/preload-6WVMHX3A.js +13 -0
- package/dist/{reset-PIFYNOS3.js → reset-BGW6OGMV.js} +17 -11
- package/dist/{run-3VSPP24F.js → run-YTPEYQOH.js} +60 -48
- package/dist/{share-D36RQCXM.js → share-YIFFV4NQ.js} +16 -10
- package/dist/{skills-F2MRLELY.js → skills-2V6RA3OQ.js} +18 -11
- package/dist/{skills-eval-E2ZTW4PL.js → skills-eval-S2TVJO4F.js} +45 -36
- package/dist/{targets-DZMEZAH4.js → targets-TYXLPB23.js} +61 -59
- package/dist/{trace-7NYCUI2J.js → trace-GGOJ6Q6Z.js} +9 -3
- package/dist/{uninstall-AD3JWHBB.js → uninstall-LLLT4F4W.js} +14 -8
- package/dist/{upgrade-WYYBKGDY.js → upgrade-33G2LMM5.js} +45 -23
- package/dist/{usage-ULIDAGFF.js → usage-ZAFSXKKG.js} +35 -27
- package/dist/version-KGEG7EPO.js +21 -0
- package/dist/{wiki-generate-PKFIX6OB.js → wiki-generate-NUQCVOQ3.js} +55 -45
- package/dist/worker/entry.js +101 -43
- package/docs/README.md +12 -9
- package/docs/acp.md +28 -5
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +23 -2
- package/docs/artifact-placement.md +101 -0
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +4 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +125 -41
- package/docs/configuration-and-targets.md +88 -18
- package/docs/context-engine.md +6 -2
- package/docs/development-pipeline.md +77 -0
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +3 -3
- package/docs/environment-variables.md +2 -1
- package/docs/eval-runner.md +3 -3
- package/docs/evals-internal.md +2 -2
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +1 -1
- package/docs/exit-codes-and-output.md +1 -1
- package/docs/extensions-and-sharing.md +18 -11
- package/docs/fleet-demo-runbook.md +22 -23
- package/docs/fleet-dispatch.md +111 -12
- package/docs/glossary.md +107 -15
- package/docs/html/agents_blueprint.html +3 -3
- package/docs/html/alcf_blueprint.html +3 -3
- package/docs/html/architecture_blueprint.html +3 -3
- package/docs/html/commands_blueprint.html +187 -42
- package/docs/html/configuration_blueprint.html +7 -7
- package/docs/html/context_blueprint.html +3 -3
- package/docs/html/documentation_blueprint.html +1 -1
- package/docs/html/environment_blueprint.html +3 -3
- package/docs/html/eval_blueprint.html +4 -4
- package/docs/html/evals_internal_blueprint.html +3 -3
- package/docs/html/evolution_blueprint.html +3 -3
- package/docs/html/extensions_blueprint.html +3 -3
- package/docs/html/fleet_dispatch_blueprint.html +8 -8
- package/docs/html/index.html +5 -5
- package/docs/html/lifecycle_blueprint.html +4 -4
- package/docs/html/memory_blueprint.html +3 -3
- package/docs/html/middleware_blueprint.html +3 -3
- package/docs/html/models_blueprint.html +2 -2
- package/docs/html/observability_blueprint.html +2 -2
- package/docs/html/provider_adapter_blueprint.html +3 -3
- package/docs/html/safety_blueprint.html +3 -3
- package/docs/html/skills_blueprint.html +2 -2
- package/docs/html/soak_blueprint.html +3 -3
- package/docs/html/tool_usage_blueprint.html +4 -4
- package/docs/html/tools_blueprint.html +2 -2
- package/docs/html/trace_blueprint.html +3 -3
- package/docs/html/tui_design_blueprint.html +100 -40
- package/docs/html/validation_blueprint.html +1 -1
- package/docs/html/worker_dispatch_blueprint.html +3 -3
- package/docs/installation-and-lifecycle.md +62 -11
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +2 -2
- package/docs/observability.md +3 -3
- package/docs/proactive-memory.md +12 -12
- package/docs/prompt-envelope-and-tools.md +2 -2
- package/docs/provider-adapter-cookbook.md +1 -1
- package/docs/release-cut-checklist.md +4 -0
- package/docs/safety-model.md +21 -5
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +2 -2
- package/docs/skills-marketplace.md +1 -1
- package/docs/time-conventions.md +101 -0
- package/docs/tool-usage.md +5 -4
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/tui-design.md +83 -27
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +16 -16
- package/skills/README.md +5 -6
- package/skills/git/file-ticket/SKILL.md +107 -0
- package/skills/git/file-ticket/evals.md +54 -0
- package/skills/git/fix-issue/SKILL.md +106 -0
- package/skills/git/fix-issue/evals.md +71 -0
- package/skills/git/ship/SKILL.md +92 -0
- package/skills/git/ship/evals.md +72 -0
- package/skills/skill-marketplace.json +12 -20
- package/src/cli/acp.ts +88 -0
- package/src/cli/agents.ts +60 -0
- package/src/cli/args.ts +280 -0
- package/src/cli/argv.ts +170 -0
- package/src/cli/ask.ts +34 -0
- package/src/cli/auth.ts +468 -0
- package/src/cli/bootstrap-generate.ts +498 -0
- package/src/cli/clio.ts +34 -0
- package/src/cli/components.ts +195 -0
- package/src/cli/config-inspect.ts +330 -0
- package/src/cli/config.ts +72 -0
- package/src/cli/configure-interop.ts +67 -0
- package/src/cli/configure-layout.ts +172 -0
- package/src/cli/configure.ts +1487 -0
- package/src/cli/context-clear.ts +76 -0
- package/src/cli/context-index.ts +102 -0
- package/src/cli/context.ts +316 -0
- package/src/cli/default-target.ts +63 -0
- package/src/cli/docs.ts +340 -0
- package/src/cli/doctor.ts +54 -0
- package/src/cli/eval.ts +315 -0
- package/src/cli/evidence.ts +222 -0
- package/src/cli/evolve.ts +219 -0
- package/src/cli/extensions.ts +205 -0
- package/src/cli/fleet.ts +827 -0
- package/src/cli/index.ts +309 -0
- package/src/cli/init.ts +219 -0
- package/src/cli/initial-message.ts +47 -0
- package/src/cli/internal-dispatch.ts +55 -0
- package/src/cli/memory.ts +180 -0
- package/src/cli/models.ts +257 -0
- package/src/cli/modes/json-stream.ts +85 -0
- package/src/cli/modes/jsonl.ts +9 -0
- package/src/cli/modes/print.ts +589 -0
- package/src/cli/oauth-manual-input.ts +72 -0
- package/src/cli/oauth-select.ts +36 -0
- package/src/cli/output-guard.ts +48 -0
- package/src/cli/paths.ts +44 -0
- package/src/cli/provider-target.ts +113 -0
- package/src/cli/removal.ts +72 -0
- package/src/cli/reset.ts +253 -0
- package/src/cli/run.ts +497 -0
- package/src/cli/share.ts +243 -0
- package/src/cli/shared.ts +60 -0
- package/src/cli/skills-eval.ts +1225 -0
- package/src/cli/skills.ts +470 -0
- package/src/cli/steer-channel.ts +86 -0
- package/src/cli/targets.ts +1150 -0
- package/src/cli/text-layout.ts +102 -0
- package/src/cli/trace.ts +274 -0
- package/src/cli/uninstall.ts +405 -0
- package/src/cli/upgrade.ts +270 -0
- package/src/cli/usage.ts +869 -0
- package/src/cli/validate-model.ts +28 -0
- package/src/cli/version.ts +7 -0
- package/src/cli/wiki-generate.ts +509 -0
- package/src/core/artifact-paths.ts +43 -0
- package/src/core/bash-exec.ts +242 -0
- package/src/core/boot-trace.ts +37 -0
- package/src/core/bus-events.ts +728 -0
- package/src/core/bus-trace.ts +53 -0
- package/src/core/c-header-language.ts +265 -0
- package/src/core/clio-repo.ts +78 -0
- package/src/core/config.ts +1593 -0
- package/src/core/context-floor.ts +33 -0
- package/src/core/defaults.ts +625 -0
- package/src/core/domain-loader.ts +170 -0
- package/src/core/event-bus.ts +94 -0
- package/src/core/file-references.ts +282 -0
- package/src/core/guardrails.ts +185 -0
- package/src/core/headless-permission.ts +21 -0
- package/src/core/init.ts +223 -0
- package/src/core/json-payload.ts +58 -0
- package/src/core/package-root.ts +54 -0
- package/src/core/path-canonical.ts +37 -0
- package/src/core/process-identity.ts +41 -0
- package/src/core/recent-models.ts +91 -0
- package/src/core/release.ts +2 -0
- package/src/core/residency-protection.ts +56 -0
- package/src/core/resolve-config-value.ts +88 -0
- package/src/core/response-schema.ts +279 -0
- package/src/core/run-overrides.ts +77 -0
- package/src/core/safe-exec.ts +193 -0
- package/src/core/safe-id.ts +37 -0
- package/src/core/safe-resource-write.ts +162 -0
- package/src/core/session-routing.ts +339 -0
- package/src/core/settings-layers.ts +220 -0
- package/src/core/shared-bus.ts +8 -0
- package/src/core/shell-quote.ts +26 -0
- package/src/core/skill-activation.ts +190 -0
- package/src/core/startup-timer.ts +37 -0
- package/src/core/state-file-lock.ts +207 -0
- package/src/core/termination.ts +202 -0
- package/src/core/timers.ts +38 -0
- package/src/core/tool-names.ts +65 -0
- package/src/core/verification-scripts.ts +13 -0
- package/src/core/workspace-files.ts +492 -0
- package/src/core/xdg.ts +177 -0
- package/src/domains/agents/builtins/architect.md +4 -4
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +1 -1
- package/src/domains/agents/builtins/documenter.md +1 -1
- package/src/domains/agents/builtins/git-master.md +3 -3
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +1 -1
- package/src/domains/agents/builtins/verifier.md +1 -1
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/catalog.ts +172 -0
- package/src/domains/agents/contract.ts +16 -0
- package/src/domains/agents/extension.ts +110 -0
- package/src/domains/agents/fleet-commands.ts +154 -0
- package/src/domains/agents/fleet-contract.ts +797 -0
- package/src/domains/agents/frontmatter.ts +40 -0
- package/src/domains/agents/index.ts +102 -0
- package/src/domains/agents/manifest.ts +6 -0
- package/src/domains/agents/recipe-schema.ts +202 -0
- package/src/domains/agents/recipe.ts +125 -0
- package/src/domains/agents/registry.ts +111 -0
- package/src/domains/agents/result-contract.ts +1265 -0
- package/src/domains/agents/spec.ts +371 -0
- package/src/domains/agents/write-boundary.ts +109 -0
- package/src/domains/components/diff.ts +99 -0
- package/src/domains/components/hash.ts +21 -0
- package/src/domains/components/index.ts +3 -0
- package/src/domains/components/scan.ts +304 -0
- package/src/domains/components/snapshot.ts +108 -0
- package/src/domains/components/types.ts +82 -0
- package/src/domains/config/agent-namespace.ts +13 -0
- package/src/domains/config/classify.ts +94 -0
- package/src/domains/config/contract.ts +22 -0
- package/src/domains/config/extension.ts +136 -0
- package/src/domains/config/index.ts +13 -0
- package/src/domains/config/keybindings.ts +164 -0
- package/src/domains/config/manifest.ts +6 -0
- package/src/domains/config/watcher.ts +41 -0
- package/src/domains/context/adoption.ts +880 -0
- package/src/domains/context/bootstrap-prompt.ts +273 -0
- package/src/domains/context/bootstrap.ts +1409 -0
- package/src/domains/context/clear.ts +86 -0
- package/src/domains/context/clio-md.ts +327 -0
- package/src/domains/context/codewiki/cmake.ts +356 -0
- package/src/domains/context/codewiki/cooperative.ts +46 -0
- package/src/domains/context/codewiki/digest.ts +135 -0
- package/src/domains/context/codewiki/grammar-assets.ts +33 -0
- package/src/domains/context/codewiki/indexer.ts +1614 -0
- package/src/domains/context/codewiki/tree-sitter.ts +771 -0
- package/src/domains/context/contract.ts +62 -0
- package/src/domains/context/excluded-dirs.ts +1 -0
- package/src/domains/context/extension.ts +407 -0
- package/src/domains/context/fingerprint.ts +196 -0
- package/src/domains/context/index.ts +164 -0
- package/src/domains/context/init-options.ts +69 -0
- package/src/domains/context/manifest.ts +6 -0
- package/src/domains/context/operator-profile.ts +157 -0
- package/src/domains/context/project-metadata.ts +510 -0
- package/src/domains/context/project-rules.ts +227 -0
- package/src/domains/context/prompt-context.ts +62 -0
- package/src/domains/context/refresh.ts +170 -0
- package/src/domains/context/sibling-files.ts +10 -0
- package/src/domains/context/state.ts +237 -0
- package/src/domains/context/wiki/assemble.ts +303 -0
- package/src/domains/context/wiki/frontmatter.ts +210 -0
- package/src/domains/context/wiki/generate.ts +590 -0
- package/src/domains/context/wiki/layout.ts +111 -0
- package/src/domains/context/wiki/meta.ts +221 -0
- package/src/domains/context/wiki/plan-store.ts +217 -0
- package/src/domains/context/wiki/plan.ts +250 -0
- package/src/domains/context/wiki/prompts.ts +270 -0
- package/src/domains/context/wiki/staleness.ts +198 -0
- package/src/domains/dispatch/active-route-planner.ts +168 -0
- package/src/domains/dispatch/admission-queue.ts +150 -0
- package/src/domains/dispatch/admission.ts +334 -0
- package/src/domains/dispatch/agent-candidates.ts +307 -0
- package/src/domains/dispatch/agent-ledger-hub.ts +71 -0
- package/src/domains/dispatch/agent-ledger-store.ts +257 -0
- package/src/domains/dispatch/agent-ledger.ts +212 -0
- package/src/domains/dispatch/agent-plan-adapter.ts +85 -0
- package/src/domains/dispatch/assignment-events.ts +132 -0
- package/src/domains/dispatch/assignment-reconcile.ts +76 -0
- package/src/domains/dispatch/assignment-store.ts +162 -0
- package/src/domains/dispatch/assignment.ts +278 -0
- package/src/domains/dispatch/backoff.ts +59 -0
- package/src/domains/dispatch/batch-store.ts +134 -0
- package/src/domains/dispatch/batch-tracker.ts +66 -0
- package/src/domains/dispatch/capability-match.ts +155 -0
- package/src/domains/dispatch/capacity-lease.ts +413 -0
- package/src/domains/dispatch/code-step-store.ts +52 -0
- package/src/domains/dispatch/code-step.ts +368 -0
- package/src/domains/dispatch/contract.ts +278 -0
- package/src/domains/dispatch/dedup.ts +133 -0
- package/src/domains/dispatch/event-pump.ts +251 -0
- package/src/domains/dispatch/execution-handoff.ts +29 -0
- package/src/domains/dispatch/execution-plan.ts +328 -0
- package/src/domains/dispatch/execution-role.ts +277 -0
- package/src/domains/dispatch/execution-scheduler.ts +583 -0
- package/src/domains/dispatch/extension.ts +5869 -0
- package/src/domains/dispatch/failure-classification.ts +141 -0
- package/src/domains/dispatch/fleet-plan.ts +225 -0
- package/src/domains/dispatch/fleet-preflight.ts +394 -0
- package/src/domains/dispatch/gate-decisions.ts +1040 -0
- package/src/domains/dispatch/gate-role-prompts.ts +58 -0
- package/src/domains/dispatch/heartbeat.ts +27 -0
- package/src/domains/dispatch/index.ts +137 -0
- package/src/domains/dispatch/joint-route-adapter.ts +114 -0
- package/src/domains/dispatch/joint-route-resolver.ts +283 -0
- package/src/domains/dispatch/manifest.ts +6 -0
- package/src/domains/dispatch/orphan-recovery.ts +224 -0
- package/src/domains/dispatch/outcome.ts +109 -0
- package/src/domains/dispatch/phase-timing.ts +47 -0
- package/src/domains/dispatch/placement.ts +202 -0
- package/src/domains/dispatch/receipt-findings.ts +255 -0
- package/src/domains/dispatch/receipt-integrity.ts +378 -0
- package/src/domains/dispatch/recovery-candidates.ts +74 -0
- package/src/domains/dispatch/reproducibility.ts +48 -0
- package/src/domains/dispatch/reservation-store.ts +501 -0
- package/src/domains/dispatch/route-approval.ts +177 -0
- package/src/domains/dispatch/route-candidates.ts +57 -0
- package/src/domains/dispatch/route-decision.ts +1079 -0
- package/src/domains/dispatch/route-facts.ts +187 -0
- package/src/domains/dispatch/route-history.ts +238 -0
- package/src/domains/dispatch/route-observer.ts +488 -0
- package/src/domains/dispatch/route-policy.ts +327 -0
- package/src/domains/dispatch/route-quality.ts +256 -0
- package/src/domains/dispatch/route-readiness.ts +120 -0
- package/src/domains/dispatch/routing-intent.ts +287 -0
- package/src/domains/dispatch/run-identity.ts +56 -0
- package/src/domains/dispatch/scout-transition.ts +130 -0
- package/src/domains/dispatch/state.ts +277 -0
- package/src/domains/dispatch/tool-stats.ts +132 -0
- package/src/domains/dispatch/transport.ts +209 -0
- package/src/domains/dispatch/types.ts +785 -0
- package/src/domains/dispatch/validation-grounding.ts +154 -0
- package/src/domains/dispatch/validation.ts +721 -0
- package/src/domains/dispatch/worker-protocol.ts +275 -0
- package/src/domains/dispatch/worker-spawn.ts +566 -0
- package/src/domains/dispatch/write-boundary-enforcer.ts +97 -0
- package/src/domains/dispatch/write-boundary.ts +426 -0
- package/src/domains/eval/artifacts/redact.ts +42 -0
- package/src/domains/eval/artifacts/store.ts +173 -0
- package/src/domains/eval/compare/compare.ts +33 -0
- package/src/domains/eval/compare/gates.ts +66 -0
- package/src/domains/eval/compare/thresholds.ts +92 -0
- package/src/domains/eval/harness-metrics.ts +62 -0
- package/src/domains/eval/index.ts +66 -0
- package/src/domains/eval/metrics/chaos-stream.ts +93 -0
- package/src/domains/eval/metrics/context.ts +34 -0
- package/src/domains/eval/metrics/coverage.ts +21 -0
- package/src/domains/eval/metrics/evidence.ts +182 -0
- package/src/domains/eval/metrics/fleet-loop-stream.ts +196 -0
- package/src/domains/eval/metrics/invariants.ts +736 -0
- package/src/domains/eval/metrics/latency.ts +4 -0
- package/src/domains/eval/metrics/token-stream.ts +139 -0
- package/src/domains/eval/metrics/tokens.ts +51 -0
- package/src/domains/eval/metrics/tool-calls.ts +7 -0
- package/src/domains/eval/proactive-memory.ts +279 -0
- package/src/domains/eval/provenance.ts +35 -0
- package/src/domains/eval/report.ts +234 -0
- package/src/domains/eval/reports/json.ts +5 -0
- package/src/domains/eval/reports/junit.ts +23 -0
- package/src/domains/eval/reports/markdown.ts +20 -0
- package/src/domains/eval/reports/swe-jsonl.ts +16 -0
- package/src/domains/eval/reports/text.ts +25 -0
- package/src/domains/eval/run-compare.ts +274 -0
- package/src/domains/eval/runner.ts +244 -0
- package/src/domains/eval/runners/clio-run.ts +148 -0
- package/src/domains/eval/runners/context-index.ts +56 -0
- package/src/domains/eval/runners/context-init.ts +203 -0
- package/src/domains/eval/runners/external-command.ts +350 -0
- package/src/domains/eval/runtime-paths.ts +171 -0
- package/src/domains/eval/schema/artifact.ts +75 -0
- package/src/domains/eval/schema/suite.ts +235 -0
- package/src/domains/eval/schema/validate.ts +339 -0
- package/src/domains/eval/store.ts +392 -0
- package/src/domains/eval/suites/load.ts +74 -0
- package/src/domains/eval/suites/matrix.ts +19 -0
- package/src/domains/eval/suites/resolve.ts +44 -0
- package/src/domains/eval/suites/run.ts +325 -0
- package/src/domains/eval/task-file.ts +186 -0
- package/src/domains/eval/types.ts +141 -0
- package/src/domains/eval/verifiers/command.ts +27 -0
- package/src/domains/eval/verifiers/file-exists.ts +6 -0
- package/src/domains/eval/verifiers/patch.ts +22 -0
- package/src/domains/eval/workspaces/git.ts +41 -0
- package/src/domains/eval/workspaces/local.ts +17 -0
- package/src/domains/eval/workspaces/temp-copy.ts +29 -0
- package/src/domains/evidence/build.ts +1714 -0
- package/src/domains/evidence/eval.ts +605 -0
- package/src/domains/evidence/failure-attribution.ts +54 -0
- package/src/domains/evidence/finish-contract-map.ts +42 -0
- package/src/domains/evidence/index.ts +55 -0
- package/src/domains/evidence/provenance.ts +200 -0
- package/src/domains/evidence/redact.ts +81 -0
- package/src/domains/evidence/store.ts +291 -0
- package/src/domains/evidence/types.ts +325 -0
- package/src/domains/evolution/SELF_EDIT_GATE.md +91 -0
- package/src/domains/evolution/index.ts +26 -0
- package/src/domains/evolution/manifest.ts +154 -0
- package/src/domains/evolution/validate.ts +304 -0
- package/src/domains/extensions/contract.ts +22 -0
- package/src/domains/extensions/discovery.ts +193 -0
- package/src/domains/extensions/extension.ts +46 -0
- package/src/domains/extensions/index.ts +34 -0
- package/src/domains/extensions/manager.ts +30 -0
- package/src/domains/extensions/manifest.ts +6 -0
- package/src/domains/extensions/resources.ts +38 -0
- package/src/domains/extensions/state.ts +224 -0
- package/src/domains/extensions/types.ts +83 -0
- package/src/domains/interop/consent.ts +185 -0
- package/src/domains/interop/contract.ts +29 -0
- package/src/domains/interop/detect.ts +173 -0
- package/src/domains/interop/extension.ts +59 -0
- package/src/domains/interop/index.ts +34 -0
- package/src/domains/interop/manifest.ts +6 -0
- package/src/domains/interop/registry.ts +139 -0
- package/src/domains/interop/state.ts +92 -0
- package/src/domains/interop/types.ts +109 -0
- package/src/domains/lifecycle/contract.ts +11 -0
- package/src/domains/lifecycle/doctor.ts +536 -0
- package/src/domains/lifecycle/extension.ts +23 -0
- package/src/domains/lifecycle/index.ts +21 -0
- package/src/domains/lifecycle/install-method.ts +51 -0
- package/src/domains/lifecycle/manifest.ts +6 -0
- package/src/domains/lifecycle/migrations/index.ts +94 -0
- package/src/domains/lifecycle/state.ts +93 -0
- package/src/domains/lifecycle/upgrade-notice.ts +35 -0
- package/src/domains/lifecycle/version.ts +35 -0
- package/src/domains/memory/index.ts +128 -0
- package/src/domains/memory/operations.ts +143 -0
- package/src/domains/memory/prompt-section.ts +86 -0
- package/src/domains/memory/proposal.ts +180 -0
- package/src/domains/memory/store.ts +163 -0
- package/src/domains/memory/task-bank.ts +229 -0
- package/src/domains/memory/task-memory-handoff.ts +222 -0
- package/src/domains/memory/task-memory-policy.ts +602 -0
- package/src/domains/memory/task-memory-status.ts +58 -0
- package/src/domains/memory/task-memory-telemetry.ts +346 -0
- package/src/domains/memory/task-memory-trace.ts +89 -0
- package/src/domains/memory/types.ts +74 -0
- package/src/domains/memory/validate.ts +297 -0
- package/src/domains/middleware/budget.ts +216 -0
- package/src/domains/middleware/contract.ts +35 -0
- package/src/domains/middleware/dispatch-nudge.ts +469 -0
- package/src/domains/middleware/extension.ts +129 -0
- package/src/domains/middleware/hook-receipts.ts +70 -0
- package/src/domains/middleware/hooks-io.ts +174 -0
- package/src/domains/middleware/hooks.ts +432 -0
- package/src/domains/middleware/index.ts +154 -0
- package/src/domains/middleware/manifest.ts +6 -0
- package/src/domains/middleware/memory-intervention.ts +701 -0
- package/src/domains/middleware/rules.ts +42 -0
- package/src/domains/middleware/runtime.ts +333 -0
- package/src/domains/middleware/skills-reminder.ts +187 -0
- package/src/domains/middleware/snapshot.ts +71 -0
- package/src/domains/middleware/stalled-turn.ts +71 -0
- package/src/domains/middleware/task-board-reminder.ts +87 -0
- package/src/domains/middleware/task-nudge.ts +77 -0
- package/src/domains/middleware/tool-choice-control.ts +42 -0
- package/src/domains/middleware/types.ts +131 -0
- package/src/domains/middleware/validate.ts +329 -0
- package/src/domains/observability/accountability.ts +67 -0
- package/src/domains/observability/contract.ts +168 -0
- package/src/domains/observability/cost.ts +206 -0
- package/src/domains/observability/evidence-index.ts +123 -0
- package/src/domains/observability/extension.ts +281 -0
- package/src/domains/observability/index.ts +78 -0
- package/src/domains/observability/manifest.ts +10 -0
- package/src/domains/observability/metrics.ts +37 -0
- package/src/domains/observability/projection.ts +477 -0
- package/src/domains/observability/telemetry.ts +89 -0
- package/src/domains/observability/trace-store.ts +1454 -0
- package/src/domains/prompts/compiler.ts +556 -0
- package/src/domains/prompts/contract.ts +30 -0
- package/src/domains/prompts/extension.ts +304 -0
- package/src/domains/prompts/fragment-loader.ts +139 -0
- package/src/domains/prompts/fragments/identity/clio.md +3 -2
- package/src/domains/prompts/fragments/identity/self-awareness.md +63 -0
- package/src/domains/prompts/fragments/operating/contract.md +10 -1
- package/src/domains/prompts/hash.ts +73 -0
- package/src/domains/prompts/index.ts +32 -0
- package/src/domains/prompts/manifest.ts +8 -0
- package/src/domains/prompts/memory-intervention.ts +57 -0
- package/src/domains/prompts/preload.ts +82 -0
- package/src/domains/providers/auth/api-key.ts +47 -0
- package/src/domains/providers/auth/backend-file.ts +69 -0
- package/src/domains/providers/auth/backend-memory.ts +17 -0
- package/src/domains/providers/auth/index.ts +37 -0
- package/src/domains/providers/auth/oauth.ts +36 -0
- package/src/domains/providers/auth/storage.ts +667 -0
- package/src/domains/providers/capabilities.ts +50 -0
- package/src/domains/providers/catalog.ts +162 -0
- package/src/domains/providers/contract.ts +151 -0
- package/src/domains/providers/credentials.ts +20 -0
- package/src/domains/providers/eligibility.ts +24 -0
- package/src/domains/providers/errors.ts +64 -0
- package/src/domains/providers/extension.ts +536 -0
- package/src/domains/providers/index.ts +142 -0
- package/src/domains/providers/knowledge-base-path.ts +102 -0
- package/src/domains/providers/manifest.ts +6 -0
- package/src/domains/providers/model-capabilities.ts +136 -0
- package/src/domains/providers/model-discovery.ts +144 -0
- package/src/domains/providers/model-family.ts +32 -0
- package/src/domains/providers/model-runtime-capabilities.ts +712 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +2 -2
- package/src/domains/providers/plugins.ts +59 -0
- package/src/domains/providers/probe/fingerprint.ts +44 -0
- package/src/domains/providers/probe/http.ts +114 -0
- package/src/domains/providers/probe/reasoning.ts +111 -0
- package/src/domains/providers/registry.ts +166 -0
- package/src/domains/providers/resolver.ts +156 -0
- package/src/domains/providers/runtime-resolution.ts +720 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +90 -0
- package/src/domains/providers/runtimes/builtins.ts +78 -0
- package/src/domains/providers/runtimes/claude/claude-code.ts +38 -0
- package/src/domains/providers/runtimes/claude/claude-sdk.ts +38 -0
- package/src/domains/providers/runtimes/claude/common.ts +55 -0
- package/src/domains/providers/runtimes/cloud/alcf.ts +171 -0
- package/src/domains/providers/runtimes/cloud/anthropic-max.ts +71 -0
- package/src/domains/providers/runtimes/cloud/anthropic.ts +43 -0
- package/src/domains/providers/runtimes/cloud/bedrock.ts +35 -0
- package/src/domains/providers/runtimes/cloud/deepseek.ts +50 -0
- package/src/domains/providers/runtimes/cloud/google.ts +41 -0
- package/src/domains/providers/runtimes/cloud/groq.ts +46 -0
- package/src/domains/providers/runtimes/cloud/mistral.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openai-codex.ts +49 -0
- package/src/domains/providers/runtimes/cloud/openai.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openrouter.ts +111 -0
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +32 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +165 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +474 -0
- package/src/domains/providers/runtimes/local-native/lemonade-anthropic.ts +27 -0
- package/src/domains/providers/runtimes/local-native/lemonade-openai.ts +26 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +88 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +207 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +180 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +126 -0
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +98 -0
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +491 -0
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +117 -0
- package/src/domains/providers/runtimes/local-native/sglang.ts +26 -0
- package/src/domains/providers/runtimes/local-native/vllm.ts +27 -0
- package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +104 -0
- package/src/domains/providers/runtimes/protocol/anthropic-messages.ts +28 -0
- package/src/domains/providers/runtimes/protocol/bedrock.ts +26 -0
- package/src/domains/providers/runtimes/protocol/google.ts +27 -0
- package/src/domains/providers/runtimes/protocol/openai-compat.ts +145 -0
- package/src/domains/providers/support.ts +238 -0
- package/src/domains/providers/thinking-control-policy.ts +85 -0
- package/src/domains/providers/types/capability-flags.ts +114 -0
- package/src/domains/providers/types/cost-provenance.ts +7 -0
- package/src/domains/providers/types/inference.ts +41 -0
- package/src/domains/providers/types/knowledge-base.ts +156 -0
- package/src/domains/providers/types/local-model-quirks.ts +218 -0
- package/src/domains/providers/types/runtime-descriptor.ts +170 -0
- package/src/domains/providers/types/target-descriptor.ts +38 -0
- package/src/domains/resources/collision.ts +92 -0
- package/src/domains/resources/common-loader.ts +140 -0
- package/src/domains/resources/contract.ts +25 -0
- package/src/domains/resources/extension.ts +61 -0
- package/src/domains/resources/index.ts +74 -0
- package/src/domains/resources/loader.ts +86 -0
- package/src/domains/resources/manifest.ts +6 -0
- package/src/domains/resources/prompts/loader.ts +232 -0
- package/src/domains/resources/prompts/substitute.ts +65 -0
- package/src/domains/resources/skills/content-hash.ts +105 -0
- package/src/domains/resources/skills/evals.ts +175 -0
- package/src/domains/resources/skills/install.ts +410 -0
- package/src/domains/resources/skills/loader.ts +978 -0
- package/src/domains/resources/skills/marketplace.ts +255 -0
- package/src/domains/resources/skills/provenance-pin.ts +115 -0
- package/src/domains/safety/action-classifier.ts +268 -0
- package/src/domains/safety/approval-axis.ts +23 -0
- package/src/domains/safety/audit.ts +487 -0
- package/src/domains/safety/autonomy.ts +174 -0
- package/src/domains/safety/call-target.ts +59 -0
- package/src/domains/safety/contract.ts +65 -0
- package/src/domains/safety/damage-control.ts +44 -0
- package/src/domains/safety/default-path-policy.ts +117 -0
- package/src/domains/safety/extension.ts +383 -0
- package/src/domains/safety/finish-contract-registration.ts +128 -0
- package/src/domains/safety/finish-contract.ts +554 -0
- package/src/domains/safety/index.ts +44 -0
- package/src/domains/safety/loop-detector.ts +143 -0
- package/src/domains/safety/manifest.ts +6 -0
- package/src/domains/safety/path-policy.ts +164 -0
- package/src/domains/safety/policy-engine.ts +994 -0
- package/src/domains/safety/project-policy.ts +391 -0
- package/src/domains/safety/protected-artifacts-registration.ts +189 -0
- package/src/domains/safety/protected-artifacts.ts +993 -0
- package/src/domains/safety/rejection-feedback.ts +102 -0
- package/src/domains/safety/rigor.ts +72 -0
- package/src/domains/safety/rule-compiler.ts +48 -0
- package/src/domains/safety/rule-pack-loader.ts +92 -0
- package/src/domains/safety/run-effects.ts +197 -0
- package/src/domains/safety/scope.ts +61 -0
- package/src/domains/scheduling/budget.ts +35 -0
- package/src/domains/scheduling/cluster.ts +175 -0
- package/src/domains/scheduling/contract.ts +30 -0
- package/src/domains/scheduling/extension.ts +91 -0
- package/src/domains/scheduling/index.ts +12 -0
- package/src/domains/scheduling/manifest.ts +6 -0
- package/src/domains/session/archive-readers.ts +208 -0
- package/src/domains/session/checkpoint.ts +38 -0
- package/src/domains/session/compaction/auto.ts +89 -0
- package/src/domains/session/compaction/branch-summary.ts +186 -0
- package/src/domains/session/compaction/compact.ts +493 -0
- package/src/domains/session/compaction/cut-point.ts +171 -0
- package/src/domains/session/compaction/defaults.ts +34 -0
- package/src/domains/session/compaction/mask-observations.ts +265 -0
- package/src/domains/session/compaction/session-entries.ts +18 -0
- package/src/domains/session/compaction/tokens.ts +147 -0
- package/src/domains/session/context-accounting.ts +583 -0
- package/src/domains/session/context-ledger.ts +348 -0
- package/src/domains/session/contract.ts +144 -0
- package/src/domains/session/cwd-fallback.ts +65 -0
- package/src/domains/session/entries.ts +509 -0
- package/src/domains/session/extension.ts +322 -0
- package/src/domains/session/history.ts +172 -0
- package/src/domains/session/index.ts +84 -0
- package/src/domains/session/manager.ts +128 -0
- package/src/domains/session/manifest.ts +6 -0
- package/src/domains/session/migrations/index.ts +27 -0
- package/src/domains/session/prompt-manifest.ts +173 -0
- package/src/domains/session/protected-artifact-journal.ts +241 -0
- package/src/domains/session/protected-artifacts.ts +90 -0
- package/src/domains/session/retry.ts +238 -0
- package/src/domains/session/task-board.ts +375 -0
- package/src/domains/session/tree/active-path.ts +98 -0
- package/src/domains/session/tree/fork.ts +160 -0
- package/src/domains/session/tree/manager.ts +128 -0
- package/src/domains/session/tree/navigator.ts +177 -0
- package/src/domains/session/tree/preview.ts +259 -0
- package/src/domains/session/usage.ts +148 -0
- package/src/domains/session/workspace/git-probe.ts +161 -0
- package/src/domains/session/workspace/index.ts +4 -0
- package/src/domains/session/workspace/project-type.ts +217 -0
- package/src/domains/session/workspace/snapshot.ts +74 -0
- package/src/domains/share/archive.ts +684 -0
- package/src/domains/share/contract.ts +9 -0
- package/src/domains/share/extension.ts +26 -0
- package/src/domains/share/index.ts +28 -0
- package/src/domains/share/manifest.ts +6 -0
- package/src/engine/acp/adapter.ts +397 -0
- package/src/engine/acp/errors.ts +32 -0
- package/src/engine/acp/event-mapper.ts +154 -0
- package/src/engine/acp/server.ts +656 -0
- package/src/engine/acp/tool-mediator.ts +686 -0
- package/src/engine/acp/transport.ts +654 -0
- package/src/engine/acp/types.ts +170 -0
- package/src/engine/agent.ts +29 -0
- package/src/engine/ai.ts +202 -0
- package/src/engine/alcf-oauth.ts +198 -0
- package/src/engine/antigravity/subprocess-runtime.ts +205 -0
- package/src/engine/apis/degraded-inference.ts +95 -0
- package/src/engine/apis/index.ts +20 -0
- package/src/engine/apis/llamacpp-residency.ts +252 -0
- package/src/engine/apis/lmstudio-native.ts +1438 -0
- package/src/engine/apis/lmstudio-residency.ts +92 -0
- package/src/engine/apis/ollama-native.ts +507 -0
- package/src/engine/apis/openai-completions.ts +716 -0
- package/src/engine/apis/output-budget.ts +99 -0
- package/src/engine/apis/residency-lock.ts +29 -0
- package/src/engine/apis/residency.ts +640 -0
- package/src/engine/apis/resident-models.ts +42 -0
- package/src/engine/apis/sampling-overrides.ts +38 -0
- package/src/engine/apis/thinking-replay.ts +11 -0
- package/src/engine/claude/sdk-runtime.ts +685 -0
- package/src/engine/claude/session-id.ts +5 -0
- package/src/engine/claude/subprocess-runtime.ts +316 -0
- package/src/engine/claude/tool-safety.ts +400 -0
- package/src/engine/external-subprocess.ts +23 -0
- package/src/engine/harmony-response.ts +165 -0
- package/src/engine/loop-guard.ts +1127 -0
- package/src/engine/oauth.ts +192 -0
- package/src/engine/pi-mono-names.ts +13 -0
- package/src/engine/provider-payload.ts +315 -0
- package/src/engine/select-list.ts +53 -0
- package/src/engine/session.ts +834 -0
- package/src/engine/strip-tokenizer-sentinels.ts +125 -0
- package/src/engine/tui.ts +103 -0
- package/src/engine/types.ts +66 -0
- package/src/engine/worker-events.ts +100 -0
- package/src/engine/worker-runtime.ts +1022 -0
- package/src/engine/worker-tools.ts +203 -0
- package/src/entry/orchestrator.ts +1873 -0
- package/src/interactive/application-controller.ts +346 -0
- package/src/interactive/bus-notices.ts +265 -0
- package/src/interactive/chat-loop-messages.ts +626 -0
- package/src/interactive/chat-loop-policy.ts +18 -0
- package/src/interactive/chat-loop.ts +865 -0
- package/src/interactive/chat-panel.ts +1694 -0
- package/src/interactive/chat-renderer.ts +1038 -0
- package/src/interactive/clio-editor.ts +166 -0
- package/src/interactive/command-fallbacks.ts +23 -0
- package/src/interactive/command-output.ts +85 -0
- package/src/interactive/context-activity.ts +203 -0
- package/src/interactive/context-meter.ts +223 -0
- package/src/interactive/context-overlay.ts +220 -0
- package/src/interactive/cost-overlay.ts +279 -0
- package/src/interactive/dispatch-board.ts +1319 -0
- package/src/interactive/dispatch-steering.ts +86 -0
- package/src/interactive/editor-bash.ts +46 -0
- package/src/interactive/editor-steer.ts +51 -0
- package/src/interactive/editor-submit.ts +303 -0
- package/src/interactive/external-editor.ts +67 -0
- package/src/interactive/follow-up-queue-panel.ts +75 -0
- package/src/interactive/footer/dashboard.ts +534 -0
- package/src/interactive/footer/notifications.ts +275 -0
- package/src/interactive/footer/widgets.ts +1246 -0
- package/src/interactive/footer-panel.ts +187 -0
- package/src/interactive/format-time.ts +85 -0
- package/src/interactive/index.ts +11 -0
- package/src/interactive/interactive-application.ts +755 -0
- package/src/interactive/interactive-event-projection.ts +380 -0
- package/src/interactive/interactive-input-runtime.ts +261 -0
- package/src/interactive/interactive-presentation.ts +452 -0
- package/src/interactive/interactive-shell.ts +134 -0
- package/src/interactive/interactive-slash-runtime.ts +492 -0
- package/src/interactive/interactive-subscriptions.ts +111 -0
- package/src/interactive/interactive-tickers.ts +152 -0
- package/src/interactive/keybinding-manager.ts +496 -0
- package/src/interactive/layout.ts +20 -0
- package/src/interactive/leader-key.ts +143 -0
- package/src/interactive/loop-guard-interrupt.ts +101 -0
- package/src/interactive/memory-overlay.ts +280 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +110 -0
- package/src/interactive/overlay-auth-lifecycle.ts +308 -0
- package/src/interactive/overlay-frame.ts +502 -0
- package/src/interactive/overlay-general-openers.ts +217 -0
- package/src/interactive/overlay-key-routing.ts +213 -0
- package/src/interactive/overlay-lifecycle.ts +413 -0
- package/src/interactive/overlay-model-selectors.ts +127 -0
- package/src/interactive/overlay-permission-lifecycle.ts +344 -0
- package/src/interactive/overlay-resource-openers.ts +112 -0
- package/src/interactive/overlay-session-lifecycle.ts +270 -0
- package/src/interactive/overlay-transitions.ts +57 -0
- package/src/interactive/overlays/agents.ts +69 -0
- package/src/interactive/overlays/ask-user.ts +921 -0
- package/src/interactive/overlays/auth-dialog.ts +221 -0
- package/src/interactive/overlays/context-reset.ts +108 -0
- package/src/interactive/overlays/cwd-fallback.ts +141 -0
- package/src/interactive/overlays/extensions.ts +54 -0
- package/src/interactive/overlays/help-reference.ts +140 -0
- package/src/interactive/overlays/interop.ts +139 -0
- package/src/interactive/overlays/keybinding-detail.ts +90 -0
- package/src/interactive/overlays/list-overlay.ts +606 -0
- package/src/interactive/overlays/message-picker.ts +155 -0
- package/src/interactive/overlays/model-selector.ts +1091 -0
- package/src/interactive/overlays/prompts.ts +72 -0
- package/src/interactive/overlays/session-selector-search.ts +31 -0
- package/src/interactive/overlays/session-selector.ts +266 -0
- package/src/interactive/overlays/settings.ts +3363 -0
- package/src/interactive/overlays/skills-hub.ts +237 -0
- package/src/interactive/overlays/tree-selector.ts +387 -0
- package/src/interactive/permission-overlay.ts +170 -0
- package/src/interactive/render-trace.ts +125 -0
- package/src/interactive/renderers/branch-summary.ts +86 -0
- package/src/interactive/renderers/code-ink.ts +420 -0
- package/src/interactive/renderers/compaction-summary.ts +112 -0
- package/src/interactive/renderers/diff.ts +126 -0
- package/src/interactive/renderers/notice.ts +28 -0
- package/src/interactive/renderers/retry-status.ts +31 -0
- package/src/interactive/renderers/structured.ts +89 -0
- package/src/interactive/renderers/tool-execution.ts +1104 -0
- package/src/interactive/renderers/worker-entry.ts +264 -0
- package/src/interactive/session-last-turn.ts +186 -0
- package/src/interactive/session-transcript.ts +105 -0
- package/src/interactive/session-usage-reseed.ts +74 -0
- package/src/interactive/slash-autocomplete.ts +364 -0
- package/src/interactive/slash-commands.ts +1319 -0
- package/src/interactive/slash-spec.ts +453 -0
- package/src/interactive/status/controller.ts +256 -0
- package/src/interactive/status/index.ts +23 -0
- package/src/interactive/status/state-machine.ts +530 -0
- package/src/interactive/status/summary.ts +170 -0
- package/src/interactive/status/types.ts +121 -0
- package/src/interactive/status/verbs.ts +163 -0
- package/src/interactive/status/watchdog.ts +24 -0
- package/src/interactive/tasks-overlay.ts +186 -0
- package/src/interactive/theme/components.ts +55 -0
- package/src/interactive/theme/glyphs.ts +70 -0
- package/src/interactive/theme/index.ts +15 -0
- package/src/interactive/theme/labels.ts +88 -0
- package/src/interactive/theme/rules.ts +138 -0
- package/src/interactive/theme/segments.ts +88 -0
- package/src/interactive/theme/tokens.ts +121 -0
- package/src/interactive/thinking-level-policy.ts +6 -0
- package/src/interactive/tool-prose-loop.ts +122 -0
- package/src/interactive/tool-prose-registration.ts +48 -0
- package/src/interactive/turn-context.ts +854 -0
- package/src/interactive/turn-middleware.ts +283 -0
- package/src/interactive/turn-persistence.ts +441 -0
- package/src/interactive/turn-queues.ts +169 -0
- package/src/interactive/turn-recovery.ts +306 -0
- package/src/interactive/turn-runtime.ts +802 -0
- package/src/interactive/turn-state.ts +123 -0
- package/src/interactive/view/artifacts.ts +1342 -0
- package/src/interactive/view/view-overlay.ts +732 -0
- package/src/interactive/welcome-dashboard.ts +536 -0
- package/src/interactive/worker-receipts.ts +94 -0
- package/src/interactive/worker-replay.ts +111 -0
- package/src/interactive/worker-share.ts +100 -0
- package/src/interactive/worker-stream.ts +442 -0
- package/src/interactive/workspace-facts.ts +141 -0
- package/src/tools/agent-tools.ts +382 -0
- package/src/tools/artifact.ts +103 -0
- package/src/tools/ask-user.ts +656 -0
- package/src/tools/bash.ts +176 -0
- package/src/tools/bootstrap.ts +474 -0
- package/src/tools/codewiki/code-nav.ts +563 -0
- package/src/tools/codewiki/shared.ts +115 -0
- package/src/tools/compete-worktrees.ts +898 -0
- package/src/tools/context/docs-engine.ts +619 -0
- package/src/tools/context/index.ts +435 -0
- package/src/tools/credential-present.ts +151 -0
- package/src/tools/dispatch-arguments.ts +228 -0
- package/src/tools/dispatch-plan.ts +741 -0
- package/src/tools/dispatch-scout.ts +461 -0
- package/src/tools/dispatch.ts +3338 -0
- package/src/tools/edit-diff.ts +534 -0
- package/src/tools/edit.ts +128 -0
- package/src/tools/executables.ts +22 -0
- package/src/tools/file-mutation-queue.ts +35 -0
- package/src/tools/find.ts +292 -0
- package/src/tools/grep.ts +495 -0
- package/src/tools/ignore-policy.ts +169 -0
- package/src/tools/ledger.ts +206 -0
- package/src/tools/ls.ts +110 -0
- package/src/tools/monitor.ts +797 -0
- package/src/tools/network-policy.ts +29 -0
- package/src/tools/observation.ts +421 -0
- package/src/tools/observers.ts +99 -0
- package/src/tools/path-utils.ts +79 -0
- package/src/tools/policy.ts +154 -0
- package/src/tools/profiles.ts +108 -0
- package/src/tools/read.ts +173 -0
- package/src/tools/registry.ts +1157 -0
- package/src/tools/result-shaping.ts +204 -0
- package/src/tools/safe-exec.ts +128 -0
- package/src/tools/spawn-hygiene.ts +182 -0
- package/src/tools/steer.ts +88 -0
- package/src/tools/string-enum.ts +15 -0
- package/src/tools/tasks.ts +168 -0
- package/src/tools/truncate-utf8.ts +17 -0
- package/src/tools/truncate.ts +202 -0
- package/src/tools/verify/frontend.ts +685 -0
- package/src/tools/verify/index.ts +66 -0
- package/src/tools/verify/scripts.ts +108 -0
- package/src/tools/web-fetch.ts +777 -0
- package/src/tools/worker-evidence.ts +215 -0
- package/src/tools/write.ts +52 -0
- package/src/utils/exif-orientation.ts +192 -0
- package/src/utils/git.ts +24 -0
- package/src/utils/image-resize.ts +148 -0
- package/src/utils/photon.ts +103 -0
- package/src/worker/control-lane.ts +22 -0
- package/src/worker/entry.ts +257 -0
- package/src/worker/event-projection.ts +56 -0
- package/src/worker/heartbeat.ts +24 -0
- package/src/worker/ledger-mirror.ts +95 -0
- package/src/worker/ndjson.ts +40 -0
- package/src/worker/protocol.ts +529 -0
- package/src/worker/resource-facts.ts +79 -0
- package/src/worker/runtime-registry.ts +12 -0
- package/src/worker/spec-contract.ts +654 -0
- package/src/worker/stdin-demux.ts +316 -0
- package/dist/acp-UMLFVA3F.js +0 -92
- package/dist/chunk-262G75JS.js +0 -35
- package/dist/chunk-5LDRNKX2.js +0 -1063
- package/dist/chunk-67MTHP2E.js +0 -135
- package/dist/chunk-GOTUR54M.js +0 -9
- package/dist/chunk-TPOCL34A.js +0 -2876
- package/dist/chunk-XV4ZJ6ZM.js +0 -3177
- package/dist/clio-KIQ5SNDS.js +0 -53
- package/dist/configure-G4E3A2PG.js +0 -27
- package/dist/doctor-M5HJJZOL.js +0 -61
- package/dist/domains/agents/builtins/architect.md +0 -33
- package/dist/domains/agents/builtins/coder.md +0 -31
- package/dist/domains/agents/builtins/context-bootstrap.md +0 -38
- package/dist/domains/agents/builtins/debugger.md +0 -30
- package/dist/domains/agents/builtins/documenter.md +0 -31
- package/dist/domains/agents/builtins/git-master.md +0 -30
- package/dist/domains/agents/builtins/provenance.md +0 -30
- package/dist/domains/agents/builtins/researcher.md +0 -71
- package/dist/domains/agents/builtins/scout.md +0 -42
- package/dist/domains/agents/builtins/tester.md +0 -31
- package/dist/domains/agents/builtins/verifier.md +0 -30
- package/dist/domains/agents/builtins/wiki-writer.md +0 -41
- package/dist/fleet-preflight-CLIAX7YR.js +0 -21
- package/dist/preload-KZVHET2B.js +0 -11
- package/dist/version-ROZ6CZKH.js +0 -16
- package/skills/git/commit-crafting/SKILL.md +0 -79
- package/skills/git/commit-crafting/evals.md +0 -92
- package/skills/git/create-pr/SKILL.md +0 -116
- package/skills/git/create-pr/evals.md +0 -114
- package/skills/git/investigate-issue/SKILL.md +0 -139
- package/skills/git/investigate-issue/evals.md +0 -94
- package/skills/git/review-changes/SKILL.md +0 -103
- package/skills/git/review-changes/evals.md +0 -85
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-run enforcement of declared write boundaries.
|
|
3
|
+
*
|
|
4
|
+
* This is detect-and-rollback, not sandboxing. Nothing here prevents a write:
|
|
5
|
+
* no container, no seccomp filter, no read-only mount, no interception of the
|
|
6
|
+
* worker's file tools. A step runs with whatever reach its tool permissions
|
|
7
|
+
* give it, and afterwards the orchestrator compares the checkout against the
|
|
8
|
+
* snapshot it took before the step, rolls back what the step was not allowed to
|
|
9
|
+
* change, and fails the step with a typed reason. An operator who needs a step
|
|
10
|
+
* to be *unable* to write outside its allowlist needs OS-level isolation, which
|
|
11
|
+
* this module deliberately does not claim to provide.
|
|
12
|
+
*
|
|
13
|
+
* Enforcement is orchestrator-side because a worker cannot be its own witness:
|
|
14
|
+
* a self-check runs inside the process whose behaviour is in question, so the
|
|
15
|
+
* only authority is the same one that seals result-contract validation.
|
|
16
|
+
*
|
|
17
|
+
* The comparison is git plumbing rather than a tree hash, because this runs
|
|
18
|
+
* after every bounded step and must stay proportionate: one `status` call plus
|
|
19
|
+
* one object-hash call over the dirty set, not a walk of the repository.
|
|
20
|
+
*
|
|
21
|
+
* Everything is pinned to the baseline commit recorded at snapshot time, so a
|
|
22
|
+
* commit step that moves HEAD without touching the working tree reads as "no
|
|
23
|
+
* change" instead of as a wholesale rewrite.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { execFileSync } from "node:child_process";
|
|
27
|
+
import { createHash } from "node:crypto";
|
|
28
|
+
import { existsSync, lstatSync, mkdirSync, readlinkSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
29
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
30
|
+
import { clioStateDir } from "../../core/xdg.js";
|
|
31
|
+
import { atomicWrite } from "../../engine/session.js";
|
|
32
|
+
import { isGitRepository } from "../../tools/compete-worktrees.js";
|
|
33
|
+
import {
|
|
34
|
+
describeWriteBoundary,
|
|
35
|
+
normalizeWriteBoundary,
|
|
36
|
+
type WriteBoundary,
|
|
37
|
+
writeBoundaryCovers,
|
|
38
|
+
} from "../agents/write-boundary.js";
|
|
39
|
+
|
|
40
|
+
/** Typed step failure an operator can act on: widen the declaration, or don't write there. */
|
|
41
|
+
export const WRITE_BOUNDARY_VIOLATION_REASON = "writes_boundary_violation";
|
|
42
|
+
|
|
43
|
+
/** Content token for a path that does not exist. */
|
|
44
|
+
const ABSENT = "absent";
|
|
45
|
+
|
|
46
|
+
const GIT_TIMEOUT_MS = 30_000;
|
|
47
|
+
|
|
48
|
+
function git(root: string, args: ReadonlyArray<string>, input?: string): string {
|
|
49
|
+
return execFileSync("git", ["-C", root, ...args], {
|
|
50
|
+
encoding: "utf8",
|
|
51
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
52
|
+
timeout: GIT_TIMEOUT_MS,
|
|
53
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
54
|
+
...(input === undefined ? {} : { input }),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function gitBytes(root: string, args: ReadonlyArray<string>): Buffer {
|
|
59
|
+
return execFileSync("git", ["-C", root, ...args], {
|
|
60
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
61
|
+
timeout: GIT_TIMEOUT_MS,
|
|
62
|
+
maxBuffer: 256 * 1024 * 1024,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Every path git currently reports as dirty, tracked or not. `-uall` lists
|
|
68
|
+
* untracked files individually: a collapsed directory entry cannot be compared
|
|
69
|
+
* against a path allowlist. `--no-renames` keeps one path per entry, so a
|
|
70
|
+
* rename reads as the delete and the create it is on disk.
|
|
71
|
+
*
|
|
72
|
+
* Enforcement sees exactly what git sees, so an ignored path is outside it: a
|
|
73
|
+
* repository decides what counts as its own content, and this is not the place
|
|
74
|
+
* to overrule that. The one thing subtracted is Clio's own state directory when
|
|
75
|
+
* an operator has placed it inside the workspace. Receipts, code-step logs, and
|
|
76
|
+
* boundary verdicts are the orchestrator writing its journal while the step
|
|
77
|
+
* runs, and blaming the step for them would make every window a violation.
|
|
78
|
+
*/
|
|
79
|
+
function dirtyPaths(root: string): string[] {
|
|
80
|
+
const raw = git(root, ["status", "--porcelain=v1", "-z", "-uall", "--no-renames"]);
|
|
81
|
+
const journal = repoRelative(root, clioStateDir());
|
|
82
|
+
return raw
|
|
83
|
+
.split("\0")
|
|
84
|
+
.filter((entry) => entry.length > 3)
|
|
85
|
+
.map((entry) => entry.slice(3))
|
|
86
|
+
.filter((path) => journal === null || !(path === journal || path.startsWith(`${journal}/`)));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Content identity of one working-tree path.
|
|
91
|
+
*
|
|
92
|
+
* A blob hash rather than a status letter, because status is a statement about
|
|
93
|
+
* the index and this has to answer "are the bytes the same". A symlink is
|
|
94
|
+
* recorded as its target, so replacing a file with a link out of the repository
|
|
95
|
+
* is a change rather than an unreadable file.
|
|
96
|
+
*/
|
|
97
|
+
function contentTokens(root: string, paths: ReadonlyArray<string>): Map<string, string> {
|
|
98
|
+
const tokens = new Map<string, string>();
|
|
99
|
+
const hashable: string[] = [];
|
|
100
|
+
for (const path of paths) {
|
|
101
|
+
const full = join(root, path);
|
|
102
|
+
let stat: ReturnType<typeof lstatSync>;
|
|
103
|
+
try {
|
|
104
|
+
stat = lstatSync(full);
|
|
105
|
+
} catch {
|
|
106
|
+
tokens.set(path, ABSENT);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (stat.isSymbolicLink()) {
|
|
110
|
+
tokens.set(path, `link:${readlinkSync(full)}`);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (stat.isDirectory()) {
|
|
114
|
+
tokens.set(path, "dir");
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (!stat.isFile()) {
|
|
118
|
+
tokens.set(path, `special:${stat.mode}`);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
// A newline in a path would corrupt the batch protocol, so those paths
|
|
122
|
+
// are hashed one at a time rather than guessed at.
|
|
123
|
+
if (path.includes("\n")) {
|
|
124
|
+
tokens.set(path, `blob:${git(root, ["hash-object", "--", full]).trim()}`);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
hashable.push(path);
|
|
128
|
+
}
|
|
129
|
+
if (hashable.length > 0) {
|
|
130
|
+
const hashes = git(root, ["hash-object", "--stdin-paths"], `${hashable.map((path) => join(root, path)).join("\n")}\n`)
|
|
131
|
+
.split("\n")
|
|
132
|
+
.filter((line) => line.length > 0);
|
|
133
|
+
hashable.forEach((path, index) => {
|
|
134
|
+
tokens.set(path, `blob:${hashes[index] ?? "unknown"}`);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return tokens;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Content identity of the same paths in the pinned baseline commit. */
|
|
141
|
+
function baselineTokens(root: string, head: string, paths: ReadonlyArray<string>): Map<string, string> {
|
|
142
|
+
const tokens = new Map<string, string>();
|
|
143
|
+
if (paths.length === 0) return tokens;
|
|
144
|
+
const query = paths.map((path) => `${head}:${path}`).join("\n");
|
|
145
|
+
const answered = git(root, ["cat-file", "--batch-check=%(objectname) %(objecttype)"], `${query}\n`)
|
|
146
|
+
.split("\n")
|
|
147
|
+
.filter((line) => line.length > 0);
|
|
148
|
+
paths.forEach((path, index) => {
|
|
149
|
+
const line = answered[index] ?? "";
|
|
150
|
+
const [objectName, objectType] = line.split(" ");
|
|
151
|
+
if (objectType === "blob" && objectName !== undefined) tokens.set(path, `blob:${objectName}`);
|
|
152
|
+
else if (objectType === "tree") tokens.set(path, "dir");
|
|
153
|
+
else tokens.set(path, ABSENT);
|
|
154
|
+
});
|
|
155
|
+
return tokens;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The workspace as it stood before a step ran: the commit every comparison is
|
|
160
|
+
* pinned to, plus the content identity of everything already dirty. The dirty
|
|
161
|
+
* half matters for rollback rather than for detection: a path this snapshot
|
|
162
|
+
* already found modified has no stored content anywhere, so a later
|
|
163
|
+
* unauthorized change to it cannot be undone without guessing.
|
|
164
|
+
*/
|
|
165
|
+
export interface WorkspaceSnapshot {
|
|
166
|
+
root: string;
|
|
167
|
+
head: string;
|
|
168
|
+
/** Dirty path -> content token at capture time. */
|
|
169
|
+
entries: ReadonlyMap<string, string>;
|
|
170
|
+
capturedAt: string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function captureWorkspaceSnapshot(root: string): WorkspaceSnapshot {
|
|
174
|
+
const absolute = resolve(root);
|
|
175
|
+
if (!isGitRepository(absolute)) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`write boundary: ${absolute} is not a git repository, so a declared boundary cannot be verified (enforcement fails closed)`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
const head = git(absolute, ["rev-parse", "HEAD"]).trim();
|
|
181
|
+
const paths = dirtyPaths(absolute);
|
|
182
|
+
return { root: absolute, head, entries: contentTokens(absolute, paths), capturedAt: new Date().toISOString() };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface WorkspaceChange {
|
|
186
|
+
path: string;
|
|
187
|
+
before: string;
|
|
188
|
+
after: string;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* What changed since the snapshot. Candidates are the paths that were dirty
|
|
193
|
+
* then plus the paths that are dirty now; anything else is identical to the
|
|
194
|
+
* baseline in both readings and cannot have been touched and restored in a way
|
|
195
|
+
* that matters to the repository.
|
|
196
|
+
*/
|
|
197
|
+
export function diffWorkspace(snapshot: WorkspaceSnapshot): WorkspaceChange[] {
|
|
198
|
+
const candidates = [...new Set([...snapshot.entries.keys(), ...dirtyPaths(snapshot.root)])].sort();
|
|
199
|
+
if (candidates.length === 0) return [];
|
|
200
|
+
const unknownBefore = candidates.filter((path) => !snapshot.entries.has(path));
|
|
201
|
+
const baseline = baselineTokens(snapshot.root, snapshot.head, unknownBefore);
|
|
202
|
+
const now = contentTokens(snapshot.root, candidates);
|
|
203
|
+
const changes: WorkspaceChange[] = [];
|
|
204
|
+
for (const path of candidates) {
|
|
205
|
+
const before = snapshot.entries.get(path) ?? baseline.get(path) ?? ABSENT;
|
|
206
|
+
const after = now.get(path) ?? ABSENT;
|
|
207
|
+
if (before !== after) changes.push({ path, before, after });
|
|
208
|
+
}
|
|
209
|
+
return changes;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export interface WriteBoundaryRollback {
|
|
213
|
+
path: string;
|
|
214
|
+
action: "restored" | "removed";
|
|
215
|
+
/** Where the restored content came from, named so the record is checkable. */
|
|
216
|
+
restoredFrom: string;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface WriteBoundaryUnrecoverable {
|
|
220
|
+
path: string;
|
|
221
|
+
reason: string;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* `clean` means nothing outside the allowlist changed. `rolled-back` means
|
|
226
|
+
* something did and the repository now looks as it did before. Anything else is
|
|
227
|
+
* `rollback-incomplete`: the working tree is left exactly as the step made it
|
|
228
|
+
* and handed to the operator with the list, because a rollback that guesses at
|
|
229
|
+
* content it never recorded destroys work.
|
|
230
|
+
*/
|
|
231
|
+
export type WriteBoundaryStatus = "clean" | "rolled-back" | "rollback-incomplete";
|
|
232
|
+
|
|
233
|
+
export interface WriteBoundaryVerdict {
|
|
234
|
+
version: 1;
|
|
235
|
+
/** Which scheduling window this covers, e.g. `wave-2` or `revalidate-suite.check.1`. */
|
|
236
|
+
window: string;
|
|
237
|
+
/** Every step that ran inside the window. One id means exact attribution. */
|
|
238
|
+
stepIds: ReadonlyArray<string>;
|
|
239
|
+
/** The union the window was permitted to change. */
|
|
240
|
+
allow: ReadonlyArray<string>;
|
|
241
|
+
baselineHead: string;
|
|
242
|
+
capturedAt: string;
|
|
243
|
+
checkedAt: string;
|
|
244
|
+
changedPaths: ReadonlyArray<string>;
|
|
245
|
+
violations: ReadonlyArray<string>;
|
|
246
|
+
rolledBack: ReadonlyArray<WriteBoundaryRollback>;
|
|
247
|
+
unrecoverable: ReadonlyArray<WriteBoundaryUnrecoverable>;
|
|
248
|
+
status: WriteBoundaryStatus;
|
|
249
|
+
/** Typed failure reason, or null when the window stayed inside its boundary. */
|
|
250
|
+
reason: typeof WRITE_BOUNDARY_VIOLATION_REASON | null;
|
|
251
|
+
/** Operator-facing message naming the offending paths and the declaration. */
|
|
252
|
+
detail: string | null;
|
|
253
|
+
digest: string;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export interface EnforceWriteBoundaryInput {
|
|
257
|
+
snapshot: WorkspaceSnapshot;
|
|
258
|
+
window: string;
|
|
259
|
+
stepIds: ReadonlyArray<string>;
|
|
260
|
+
allow: WriteBoundary;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function canonicalVerdict(verdict: Omit<WriteBoundaryVerdict, "digest">): string {
|
|
264
|
+
return JSON.stringify(verdict);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Restore one unauthorized path.
|
|
269
|
+
*
|
|
270
|
+
* The only content this can restore is content git already has: the pinned
|
|
271
|
+
* baseline commit. A path that was already dirty when the snapshot was taken
|
|
272
|
+
* has its pre-step bytes nowhere but in the tree the step then overwrote, so it
|
|
273
|
+
* is reported rather than reconstructed.
|
|
274
|
+
*/
|
|
275
|
+
function rollbackPath(
|
|
276
|
+
snapshot: WorkspaceSnapshot,
|
|
277
|
+
change: WorkspaceChange,
|
|
278
|
+
): { rolledBack?: WriteBoundaryRollback; unrecoverable?: WriteBoundaryUnrecoverable } {
|
|
279
|
+
const full = join(snapshot.root, change.path);
|
|
280
|
+
if (snapshot.entries.has(change.path)) {
|
|
281
|
+
return {
|
|
282
|
+
unrecoverable: {
|
|
283
|
+
path: change.path,
|
|
284
|
+
reason: `path was already modified or untracked before the step, so its prior content is not recorded anywhere`,
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
if (change.before === ABSENT) {
|
|
289
|
+
try {
|
|
290
|
+
rmSync(full, { force: true, recursive: false });
|
|
291
|
+
} catch (error) {
|
|
292
|
+
return {
|
|
293
|
+
unrecoverable: { path: change.path, reason: `could not remove: ${(error as Error).message}` },
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return { rolledBack: { path: change.path, action: "removed", restoredFrom: "did not exist at baseline" } };
|
|
297
|
+
}
|
|
298
|
+
if (!change.before.startsWith("blob:")) {
|
|
299
|
+
return {
|
|
300
|
+
unrecoverable: {
|
|
301
|
+
path: change.path,
|
|
302
|
+
reason: `baseline state '${change.before}' is not a regular file and is not restorable in place`,
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
const content = gitBytes(snapshot.root, ["cat-file", "blob", `${snapshot.head}:${change.path}`]);
|
|
308
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
309
|
+
// Written directly rather than through `git checkout`, which would also
|
|
310
|
+
// stage the path and quietly rewrite an operator's index.
|
|
311
|
+
writeFileSync(full, content);
|
|
312
|
+
} catch (error) {
|
|
313
|
+
return {
|
|
314
|
+
unrecoverable: { path: change.path, reason: `could not restore from baseline: ${(error as Error).message}` },
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
return { rolledBack: { path: change.path, action: "restored", restoredFrom: `${snapshot.head}:${change.path}` } };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Compare, roll back, and return the verdict. Never throws for a violation: a
|
|
322
|
+
* violation is evidence the caller records and acts on, not an exception that
|
|
323
|
+
* would lose the list of what was restored.
|
|
324
|
+
*/
|
|
325
|
+
export function enforceWriteBoundary(input: EnforceWriteBoundaryInput): WriteBoundaryVerdict {
|
|
326
|
+
const allow = normalizeWriteBoundary(input.allow);
|
|
327
|
+
const changes = diffWorkspace(input.snapshot);
|
|
328
|
+
const violations = changes.filter((change) => !writeBoundaryCovers(allow, change.path));
|
|
329
|
+
const rolledBack: WriteBoundaryRollback[] = [];
|
|
330
|
+
const unrecoverable: WriteBoundaryUnrecoverable[] = [];
|
|
331
|
+
for (const change of violations) {
|
|
332
|
+
const outcome = rollbackPath(input.snapshot, change);
|
|
333
|
+
if (outcome.rolledBack !== undefined) rolledBack.push(outcome.rolledBack);
|
|
334
|
+
if (outcome.unrecoverable !== undefined) unrecoverable.push(outcome.unrecoverable);
|
|
335
|
+
}
|
|
336
|
+
const status: WriteBoundaryStatus =
|
|
337
|
+
violations.length === 0 ? "clean" : unrecoverable.length === 0 ? "rolled-back" : "rollback-incomplete";
|
|
338
|
+
const attribution =
|
|
339
|
+
input.stepIds.length === 1
|
|
340
|
+
? `step '${input.stepIds[0]}'`
|
|
341
|
+
: `steps ${input.stepIds.map((id) => `'${id}'`).join(", ")} ran concurrently in one checkout, so the write cannot be attributed to one of them`;
|
|
342
|
+
const detail =
|
|
343
|
+
violations.length === 0
|
|
344
|
+
? null
|
|
345
|
+
: [
|
|
346
|
+
`${attribution} wrote outside its declared boundary.`,
|
|
347
|
+
`Unauthorized paths: ${violations.map((change) => change.path).join(", ")}.`,
|
|
348
|
+
`Declared writes: ${describeWriteBoundary(allow)}.`,
|
|
349
|
+
status === "rolled-back"
|
|
350
|
+
? "Those paths were rolled back to the baseline commit."
|
|
351
|
+
: `Rollback is incomplete; the working tree is left as the step made it. Unrestorable: ${unrecoverable
|
|
352
|
+
.map((entry) => `${entry.path} (${entry.reason})`)
|
|
353
|
+
.join("; ")}.`,
|
|
354
|
+
"If the change was legitimate, widen the step's `writes:` declaration to cover it.",
|
|
355
|
+
].join(" ");
|
|
356
|
+
const body: Omit<WriteBoundaryVerdict, "digest"> = {
|
|
357
|
+
version: 1,
|
|
358
|
+
window: input.window,
|
|
359
|
+
stepIds: [...input.stepIds],
|
|
360
|
+
allow,
|
|
361
|
+
baselineHead: input.snapshot.head,
|
|
362
|
+
capturedAt: input.snapshot.capturedAt,
|
|
363
|
+
checkedAt: new Date().toISOString(),
|
|
364
|
+
changedPaths: changes.map((change) => change.path),
|
|
365
|
+
violations: violations.map((change) => change.path),
|
|
366
|
+
rolledBack,
|
|
367
|
+
unrecoverable,
|
|
368
|
+
status,
|
|
369
|
+
reason: violations.length === 0 ? null : WRITE_BOUNDARY_VIOLATION_REASON,
|
|
370
|
+
detail,
|
|
371
|
+
};
|
|
372
|
+
return { ...body, digest: createHash("sha256").update(canonicalVerdict(body), "utf8").digest("hex") };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Refuse a declaration that leaves the repository through a symlink. An entry
|
|
377
|
+
* is matched against git's own repo-relative paths, so a link that points
|
|
378
|
+
* outside can never be *reported* as changed; declaring it would create a
|
|
379
|
+
* boundary that silently permits nothing and hides real writes elsewhere.
|
|
380
|
+
*/
|
|
381
|
+
export function assertWriteBoundaryInsideRoot(root: string, allow: WriteBoundary): void {
|
|
382
|
+
const realRoot = realpathSync(resolve(root));
|
|
383
|
+
for (const entry of allow) {
|
|
384
|
+
const relativeEntry = entry.endsWith("/") ? entry.slice(0, -1) : entry;
|
|
385
|
+
let probe = join(realRoot, relativeEntry);
|
|
386
|
+
// Resolve the longest existing prefix: a boundary may legitimately name a
|
|
387
|
+
// path a step is about to create.
|
|
388
|
+
while (probe !== realRoot && !existsSync(probe)) probe = dirname(probe);
|
|
389
|
+
const resolved = realpathSync(probe);
|
|
390
|
+
if (resolved !== realRoot && !resolved.startsWith(realRoot + sep)) {
|
|
391
|
+
throw new Error(`write boundary: entry '${entry}' resolves to ${resolved}, outside the workspace at ${realRoot}`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Repo-relative form of an absolute path, or null when it is outside. */
|
|
397
|
+
function repoRelative(root: string, path: string): string | null {
|
|
398
|
+
const rel = relative(resolve(root), resolve(path));
|
|
399
|
+
if (rel.length === 0 || rel.startsWith("..") || rel.startsWith(`..${sep}`)) return null;
|
|
400
|
+
return rel.split(sep).join("/");
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
// Durable record
|
|
405
|
+
// ---------------------------------------------------------------------------
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Verdicts are recorded beside the run ledger, in the shape code steps already
|
|
409
|
+
* use: `write-boundaries/<rootId>/<window>.json` under the Clio state
|
|
410
|
+
* directory. A verdict is a fact about the checkout across a scheduling window,
|
|
411
|
+
* not about one model run, so it has no receipt to be sealed inside; it carries
|
|
412
|
+
* its own digest and names the baseline commit it was computed against.
|
|
413
|
+
*/
|
|
414
|
+
export function writeBoundaryDir(rootId: string): string {
|
|
415
|
+
return join(clioStateDir(), "write-boundaries", rootId);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function writeBoundaryVerdictPath(rootId: string, window: string): string {
|
|
419
|
+
return join(writeBoundaryDir(rootId), `${window.replace(/[^A-Za-z0-9._-]/gu, "_")}.json`);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export function writeWriteBoundaryVerdict(rootId: string, verdict: WriteBoundaryVerdict): string {
|
|
423
|
+
const path = writeBoundaryVerdictPath(rootId, verdict.window);
|
|
424
|
+
atomicWrite(path, `${JSON.stringify(verdict, null, 2)}\n`);
|
|
425
|
+
return path;
|
|
426
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const SENSITIVE_KEY = /(?:^|[_-])(api[_-]?key|authorization|cookie|password|secret|token)(?:$|[_-])/i;
|
|
2
|
+
|
|
3
|
+
const CREDENTIAL_PATTERNS: Array<[RegExp, string]> = [
|
|
4
|
+
[/\b(authorization\s*[:=]\s*)(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]+/gi, "$1[redacted]"],
|
|
5
|
+
[/\b(bearer\s+)[A-Za-z0-9._~+/=-]{12,}/gi, "$1[redacted]"],
|
|
6
|
+
[/\b(sk-[A-Za-z0-9_-]{16,})\b/g, "[redacted]"],
|
|
7
|
+
[/\b(gh[pousr]_[A-Za-z0-9_]{16,})\b/g, "[redacted]"],
|
|
8
|
+
[/\b(AKIA[0-9A-Z]{16})\b/g, "[redacted]"],
|
|
9
|
+
[/\b((?:api[_-]?key|access[_-]?token|refresh[_-]?token|password|secret)\s*[:=]\s*)[^\s"',}]+/gi, "$1[redacted]"],
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export function redactArtifactForStorage<T>(value: T, env: NodeJS.ProcessEnv = process.env): T {
|
|
13
|
+
return redactValue(value, env) as T;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function redactValue(value: unknown, env: NodeJS.ProcessEnv): unknown {
|
|
17
|
+
if (typeof value === "string") return redactString(value, env);
|
|
18
|
+
if (Array.isArray(value)) return value.map((entry) => redactValue(entry, env));
|
|
19
|
+
if (value !== null && typeof value === "object") {
|
|
20
|
+
const out: Record<string, unknown> = {};
|
|
21
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
22
|
+
out[key] = SENSITIVE_KEY.test(key) ? "[redacted]" : redactValue(entry, env);
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function redactString(value: string, env: NodeJS.ProcessEnv): string {
|
|
30
|
+
let out = stripHomePrefix(value, env.HOME);
|
|
31
|
+
for (const [pattern, replacement] of CREDENTIAL_PATTERNS) {
|
|
32
|
+
out = out.replace(pattern, replacement);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function stripHomePrefix(value: string, home: string | undefined): string {
|
|
38
|
+
if (home === undefined || home.length === 0) return value;
|
|
39
|
+
const normalized = home.replace(/\/+$/g, "");
|
|
40
|
+
if (normalized.length === 0) return value;
|
|
41
|
+
return value.split(normalized).join("$HOME");
|
|
42
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { assertSafeId } from "../../../core/safe-id.js";
|
|
4
|
+
import { safeResourceWrite } from "../../../core/safe-resource-write.js";
|
|
5
|
+
import type { EvalArtifactV4, EvalTokenAccountingV4 } from "../schema/artifact.js";
|
|
6
|
+
import { evalRoot } from "../store.js";
|
|
7
|
+
import { redactArtifactForStorage } from "./redact.js";
|
|
8
|
+
|
|
9
|
+
function evalArtifactPathV4(dataDir: string, evalId: string): string {
|
|
10
|
+
assertSafeId(evalId, "eval");
|
|
11
|
+
return join(evalRoot(dataDir), `${evalId}.json`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function writeEvalArtifactV4(dataDir: string, artifact: EvalArtifactV4, out?: string): Promise<string> {
|
|
15
|
+
const path =
|
|
16
|
+
out === undefined
|
|
17
|
+
? evalArtifactPathV4(dataDir, artifact.evalId)
|
|
18
|
+
: out.endsWith(".json")
|
|
19
|
+
? out
|
|
20
|
+
: join(out, `${artifact.evalId}.json`);
|
|
21
|
+
safeResourceWrite(path, `${JSON.stringify(redactArtifactForStorage(artifact), null, 2)}\n`, { encoding: "utf8" });
|
|
22
|
+
return path;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Read only the current explicit-link artifact format; retired shapes are
|
|
27
|
+
* rejected. An id with no artifact under the store root is named as such: the
|
|
28
|
+
* caller supplied an id, not a path, so the path node:fs would have quoted is
|
|
29
|
+
* not the thing they can correct.
|
|
30
|
+
*/
|
|
31
|
+
export async function loadEvalArtifactV4(dataDir: string, evalId: string): Promise<EvalArtifactV4> {
|
|
32
|
+
let raw: string;
|
|
33
|
+
try {
|
|
34
|
+
raw = await readFile(evalArtifactPathV4(dataDir, evalId), "utf8");
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") throw new Error(`eval artifact not found: ${evalId}`);
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
return parseEvalArtifactV4(JSON.parse(raw) as unknown, evalId);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function parseEvalArtifactV4(value: unknown, source: string): EvalArtifactV4 {
|
|
43
|
+
if (!isRecord(value)) throw new Error(`${source}: expected object`);
|
|
44
|
+
if (value.version !== 4) throw new Error(`${source}.version: expected current version 4`);
|
|
45
|
+
const summary = asRecord(value.summary, `${source}.summary`);
|
|
46
|
+
const matrix = asRecord(value.matrix, `${source}.matrix`);
|
|
47
|
+
const suite = asRecord(value.suite, `${source}.suite`);
|
|
48
|
+
return {
|
|
49
|
+
version: 4,
|
|
50
|
+
evalId: readString(value, source, "evalId"),
|
|
51
|
+
suite: { id: readString(suite, `${source}.suite`, "id"), hash: readString(suite, `${source}.suite`, "hash") },
|
|
52
|
+
clio: {
|
|
53
|
+
version: readString(asRecord(value.clio, `${source}.clio`), `${source}.clio`, "version"),
|
|
54
|
+
commit: readNullableString(asRecord(value.clio, `${source}.clio`), `${source}.clio`, "commit"),
|
|
55
|
+
entry: readString(asRecord(value.clio, `${source}.clio`), `${source}.clio`, "entry"),
|
|
56
|
+
},
|
|
57
|
+
environment: {
|
|
58
|
+
platform: readString(asRecord(value.environment, `${source}.environment`), `${source}.environment`, "platform"),
|
|
59
|
+
node: readString(asRecord(value.environment, `${source}.environment`), `${source}.environment`, "node"),
|
|
60
|
+
},
|
|
61
|
+
matrix: {
|
|
62
|
+
target: readString(matrix, `${source}.matrix`, "target"),
|
|
63
|
+
model: readNullableString(matrix, `${source}.matrix`, "model"),
|
|
64
|
+
thinking: readNullableString(matrix, `${source}.matrix`, "thinking"),
|
|
65
|
+
},
|
|
66
|
+
summary: {
|
|
67
|
+
runs: readNumber(summary, `${source}.summary`, "runs"),
|
|
68
|
+
passed: readNumber(summary, `${source}.summary`, "passed"),
|
|
69
|
+
failed: readNumber(summary, `${source}.summary`, "failed"),
|
|
70
|
+
passRate: readNumber(summary, `${source}.summary`, "passRate"),
|
|
71
|
+
tokens: parseTokenAccounting(summary.tokens, `${source}.summary.tokens`),
|
|
72
|
+
wallTimeMs: readNumber(summary, `${source}.summary`, "wallTimeMs"),
|
|
73
|
+
},
|
|
74
|
+
results: readArray(value, source, "results").map((entry, index) => parseResult(entry, `${source}.results[${index}]`)),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* An unmeasured artifact must carry no counts. Reading counts beside
|
|
80
|
+
* `measured: false` is a contradiction rather than a value to prefer, so it is
|
|
81
|
+
* refused instead of being resolved silently.
|
|
82
|
+
*/
|
|
83
|
+
function parseTokenAccounting(value: unknown, source: string): EvalTokenAccountingV4 {
|
|
84
|
+
const record = asRecord(value, source);
|
|
85
|
+
const measured = readBoolean(record, source, "measured");
|
|
86
|
+
const runs = readNumber(record, source, "runs");
|
|
87
|
+
const measuredRuns = readNumber(record, source, "measuredRuns");
|
|
88
|
+
const countFields = ["input", "output", "total", "cacheRead", "cacheWrite"] as const;
|
|
89
|
+
if (!measured) {
|
|
90
|
+
if (measuredRuns !== 0) throw new Error(`${source}.measuredRuns: expected 0 when unmeasured`);
|
|
91
|
+
const present = countFields.filter((field) => field in record);
|
|
92
|
+
if (present.length > 0) throw new Error(`${source}: unmeasured accounting carries no counts (${present.join(", ")})`);
|
|
93
|
+
return { measured: false, runs, measuredRuns: 0 };
|
|
94
|
+
}
|
|
95
|
+
if (measuredRuns <= 0) throw new Error(`${source}.measuredRuns: expected a positive count when measured`);
|
|
96
|
+
return {
|
|
97
|
+
measured: true,
|
|
98
|
+
runs,
|
|
99
|
+
measuredRuns,
|
|
100
|
+
input: readNumber(record, source, "input"),
|
|
101
|
+
output: readNumber(record, source, "output"),
|
|
102
|
+
total: readNumber(record, source, "total"),
|
|
103
|
+
cacheRead: readNumber(record, source, "cacheRead"),
|
|
104
|
+
cacheWrite: readNumber(record, source, "cacheWrite"),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function parseResult(value: unknown, source: string): EvalArtifactV4["results"][number] {
|
|
109
|
+
const record = asRecord(value, source);
|
|
110
|
+
const target = asRecord(record.target, `${source}.target`);
|
|
111
|
+
return {
|
|
112
|
+
assignmentId: readNullableString(record, source, "assignmentId"),
|
|
113
|
+
terminalReceiptDigest: readNullableDigest(record, source, "terminalReceiptDigest"),
|
|
114
|
+
taskId: readString(record, source, "taskId"),
|
|
115
|
+
repeatIndex: readNumber(record, source, "repeatIndex"),
|
|
116
|
+
target: {
|
|
117
|
+
id: readString(target, `${source}.target`, "id"),
|
|
118
|
+
model: readNullableString(target, `${source}.target`, "model"),
|
|
119
|
+
thinking: readNullableString(target, `${source}.target`, "thinking"),
|
|
120
|
+
},
|
|
121
|
+
pass: readBoolean(record, source, "pass"),
|
|
122
|
+
failureClass: readNullableString(record, source, "failureClass"),
|
|
123
|
+
metrics: asRecord(record.metrics, `${source}.metrics`) as Record<string, number | string | boolean | null>,
|
|
124
|
+
artifacts: asRecord(record.artifacts, `${source}.artifacts`) as Record<string, string | string[] | null>,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function asRecord(value: unknown, source: string): Record<string, unknown> {
|
|
129
|
+
if (isRecord(value)) return value;
|
|
130
|
+
throw new Error(`${source}: expected object`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
134
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function readString(record: Record<string, unknown>, source: string, field: string): string {
|
|
138
|
+
const value = record[field];
|
|
139
|
+
if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string`);
|
|
140
|
+
return value;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function readNullableString(record: Record<string, unknown>, source: string, field: string): string | null {
|
|
144
|
+
const value = record[field];
|
|
145
|
+
if (value === null) return null;
|
|
146
|
+
if (typeof value !== "string" || value.length === 0) throw new Error(`${source}.${field}: expected string or null`);
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function readNullableDigest(record: Record<string, unknown>, source: string, field: string): string | null {
|
|
151
|
+
const value = readNullableString(record, source, field);
|
|
152
|
+
if (value !== null && !/^[0-9a-f]{64}$/u.test(value))
|
|
153
|
+
throw new Error(`${source}.${field}: expected sha256 digest or null`);
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function readNumber(record: Record<string, unknown>, source: string, field: string): number {
|
|
158
|
+
const value = record[field];
|
|
159
|
+
if (typeof value !== "number" || !Number.isFinite(value)) throw new Error(`${source}.${field}: expected number`);
|
|
160
|
+
return value;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function readBoolean(record: Record<string, unknown>, source: string, field: string): boolean {
|
|
164
|
+
const value = record[field];
|
|
165
|
+
if (typeof value !== "boolean") throw new Error(`${source}.${field}: expected boolean`);
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function readArray(record: Record<string, unknown>, source: string, field: string): unknown[] {
|
|
170
|
+
const value = record[field];
|
|
171
|
+
if (!Array.isArray(value)) throw new Error(`${source}.${field}: expected array`);
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { EvalArtifactV4 } from "../schema/artifact.js";
|
|
2
|
+
|
|
3
|
+
export interface EvalCompareV4Summary {
|
|
4
|
+
baselineEvalId: string;
|
|
5
|
+
candidateEvalId: string;
|
|
6
|
+
passRateDelta: number;
|
|
7
|
+
/** Null when either side observed no usage: a delta against an unknown is not zero. */
|
|
8
|
+
tokenDelta: number | null;
|
|
9
|
+
wallTimeDelta: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function compareEvalArtifactsV4(baseline: EvalArtifactV4, candidate: EvalArtifactV4): EvalCompareV4Summary {
|
|
13
|
+
const baselineTokens = baseline.summary.tokens;
|
|
14
|
+
const candidateTokens = candidate.summary.tokens;
|
|
15
|
+
return {
|
|
16
|
+
baselineEvalId: baseline.evalId,
|
|
17
|
+
candidateEvalId: candidate.evalId,
|
|
18
|
+
passRateDelta: candidate.summary.passRate - baseline.summary.passRate,
|
|
19
|
+
tokenDelta: baselineTokens.measured && candidateTokens.measured ? candidateTokens.total - baselineTokens.total : null,
|
|
20
|
+
wallTimeDelta: candidate.summary.wallTimeMs - baseline.summary.wallTimeMs,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function renderEvalComparisonV4(summary: EvalCompareV4Summary): string {
|
|
25
|
+
return [
|
|
26
|
+
`baseline eval: ${summary.baselineEvalId}`,
|
|
27
|
+
`candidate eval: ${summary.candidateEvalId}`,
|
|
28
|
+
`pass-rate delta: ${(summary.passRateDelta * 100).toFixed(2)}%`,
|
|
29
|
+
`token delta: ${summary.tokenDelta === null ? "unmeasured" : summary.tokenDelta}`,
|
|
30
|
+
`wall-time delta ms: ${summary.wallTimeDelta}`,
|
|
31
|
+
"",
|
|
32
|
+
].join("\n");
|
|
33
|
+
}
|