@prismatic-io/lux 0.0.2-preview.14 → 0.0.2-preview.16
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 +14 -2
- package/lib/answerers/claude-code/index.d.ts.map +1 -1
- package/lib/answerers/claude-code/index.js +3 -3
- package/lib/answerers/claude-code/index.js.map +1 -1
- package/lib/answerers/persona/index.d.ts +28 -2
- package/lib/answerers/persona/index.d.ts.map +1 -1
- package/lib/answerers/persona/index.js +3 -3
- package/lib/answerers/persona/index.js.map +1 -1
- package/lib/answerers/terminal/index.d.ts +8 -2
- package/lib/answerers/terminal/index.d.ts.map +1 -1
- package/lib/answerers/terminal/index.js +3 -2
- package/lib/answerers/terminal/index.js.map +1 -1
- package/lib/assertions/core/resource-checks.d.ts.map +1 -1
- package/lib/assertions/core/resource-checks.js +3 -5
- package/lib/assertions/core/resource-checks.js.map +1 -1
- package/lib/assertions/rubric/index.d.ts.map +1 -1
- package/lib/assertions/rubric/index.js +7 -1
- package/lib/assertions/rubric/index.js.map +1 -1
- package/lib/assertions/rubric/internal.d.ts +16 -5
- package/lib/assertions/rubric/internal.d.ts.map +1 -1
- package/lib/assertions/rubric/internal.js +10 -6
- package/lib/assertions/rubric/internal.js.map +1 -1
- package/lib/authoring.d.ts +32 -2
- package/lib/authoring.d.ts.map +1 -1
- package/lib/authoring.js +33 -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/init-templates.d.ts +11 -0
- package/lib/cli/init-templates.d.ts.map +1 -0
- package/lib/cli/init-templates.js +207 -0
- package/lib/cli/init-templates.js.map +1 -0
- package/lib/cli/init.d.ts +7 -0
- package/lib/cli/init.d.ts.map +1 -1
- package/lib/cli/init.js +23 -173
- package/lib/cli/init.js.map +1 -1
- package/lib/cli/output-schemas.d.ts +1399 -0
- package/lib/cli/output-schemas.d.ts.map +1 -0
- package/lib/cli/output-schemas.js +91 -0
- package/lib/cli/output-schemas.js.map +1 -0
- package/lib/cli/program.d.ts +135 -4
- package/lib/cli/program.d.ts.map +1 -1
- package/lib/cli/program.js +725 -520
- package/lib/cli/program.js.map +1 -1
- package/lib/cli/render/reporter.d.ts.map +1 -1
- package/lib/cli/render/reporter.js +24 -4
- package/lib/cli/render/reporter.js.map +1 -1
- package/lib/cli/run-options.d.ts +0 -4
- package/lib/cli/run-options.d.ts.map +1 -1
- package/lib/cli/run-options.js +8 -19
- package/lib/cli/run-options.js.map +1 -1
- package/lib/cli/view.d.ts +5 -3
- package/lib/cli/view.d.ts.map +1 -1
- package/lib/cli/view.js +120 -78
- package/lib/cli/view.js.map +1 -1
- 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/assertion.d.ts +3 -0
- package/lib/core/assertion.d.ts.map +1 -1
- package/lib/core/assertion.js +3 -0
- package/lib/core/assertion.js.map +1 -1
- package/lib/core/case.d.ts +24 -2
- package/lib/core/case.d.ts.map +1 -1
- package/lib/core/case.js +5 -1
- package/lib/core/case.js.map +1 -1
- package/lib/core/driver.d.ts +40 -0
- package/lib/core/driver.d.ts.map +1 -1
- package/lib/core/driver.js +12 -0
- package/lib/core/driver.js.map +1 -1
- 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/experiment.d.ts +11 -0
- package/lib/core/experiment.d.ts.map +1 -1
- package/lib/core/experiment.js +31 -17
- 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/index.d.ts +1 -0
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js +1 -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/platform-process.d.ts +5 -1
- package/lib/core/platform-process.d.ts.map +1 -1
- package/lib/core/platform-process.js +48 -10
- package/lib/core/platform-process.js.map +1 -1
- package/lib/core/run.d.ts +93 -1
- package/lib/core/run.d.ts.map +1 -1
- package/lib/core/run.js +16 -0
- package/lib/core/run.js.map +1 -1
- 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/drivers/claude-code/index.d.ts +65 -2
- package/lib/drivers/claude-code/index.d.ts.map +1 -1
- package/lib/drivers/claude-code/index.js +30 -3
- package/lib/drivers/claude-code/index.js.map +1 -1
- package/lib/drivers/codex/app-events.d.ts.map +1 -1
- package/lib/drivers/codex/app-events.js +41 -30
- package/lib/drivers/codex/app-events.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 +76 -4
- package/lib/drivers/codex/index.d.ts.map +1 -1
- package/lib/drivers/codex/index.js +35 -232
- package/lib/drivers/codex/index.js.map +1 -1
- package/lib/drivers/cursor/acp-transport.d.ts +38 -0
- package/lib/drivers/cursor/acp-transport.d.ts.map +1 -0
- package/lib/drivers/cursor/acp-transport.js +152 -0
- package/lib/drivers/cursor/acp-transport.js.map +1 -0
- package/lib/drivers/cursor/config.d.ts +22 -0
- package/lib/drivers/cursor/config.d.ts.map +1 -0
- package/lib/drivers/cursor/config.js +26 -0
- package/lib/drivers/cursor/config.js.map +1 -0
- package/lib/drivers/cursor/events.d.ts +13 -0
- package/lib/drivers/cursor/events.d.ts.map +1 -0
- package/lib/drivers/cursor/events.js +73 -0
- package/lib/drivers/cursor/events.js.map +1 -0
- package/lib/drivers/cursor/index.d.ts +37 -0
- package/lib/drivers/cursor/index.d.ts.map +1 -0
- package/lib/drivers/cursor/index.js +276 -0
- package/lib/drivers/cursor/index.js.map +1 -0
- package/lib/drivers/cursor/interaction.d.ts +7 -0
- package/lib/drivers/cursor/interaction.d.ts.map +1 -0
- package/lib/drivers/cursor/interaction.js +66 -0
- package/lib/drivers/cursor/interaction.js.map +1 -0
- package/lib/drivers/mcp/index.d.ts +35 -2
- package/lib/drivers/mcp/index.d.ts.map +1 -1
- package/lib/drivers/mcp/index.js +16 -3
- package/lib/drivers/mcp/index.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 +197 -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 +143 -0
- package/lib/drivers/shared/experiment-policy.js.map +1 -0
- package/lib/drivers/subprocess/index.d.ts +37 -2
- package/lib/drivers/subprocess/index.d.ts.map +1 -1
- package/lib/drivers/subprocess/index.js +46 -6
- package/lib/drivers/subprocess/index.js.map +1 -1
- package/lib/index.d.ts +6 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -3
- package/lib/index.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/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/compare.d.ts +4 -0
- package/lib/orchestrator/compare.d.ts.map +1 -1
- package/lib/orchestrator/compare.js +13 -1
- package/lib/orchestrator/compare.js.map +1 -1
- package/lib/orchestrator/comparison-identity.d.ts.map +1 -1
- package/lib/orchestrator/comparison-identity.js +1 -0
- package/lib/orchestrator/comparison-identity.js.map +1 -1
- package/lib/orchestrator/config.d.ts +42 -0
- package/lib/orchestrator/config.d.ts.map +1 -1
- package/lib/orchestrator/config.js +6 -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.map +1 -1
- package/lib/orchestrator/doctor.js +34 -26
- package/lib/orchestrator/doctor.js.map +1 -1
- package/lib/orchestrator/driver-capabilities.d.ts +3 -0
- package/lib/orchestrator/driver-capabilities.d.ts.map +1 -0
- package/lib/orchestrator/driver-capabilities.js +10 -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 +41 -0
- package/lib/orchestrator/driver-identity.js.map +1 -0
- package/lib/orchestrator/experiment-context.d.ts +10 -0
- package/lib/orchestrator/experiment-context.d.ts.map +1 -1
- package/lib/orchestrator/experiment-contracts.d.ts +10 -0
- package/lib/orchestrator/experiment-contracts.d.ts.map +1 -1
- package/lib/orchestrator/experiment-corpus.d.ts.map +1 -1
- package/lib/orchestrator/experiment-corpus.js +17 -19
- 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 +44 -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 +36 -3
- package/lib/orchestrator/experiment-evaluation.js.map +1 -1
- package/lib/orchestrator/experiment-identity.d.ts.map +1 -1
- package/lib/orchestrator/experiment-identity.js +18 -29
- package/lib/orchestrator/experiment-identity.js.map +1 -1
- package/lib/orchestrator/experiment-loader.d.ts +7 -2
- package/lib/orchestrator/experiment-loader.d.ts.map +1 -1
- package/lib/orchestrator/experiment-report.d.ts +70 -0
- 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 +22 -1
- 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 +52 -0
- package/lib/orchestrator/experiment-selection.js.map +1 -1
- package/lib/orchestrator/experiment.d.ts +0 -2
- package/lib/orchestrator/experiment.d.ts.map +1 -1
- package/lib/orchestrator/experiment.js +23 -15
- package/lib/orchestrator/experiment.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 +17 -1
- package/lib/orchestrator/grader-experiment.d.ts.map +1 -1
- package/lib/orchestrator/grader-experiment.js +52 -7
- package/lib/orchestrator/grader-experiment.js.map +1 -1
- package/lib/orchestrator/grading.d.ts.map +1 -1
- package/lib/orchestrator/grading.js +13 -6
- package/lib/orchestrator/grading.js.map +1 -1
- package/lib/orchestrator/list-runs.d.ts +1 -0
- package/lib/orchestrator/list-runs.d.ts.map +1 -1
- package/lib/orchestrator/list-runs.js +27 -6
- 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 +6 -1
- package/lib/orchestrator/orchestrator.d.ts.map +1 -1
- package/lib/orchestrator/orchestrator.js +17 -143
- 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 +158 -0
- package/lib/orchestrator/paired-effects.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 +1 -0
- package/lib/orchestrator/regrade.d.ts.map +1 -1
- package/lib/orchestrator/run-execution.d.ts +2 -0
- package/lib/orchestrator/run-execution.d.ts.map +1 -1
- package/lib/orchestrator/run-execution.js +18 -3
- 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/suite-runs.d.ts +3 -1
- package/lib/orchestrator/suite-runs.d.ts.map +1 -1
- package/lib/orchestrator/suite-runs.js +12 -2
- package/lib/orchestrator/suite-runs.js.map +1 -1
- package/lib/orchestrator/suite-summary.d.ts.map +1 -1
- package/lib/orchestrator/suite-summary.js +2 -1
- package/lib/orchestrator/suite-summary.js.map +1 -1
- package/lib/previewer/server.d.ts +6 -0
- package/lib/previewer/server.d.ts.map +1 -1
- package/lib/previewer/server.js +21 -5
- package/lib/previewer/server.js.map +1 -1
- package/package.json +2 -2
- package/skills/lux/references/cli.md +5 -2
- package/skills/lux/references/eval-authoring.md +0 -7
- package/skills/lux-answerer/SKILL.md +1 -1
- package/src/answerers/claude-code/index.ts +3 -3
- package/src/answerers/persona/index.ts +3 -3
- package/src/answerers/terminal/index.ts +4 -9
- package/src/assertions/core/resource-checks.ts +3 -5
- package/src/assertions/rubric/index.ts +7 -1
- package/src/assertions/rubric/internal.ts +13 -8
- package/src/authoring.ts +331 -2
- package/src/cli/bin.ts +2 -12
- package/src/cli/command-runtime.ts +20 -9
- package/src/cli/init-templates.ts +223 -0
- package/src/cli/init.ts +38 -184
- package/src/cli/output-schemas.ts +106 -0
- package/src/cli/program.ts +621 -548
- package/src/cli/render/reporter.ts +25 -4
- package/src/cli/run-options.ts +8 -25
- package/src/cli/view.ts +45 -84
- package/src/core/annotation.ts +2 -1
- package/src/core/answerer.ts +9 -0
- package/src/core/assertion.ts +3 -0
- package/src/core/case.ts +5 -1
- package/src/core/driver.ts +38 -0
- package/src/core/environment.ts +22 -0
- package/src/core/evaluation-clusters.ts +35 -0
- package/src/core/experiment.ts +60 -23
- package/src/core/file-tree.ts +35 -0
- package/src/core/index.ts +1 -0
- package/src/core/lifecycle-fixtures.ts +4 -2
- package/src/core/platform-process.ts +54 -6
- package/src/core/run.ts +20 -0
- package/src/core/usage.ts +8 -0
- package/src/drivers/claude-code/index.ts +34 -3
- package/src/drivers/codex/app-events.ts +43 -33
- package/src/drivers/codex/exec-events.ts +258 -0
- package/src/drivers/codex/index.ts +37 -262
- package/src/drivers/cursor/README.md +57 -0
- package/src/drivers/cursor/acp-transport.ts +182 -0
- package/src/drivers/cursor/config.ts +29 -0
- package/src/drivers/cursor/events.ts +83 -0
- package/src/drivers/cursor/index.ts +316 -0
- package/src/drivers/cursor/interaction.ts +90 -0
- package/src/drivers/mcp/index.ts +16 -3
- package/src/drivers/shared/experiment-behavior.ts +214 -0
- package/src/drivers/shared/experiment-policy.ts +195 -0
- package/src/drivers/subprocess/index.ts +45 -6
- package/src/index.ts +16 -5
- package/src/orchestrator/annotation-loader.ts +10 -0
- package/src/orchestrator/annotation-store.ts +24 -3
- package/src/orchestrator/campaign-lifecycle.ts +5 -1
- package/src/orchestrator/compare.ts +16 -1
- package/src/orchestrator/comparison-identity.ts +1 -0
- package/src/orchestrator/config.ts +6 -2
- package/src/orchestrator/discover.ts +8 -1
- package/src/orchestrator/doctor.ts +40 -22
- package/src/orchestrator/driver-capabilities.ts +16 -0
- package/src/orchestrator/driver-identity.ts +59 -0
- package/src/orchestrator/experiment-corpus.ts +23 -28
- package/src/orchestrator/experiment-effects.ts +61 -0
- package/src/orchestrator/experiment-evaluation.ts +45 -5
- package/src/orchestrator/experiment-identity.ts +27 -36
- 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 +77 -0
- package/src/orchestrator/experiment.ts +26 -24
- package/src/orchestrator/fs-read.ts +2 -32
- package/src/orchestrator/grader-experiment.ts +72 -8
- package/src/orchestrator/grading.ts +15 -6
- package/src/orchestrator/list-runs.ts +29 -6
- package/src/orchestrator/optimization-lifecycle.ts +4 -1
- package/src/orchestrator/orchestrator.ts +26 -183
- package/src/orchestrator/paired-effects.ts +209 -0
- package/src/orchestrator/provenance.ts +23 -3
- package/src/orchestrator/run-execution.ts +18 -3
- package/src/orchestrator/run-lifecycle.ts +4 -2
- package/src/orchestrator/suite-runs.ts +10 -1
- package/src/orchestrator/suite-summary.ts +2 -1
- package/src/previewer/server.ts +27 -5
- package/viewer/app.js +27 -6
- package/viewer/detail.js +22 -5
- package/lib/answerers/scripted/index.d.ts +0 -18
- package/lib/answerers/scripted/index.d.ts.map +0 -1
- package/lib/answerers/scripted/index.js +0 -63
- package/lib/answerers/scripted/index.js.map +0 -1
- 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/src/answerers/scripted/index.ts +0 -78
- package/src/cli/skills.ts +0 -129
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { rm } from "node:fs/promises";
|
|
3
3
|
import type { z } from "zod";
|
|
4
|
+
import { independentClusterCount } from "../core/evaluation-clusters.js";
|
|
4
5
|
import {
|
|
5
6
|
bootstrapMeanConfidenceInterval,
|
|
6
7
|
type Candidate,
|
|
@@ -55,14 +56,7 @@ import {
|
|
|
55
56
|
openExperimentRun,
|
|
56
57
|
resumeExperimentRun,
|
|
57
58
|
} from "./experiment-runs.js";
|
|
58
|
-
import {
|
|
59
|
-
claudeConfigRoot,
|
|
60
|
-
claudeUserBehaviorHash,
|
|
61
|
-
cliIdentity,
|
|
62
|
-
configuredClaudeSourceHashes,
|
|
63
|
-
LUX_VERSION,
|
|
64
|
-
runtimeCliIdentityHashForReferences,
|
|
65
|
-
} from "./experiment-runtime-identity.js";
|
|
59
|
+
import { LUX_VERSION, runtimeCliIdentityHashForReferences } from "./experiment-runtime-identity.js";
|
|
66
60
|
import {
|
|
67
61
|
candidateEvaluations,
|
|
68
62
|
type ExperimentSelectionDerivationOptionsSchema,
|
|
@@ -254,50 +248,57 @@ export const planExperimentCampaign = async (
|
|
|
254
248
|
const splitSelector = splitSelectors.find((split) => split.name === constraint.split)?.selector;
|
|
255
249
|
let examples = splits.find((split) => split.split === constraint.split)?.examples ?? 0;
|
|
256
250
|
if (corpus.kind === "grader" && splitSelector) {
|
|
257
|
-
|
|
251
|
+
let selected = selectGraderAnnotations(graderAnnotations, splitSelector);
|
|
258
252
|
if (constraint.metric === "grader.macroFalsePositiveRate") {
|
|
259
|
-
|
|
253
|
+
selected = selected.filter((annotation) =>
|
|
260
254
|
[
|
|
261
255
|
annotation.expected.casePassed,
|
|
262
256
|
...Object.values(annotation.expected.assertions).map((label) => label.passed),
|
|
263
257
|
].includes(false),
|
|
264
|
-
)
|
|
258
|
+
);
|
|
265
259
|
} else if (constraint.metric === "grader.macroFalseNegativeRate") {
|
|
266
|
-
|
|
260
|
+
selected = selected.filter((annotation) =>
|
|
267
261
|
[
|
|
268
262
|
annotation.expected.casePassed,
|
|
269
263
|
...Object.values(annotation.expected.assertions).map((label) => label.passed),
|
|
270
264
|
].includes(true),
|
|
271
|
-
)
|
|
265
|
+
);
|
|
272
266
|
} else if (constraint.metric === "grader.scoreMae") {
|
|
273
|
-
|
|
267
|
+
selected = selected.filter(
|
|
274
268
|
(annotation) =>
|
|
275
269
|
annotation.expected.caseScore !== undefined ||
|
|
276
270
|
Object.values(annotation.expected.assertions).some(
|
|
277
271
|
(label) => label.score !== undefined,
|
|
278
272
|
),
|
|
279
|
-
)
|
|
273
|
+
);
|
|
280
274
|
} else if (constraint.metric === "grader.caseAgreement") {
|
|
281
|
-
|
|
275
|
+
selected = selected.filter(
|
|
282
276
|
(annotation) =>
|
|
283
277
|
annotation.expected.casePassed !== undefined ||
|
|
284
278
|
annotation.expected.caseScore !== undefined,
|
|
285
|
-
)
|
|
279
|
+
);
|
|
286
280
|
} else if (constraint.metric === "grader.assertionAgreement") {
|
|
287
|
-
|
|
281
|
+
selected = selected.filter(
|
|
288
282
|
(annotation) => Object.keys(annotation.expected.assertions).length > 0,
|
|
289
|
-
)
|
|
283
|
+
);
|
|
290
284
|
} else if (
|
|
291
285
|
constraint.metric === "grader.abstentionRate" ||
|
|
286
|
+
constraint.metric === "grader.insufficientEvidenceRate" ||
|
|
287
|
+
constraint.metric === "grader.operationalErrorRate" ||
|
|
292
288
|
constraint.metric === "grader.coverage"
|
|
293
289
|
) {
|
|
294
|
-
|
|
290
|
+
selected = selected.filter(
|
|
295
291
|
(annotation) =>
|
|
296
292
|
annotation.expected.casePassed !== undefined ||
|
|
297
293
|
Object.keys(annotation.expected.assertions).length > 0,
|
|
298
|
-
)
|
|
294
|
+
);
|
|
299
295
|
}
|
|
296
|
+
examples = independentClusterCount(
|
|
297
|
+
selected.map((annotation) => ({ id: annotation.id, cluster: annotation.meta?.cluster })),
|
|
298
|
+
);
|
|
300
299
|
}
|
|
300
|
+
if (corpus.kind === "agent" && splitSelector)
|
|
301
|
+
examples = independentClusterCount(selectCases(corpus.cases, splitSelector));
|
|
301
302
|
if (constraint.metric === "subject.bytes" || constraint.metric === "quality.caseRegressions") {
|
|
302
303
|
examples = 1;
|
|
303
304
|
}
|
|
@@ -318,6 +319,10 @@ export const planExperimentCampaign = async (
|
|
|
318
319
|
Array<number>(examples).fill(0),
|
|
319
320
|
constraint.confidence,
|
|
320
321
|
);
|
|
322
|
+
if (constraint.relativeTo) {
|
|
323
|
+
bestForMin.lower = 2 * bestForMin.lower - 1;
|
|
324
|
+
bestForMax.upper = 2 * bestForMax.upper - 1;
|
|
325
|
+
}
|
|
321
326
|
if (constraint.min !== undefined && bestForMin.lower < constraint.min) {
|
|
322
327
|
notes.push(
|
|
323
328
|
`${constraint.split} metric '${constraint.metric}' cannot attain confidence lower bound ${constraint.min} with only ${examples} samples (best ${bestForMin.lower.toFixed(3)})`,
|
|
@@ -986,6 +991,3 @@ export const optimizeExperimentCampaign = async (
|
|
|
986
991
|
new CampaignExecution(execution, "optimize", runOptimizationCampaignWork),
|
|
987
992
|
);
|
|
988
993
|
};
|
|
989
|
-
|
|
990
|
-
// Internal exports for identity contract tests.
|
|
991
|
-
export { claudeConfigRoot, claudeUserBehaviorHash, cliIdentity, configuredClaudeSourceHashes };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import type { FileHandle } from "node:fs/promises";
|
|
3
3
|
import { readdir, readFile } from "node:fs/promises";
|
|
4
|
-
import { join, relative
|
|
4
|
+
import { join, relative } from "node:path";
|
|
5
5
|
import type { z } from "zod";
|
|
6
6
|
|
|
7
7
|
const errorMessage = (error: unknown): string =>
|
|
@@ -93,34 +93,4 @@ export const walkFiles = async (root: string, maxFiles?: number): Promise<string
|
|
|
93
93
|
return out.sort();
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
* Walk authored trees without silently following or omitting a symlink that
|
|
98
|
-
* can change outside the experiment identity. Exact ignored paths support
|
|
99
|
-
* generated state directories whose names are project-configurable.
|
|
100
|
-
*/
|
|
101
|
-
export const walkAuthoredFiles = async (
|
|
102
|
-
root: string,
|
|
103
|
-
ignoredDirectoryNames: ReadonlySet<string> = new Set(),
|
|
104
|
-
ignoredPaths: ReadonlySet<string> = new Set(),
|
|
105
|
-
): Promise<string[]> => {
|
|
106
|
-
if (!existsSync(root)) return [];
|
|
107
|
-
const out: string[] = [];
|
|
108
|
-
const stack = [root];
|
|
109
|
-
while (stack.length > 0) {
|
|
110
|
-
const dir = stack.pop();
|
|
111
|
-
if (!dir) continue;
|
|
112
|
-
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
113
|
-
const full = join(dir, entry.name);
|
|
114
|
-
if (ignoredPaths.has(resolve(full))) continue;
|
|
115
|
-
if (entry.isDirectory() && ignoredDirectoryNames.has(entry.name)) continue;
|
|
116
|
-
if (entry.isSymbolicLink()) {
|
|
117
|
-
throw new Error(
|
|
118
|
-
`authored evaluation trees cannot contain symlinks: ${relative(root, full)}`,
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
if (entry.isDirectory()) stack.push(full);
|
|
122
|
-
else if (entry.isFile()) out.push(relative(root, full));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return out.sort();
|
|
126
|
-
};
|
|
96
|
+
export { walkAuthoredFiles } from "../core/file-tree.js";
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
import type { CampaignExecutionOptions } from "./experiment.js";
|
|
29
29
|
import type { OpenedExperimentRun } from "./experiment-runs.js";
|
|
30
30
|
import { gradeRun } from "./grading.js";
|
|
31
|
+
import { clusterCaseSamples, groupedCaseMetricSamples } from "./paired-effects.js";
|
|
31
32
|
import { loadFrozenRegradableRun, releaseFrozenRegradableRun } from "./regrade.js";
|
|
32
33
|
import { loadRubricDefinition } from "./rubric-loader.js";
|
|
33
34
|
|
|
@@ -38,10 +39,12 @@ const GraderJudgmentSchema = z.object({
|
|
|
38
39
|
actual: z.union([z.boolean(), z.number()]).nullable(),
|
|
39
40
|
matched: z.boolean(),
|
|
40
41
|
absoluteError: z.exactOptional(z.number()),
|
|
42
|
+
unavailableReason: z.exactOptional(z.enum(["insufficient-evidence", "operational-error"])),
|
|
41
43
|
});
|
|
42
44
|
export type GraderJudgment = z.infer<typeof GraderJudgmentSchema>;
|
|
43
45
|
|
|
44
46
|
const GraderEvidenceItemSchema = z.object({
|
|
47
|
+
clusterId: z.exactOptional(z.string().min(1)),
|
|
45
48
|
annotationId: z.string(),
|
|
46
49
|
repetition: z.number().int().positive(),
|
|
47
50
|
runDir: z.string(),
|
|
@@ -95,6 +98,11 @@ const assertionOperationalError = (
|
|
|
95
98
|
return detail.success && detail.data.graderError !== undefined;
|
|
96
99
|
};
|
|
97
100
|
|
|
101
|
+
const assertionUnavailableReason = (
|
|
102
|
+
entry: GradingReport["assertions"][number] | undefined,
|
|
103
|
+
): GraderJudgment["unavailableReason"] =>
|
|
104
|
+
assertionOperationalError(entry) ? "operational-error" : entry?.abstention;
|
|
105
|
+
|
|
98
106
|
const assertionModelAccounting = (
|
|
99
107
|
assertion: GradingReport["assertions"][number],
|
|
100
108
|
): { attempts: number; costUsd: number; unpricedModelCalls: number } => {
|
|
@@ -115,19 +123,22 @@ export const compareGraderAnnotation = (
|
|
|
115
123
|
scoreTolerance: number,
|
|
116
124
|
): GraderJudgment[] => {
|
|
117
125
|
const judgments: GraderJudgment[] = [];
|
|
118
|
-
const
|
|
126
|
+
const reportUnavailableReason = report.assertions.some(assertionOperationalError)
|
|
127
|
+
? "operational-error"
|
|
128
|
+
: report.assertions.find((entry) => entry.abstention)?.abstention;
|
|
119
129
|
if (annotation.expected.casePassed !== undefined) {
|
|
120
|
-
const actual =
|
|
130
|
+
const actual = reportUnavailableReason ? null : report.casePassed;
|
|
121
131
|
judgments.push({
|
|
122
132
|
key: "case",
|
|
123
133
|
kind: "case-pass",
|
|
124
134
|
expected: annotation.expected.casePassed,
|
|
125
135
|
actual,
|
|
126
136
|
matched: actual === annotation.expected.casePassed,
|
|
137
|
+
...(reportUnavailableReason ? { unavailableReason: reportUnavailableReason } : {}),
|
|
127
138
|
});
|
|
128
139
|
}
|
|
129
140
|
if (annotation.expected.caseScore !== undefined) {
|
|
130
|
-
const actual =
|
|
141
|
+
const actual = reportUnavailableReason ? null : report.caseScore;
|
|
131
142
|
const absoluteError = actual === null ? 1 : Math.abs(actual - annotation.expected.caseScore);
|
|
132
143
|
judgments.push({
|
|
133
144
|
key: "case",
|
|
@@ -136,6 +147,7 @@ export const compareGraderAnnotation = (
|
|
|
136
147
|
actual,
|
|
137
148
|
matched: actual !== null && absoluteError <= scoreTolerance,
|
|
138
149
|
absoluteError,
|
|
150
|
+
...(reportUnavailableReason ? { unavailableReason: reportUnavailableReason } : {}),
|
|
139
151
|
});
|
|
140
152
|
}
|
|
141
153
|
const entries = new Map(
|
|
@@ -143,13 +155,15 @@ export const compareGraderAnnotation = (
|
|
|
143
155
|
);
|
|
144
156
|
for (const [assertionId, expected] of Object.entries(annotation.expected.assertions)) {
|
|
145
157
|
const entry = entries.get(assertionId);
|
|
146
|
-
const
|
|
158
|
+
const unavailableReason = assertionUnavailableReason(entry);
|
|
159
|
+
const actual = unavailableReason ? undefined : entry;
|
|
147
160
|
judgments.push({
|
|
148
161
|
key: assertionId,
|
|
149
162
|
kind: "assertion-pass",
|
|
150
163
|
expected: expected.passed,
|
|
151
164
|
actual: actual?.passed ?? null,
|
|
152
165
|
matched: actual?.passed === expected.passed,
|
|
166
|
+
...(unavailableReason ? { unavailableReason } : {}),
|
|
153
167
|
});
|
|
154
168
|
if (expected.score !== undefined) {
|
|
155
169
|
const absoluteError = actual ? Math.abs(actual.score - expected.score) : 1;
|
|
@@ -160,6 +174,7 @@ export const compareGraderAnnotation = (
|
|
|
160
174
|
actual: actual?.score ?? null,
|
|
161
175
|
matched: actual !== undefined && absoluteError <= scoreTolerance,
|
|
162
176
|
absoluteError,
|
|
177
|
+
...(unavailableReason ? { unavailableReason } : {}),
|
|
163
178
|
});
|
|
164
179
|
}
|
|
165
180
|
}
|
|
@@ -233,7 +248,7 @@ const collectGraderEvidence = (
|
|
|
233
248
|
|
|
234
249
|
export const summarizeGraderEvidence = (
|
|
235
250
|
items: readonly z.infer<typeof GraderEvidenceItemSchema>[],
|
|
236
|
-
candidate: Candidate,
|
|
251
|
+
candidate: Pick<Candidate, "sourceBytes">,
|
|
237
252
|
): { metrics: Record<string, number>; samples: Record<string, number[]> } => {
|
|
238
253
|
const samples: Record<string, number[]> = {};
|
|
239
254
|
const { byAnnotation, itemsByAnnotation, counts } = collectGraderEvidence(items);
|
|
@@ -323,6 +338,18 @@ export const summarizeGraderEvidence = (
|
|
|
323
338
|
"grader.abstentionRate",
|
|
324
339
|
passes.filter((judgment) => judgment.actual === null).length / passes.length,
|
|
325
340
|
);
|
|
341
|
+
addSample(
|
|
342
|
+
samples,
|
|
343
|
+
"grader.insufficientEvidenceRate",
|
|
344
|
+
passes.filter((judgment) => judgment.unavailableReason === "insufficient-evidence").length /
|
|
345
|
+
passes.length,
|
|
346
|
+
);
|
|
347
|
+
addSample(
|
|
348
|
+
samples,
|
|
349
|
+
"grader.operationalErrorRate",
|
|
350
|
+
passes.filter((judgment) => judgment.unavailableReason === "operational-error").length /
|
|
351
|
+
passes.length,
|
|
352
|
+
);
|
|
326
353
|
}
|
|
327
354
|
}
|
|
328
355
|
const precision = ratio(
|
|
@@ -440,7 +467,42 @@ const evaluationFromEvidence = (
|
|
|
440
467
|
evidencePath: string,
|
|
441
468
|
evidence: GraderEvaluationEvidence,
|
|
442
469
|
): CandidateEvaluation & { evidencePath: string } => {
|
|
470
|
+
const caseSamples = clusterCaseSamples(
|
|
471
|
+
evidence.items.map((item) => {
|
|
472
|
+
const summary = summarizeGraderEvidence([item], {
|
|
473
|
+
sourceBytes: evidence.metrics["subject.bytes"] ?? 0,
|
|
474
|
+
});
|
|
475
|
+
return {
|
|
476
|
+
[item.annotationId]: {
|
|
477
|
+
...(item.clusterId ? { clusterId: item.clusterId } : {}),
|
|
478
|
+
identityHash: experiment.manifest.evaluationHash
|
|
479
|
+
? valueHash({
|
|
480
|
+
evaluationHash: experiment.manifest.evaluationHash,
|
|
481
|
+
annotationId: item.annotationId,
|
|
482
|
+
profileId: evidence.profileId,
|
|
483
|
+
split: evidence.split,
|
|
484
|
+
})
|
|
485
|
+
: null,
|
|
486
|
+
metrics: Object.fromEntries(
|
|
487
|
+
Object.entries(summary.samples).flatMap(([metric, values]) =>
|
|
488
|
+
values.length === 1 ? [[metric, { mean: values[0] ?? 0, n: 1 }]] : [],
|
|
489
|
+
),
|
|
490
|
+
),
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
}),
|
|
494
|
+
);
|
|
443
495
|
const byAnnotation = new Map<string, number[]>();
|
|
496
|
+
const grouped = groupedCaseMetricSamples(caseSamples, evidence.repetitions);
|
|
497
|
+
const metrics = grouped
|
|
498
|
+
? Object.fromEntries(
|
|
499
|
+
Object.entries(evidence.metrics).flatMap(([name, value]) => {
|
|
500
|
+
if (!Object.hasOwn(evidence.samples, name)) return [[name, value]];
|
|
501
|
+
const values = grouped[name];
|
|
502
|
+
return values ? [[name, mean(values)]] : [];
|
|
503
|
+
}),
|
|
504
|
+
)
|
|
505
|
+
: evidence.metrics;
|
|
444
506
|
for (const item of evidence.items) {
|
|
445
507
|
const values = byAnnotation.get(item.annotationId) ?? [];
|
|
446
508
|
values.push(...item.judgments.map((judgment) => (judgment.matched ? 1 : 0)));
|
|
@@ -471,10 +533,11 @@ const evaluationFromEvidence = (
|
|
|
471
533
|
profileId: evidence.profileId,
|
|
472
534
|
split: evidence.split,
|
|
473
535
|
evidencePath: relative(experiment.path, evidencePath),
|
|
474
|
-
passRate:
|
|
536
|
+
passRate: metrics["quality.passRate"] ?? 0,
|
|
475
537
|
casePassRates: Object.fromEntries([...byAnnotation].map(([id, values]) => [id, mean(values)])),
|
|
476
|
-
metrics
|
|
477
|
-
samples: evidence.samples,
|
|
538
|
+
metrics,
|
|
539
|
+
samples: grouped ?? evidence.samples,
|
|
540
|
+
...(caseSamples ? { caseSamples } : {}),
|
|
478
541
|
metricCalls: evidence.items.length,
|
|
479
542
|
judgeCalls: evidence.items.reduce(
|
|
480
543
|
(total, item) =>
|
|
@@ -779,6 +842,7 @@ export const evaluateGraderCandidate = async (options: {
|
|
|
779
842
|
);
|
|
780
843
|
const item: GraderEvidenceItem = {
|
|
781
844
|
annotationId: annotation.id,
|
|
845
|
+
...(annotation.meta?.cluster ? { clusterId: annotation.meta.cluster } : {}),
|
|
782
846
|
repetition,
|
|
783
847
|
runDir: annotation.runDir,
|
|
784
848
|
rubricPath: annotation.rubricPath,
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
type Assertion,
|
|
4
4
|
type AssertionImpl,
|
|
5
5
|
type AssertionProgress,
|
|
6
|
+
type AssertionResult,
|
|
6
7
|
AssertionResultSchema,
|
|
7
8
|
type GradingAssertionEntry,
|
|
8
9
|
type GradingReport,
|
|
@@ -124,6 +125,12 @@ const describeAssertion = (a: Assertion): string => {
|
|
|
124
125
|
return fields ? `${a.type} ${fields}` : a.type;
|
|
125
126
|
};
|
|
126
127
|
|
|
128
|
+
const assertionPassed = (result: AssertionResult, threshold: number): boolean =>
|
|
129
|
+
result.errorMessage === undefined &&
|
|
130
|
+
result.abstention === undefined &&
|
|
131
|
+
result.passed &&
|
|
132
|
+
result.score >= threshold;
|
|
133
|
+
|
|
127
134
|
export const gradeRun = async (
|
|
128
135
|
run: Run,
|
|
129
136
|
registry: Registry,
|
|
@@ -154,6 +161,7 @@ export const gradeRun = async (
|
|
|
154
161
|
let weightSum = 0;
|
|
155
162
|
let allPassed = true;
|
|
156
163
|
let gradingIncomplete = false;
|
|
164
|
+
let gradingAbstained = false;
|
|
157
165
|
|
|
158
166
|
for (const [index, a] of assertions.entries()) {
|
|
159
167
|
if (skipJudge && a.type === "rubric") {
|
|
@@ -219,8 +227,7 @@ export const gradeRun = async (
|
|
|
219
227
|
: {}),
|
|
220
228
|
}),
|
|
221
229
|
);
|
|
222
|
-
const passed =
|
|
223
|
-
result.errorMessage === undefined && result.passed && result.score >= threshold;
|
|
230
|
+
const passed = assertionPassed(result, threshold);
|
|
224
231
|
entry = {
|
|
225
232
|
id,
|
|
226
233
|
type: a.type,
|
|
@@ -232,11 +239,14 @@ export const gradeRun = async (
|
|
|
232
239
|
durationMs: Date.now() - startedAt,
|
|
233
240
|
...(result.comment !== undefined ? { comment: result.comment } : {}),
|
|
234
241
|
detail: result.detail,
|
|
242
|
+
...(result.abstention !== undefined ? { abstention: result.abstention } : {}),
|
|
235
243
|
...(result.errorMessage !== undefined ? { errorMessage: result.errorMessage } : {}),
|
|
236
244
|
...(result.usage ? { usage: result.usage } : {}),
|
|
237
245
|
};
|
|
238
246
|
if (result.errorMessage !== undefined) {
|
|
239
247
|
gradingIncomplete = true;
|
|
248
|
+
} else if (result.abstention !== undefined) {
|
|
249
|
+
gradingAbstained = true;
|
|
240
250
|
} else {
|
|
241
251
|
if (!passed) allPassed = false;
|
|
242
252
|
weightedScoreSum += weight * result.score;
|
|
@@ -264,12 +274,11 @@ export const gradeRun = async (
|
|
|
264
274
|
await modelAttempts?.complete(assertionAttemptIds);
|
|
265
275
|
}
|
|
266
276
|
|
|
267
|
-
|
|
268
|
-
if (!gradingIncomplete && weightSum > 0) caseScore = weightedScoreSum / weightSum;
|
|
277
|
+
const hasVerdict = !gradingIncomplete && !gradingAbstained && weightSum > 0;
|
|
269
278
|
return {
|
|
270
279
|
schemaVersion: 1,
|
|
271
|
-
casePassed:
|
|
272
|
-
caseScore,
|
|
280
|
+
casePassed: hasVerdict ? allPassed : null,
|
|
281
|
+
caseScore: hasVerdict ? weightedScoreSum / weightSum : null,
|
|
273
282
|
assertions: entries,
|
|
274
283
|
...(skippedAssertions.length > 0 ? { skippedAssertions } : {}),
|
|
275
284
|
...(gradingIncomplete
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
ToolResultPayloadSchema,
|
|
21
21
|
totalTokens,
|
|
22
22
|
} from "../core/index.js";
|
|
23
|
+
import { hasAgentUsage } from "../core/usage.js";
|
|
23
24
|
import { readBoundedHandle, safeReadJson, walkFiles } from "./fs-read.js";
|
|
24
25
|
import { MAX_RUN_TRACE_BYTES, MAX_RUN_TRACE_EVENTS } from "./trace-limits.js";
|
|
25
26
|
|
|
@@ -45,6 +46,7 @@ export type ListedRun = {
|
|
|
45
46
|
caseScore: number | null;
|
|
46
47
|
assertionPassed: number;
|
|
47
48
|
assertionTotal: number;
|
|
49
|
+
readErrors?: string[];
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
const summarizeRun = async (
|
|
@@ -53,10 +55,19 @@ const summarizeRun = async (
|
|
|
53
55
|
ts: string,
|
|
54
56
|
runDir: string,
|
|
55
57
|
): Promise<ListedRun> => {
|
|
56
|
-
const [
|
|
58
|
+
const [metadataResult, gradingResult] = await Promise.allSettled([
|
|
57
59
|
safeReadJson(join(runDir, "run.json"), RunMetadataSchema),
|
|
58
60
|
safeReadJson(join(runDir, "grading.json"), GradingReportSchema),
|
|
59
61
|
]);
|
|
62
|
+
const readErrors = [metadataResult, gradingResult].flatMap((result) =>
|
|
63
|
+
result.status === "rejected"
|
|
64
|
+
? [result.reason instanceof Error ? result.reason.message : String(result.reason)]
|
|
65
|
+
: [],
|
|
66
|
+
);
|
|
67
|
+
const meta = metadataResult.status === "fulfilled" ? metadataResult.value : null;
|
|
68
|
+
// A valid grading file cannot establish a result when its run metadata is damaged.
|
|
69
|
+
const grading =
|
|
70
|
+
readErrors.length === 0 && gradingResult.status === "fulfilled" ? gradingResult.value : null;
|
|
60
71
|
const startedAt = meta?.startedAt ?? null;
|
|
61
72
|
const endedAt = meta?.endedAt ?? null;
|
|
62
73
|
const started = Date.parse(startedAt ?? "");
|
|
@@ -83,6 +94,7 @@ const summarizeRun = async (
|
|
|
83
94
|
caseScore: grading?.caseScore ?? null,
|
|
84
95
|
assertionPassed: passing,
|
|
85
96
|
assertionTotal: grading?.assertions.length ?? 0,
|
|
97
|
+
...(readErrors.length > 0 ? { readErrors } : {}),
|
|
86
98
|
};
|
|
87
99
|
};
|
|
88
100
|
|
|
@@ -146,7 +158,8 @@ export const formatRunsTable = (runs: ListedRun[]): string => {
|
|
|
146
158
|
["status", "case", "driver", "agents", "ts", "exit", "score", "duration"],
|
|
147
159
|
...runs.map((r) => {
|
|
148
160
|
let status = "ungraded";
|
|
149
|
-
if (r.
|
|
161
|
+
if (r.readErrors?.length) status = "DAMAGED";
|
|
162
|
+
else if (r.casePassed === true) status = "PASS";
|
|
150
163
|
else if (r.casePassed === false) status = "FAIL";
|
|
151
164
|
const score =
|
|
152
165
|
r.caseScore !== null
|
|
@@ -159,9 +172,11 @@ export const formatRunsTable = (runs: ListedRun[]): string => {
|
|
|
159
172
|
];
|
|
160
173
|
const header = rows[0] ?? [];
|
|
161
174
|
const widths = header.map((_, col) => Math.max(...rows.map((r) => r[col]?.length ?? 0)));
|
|
162
|
-
|
|
175
|
+
const table = rows
|
|
163
176
|
.map((row) => row.map((cell, col) => cell.padEnd(widths[col] ?? 0)).join(" "))
|
|
164
177
|
.join("\n");
|
|
178
|
+
const diagnostics = runs.flatMap((run) => run.readErrors ?? []);
|
|
179
|
+
return diagnostics.length > 0 ? `${table}\n\n${diagnostics.join("\n")}` : table;
|
|
165
180
|
};
|
|
166
181
|
|
|
167
182
|
export type RunDetail = {
|
|
@@ -289,6 +304,12 @@ const appendMetadataDetail = (lines: string[], detail: RunDetail): void => {
|
|
|
289
304
|
}`,
|
|
290
305
|
);
|
|
291
306
|
}
|
|
307
|
+
const environment = provenance?.environment;
|
|
308
|
+
if (environment) {
|
|
309
|
+
lines.push(`concurrency: ${environment.concurrency}`);
|
|
310
|
+
if (environment.declared)
|
|
311
|
+
lines.push(`declared environment: ${JSON.stringify(environment.declared)}`);
|
|
312
|
+
}
|
|
292
313
|
const c = detail.metadata.interruptCounts;
|
|
293
314
|
lines.push(`interrupts: ask=${c.ask} approve=${c.approve} custom=${c.custom}`);
|
|
294
315
|
const tools = detail.metadata.toolOutcomes;
|
|
@@ -301,7 +322,7 @@ const appendMetadataDetail = (lines: string[], detail: RunDetail): void => {
|
|
|
301
322
|
}
|
|
302
323
|
const usage = detail.metadata.usage;
|
|
303
324
|
lines.push(
|
|
304
|
-
`tokens: agent=${totalTokens(usage.agent)} harness=${totalTokens(harnessUsage(usage))}` +
|
|
325
|
+
`tokens: agent=${hasAgentUsage(detail.metadata) ? totalTokens(usage.agent) : "unavailable"} harness=${totalTokens(harnessUsage(usage))}` +
|
|
305
326
|
` (answerer=${totalTokens(usage.answerer)} judge=${totalTokens(usage.grading)})`,
|
|
306
327
|
);
|
|
307
328
|
const phases = detail.metadata.phaseDurationMs;
|
|
@@ -347,9 +368,11 @@ const appendGradingDetail = (lines: string[], detail: RunDetail): void => {
|
|
|
347
368
|
`grading: ${status} (${score}, ${detail.grading.assertions.filter((a) => a.passed).length}/${detail.grading.assertions.length})`,
|
|
348
369
|
);
|
|
349
370
|
for (const a of detail.grading.assertions) {
|
|
350
|
-
|
|
371
|
+
let mark = a.passed ? "✓" : "✗";
|
|
372
|
+
if (a.abstention) mark = "?";
|
|
351
373
|
const took = ` (${(a.durationMs / 1000).toFixed(1)}s)`;
|
|
352
|
-
|
|
374
|
+
const abstention = a.abstention ? " — insufficient evidence" : "";
|
|
375
|
+
lines.push(` ${mark} ${a.name}${took}${abstention}${a.comment ? ` — ${a.comment}` : ""}`);
|
|
353
376
|
}
|
|
354
377
|
}
|
|
355
378
|
};
|
|
@@ -26,6 +26,7 @@ export const executeOptimizationLifecycle = async <Search, Deployment, Result>(
|
|
|
26
26
|
deployment: Deployment | undefined;
|
|
27
27
|
result: Result | undefined;
|
|
28
28
|
error: unknown;
|
|
29
|
+
failed: boolean;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
const machine = setup({
|
|
@@ -59,6 +60,7 @@ export const executeOptimizationLifecycle = async <Search, Deployment, Result>(
|
|
|
59
60
|
result: ({ event }) => ("output" in event ? event.output : undefined),
|
|
60
61
|
}),
|
|
61
62
|
captureError: assign({
|
|
63
|
+
failed: true,
|
|
62
64
|
error: ({ event }) =>
|
|
63
65
|
"error" in event ? event.error : new Error("optimization lifecycle failed"),
|
|
64
66
|
}),
|
|
@@ -70,6 +72,7 @@ export const executeOptimizationLifecycle = async <Search, Deployment, Result>(
|
|
|
70
72
|
deployment: undefined,
|
|
71
73
|
result: undefined,
|
|
72
74
|
error: undefined,
|
|
75
|
+
failed: false,
|
|
73
76
|
},
|
|
74
77
|
initial: "evaluatingSearchSeeds",
|
|
75
78
|
states: {
|
|
@@ -112,7 +115,7 @@ export const executeOptimizationLifecycle = async <Search, Deployment, Result>(
|
|
|
112
115
|
failed: { type: "final" },
|
|
113
116
|
},
|
|
114
117
|
output: ({ context }) =>
|
|
115
|
-
context.
|
|
118
|
+
!context.failed
|
|
116
119
|
? { status: "succeeded", result: context.result }
|
|
117
120
|
: { status: "failed", error: context.error },
|
|
118
121
|
});
|