@prismatic-io/lux 0.0.2-preview.4 → 0.0.2-preview.40
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/lib/answerers/claude-code/index.d.ts +15 -3
- package/lib/answerers/claude-code/index.d.ts.map +1 -1
- package/lib/answerers/claude-code/index.js +6 -5
- package/lib/answerers/claude-code/index.js.map +1 -1
- package/lib/answerers/persona/index.d.ts +44 -5
- package/lib/answerers/persona/index.d.ts.map +1 -1
- package/lib/answerers/persona/index.js +60 -34
- package/lib/answerers/persona/index.js.map +1 -1
- package/lib/answerers/terminal/index.d.ts +9 -3
- package/lib/answerers/terminal/index.d.ts.map +1 -1
- package/lib/answerers/terminal/index.js +6 -4
- package/lib/answerers/terminal/index.js.map +1 -1
- package/lib/assertions/authoring.d.ts +2 -2
- package/lib/assertions/authoring.d.ts.map +1 -1
- package/lib/assertions/authoring.js.map +1 -1
- package/lib/assertions/core/command-exits-zero.d.ts +5 -2
- package/lib/assertions/core/command-exits-zero.d.ts.map +1 -1
- package/lib/assertions/core/command-exits-zero.js +59 -14
- package/lib/assertions/core/command-exits-zero.js.map +1 -1
- package/lib/assertions/core/event-checks.d.ts +3 -0
- package/lib/assertions/core/event-checks.d.ts.map +1 -1
- package/lib/assertions/core/event-checks.js +49 -3
- package/lib/assertions/core/event-checks.js.map +1 -1
- package/lib/assertions/core/file-checks.d.ts +6 -0
- package/lib/assertions/core/file-checks.d.ts.map +1 -1
- package/lib/assertions/core/index.d.ts.map +1 -1
- package/lib/assertions/core/index.js +2 -1
- package/lib/assertions/core/index.js.map +1 -1
- package/lib/assertions/core/json-pointer-equals.d.ts +1 -0
- package/lib/assertions/core/json-pointer-equals.d.ts.map +1 -1
- package/lib/assertions/core/output-checks.d.ts +3 -0
- package/lib/assertions/core/output-checks.d.ts.map +1 -1
- package/lib/assertions/core/predicate.d.ts +1 -0
- package/lib/assertions/core/predicate.d.ts.map +1 -1
- package/lib/assertions/core/resource-checks.d.ts +25 -0
- package/lib/assertions/core/resource-checks.d.ts.map +1 -1
- package/lib/assertions/core/resource-checks.js +35 -5
- package/lib/assertions/core/resource-checks.js.map +1 -1
- package/lib/assertions/core/safe-regex.d.ts.map +1 -1
- package/lib/assertions/core/safe-regex.js +7 -1
- package/lib/assertions/core/safe-regex.js.map +1 -1
- package/lib/assertions/rubric/evidence.d.ts +88 -0
- package/lib/assertions/rubric/evidence.d.ts.map +1 -0
- package/lib/assertions/rubric/evidence.js +75 -0
- package/lib/assertions/rubric/evidence.js.map +1 -0
- package/lib/assertions/rubric/index.d.ts +88 -34
- package/lib/assertions/rubric/index.d.ts.map +1 -1
- package/lib/assertions/rubric/index.js +59 -43
- package/lib/assertions/rubric/index.js.map +1 -1
- package/lib/assertions/rubric/internal.d.ts +30 -5
- package/lib/assertions/rubric/internal.d.ts.map +1 -1
- package/lib/assertions/rubric/internal.js +203 -41
- package/lib/assertions/rubric/internal.js.map +1 -1
- package/lib/authoring.d.ts +37 -2
- package/lib/authoring.d.ts.map +1 -1
- package/lib/authoring.js +36 -1
- package/lib/authoring.js.map +1 -1
- package/lib/cli/bin.js +2 -13
- package/lib/cli/bin.js.map +1 -1
- package/lib/cli/command-runtime.d.ts +3 -3
- package/lib/cli/command-runtime.d.ts.map +1 -1
- package/lib/cli/command-runtime.js +17 -6
- package/lib/cli/command-runtime.js.map +1 -1
- package/lib/cli/doctor.d.ts +55 -0
- package/lib/cli/doctor.d.ts.map +1 -0
- package/lib/cli/doctor.js +14 -0
- package/lib/cli/doctor.js.map +1 -0
- package/lib/cli/harness-plan.d.ts +27 -0
- package/lib/cli/harness-plan.d.ts.map +1 -0
- package/lib/cli/harness-plan.js +75 -0
- package/lib/cli/harness-plan.js.map +1 -0
- package/lib/cli/init-templates.d.ts +11 -0
- package/lib/cli/init-templates.d.ts.map +1 -0
- package/lib/cli/init-templates.js +215 -0
- package/lib/cli/init-templates.js.map +1 -0
- package/lib/cli/init.d.ts +10 -0
- package/lib/cli/init.d.ts.map +1 -1
- package/lib/cli/init.js +34 -173
- package/lib/cli/init.js.map +1 -1
- package/lib/cli/output-schemas.d.ts +1412 -0
- package/lib/cli/output-schemas.d.ts.map +1 -0
- package/lib/cli/output-schemas.js +94 -0
- package/lib/cli/output-schemas.js.map +1 -0
- package/lib/cli/program.d.ts +140 -12
- package/lib/cli/program.d.ts.map +1 -1
- package/lib/cli/program.js +783 -650
- package/lib/cli/program.js.map +1 -1
- package/lib/cli/render/format.d.ts.map +1 -1
- package/lib/cli/render/format.js +1 -1
- package/lib/cli/render/format.js.map +1 -1
- package/lib/cli/render/reporter.d.ts.map +1 -1
- package/lib/cli/render/reporter.js +35 -8
- package/lib/cli/render/reporter.js.map +1 -1
- package/lib/cli/run-options.d.ts +19 -4
- package/lib/cli/run-options.d.ts.map +1 -1
- package/lib/cli/run-options.js +100 -19
- package/lib/cli/run-options.js.map +1 -1
- package/lib/cli/view.d.ts +15 -0
- package/lib/cli/view.d.ts.map +1 -0
- package/lib/cli/view.js +168 -0
- package/lib/cli/view.js.map +1 -0
- package/lib/container/driver.d.ts +27 -0
- package/lib/container/driver.d.ts.map +1 -0
- package/lib/container/driver.js +199 -0
- package/lib/container/driver.js.map +1 -0
- package/lib/container/paths.d.ts +3 -0
- package/lib/container/paths.d.ts.map +1 -0
- package/lib/container/paths.js +27 -0
- package/lib/container/paths.js.map +1 -0
- package/lib/container/protocol.d.ts +12 -0
- package/lib/container/protocol.d.ts.map +1 -0
- package/lib/container/protocol.js +38 -0
- package/lib/container/protocol.js.map +1 -0
- package/lib/container/resources.d.ts +14 -0
- package/lib/container/resources.d.ts.map +1 -0
- package/lib/container/resources.js +141 -0
- package/lib/container/resources.js.map +1 -0
- package/lib/container/worker.d.ts +2 -0
- package/lib/container/worker.d.ts.map +1 -0
- package/lib/container/worker.js +85 -0
- package/lib/container/worker.js.map +1 -0
- package/lib/core/action-events.d.ts +29 -0
- package/lib/core/action-events.d.ts.map +1 -0
- package/lib/core/action-events.js +51 -0
- package/lib/core/action-events.js.map +1 -0
- package/lib/core/agent-activity.d.ts +49 -0
- package/lib/core/agent-activity.d.ts.map +1 -0
- package/lib/core/agent-activity.js +206 -0
- package/lib/core/agent-activity.js.map +1 -0
- package/lib/core/agent-environment.d.ts +5 -0
- package/lib/core/agent-environment.d.ts.map +1 -0
- package/lib/core/agent-environment.js +47 -0
- package/lib/core/agent-environment.js.map +1 -0
- package/lib/core/agent-events.d.ts +26 -0
- package/lib/core/agent-events.d.ts.map +1 -0
- package/lib/core/agent-events.js +13 -0
- package/lib/core/agent-events.js.map +1 -0
- package/lib/core/annotation.d.ts +6 -2
- package/lib/core/annotation.d.ts.map +1 -1
- package/lib/core/annotation.js +2 -1
- package/lib/core/annotation.js.map +1 -1
- package/lib/core/answerer.d.ts +12 -0
- package/lib/core/answerer.d.ts.map +1 -1
- package/lib/core/answerer.js +2 -0
- package/lib/core/answerer.js.map +1 -1
- package/lib/core/artifact-evidence.d.ts +6 -1
- package/lib/core/artifact-evidence.d.ts.map +1 -1
- package/lib/core/artifact-evidence.js +27 -6
- package/lib/core/artifact-evidence.js.map +1 -1
- package/lib/core/assertion.d.ts +10 -4
- package/lib/core/assertion.d.ts.map +1 -1
- package/lib/core/assertion.js +8 -2
- package/lib/core/assertion.js.map +1 -1
- package/lib/core/case-defaults.d.ts +16 -0
- package/lib/core/case-defaults.d.ts.map +1 -0
- package/lib/core/case-defaults.js +42 -0
- package/lib/core/case-defaults.js.map +1 -0
- package/lib/core/case.d.ts +120 -6
- package/lib/core/case.d.ts.map +1 -1
- package/lib/core/case.js +51 -5
- package/lib/core/case.js.map +1 -1
- package/lib/core/command-verification.d.ts +10 -0
- package/lib/core/command-verification.d.ts.map +1 -0
- package/lib/core/command-verification.js +66 -0
- package/lib/core/command-verification.js.map +1 -0
- package/lib/core/driver-execution.d.ts +83 -0
- package/lib/core/driver-execution.d.ts.map +1 -0
- package/lib/core/driver-execution.js +72 -0
- package/lib/core/driver-execution.js.map +1 -0
- package/lib/core/driver-metrics.d.ts +98 -0
- package/lib/core/driver-metrics.d.ts.map +1 -0
- package/lib/core/driver-metrics.js +36 -0
- package/lib/core/driver-metrics.js.map +1 -0
- package/lib/core/driver.d.ts +64 -0
- package/lib/core/driver.d.ts.map +1 -1
- package/lib/core/driver.js +28 -0
- package/lib/core/driver.js.map +1 -1
- package/lib/core/duration.d.ts +5 -0
- package/lib/core/duration.d.ts.map +1 -0
- package/lib/core/duration.js +49 -0
- package/lib/core/duration.js.map +1 -0
- package/lib/core/environment.d.ts +18 -0
- package/lib/core/environment.d.ts.map +1 -0
- package/lib/core/environment.js +21 -0
- package/lib/core/environment.js.map +1 -0
- package/lib/core/evaluation-clusters.d.ts +17 -0
- package/lib/core/evaluation-clusters.d.ts.map +1 -0
- package/lib/core/evaluation-clusters.js +23 -0
- package/lib/core/evaluation-clusters.js.map +1 -0
- package/lib/core/events.d.ts +34 -0
- package/lib/core/events.d.ts.map +1 -1
- package/lib/core/events.js +11 -2
- package/lib/core/events.js.map +1 -1
- package/lib/core/experiment.d.ts +33 -2
- package/lib/core/experiment.d.ts.map +1 -1
- package/lib/core/experiment.js +40 -19
- package/lib/core/experiment.js.map +1 -1
- package/lib/core/file-tree.d.ts +7 -0
- package/lib/core/file-tree.d.ts.map +1 -0
- package/lib/core/file-tree.js +35 -0
- package/lib/core/file-tree.js.map +1 -0
- package/lib/core/global-id.d.ts +6 -0
- package/lib/core/global-id.d.ts.map +1 -0
- package/lib/core/global-id.js +17 -0
- package/lib/core/global-id.js.map +1 -0
- package/lib/core/harness-catalog.d.ts +35 -0
- package/lib/core/harness-catalog.d.ts.map +1 -0
- package/lib/core/harness-catalog.js +45 -0
- package/lib/core/harness-catalog.js.map +1 -0
- package/lib/core/harness-catalogs/antigravity.d.ts +11 -0
- package/lib/core/harness-catalogs/antigravity.d.ts.map +1 -0
- package/lib/core/harness-catalogs/antigravity.js +23 -0
- package/lib/core/harness-catalogs/antigravity.js.map +1 -0
- package/lib/core/harness-catalogs/claude-code.d.ts +12 -0
- package/lib/core/harness-catalogs/claude-code.d.ts.map +1 -0
- package/lib/core/harness-catalogs/claude-code.js +24 -0
- package/lib/core/harness-catalogs/claude-code.js.map +1 -0
- package/lib/core/harness-catalogs/codex.d.ts +11 -0
- package/lib/core/harness-catalogs/codex.d.ts.map +1 -0
- package/lib/core/harness-catalogs/codex.js +26 -0
- package/lib/core/harness-catalogs/codex.js.map +1 -0
- package/lib/core/harness-catalogs/copilot.d.ts +29 -0
- package/lib/core/harness-catalogs/copilot.d.ts.map +1 -0
- package/lib/core/harness-catalogs/copilot.js +45 -0
- package/lib/core/harness-catalogs/copilot.js.map +1 -0
- package/lib/core/harness-catalogs/cursor.d.ts +2 -0
- package/lib/core/harness-catalogs/cursor.d.ts.map +1 -0
- package/lib/core/harness-catalogs/cursor.js +13 -0
- package/lib/core/harness-catalogs/cursor.js.map +1 -0
- package/lib/core/harness-catalogs/grok-build.d.ts +7 -0
- package/lib/core/harness-catalogs/grok-build.d.ts.map +1 -0
- package/lib/core/harness-catalogs/grok-build.js +18 -0
- package/lib/core/harness-catalogs/grok-build.js.map +1 -0
- package/lib/core/harness-catalogs/index.d.ts +73 -0
- package/lib/core/harness-catalogs/index.d.ts.map +1 -0
- package/lib/core/harness-catalogs/index.js +17 -0
- package/lib/core/harness-catalogs/index.js.map +1 -0
- package/lib/core/harness-matrix.d.ts +154 -0
- package/lib/core/harness-matrix.d.ts.map +1 -0
- package/lib/core/harness-matrix.js +204 -0
- package/lib/core/harness-matrix.js.map +1 -0
- package/lib/core/index.d.ts +12 -0
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +12 -0
- package/lib/core/index.js.map +1 -1
- package/lib/core/lifecycle-fixtures.d.ts.map +1 -1
- package/lib/core/lifecycle-fixtures.js +4 -2
- package/lib/core/lifecycle-fixtures.js.map +1 -1
- package/lib/core/model-cli.d.ts +9 -11
- package/lib/core/model-cli.d.ts.map +1 -1
- package/lib/core/model-cli.js +39 -22
- package/lib/core/model-cli.js.map +1 -1
- package/lib/core/platform-process.d.ts +7 -2
- package/lib/core/platform-process.d.ts.map +1 -1
- package/lib/core/platform-process.js +54 -16
- package/lib/core/platform-process.js.map +1 -1
- package/lib/core/reference-defaults.d.ts +5 -0
- package/lib/core/reference-defaults.d.ts.map +1 -0
- package/lib/core/reference-defaults.js +42 -0
- package/lib/core/reference-defaults.js.map +1 -0
- package/lib/core/rubric.d.ts +1 -0
- package/lib/core/rubric.d.ts.map +1 -1
- package/lib/core/run.d.ts +292 -1
- package/lib/core/run.d.ts.map +1 -1
- package/lib/core/run.js +27 -0
- package/lib/core/run.js.map +1 -1
- package/lib/core/secure-copy.d.ts.map +1 -0
- package/lib/core/secure-copy.js.map +1 -0
- package/lib/core/usage.d.ts +5 -0
- package/lib/core/usage.d.ts.map +1 -1
- package/lib/core/usage.js +3 -0
- package/lib/core/usage.js.map +1 -1
- package/lib/core/wire.d.ts +11 -0
- package/lib/core/wire.d.ts.map +1 -1
- package/lib/drivers/antigravity/artifacts.d.ts +2 -0
- package/lib/drivers/antigravity/artifacts.d.ts.map +1 -0
- package/lib/drivers/antigravity/artifacts.js +33 -0
- package/lib/drivers/antigravity/artifacts.js.map +1 -0
- package/lib/drivers/antigravity/config.d.ts +88 -0
- package/lib/drivers/antigravity/config.d.ts.map +1 -0
- package/lib/drivers/antigravity/config.js +87 -0
- package/lib/drivers/antigravity/config.js.map +1 -0
- package/lib/drivers/antigravity/events.d.ts +4 -0
- package/lib/drivers/antigravity/events.d.ts.map +1 -0
- package/lib/drivers/antigravity/events.js +241 -0
- package/lib/drivers/antigravity/events.js.map +1 -0
- package/lib/drivers/antigravity/index.d.ts +114 -0
- package/lib/drivers/antigravity/index.d.ts.map +1 -0
- package/lib/drivers/antigravity/index.js +113 -0
- package/lib/drivers/antigravity/index.js.map +1 -0
- package/lib/drivers/antigravity/runtime.d.ts +7 -0
- package/lib/drivers/antigravity/runtime.d.ts.map +1 -0
- package/lib/drivers/antigravity/runtime.js +83 -0
- package/lib/drivers/antigravity/runtime.js.map +1 -0
- package/lib/drivers/claude-code/deferred-process.d.ts +17 -0
- package/lib/drivers/claude-code/deferred-process.d.ts.map +1 -0
- package/lib/drivers/claude-code/deferred-process.js +108 -0
- package/lib/drivers/claude-code/deferred-process.js.map +1 -0
- package/lib/drivers/claude-code/index.d.ts +187 -10
- package/lib/drivers/claude-code/index.d.ts.map +1 -1
- package/lib/drivers/claude-code/index.js +197 -252
- package/lib/drivers/claude-code/index.js.map +1 -1
- package/lib/drivers/claude-code/isolation.d.ts +8 -0
- package/lib/drivers/claude-code/isolation.d.ts.map +1 -0
- package/lib/drivers/claude-code/isolation.js +199 -0
- package/lib/drivers/claude-code/isolation.js.map +1 -0
- package/lib/drivers/claude-code/parse-events.d.ts.map +1 -1
- package/lib/drivers/claude-code/parse-events.js +73 -8
- package/lib/drivers/claude-code/parse-events.js.map +1 -1
- package/lib/drivers/codex/app-events.d.ts +9 -2
- package/lib/drivers/codex/app-events.d.ts.map +1 -1
- package/lib/drivers/codex/app-events.js +104 -12
- package/lib/drivers/codex/app-events.js.map +1 -1
- package/lib/drivers/codex/config.d.ts +69 -5
- package/lib/drivers/codex/config.d.ts.map +1 -1
- package/lib/drivers/codex/config.js +48 -8
- package/lib/drivers/codex/config.js.map +1 -1
- package/lib/drivers/codex/exec-events.d.ts +4 -0
- package/lib/drivers/codex/exec-events.d.ts.map +1 -0
- package/lib/drivers/codex/exec-events.js +230 -0
- package/lib/drivers/codex/exec-events.js.map +1 -0
- package/lib/drivers/codex/index.d.ts +142 -4
- package/lib/drivers/codex/index.d.ts.map +1 -1
- package/lib/drivers/codex/index.js +114 -276
- package/lib/drivers/codex/index.js.map +1 -1
- package/lib/drivers/copilot/config.d.ts +84 -0
- package/lib/drivers/copilot/config.d.ts.map +1 -0
- package/lib/drivers/copilot/config.js +57 -0
- package/lib/drivers/copilot/config.js.map +1 -0
- package/lib/drivers/copilot/index.d.ts +107 -0
- package/lib/drivers/copilot/index.d.ts.map +1 -0
- package/lib/drivers/copilot/index.js +268 -0
- package/lib/drivers/copilot/index.js.map +1 -0
- package/lib/drivers/cursor/config.d.ts +28 -0
- package/lib/drivers/cursor/config.d.ts.map +1 -0
- package/lib/drivers/cursor/config.js +28 -0
- package/lib/drivers/cursor/config.js.map +1 -0
- package/lib/drivers/cursor/index.d.ts +44 -0
- package/lib/drivers/cursor/index.d.ts.map +1 -0
- package/lib/drivers/cursor/index.js +286 -0
- package/lib/drivers/cursor/index.js.map +1 -0
- package/lib/drivers/cursor/interaction.d.ts +6 -0
- package/lib/drivers/cursor/interaction.d.ts.map +1 -0
- package/lib/drivers/cursor/interaction.js +55 -0
- package/lib/drivers/cursor/interaction.js.map +1 -0
- package/lib/drivers/grok-build/config.d.ts +68 -0
- package/lib/drivers/grok-build/config.d.ts.map +1 -0
- package/lib/drivers/grok-build/config.js +40 -0
- package/lib/drivers/grok-build/config.js.map +1 -0
- package/lib/drivers/grok-build/index.d.ts +87 -0
- package/lib/drivers/grok-build/index.d.ts.map +1 -0
- package/lib/drivers/grok-build/index.js +293 -0
- package/lib/drivers/grok-build/index.js.map +1 -0
- package/lib/drivers/mcp/index.d.ts +37 -4
- package/lib/drivers/mcp/index.d.ts.map +1 -1
- package/lib/drivers/mcp/index.js +25 -11
- package/lib/drivers/mcp/index.js.map +1 -1
- package/lib/drivers/shared/acp-events.d.ts +15 -0
- package/lib/drivers/shared/acp-events.d.ts.map +1 -0
- package/lib/drivers/shared/acp-events.js +83 -0
- package/lib/drivers/shared/acp-events.js.map +1 -0
- package/lib/drivers/shared/acp-interaction.d.ts +7 -0
- package/lib/drivers/shared/acp-interaction.d.ts.map +1 -0
- package/lib/drivers/shared/acp-interaction.js +20 -0
- package/lib/drivers/shared/acp-interaction.js.map +1 -0
- package/lib/drivers/shared/acp-session.d.ts +4 -0
- package/lib/drivers/shared/acp-session.d.ts.map +1 -0
- package/lib/drivers/shared/acp-session.js +23 -0
- package/lib/drivers/shared/acp-session.js.map +1 -0
- package/lib/drivers/shared/acp-transport.d.ts +40 -0
- package/lib/drivers/shared/acp-transport.d.ts.map +1 -0
- package/lib/drivers/shared/acp-transport.js +152 -0
- package/lib/drivers/shared/acp-transport.js.map +1 -0
- package/lib/drivers/shared/artifacts.d.ts.map +1 -1
- package/lib/drivers/shared/artifacts.js +3 -2
- package/lib/drivers/shared/artifacts.js.map +1 -1
- package/lib/drivers/shared/experiment-behavior.d.ts +13 -0
- package/lib/drivers/shared/experiment-behavior.d.ts.map +1 -0
- package/lib/drivers/shared/experiment-behavior.js +200 -0
- package/lib/drivers/shared/experiment-behavior.js.map +1 -0
- package/lib/drivers/shared/experiment-policy.d.ts +4 -0
- package/lib/drivers/shared/experiment-policy.d.ts.map +1 -0
- package/lib/drivers/shared/experiment-policy.js +144 -0
- package/lib/drivers/shared/experiment-policy.js.map +1 -0
- package/lib/drivers/shared/skills.d.ts +3 -0
- package/lib/drivers/shared/skills.d.ts.map +1 -0
- package/lib/drivers/shared/skills.js +73 -0
- package/lib/drivers/shared/skills.js.map +1 -0
- package/lib/drivers/subprocess/index.d.ts +39 -4
- package/lib/drivers/subprocess/index.d.ts.map +1 -1
- package/lib/drivers/subprocess/index.js +56 -12
- package/lib/drivers/subprocess/index.js.map +1 -1
- package/lib/index.d.ts +24 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +20 -5
- package/lib/index.js.map +1 -1
- package/lib/optimization/reflective.d.ts +3 -1
- package/lib/optimization/reflective.d.ts.map +1 -1
- package/lib/optimization/reflective.js +3 -2
- package/lib/optimization/reflective.js.map +1 -1
- package/lib/orchestrator/annotation-loader.d.ts +6 -2
- package/lib/orchestrator/annotation-loader.d.ts.map +1 -1
- package/lib/orchestrator/annotation-loader.js +8 -0
- package/lib/orchestrator/annotation-loader.js.map +1 -1
- package/lib/orchestrator/annotation-store.d.ts.map +1 -1
- package/lib/orchestrator/annotation-store.js +16 -2
- package/lib/orchestrator/annotation-store.js.map +1 -1
- package/lib/orchestrator/artifact-origin.d.ts +3 -0
- package/lib/orchestrator/artifact-origin.d.ts.map +1 -0
- package/lib/orchestrator/artifact-origin.js +40 -0
- package/lib/orchestrator/artifact-origin.js.map +1 -0
- package/lib/orchestrator/campaign-lifecycle.d.ts +1 -0
- package/lib/orchestrator/campaign-lifecycle.d.ts.map +1 -1
- package/lib/orchestrator/campaign-lifecycle.js +4 -1
- package/lib/orchestrator/campaign-lifecycle.js.map +1 -1
- package/lib/orchestrator/candidates.d.ts.map +1 -1
- package/lib/orchestrator/candidates.js +3 -2
- package/lib/orchestrator/candidates.js.map +1 -1
- package/lib/orchestrator/compare.d.ts +23 -6
- package/lib/orchestrator/compare.d.ts.map +1 -1
- package/lib/orchestrator/compare.js +45 -12
- package/lib/orchestrator/compare.js.map +1 -1
- package/lib/orchestrator/comparison-identity.d.ts.map +1 -1
- package/lib/orchestrator/comparison-identity.js +2 -0
- package/lib/orchestrator/comparison-identity.js.map +1 -1
- package/lib/orchestrator/config.d.ts +180 -1
- package/lib/orchestrator/config.d.ts.map +1 -1
- package/lib/orchestrator/config.js +21 -2
- package/lib/orchestrator/config.js.map +1 -1
- package/lib/orchestrator/discover.d.ts +1 -0
- package/lib/orchestrator/discover.d.ts.map +1 -1
- package/lib/orchestrator/discover.js +7 -1
- package/lib/orchestrator/discover.js.map +1 -1
- package/lib/orchestrator/doctor.d.ts +1 -0
- package/lib/orchestrator/doctor.d.ts.map +1 -1
- package/lib/orchestrator/doctor.js +134 -69
- package/lib/orchestrator/doctor.js.map +1 -1
- package/lib/orchestrator/driver-capabilities.d.ts +4 -0
- package/lib/orchestrator/driver-capabilities.d.ts.map +1 -0
- package/lib/orchestrator/driver-capabilities.js +13 -0
- package/lib/orchestrator/driver-capabilities.js.map +1 -0
- package/lib/orchestrator/driver-identity.d.ts +5 -0
- package/lib/orchestrator/driver-identity.d.ts.map +1 -0
- package/lib/orchestrator/driver-identity.js +51 -0
- package/lib/orchestrator/driver-identity.js.map +1 -0
- package/lib/orchestrator/experiment-context.d.ts +51 -3
- package/lib/orchestrator/experiment-context.d.ts.map +1 -1
- package/lib/orchestrator/experiment-context.js +2 -1
- package/lib/orchestrator/experiment-context.js.map +1 -1
- package/lib/orchestrator/experiment-contracts.d.ts +31 -1
- package/lib/orchestrator/experiment-contracts.d.ts.map +1 -1
- package/lib/orchestrator/experiment-corpus.d.ts +2 -1
- package/lib/orchestrator/experiment-corpus.d.ts.map +1 -1
- package/lib/orchestrator/experiment-corpus.js +28 -22
- package/lib/orchestrator/experiment-corpus.js.map +1 -1
- package/lib/orchestrator/experiment-effects.d.ts +33 -0
- package/lib/orchestrator/experiment-effects.d.ts.map +1 -0
- package/lib/orchestrator/experiment-effects.js +46 -0
- package/lib/orchestrator/experiment-effects.js.map +1 -0
- package/lib/orchestrator/experiment-evaluation.d.ts.map +1 -1
- package/lib/orchestrator/experiment-evaluation.js +70 -5
- package/lib/orchestrator/experiment-evaluation.js.map +1 -1
- package/lib/orchestrator/experiment-identity.d.ts +3 -0
- package/lib/orchestrator/experiment-identity.d.ts.map +1 -1
- package/lib/orchestrator/experiment-identity.js +22 -33
- package/lib/orchestrator/experiment-identity.js.map +1 -1
- package/lib/orchestrator/experiment-loader.d.ts +8 -3
- package/lib/orchestrator/experiment-loader.d.ts.map +1 -1
- package/lib/orchestrator/experiment-preflight.d.ts +3 -0
- package/lib/orchestrator/experiment-preflight.d.ts.map +1 -0
- package/lib/orchestrator/experiment-preflight.js +21 -0
- package/lib/orchestrator/experiment-preflight.js.map +1 -0
- package/lib/orchestrator/experiment-report.d.ts +91 -1
- package/lib/orchestrator/experiment-report.d.ts.map +1 -1
- package/lib/orchestrator/experiment-report.js +9 -1
- package/lib/orchestrator/experiment-report.js.map +1 -1
- package/lib/orchestrator/experiment-runs.d.ts +63 -2
- package/lib/orchestrator/experiment-runs.d.ts.map +1 -1
- package/lib/orchestrator/experiment-runs.js +13 -5
- package/lib/orchestrator/experiment-runs.js.map +1 -1
- package/lib/orchestrator/experiment-runtime-identity.d.ts +0 -16
- package/lib/orchestrator/experiment-runtime-identity.d.ts.map +1 -1
- package/lib/orchestrator/experiment-runtime-identity.js +5 -220
- package/lib/orchestrator/experiment-runtime-identity.js.map +1 -1
- package/lib/orchestrator/experiment-selection.d.ts.map +1 -1
- package/lib/orchestrator/experiment-selection.js +151 -43
- package/lib/orchestrator/experiment-selection.js.map +1 -1
- package/lib/orchestrator/experiment.d.ts +3 -3
- package/lib/orchestrator/experiment.d.ts.map +1 -1
- package/lib/orchestrator/experiment.js +26 -21
- package/lib/orchestrator/experiment.js.map +1 -1
- package/lib/orchestrator/fixture-identity.d.ts +1 -0
- package/lib/orchestrator/fixture-identity.d.ts.map +1 -1
- package/lib/orchestrator/fixture-identity.js +6 -1
- package/lib/orchestrator/fixture-identity.js.map +1 -1
- package/lib/orchestrator/fs-read.d.ts +1 -6
- package/lib/orchestrator/fs-read.d.ts.map +1 -1
- package/lib/orchestrator/fs-read.js +2 -32
- package/lib/orchestrator/fs-read.js.map +1 -1
- package/lib/orchestrator/grader-experiment.d.ts +23 -5
- package/lib/orchestrator/grader-experiment.d.ts.map +1 -1
- package/lib/orchestrator/grader-experiment.js +54 -9
- package/lib/orchestrator/grader-experiment.js.map +1 -1
- package/lib/orchestrator/grading.d.ts +1 -0
- package/lib/orchestrator/grading.d.ts.map +1 -1
- package/lib/orchestrator/grading.js +41 -33
- package/lib/orchestrator/grading.js.map +1 -1
- package/lib/orchestrator/harness-catalog-drift.d.ts +22 -0
- package/lib/orchestrator/harness-catalog-drift.d.ts.map +1 -0
- package/lib/orchestrator/harness-catalog-drift.js +90 -0
- package/lib/orchestrator/harness-catalog-drift.js.map +1 -0
- package/lib/orchestrator/harness-registry.d.ts +4 -0
- package/lib/orchestrator/harness-registry.d.ts.map +1 -0
- package/lib/orchestrator/harness-registry.js +5 -0
- package/lib/orchestrator/harness-registry.js.map +1 -0
- package/lib/orchestrator/index.d.ts +1 -1
- package/lib/orchestrator/index.d.ts.map +1 -1
- package/lib/orchestrator/index.js +1 -1
- package/lib/orchestrator/index.js.map +1 -1
- package/lib/orchestrator/list-runs.d.ts +8 -1
- package/lib/orchestrator/list-runs.d.ts.map +1 -1
- package/lib/orchestrator/list-runs.js +83 -18
- package/lib/orchestrator/list-runs.js.map +1 -1
- package/lib/orchestrator/optimization-lifecycle.d.ts.map +1 -1
- package/lib/orchestrator/optimization-lifecycle.js +3 -1
- package/lib/orchestrator/optimization-lifecycle.js.map +1 -1
- package/lib/orchestrator/orchestrator.d.ts +17 -2
- package/lib/orchestrator/orchestrator.d.ts.map +1 -1
- package/lib/orchestrator/orchestrator.js +55 -177
- package/lib/orchestrator/orchestrator.js.map +1 -1
- package/lib/orchestrator/paired-effects.d.ts +34 -0
- package/lib/orchestrator/paired-effects.d.ts.map +1 -0
- package/lib/orchestrator/paired-effects.js +164 -0
- package/lib/orchestrator/paired-effects.js.map +1 -0
- package/lib/orchestrator/profile.d.ts +4 -0
- package/lib/orchestrator/profile.d.ts.map +1 -0
- package/lib/orchestrator/profile.js +10 -0
- package/lib/orchestrator/profile.js.map +1 -0
- package/lib/orchestrator/provenance.d.ts +5 -1
- package/lib/orchestrator/provenance.d.ts.map +1 -1
- package/lib/orchestrator/provenance.js +16 -3
- package/lib/orchestrator/provenance.js.map +1 -1
- package/lib/orchestrator/regrade.d.ts +4 -2
- package/lib/orchestrator/regrade.d.ts.map +1 -1
- package/lib/orchestrator/rubric-loader.js +1 -1
- package/lib/orchestrator/rubric-loader.js.map +1 -1
- package/lib/orchestrator/run-dir.d.ts +2 -0
- package/lib/orchestrator/run-dir.d.ts.map +1 -1
- package/lib/orchestrator/run-dir.js +1 -1
- package/lib/orchestrator/run-dir.js.map +1 -1
- package/lib/orchestrator/run-execution.d.ts +3 -0
- package/lib/orchestrator/run-execution.d.ts.map +1 -1
- package/lib/orchestrator/run-execution.js +64 -10
- package/lib/orchestrator/run-execution.js.map +1 -1
- package/lib/orchestrator/run-lifecycle.d.ts +1 -0
- package/lib/orchestrator/run-lifecycle.d.ts.map +1 -1
- package/lib/orchestrator/run-lifecycle.js +3 -2
- package/lib/orchestrator/run-lifecycle.js.map +1 -1
- package/lib/orchestrator/run-workspace.d.ts +10 -0
- package/lib/orchestrator/run-workspace.d.ts.map +1 -0
- package/lib/orchestrator/run-workspace.js +58 -0
- package/lib/orchestrator/run-workspace.js.map +1 -0
- package/lib/orchestrator/suite-compare.d.ts +37 -0
- package/lib/orchestrator/suite-compare.d.ts.map +1 -1
- package/lib/orchestrator/suite-compare.js +44 -22
- package/lib/orchestrator/suite-compare.js.map +1 -1
- package/lib/orchestrator/suite-runs.d.ts +6 -1
- package/lib/orchestrator/suite-runs.d.ts.map +1 -1
- package/lib/orchestrator/suite-runs.js +14 -2
- package/lib/orchestrator/suite-runs.js.map +1 -1
- package/lib/orchestrator/suite-summary.d.ts +79 -0
- package/lib/orchestrator/suite-summary.d.ts.map +1 -1
- package/lib/orchestrator/suite-summary.js +67 -14
- package/lib/orchestrator/suite-summary.js.map +1 -1
- package/lib/previewer/artifacts.d.ts +25 -0
- package/lib/previewer/artifacts.d.ts.map +1 -0
- package/lib/previewer/artifacts.js +180 -0
- package/lib/previewer/artifacts.js.map +1 -0
- package/lib/previewer/server.d.ts +111 -0
- package/lib/previewer/server.d.ts.map +1 -0
- package/lib/previewer/server.js +559 -0
- package/lib/previewer/server.js.map +1 -0
- package/package.json +4 -2
- package/skills/lux-answerer/SKILL.md +2 -2
- package/src/answerers/claude-code/index.ts +6 -5
- package/src/answerers/persona/index.ts +75 -34
- package/src/answerers/terminal/index.ts +7 -11
- package/src/assertions/authoring.ts +2 -0
- package/src/assertions/core/command-exits-zero.ts +82 -17
- package/src/assertions/core/event-checks.ts +64 -3
- package/src/assertions/core/index.ts +2 -0
- package/src/assertions/core/resource-checks.ts +38 -5
- package/src/assertions/core/safe-regex.ts +16 -6
- package/src/assertions/rubric/evidence.ts +85 -0
- package/src/assertions/rubric/index.ts +63 -46
- package/src/assertions/rubric/internal.ts +256 -41
- package/src/authoring.ts +346 -2
- package/src/cli/bin.ts +2 -12
- package/src/cli/command-runtime.ts +20 -9
- package/src/cli/doctor.ts +17 -0
- package/src/cli/harness-plan.ts +123 -0
- package/src/cli/init-templates.ts +238 -0
- package/src/cli/init.ts +53 -184
- package/src/cli/output-schemas.ts +109 -0
- package/src/cli/program.ts +697 -730
- package/src/cli/render/format.ts +1 -1
- package/src/cli/render/reporter.ts +36 -8
- package/src/cli/run-options.ts +131 -25
- package/src/cli/view.ts +129 -0
- package/src/container/driver.ts +213 -0
- package/src/container/paths.ts +29 -0
- package/src/container/protocol.ts +48 -0
- package/src/container/resources.ts +165 -0
- package/src/container/worker.ts +107 -0
- package/src/core/action-events.ts +59 -0
- package/src/core/agent-activity.ts +236 -0
- package/src/core/agent-environment.ts +64 -0
- package/src/core/agent-events.ts +17 -0
- package/src/core/annotation.ts +2 -1
- package/src/core/answerer.ts +9 -0
- package/src/core/artifact-evidence.ts +40 -5
- package/src/core/assertion.ts +8 -2
- package/src/core/case-defaults.ts +65 -0
- package/src/core/case.ts +79 -8
- package/src/core/command-verification.ts +74 -0
- package/src/core/driver-execution.ts +84 -0
- package/src/core/driver-metrics.ts +51 -0
- package/src/core/driver.ts +76 -0
- package/src/core/duration.ts +52 -0
- package/src/core/environment.ts +22 -0
- package/src/core/evaluation-clusters.ts +35 -0
- package/src/core/events.ts +13 -2
- package/src/core/experiment.ts +71 -25
- package/src/core/file-tree.ts +35 -0
- package/src/core/global-id.ts +26 -0
- package/src/core/harness-catalog.ts +100 -0
- package/src/core/harness-catalogs/antigravity.ts +24 -0
- package/src/core/harness-catalogs/claude-code.ts +25 -0
- package/src/core/harness-catalogs/codex.ts +27 -0
- package/src/core/harness-catalogs/copilot.ts +46 -0
- package/src/core/harness-catalogs/cursor.ts +13 -0
- package/src/core/harness-catalogs/grok-build.ts +19 -0
- package/src/core/harness-catalogs/index.ts +31 -0
- package/src/core/harness-matrix.ts +316 -0
- package/src/core/index.ts +12 -0
- package/src/core/lifecycle-fixtures.ts +4 -2
- package/src/core/model-cli.ts +60 -26
- package/src/core/platform-process.ts +65 -16
- package/src/core/reference-defaults.ts +47 -0
- package/src/core/run.ts +31 -0
- package/src/core/usage.ts +8 -0
- package/src/drivers/antigravity/README.md +171 -0
- package/src/drivers/antigravity/artifacts.ts +37 -0
- package/src/drivers/antigravity/config.ts +92 -0
- package/src/drivers/antigravity/events.ts +290 -0
- package/src/drivers/antigravity/index.ts +132 -0
- package/src/drivers/antigravity/runtime.ts +94 -0
- package/src/drivers/claude-code/deferred-process.ts +118 -0
- package/src/drivers/claude-code/index.ts +227 -281
- package/src/drivers/claude-code/isolation.ts +228 -0
- package/src/drivers/claude-code/parse-events.ts +98 -12
- package/src/drivers/codex/app-events.ts +126 -16
- package/src/drivers/codex/config.ts +59 -8
- package/src/drivers/codex/exec-events.ts +258 -0
- package/src/drivers/codex/index.ts +146 -312
- package/src/drivers/copilot/README.md +60 -0
- package/src/drivers/copilot/config.ts +61 -0
- package/src/drivers/copilot/index.ts +310 -0
- package/src/drivers/cursor/README.md +66 -0
- package/src/drivers/cursor/config.ts +31 -0
- package/src/drivers/cursor/index.ts +326 -0
- package/src/drivers/cursor/interaction.ts +74 -0
- package/src/drivers/grok-build/README.md +112 -0
- package/src/drivers/grok-build/config.ts +43 -0
- package/src/drivers/grok-build/index.ts +331 -0
- package/src/drivers/mcp/index.ts +25 -11
- package/src/drivers/shared/acp-events.ts +94 -0
- package/src/drivers/shared/acp-interaction.ts +27 -0
- package/src/drivers/shared/acp-session.ts +40 -0
- package/src/drivers/shared/acp-transport.ts +187 -0
- package/src/drivers/shared/artifacts.ts +6 -2
- package/src/drivers/shared/experiment-behavior.ts +217 -0
- package/src/drivers/shared/experiment-policy.ts +196 -0
- package/src/drivers/shared/skills.ts +74 -0
- package/src/drivers/subprocess/index.ts +55 -12
- package/src/index.ts +117 -6
- package/src/optimization/reflective.ts +3 -2
- package/src/orchestrator/annotation-loader.ts +10 -0
- package/src/orchestrator/annotation-store.ts +24 -3
- package/src/orchestrator/artifact-origin.ts +50 -0
- package/src/orchestrator/campaign-lifecycle.ts +5 -1
- package/src/orchestrator/candidates.ts +3 -2
- package/src/orchestrator/compare.ts +62 -13
- package/src/orchestrator/comparison-identity.ts +2 -0
- package/src/orchestrator/config.ts +23 -1
- package/src/orchestrator/discover.ts +8 -1
- package/src/orchestrator/doctor.ts +211 -65
- package/src/orchestrator/driver-capabilities.ts +21 -0
- package/src/orchestrator/driver-identity.ts +69 -0
- package/src/orchestrator/experiment-context.ts +5 -3
- package/src/orchestrator/experiment-corpus.ts +58 -37
- package/src/orchestrator/experiment-effects.ts +63 -0
- package/src/orchestrator/experiment-evaluation.ts +88 -10
- package/src/orchestrator/experiment-identity.ts +57 -48
- package/src/orchestrator/experiment-preflight.ts +27 -0
- package/src/orchestrator/experiment-report.ts +21 -1
- package/src/orchestrator/experiment-runs.ts +11 -4
- package/src/orchestrator/experiment-runtime-identity.ts +5 -243
- package/src/orchestrator/experiment-selection.ts +178 -18
- package/src/orchestrator/experiment.ts +29 -29
- package/src/orchestrator/fixture-identity.ts +9 -1
- package/src/orchestrator/fs-read.ts +2 -32
- package/src/orchestrator/grader-experiment.ts +74 -13
- package/src/orchestrator/grading.ts +60 -31
- package/src/orchestrator/harness-catalog-drift.ts +132 -0
- package/src/orchestrator/harness-registry.ts +12 -0
- package/src/orchestrator/index.ts +1 -0
- package/src/orchestrator/list-runs.ts +102 -18
- package/src/orchestrator/optimization-lifecycle.ts +4 -1
- package/src/orchestrator/orchestrator.ts +105 -224
- package/src/orchestrator/paired-effects.ts +214 -0
- package/src/orchestrator/profile.ts +24 -0
- package/src/orchestrator/provenance.ts +23 -3
- package/src/orchestrator/rubric-loader.ts +1 -1
- package/src/orchestrator/run-dir.ts +8 -1
- package/src/orchestrator/run-execution.ts +75 -10
- package/src/orchestrator/run-lifecycle.ts +4 -2
- package/src/orchestrator/run-workspace.ts +62 -0
- package/src/orchestrator/suite-compare.ts +47 -23
- package/src/orchestrator/suite-runs.ts +13 -2
- package/src/orchestrator/suite-summary.ts +129 -15
- package/src/previewer/artifacts.ts +221 -0
- package/src/previewer/server.ts +789 -0
- package/viewer/app.css +2111 -0
- package/viewer/app.js +627 -0
- package/viewer/artifact-view.js +48 -0
- package/viewer/charts.js +98 -0
- package/viewer/detail.js +1266 -0
- package/viewer/format.js +129 -0
- package/viewer/index.html +151 -0
- package/lib/cli/skills.d.ts +0 -38
- package/lib/cli/skills.d.ts.map +0 -1
- package/lib/cli/skills.js +0 -84
- package/lib/cli/skills.js.map +0 -1
- package/lib/drivers/shared/secure-copy.d.ts.map +0 -1
- package/lib/drivers/shared/secure-copy.js.map +0 -1
- package/skills/lux/SKILL.md +0 -89
- package/skills/lux/references/cli.md +0 -125
- package/skills/lux/references/eval-authoring.md +0 -257
- package/src/cli/skills.ts +0 -129
- /package/lib/{drivers/shared → core}/secure-copy.d.ts +0 -0
- /package/lib/{drivers/shared → core}/secure-copy.js +0 -0
- /package/src/{drivers/shared → core}/secure-copy.ts +0 -0
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { basename, extname,
|
|
1
|
+
import { basename, extname, join, resolve } from "node:path";
|
|
2
|
+
import { ContainerDriver } from "../container/driver.js";
|
|
3
|
+
import { driverExecutionOf } from "../core/driver-execution.js";
|
|
4
|
+
import { type EnvironmentDeclaration, EnvironmentDeclarationSchema } from "../core/environment.js";
|
|
2
5
|
import {
|
|
3
6
|
type Answerer,
|
|
4
7
|
type AnswererModelCallAccounting,
|
|
5
8
|
type AnswererRef,
|
|
6
9
|
bindSubjectRoot,
|
|
7
10
|
type DriverRef,
|
|
11
|
+
driverConfigOf,
|
|
12
|
+
driverNameOf,
|
|
8
13
|
type EvalCase,
|
|
9
14
|
type GradingAssertionEntry,
|
|
10
15
|
type GradingReport,
|
|
@@ -18,12 +23,19 @@ import {
|
|
|
18
23
|
type SuiteLifecycleHookContext,
|
|
19
24
|
valueHash,
|
|
20
25
|
} from "../core/index.js";
|
|
26
|
+
import {
|
|
27
|
+
mergeAnswererReference,
|
|
28
|
+
mergeDriverReference,
|
|
29
|
+
withDriverDefaults,
|
|
30
|
+
} from "../core/reference-defaults.js";
|
|
21
31
|
import {
|
|
22
32
|
fixturesForEvalCase,
|
|
23
33
|
mergeLifecycleFixtures,
|
|
24
34
|
registryForEvalCase,
|
|
25
35
|
valuesForFixtures,
|
|
26
36
|
} from "./case-extensions.js";
|
|
37
|
+
import { isBuiltinDriver } from "./config.js";
|
|
38
|
+
import { validateDriverCapabilities } from "./driver-capabilities.js";
|
|
27
39
|
import { evaluatorImplementationHash } from "./evaluator-identity.js";
|
|
28
40
|
import {
|
|
29
41
|
assertionEvaluatorIdentities,
|
|
@@ -102,11 +114,13 @@ const recordLifecycleCleanupFailure = async (result: RunResult, error: unknown):
|
|
|
102
114
|
};
|
|
103
115
|
|
|
104
116
|
export type OrchestratorOptions = {
|
|
117
|
+
environment?: EnvironmentDeclaration | undefined;
|
|
105
118
|
registry: Registry;
|
|
106
119
|
/** Answerer used when a case names none. Defaults to "persona". */
|
|
107
120
|
defaultAnswerer?: AnswererRef;
|
|
108
121
|
/** Driver used when a case names none. */
|
|
109
122
|
defaultDriver?: DriverRef;
|
|
123
|
+
driverDefaults?: Record<string, unknown> | undefined;
|
|
110
124
|
/** Shared provider/model defaults for built-in harness components. */
|
|
111
125
|
harness?: HarnessModelConfig;
|
|
112
126
|
/** Versioned project resource fixtures. */
|
|
@@ -114,6 +128,8 @@ export type OrchestratorOptions = {
|
|
|
114
128
|
};
|
|
115
129
|
|
|
116
130
|
export type RunRequest = {
|
|
131
|
+
/** Effective parent suite worker limit; direct runs default to one. */
|
|
132
|
+
suiteConcurrency?: number | undefined;
|
|
117
133
|
/** Path to a TS case file. Mutually exclusive with `case`. */
|
|
118
134
|
casePath?: string;
|
|
119
135
|
/** Pre-loaded EvalCase. Mutually exclusive with `casePath`. */
|
|
@@ -137,6 +153,12 @@ export type RunRequest = {
|
|
|
137
153
|
subjectRoot?: string | undefined;
|
|
138
154
|
subjectHash?: string | undefined;
|
|
139
155
|
profileId?: string | undefined;
|
|
156
|
+
/**
|
|
157
|
+
* Driver bound by a harness permutation. It replaces the project default;
|
|
158
|
+
* a case pinned to another driver is rejected rather than silently rerouted.
|
|
159
|
+
*/
|
|
160
|
+
driver?: DriverRef | undefined;
|
|
161
|
+
permutationId?: string | undefined;
|
|
140
162
|
experimentId?: string | undefined;
|
|
141
163
|
variantId?: string | undefined;
|
|
142
164
|
candidateId?: string | undefined;
|
|
@@ -195,7 +217,13 @@ export type SuiteObserver = RunObserver & {
|
|
|
195
217
|
* `caseId` is the canonical id runs are filed under when the case declares
|
|
196
218
|
* none — display decorations (a `--loop` suffix) must not fork run history.
|
|
197
219
|
*/
|
|
198
|
-
export type SuiteItem = {
|
|
220
|
+
export type SuiteItem = {
|
|
221
|
+
path: string;
|
|
222
|
+
id: string;
|
|
223
|
+
caseId?: string | undefined;
|
|
224
|
+
driver?: DriverRef | undefined;
|
|
225
|
+
permutationId?: string | undefined;
|
|
226
|
+
};
|
|
199
227
|
|
|
200
228
|
const resolveCaseId = (casePath: string, evalCase: EvalCase, fallback?: string): string => {
|
|
201
229
|
if (evalCase.id) return evalCase.id;
|
|
@@ -206,40 +234,24 @@ const resolveCaseId = (casePath: string, evalCase: EvalCase, fallback?: string):
|
|
|
206
234
|
return ext ? base.slice(0, -ext.length) : base;
|
|
207
235
|
};
|
|
208
236
|
|
|
209
|
-
const driverNameOf = (ref: DriverRef): string => (typeof ref === "string" ? ref : ref.name);
|
|
210
|
-
|
|
211
|
-
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
212
|
-
Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
213
|
-
|
|
214
|
-
/** Merge plugin config recursively so nested Codex `config`/`env` overrides stay additive. */
|
|
215
|
-
const mergePluginConfig = (base: unknown, local: unknown): unknown => {
|
|
216
|
-
if (!isRecord(base) || !isRecord(local)) return local ?? base;
|
|
217
|
-
const merged: Record<string, unknown> = { ...base };
|
|
218
|
-
for (const [key, value] of Object.entries(local)) {
|
|
219
|
-
merged[key] = key in merged ? mergePluginConfig(merged[key], value) : value;
|
|
220
|
-
}
|
|
221
|
-
return merged;
|
|
222
|
-
};
|
|
223
|
-
|
|
224
237
|
export const resolveDriverReference = (
|
|
225
238
|
evalCase: EvalCase,
|
|
226
239
|
fallback: DriverRef | undefined,
|
|
240
|
+
permutation?: DriverRef | undefined,
|
|
241
|
+
defaults?: Record<string, unknown> | undefined,
|
|
227
242
|
): DriverRef => {
|
|
228
243
|
const local = evalCase.driver;
|
|
229
|
-
if (
|
|
230
|
-
|
|
231
|
-
|
|
244
|
+
if (permutation && local && driverNameOf(local) !== driverNameOf(permutation)) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
`case is pinned to driver '${driverNameOf(local)}' but the run selected '${driverNameOf(permutation)}'`,
|
|
247
|
+
);
|
|
232
248
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return {
|
|
240
|
-
name: driverNameOf(local),
|
|
241
|
-
config: mergePluginConfig(baseConfig, localConfig),
|
|
242
|
-
};
|
|
249
|
+
const reference = withDriverDefaults(
|
|
250
|
+
mergeDriverReference(permutation ?? fallback, local),
|
|
251
|
+
defaults,
|
|
252
|
+
);
|
|
253
|
+
if (!reference) throw new Error("case names no driver and no defaultDriver is configured");
|
|
254
|
+
return reference;
|
|
243
255
|
};
|
|
244
256
|
|
|
245
257
|
export const resolveAnswererReference = (
|
|
@@ -248,7 +260,18 @@ export const resolveAnswererReference = (
|
|
|
248
260
|
harness: HarnessModelConfig | undefined,
|
|
249
261
|
override?: string,
|
|
250
262
|
): AnswererRef => {
|
|
251
|
-
const
|
|
263
|
+
const fallbackName = typeof fallback === "string" ? fallback : fallback.name;
|
|
264
|
+
const inherited =
|
|
265
|
+
harness && fallbackName === "persona"
|
|
266
|
+
? {
|
|
267
|
+
name: "persona",
|
|
268
|
+
config: mergeHarnessModelConfig(
|
|
269
|
+
harness,
|
|
270
|
+
typeof fallback === "object" ? fallback.config : undefined,
|
|
271
|
+
),
|
|
272
|
+
}
|
|
273
|
+
: fallback;
|
|
274
|
+
const ref = mergeAnswererReference(inherited, override ?? evalCase.answerer) as AnswererRef;
|
|
252
275
|
const name = typeof ref === "string" ? ref : ref.name;
|
|
253
276
|
if (!harness || name !== "persona") return ref;
|
|
254
277
|
return {
|
|
@@ -259,197 +282,25 @@ export const resolveAnswererReference = (
|
|
|
259
282
|
|
|
260
283
|
const answererNameOf = (ref: AnswererRef): string => (typeof ref === "string" ? ref : ref.name);
|
|
261
284
|
|
|
262
|
-
const driverConfigOf = (ref: DriverRef): unknown =>
|
|
263
|
-
typeof ref === "object" ? ref.config : undefined;
|
|
264
|
-
|
|
265
285
|
const answererConfigOf = (ref: AnswererRef): unknown =>
|
|
266
286
|
typeof ref === "object" ? ref.config : undefined;
|
|
267
287
|
|
|
268
|
-
const EXPERIMENT_BEHAVIOR_SOURCE_ARGS = new Set([
|
|
269
|
-
"--continue",
|
|
270
|
-
"-c",
|
|
271
|
-
"--fork-session",
|
|
272
|
-
"--resume",
|
|
273
|
-
"-r",
|
|
274
|
-
"--add-dir",
|
|
275
|
-
"--append-system-prompt-file",
|
|
276
|
-
"--mcp-config",
|
|
277
|
-
"--plugin-dir",
|
|
278
|
-
"--settings",
|
|
279
|
-
"--setting-sources",
|
|
280
|
-
"--system-prompt-file",
|
|
281
|
-
]);
|
|
282
|
-
|
|
283
|
-
const CODEX_EXPERIMENT_SOURCE_ARGS = new Set([
|
|
284
|
-
"--add-dir",
|
|
285
|
-
"--cd",
|
|
286
|
-
"-C",
|
|
287
|
-
"--config",
|
|
288
|
-
"-c",
|
|
289
|
-
"--profile",
|
|
290
|
-
"-p",
|
|
291
|
-
]);
|
|
292
|
-
|
|
293
|
-
const bindSubprocessExperimentConfig = (config: Record<string, unknown>): unknown => {
|
|
294
|
-
if (typeof config.command !== "string" || !isAbsolute(config.command)) {
|
|
295
|
-
throw new Error(
|
|
296
|
-
"experiment subprocess commands must be absolute direct wrappers so Lux can fingerprint the invoked behavior",
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
if (typeof config.cwd === "string") {
|
|
300
|
-
throw new Error(
|
|
301
|
-
"experiment runs do not allow an explicit subprocess cwd; use the candidate subject and staged fixtures",
|
|
302
|
-
);
|
|
303
|
-
}
|
|
304
|
-
if (Array.isArray(config.args) && config.args.length > 0) {
|
|
305
|
-
throw new Error(
|
|
306
|
-
"experiment subprocesses do not allow args; put stable behavior in the fingerprinted direct wrapper",
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
if (isRecord(config.env) && Object.keys(config.env).length > 0) {
|
|
310
|
-
throw new Error(
|
|
311
|
-
"experiment subprocesses do not allow custom env; put stable behavior in the fingerprinted direct wrapper",
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
return { ...config, inheritEnv: false };
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
type AgentDriverName = "claude-code" | "codex";
|
|
318
|
-
|
|
319
|
-
const validateAgentExperimentConfig = (
|
|
320
|
-
driverName: AgentDriverName,
|
|
321
|
-
config: Record<string, unknown>,
|
|
322
|
-
): { driverEnv: Record<string, unknown>; extraArgs: string[] } => {
|
|
323
|
-
const driverEnv = isRecord(config.env) ? config.env : {};
|
|
324
|
-
const commandResolutionOverride = Object.keys(driverEnv).find((name) =>
|
|
325
|
-
["PATH", "PATHEXT"].includes(name.toUpperCase()),
|
|
326
|
-
);
|
|
327
|
-
if (commandResolutionOverride) {
|
|
328
|
-
throw new Error(
|
|
329
|
-
`experiment runs do not allow driver env.${commandResolutionOverride}; command resolution must match the fingerprinted host executable`,
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
|
-
if (typeof config.cwd === "string") {
|
|
333
|
-
throw new Error(
|
|
334
|
-
`experiment runs do not allow an explicit ${driverName} cwd; use the candidate subject and staged fixtures`,
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const extraArgs = Array.isArray(config.extraArgs)
|
|
339
|
-
? config.extraArgs.filter((value): value is string => typeof value === "string")
|
|
340
|
-
: [];
|
|
341
|
-
const disallowedArgs =
|
|
342
|
-
driverName === "claude-code" ? EXPERIMENT_BEHAVIOR_SOURCE_ARGS : CODEX_EXPERIMENT_SOURCE_ARGS;
|
|
343
|
-
const behaviorSourceArg = extraArgs.find((arg) =>
|
|
344
|
-
[...disallowedArgs].some((name) => arg === name || arg.startsWith(`${name}=`)),
|
|
345
|
-
);
|
|
346
|
-
if (behaviorSourceArg) {
|
|
347
|
-
throw new Error(
|
|
348
|
-
`experiment runs do not allow behavior-bearing extraArgs '${behaviorSourceArg}'; use structured driver fields so Lux can fingerprint the source`,
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const isolation = isRecord(config.isolation) ? config.isolation : {};
|
|
353
|
-
const structuredPaths = [
|
|
354
|
-
...(driverName === "claude-code" && Array.isArray(config.pluginDirs) ? config.pluginDirs : []),
|
|
355
|
-
...(Array.isArray(config.addDirs) ? config.addDirs : []),
|
|
356
|
-
...(driverName === "claude-code" && Array.isArray(isolation.allowRead)
|
|
357
|
-
? isolation.allowRead
|
|
358
|
-
: []),
|
|
359
|
-
].filter((value): value is string => typeof value === "string");
|
|
360
|
-
const relativeSource = structuredPaths.find((path) => !isAbsolute(path));
|
|
361
|
-
if (relativeSource) {
|
|
362
|
-
throw new Error(
|
|
363
|
-
`experiment driver source paths must be absolute after subjectPath binding: ${relativeSource}`,
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
return { driverEnv, extraArgs };
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
const bindCodexExperimentConfig = (
|
|
370
|
-
config: Record<string, unknown>,
|
|
371
|
-
extraArgs: readonly string[],
|
|
372
|
-
): unknown => {
|
|
373
|
-
if (typeof config.profile === "string") {
|
|
374
|
-
throw new Error(
|
|
375
|
-
"experiment runs do not allow a Codex profile; use inline driver config so Lux can fingerprint it",
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
|
-
if (config.ephemeral === false) {
|
|
379
|
-
throw new Error("experiment runs require ephemeral Codex sessions");
|
|
380
|
-
}
|
|
381
|
-
const inlineConfig = isRecord(config.config) ? config.config : {};
|
|
382
|
-
const externalConfigKey = ((): string | undefined => {
|
|
383
|
-
const visit = (value: Record<string, unknown>, parent = ""): string | undefined => {
|
|
384
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
385
|
-
const path = parent ? `${parent}.${key}` : key;
|
|
386
|
-
if (/(?:mcp_servers|instructions_file|notify|project_doc)/i.test(key)) return path;
|
|
387
|
-
if (isRecord(nested)) {
|
|
388
|
-
const found = visit(nested, path);
|
|
389
|
-
if (found) return found;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
return undefined;
|
|
393
|
-
};
|
|
394
|
-
return visit(inlineConfig);
|
|
395
|
-
})();
|
|
396
|
-
if (externalConfigKey) {
|
|
397
|
-
throw new Error(
|
|
398
|
-
`experiment runs do not allow path-bearing Codex config '${externalConfigKey}'`,
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
const appServer = config.interactionMode !== "exec";
|
|
402
|
-
return {
|
|
403
|
-
...config,
|
|
404
|
-
ephemeral: true,
|
|
405
|
-
ignoreUserConfig: true,
|
|
406
|
-
ignoreRules: true,
|
|
407
|
-
...(appServer && !config.isolation ? { isolation: { allowRead: [] } } : {}),
|
|
408
|
-
extraArgs,
|
|
409
|
-
};
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
const bindClaudeExperimentConfig = (
|
|
413
|
-
config: Record<string, unknown>,
|
|
414
|
-
extraArgs: readonly string[],
|
|
415
|
-
driverEnv: Record<string, unknown>,
|
|
416
|
-
): unknown => {
|
|
417
|
-
if (config.isolation) return config;
|
|
418
|
-
return {
|
|
419
|
-
...config,
|
|
420
|
-
extraArgs: [
|
|
421
|
-
...extraArgs,
|
|
422
|
-
"--setting-sources",
|
|
423
|
-
"user",
|
|
424
|
-
"--strict-mcp-config",
|
|
425
|
-
"--settings",
|
|
426
|
-
JSON.stringify({ disableAllHooks: true }),
|
|
427
|
-
],
|
|
428
|
-
env: {
|
|
429
|
-
...driverEnv,
|
|
430
|
-
CLAUDE_CODE_DISABLE_AUTO_MEMORY: "1",
|
|
431
|
-
CLAUDE_CODE_DISABLE_CLAUDE_MDS: "1",
|
|
432
|
-
CLAUDE_CODE_SKIP_PROMPT_HISTORY: "1",
|
|
433
|
-
CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: "1",
|
|
434
|
-
CLAUDE_CODE_AUTO_CONNECT_IDE: "false",
|
|
435
|
-
CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL: "1",
|
|
436
|
-
DISABLE_AUTOUPDATER: "1",
|
|
437
|
-
},
|
|
438
|
-
};
|
|
439
|
-
};
|
|
440
|
-
|
|
441
288
|
export const boundExperimentDriverConfig = (
|
|
442
|
-
|
|
289
|
+
plugin: import("../core/driver.js").DriverPlugin,
|
|
443
290
|
config: unknown,
|
|
444
291
|
experimentId: string | undefined,
|
|
445
292
|
): unknown => {
|
|
446
|
-
if (!experimentId
|
|
447
|
-
if (
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
293
|
+
if (!experimentId) return config;
|
|
294
|
+
if (!plugin.experiment) {
|
|
295
|
+
throw new Error(
|
|
296
|
+
`driver '${plugin.name}' supports ordinary eval runs but does not declare controlled experiment support`,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return validatePluginConfig(
|
|
300
|
+
plugin.configSchema,
|
|
301
|
+
plugin.experiment.prepare(config),
|
|
302
|
+
`driver '${plugin.name}' experiment configuration`,
|
|
303
|
+
);
|
|
453
304
|
};
|
|
454
305
|
|
|
455
306
|
const closeQuietly = async (close: () => Promise<void>, label: string): Promise<void> => {
|
|
@@ -463,17 +314,23 @@ const closeQuietly = async (close: () => Promise<void>, label: string): Promise<
|
|
|
463
314
|
};
|
|
464
315
|
|
|
465
316
|
export class Orchestrator {
|
|
317
|
+
private readonly environment: EnvironmentDeclaration | undefined;
|
|
466
318
|
private evaluatorHash: Promise<string> | undefined;
|
|
467
319
|
readonly registry: Registry;
|
|
468
320
|
private readonly defaultAnswerer: AnswererRef;
|
|
469
321
|
private readonly defaultDriver: DriverRef | undefined;
|
|
322
|
+
private readonly driverDefaults: Record<string, unknown> | undefined;
|
|
470
323
|
private readonly harness: HarnessModelConfig | undefined;
|
|
471
324
|
private readonly lifecycleFixtures: readonly LifecycleHooksPlugin[];
|
|
472
325
|
|
|
473
326
|
constructor(options: OrchestratorOptions) {
|
|
327
|
+
this.environment = options.environment
|
|
328
|
+
? EnvironmentDeclarationSchema.parse(options.environment)
|
|
329
|
+
: undefined;
|
|
474
330
|
this.registry = options.registry;
|
|
475
331
|
this.defaultAnswerer = options.defaultAnswerer ?? "persona";
|
|
476
332
|
this.defaultDriver = options.defaultDriver;
|
|
333
|
+
this.driverDefaults = options.driverDefaults;
|
|
477
334
|
this.harness = options.harness;
|
|
478
335
|
this.lifecycleFixtures = [...(options.lifecycleFixtures ?? [])];
|
|
479
336
|
}
|
|
@@ -512,13 +369,19 @@ export class Orchestrator {
|
|
|
512
369
|
registry,
|
|
513
370
|
);
|
|
514
371
|
|
|
515
|
-
const driverRef =
|
|
372
|
+
const driverRef = bindSubjectRoot(
|
|
373
|
+
resolveDriverReference(evalCase, this.defaultDriver, request.driver, this.driverDefaults),
|
|
374
|
+
request.subjectRoot,
|
|
375
|
+
);
|
|
516
376
|
const driverName = driverNameOf(driverRef);
|
|
517
|
-
const answererRef =
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
377
|
+
const answererRef = bindSubjectRoot(
|
|
378
|
+
resolveAnswererReference(
|
|
379
|
+
evalCase,
|
|
380
|
+
this.defaultAnswerer,
|
|
381
|
+
this.harness,
|
|
382
|
+
request.answererOverride,
|
|
383
|
+
),
|
|
384
|
+
request.subjectRoot,
|
|
522
385
|
);
|
|
523
386
|
const answererName = answererNameOf(answererRef);
|
|
524
387
|
|
|
@@ -534,7 +397,7 @@ export class Orchestrator {
|
|
|
534
397
|
// Validate both configs before instantiating either plugin so a
|
|
535
398
|
// schema failure can't leak a half-initialized driver/answerer.
|
|
536
399
|
const driverCfg = boundExperimentDriverConfig(
|
|
537
|
-
|
|
400
|
+
driverPlugin,
|
|
538
401
|
validatePluginConfig(
|
|
539
402
|
driverPlugin.configSchema,
|
|
540
403
|
driverConfigOf(driverRef),
|
|
@@ -548,7 +411,20 @@ export class Orchestrator {
|
|
|
548
411
|
`answerer '${answererName}'`,
|
|
549
412
|
);
|
|
550
413
|
|
|
551
|
-
const
|
|
414
|
+
const execution = driverExecutionOf(driverRef);
|
|
415
|
+
if (execution?.kind === "container" && request.experimentId)
|
|
416
|
+
throw new Error("container execution does not yet support controlled experiments");
|
|
417
|
+
if (
|
|
418
|
+
execution?.kind === "container" &&
|
|
419
|
+
!execution.driverModule &&
|
|
420
|
+
!isBuiltinDriver(driverPlugin)
|
|
421
|
+
)
|
|
422
|
+
throw new Error("custom container drivers require execution.driverModule in the image");
|
|
423
|
+
validateDriverCapabilities(driverPlugin, driverCfg, evalCase.requires, execution);
|
|
424
|
+
const driver =
|
|
425
|
+
execution?.kind === "container"
|
|
426
|
+
? new ContainerDriver(driverName, driverCfg, execution)
|
|
427
|
+
: await driverPlugin.create(driverCfg);
|
|
552
428
|
let answerer: Answerer;
|
|
553
429
|
try {
|
|
554
430
|
answerer = await answererPlugin.create(answererCfg);
|
|
@@ -581,9 +457,10 @@ export class Orchestrator {
|
|
|
581
457
|
validatedAssertionConfigs,
|
|
582
458
|
caseId,
|
|
583
459
|
driverName,
|
|
460
|
+
permutationId: request.permutationId,
|
|
584
461
|
answererName,
|
|
585
462
|
answererConfig: answererCfg,
|
|
586
|
-
driverConfigHash: valueHash(driverCfg),
|
|
463
|
+
driverConfigHash: valueHash(execution ? { config: driverCfg, execution } : driverCfg),
|
|
587
464
|
answererConfigHash: valueHash(answererCfg),
|
|
588
465
|
validatedAssertionsHash,
|
|
589
466
|
graderConfigHash: graderHash,
|
|
@@ -599,6 +476,7 @@ export class Orchestrator {
|
|
|
599
476
|
skipJudge: request.skipJudge ?? false,
|
|
600
477
|
}),
|
|
601
478
|
fixtureValues: valuesForFixtures(lifecycleFixtures),
|
|
479
|
+
environment: this.environment,
|
|
602
480
|
driver,
|
|
603
481
|
answerer,
|
|
604
482
|
},
|
|
@@ -797,9 +675,12 @@ export class Orchestrator {
|
|
|
797
675
|
observer: handle ?? observer,
|
|
798
676
|
abortSignal: opts.abortSignal,
|
|
799
677
|
suiteId: suite.manifest.suiteId,
|
|
678
|
+
suiteConcurrency: concurrency,
|
|
800
679
|
subjectRoot: opts.subjectRoot,
|
|
801
680
|
subjectHash: opts.subjectHash,
|
|
802
681
|
profileId: opts.profileId,
|
|
682
|
+
driver: item.driver,
|
|
683
|
+
permutationId: item.permutationId,
|
|
803
684
|
experimentId: opts.experimentId,
|
|
804
685
|
variantId: opts.variantId,
|
|
805
686
|
candidateId: opts.candidateId,
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { clusterKey } from "../core/evaluation-clusters.js";
|
|
3
|
+
import {
|
|
4
|
+
bootstrapMeanConfidenceInterval,
|
|
5
|
+
type CandidateEvaluation,
|
|
6
|
+
type ConfidenceConfig,
|
|
7
|
+
ConfidenceIntervalSchema,
|
|
8
|
+
} from "../core/index.js";
|
|
9
|
+
|
|
10
|
+
type CaseSamples = NonNullable<CandidateEvaluation["caseSamples"]>;
|
|
11
|
+
type Evaluation = CandidateEvaluation & { repetitions: number };
|
|
12
|
+
|
|
13
|
+
export const clusterCaseSamples = (
|
|
14
|
+
groups: readonly (CaseSamples | undefined)[],
|
|
15
|
+
): CaseSamples | undefined => {
|
|
16
|
+
if (groups.some((group) => group === undefined)) return undefined;
|
|
17
|
+
const result = new Map<string, CaseSamples[string]>();
|
|
18
|
+
for (const group of groups) {
|
|
19
|
+
for (const [id, sample] of Object.entries(group ?? {})) {
|
|
20
|
+
const current = result.get(id);
|
|
21
|
+
if (!current) {
|
|
22
|
+
result.set(id, structuredClone(sample));
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (current.identityHash !== sample.identityHash) current.identityHash = null;
|
|
26
|
+
if (current.clusterId !== sample.clusterId) current.identityHash = null;
|
|
27
|
+
if (current.scoreBasis !== sample.scoreBasis) current.scoreBasis = null;
|
|
28
|
+
const metrics = new Map(Object.entries(current.metrics));
|
|
29
|
+
for (const [metric, value] of Object.entries(sample.metrics)) {
|
|
30
|
+
const before = metrics.get(metric);
|
|
31
|
+
metrics.set(
|
|
32
|
+
metric,
|
|
33
|
+
before
|
|
34
|
+
? {
|
|
35
|
+
mean: (before.mean * before.n + value.mean * value.n) / (before.n + value.n),
|
|
36
|
+
n: before.n + value.n,
|
|
37
|
+
}
|
|
38
|
+
: { ...value },
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
current.metrics = Object.fromEntries(metrics);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return Object.fromEntries(result);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const caseGroups = (samples: CaseSamples): Map<string, string[]> => {
|
|
48
|
+
const groups = new Map<string, string[]>();
|
|
49
|
+
for (const id of Object.keys(samples).sort()) {
|
|
50
|
+
const key = clusterKey(id, samples[id]?.clusterId);
|
|
51
|
+
groups.set(key, [...(groups.get(key) ?? []), id]);
|
|
52
|
+
}
|
|
53
|
+
return groups;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const groupedCaseMetricSamples = (
|
|
57
|
+
samples: CaseSamples | undefined,
|
|
58
|
+
repetitions: number,
|
|
59
|
+
): Record<string, number[]> | undefined => {
|
|
60
|
+
if (!samples || !Object.values(samples).some((sample) => sample.clusterId !== undefined))
|
|
61
|
+
return undefined;
|
|
62
|
+
const groups = caseGroups(samples);
|
|
63
|
+
const metrics = new Set(Object.values(samples).flatMap((sample) => Object.keys(sample.metrics)));
|
|
64
|
+
return Object.fromEntries(
|
|
65
|
+
[...metrics].flatMap((metric) => {
|
|
66
|
+
if (
|
|
67
|
+
Object.values(samples).some(
|
|
68
|
+
(sample) =>
|
|
69
|
+
!Object.hasOwn(sample.metrics, metric) ||
|
|
70
|
+
sample.metrics[metric]?.n !== repetitions ||
|
|
71
|
+
(metric === "score" && !sample.scoreBasis),
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
return [];
|
|
75
|
+
return [
|
|
76
|
+
[
|
|
77
|
+
metric,
|
|
78
|
+
[...groups.values()].map(
|
|
79
|
+
(ids) =>
|
|
80
|
+
ids.reduce((sum, id) => sum + (samples[id]?.metrics[metric]?.mean ?? 0), 0) /
|
|
81
|
+
ids.length,
|
|
82
|
+
),
|
|
83
|
+
],
|
|
84
|
+
];
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const PairedEffectSchema = z.object({
|
|
90
|
+
caseIds: z.array(z.string()),
|
|
91
|
+
n: z.number().int().nonnegative(),
|
|
92
|
+
caseCount: z.number().int().nonnegative().optional(),
|
|
93
|
+
clusters: z.record(z.string(), z.array(z.string())).optional(),
|
|
94
|
+
meanDelta: z.number().finite().nullable(),
|
|
95
|
+
interval: ConfidenceIntervalSchema.nullable(),
|
|
96
|
+
note: z.string().nullable(),
|
|
97
|
+
});
|
|
98
|
+
export type PairedEffect = z.infer<typeof PairedEffectSchema>;
|
|
99
|
+
|
|
100
|
+
export const confidenceGateIssue = (
|
|
101
|
+
interval: z.infer<typeof ConfidenceIntervalSchema>,
|
|
102
|
+
): string | undefined =>
|
|
103
|
+
interval.method === "percentile-bootstrap" && interval.lower === interval.upper
|
|
104
|
+
? "zero-width percentile-bootstrap interval cannot establish promotion confidence; use Hoeffding for bounded means or collect more varied independent evidence"
|
|
105
|
+
: undefined;
|
|
106
|
+
|
|
107
|
+
const pairedDeltas = (
|
|
108
|
+
before: Evaluation | undefined,
|
|
109
|
+
after: Evaluation | undefined,
|
|
110
|
+
metric: string,
|
|
111
|
+
): { caseIds: string[]; values: number[]; clusters: Record<string, string[]> } => {
|
|
112
|
+
if (!before?.caseSamples || !after?.caseSamples)
|
|
113
|
+
throw new Error("keyed case evidence unavailable");
|
|
114
|
+
if (
|
|
115
|
+
before.profileId !== after.profileId ||
|
|
116
|
+
before.split !== after.split ||
|
|
117
|
+
before.repetitions !== after.repetitions
|
|
118
|
+
) {
|
|
119
|
+
throw new Error("paired evidence requires matching profile, split, and repetitions");
|
|
120
|
+
}
|
|
121
|
+
const caseIds = Object.keys(before.caseSamples).sort();
|
|
122
|
+
const afterIds = Object.keys(after.caseSamples).sort();
|
|
123
|
+
const beforeCases = Object.keys(before.casePassRates).sort();
|
|
124
|
+
const afterCases = Object.keys(after.casePassRates).sort();
|
|
125
|
+
if (
|
|
126
|
+
caseIds.length === 0 ||
|
|
127
|
+
[afterIds, beforeCases, afterCases].some(
|
|
128
|
+
(ids) => JSON.stringify(ids) !== JSON.stringify(caseIds),
|
|
129
|
+
)
|
|
130
|
+
) {
|
|
131
|
+
throw new Error("paired evidence requires identical canonical case sets");
|
|
132
|
+
}
|
|
133
|
+
const values = caseIds.map((id) => {
|
|
134
|
+
const a = before.caseSamples?.[id];
|
|
135
|
+
const b = after.caseSamples?.[id];
|
|
136
|
+
if (!a?.identityHash || a.identityHash !== b?.identityHash)
|
|
137
|
+
throw new Error(`paired case '${id}' has incompatible evaluation identity`);
|
|
138
|
+
if (metric === "score" && (!a.scoreBasis || a.scoreBasis !== b.scoreBasis))
|
|
139
|
+
throw new Error(`paired score for case '${id}' has different or unavailable scoring basis`);
|
|
140
|
+
if (a.clusterId !== b.clusterId)
|
|
141
|
+
throw new Error(`paired case '${id}' has incompatible cluster membership`);
|
|
142
|
+
const av = Object.hasOwn(a.metrics, metric) ? a.metrics[metric] : undefined;
|
|
143
|
+
const bv = Object.hasOwn(b.metrics, metric) ? b.metrics[metric] : undefined;
|
|
144
|
+
if (!av || !bv || av.n !== before.repetitions || bv.n !== after.repetitions) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`paired metric '${metric}' lacks complete repetition coverage for case '${id}'`,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return bv.mean - av.mean;
|
|
150
|
+
});
|
|
151
|
+
const byCase = new Map(caseIds.map((id, index) => [id, values[index] ?? 0]));
|
|
152
|
+
const groups = caseGroups(before.caseSamples);
|
|
153
|
+
return {
|
|
154
|
+
caseIds,
|
|
155
|
+
clusters: Object.fromEntries(groups),
|
|
156
|
+
values: [...groups.values()].map(
|
|
157
|
+
(ids) => ids.reduce((sum, id) => sum + (byCase.get(id) ?? 0), 0) / ids.length,
|
|
158
|
+
),
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export const pairedEffect = (
|
|
163
|
+
before: Evaluation | undefined,
|
|
164
|
+
after: Evaluation | undefined,
|
|
165
|
+
metric: string,
|
|
166
|
+
confidence?: ConfidenceConfig,
|
|
167
|
+
): PairedEffect => {
|
|
168
|
+
let paired: ReturnType<typeof pairedDeltas>;
|
|
169
|
+
try {
|
|
170
|
+
paired = pairedDeltas(before, after, metric);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
return {
|
|
173
|
+
caseIds: [],
|
|
174
|
+
n: 0,
|
|
175
|
+
caseCount: 0,
|
|
176
|
+
clusters: {},
|
|
177
|
+
meanDelta: null,
|
|
178
|
+
interval: null,
|
|
179
|
+
note: error instanceof Error ? error.message : String(error),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const result: PairedEffect = {
|
|
183
|
+
caseIds: paired.caseIds,
|
|
184
|
+
n: paired.values.length,
|
|
185
|
+
caseCount: paired.caseIds.length,
|
|
186
|
+
clusters: paired.clusters,
|
|
187
|
+
meanDelta: paired.values.reduce((sum, value) => sum + value, 0) / paired.values.length,
|
|
188
|
+
interval: null,
|
|
189
|
+
note: null,
|
|
190
|
+
};
|
|
191
|
+
if (!confidence) return result;
|
|
192
|
+
try {
|
|
193
|
+
if (confidence.method === "wilson")
|
|
194
|
+
throw new Error("Wilson cannot estimate paired differences");
|
|
195
|
+
if (confidence.method === "hoeffding") {
|
|
196
|
+
const interval = bootstrapMeanConfidenceInterval(
|
|
197
|
+
paired.values.map((value) => (value + 1) / 2),
|
|
198
|
+
confidence,
|
|
199
|
+
);
|
|
200
|
+
result.interval = {
|
|
201
|
+
...interval,
|
|
202
|
+
estimate: 2 * interval.estimate - 1,
|
|
203
|
+
lower: 2 * interval.lower - 1,
|
|
204
|
+
upper: 2 * interval.upper - 1,
|
|
205
|
+
};
|
|
206
|
+
} else {
|
|
207
|
+
result.interval = bootstrapMeanConfidenceInterval(paired.values, confidence);
|
|
208
|
+
}
|
|
209
|
+
result.note = confidenceGateIssue(result.interval) ?? null;
|
|
210
|
+
} catch (error) {
|
|
211
|
+
result.note = error instanceof Error ? error.message : String(error);
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
};
|