@bjoernrochel/sevro 0.1.0-rc.7 → 1.0.0
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/CONTRIBUTING.md +22 -6
- package/README.md +5 -1
- package/docs/README.md +19 -15
- package/docs/architecture.md +138 -17
- package/docs/assets/README.md +5 -4
- package/docs/builtin-graders-v1.md +17 -3
- package/docs/codex-host.md +155 -49
- package/docs/contracts.md +2 -1
- package/docs/creating-cases.md +9 -2
- package/docs/development-cli.md +187 -19
- package/docs/documentation-quality.md +12 -2
- package/docs/evaluation-workflow.md +110 -0
- package/docs/extension-protocol-v1.md +26 -3
- package/docs/getting-started.md +23 -2
- package/docs/guide-evaluation.md +33 -1
- package/docs/identity-v1.md +25 -2
- package/docs/installing.md +11 -11
- package/docs/native-controls.md +76 -5
- package/docs/native-hosts.md +196 -7
- package/docs/reading-results.md +102 -0
- package/docs/recipes.md +489 -0
- package/docs/releases.md +31 -12
- package/docs/report-v1.md +29 -1
- package/docs/results-v1.md +141 -4
- package/docs/run-settings-v1.md +147 -0
- package/docs/runtime-v1.md +307 -18
- package/docs/troubleshooting.md +12 -12
- package/docs/typescript-quality.md +89 -26
- package/examples/recipes/candidate.ts +26 -0
- package/examples/recipes/cases/coding-change.json +21 -0
- package/examples/recipes/cases/host-tools.json +21 -0
- package/examples/recipes/cases/mise.json +21 -0
- package/examples/recipes/cases/node.json +21 -0
- package/examples/recipes/cases/python-uv.json +21 -0
- package/examples/recipes/cases/semantic.json +17 -0
- package/examples/recipes/coding-change/check.ts +23 -0
- package/examples/recipes/extension-artifacts.ts +65 -0
- package/examples/recipes/extension-methods.ts +174 -0
- package/examples/recipes/extension.ts +37 -0
- package/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
- package/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
- package/examples/recipes/repository-skill/README.md +3 -0
- package/examples/recipes/run-inputs.ts +188 -0
- package/examples/recipes/run-options.ts +131 -0
- package/examples/recipes/run.ts +63 -0
- package/examples/recipes/runtime/empty.json +1 -0
- package/examples/recipes/runtime/goals.json +1 -0
- package/examples/recipes/runtime/mise.json +6 -0
- package/examples/recipes/runtime/path.json +1 -0
- package/examples/recipes/runtime/plugins.json +4 -0
- package/examples/recipes/runtime/python-uv.json +10 -0
- package/examples/recipes/semantic-judge.ts +29 -0
- package/examples/templates/coding/adapter.ts +17 -0
- package/examples/templates/coding/case.json +15 -0
- package/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
- package/examples/templates/repository-skill/extension-data.ts +64 -0
- package/examples/templates/repository-skill/extension.ts +31 -0
- package/examples/templates/response/adapter.ts +12 -0
- package/examples/templates/response/case.json +13 -0
- package/package.json +11 -5
- package/schemas/report-v1.schema.json +9 -0
- package/schemas/run-evidence-v1.schema.json +2 -1
- package/schemas/runtime-v1.schema.json +63 -7
- package/src/advisory.ts +2 -2
- package/src/candidate-artifacts.ts +206 -0
- package/src/candidate-codex-state.ts +185 -0
- package/src/case-validation.ts +73 -50
- package/src/cli/cancellation.ts +20 -0
- package/src/cli/command.ts +87 -0
- package/src/cli/completion.ts +15 -0
- package/src/cli/demo.ts +60 -0
- package/src/cli/evaluation.ts +55 -0
- package/src/cli/extension.ts +79 -0
- package/src/cli/help.ts +198 -0
- package/src/cli/hosts.ts +55 -0
- package/src/cli/init-settings.ts +30 -0
- package/src/cli/init.ts +111 -0
- package/src/{cli-invocation.ts → cli/invocation.ts} +214 -218
- package/src/cli/loading.ts +151 -0
- package/src/cli/preparation.ts +154 -0
- package/src/cli/presentation.ts +93 -0
- package/src/cli/progress.ts +6 -0
- package/src/cli/run-manifest.ts +128 -0
- package/src/cli/run-options.ts +403 -0
- package/src/cli/run-overrides.ts +69 -0
- package/src/cli/settings.ts +154 -0
- package/src/cli/summary.ts +43 -0
- package/src/cli.ts +13 -591
- package/src/contract-types.ts +94 -0
- package/src/engine.ts +13 -5
- package/src/evaluation/advisory.ts +150 -0
- package/src/{evaluation-check-plan.ts → evaluation/check-plan.ts} +103 -67
- package/src/evaluation/collection.ts +88 -0
- package/src/evaluation/context.ts +10 -0
- package/src/{evaluation-grading-host.ts → evaluation/grading-host.ts} +5 -5
- package/src/evaluation/grading.ts +235 -0
- package/src/{evaluation-invocation-plan.ts → evaluation/invocation-plan.ts} +147 -58
- package/src/{evaluation-plan.ts → evaluation/plan.ts} +208 -141
- package/src/evaluation/progress.ts +19 -0
- package/src/evaluation/resources.ts +241 -0
- package/src/evaluation/run.ts +206 -0
- package/src/{evaluation-semantic.ts → evaluation/semantic.ts} +133 -115
- package/src/evaluation/trial.ts +800 -0
- package/src/evaluation/types.ts +207 -0
- package/src/evidence/host-results.ts +85 -0
- package/src/evidence/retained-artifacts.ts +18 -0
- package/src/evidence/trial-writer.ts +203 -0
- package/src/evidence/usage.ts +17 -0
- package/src/extension-client.ts +34 -96
- package/src/extension-session.ts +24 -48
- package/src/{advisory-fixture.ts → fixtures/advisory.ts} +15 -76
- package/src/{fixture-bin.ts → fixtures/bin.ts} +1 -1
- package/src/{fixture-cleanup.ts → fixtures/cleanup.ts} +13 -7
- package/src/fixtures/create.ts +183 -0
- package/src/{generated-fixture.ts → fixtures/generated.ts} +10 -53
- package/src/{git-hooks.ts → fixtures/git-hooks.ts} +1 -1
- package/src/{preparation.ts → fixtures/preparation.ts} +6 -16
- package/src/{repository-fixture.ts → fixtures/repository.ts} +30 -64
- package/src/{fixture-setup.ts → fixtures/setup.ts} +33 -51
- package/src/{fixture-tools.ts → fixtures/tools.ts} +1 -1
- package/src/fixtures/workspace-state.ts +212 -0
- package/src/generated/cli-result.d.cts +2 -1
- package/src/generated/extension.d.cts +2 -1
- package/src/generated/report.cjs +1 -1
- package/src/generated/report.d.cts +2 -1
- package/src/generated/run-evidence.cjs +1 -1
- package/src/generated/run-evidence.d.cts +2 -1
- package/src/generated/runtime.cjs +1 -1
- package/src/generated/runtime.d.cts +2 -1
- package/src/git.ts +93 -0
- package/src/graders/git-head.ts +29 -84
- package/src/graders/shell.ts +57 -68
- package/src/host-diagnostic-redaction.ts +52 -0
- package/src/host-diagnostics.ts +331 -0
- package/src/hosts/claude-continuation.ts +57 -40
- package/src/hosts/claude-credential.ts +160 -63
- package/src/hosts/claude-events.ts +34 -18
- package/src/hosts/claude-keychain.ts +78 -21
- package/src/hosts/claude-login-recovery.ts +85 -0
- package/src/hosts/claude-login-refresh.ts +178 -0
- package/src/hosts/claude-login-store.ts +162 -0
- package/src/hosts/claude-login.ts +107 -0
- package/src/hosts/claude-native-goal.ts +15 -12
- package/src/hosts/claude-process.ts +10 -50
- package/src/hosts/claude-refresh-lock.ts +81 -0
- package/src/hosts/claude-repository-invocation.ts +9 -34
- package/src/hosts/claude-settings.ts +91 -14
- package/src/hosts/claude-skill-activations.ts +169 -0
- package/src/hosts/claude-state.ts +46 -16
- package/src/hosts/claude-tool-calls.ts +13 -10
- package/src/hosts/claude.ts +122 -73
- package/src/hosts/codex-app-server.ts +78 -52
- package/src/hosts/codex-configuration.ts +5 -10
- package/src/hosts/codex-exec-controls.ts +516 -0
- package/src/hosts/codex-marketplace.ts +12 -10
- package/src/hosts/codex-native-calls.ts +15 -122
- package/src/hosts/codex-process.ts +10 -54
- package/src/hosts/codex-profile.ts +50 -21
- package/src/hosts/codex-session-files.ts +1 -9
- package/src/hosts/codex-state.ts +141 -19
- package/src/hosts/codex.ts +221 -179
- package/src/hosts/isolation-common.ts +15 -11
- package/src/hosts/isolation-roots.ts +13 -20
- package/src/hosts/linux-sandbox.ts +27 -3
- package/src/hosts/mac-sandbox.ts +111 -18
- package/src/hosts/native-controls.ts +72 -22
- package/src/hosts/native-request.ts +55 -0
- package/src/hosts/process-lifecycle.ts +221 -45
- package/src/hosts/protected-worktrees.ts +1 -1
- package/src/hosts/skill-hook-catalog.ts +131 -0
- package/src/hosts/skill-hook-handler.ts +374 -0
- package/src/hosts/skill-hooks.ts +577 -0
- package/src/instrumentation.ts +7 -8
- package/src/native-transcript-state.ts +22 -3
- package/src/native-transcript-view.ts +52 -13
- package/src/native-transcripts.ts +34 -15
- package/src/paths.ts +22 -0
- package/src/process-lifecycle.ts +150 -0
- package/src/provenance.ts +27 -7
- package/src/prune.ts +300 -0
- package/src/report.ts +63 -36
- package/src/resolved-case.ts +1 -1
- package/src/results-lock.ts +42 -0
- package/src/results.ts +14 -18
- package/src/run-owner.ts +4 -4
- package/src/{runtime-config.ts → runtime/config.ts} +182 -44
- package/src/{runtime-discovery-apple.ts → runtime/discovery-apple.ts} +3 -3
- package/src/{runtime-discovery-providers.ts → runtime/discovery-providers.ts} +3 -9
- package/src/{runtime-discovery.ts → runtime/discovery.ts} +4 -4
- package/src/{runtime-hook-processes.ts → runtime/hook-processes.ts} +1 -1
- package/src/{runtime-hooks.ts → runtime/hooks.ts} +33 -22
- package/src/{runtime-paths.ts → runtime/paths.ts} +6 -18
- package/src/{runtime-query.ts → runtime/query.ts} +5 -5
- package/src/{runtime-seeds.ts → runtime/seeds.ts} +3 -3
- package/src/runtime/shared-cache.ts +130 -0
- package/src/{runtime-state.ts → runtime/state.ts} +28 -11
- package/src/schema-types.ts +73 -161
- package/src/shell.ts +4 -0
- package/src/transcript-retention.ts +146 -0
- package/src/value-guards.ts +22 -0
- package/docs/assets/sevro-logo.png +0 -0
- package/docs/assets/sevro-symbol.svg +0 -1
- package/docs/assets/sevro-wordmark.svg +0 -1
- package/docs/cache-ownership-validation.md +0 -49
- package/docs/claude-continuation-validation.md +0 -47
- package/docs/concurrency-validation.md +0 -86
- package/docs/configuration-root-validation.md +0 -70
- package/docs/engine-slice.md +0 -114
- package/docs/evidence/runtime-startup-30/README.md +0 -185
- package/docs/evidence/runtime-startup-30/after.json +0 -319
- package/docs/evidence/runtime-startup-30/baseline-timeout.jsonl +0 -2
- package/docs/evidence/runtime-startup-30/before.json +0 -403
- package/docs/evidence/runtime-startup-30/consumer-smoke.json +0 -63
- package/docs/evidence/runtime-startup-30/full-policy-diagnostic.jsonl +0 -3
- package/docs/evidence/runtime-startup-30/minimal-policy-diagnostic.jsonl +0 -3
- package/docs/evidence/runtime-startup-30/plugin-template-assessment.json +0 -20
- package/docs/evidence/runtime-startup-30/seedless-timeout.jsonl +0 -2
- package/docs/evidence.md +0 -17
- package/docs/fixture-cleanup-validation.md +0 -70
- package/docs/guide-verification.json +0 -239
- package/src/evaluation-context.ts +0 -257
- package/src/evaluation-fixture.ts +0 -313
- package/src/evaluation-run.ts +0 -198
- package/src/evaluation-trial.ts +0 -946
- package/src/evaluation-types.ts +0 -149
- package/src/hosts/claude-nested-skills.ts +0 -272
- package/src/hosts/codex-command-output.ts +0 -510
- package/src/hosts/codex-executor-command.ts +0 -291
- package/src/hosts/codex-skill-reads.ts +0 -609
- /package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +0 -0
package/src/engine.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
EvaluationConfigurationError,
|
|
3
|
+
HostExecutionFailure,
|
|
4
|
+
} from "./evaluation/types";
|
|
2
5
|
export type {
|
|
3
6
|
HostResult,
|
|
4
7
|
HostAdapter,
|
|
5
8
|
ResolvedCase,
|
|
6
9
|
EvaluationOptions,
|
|
10
|
+
EvaluationProgress,
|
|
7
11
|
CliResult,
|
|
8
|
-
} from "./evaluation
|
|
9
|
-
export { runEvaluation } from "./evaluation
|
|
10
|
-
export { loadRuntimeConfiguration } from "./runtime
|
|
11
|
-
export type { RuntimeConfiguration, RuntimePolicy } from "./runtime
|
|
12
|
+
} from "./evaluation/types";
|
|
13
|
+
export { runEvaluation } from "./evaluation/run";
|
|
14
|
+
export { loadRuntimeConfiguration } from "./runtime/config";
|
|
15
|
+
export type { RuntimeConfiguration, RuntimePolicy } from "./runtime/config";
|
|
16
|
+
export type {
|
|
17
|
+
RuntimeArtifactDirectory,
|
|
18
|
+
CandidateArtifactRoots,
|
|
19
|
+
} from "./candidate-artifacts";
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
advisoryPrompt,
|
|
3
|
+
parseAdvisoryAssessment,
|
|
4
|
+
type AdvisoryAssessment,
|
|
5
|
+
} from "../advisory";
|
|
6
|
+
import type { CandidateArtifactRoots } from "../candidate-artifacts";
|
|
7
|
+
import type { TrialEvidenceWriter } from "../evidence/trial-writer";
|
|
8
|
+
import { usage } from "../evidence/usage";
|
|
9
|
+
import { buildBlindAdvisoryFixture } from "../fixtures/advisory";
|
|
10
|
+
import { removeWorkspace } from "../fixtures/workspace-state";
|
|
11
|
+
import { HostDiagnosticPersistenceError } from "../host-diagnostics";
|
|
12
|
+
import type { CheckOutcome } from "../results";
|
|
13
|
+
import type { AdvisoryReviewData } from "../schema-types";
|
|
14
|
+
import type { RuntimePolicy } from "../runtime/config";
|
|
15
|
+
import { gradingRuntimePolicy, scopedHostArtifacts } from "./grading-host";
|
|
16
|
+
import {
|
|
17
|
+
TrialPersistenceError,
|
|
18
|
+
type HostAdapter,
|
|
19
|
+
type HostResult,
|
|
20
|
+
} from "./types";
|
|
21
|
+
|
|
22
|
+
export type AdvisoryReview = AdvisoryReviewData;
|
|
23
|
+
|
|
24
|
+
interface AdvisoryInput {
|
|
25
|
+
readonly host: HostAdapter;
|
|
26
|
+
readonly candidateCompleted: boolean;
|
|
27
|
+
readonly candidateWorkspace: string;
|
|
28
|
+
readonly candidateTranscriptRoot?: string;
|
|
29
|
+
readonly candidateArtifactRoots?: CandidateArtifactRoots;
|
|
30
|
+
readonly baseRevision: string | null;
|
|
31
|
+
readonly excludedPaths?: string[];
|
|
32
|
+
readonly task: string;
|
|
33
|
+
readonly checks: readonly CheckOutcome[];
|
|
34
|
+
readonly declaredChecks: { id: string }[];
|
|
35
|
+
readonly runtimePolicy?: RuntimePolicy;
|
|
36
|
+
readonly signal?: AbortSignal;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface AdvisoryEffects {
|
|
40
|
+
readonly evidence: Pick<
|
|
41
|
+
TrialEvidenceWriter,
|
|
42
|
+
"artifactRefs" | "retainArtifacts" | "retainAdvisoryResponse"
|
|
43
|
+
>;
|
|
44
|
+
retainWorkspace(workspace: string): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function defaultAdvisoryReview(host: HostAdapter): AdvisoryReview {
|
|
48
|
+
return {
|
|
49
|
+
status: "not_run",
|
|
50
|
+
assessment: null,
|
|
51
|
+
usage: usage(null),
|
|
52
|
+
rawResult: { source: host.id, path: null, sha256: null },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function completeAdvisoryAssessment(response: HostResult): AdvisoryAssessment {
|
|
57
|
+
if (
|
|
58
|
+
response.executionFailed ||
|
|
59
|
+
!response.complete ||
|
|
60
|
+
response.finalMessage === null
|
|
61
|
+
)
|
|
62
|
+
throw new Error("advisory response is incomplete");
|
|
63
|
+
return parseAdvisoryAssessment(response.finalMessage);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function cleanupAdvisoryWorkspace(
|
|
67
|
+
workspace: string | null,
|
|
68
|
+
successful: boolean,
|
|
69
|
+
effects: AdvisoryEffects,
|
|
70
|
+
): Promise<void> {
|
|
71
|
+
if (!workspace) return;
|
|
72
|
+
if (!successful) return effects.retainWorkspace(workspace);
|
|
73
|
+
try {
|
|
74
|
+
await removeWorkspace(workspace);
|
|
75
|
+
} catch {
|
|
76
|
+
console.warn(`advisory fixture cleanup failed; retained at ${workspace}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function executeAdvisoryReview(
|
|
81
|
+
input: AdvisoryInput,
|
|
82
|
+
effects: AdvisoryEffects,
|
|
83
|
+
review: AdvisoryReview,
|
|
84
|
+
): Promise<void> {
|
|
85
|
+
let workspace: string | null = null;
|
|
86
|
+
try {
|
|
87
|
+
if (input.baseRevision === null)
|
|
88
|
+
throw new Error("advisory base revision is unavailable");
|
|
89
|
+
workspace = await buildBlindAdvisoryFixture(input.candidateWorkspace, {
|
|
90
|
+
baseRevision: input.baseRevision,
|
|
91
|
+
excludedPaths: input.excludedPaths,
|
|
92
|
+
});
|
|
93
|
+
const response = await input.host.run({
|
|
94
|
+
retainHostDiagnostics: (bytes) =>
|
|
95
|
+
effects.evidence.retainArtifacts([
|
|
96
|
+
{
|
|
97
|
+
id: "sevro.advisory.sevro.host.diagnostics",
|
|
98
|
+
bytes: Buffer.from(bytes),
|
|
99
|
+
},
|
|
100
|
+
]),
|
|
101
|
+
candidateTranscriptRoot: input.candidateTranscriptRoot,
|
|
102
|
+
candidateArtifactRoots: input.candidateArtifactRoots,
|
|
103
|
+
prompt: advisoryPrompt(input.task, [...input.checks]),
|
|
104
|
+
runtimePolicy: gradingRuntimePolicy(input.runtimePolicy),
|
|
105
|
+
runtimeRole: "advisory",
|
|
106
|
+
workspace,
|
|
107
|
+
condition: "passive",
|
|
108
|
+
signal: input.signal,
|
|
109
|
+
});
|
|
110
|
+
review.usage = usage(response);
|
|
111
|
+
const artifacts = scopedHostArtifacts(
|
|
112
|
+
response,
|
|
113
|
+
"sevro.advisory.",
|
|
114
|
+
effects.evidence.artifactRefs,
|
|
115
|
+
input.declaredChecks,
|
|
116
|
+
"sevro.advisory.response",
|
|
117
|
+
);
|
|
118
|
+
await effects.evidence.retainArtifacts(artifacts);
|
|
119
|
+
review.rawResult = await effects.evidence.retainAdvisoryResponse(
|
|
120
|
+
input.host.id,
|
|
121
|
+
response.finalMessage,
|
|
122
|
+
);
|
|
123
|
+
review.assessment = completeAdvisoryAssessment(response);
|
|
124
|
+
review.status = "completed";
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (
|
|
127
|
+
error instanceof HostDiagnosticPersistenceError ||
|
|
128
|
+
error instanceof TrialPersistenceError
|
|
129
|
+
)
|
|
130
|
+
throw error;
|
|
131
|
+
review.status = "failed";
|
|
132
|
+
} finally {
|
|
133
|
+
await cleanupAdvisoryWorkspace(
|
|
134
|
+
workspace,
|
|
135
|
+
review.status === "completed",
|
|
136
|
+
effects,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Advisory execution depends on candidate completion, independently of task grading. */
|
|
142
|
+
export async function runAdvisoryReview(
|
|
143
|
+
input: AdvisoryInput,
|
|
144
|
+
effects: AdvisoryEffects,
|
|
145
|
+
): Promise<AdvisoryReview> {
|
|
146
|
+
const review = defaultAdvisoryReview(input.host);
|
|
147
|
+
if (!input.candidateCompleted || input.signal?.aborted) return review;
|
|
148
|
+
await executeAdvisoryReview(input, effects, review);
|
|
149
|
+
return review;
|
|
150
|
+
}
|
|
@@ -1,40 +1,83 @@
|
|
|
1
1
|
import { isAbsolute } from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { validQualifiedId } from "../value-guards";
|
|
3
|
+
import { validInlineFixture } from "../case-validation";
|
|
3
4
|
import {
|
|
4
5
|
EvaluationConfigurationError,
|
|
5
6
|
type EvaluationOptions,
|
|
6
7
|
type HostAdapter,
|
|
7
8
|
type ResolvedCase,
|
|
8
|
-
} from "./
|
|
9
|
+
} from "./types";
|
|
9
10
|
import {
|
|
10
11
|
prepareGeneratedFixture,
|
|
11
12
|
type GeneratedFixture,
|
|
12
|
-
} from "
|
|
13
|
+
} from "../fixtures/generated";
|
|
13
14
|
import {
|
|
14
15
|
prepareGitHeadChecks,
|
|
15
16
|
type GitHeadCheckDeclaration,
|
|
16
|
-
|
|
17
|
+
type PreparedGitHeadCheck,
|
|
18
|
+
} from "../graders/git-head";
|
|
17
19
|
import {
|
|
18
20
|
isOutputGrader,
|
|
19
21
|
prepareOutputChecks,
|
|
20
22
|
type OutputCheckDeclaration,
|
|
21
|
-
|
|
23
|
+
type PreparedOutputCheck,
|
|
24
|
+
} from "../graders/output";
|
|
22
25
|
import {
|
|
23
26
|
prepareSemanticChecks,
|
|
24
27
|
type SemanticCheckDeclaration,
|
|
25
|
-
|
|
28
|
+
type PreparedSemanticCheck,
|
|
29
|
+
} from "../graders/semantic";
|
|
26
30
|
import {
|
|
27
31
|
prepareShellChecks,
|
|
28
32
|
type ShellCheckDeclaration,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
import {
|
|
33
|
+
type PreparedShellCheck,
|
|
34
|
+
} from "../graders/shell";
|
|
35
|
+
import { hashJson } from "../identity";
|
|
36
|
+
import { fixtureParts } from "../fixtures/preparation";
|
|
32
37
|
import {
|
|
33
38
|
prepareRepositoryFixture,
|
|
34
39
|
type RepositoryFixture,
|
|
35
|
-
} from "
|
|
36
|
-
import { resolvedFixture } from "
|
|
37
|
-
import { isOptionalNonblankString, isRecord } from "
|
|
40
|
+
} from "../fixtures/repository";
|
|
41
|
+
import { resolvedFixture } from "../resolved-case";
|
|
42
|
+
import { isOptionalNonblankString, isRecord } from "../value-guards";
|
|
43
|
+
import type { FixtureSource } from "../fixtures/create";
|
|
44
|
+
|
|
45
|
+
interface CaseCheckDeclarations {
|
|
46
|
+
allBuiltinDeclarations: OutputCheckDeclaration[];
|
|
47
|
+
allShellDeclarations: ShellCheckDeclaration[];
|
|
48
|
+
allGitHeadDeclarations: GitHeadCheckDeclaration[];
|
|
49
|
+
allSemanticDeclarations: SemanticCheckDeclaration[];
|
|
50
|
+
extensionDeclarations: ResolvedCase["checks"];
|
|
51
|
+
replacedBuiltinGraders: string[];
|
|
52
|
+
replaced: Set<string>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface ActiveCheckDeclarations {
|
|
56
|
+
readonly builtinDeclarations: OutputCheckDeclaration[];
|
|
57
|
+
readonly shellDeclarations: ShellCheckDeclaration[];
|
|
58
|
+
readonly gitHeadDeclarations: GitHeadCheckDeclaration[];
|
|
59
|
+
readonly semanticDeclarations: SemanticCheckDeclaration[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface BuiltInCheckPlan {
|
|
63
|
+
readonly prepared: PreparedOutputCheck[];
|
|
64
|
+
readonly preparedShell: PreparedShellCheck[];
|
|
65
|
+
readonly preparedGitHead: PreparedGitHeadCheck[];
|
|
66
|
+
readonly preparedSemantic: PreparedSemanticCheck[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface PreparedChecks
|
|
70
|
+
extends ActiveCheckDeclarations, BuiltInCheckPlan {
|
|
71
|
+
readonly extensionDeclarations: ResolvedCase["checks"];
|
|
72
|
+
readonly replacedBuiltinGraders: string[];
|
|
73
|
+
readonly replaced: ReadonlySet<string>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface EvaluationCheckPlan {
|
|
77
|
+
readonly source: FixtureSource<null>;
|
|
78
|
+
readonly jobs: number;
|
|
79
|
+
readonly checks: PreparedChecks;
|
|
80
|
+
}
|
|
38
81
|
|
|
39
82
|
function validateRootOptions(options: EvaluationOptions): void {
|
|
40
83
|
if (
|
|
@@ -139,23 +182,23 @@ function validateInlineEvaluationFixture(
|
|
|
139
182
|
);
|
|
140
183
|
}
|
|
141
184
|
|
|
142
|
-
function prepareEvaluationFixture(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
} {
|
|
185
|
+
function prepareEvaluationFixture(
|
|
186
|
+
options: EvaluationOptions,
|
|
187
|
+
): FixtureSource<null> {
|
|
146
188
|
const fixture = evaluationFixtureObject(options.case.fixture);
|
|
147
189
|
if ("kind" in fixture)
|
|
148
190
|
return {
|
|
149
|
-
|
|
150
|
-
|
|
191
|
+
kind: "generated",
|
|
192
|
+
fixture: generatedEvaluationFixture(fixture),
|
|
151
193
|
};
|
|
152
194
|
if (Object.hasOwn(fixture, "sourceRef"))
|
|
153
195
|
return {
|
|
154
|
-
|
|
155
|
-
|
|
196
|
+
kind: "repository",
|
|
197
|
+
fixture: repositoryEvaluationFixture(fixture),
|
|
198
|
+
repository: null,
|
|
156
199
|
};
|
|
157
200
|
validateInlineEvaluationFixture(fixture);
|
|
158
|
-
return {
|
|
201
|
+
return { kind: "inline", files: options.case.fixture.files };
|
|
159
202
|
}
|
|
160
203
|
|
|
161
204
|
function validateTrialInteger(value: number, message: string): void {
|
|
@@ -173,15 +216,12 @@ function validatePassThreshold(value: number): void {
|
|
|
173
216
|
function validateRequiredEvidence(ids: string[]): void {
|
|
174
217
|
if (
|
|
175
218
|
new Set(ids).size !== ids.length ||
|
|
176
|
-
ids.some((id) =>
|
|
219
|
+
ids.some((id) => !validQualifiedId(id))
|
|
177
220
|
)
|
|
178
221
|
throw new EvaluationConfigurationError("invalid required evidence IDs");
|
|
179
222
|
}
|
|
180
223
|
|
|
181
|
-
function prepareTrialParameters(
|
|
182
|
-
options: EvaluationOptions,
|
|
183
|
-
state: ReturnType<typeof prepareEvaluationFixture>,
|
|
184
|
-
) {
|
|
224
|
+
function prepareTrialParameters(options: EvaluationOptions): number {
|
|
185
225
|
validateTrialInteger(
|
|
186
226
|
options.trialCount,
|
|
187
227
|
"trial count must be a positive integer",
|
|
@@ -190,10 +230,10 @@ function prepareTrialParameters(
|
|
|
190
230
|
validateTrialInteger(jobs, "jobs must be a positive integer");
|
|
191
231
|
validatePassThreshold(options.passThreshold);
|
|
192
232
|
validateRequiredEvidence(options.case.requiredEvidence);
|
|
193
|
-
return
|
|
233
|
+
return jobs;
|
|
194
234
|
}
|
|
195
235
|
|
|
196
|
-
function declaredCaseChecks(options: EvaluationOptions) {
|
|
236
|
+
function declaredCaseChecks(options: EvaluationOptions): CaseCheckDeclarations {
|
|
197
237
|
const allBuiltinDeclarations = options.case.checks.filter((check) =>
|
|
198
238
|
isOutputGrader(check.grader),
|
|
199
239
|
) as OutputCheckDeclaration[];
|
|
@@ -227,8 +267,6 @@ function declaredCaseChecks(options: EvaluationOptions) {
|
|
|
227
267
|
};
|
|
228
268
|
}
|
|
229
269
|
|
|
230
|
-
type CaseCheckDeclarations = ReturnType<typeof declaredCaseChecks>;
|
|
231
|
-
|
|
232
270
|
function validateBuiltInReplacements(context: CaseCheckDeclarations): void {
|
|
233
271
|
const {
|
|
234
272
|
allBuiltinDeclarations,
|
|
@@ -260,7 +298,9 @@ function validateBuiltInReplacements(context: CaseCheckDeclarations): void {
|
|
|
260
298
|
);
|
|
261
299
|
}
|
|
262
300
|
|
|
263
|
-
function activeCheckDeclarations(
|
|
301
|
+
function activeCheckDeclarations(
|
|
302
|
+
context: CaseCheckDeclarations,
|
|
303
|
+
): ActiveCheckDeclarations {
|
|
264
304
|
const {
|
|
265
305
|
allBuiltinDeclarations,
|
|
266
306
|
allShellDeclarations,
|
|
@@ -288,10 +328,6 @@ function activeCheckDeclarations(context: CaseCheckDeclarations) {
|
|
|
288
328
|
};
|
|
289
329
|
}
|
|
290
330
|
|
|
291
|
-
type CaseCheckPlan = ReturnType<typeof prepareTrialParameters> &
|
|
292
|
-
CaseCheckDeclarations &
|
|
293
|
-
ReturnType<typeof activeCheckDeclarations>;
|
|
294
|
-
|
|
295
331
|
function validateSemanticRoute(
|
|
296
332
|
options: EvaluationOptions,
|
|
297
333
|
checks: SemanticCheckDeclaration[],
|
|
@@ -306,11 +342,8 @@ function validateSemanticRoute(
|
|
|
306
342
|
);
|
|
307
343
|
}
|
|
308
344
|
|
|
309
|
-
function validateAdvisoryGitFixture(
|
|
310
|
-
|
|
311
|
-
generated: GeneratedFixture | null,
|
|
312
|
-
): void {
|
|
313
|
-
if (!generated && !options.case.fixture.sourceRef)
|
|
345
|
+
function validateAdvisoryGitFixture(source: FixtureSource<null>): void {
|
|
346
|
+
if (source.kind === "inline")
|
|
314
347
|
throw new EvaluationConfigurationError(
|
|
315
348
|
"advisory review requires a Git fixture",
|
|
316
349
|
);
|
|
@@ -335,7 +368,7 @@ function validateAdvisoryExclusions(paths: string[]): void {
|
|
|
335
368
|
|
|
336
369
|
function validateAdvisoryRoute(
|
|
337
370
|
options: EvaluationOptions,
|
|
338
|
-
|
|
371
|
+
source: FixtureSource<null>,
|
|
339
372
|
): void {
|
|
340
373
|
const host = options.advisoryHost;
|
|
341
374
|
if (!host) {
|
|
@@ -345,7 +378,7 @@ function validateAdvisoryRoute(
|
|
|
345
378
|
);
|
|
346
379
|
return;
|
|
347
380
|
}
|
|
348
|
-
validateAdvisoryGitFixture(
|
|
381
|
+
validateAdvisoryGitFixture(source);
|
|
349
382
|
validateAdvisoryIdentity(host);
|
|
350
383
|
validateAdvisoryExclusions(options.advisoryExcludedPaths ?? []);
|
|
351
384
|
}
|
|
@@ -367,12 +400,11 @@ function validateShellRoute(
|
|
|
367
400
|
);
|
|
368
401
|
}
|
|
369
402
|
|
|
370
|
-
function validateGitHeadRoute(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
)
|
|
403
|
+
function validateGitHeadRoute(
|
|
404
|
+
source: FixtureSource<null>,
|
|
405
|
+
checks: GitHeadCheckDeclaration[],
|
|
406
|
+
): void {
|
|
407
|
+
if (checks.length && source.kind === "inline")
|
|
376
408
|
throw new EvaluationConfigurationError(
|
|
377
409
|
"Git HEAD checks require a Git fixture",
|
|
378
410
|
);
|
|
@@ -443,8 +475,8 @@ function validateInlinePaths(files: ResolvedCase["fixture"]["files"]): void {
|
|
|
443
475
|
|
|
444
476
|
function prepareBuiltInChecks(
|
|
445
477
|
options: EvaluationOptions,
|
|
446
|
-
context:
|
|
447
|
-
) {
|
|
478
|
+
context: CaseCheckDeclarations,
|
|
479
|
+
): BuiltInCheckPlan {
|
|
448
480
|
const {
|
|
449
481
|
allBuiltinDeclarations,
|
|
450
482
|
allShellDeclarations,
|
|
@@ -483,28 +515,32 @@ function prepareBuiltInChecks(
|
|
|
483
515
|
|
|
484
516
|
function prepareCheckPlan(
|
|
485
517
|
options: EvaluationOptions,
|
|
486
|
-
|
|
487
|
-
) {
|
|
518
|
+
source: FixtureSource<null>,
|
|
519
|
+
): PreparedChecks {
|
|
488
520
|
const declarations = declaredCaseChecks(options);
|
|
489
521
|
validateBuiltInReplacements(declarations);
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
validateSemanticRoute(options, context.semanticDeclarations);
|
|
496
|
-
validateAdvisoryRoute(options, context.generated);
|
|
497
|
-
validateShellRoute(options, context.shellDeclarations);
|
|
498
|
-
validateGitHeadRoute(context);
|
|
522
|
+
const active = activeCheckDeclarations(declarations);
|
|
523
|
+
validateSemanticRoute(options, active.semanticDeclarations);
|
|
524
|
+
validateAdvisoryRoute(options, source);
|
|
525
|
+
validateShellRoute(options, active.shellDeclarations);
|
|
526
|
+
validateGitHeadRoute(source, active.gitHeadDeclarations);
|
|
499
527
|
validateCaseCheckIds(options.case.checks);
|
|
500
|
-
validateExtensionGraders(options,
|
|
528
|
+
validateExtensionGraders(options, declarations.extensionDeclarations);
|
|
501
529
|
validateResolvedExtensionCase(options);
|
|
502
|
-
return {
|
|
530
|
+
return {
|
|
531
|
+
...active,
|
|
532
|
+
...prepareBuiltInChecks(options, declarations),
|
|
533
|
+
extensionDeclarations: declarations.extensionDeclarations,
|
|
534
|
+
replacedBuiltinGraders: declarations.replacedBuiltinGraders,
|
|
535
|
+
replaced: declarations.replaced,
|
|
536
|
+
};
|
|
503
537
|
}
|
|
504
538
|
|
|
505
|
-
export function prepareEvaluationChecks(
|
|
539
|
+
export function prepareEvaluationChecks(
|
|
540
|
+
options: EvaluationOptions,
|
|
541
|
+
): EvaluationCheckPlan {
|
|
506
542
|
validateEvaluationInputs(options);
|
|
507
|
-
const
|
|
508
|
-
const
|
|
509
|
-
return prepareCheckPlan(options,
|
|
543
|
+
const source = prepareEvaluationFixture(options);
|
|
544
|
+
const jobs = prepareTrialParameters(options);
|
|
545
|
+
return { source, jobs, checks: prepareCheckPlan(options, source) };
|
|
510
546
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { checkpointRunOwner, type RunOwner } from "../run-owner";
|
|
2
|
+
import { summarizeAssessments, type Assessment } from "../results";
|
|
3
|
+
import type { Diagnostic } from "../contract-types";
|
|
4
|
+
import type { RunEvidenceDataTrialEvidence } from "../schema-types";
|
|
5
|
+
import type { CaseSummary, TrialSummary } from "./types";
|
|
6
|
+
|
|
7
|
+
type TrialEvidence = RunEvidenceDataTrialEvidence;
|
|
8
|
+
|
|
9
|
+
export interface CompletedTrial {
|
|
10
|
+
readonly summary: TrialSummary;
|
|
11
|
+
readonly evidence: TrialEvidence;
|
|
12
|
+
readonly diagnostic?: Diagnostic;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CollectedResults {
|
|
16
|
+
readonly caseSummary: CaseSummary;
|
|
17
|
+
readonly trials: readonly TrialEvidence[];
|
|
18
|
+
readonly diagnostic: Diagnostic | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Registers retained trials before checkpointing; owns their final ordering. */
|
|
22
|
+
export class ResultCollector {
|
|
23
|
+
private readonly summaries: TrialSummary[] = [];
|
|
24
|
+
private readonly evidence: TrialEvidence[] = [];
|
|
25
|
+
private readonly diagnostics: { trial: number; diagnostic: Diagnostic }[] =
|
|
26
|
+
[];
|
|
27
|
+
|
|
28
|
+
constructor(private readonly owner: RunOwner) {}
|
|
29
|
+
|
|
30
|
+
complete(record: CompletedTrial): void {
|
|
31
|
+
this.summaries.push(record.summary);
|
|
32
|
+
this.summaries.sort((left, right) => left.trial - right.trial);
|
|
33
|
+
this.evidence.push(record.evidence);
|
|
34
|
+
this.evidence.sort((left, right) => left.trial - right.trial);
|
|
35
|
+
if (record.diagnostic)
|
|
36
|
+
this.diagnostics.push({
|
|
37
|
+
trial: record.summary.trial,
|
|
38
|
+
diagnostic: record.diagnostic,
|
|
39
|
+
});
|
|
40
|
+
this.checkpoint("active");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
snapshot(input: {
|
|
44
|
+
caseId: string;
|
|
45
|
+
passThreshold: number;
|
|
46
|
+
cancelled: boolean;
|
|
47
|
+
}): CollectedResults {
|
|
48
|
+
const assessment: Assessment =
|
|
49
|
+
!this.summaries.length && input.cancelled
|
|
50
|
+
? {
|
|
51
|
+
execution: { status: "cancelled" },
|
|
52
|
+
grading: { status: "not_requested" },
|
|
53
|
+
task: { verdict: "not_assessed" },
|
|
54
|
+
}
|
|
55
|
+
: summarizeAssessments(this.summaries, input.passThreshold);
|
|
56
|
+
const diagnostic = this.diagnostics.sort(
|
|
57
|
+
(left, right) => left.trial - right.trial,
|
|
58
|
+
)[0]?.diagnostic;
|
|
59
|
+
return {
|
|
60
|
+
caseSummary: {
|
|
61
|
+
caseId: input.caseId,
|
|
62
|
+
...assessment,
|
|
63
|
+
trials: this.summaries,
|
|
64
|
+
},
|
|
65
|
+
trials: this.evidence,
|
|
66
|
+
diagnostic,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
checkpoint(status: "active" | "complete" | "interrupted"): void {
|
|
71
|
+
checkpointRunOwner(this.owner, this.checkpointTrials(), status);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
diagnoseFailure(): void {
|
|
75
|
+
try {
|
|
76
|
+
checkpointRunOwner(this.owner, this.checkpointTrials(), "diagnostic");
|
|
77
|
+
} catch {
|
|
78
|
+
/* Preserve the original failure and retained artifacts. */
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private checkpointTrials() {
|
|
83
|
+
return this.summaries.map((trial) => ({
|
|
84
|
+
trial: trial.trial,
|
|
85
|
+
artifactPath: trial.artifactPath,
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ResultCollector } from "./collection";
|
|
2
|
+
import type { PreparedEvaluation } from "./plan";
|
|
3
|
+
import type { PreparationArtifactReference, RunResources } from "./resources";
|
|
4
|
+
|
|
5
|
+
export interface EvaluationContext {
|
|
6
|
+
readonly prepared: PreparedEvaluation;
|
|
7
|
+
readonly resources: RunResources;
|
|
8
|
+
readonly results: ResultCollector;
|
|
9
|
+
readonly preparationArtifacts: readonly PreparationArtifactReference[];
|
|
10
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { hostArtifacts } from "
|
|
2
|
-
import type { HostResult
|
|
3
|
-
import { runtimeSeedSources, type RuntimePolicy } from "
|
|
1
|
+
import { hostArtifacts } from "../evidence/host-results";
|
|
2
|
+
import type { HostResult } from "./types";
|
|
3
|
+
import { runtimeSeedSources, type RuntimePolicy } from "../runtime/config";
|
|
4
4
|
export function scopedHostArtifacts(
|
|
5
5
|
response: HostResult,
|
|
6
6
|
prefix: string,
|
|
7
|
-
artifacts: { id: string }[],
|
|
8
|
-
checks:
|
|
7
|
+
artifacts: readonly { id: string }[],
|
|
8
|
+
checks: readonly { id: string }[],
|
|
9
9
|
reservedId: string,
|
|
10
10
|
) {
|
|
11
11
|
return hostArtifacts(
|