@bjoernrochel/sevro 0.1.0-rc.2 → 0.1.0-rc.21
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 +170 -0
- package/LICENSE +63 -136
- package/README.md +83 -66
- package/docs/README.md +44 -0
- package/docs/acknowledgements.md +14 -0
- package/docs/architecture.md +146 -0
- package/docs/assets/README.md +27 -0
- package/docs/assets/sevro-logo.png +0 -0
- package/docs/assets/sevro-symbol.svg +1 -0
- package/docs/assets/sevro-wordmark.svg +1 -0
- package/docs/builtin-graders-v1.md +41 -13
- package/docs/codex-host.md +184 -52
- package/docs/contracts.md +19 -0
- package/docs/creating-cases.md +139 -0
- package/docs/development-cli.md +190 -30
- package/docs/documentation-quality.md +61 -0
- package/docs/evaluation-workflow.md +110 -0
- package/docs/evidence/code-mode-controls-71.md +64 -0
- package/docs/evidence/code-mode-programs-85.md +64 -0
- package/docs/evidence/codex-state-73/README.md +204 -0
- package/docs/evidence/codex-state-73/darrow-migration.patch +182 -0
- package/docs/evidence/codex-state-73/results.json +661 -0
- package/docs/evidence/local-http-74.md +104 -0
- package/docs/evidence/runtime-startup-30/README.md +185 -0
- package/docs/evidence/runtime-startup-30/after.json +319 -0
- package/docs/evidence/runtime-startup-30/baseline-timeout.jsonl +2 -0
- package/docs/evidence/runtime-startup-30/before.json +403 -0
- package/docs/evidence/runtime-startup-30/consumer-smoke.json +63 -0
- package/docs/evidence/runtime-startup-30/full-policy-diagnostic.jsonl +3 -0
- package/docs/evidence/runtime-startup-30/minimal-policy-diagnostic.jsonl +3 -0
- package/docs/evidence/runtime-startup-30/plugin-template-assessment.json +20 -0
- package/docs/evidence/runtime-startup-30/seedless-timeout.jsonl +2 -0
- package/docs/evidence/skill-reads-70/results.json +823 -0
- package/docs/evidence.md +21 -0
- package/docs/extension-protocol-v1.md +50 -16
- package/docs/fixture-cleanup-validation.md +3 -0
- package/docs/getting-started.md +102 -0
- package/docs/guide-evaluation.md +89 -0
- package/docs/guide-verification.json +239 -0
- package/docs/identity-v1.md +35 -1
- package/docs/installing.md +88 -0
- package/docs/licenses/BUSL-1.1-0.1.0-rc.2.txt +159 -0
- package/docs/licensing.md +42 -0
- package/docs/native-controls.md +76 -5
- package/docs/native-hosts.md +228 -0
- package/docs/reading-results.md +141 -0
- package/docs/recipes.md +489 -0
- package/docs/releases.md +81 -40
- package/docs/report-v1.md +29 -1
- package/docs/results-v1.md +180 -0
- package/docs/run-settings-v1.md +147 -0
- package/docs/running-evaluations.md +31 -0
- package/docs/runtime-v1.md +614 -0
- package/docs/specs/repository-guide.md +58 -0
- package/docs/troubleshooting.md +30 -0
- package/docs/typescript-quality.md +234 -0
- package/docs/usability-study.md +114 -0
- package/examples/basic/host.ts +2 -2
- 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 +39 -6
- package/schemas/report-v1.schema.json +9 -0
- package/schemas/run-evidence-v1.schema.json +2 -1
- package/schemas/runtime-v1.schema.json +193 -0
- package/src/advisory.ts +10 -5
- package/src/candidate-artifacts.ts +208 -0
- package/src/candidate-codex-state.ts +185 -0
- package/src/case-validation.ts +105 -0
- package/src/cli/cancellation.ts +20 -0
- package/src/cli/command.ts +81 -0
- package/src/cli/completion.ts +15 -0
- package/src/cli/demo.ts +59 -0
- package/src/cli/evaluation.ts +55 -0
- package/src/cli/extension.ts +79 -0
- package/src/cli/help.ts +222 -0
- package/src/cli/hosts.ts +59 -0
- package/src/cli/init-settings.ts +30 -0
- package/src/cli/init.ts +111 -0
- package/src/cli/invocation.ts +627 -0
- package/src/cli/loading.ts +151 -0
- package/src/cli/preparation.ts +163 -0
- package/src/cli/presentation.ts +91 -0
- package/src/cli/progress.ts +6 -0
- package/src/cli/run-manifest.ts +133 -0
- package/src/cli/run-options.ts +101 -0
- package/src/cli/run-overrides.ts +83 -0
- package/src/cli/settings.ts +160 -0
- package/src/cli/summary.ts +43 -0
- package/src/cli.ts +13 -843
- package/src/contract-types.ts +94 -0
- package/src/engine.ts +19 -2373
- package/src/evaluation/advisory.ts +150 -0
- package/src/evaluation/check-plan.ts +510 -0
- package/src/evaluation/collection.ts +88 -0
- package/src/evaluation/context.ts +10 -0
- package/src/evaluation/grading-host.ts +39 -0
- package/src/evaluation/grading.ts +258 -0
- package/src/evaluation/invocation-plan.ts +548 -0
- package/src/evaluation/plan.ts +736 -0
- package/src/evaluation/progress.ts +19 -0
- package/src/evaluation/resources.ts +241 -0
- package/src/evaluation/run.ts +206 -0
- package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +3 -1
- package/src/evaluation/semantic.ts +312 -0
- package/src/evaluation/trial.ts +866 -0
- package/src/evaluation/types.ts +207 -0
- package/src/evidence/host-results.ts +92 -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 +228 -148
- package/src/extension-session.ts +326 -195
- package/src/fixtures/advisory.ts +338 -0
- package/src/fixtures/bin.ts +57 -0
- package/src/{fixture-cleanup.ts → fixtures/cleanup.ts} +13 -7
- package/src/fixtures/create.ts +187 -0
- package/src/fixtures/generated.ts +300 -0
- package/src/fixtures/git-hooks.ts +24 -0
- package/src/fixtures/preparation.ts +270 -0
- package/src/{repository-fixture.ts → fixtures/repository.ts} +207 -85
- package/src/fixtures/setup.ts +224 -0
- package/src/fixtures/tools.ts +88 -0
- package/src/fixtures/workspace-state.ts +212 -0
- package/src/generated/cli-result.cjs +2 -0
- package/src/generated/cli-result.d.cts +3 -0
- package/src/generated/extension.cjs +2 -0
- package/src/generated/extension.d.cts +3 -0
- package/src/generated/report.cjs +2 -0
- package/src/generated/report.d.cts +3 -0
- package/src/generated/run-evidence.cjs +2 -0
- package/src/generated/run-evidence.d.cts +3 -0
- package/src/generated/runtime.cjs +2 -0
- package/src/generated/runtime.d.cts +3 -0
- package/src/graders/artifact.ts +56 -23
- package/src/graders/git-head.ts +79 -75
- package/src/graders/output.ts +222 -140
- package/src/graders/semantic.ts +102 -43
- package/src/graders/shell.ts +379 -207
- package/src/host-diagnostic-redaction.ts +52 -0
- package/src/host-diagnostics.ts +319 -0
- package/src/hosts/claude-continuation.ts +63 -18
- package/src/hosts/claude-credential.ts +43 -62
- package/src/hosts/claude-events.ts +86 -51
- package/src/hosts/claude-keychain.ts +59 -0
- package/src/hosts/claude-native-goal.ts +57 -33
- package/src/hosts/claude-process.ts +111 -0
- package/src/hosts/claude-repository-invocation.ts +208 -117
- package/src/hosts/claude-settings.ts +240 -21
- package/src/hosts/claude-skill-activations.ts +166 -0
- package/src/hosts/claude-state.ts +403 -0
- package/src/hosts/claude-tool-calls.ts +171 -106
- package/src/hosts/claude.ts +561 -451
- package/src/hosts/codex-app-server.ts +326 -178
- package/src/hosts/codex-configuration.ts +44 -18
- package/src/hosts/codex-events.ts +97 -60
- package/src/hosts/codex-exec-controls.ts +516 -0
- package/src/hosts/codex-invocation.ts +70 -0
- package/src/hosts/codex-marketplace.ts +283 -0
- package/src/hosts/codex-native-calls.ts +546 -500
- package/src/hosts/codex-process.ts +202 -0
- package/src/hosts/codex-profile.ts +257 -28
- package/src/hosts/codex-session-files.ts +106 -0
- package/src/hosts/codex-state.ts +492 -0
- package/src/hosts/codex.ts +783 -832
- package/src/hosts/isolation-common.ts +94 -0
- package/src/hosts/isolation-roots.ts +54 -27
- package/src/hosts/isolation.ts +10 -0
- package/src/hosts/linux-sandbox.ts +159 -0
- package/src/hosts/mac-sandbox.ts +187 -61
- package/src/hosts/native-controls.ts +152 -62
- package/src/hosts/process-lifecycle.ts +37 -0
- package/src/hosts/protected-worktrees.ts +51 -19
- package/src/hosts/skill-hook-catalog.ts +131 -0
- package/src/hosts/skill-hook-handler.ts +374 -0
- package/src/hosts/skill-hooks.ts +580 -0
- package/src/hosts/workspace-fingerprint.ts +55 -35
- package/src/identity.ts +102 -48
- package/src/instrumentation.ts +109 -48
- package/src/native-transcript-state.ts +131 -0
- package/src/native-transcript-view.ts +90 -0
- package/src/native-transcripts.ts +286 -0
- package/src/process-lifecycle.ts +150 -0
- package/src/provenance.ts +161 -81
- package/src/prune.ts +215 -0
- package/src/report.ts +172 -140
- package/src/resolved-case.ts +33 -0
- package/src/results-lock.ts +29 -0
- package/src/results.ts +133 -86
- package/src/run-owner.ts +154 -63
- package/src/runtime/config.ts +456 -0
- package/src/runtime/discovery-apple.ts +90 -0
- package/src/runtime/discovery-providers.ts +63 -0
- package/src/runtime/discovery.ts +70 -0
- package/src/runtime/hook-processes.ts +97 -0
- package/src/runtime/hooks.ts +476 -0
- package/src/runtime/paths.ts +313 -0
- package/src/runtime/query.ts +85 -0
- package/src/runtime/seeds.ts +134 -0
- package/src/runtime/shared-cache.ts +143 -0
- package/src/runtime/state.ts +143 -0
- package/src/schema-types.ts +198 -0
- package/src/schema.ts +15 -19
- package/src/transcript-retention.ts +146 -0
- package/src/value-guards.ts +20 -0
- package/src/advisory-fixture.ts +0 -282
- package/src/fixture-bin.ts +0 -87
- package/src/fixture-setup.ts +0 -163
- package/src/generated-fixture.ts +0 -220
- package/src/git-hooks.ts +0 -63
- package/src/hosts/claude-nested-skills.ts +0 -218
- package/src/hosts/codex-command-output.ts +0 -399
- package/src/hosts/codex-executor-command.ts +0 -195
- package/src/hosts/codex-skill-reads.ts +0 -391
- package/src/preparation.ts +0 -211
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { hostArtifacts } from "../evidence/host-results";
|
|
2
|
+
import type { HostResult } from "./types";
|
|
3
|
+
import { runtimeSeedSources, type RuntimePolicy } from "../runtime/config";
|
|
4
|
+
export function scopedHostArtifacts(
|
|
5
|
+
response: HostResult,
|
|
6
|
+
prefix: string,
|
|
7
|
+
artifacts: readonly { id: string }[],
|
|
8
|
+
checks: readonly { id: string }[],
|
|
9
|
+
reservedId: string,
|
|
10
|
+
) {
|
|
11
|
+
return hostArtifacts(
|
|
12
|
+
{
|
|
13
|
+
...response,
|
|
14
|
+
artifacts: response.artifacts?.map((item) => ({
|
|
15
|
+
...item,
|
|
16
|
+
id: `${prefix}${item.id}`,
|
|
17
|
+
})),
|
|
18
|
+
},
|
|
19
|
+
new Set([
|
|
20
|
+
...artifacts.map((item) => item.id),
|
|
21
|
+
...checks.map((item) => item.id),
|
|
22
|
+
reservedId,
|
|
23
|
+
]),
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
export function gradingRuntimePolicy(
|
|
27
|
+
policy: RuntimePolicy | undefined,
|
|
28
|
+
responseOnly = false,
|
|
29
|
+
) {
|
|
30
|
+
if (!policy) return undefined;
|
|
31
|
+
return {
|
|
32
|
+
...policy,
|
|
33
|
+
hooks: undefined,
|
|
34
|
+
seedReadDenyRoots: runtimeSeedSources(policy),
|
|
35
|
+
seeds: responseOnly
|
|
36
|
+
? (policy.seeds ?? []).filter((seed) => seed.roles?.includes("semantic"))
|
|
37
|
+
: policy.seeds,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assessGitHeadCheck,
|
|
3
|
+
gitHeadState,
|
|
4
|
+
type PreparedGitHeadCheck,
|
|
5
|
+
} from "../graders/git-head";
|
|
6
|
+
import { gradeOutput, type PreparedOutputCheck } from "../graders/output";
|
|
7
|
+
import {
|
|
8
|
+
assessShellCheck,
|
|
9
|
+
runShellCheck,
|
|
10
|
+
type PreparedShellCheck,
|
|
11
|
+
} from "../graders/shell";
|
|
12
|
+
import { evaluationProtectedRoots } from "../hosts/isolation-roots";
|
|
13
|
+
import { sha256 } from "../identity";
|
|
14
|
+
import type { TrialObservation } from "../evidence/trial-writer";
|
|
15
|
+
import {
|
|
16
|
+
ExtensionSourceChangedError,
|
|
17
|
+
type EvaluationRequest,
|
|
18
|
+
type EvaluationResult,
|
|
19
|
+
} from "../extension-session";
|
|
20
|
+
import type { CheckOutcome } from "../results";
|
|
21
|
+
|
|
22
|
+
export interface GradingFailure {
|
|
23
|
+
readonly message: string;
|
|
24
|
+
readonly cancelable: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface GradingResult {
|
|
28
|
+
checks: CheckOutcome[];
|
|
29
|
+
observations: TrialObservation[];
|
|
30
|
+
failure: GradingFailure | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface GradingFailureEffects {
|
|
34
|
+
/** Close admission when failure is detected, before an async result returns. */
|
|
35
|
+
onFailure(failure: GradingFailure): void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function failedGrading(
|
|
39
|
+
checks: CheckOutcome[],
|
|
40
|
+
observations: TrialObservation[],
|
|
41
|
+
message: string,
|
|
42
|
+
effects: GradingFailureEffects,
|
|
43
|
+
): GradingResult {
|
|
44
|
+
const failure = { message, cancelable: true };
|
|
45
|
+
effects.onFailure(failure);
|
|
46
|
+
return { checks, observations, failure };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function gradeCandidateOutput(input: {
|
|
50
|
+
readonly result: { finalMessage: string | null; complete: boolean } | null;
|
|
51
|
+
readonly checks: readonly PreparedOutputCheck[];
|
|
52
|
+
readonly evidenceRefs: string[];
|
|
53
|
+
}): GradingResult {
|
|
54
|
+
try {
|
|
55
|
+
if (!input.result) throw new Error("host result is unavailable");
|
|
56
|
+
const checks = gradeOutput(
|
|
57
|
+
input.result.finalMessage,
|
|
58
|
+
input.result.complete,
|
|
59
|
+
[...input.checks],
|
|
60
|
+
).map((check) => ({ ...check, evidenceRefs: [...input.evidenceRefs] }));
|
|
61
|
+
return { checks, observations: [], failure: null };
|
|
62
|
+
} catch {
|
|
63
|
+
return {
|
|
64
|
+
checks: [],
|
|
65
|
+
observations: [],
|
|
66
|
+
failure: {
|
|
67
|
+
message: "output grading did not complete",
|
|
68
|
+
cancelable: false,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface ShellGradingInput {
|
|
75
|
+
readonly checks: readonly PreparedShellCheck[];
|
|
76
|
+
readonly protectedRoots:
|
|
77
|
+
Parameters<typeof evaluationProtectedRoots>[0] | null;
|
|
78
|
+
readonly execution: Omit<
|
|
79
|
+
Parameters<typeof runShellCheck>[1],
|
|
80
|
+
"protectedRoots"
|
|
81
|
+
>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function gradeShellCheck(
|
|
85
|
+
check: PreparedShellCheck,
|
|
86
|
+
execution: Parameters<typeof runShellCheck>[1],
|
|
87
|
+
): Promise<{ check: CheckOutcome; observation: TrialObservation }> {
|
|
88
|
+
const result = await runShellCheck(check, execution);
|
|
89
|
+
const graded = assessShellCheck(check, result);
|
|
90
|
+
const id = `sevro.observation.shell.${check.id}`;
|
|
91
|
+
return {
|
|
92
|
+
observation: {
|
|
93
|
+
id,
|
|
94
|
+
source: "sevro.shell",
|
|
95
|
+
completeness: "complete",
|
|
96
|
+
data: {
|
|
97
|
+
exitCode: result.exitCode,
|
|
98
|
+
expectedExitCode: check.expectedExitCode,
|
|
99
|
+
...(result.stdout === null
|
|
100
|
+
? {}
|
|
101
|
+
: {
|
|
102
|
+
stdoutSha256: sha256(result.stdout),
|
|
103
|
+
stdoutByteLength: Buffer.byteLength(result.stdout, "utf8"),
|
|
104
|
+
}),
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
check: {
|
|
108
|
+
id: check.id,
|
|
109
|
+
grader: "sevro.shell",
|
|
110
|
+
status: graded.passed ? "passed" : "failed",
|
|
111
|
+
detail: graded.detail,
|
|
112
|
+
evidenceRefs: [id],
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function gradeShellChecks(
|
|
118
|
+
input: ShellGradingInput,
|
|
119
|
+
effects: GradingFailureEffects,
|
|
120
|
+
): Promise<GradingResult> {
|
|
121
|
+
const checks: CheckOutcome[] = [];
|
|
122
|
+
const observations: TrialObservation[] = [];
|
|
123
|
+
try {
|
|
124
|
+
if (!input.protectedRoots)
|
|
125
|
+
throw new Error("shell checks require explicit protected source roots");
|
|
126
|
+
const protectedRoots = await evaluationProtectedRoots(input.protectedRoots);
|
|
127
|
+
for (const check of input.checks) {
|
|
128
|
+
const graded = await gradeShellCheck(check, {
|
|
129
|
+
...input.execution,
|
|
130
|
+
protectedRoots,
|
|
131
|
+
protectedRootsCanonical: true,
|
|
132
|
+
});
|
|
133
|
+
checks.push(graded.check);
|
|
134
|
+
observations.push(graded.observation);
|
|
135
|
+
}
|
|
136
|
+
return { checks, observations, failure: null };
|
|
137
|
+
} catch {
|
|
138
|
+
return failedGrading(
|
|
139
|
+
checks,
|
|
140
|
+
observations,
|
|
141
|
+
"shell grading did not complete",
|
|
142
|
+
effects,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function gradeGitHeadChecks(
|
|
148
|
+
input: {
|
|
149
|
+
readonly checks: readonly PreparedGitHeadCheck[];
|
|
150
|
+
readonly base: string | null;
|
|
151
|
+
readonly workspace: string;
|
|
152
|
+
readonly signal?: AbortSignal;
|
|
153
|
+
},
|
|
154
|
+
effects: GradingFailureEffects,
|
|
155
|
+
): Promise<GradingResult> {
|
|
156
|
+
const observations: TrialObservation[] = [];
|
|
157
|
+
try {
|
|
158
|
+
const base = input.base;
|
|
159
|
+
if (base === null) throw new Error("Git HEAD base revision is unavailable");
|
|
160
|
+
const state = await gitHeadState(input.workspace, base, input.signal);
|
|
161
|
+
const id = "sevro.observation.git-head";
|
|
162
|
+
observations.push({
|
|
163
|
+
id,
|
|
164
|
+
source: "sevro.git-head",
|
|
165
|
+
completeness: "complete",
|
|
166
|
+
data: {
|
|
167
|
+
baseRevision: base,
|
|
168
|
+
currentRevision: state.currentRevision,
|
|
169
|
+
baseAncestor: state.baseAncestor,
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
const checks = input.checks.map((check): CheckOutcome => {
|
|
173
|
+
const graded = assessGitHeadCheck(check, base, state);
|
|
174
|
+
return {
|
|
175
|
+
id: check.id,
|
|
176
|
+
grader: "sevro.git-head",
|
|
177
|
+
status: graded.passed ? "passed" : "failed",
|
|
178
|
+
detail: graded.detail,
|
|
179
|
+
evidenceRefs: [id],
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
return { checks, observations, failure: null };
|
|
183
|
+
} catch {
|
|
184
|
+
return failedGrading(
|
|
185
|
+
[],
|
|
186
|
+
observations,
|
|
187
|
+
"Git HEAD grading did not complete",
|
|
188
|
+
effects,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function extensionCheckResult(
|
|
194
|
+
check: EvaluationResult["checks"][number],
|
|
195
|
+
declared: ReadonlyMap<string, string>,
|
|
196
|
+
): CheckOutcome {
|
|
197
|
+
const grader = declared.get(check.id);
|
|
198
|
+
if (grader === undefined)
|
|
199
|
+
throw new Error("extension returned an undeclared check");
|
|
200
|
+
return {
|
|
201
|
+
id: check.id,
|
|
202
|
+
grader,
|
|
203
|
+
status: check.status,
|
|
204
|
+
...(check.detail ? { detail: check.detail } : {}),
|
|
205
|
+
evidenceRefs: check.evidenceRefs,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface ExtensionGradingResult {
|
|
210
|
+
checks: CheckOutcome[];
|
|
211
|
+
metrics: EvaluationResult["metrics"];
|
|
212
|
+
domainOutcomes: NonNullable<EvaluationResult["domainOutcomes"]>;
|
|
213
|
+
recommendation: "passed" | "failed" | "not_assessed" | null;
|
|
214
|
+
failure: GradingFailure | null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export async function gradeExtensionChecks(
|
|
218
|
+
input: {
|
|
219
|
+
readonly evaluate: (
|
|
220
|
+
request: EvaluationRequest,
|
|
221
|
+
) => Promise<EvaluationResult>;
|
|
222
|
+
readonly request: EvaluationRequest;
|
|
223
|
+
readonly declarations: readonly { id: string; grader: string }[];
|
|
224
|
+
},
|
|
225
|
+
effects: GradingFailureEffects,
|
|
226
|
+
): Promise<ExtensionGradingResult> {
|
|
227
|
+
try {
|
|
228
|
+
const result = await input.evaluate(input.request);
|
|
229
|
+
const declared = new Map(
|
|
230
|
+
input.declarations.map((check) => [check.id, check.grader]),
|
|
231
|
+
);
|
|
232
|
+
return {
|
|
233
|
+
checks: result.checks.map((check) =>
|
|
234
|
+
extensionCheckResult(check, declared),
|
|
235
|
+
),
|
|
236
|
+
metrics: result.metrics,
|
|
237
|
+
domainOutcomes: result.domainOutcomes ?? [],
|
|
238
|
+
recommendation: result.taskVerdictRecommendation ?? null,
|
|
239
|
+
failure: null,
|
|
240
|
+
};
|
|
241
|
+
} catch (error) {
|
|
242
|
+
const failure = {
|
|
243
|
+
message:
|
|
244
|
+
error instanceof ExtensionSourceChangedError
|
|
245
|
+
? "extension source inputs changed during evaluation; assessment was refused. Finish changing evaluator inputs, then start a fresh evaluation with inputs held stable."
|
|
246
|
+
: "extension grading did not complete",
|
|
247
|
+
cancelable: true,
|
|
248
|
+
};
|
|
249
|
+
effects.onFailure(failure);
|
|
250
|
+
return {
|
|
251
|
+
checks: [],
|
|
252
|
+
metrics: [],
|
|
253
|
+
domainOutcomes: [],
|
|
254
|
+
recommendation: null,
|
|
255
|
+
failure,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|