@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,736 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invariant metrics: the promises Clio makes about its own machinery, read
|
|
3
|
+
* from the journal one eval item left behind.
|
|
4
|
+
*
|
|
5
|
+
* These invert what a benchmark measures. A weak model that never solved the
|
|
6
|
+
* task leaves every one of them intact; a strong model that solved it leaves
|
|
7
|
+
* them broken the moment Clio failed to seal, to agree with itself, or to
|
|
8
|
+
* write a receipt its own ledger can authenticate. The task outcome and the
|
|
9
|
+
* machinery's behavior are separate readings, and only the second is a gate.
|
|
10
|
+
*
|
|
11
|
+
* Every reader here is total and never throws. A metric this pass could not
|
|
12
|
+
* compute is absent rather than false: a threshold on an absent metric fails
|
|
13
|
+
* closed, while a fabricated value would be indistinguishable from a check
|
|
14
|
+
* that ran and passed.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import { verifyReceiptIntegrity } from "../../dispatch/receipt-integrity.js";
|
|
20
|
+
import type { RunEnvelope, RunReceipt } from "../../dispatch/types.js";
|
|
21
|
+
|
|
22
|
+
export interface EvalRunJournal {
|
|
23
|
+
/** Ledger envelopes by run id. The authority a receipt is authenticated against. */
|
|
24
|
+
envelopes: Map<string, RunEnvelope>;
|
|
25
|
+
/** Receipts that parsed into receipt shape. */
|
|
26
|
+
receipts: RunReceipt[];
|
|
27
|
+
/**
|
|
28
|
+
* Files present under receipts/. A file Clio wrote that no longer parses
|
|
29
|
+
* as a receipt is a sealed artifact that cannot be read, so the count is
|
|
30
|
+
* kept apart from `receipts.length` rather than folded into it.
|
|
31
|
+
*/
|
|
32
|
+
receiptFiles: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Read the run ledger and receipts an eval item's Clio wrote under its own
|
|
37
|
+
* state directory. Returns null when there is no such directory to read, which
|
|
38
|
+
* is the one case where the invariants below are genuinely unobservable.
|
|
39
|
+
*/
|
|
40
|
+
export function readRunJournal(stateDir: string): EvalRunJournal | null {
|
|
41
|
+
if (!existsSync(stateDir)) return null;
|
|
42
|
+
return {
|
|
43
|
+
envelopes: readEnvelopes(join(stateDir, "runs.json")),
|
|
44
|
+
...readReceipts(join(stateDir, "receipts")),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function readEnvelopes(runsPath: string): Map<string, RunEnvelope> {
|
|
49
|
+
const envelopes = new Map<string, RunEnvelope>();
|
|
50
|
+
if (!existsSync(runsPath)) return envelopes;
|
|
51
|
+
let parsed: unknown;
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(readFileSync(runsPath, "utf8")) as unknown;
|
|
54
|
+
} catch {
|
|
55
|
+
return envelopes;
|
|
56
|
+
}
|
|
57
|
+
if (!Array.isArray(parsed)) return envelopes;
|
|
58
|
+
for (const entry of parsed) {
|
|
59
|
+
if (isRecord(entry) && typeof entry.id === "string") envelopes.set(entry.id, entry as unknown as RunEnvelope);
|
|
60
|
+
}
|
|
61
|
+
return envelopes;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readReceipts(receiptsDir: string): { receipts: RunReceipt[]; receiptFiles: number } {
|
|
65
|
+
if (!existsSync(receiptsDir)) return { receipts: [], receiptFiles: 0 };
|
|
66
|
+
let names: string[];
|
|
67
|
+
try {
|
|
68
|
+
names = readdirSync(receiptsDir).filter((name) => name.endsWith(".json"));
|
|
69
|
+
} catch {
|
|
70
|
+
return { receipts: [], receiptFiles: 0 };
|
|
71
|
+
}
|
|
72
|
+
const receipts: RunReceipt[] = [];
|
|
73
|
+
for (const name of names) {
|
|
74
|
+
try {
|
|
75
|
+
const parsed: unknown = JSON.parse(readFileSync(join(receiptsDir, name), "utf8"));
|
|
76
|
+
if (isReceiptShaped(parsed)) receipts.push(parsed);
|
|
77
|
+
} catch {
|
|
78
|
+
// Counted by receiptFiles below: an unreadable receipt is a broken
|
|
79
|
+
// seal, not a receipt that was never written.
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { receipts, receiptFiles: names.length };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Invariant metrics for one eval item.
|
|
87
|
+
*
|
|
88
|
+
* - `receipt.count` / `receipt.sealed`: how many receipts this item's Clio
|
|
89
|
+
* sealed. Zero is an observation, not an absence: the journal was readable
|
|
90
|
+
* and empty.
|
|
91
|
+
* - `receipt.rootCount`: receipts that begin their own lineage. One per
|
|
92
|
+
* operator-initiated run; a plan with retries has more.
|
|
93
|
+
* - `receipt.integrityValid`: every sealed receipt parsed and authenticated
|
|
94
|
+
* against its own ledger envelope through `verifyReceiptIntegrity`. Absent
|
|
95
|
+
* when nothing sealed, because there is no seal to judge.
|
|
96
|
+
* - `receipt.outcomeMatchesExit`: no receipt claims an outcome its own exit
|
|
97
|
+
* code contradicts, and where exactly one root receipt exists, its success
|
|
98
|
+
* agrees with the exit status the process reported. A receipt that says
|
|
99
|
+
* `succeeded` while the process exited nonzero is the failure this catches.
|
|
100
|
+
* With several roots the process-level half is unattributable and only the
|
|
101
|
+
* per-receipt half is checked.
|
|
102
|
+
*/
|
|
103
|
+
export function receiptInvariantMetrics(
|
|
104
|
+
journal: EvalRunJournal | null,
|
|
105
|
+
processExitCode: number,
|
|
106
|
+
): Record<string, number | boolean> {
|
|
107
|
+
if (journal === null) return {};
|
|
108
|
+
const sealed = journal.receiptFiles > 0;
|
|
109
|
+
const roots = journal.receipts.filter(isRootReceipt);
|
|
110
|
+
const base = {
|
|
111
|
+
"receipt.count": journal.receiptFiles,
|
|
112
|
+
"receipt.sealed": sealed,
|
|
113
|
+
"receipt.rootCount": roots.length,
|
|
114
|
+
// Every attempt after the first is `recovery`. A bounded loop's repairs
|
|
115
|
+
// are exactly those attempts, so this is what a loop's attempt accounting
|
|
116
|
+
// is checked against.
|
|
117
|
+
"receipt.recoveryCount": journal.receipts.filter((receipt) => receipt.executionRole === "recovery").length,
|
|
118
|
+
};
|
|
119
|
+
if (!sealed) return base;
|
|
120
|
+
return {
|
|
121
|
+
...base,
|
|
122
|
+
"receipt.integrityValid": integrityValid(journal),
|
|
123
|
+
"receipt.outcomeMatchesExit": outcomeMatchesExit(journal, roots, processExitCode),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Receipt-derived token and cost accounting for one eval item.
|
|
129
|
+
*
|
|
130
|
+
* This is a different observation from `tokens.*`, which is folded live off
|
|
131
|
+
* the runner's stdout by `token-stream.ts` and means exactly one thing: usage
|
|
132
|
+
* a provider reported on an assistant `message_end` this runner watched cross
|
|
133
|
+
* the wire. Some surfaces publish no such stream. `clio-coder fleet run --json`
|
|
134
|
+
* drains its workers' events and publishes receipts and one summary, so a
|
|
135
|
+
* bounded loop's cost never reaches that fold and `tokens.measured` is
|
|
136
|
+
* correctly false.
|
|
137
|
+
*
|
|
138
|
+
* The cost is still sealed. Every attempt writes a receipt carrying
|
|
139
|
+
* `tokenCount` and `costUsd`, authenticated against its own ledger envelope.
|
|
140
|
+
* That is an observation too, and an authenticated one, but its provenance is
|
|
141
|
+
* the journal rather than the wire: it is what Clio sealed, not what a
|
|
142
|
+
* provider was watched reporting. The two never merge and never reconcile.
|
|
143
|
+
* `tokens.*` keeps its single meaning, `receiptUsage.*` carries its own, and
|
|
144
|
+
* neither enters the artifact's `summary.tokens`.
|
|
145
|
+
*
|
|
146
|
+
* Reading is total and fails closed. An unreadable journal yields no metrics
|
|
147
|
+
* at all. A readable journal that sealed nothing yields `measured: false`,
|
|
148
|
+
* which is an observation rather than an absence. Anything that breaks the
|
|
149
|
+
* completeness or authenticity of the receipt set yields `measured: false`
|
|
150
|
+
* and no counts, because a sum over receipts that could not all be
|
|
151
|
+
* authenticated reports a cost nobody can vouch for.
|
|
152
|
+
*
|
|
153
|
+
* The optional per-field split (`inputTokenCount` and its siblings) is
|
|
154
|
+
* deliberately not exposed. It is optional on the receipt, so partial
|
|
155
|
+
* availability would need its own per-field coverage semantics, and the
|
|
156
|
+
* required totals already close the gap.
|
|
157
|
+
*/
|
|
158
|
+
export function receiptUsageMetrics(journal: EvalRunJournal | null): Record<string, number | boolean> {
|
|
159
|
+
if (journal === null) return {};
|
|
160
|
+
if (journal.receiptFiles === 0) return { "receiptUsage.measured": false };
|
|
161
|
+
if (!integrityValid(journal)) return { "receiptUsage.measured": false };
|
|
162
|
+
let totalTokens = 0;
|
|
163
|
+
let costUsd = 0;
|
|
164
|
+
for (const receipt of journal.receipts) {
|
|
165
|
+
totalTokens += finiteNumber(receipt.tokenCount);
|
|
166
|
+
costUsd += finiteNumber(receipt.costUsd);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
"receiptUsage.measured": true,
|
|
170
|
+
"receiptUsage.receiptCount": journal.receipts.length,
|
|
171
|
+
"receiptUsage.totalTokens": totalTokens,
|
|
172
|
+
"receiptUsage.costUsd": costUsd,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function finiteNumber(value: number): number {
|
|
177
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function integrityValid(journal: EvalRunJournal): boolean {
|
|
181
|
+
// A receipt file that did not parse never reaches the loop below, so the
|
|
182
|
+
// count has to agree first: an unreadable seal cannot be authenticated.
|
|
183
|
+
if (journal.receipts.length !== journal.receiptFiles) return false;
|
|
184
|
+
return journal.receipts.every((receipt) => {
|
|
185
|
+
const envelope = journal.envelopes.get(receipt.runId);
|
|
186
|
+
// No envelope means no authority to verify against. The receipt is
|
|
187
|
+
// unauthenticated, which is a failure and never an absence.
|
|
188
|
+
if (envelope === undefined) return false;
|
|
189
|
+
return verifyReceiptIntegrity(receipt, envelope).ok;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function outcomeMatchesExit(
|
|
194
|
+
journal: EvalRunJournal,
|
|
195
|
+
roots: ReadonlyArray<RunReceipt>,
|
|
196
|
+
processExitCode: number,
|
|
197
|
+
): boolean {
|
|
198
|
+
if (journal.receipts.length !== journal.receiptFiles) return false;
|
|
199
|
+
const selfConsistent = journal.receipts.every(
|
|
200
|
+
(receipt) => (receipt.outcome === "succeeded") === (receipt.exitCode === 0),
|
|
201
|
+
);
|
|
202
|
+
if (!selfConsistent) return false;
|
|
203
|
+
const root = roots.length === 1 ? roots[0] : undefined;
|
|
204
|
+
if (root === undefined) return true;
|
|
205
|
+
return (root.exitCode === 0) === (processExitCode === 0);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function isRootReceipt(receipt: RunReceipt): boolean {
|
|
209
|
+
return receipt.lineage === undefined || receipt.lineage.rootRunId === receipt.runId;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
interface SessionTranscriptInvariants {
|
|
213
|
+
formatVersion: number;
|
|
214
|
+
toolPairsUnmatched: number;
|
|
215
|
+
assistantBetweenCallAndResult: number;
|
|
216
|
+
compactionSummaryPresent: boolean;
|
|
217
|
+
answeredFromPreCompaction: boolean;
|
|
218
|
+
turnsAfterCompaction: number;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Session-ledger and continuity invariants for every transcript this eval item
|
|
223
|
+
* wrote beneath its isolated state directory.
|
|
224
|
+
*
|
|
225
|
+
* A present session whose `current.jsonl` cannot be read, or whose first line
|
|
226
|
+
* is not a readable session header, contributes format version zero. Tool
|
|
227
|
+
* calls and results are paired by id rather than adjacency because one
|
|
228
|
+
* assistant response may emit a batch of calls before any result lands.
|
|
229
|
+
*
|
|
230
|
+
* The whole group is absent when the item wrote no session at all. That is not
|
|
231
|
+
* a clean ledger: it is a surface with no transcript to judge.
|
|
232
|
+
*/
|
|
233
|
+
export function sessionInvariantMetrics(stateDir: string): Record<string, number | boolean> {
|
|
234
|
+
const sessionDirs = findSessionDirs(join(stateDir, "sessions"));
|
|
235
|
+
if (sessionDirs.length === 0) return {};
|
|
236
|
+
|
|
237
|
+
let formatVersion = Number.POSITIVE_INFINITY;
|
|
238
|
+
let toolPairsUnmatched = 0;
|
|
239
|
+
let assistantBetweenCallAndResult = 0;
|
|
240
|
+
let compactionSummaryPresent = false;
|
|
241
|
+
let answeredFromPreCompaction = false;
|
|
242
|
+
let turnsAfterCompaction = 0;
|
|
243
|
+
for (const sessionDir of sessionDirs) {
|
|
244
|
+
const transcript = readSessionTranscript(join(sessionDir, "current.jsonl"));
|
|
245
|
+
formatVersion = Math.min(formatVersion, transcript.formatVersion);
|
|
246
|
+
toolPairsUnmatched += transcript.toolPairsUnmatched;
|
|
247
|
+
assistantBetweenCallAndResult += transcript.assistantBetweenCallAndResult;
|
|
248
|
+
compactionSummaryPresent ||= transcript.compactionSummaryPresent;
|
|
249
|
+
answeredFromPreCompaction ||= transcript.answeredFromPreCompaction;
|
|
250
|
+
turnsAfterCompaction += transcript.turnsAfterCompaction;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
"ledger.formatVersion": formatVersion,
|
|
255
|
+
"ledger.toolPairsUnmatched": toolPairsUnmatched,
|
|
256
|
+
"ledger.assistantBetweenCallAndResult": assistantBetweenCallAndResult,
|
|
257
|
+
"ledger.sessionCount": sessionDirs.length,
|
|
258
|
+
"continuity.compactionSummaryPresent": compactionSummaryPresent,
|
|
259
|
+
"continuity.answeredFromPreCompaction": answeredFromPreCompaction,
|
|
260
|
+
"continuity.turnsAfterCompaction": turnsAfterCompaction,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function findSessionDirs(sessionsRoot: string): string[] {
|
|
265
|
+
try {
|
|
266
|
+
const dirs: string[] = [];
|
|
267
|
+
for (const cwdDir of readdirSync(sessionsRoot, { withFileTypes: true })) {
|
|
268
|
+
if (!cwdDir.isDirectory()) continue;
|
|
269
|
+
const cwdPath = join(sessionsRoot, cwdDir.name);
|
|
270
|
+
try {
|
|
271
|
+
for (const sessionDir of readdirSync(cwdPath, { withFileTypes: true })) {
|
|
272
|
+
if (sessionDir.isDirectory()) dirs.push(join(cwdPath, sessionDir.name));
|
|
273
|
+
}
|
|
274
|
+
} catch {
|
|
275
|
+
// A concurrently unreadable cwd bucket contributes no discoverable
|
|
276
|
+
// session. The reducer remains total and judges every session it found.
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return dirs;
|
|
280
|
+
} catch {
|
|
281
|
+
return [];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function readSessionTranscript(path: string): SessionTranscriptInvariants {
|
|
286
|
+
let lines: string[];
|
|
287
|
+
try {
|
|
288
|
+
lines = readFileSync(path, "utf8").split(/\r?\n/u);
|
|
289
|
+
} catch {
|
|
290
|
+
return {
|
|
291
|
+
formatVersion: 0,
|
|
292
|
+
toolPairsUnmatched: 0,
|
|
293
|
+
assistantBetweenCallAndResult: 0,
|
|
294
|
+
compactionSummaryPresent: false,
|
|
295
|
+
answeredFromPreCompaction: false,
|
|
296
|
+
turnsAfterCompaction: 0,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const entries = lines.map(parseJsonRecord);
|
|
301
|
+
const header = entries[0];
|
|
302
|
+
const formatVersion =
|
|
303
|
+
header?.type === "session" && Number.isInteger(header.version) && (header.version as number) > 0
|
|
304
|
+
? (header.version as number)
|
|
305
|
+
: 0;
|
|
306
|
+
const pendingCalls = new Map<string, number[]>();
|
|
307
|
+
let invalidCalls = 0;
|
|
308
|
+
let orphanResults = 0;
|
|
309
|
+
let assistantGeneration = 0;
|
|
310
|
+
let assistantBetweenCallAndResult = 0;
|
|
311
|
+
const readCalls = new Map<string, string[]>();
|
|
312
|
+
const completedReads: Array<{ path: string; entryIndex: number }> = [];
|
|
313
|
+
let latestCompactionIndex = -1;
|
|
314
|
+
|
|
315
|
+
for (const [entryIndex, entry] of entries.entries()) {
|
|
316
|
+
if (isCompactionSummary(entry)) latestCompactionIndex = entryIndex;
|
|
317
|
+
if (entry?.kind !== "message") continue;
|
|
318
|
+
if (entry.role === "assistant") {
|
|
319
|
+
assistantGeneration += 1;
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (entry.role !== "tool_call" && entry.role !== "tool_result") continue;
|
|
323
|
+
const payload = isRecord(entry.payload) ? entry.payload : undefined;
|
|
324
|
+
const toolCallId = payload?.toolCallId;
|
|
325
|
+
if (entry.role === "tool_call") {
|
|
326
|
+
if (typeof toolCallId !== "string" || toolCallId.length === 0) {
|
|
327
|
+
invalidCalls += 1;
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
const calls = pendingCalls.get(toolCallId) ?? [];
|
|
331
|
+
calls.push(assistantGeneration);
|
|
332
|
+
pendingCalls.set(toolCallId, calls);
|
|
333
|
+
if (payload?.name === "read") {
|
|
334
|
+
const args = isRecord(payload.args) ? payload.args : undefined;
|
|
335
|
+
const readPath = args?.path;
|
|
336
|
+
if (typeof readPath === "string" && readPath.trim().length > 0) {
|
|
337
|
+
const paths = readCalls.get(toolCallId) ?? [];
|
|
338
|
+
paths.push(readPath.trim());
|
|
339
|
+
readCalls.set(toolCallId, paths);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (typeof toolCallId !== "string" || toolCallId.length === 0) {
|
|
346
|
+
orphanResults += 1;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const calls = pendingCalls.get(toolCallId);
|
|
350
|
+
const callGeneration = calls?.shift();
|
|
351
|
+
if (callGeneration === undefined) {
|
|
352
|
+
orphanResults += 1;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (calls?.length === 0) pendingCalls.delete(toolCallId);
|
|
356
|
+
if (assistantGeneration > callGeneration) assistantBetweenCallAndResult += 1;
|
|
357
|
+
const readPaths = readCalls.get(toolCallId);
|
|
358
|
+
const readPath = readPaths?.shift();
|
|
359
|
+
if (readPaths?.length === 0) readCalls.delete(toolCallId);
|
|
360
|
+
if (readPath !== undefined && payload?.isError !== true) completedReads.push({ path: readPath, entryIndex });
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
let danglingCalls = invalidCalls;
|
|
364
|
+
for (const calls of pendingCalls.values()) danglingCalls += calls.length;
|
|
365
|
+
const pathsReadBeforeCompaction = new Set(
|
|
366
|
+
completedReads.filter((read) => read.entryIndex < latestCompactionIndex).map((read) => read.path),
|
|
367
|
+
);
|
|
368
|
+
const answeredFromPreCompaction = completedReads.some(
|
|
369
|
+
(read) => read.entryIndex > latestCompactionIndex && pathsReadBeforeCompaction.has(read.path),
|
|
370
|
+
);
|
|
371
|
+
return {
|
|
372
|
+
formatVersion,
|
|
373
|
+
toolPairsUnmatched: danglingCalls + orphanResults,
|
|
374
|
+
assistantBetweenCallAndResult,
|
|
375
|
+
compactionSummaryPresent: latestCompactionIndex >= 0,
|
|
376
|
+
answeredFromPreCompaction: latestCompactionIndex >= 0 && answeredFromPreCompaction,
|
|
377
|
+
turnsAfterCompaction:
|
|
378
|
+
latestCompactionIndex < 0
|
|
379
|
+
? 0
|
|
380
|
+
: entries.slice(latestCompactionIndex + 1).filter((entry) => entry?.kind === "message").length,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function isCompactionSummary(entry: Record<string, unknown> | undefined): boolean {
|
|
385
|
+
return (
|
|
386
|
+
entry?.kind === "compactionSummary" &&
|
|
387
|
+
typeof entry.summary === "string" &&
|
|
388
|
+
typeof entry.tokensBefore === "number" &&
|
|
389
|
+
Number.isFinite(entry.tokensBefore) &&
|
|
390
|
+
typeof entry.firstKeptTurnId === "string"
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function parseJsonRecord(line: string): Record<string, unknown> | undefined {
|
|
395
|
+
if (line.trim().length === 0) return undefined;
|
|
396
|
+
try {
|
|
397
|
+
const parsed: unknown = JSON.parse(line);
|
|
398
|
+
return isRecord(parsed) ? parsed : undefined;
|
|
399
|
+
} catch {
|
|
400
|
+
return undefined;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Worker processes this item's receipts attested, checked for survival after
|
|
406
|
+
* the item finished.
|
|
407
|
+
*
|
|
408
|
+
* A local or remote worker leads its own process group and abort escalates
|
|
409
|
+
* against the whole group, so a group that outlives the run is a child nobody
|
|
410
|
+
* is going to kill. The attested pid and group id are read from the receipt
|
|
411
|
+
* rather than by walking a process tree: the receipt names exactly the
|
|
412
|
+
* processes this run was responsible for.
|
|
413
|
+
*
|
|
414
|
+
* - `process.attestedWorkers`: workers whose receipt recorded a pid.
|
|
415
|
+
* - `process.orphanedChildren`: how many of them, or their process groups, are
|
|
416
|
+
* still alive. Absent when no receipt carried an attestation, which is the
|
|
417
|
+
* main-agent path: it runs in this process and attests no worker.
|
|
418
|
+
*
|
|
419
|
+
* A pid can in principle be reused between the run ending and this check, which
|
|
420
|
+
* would read as an orphan. That direction is the safe one: this reports a
|
|
421
|
+
* process that may not be Clio's, never a Clio process it failed to see.
|
|
422
|
+
*/
|
|
423
|
+
export function processInvariantMetrics(journal: EvalRunJournal | null): Record<string, number> {
|
|
424
|
+
if (journal === null) return {};
|
|
425
|
+
const attested = journal.receipts.flatMap((receipt) =>
|
|
426
|
+
receipt.attestation === undefined ? [] : [receipt.attestation],
|
|
427
|
+
);
|
|
428
|
+
if (attested.length === 0) return {};
|
|
429
|
+
const orphaned = attested.filter((attestation) => {
|
|
430
|
+
if (isProcessAlive(attestation.pid)) return true;
|
|
431
|
+
// Only a worker that leads its own group can be checked as a group; a pid
|
|
432
|
+
// that is not its own group leader shares a group with its parent, and
|
|
433
|
+
// asking about that group asks about the orchestrator.
|
|
434
|
+
const group = attestation.processGroupId;
|
|
435
|
+
return group !== null && group === attestation.pid && isProcessAlive(-group);
|
|
436
|
+
});
|
|
437
|
+
return { "process.attestedWorkers": attested.length, "process.orphanedChildren": orphaned.length };
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function isProcessAlive(pid: number): boolean {
|
|
441
|
+
if (!Number.isInteger(pid) || pid === 0) return false;
|
|
442
|
+
try {
|
|
443
|
+
process.kill(pid, 0);
|
|
444
|
+
return true;
|
|
445
|
+
} catch (error) {
|
|
446
|
+
// ESRCH is the one answer that means gone. EPERM means it exists and
|
|
447
|
+
// belongs to someone else, which is still alive.
|
|
448
|
+
return (error as NodeJS.ErrnoException).code !== "ESRCH";
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Write-boundary invariants, read from the verdicts an item's Clio sealed under
|
|
454
|
+
* `write-boundaries/<rootId>/` in its own state directory.
|
|
455
|
+
*
|
|
456
|
+
* Enforcement is detect-and-rollback, so the promise is not "nothing was
|
|
457
|
+
* written outside the allowlist". It is that Clio saw what was written, named
|
|
458
|
+
* it with the typed reason, put back what git could put back, and left a signed
|
|
459
|
+
* record of the whole thing against the baseline it measured. A step that
|
|
460
|
+
* escaped its allowlist and passed anyway is the failure these catch.
|
|
461
|
+
*
|
|
462
|
+
* - `boundary.verdictCount`: verdict files this item's Clio wrote.
|
|
463
|
+
* - `boundary.verdictSealed`: every one of them parsed and carries both a
|
|
464
|
+
* digest and the baseline commit it was computed against. False when any file
|
|
465
|
+
* is unreadable: a verdict that cannot be read is a record that cannot be
|
|
466
|
+
* audited, never an absence.
|
|
467
|
+
* - `boundary.violationsDetected`: verdicts whose typed reason is
|
|
468
|
+
* `writes_boundary_violation`.
|
|
469
|
+
* - `boundary.violationsRolledBack`: verdicts that put the repository back.
|
|
470
|
+
* - `boundary.rollbackIncomplete`: verdicts that could not, because a path was
|
|
471
|
+
* already dirty when the snapshot was taken. This is the honest failure, and
|
|
472
|
+
* counting it is how the honest failure stays distinguishable from a clean
|
|
473
|
+
* one.
|
|
474
|
+
*
|
|
475
|
+
* The whole group is absent when the item sealed no verdicts at all, because a
|
|
476
|
+
* run that enforced no boundary answered none of these questions.
|
|
477
|
+
*/
|
|
478
|
+
export function writeBoundaryInvariantMetrics(stateDir: string): Record<string, number | boolean> {
|
|
479
|
+
const files = findWriteBoundaryVerdicts(join(stateDir, "write-boundaries"));
|
|
480
|
+
if (files.length === 0) return {};
|
|
481
|
+
|
|
482
|
+
let sealed = true;
|
|
483
|
+
let violationsDetected = 0;
|
|
484
|
+
let violationsRolledBack = 0;
|
|
485
|
+
let rollbackIncomplete = 0;
|
|
486
|
+
for (const file of files) {
|
|
487
|
+
const verdict = parseJsonFile(file);
|
|
488
|
+
if (verdict === undefined) {
|
|
489
|
+
sealed = false;
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
if (!isNonEmptyString(verdict.digest) || !isNonEmptyString(verdict.baselineHead)) sealed = false;
|
|
493
|
+
if (verdict.reason === WRITES_BOUNDARY_VIOLATION) violationsDetected += 1;
|
|
494
|
+
if (verdict.status === "rolled-back") violationsRolledBack += 1;
|
|
495
|
+
if (verdict.status === "rollback-incomplete") rollbackIncomplete += 1;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
"boundary.verdictCount": files.length,
|
|
500
|
+
"boundary.verdictSealed": sealed,
|
|
501
|
+
"boundary.violationsDetected": violationsDetected,
|
|
502
|
+
"boundary.violationsRolledBack": violationsRolledBack,
|
|
503
|
+
"boundary.rollbackIncomplete": rollbackIncomplete,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** Kept as a literal so the reducer reads the wire value, not an import cycle through dispatch. */
|
|
508
|
+
const WRITES_BOUNDARY_VIOLATION = "writes_boundary_violation";
|
|
509
|
+
|
|
510
|
+
function findWriteBoundaryVerdicts(root: string): string[] {
|
|
511
|
+
const files: string[] = [];
|
|
512
|
+
try {
|
|
513
|
+
for (const rootDir of readdirSync(root, { withFileTypes: true })) {
|
|
514
|
+
if (!rootDir.isDirectory()) continue;
|
|
515
|
+
const dir = join(root, rootDir.name);
|
|
516
|
+
try {
|
|
517
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
518
|
+
if (entry.isFile() && entry.name.endsWith(".json")) files.push(join(dir, entry.name));
|
|
519
|
+
}
|
|
520
|
+
} catch {
|
|
521
|
+
// A concurrently unreadable bucket contributes no discoverable verdict.
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
} catch {
|
|
525
|
+
return [];
|
|
526
|
+
}
|
|
527
|
+
return files;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function parseJsonFile(path: string): Record<string, unknown> | undefined {
|
|
531
|
+
try {
|
|
532
|
+
const parsed: unknown = JSON.parse(readFileSync(path, "utf8"));
|
|
533
|
+
return isRecord(parsed) ? parsed : undefined;
|
|
534
|
+
} catch {
|
|
535
|
+
return undefined;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
function isNonEmptyString(value: unknown): boolean {
|
|
540
|
+
return typeof value === "string" && value.length > 0;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
export interface EvalStreamInvariants {
|
|
544
|
+
/** `message_update` events seen on the wire. A diagnostic, not a promise: the two headless surfaces name increments differently. */
|
|
545
|
+
messageUpdateCount: number;
|
|
546
|
+
/** Events that republished a cumulative snapshot instead of an increment. */
|
|
547
|
+
cumulativeSnapshots: number;
|
|
548
|
+
/** Assistant `message_end` events carrying provider usage. */
|
|
549
|
+
usageMessages: number;
|
|
550
|
+
/** Assistant `message_end` events whose provider response id was already reported. */
|
|
551
|
+
repeatedResponses: number;
|
|
552
|
+
/** Assistant `message_end` events carrying a response id at all. */
|
|
553
|
+
identifiedResponses: number;
|
|
554
|
+
/** Total tokens folded from `message_end`, the per-message view. */
|
|
555
|
+
messageTokenTotal: number;
|
|
556
|
+
/** Total tokens summed from `agent_end`, the per-segment view. */
|
|
557
|
+
segmentTokenTotal: number;
|
|
558
|
+
/** `agent_end` events that reported measured usage. */
|
|
559
|
+
measuredSegments: number;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export const EMPTY_STREAM_INVARIANTS: EvalStreamInvariants = {
|
|
563
|
+
messageUpdateCount: 0,
|
|
564
|
+
cumulativeSnapshots: 0,
|
|
565
|
+
usageMessages: 0,
|
|
566
|
+
repeatedResponses: 0,
|
|
567
|
+
identifiedResponses: 0,
|
|
568
|
+
messageTokenTotal: 0,
|
|
569
|
+
segmentTokenTotal: 0,
|
|
570
|
+
measuredSegments: 0,
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Sum the readings of several child processes in one item. Response ids are
|
|
575
|
+
* per-run, so a repeat can only be a repeat within one stream; the counts
|
|
576
|
+
* therefore add without needing to compare ids across processes.
|
|
577
|
+
*/
|
|
578
|
+
export function addStreamInvariants(left: EvalStreamInvariants, right: EvalStreamInvariants): EvalStreamInvariants {
|
|
579
|
+
return {
|
|
580
|
+
messageUpdateCount: left.messageUpdateCount + right.messageUpdateCount,
|
|
581
|
+
cumulativeSnapshots: left.cumulativeSnapshots + right.cumulativeSnapshots,
|
|
582
|
+
usageMessages: left.usageMessages + right.usageMessages,
|
|
583
|
+
repeatedResponses: left.repeatedResponses + right.repeatedResponses,
|
|
584
|
+
identifiedResponses: left.identifiedResponses + right.identifiedResponses,
|
|
585
|
+
messageTokenTotal: left.messageTokenTotal + right.messageTokenTotal,
|
|
586
|
+
segmentTokenTotal: left.segmentTokenTotal + right.segmentTokenTotal,
|
|
587
|
+
measuredSegments: left.measuredSegments + right.measuredSegments,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
export interface EvalStreamInvariantFold {
|
|
592
|
+
/** Feed a raw stdout chunk; partial trailing lines are held until completed. */
|
|
593
|
+
push(chunk: string): void;
|
|
594
|
+
invariants(): EvalStreamInvariants;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Fold the headless `--json` stream's own structural promises as it arrives.
|
|
599
|
+
*
|
|
600
|
+
* Folding live rather than reading the stored artifact is what makes these
|
|
601
|
+
* readings trustworthy: the operator-facing stdout keeps only a bounded head
|
|
602
|
+
* and tail, and the one regression these catch is a verbose run republishing
|
|
603
|
+
* content, which is exactly the run whose middle does not survive.
|
|
604
|
+
*/
|
|
605
|
+
export function createStreamInvariantFold(): EvalStreamInvariantFold {
|
|
606
|
+
const state: EvalStreamInvariants = {
|
|
607
|
+
messageUpdateCount: 0,
|
|
608
|
+
cumulativeSnapshots: 0,
|
|
609
|
+
usageMessages: 0,
|
|
610
|
+
repeatedResponses: 0,
|
|
611
|
+
identifiedResponses: 0,
|
|
612
|
+
messageTokenTotal: 0,
|
|
613
|
+
segmentTokenTotal: 0,
|
|
614
|
+
measuredSegments: 0,
|
|
615
|
+
};
|
|
616
|
+
const seenResponses = new Set<string>();
|
|
617
|
+
let pending = "";
|
|
618
|
+
|
|
619
|
+
const consume = (line: string): void => {
|
|
620
|
+
if (line.trim().length === 0) return;
|
|
621
|
+
let event: unknown;
|
|
622
|
+
try {
|
|
623
|
+
event = JSON.parse(line);
|
|
624
|
+
} catch {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
if (!isRecord(event)) return;
|
|
628
|
+
if (event.type === "message_update") {
|
|
629
|
+
state.messageUpdateCount += 1;
|
|
630
|
+
// The increment is the only part of an update that is new. A top-level
|
|
631
|
+
// message or a nested partial is the growing snapshot of a message
|
|
632
|
+
// whose completed form follows, and republishing it per delta is
|
|
633
|
+
// quadratic in the length of the answer.
|
|
634
|
+
const assistantEvent = isRecord(event.assistantMessageEvent) ? event.assistantMessageEvent : undefined;
|
|
635
|
+
if (event.message !== undefined || assistantEvent?.partial !== undefined) state.cumulativeSnapshots += 1;
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
if (event.type === "agent_end") {
|
|
639
|
+
// A segment's transcript is every message that already crossed as its
|
|
640
|
+
// own `message_end`. The summary is what a segment adds.
|
|
641
|
+
if (Array.isArray(event.messages)) state.cumulativeSnapshots += 1;
|
|
642
|
+
const usage = isRecord(event.usage) ? event.usage : undefined;
|
|
643
|
+
if (usage === undefined || usage.measured !== true) return;
|
|
644
|
+
state.measuredSegments += 1;
|
|
645
|
+
state.segmentTokenTotal += numberField(usage, "totalTokens");
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
if (event.type !== "message_end") return;
|
|
649
|
+
const message = isRecord(event.message) ? event.message : undefined;
|
|
650
|
+
if (message === undefined || message.role !== "assistant") return;
|
|
651
|
+
const usage = isRecord(message.usage) ? message.usage : undefined;
|
|
652
|
+
if (usage === undefined) return;
|
|
653
|
+
state.usageMessages += 1;
|
|
654
|
+
const input = numberField(usage, "input");
|
|
655
|
+
const output = numberField(usage, "output");
|
|
656
|
+
const cacheRead = numberField(usage, "cacheRead");
|
|
657
|
+
const cacheWrite = numberField(usage, "cacheWrite");
|
|
658
|
+
const totalTokens = numberField(usage, "totalTokens");
|
|
659
|
+
state.messageTokenTotal += totalTokens > 0 ? totalTokens : input + output + cacheRead + cacheWrite;
|
|
660
|
+
const responseId = message.responseId;
|
|
661
|
+
if (typeof responseId !== "string" || responseId.length === 0) return;
|
|
662
|
+
state.identifiedResponses += 1;
|
|
663
|
+
if (seenResponses.has(responseId)) state.repeatedResponses += 1;
|
|
664
|
+
seenResponses.add(responseId);
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
return {
|
|
668
|
+
push(chunk: string): void {
|
|
669
|
+
pending += chunk;
|
|
670
|
+
for (;;) {
|
|
671
|
+
const newline = pending.indexOf("\n");
|
|
672
|
+
if (newline === -1) break;
|
|
673
|
+
consume(pending.slice(0, newline).replace(/\r$/u, ""));
|
|
674
|
+
pending = pending.slice(newline + 1);
|
|
675
|
+
}
|
|
676
|
+
},
|
|
677
|
+
invariants(): EvalStreamInvariants {
|
|
678
|
+
if (pending.length > 0) {
|
|
679
|
+
consume(pending.replace(/\r$/u, ""));
|
|
680
|
+
pending = "";
|
|
681
|
+
}
|
|
682
|
+
return { ...state };
|
|
683
|
+
},
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Metrics for the wire stream's structural promises.
|
|
689
|
+
*
|
|
690
|
+
* - `stream.cumulativeSnapshots`: content crosses the wire once, as an
|
|
691
|
+
* increment while it streams and as one completed message when it lands. An
|
|
692
|
+
* event that republishes a growing partial message, or a segment that
|
|
693
|
+
* republishes the transcript every message of which already crossed, is that
|
|
694
|
+
* promise broken. This is the one reading both headless surfaces answer: the
|
|
695
|
+
* main agent publishes increments as `text_delta` and a worker publishes them
|
|
696
|
+
* as `message_update` deltas, so `stream.messageUpdateCount` beside it is a
|
|
697
|
+
* diagnostic count rather than a promise.
|
|
698
|
+
* - `stream.usageDoubleCounted`: true when one provider response was reported
|
|
699
|
+
* as a completed assistant message more than once, which is the shape that
|
|
700
|
+
* makes a run's cost read higher than it was. Absent when no message carried
|
|
701
|
+
* a response id, because with nothing to key on there is nothing to judge.
|
|
702
|
+
* - `stream.segmentUsageMatchesMessages`: the per-message view and the
|
|
703
|
+
* per-segment view of the same run agree on its token total. Two
|
|
704
|
+
* independently computed accounts disagreeing means one of them is wrong
|
|
705
|
+
* about what the run cost. Absent when no segment reported measured usage.
|
|
706
|
+
*/
|
|
707
|
+
export function streamInvariantMetrics(stream: EvalStreamInvariants): Record<string, number | boolean> {
|
|
708
|
+
return {
|
|
709
|
+
"stream.messageUpdateCount": stream.messageUpdateCount,
|
|
710
|
+
"stream.cumulativeSnapshots": stream.cumulativeSnapshots,
|
|
711
|
+
...(stream.identifiedResponses === 0 ? {} : { "stream.usageDoubleCounted": stream.repeatedResponses > 0 }),
|
|
712
|
+
...(stream.measuredSegments === 0
|
|
713
|
+
? {}
|
|
714
|
+
: { "stream.segmentUsageMatchesMessages": stream.segmentTokenTotal === stream.messageTokenTotal }),
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
function numberField(record: Record<string, unknown>, field: string): number {
|
|
719
|
+
const value = record[field];
|
|
720
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
function isReceiptShaped(value: unknown): value is RunReceipt {
|
|
724
|
+
if (!isRecord(value)) return false;
|
|
725
|
+
return (
|
|
726
|
+
typeof value.runId === "string" &&
|
|
727
|
+
typeof value.agentId === "string" &&
|
|
728
|
+
typeof value.exitCode === "number" &&
|
|
729
|
+
typeof value.outcome === "string" &&
|
|
730
|
+
isRecord(value.integrity)
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
735
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
736
|
+
}
|