@bjoernrochel/sevro 0.1.0-rc.8 → 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 +9 -2
- package/docs/codex-host.md +155 -57
- 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 +122 -4
- package/docs/run-settings-v1.md +147 -0
- package/docs/runtime-v1.md +255 -22
- 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 +43 -7
- package/src/advisory.ts +2 -2
- package/src/candidate-artifacts.ts +42 -11
- 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 +9 -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} +77 -87
- package/src/evaluation/trial.ts +800 -0
- package/src/{evaluation-types.ts → evaluation/types.ts} +79 -29
- 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} +12 -72
- 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/{workspace-state.ts → fixtures/workspace-state.ts} +5 -5
- 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 +50 -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 +46 -9
- package/src/hosts/claude-skill-activations.ts +169 -0
- package/src/hosts/claude-state.ts +28 -15
- package/src/hosts/claude-tool-calls.ts +13 -10
- package/src/hosts/claude.ts +121 -81
- 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 -183
- package/src/hosts/codex-profile.ts +36 -21
- package/src/hosts/codex-session-files.ts +1 -9
- package/src/hosts/codex-state.ts +134 -18
- package/src/hosts/codex.ts +210 -183
- package/src/hosts/isolation-common.ts +8 -11
- package/src/hosts/isolation-roots.ts +2 -2
- package/src/hosts/linux-sandbox.ts +15 -2
- package/src/hosts/mac-sandbox.ts +87 -18
- package/src/hosts/native-controls.ts +72 -22
- package/src/hosts/native-request.ts +55 -0
- package/src/hosts/process-lifecycle.ts +216 -48
- 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 +26 -11
- 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/{runtime-config.ts → runtime/config.ts} +160 -46
- 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} +32 -22
- package/src/{runtime-paths.ts → runtime/paths.ts} +5 -19
- 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 -73
- package/docs/guide-verification.json +0 -239
- package/src/evaluation-context.ts +0 -259
- package/src/evaluation-fixture.ts +0 -302
- package/src/evaluation-run.ts +0 -200
- package/src/evaluation-trial.ts +0 -1016
- 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 -783
- /package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +0 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, realpath, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import {
|
|
6
|
+
allocateWorkspace,
|
|
7
|
+
retainWorkspace,
|
|
8
|
+
removeWorkspace,
|
|
9
|
+
} from "../fixtures/workspace-state";
|
|
10
|
+
import { createFixture } from "../fixtures/create";
|
|
11
|
+
import { fixtureBinDirectory } from "../fixtures/bin";
|
|
12
|
+
import { fixtureParts } from "../fixtures/preparation";
|
|
13
|
+
import { startRunOwner, type RunOwner } from "../run-owner";
|
|
14
|
+
import { EvaluationConfigurationError, type EvaluationOptions } from "./types";
|
|
15
|
+
import type { PreparedFixture, PreparedInvocation } from "./plan";
|
|
16
|
+
import {
|
|
17
|
+
INVOCATION_PLACEHOLDER,
|
|
18
|
+
LEGACY_CODEX_PLACEHOLDER,
|
|
19
|
+
} from "./invocation-plan";
|
|
20
|
+
import type { ArtifactReference as PreparationArtifactReference } from "../contract-types";
|
|
21
|
+
export type { ArtifactReference as PreparationArtifactReference } from "../contract-types";
|
|
22
|
+
|
|
23
|
+
/** Reservations outlive completed contents until all admitted trials drain. */
|
|
24
|
+
export class RunWorkspaceReservations {
|
|
25
|
+
private readonly candidates: string[] = [];
|
|
26
|
+
private readonly semantics: string[] = [];
|
|
27
|
+
private readonly retained = new Set<string>();
|
|
28
|
+
|
|
29
|
+
async reserve(input: {
|
|
30
|
+
count: number;
|
|
31
|
+
semantic: boolean;
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
}): Promise<void> {
|
|
34
|
+
for (
|
|
35
|
+
let trial = 1;
|
|
36
|
+
trial <= input.count && !input.signal?.aborted;
|
|
37
|
+
trial++
|
|
38
|
+
) {
|
|
39
|
+
this.candidates.push(await allocateWorkspace());
|
|
40
|
+
if (input.semantic) this.semantics.push(await allocateWorkspace());
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
candidate(trial: number): string {
|
|
45
|
+
const reservation = this.candidates[trial - 1];
|
|
46
|
+
if (reservation === undefined)
|
|
47
|
+
throw new Error(`trial ${trial} workspace was not reserved`);
|
|
48
|
+
return reservation;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
semantic(trial: number): string | undefined {
|
|
52
|
+
return this.semantics[trial - 1];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
retain(workspace: string): void {
|
|
56
|
+
this.retained.add(workspace);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
completed(reservation: string): void {
|
|
60
|
+
this.retained.delete(reservation);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async cleanup(): Promise<void> {
|
|
64
|
+
for (const workspace of this.retained) await retainWorkspace(workspace);
|
|
65
|
+
await Promise.all(
|
|
66
|
+
[...this.candidates, ...this.semantics]
|
|
67
|
+
.filter((workspace) => !this.retained.has(workspace))
|
|
68
|
+
.map(async (workspace) => {
|
|
69
|
+
try {
|
|
70
|
+
await removeWorkspace(workspace);
|
|
71
|
+
} catch {
|
|
72
|
+
console.warn(`fixture cleanup failed; retained at ${workspace}`);
|
|
73
|
+
}
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface RunResources {
|
|
80
|
+
readonly runId: string;
|
|
81
|
+
readonly runDir: string;
|
|
82
|
+
readonly runStateRoot: string;
|
|
83
|
+
readonly stateDir: string;
|
|
84
|
+
readonly evidencePath: string;
|
|
85
|
+
readonly owner: RunOwner;
|
|
86
|
+
readonly workspaces: RunWorkspaceReservations;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function allocateRunResources(
|
|
90
|
+
options: Pick<EvaluationOptions, "resultsRoot" | "runStateRoot">,
|
|
91
|
+
evaluationDigest: string,
|
|
92
|
+
): Promise<RunResources> {
|
|
93
|
+
const runId = randomUUID();
|
|
94
|
+
await mkdir(options.resultsRoot, { recursive: true, mode: 0o700 });
|
|
95
|
+
const runDir = resolve(await realpath(options.resultsRoot), runId);
|
|
96
|
+
await mkdir(runDir, { mode: 0o700 });
|
|
97
|
+
const runStateRoot = options.runStateRoot ?? options.resultsRoot;
|
|
98
|
+
await mkdir(runStateRoot, { recursive: true, mode: 0o700 });
|
|
99
|
+
const stateRoot = await realpath(runStateRoot);
|
|
100
|
+
const stateDir = join(stateRoot, runId);
|
|
101
|
+
if (stateDir !== runDir) await mkdir(stateDir, { mode: 0o700 });
|
|
102
|
+
const activePath = join(stateRoot, "active", `${runId}.json`);
|
|
103
|
+
const checkpointPath = join(stateDir, "checkpoint.json");
|
|
104
|
+
const evidencePath = join(runDir, "run.json");
|
|
105
|
+
let owner: RunOwner;
|
|
106
|
+
try {
|
|
107
|
+
owner = startRunOwner({
|
|
108
|
+
stateRoot,
|
|
109
|
+
evaluationDigest,
|
|
110
|
+
attemptId: runId,
|
|
111
|
+
activeRunPath: activePath,
|
|
112
|
+
checkpointPath,
|
|
113
|
+
evidenceDirectory: stateDir,
|
|
114
|
+
artifactPath: evidencePath,
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
await rm(runDir, { recursive: true, force: true });
|
|
118
|
+
if (stateDir !== runDir)
|
|
119
|
+
await rm(stateDir, { recursive: true, force: true });
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
runId,
|
|
124
|
+
runDir,
|
|
125
|
+
runStateRoot,
|
|
126
|
+
stateDir,
|
|
127
|
+
evidencePath,
|
|
128
|
+
owner,
|
|
129
|
+
workspaces: new RunWorkspaceReservations(),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function retainPreparationArtifacts(
|
|
134
|
+
artifacts: PreparedFixture["inlineArtifacts"],
|
|
135
|
+
runDir: string,
|
|
136
|
+
): Promise<PreparationArtifactReference[]> {
|
|
137
|
+
const artifactRefs: PreparationArtifactReference[] = [];
|
|
138
|
+
for (const artifact of artifacts) {
|
|
139
|
+
const retainedPath = join(
|
|
140
|
+
runDir,
|
|
141
|
+
"prepared",
|
|
142
|
+
...fixtureParts(artifact.relativePath),
|
|
143
|
+
);
|
|
144
|
+
await mkdir(dirname(retainedPath), { recursive: true, mode: 0o700 });
|
|
145
|
+
await writeFile(retainedPath, artifact.bytes, {
|
|
146
|
+
flag: "wx",
|
|
147
|
+
mode: artifact.executable ? 0o700 : 0o600,
|
|
148
|
+
});
|
|
149
|
+
artifactRefs.push({
|
|
150
|
+
id: artifact.id,
|
|
151
|
+
path: pathToFileURL(retainedPath).href,
|
|
152
|
+
sha256: artifact.sha256,
|
|
153
|
+
...(artifact.gitExclude ? { gitExclude: true } : {}),
|
|
154
|
+
...(artifact.executable ? { executable: true } : {}),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
return artifactRefs;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function renderTrialPrompt(
|
|
161
|
+
prompt: string,
|
|
162
|
+
workspace: string,
|
|
163
|
+
invocation: PreparedInvocation,
|
|
164
|
+
): string {
|
|
165
|
+
return prompt
|
|
166
|
+
.replaceAll("{{sevro.workspace}}", workspace)
|
|
167
|
+
.replaceAll(
|
|
168
|
+
INVOCATION_PLACEHOLDER,
|
|
169
|
+
invocation.invocationToken ?? INVOCATION_PLACEHOLDER,
|
|
170
|
+
)
|
|
171
|
+
.replaceAll(
|
|
172
|
+
LEGACY_CODEX_PLACEHOLDER,
|
|
173
|
+
invocation.invocationToken ?? LEGACY_CODEX_PLACEHOLDER,
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
type TrialPreparationOptions = Pick<
|
|
178
|
+
EvaluationOptions,
|
|
179
|
+
"case" | "preparationSources" | "signal"
|
|
180
|
+
>;
|
|
181
|
+
|
|
182
|
+
export async function prepareTrialWorkspace(
|
|
183
|
+
options: TrialPreparationOptions,
|
|
184
|
+
fixture: PreparedFixture,
|
|
185
|
+
invocation: PreparedInvocation,
|
|
186
|
+
workspaces: RunWorkspaceReservations,
|
|
187
|
+
trial: number,
|
|
188
|
+
candidateRuntimeRoot?: string,
|
|
189
|
+
) {
|
|
190
|
+
const reservation = workspaces.candidate(trial);
|
|
191
|
+
workspaces.retain(reservation);
|
|
192
|
+
const workspace = await createFixture(fixture.source, {
|
|
193
|
+
artifacts: fixture.inlineArtifacts,
|
|
194
|
+
sources: options.preparationSources,
|
|
195
|
+
setup: fixture.fixtureSetup,
|
|
196
|
+
projectRoot: fixture.projectRoot,
|
|
197
|
+
signal: options.signal,
|
|
198
|
+
reservedWorkspace: reservation,
|
|
199
|
+
candidateRuntimeRoot,
|
|
200
|
+
}).catch((error: unknown) => {
|
|
201
|
+
if (
|
|
202
|
+
!options.signal?.aborted ||
|
|
203
|
+
error instanceof EvaluationConfigurationError
|
|
204
|
+
)
|
|
205
|
+
throw error;
|
|
206
|
+
return null;
|
|
207
|
+
});
|
|
208
|
+
const details = await trialWorkspaceDetails(
|
|
209
|
+
options.case,
|
|
210
|
+
invocation,
|
|
211
|
+
reservation,
|
|
212
|
+
workspace,
|
|
213
|
+
);
|
|
214
|
+
return { ...details, candidateRuntimeRoot };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function trialWorkspaceDetails(
|
|
218
|
+
caseData: EvaluationOptions["case"],
|
|
219
|
+
invocation: PreparedInvocation,
|
|
220
|
+
reservation: string,
|
|
221
|
+
preparedWorkspace: string | null,
|
|
222
|
+
) {
|
|
223
|
+
const workspace = preparedWorkspace ?? reservation;
|
|
224
|
+
const fixtureBinDir =
|
|
225
|
+
preparedWorkspace === null
|
|
226
|
+
? undefined
|
|
227
|
+
: ((await fixtureBinDirectory(workspace)) ?? undefined);
|
|
228
|
+
const trialPrompt = renderTrialPrompt(caseData.prompt, workspace, invocation);
|
|
229
|
+
const trialFollowUpPrompt =
|
|
230
|
+
caseData.followUpPrompt === undefined
|
|
231
|
+
? undefined
|
|
232
|
+
: renderTrialPrompt(caseData.followUpPrompt, workspace, invocation);
|
|
233
|
+
return {
|
|
234
|
+
reservation,
|
|
235
|
+
workspace,
|
|
236
|
+
preparationCancelled: preparedWorkspace === null,
|
|
237
|
+
fixtureBinDir,
|
|
238
|
+
trialPrompt,
|
|
239
|
+
trialFollowUpPrompt,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { prepareEvaluation, type PreparedEvaluation } from "./plan";
|
|
2
|
+
import { type CliResult, type EvaluationOptions } from "./types";
|
|
3
|
+
import { canonicalJson, hashJson } from "../identity";
|
|
4
|
+
import { exitCodeFor, summarizeCases } from "../results";
|
|
5
|
+
import { runtimePolicySnapshot } from "../runtime/config";
|
|
6
|
+
import { cleanupExpiredWorkspaces } from "../fixtures/workspace-state";
|
|
7
|
+
import { assertCliResult, assertRunEvidence } from "../schema";
|
|
8
|
+
import { atomicWriteJson } from "../storage";
|
|
9
|
+
import {
|
|
10
|
+
allocateRunResources,
|
|
11
|
+
retainPreparationArtifacts,
|
|
12
|
+
type RunResources,
|
|
13
|
+
} from "./resources";
|
|
14
|
+
import type { EvaluationContext } from "./context";
|
|
15
|
+
import { ResultCollector, type CollectedResults } from "./collection";
|
|
16
|
+
import { executeEvaluationTrials } from "./trial";
|
|
17
|
+
import { evaluationProgress } from "./progress";
|
|
18
|
+
|
|
19
|
+
function evaluationSignal(
|
|
20
|
+
options: EvaluationOptions,
|
|
21
|
+
): "SIGINT" | "SIGTERM" | undefined {
|
|
22
|
+
const reason: unknown = options.signal?.aborted
|
|
23
|
+
? options.signal.reason
|
|
24
|
+
: null;
|
|
25
|
+
return reason === "SIGINT" || reason === "SIGTERM" ? reason : undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function finalCliResult(
|
|
29
|
+
options: EvaluationOptions,
|
|
30
|
+
resources: RunResources,
|
|
31
|
+
collected: CollectedResults,
|
|
32
|
+
): CliResult {
|
|
33
|
+
const caseResult = collected.caseSummary;
|
|
34
|
+
const assessment = summarizeCases([caseResult]);
|
|
35
|
+
const diagnostic = collected.diagnostic;
|
|
36
|
+
return {
|
|
37
|
+
format: "sevro.cli-result.v1",
|
|
38
|
+
runId: resources.runId,
|
|
39
|
+
...assessment,
|
|
40
|
+
exitCode: exitCodeFor(assessment, {
|
|
41
|
+
dryRun: options.dry,
|
|
42
|
+
signal: evaluationSignal(options),
|
|
43
|
+
}),
|
|
44
|
+
evidencePath: resources.evidencePath,
|
|
45
|
+
cases: [caseResult],
|
|
46
|
+
...(diagnostic ? { diagnostic } : {}),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function finalConditionEvidence(
|
|
51
|
+
options: Pick<EvaluationOptions, "condition" | "trialCount">,
|
|
52
|
+
requestedInstrumentation: PreparedEvaluation["requestedInstrumentation"],
|
|
53
|
+
trials: CollectedResults["trials"],
|
|
54
|
+
) {
|
|
55
|
+
const actualConditions = [
|
|
56
|
+
...new Set(trials.map((entry) => entry.condition.actual)),
|
|
57
|
+
];
|
|
58
|
+
const commonAppliedInstrumentation =
|
|
59
|
+
trials.length === options.trialCount &&
|
|
60
|
+
trials.every(
|
|
61
|
+
(entry) =>
|
|
62
|
+
canonicalJson(entry.condition.appliedInstrumentation) ===
|
|
63
|
+
canonicalJson(requestedInstrumentation),
|
|
64
|
+
)
|
|
65
|
+
? requestedInstrumentation
|
|
66
|
+
: [];
|
|
67
|
+
return {
|
|
68
|
+
requested: options.condition,
|
|
69
|
+
actual: actualConditions.length === 1 ? actualConditions[0] : "unknown",
|
|
70
|
+
requestedInstrumentation,
|
|
71
|
+
appliedInstrumentation: commonAppliedInstrumentation,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function finalExtensionEvidence(
|
|
76
|
+
options: EvaluationOptions,
|
|
77
|
+
replacedBuiltinGraders: string[],
|
|
78
|
+
) {
|
|
79
|
+
const extension = options.extension;
|
|
80
|
+
if (!extension) return null;
|
|
81
|
+
const identity = extension.session.identity;
|
|
82
|
+
return {
|
|
83
|
+
id: identity.id,
|
|
84
|
+
version: identity.version,
|
|
85
|
+
sourceDigest: identity.sourceDigest,
|
|
86
|
+
configurationDigest: identity.configurationDigest,
|
|
87
|
+
protocol: identity.protocol,
|
|
88
|
+
capabilities: identity.capabilities,
|
|
89
|
+
replacements: {
|
|
90
|
+
graders: replacedBuiltinGraders,
|
|
91
|
+
taskVerdictPolicy: identity.selectedTaskVerdictPolicy,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function finalRunEvidence(
|
|
97
|
+
options: EvaluationOptions,
|
|
98
|
+
prepared: PreparedEvaluation,
|
|
99
|
+
resources: RunResources,
|
|
100
|
+
collected: CollectedResults,
|
|
101
|
+
result: CliResult,
|
|
102
|
+
) {
|
|
103
|
+
const condition = finalConditionEvidence(
|
|
104
|
+
options,
|
|
105
|
+
prepared.requestedInstrumentation,
|
|
106
|
+
collected.trials,
|
|
107
|
+
);
|
|
108
|
+
const diagnostic = collected.diagnostic;
|
|
109
|
+
return {
|
|
110
|
+
format: "sevro.run-evidence.v1",
|
|
111
|
+
runId: resources.runId,
|
|
112
|
+
evaluationIdentity: prepared.evaluationIdentity,
|
|
113
|
+
configuration: {
|
|
114
|
+
digest: hashJson(prepared.redactedConfig),
|
|
115
|
+
redacted: prepared.redactedConfig,
|
|
116
|
+
...(options.resolvedRunSettings
|
|
117
|
+
? { resolved: options.resolvedRunSettings }
|
|
118
|
+
: {}),
|
|
119
|
+
},
|
|
120
|
+
runner: prepared.runner,
|
|
121
|
+
project: prepared.project,
|
|
122
|
+
extension: finalExtensionEvidence(
|
|
123
|
+
options,
|
|
124
|
+
prepared.checks.replacedBuiltinGraders,
|
|
125
|
+
),
|
|
126
|
+
condition,
|
|
127
|
+
graders: {
|
|
128
|
+
active: prepared.activeGraders,
|
|
129
|
+
replacedDefaults: prepared.checks.replacedBuiltinGraders,
|
|
130
|
+
},
|
|
131
|
+
routes: prepared.routes,
|
|
132
|
+
result,
|
|
133
|
+
trials: collected.trials,
|
|
134
|
+
...(diagnostic ? { diagnostic } : {}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function finishEvaluationRun(
|
|
139
|
+
options: EvaluationOptions,
|
|
140
|
+
context: EvaluationContext,
|
|
141
|
+
) {
|
|
142
|
+
const collected = context.results.snapshot({
|
|
143
|
+
caseId: options.case.id,
|
|
144
|
+
passThreshold: options.passThreshold,
|
|
145
|
+
cancelled: Boolean(options.signal?.aborted),
|
|
146
|
+
});
|
|
147
|
+
const result = finalCliResult(options, context.resources, collected);
|
|
148
|
+
const evidence = finalRunEvidence(
|
|
149
|
+
options,
|
|
150
|
+
context.prepared,
|
|
151
|
+
context.resources,
|
|
152
|
+
collected,
|
|
153
|
+
result,
|
|
154
|
+
);
|
|
155
|
+
assertCliResult(result);
|
|
156
|
+
assertRunEvidence(evidence);
|
|
157
|
+
evaluationProgress(options, "evidence", "started");
|
|
158
|
+
await atomicWriteJson(context.resources.evidencePath, evidence);
|
|
159
|
+
context.results.checkpoint(
|
|
160
|
+
options.signal?.aborted ? "interrupted" : "complete",
|
|
161
|
+
);
|
|
162
|
+
evaluationProgress(options, "evidence", "completed");
|
|
163
|
+
return { result };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Execute resolved evaluator data through an injected host and retain every trial. */
|
|
167
|
+
export async function runEvaluation(
|
|
168
|
+
options: EvaluationOptions,
|
|
169
|
+
): Promise<{ result: CliResult }> {
|
|
170
|
+
options = {
|
|
171
|
+
...options,
|
|
172
|
+
runtimePolicy: runtimePolicySnapshot(options.runtimePolicy),
|
|
173
|
+
};
|
|
174
|
+
evaluationProgress(options, "preparation", "started");
|
|
175
|
+
await cleanupExpiredWorkspaces();
|
|
176
|
+
const prepared = await prepareEvaluation(options);
|
|
177
|
+
const resources = await allocateRunResources(
|
|
178
|
+
options,
|
|
179
|
+
prepared.evaluationIdentity.digest,
|
|
180
|
+
);
|
|
181
|
+
const results = new ResultCollector(resources.owner);
|
|
182
|
+
try {
|
|
183
|
+
const preparationArtifacts = await retainPreparationArtifacts(
|
|
184
|
+
prepared.fixture.inlineArtifacts,
|
|
185
|
+
resources.runDir,
|
|
186
|
+
);
|
|
187
|
+
await resources.workspaces.reserve({
|
|
188
|
+
count: options.trialCount,
|
|
189
|
+
semantic: prepared.checks.preparedSemantic.length > 0,
|
|
190
|
+
signal: options.signal,
|
|
191
|
+
});
|
|
192
|
+
const context: EvaluationContext = {
|
|
193
|
+
prepared,
|
|
194
|
+
resources,
|
|
195
|
+
results,
|
|
196
|
+
preparationArtifacts,
|
|
197
|
+
};
|
|
198
|
+
await executeEvaluationTrials(options, context);
|
|
199
|
+
return await finishEvaluationRun(options, context);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
results.diagnoseFailure();
|
|
202
|
+
throw error;
|
|
203
|
+
} finally {
|
|
204
|
+
await resources.workspaces.cleanup();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -1,56 +1,52 @@
|
|
|
1
|
-
import { clearFixtureContents } from "
|
|
2
|
-
import type { CandidateArtifactRoots } from "
|
|
1
|
+
import { clearFixtureContents } from "../fixtures/cleanup";
|
|
2
|
+
import type { CandidateArtifactRoots } from "../candidate-artifacts";
|
|
3
|
+
import { createFixture } from "../fixtures/create";
|
|
4
|
+
import { hostArtifacts } from "../evidence/host-results";
|
|
5
|
+
import { usage } from "../evidence/usage";
|
|
6
|
+
import { gradingRuntimePolicy, scopedHostArtifacts } from "./grading-host";
|
|
3
7
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import { createFixture, hostArtifacts, usage } from "./evaluation-fixture";
|
|
10
|
-
import {
|
|
11
|
-
gradingRuntimePolicy,
|
|
12
|
-
scopedHostArtifacts,
|
|
13
|
-
} from "./evaluation-grading-host";
|
|
14
|
-
import type { HostAdapter, HostResult, ResolvedCase } from "./evaluation-types";
|
|
15
|
-
import { readSemanticArtifact } from "./graders/artifact";
|
|
8
|
+
HostExecutionFailure,
|
|
9
|
+
type HostAdapter,
|
|
10
|
+
type HostResult,
|
|
11
|
+
} from "./types";
|
|
12
|
+
import { readSemanticArtifact } from "../graders/artifact";
|
|
16
13
|
import {
|
|
17
14
|
parseSemanticVerdicts,
|
|
18
15
|
semanticCheckGroups,
|
|
19
16
|
semanticPrompt,
|
|
20
17
|
type PreparedSemanticCheck,
|
|
21
18
|
type SemanticVerdict,
|
|
22
|
-
} from "
|
|
23
|
-
import { sha256 } from "
|
|
24
|
-
import type { CheckOutcome } from "
|
|
25
|
-
import type {
|
|
19
|
+
} from "../graders/semantic";
|
|
20
|
+
import { sha256 } from "../identity";
|
|
21
|
+
import type { CheckOutcome } from "../results";
|
|
22
|
+
import type {
|
|
23
|
+
TrialEvidenceWriter,
|
|
24
|
+
TrialObservation,
|
|
25
|
+
} from "../evidence/trial-writer";
|
|
26
|
+
import type { GradingFailure, GradingResult } from "./grading";
|
|
27
|
+
import type { RuntimePolicy } from "../runtime/config";
|
|
28
|
+
import { HostDiagnosticPersistenceError } from "../host-diagnostics";
|
|
26
29
|
|
|
27
|
-
interface SemanticObservation {
|
|
28
|
-
id: string;
|
|
29
|
-
source: string;
|
|
30
|
-
completeness: "complete" | "partial";
|
|
31
|
-
data: Record<string, unknown>;
|
|
32
|
-
}
|
|
33
30
|
interface SemanticGradingInput {
|
|
34
|
-
checks: PreparedSemanticCheck[];
|
|
35
|
-
declaredChecks:
|
|
36
|
-
host: HostAdapter | undefined;
|
|
37
|
-
message: string | null;
|
|
38
|
-
candidateWorkspace: string;
|
|
39
|
-
candidateTranscriptRoot?: string;
|
|
40
|
-
candidateArtifactRoots?: CandidateArtifactRoots;
|
|
41
|
-
projectRoot: string;
|
|
42
|
-
reservedWorkspace?: string;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
runtimePolicy?: RuntimePolicy;
|
|
46
|
-
signal?: AbortSignal;
|
|
31
|
+
readonly checks: readonly PreparedSemanticCheck[];
|
|
32
|
+
readonly declaredChecks: readonly { id: string }[];
|
|
33
|
+
readonly host: HostAdapter | undefined;
|
|
34
|
+
readonly message: string | null;
|
|
35
|
+
readonly candidateWorkspace: string;
|
|
36
|
+
readonly candidateTranscriptRoot?: string;
|
|
37
|
+
readonly candidateArtifactRoots?: CandidateArtifactRoots;
|
|
38
|
+
readonly projectRoot: string;
|
|
39
|
+
readonly reservedWorkspace?: string;
|
|
40
|
+
readonly runtimePolicy?: RuntimePolicy;
|
|
41
|
+
readonly signal?: AbortSignal;
|
|
47
42
|
}
|
|
48
43
|
interface SemanticGradingEffects {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
readonly evidence: Pick<
|
|
45
|
+
TrialEvidenceWriter,
|
|
46
|
+
"artifactRefs" | "retainArtifacts" | "retainSemanticVerdicts"
|
|
47
|
+
>;
|
|
48
|
+
/** Close admission at detection, before retaining or cleaning auxiliary state. */
|
|
49
|
+
onFailure(failure: GradingFailure): void;
|
|
54
50
|
retainWorkspace(workspace: string): Promise<void>;
|
|
55
51
|
}
|
|
56
52
|
type SemanticGroup = ReturnType<typeof semanticCheckGroups>[number];
|
|
@@ -101,16 +97,25 @@ function semanticHostPrompt(
|
|
|
101
97
|
);
|
|
102
98
|
}
|
|
103
99
|
class SemanticGrading {
|
|
104
|
-
private observations:
|
|
100
|
+
private observations: TrialObservation[] = [];
|
|
105
101
|
private checks: CheckOutcome[] = [];
|
|
102
|
+
private failure: GradingFailure | null = null;
|
|
106
103
|
constructor(
|
|
107
104
|
private readonly input: SemanticGradingInput,
|
|
108
105
|
private readonly effects: SemanticGradingEffects,
|
|
109
106
|
) {}
|
|
110
|
-
async run() {
|
|
111
|
-
for (const group of semanticCheckGroups(this.input.checks))
|
|
107
|
+
async run(): Promise<GradingResult> {
|
|
108
|
+
for (const group of semanticCheckGroups([...this.input.checks]))
|
|
112
109
|
await this.gradeSemanticGroup(group);
|
|
113
|
-
return {
|
|
110
|
+
return {
|
|
111
|
+
checks: this.checks,
|
|
112
|
+
observations: this.observations,
|
|
113
|
+
failure: this.failure,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
private failGrading(message: string, cancelable = true): void {
|
|
117
|
+
this.failure = { message, cancelable };
|
|
118
|
+
this.effects.onFailure(this.failure);
|
|
114
119
|
}
|
|
115
120
|
private async semanticInput(
|
|
116
121
|
pattern: string | undefined,
|
|
@@ -122,16 +127,12 @@ class SemanticGrading {
|
|
|
122
127
|
|
|
123
128
|
private async semanticWorkspace(): Promise<string> {
|
|
124
129
|
return createFixture(
|
|
125
|
-
{ files: {} },
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
null,
|
|
132
|
-
this.input.projectRoot,
|
|
133
|
-
this.input.signal,
|
|
134
|
-
this.input.reservedWorkspace,
|
|
130
|
+
{ kind: "inline", files: {} },
|
|
131
|
+
{
|
|
132
|
+
projectRoot: this.input.projectRoot,
|
|
133
|
+
signal: this.input.signal,
|
|
134
|
+
reservedWorkspace: this.input.reservedWorkspace,
|
|
135
|
+
},
|
|
135
136
|
);
|
|
136
137
|
}
|
|
137
138
|
|
|
@@ -150,6 +151,13 @@ class SemanticGrading {
|
|
|
150
151
|
if (!host) throw new Error("semantic host is unavailable");
|
|
151
152
|
const response = await host
|
|
152
153
|
.run({
|
|
154
|
+
retainHostDiagnostics: (bytes) =>
|
|
155
|
+
this.effects.evidence.retainArtifacts([
|
|
156
|
+
{
|
|
157
|
+
id: `sevro.semantic${suffix}.sevro.host.diagnostics`,
|
|
158
|
+
bytes: Buffer.from(bytes),
|
|
159
|
+
},
|
|
160
|
+
]),
|
|
153
161
|
candidateTranscriptRoot: this.input.candidateTranscriptRoot,
|
|
154
162
|
candidateArtifactRoots: this.input.candidateArtifactRoots,
|
|
155
163
|
prompt: semanticHostPrompt(message, group, artifact),
|
|
@@ -163,45 +171,24 @@ class SemanticGrading {
|
|
|
163
171
|
signal: this.input.signal,
|
|
164
172
|
})
|
|
165
173
|
.catch((cause: unknown) => {
|
|
166
|
-
if (cause instanceof
|
|
174
|
+
if (cause instanceof HostExecutionFailure) return cause.result;
|
|
167
175
|
throw cause;
|
|
168
176
|
});
|
|
169
177
|
const artifacts = scopedHostArtifacts(
|
|
170
178
|
response,
|
|
171
179
|
`sevro.semantic${suffix}.`,
|
|
172
|
-
this.effects.artifactRefs,
|
|
180
|
+
this.effects.evidence.artifactRefs,
|
|
173
181
|
this.input.declaredChecks,
|
|
174
182
|
`sevro.semantic.verdicts${suffix}`,
|
|
175
183
|
);
|
|
176
184
|
return { result: response, artifacts, source, hostId: host.id };
|
|
177
|
-
} catch {
|
|
178
|
-
|
|
185
|
+
} catch (cause) {
|
|
186
|
+
if (cause instanceof HostDiagnosticPersistenceError) throw cause;
|
|
187
|
+
this.failGrading("semantic grading did not complete");
|
|
179
188
|
return { result: null, artifacts: [], source, hostId: null };
|
|
180
189
|
}
|
|
181
190
|
}
|
|
182
191
|
|
|
183
|
-
private async retainSemanticVerdicts(
|
|
184
|
-
result: HostResult,
|
|
185
|
-
suffix: string,
|
|
186
|
-
): Promise<void> {
|
|
187
|
-
if (
|
|
188
|
-
result.finalMessage !== null &&
|
|
189
|
-
Buffer.byteLength(result.finalMessage, "utf8") <= 1024 * 1024
|
|
190
|
-
) {
|
|
191
|
-
const bytes = Buffer.from(result.finalMessage, "utf8");
|
|
192
|
-
const path = join(
|
|
193
|
-
this.input.runDir,
|
|
194
|
-
`trial-${this.input.trial}-semantic-verdicts${suffix}.json`,
|
|
195
|
-
);
|
|
196
|
-
await this.effects.writeTrialFile(path, bytes);
|
|
197
|
-
this.effects.artifactRefs.push({
|
|
198
|
-
id: `sevro.semantic.verdicts${suffix}`,
|
|
199
|
-
path: pathToFileURL(path).href,
|
|
200
|
-
sha256: sha256(bytes),
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
192
|
private recordSemanticVerdict(
|
|
206
193
|
verdict: SemanticVerdict,
|
|
207
194
|
pattern: string | undefined,
|
|
@@ -242,8 +229,8 @@ class SemanticGrading {
|
|
|
242
229
|
this.recordSemanticVerdict(verdict, pattern, source, hostId);
|
|
243
230
|
return true;
|
|
244
231
|
} catch {
|
|
245
|
-
this.
|
|
246
|
-
|
|
232
|
+
this.failGrading(
|
|
233
|
+
result.failureMessage ?? "semantic grading did not complete",
|
|
247
234
|
result.processFailure?.reason === "cancelled",
|
|
248
235
|
);
|
|
249
236
|
return false;
|
|
@@ -259,7 +246,7 @@ class SemanticGrading {
|
|
|
259
246
|
private async gradeSemanticGroup(group: SemanticGroup): Promise<void> {
|
|
260
247
|
const pattern = group[0].artifactPath;
|
|
261
248
|
const suffix = semanticGroupSuffix(pattern);
|
|
262
|
-
if (
|
|
249
|
+
if (this.failure) return;
|
|
263
250
|
const message = this.input.message;
|
|
264
251
|
if (message === null) {
|
|
265
252
|
this.checks.push(
|
|
@@ -283,14 +270,17 @@ class SemanticGrading {
|
|
|
283
270
|
message,
|
|
284
271
|
);
|
|
285
272
|
if (outcome.result === null) return;
|
|
286
|
-
await this.effects.retainArtifacts(outcome.artifacts);
|
|
273
|
+
await this.effects.evidence.retainArtifacts(outcome.artifacts);
|
|
287
274
|
this.observations.push({
|
|
288
275
|
id: `sevro.observation.semantic.usage${suffix}`,
|
|
289
276
|
source: outcome.hostId,
|
|
290
277
|
completeness: outcome.result.usageComplete ? "complete" : "partial",
|
|
291
278
|
data: usage(outcome.result),
|
|
292
279
|
});
|
|
293
|
-
await this.retainSemanticVerdicts(
|
|
280
|
+
await this.effects.evidence.retainSemanticVerdicts(
|
|
281
|
+
outcome.result.finalMessage,
|
|
282
|
+
suffix,
|
|
283
|
+
);
|
|
294
284
|
successful = this.parseSemanticResults(
|
|
295
285
|
outcome.result,
|
|
296
286
|
group,
|