@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.
Files changed (243) hide show
  1. package/CONTRIBUTING.md +170 -0
  2. package/LICENSE +63 -136
  3. package/README.md +83 -66
  4. package/docs/README.md +44 -0
  5. package/docs/acknowledgements.md +14 -0
  6. package/docs/architecture.md +146 -0
  7. package/docs/assets/README.md +27 -0
  8. package/docs/assets/sevro-logo.png +0 -0
  9. package/docs/assets/sevro-symbol.svg +1 -0
  10. package/docs/assets/sevro-wordmark.svg +1 -0
  11. package/docs/builtin-graders-v1.md +41 -13
  12. package/docs/codex-host.md +184 -52
  13. package/docs/contracts.md +19 -0
  14. package/docs/creating-cases.md +139 -0
  15. package/docs/development-cli.md +190 -30
  16. package/docs/documentation-quality.md +61 -0
  17. package/docs/evaluation-workflow.md +110 -0
  18. package/docs/evidence/code-mode-controls-71.md +64 -0
  19. package/docs/evidence/code-mode-programs-85.md +64 -0
  20. package/docs/evidence/codex-state-73/README.md +204 -0
  21. package/docs/evidence/codex-state-73/darrow-migration.patch +182 -0
  22. package/docs/evidence/codex-state-73/results.json +661 -0
  23. package/docs/evidence/local-http-74.md +104 -0
  24. package/docs/evidence/runtime-startup-30/README.md +185 -0
  25. package/docs/evidence/runtime-startup-30/after.json +319 -0
  26. package/docs/evidence/runtime-startup-30/baseline-timeout.jsonl +2 -0
  27. package/docs/evidence/runtime-startup-30/before.json +403 -0
  28. package/docs/evidence/runtime-startup-30/consumer-smoke.json +63 -0
  29. package/docs/evidence/runtime-startup-30/full-policy-diagnostic.jsonl +3 -0
  30. package/docs/evidence/runtime-startup-30/minimal-policy-diagnostic.jsonl +3 -0
  31. package/docs/evidence/runtime-startup-30/plugin-template-assessment.json +20 -0
  32. package/docs/evidence/runtime-startup-30/seedless-timeout.jsonl +2 -0
  33. package/docs/evidence/skill-reads-70/results.json +823 -0
  34. package/docs/evidence.md +21 -0
  35. package/docs/extension-protocol-v1.md +50 -16
  36. package/docs/fixture-cleanup-validation.md +3 -0
  37. package/docs/getting-started.md +102 -0
  38. package/docs/guide-evaluation.md +89 -0
  39. package/docs/guide-verification.json +239 -0
  40. package/docs/identity-v1.md +35 -1
  41. package/docs/installing.md +88 -0
  42. package/docs/licenses/BUSL-1.1-0.1.0-rc.2.txt +159 -0
  43. package/docs/licensing.md +42 -0
  44. package/docs/native-controls.md +76 -5
  45. package/docs/native-hosts.md +228 -0
  46. package/docs/reading-results.md +141 -0
  47. package/docs/recipes.md +489 -0
  48. package/docs/releases.md +81 -40
  49. package/docs/report-v1.md +29 -1
  50. package/docs/results-v1.md +180 -0
  51. package/docs/run-settings-v1.md +147 -0
  52. package/docs/running-evaluations.md +31 -0
  53. package/docs/runtime-v1.md +614 -0
  54. package/docs/specs/repository-guide.md +58 -0
  55. package/docs/troubleshooting.md +30 -0
  56. package/docs/typescript-quality.md +234 -0
  57. package/docs/usability-study.md +114 -0
  58. package/examples/basic/host.ts +2 -2
  59. package/examples/recipes/candidate.ts +26 -0
  60. package/examples/recipes/cases/coding-change.json +21 -0
  61. package/examples/recipes/cases/host-tools.json +21 -0
  62. package/examples/recipes/cases/mise.json +21 -0
  63. package/examples/recipes/cases/node.json +21 -0
  64. package/examples/recipes/cases/python-uv.json +21 -0
  65. package/examples/recipes/cases/semantic.json +17 -0
  66. package/examples/recipes/coding-change/check.ts +23 -0
  67. package/examples/recipes/extension-artifacts.ts +65 -0
  68. package/examples/recipes/extension-methods.ts +174 -0
  69. package/examples/recipes/extension.ts +37 -0
  70. package/examples/recipes/repository-skill/.agents/skills/startup-guide/SKILL.md +7 -0
  71. package/examples/recipes/repository-skill/.claude/skills/startup-guide/SKILL.md +7 -0
  72. package/examples/recipes/repository-skill/README.md +3 -0
  73. package/examples/recipes/run-inputs.ts +188 -0
  74. package/examples/recipes/run-options.ts +131 -0
  75. package/examples/recipes/run.ts +63 -0
  76. package/examples/recipes/runtime/empty.json +1 -0
  77. package/examples/recipes/runtime/goals.json +1 -0
  78. package/examples/recipes/runtime/mise.json +6 -0
  79. package/examples/recipes/runtime/path.json +1 -0
  80. package/examples/recipes/runtime/plugins.json +4 -0
  81. package/examples/recipes/runtime/python-uv.json +10 -0
  82. package/examples/recipes/semantic-judge.ts +29 -0
  83. package/examples/templates/coding/adapter.ts +17 -0
  84. package/examples/templates/coding/case.json +15 -0
  85. package/examples/templates/repository-skill/.agents/skills/startup-guide/SKILL.md +6 -0
  86. package/examples/templates/repository-skill/extension-data.ts +64 -0
  87. package/examples/templates/repository-skill/extension.ts +31 -0
  88. package/examples/templates/response/adapter.ts +12 -0
  89. package/examples/templates/response/case.json +13 -0
  90. package/package.json +39 -6
  91. package/schemas/report-v1.schema.json +9 -0
  92. package/schemas/run-evidence-v1.schema.json +2 -1
  93. package/schemas/runtime-v1.schema.json +193 -0
  94. package/src/advisory.ts +10 -5
  95. package/src/candidate-artifacts.ts +208 -0
  96. package/src/candidate-codex-state.ts +185 -0
  97. package/src/case-validation.ts +105 -0
  98. package/src/cli/cancellation.ts +20 -0
  99. package/src/cli/command.ts +81 -0
  100. package/src/cli/completion.ts +15 -0
  101. package/src/cli/demo.ts +59 -0
  102. package/src/cli/evaluation.ts +55 -0
  103. package/src/cli/extension.ts +79 -0
  104. package/src/cli/help.ts +222 -0
  105. package/src/cli/hosts.ts +59 -0
  106. package/src/cli/init-settings.ts +30 -0
  107. package/src/cli/init.ts +111 -0
  108. package/src/cli/invocation.ts +627 -0
  109. package/src/cli/loading.ts +151 -0
  110. package/src/cli/preparation.ts +163 -0
  111. package/src/cli/presentation.ts +91 -0
  112. package/src/cli/progress.ts +6 -0
  113. package/src/cli/run-manifest.ts +133 -0
  114. package/src/cli/run-options.ts +101 -0
  115. package/src/cli/run-overrides.ts +83 -0
  116. package/src/cli/settings.ts +160 -0
  117. package/src/cli/summary.ts +43 -0
  118. package/src/cli.ts +13 -843
  119. package/src/contract-types.ts +94 -0
  120. package/src/engine.ts +19 -2373
  121. package/src/evaluation/advisory.ts +150 -0
  122. package/src/evaluation/check-plan.ts +510 -0
  123. package/src/evaluation/collection.ts +88 -0
  124. package/src/evaluation/context.ts +10 -0
  125. package/src/evaluation/grading-host.ts +39 -0
  126. package/src/evaluation/grading.ts +258 -0
  127. package/src/evaluation/invocation-plan.ts +548 -0
  128. package/src/evaluation/plan.ts +736 -0
  129. package/src/evaluation/progress.ts +19 -0
  130. package/src/evaluation/resources.ts +241 -0
  131. package/src/evaluation/run.ts +206 -0
  132. package/src/{trial-scheduler.ts → evaluation/scheduler.ts} +3 -1
  133. package/src/evaluation/semantic.ts +312 -0
  134. package/src/evaluation/trial.ts +866 -0
  135. package/src/evaluation/types.ts +207 -0
  136. package/src/evidence/host-results.ts +92 -0
  137. package/src/evidence/retained-artifacts.ts +18 -0
  138. package/src/evidence/trial-writer.ts +203 -0
  139. package/src/evidence/usage.ts +17 -0
  140. package/src/extension-client.ts +228 -148
  141. package/src/extension-session.ts +326 -195
  142. package/src/fixtures/advisory.ts +338 -0
  143. package/src/fixtures/bin.ts +57 -0
  144. package/src/{fixture-cleanup.ts → fixtures/cleanup.ts} +13 -7
  145. package/src/fixtures/create.ts +187 -0
  146. package/src/fixtures/generated.ts +300 -0
  147. package/src/fixtures/git-hooks.ts +24 -0
  148. package/src/fixtures/preparation.ts +270 -0
  149. package/src/{repository-fixture.ts → fixtures/repository.ts} +207 -85
  150. package/src/fixtures/setup.ts +224 -0
  151. package/src/fixtures/tools.ts +88 -0
  152. package/src/fixtures/workspace-state.ts +212 -0
  153. package/src/generated/cli-result.cjs +2 -0
  154. package/src/generated/cli-result.d.cts +3 -0
  155. package/src/generated/extension.cjs +2 -0
  156. package/src/generated/extension.d.cts +3 -0
  157. package/src/generated/report.cjs +2 -0
  158. package/src/generated/report.d.cts +3 -0
  159. package/src/generated/run-evidence.cjs +2 -0
  160. package/src/generated/run-evidence.d.cts +3 -0
  161. package/src/generated/runtime.cjs +2 -0
  162. package/src/generated/runtime.d.cts +3 -0
  163. package/src/graders/artifact.ts +56 -23
  164. package/src/graders/git-head.ts +79 -75
  165. package/src/graders/output.ts +222 -140
  166. package/src/graders/semantic.ts +102 -43
  167. package/src/graders/shell.ts +379 -207
  168. package/src/host-diagnostic-redaction.ts +52 -0
  169. package/src/host-diagnostics.ts +319 -0
  170. package/src/hosts/claude-continuation.ts +63 -18
  171. package/src/hosts/claude-credential.ts +43 -62
  172. package/src/hosts/claude-events.ts +86 -51
  173. package/src/hosts/claude-keychain.ts +59 -0
  174. package/src/hosts/claude-native-goal.ts +57 -33
  175. package/src/hosts/claude-process.ts +111 -0
  176. package/src/hosts/claude-repository-invocation.ts +208 -117
  177. package/src/hosts/claude-settings.ts +240 -21
  178. package/src/hosts/claude-skill-activations.ts +166 -0
  179. package/src/hosts/claude-state.ts +403 -0
  180. package/src/hosts/claude-tool-calls.ts +171 -106
  181. package/src/hosts/claude.ts +561 -451
  182. package/src/hosts/codex-app-server.ts +326 -178
  183. package/src/hosts/codex-configuration.ts +44 -18
  184. package/src/hosts/codex-events.ts +97 -60
  185. package/src/hosts/codex-exec-controls.ts +516 -0
  186. package/src/hosts/codex-invocation.ts +70 -0
  187. package/src/hosts/codex-marketplace.ts +283 -0
  188. package/src/hosts/codex-native-calls.ts +546 -500
  189. package/src/hosts/codex-process.ts +202 -0
  190. package/src/hosts/codex-profile.ts +257 -28
  191. package/src/hosts/codex-session-files.ts +106 -0
  192. package/src/hosts/codex-state.ts +492 -0
  193. package/src/hosts/codex.ts +783 -832
  194. package/src/hosts/isolation-common.ts +94 -0
  195. package/src/hosts/isolation-roots.ts +54 -27
  196. package/src/hosts/isolation.ts +10 -0
  197. package/src/hosts/linux-sandbox.ts +159 -0
  198. package/src/hosts/mac-sandbox.ts +187 -61
  199. package/src/hosts/native-controls.ts +152 -62
  200. package/src/hosts/process-lifecycle.ts +37 -0
  201. package/src/hosts/protected-worktrees.ts +51 -19
  202. package/src/hosts/skill-hook-catalog.ts +131 -0
  203. package/src/hosts/skill-hook-handler.ts +374 -0
  204. package/src/hosts/skill-hooks.ts +580 -0
  205. package/src/hosts/workspace-fingerprint.ts +55 -35
  206. package/src/identity.ts +102 -48
  207. package/src/instrumentation.ts +109 -48
  208. package/src/native-transcript-state.ts +131 -0
  209. package/src/native-transcript-view.ts +90 -0
  210. package/src/native-transcripts.ts +286 -0
  211. package/src/process-lifecycle.ts +150 -0
  212. package/src/provenance.ts +161 -81
  213. package/src/prune.ts +215 -0
  214. package/src/report.ts +172 -140
  215. package/src/resolved-case.ts +33 -0
  216. package/src/results-lock.ts +29 -0
  217. package/src/results.ts +133 -86
  218. package/src/run-owner.ts +154 -63
  219. package/src/runtime/config.ts +456 -0
  220. package/src/runtime/discovery-apple.ts +90 -0
  221. package/src/runtime/discovery-providers.ts +63 -0
  222. package/src/runtime/discovery.ts +70 -0
  223. package/src/runtime/hook-processes.ts +97 -0
  224. package/src/runtime/hooks.ts +476 -0
  225. package/src/runtime/paths.ts +313 -0
  226. package/src/runtime/query.ts +85 -0
  227. package/src/runtime/seeds.ts +134 -0
  228. package/src/runtime/shared-cache.ts +143 -0
  229. package/src/runtime/state.ts +143 -0
  230. package/src/schema-types.ts +198 -0
  231. package/src/schema.ts +15 -19
  232. package/src/transcript-retention.ts +146 -0
  233. package/src/value-guards.ts +20 -0
  234. package/src/advisory-fixture.ts +0 -282
  235. package/src/fixture-bin.ts +0 -87
  236. package/src/fixture-setup.ts +0 -163
  237. package/src/generated-fixture.ts +0 -220
  238. package/src/git-hooks.ts +0 -63
  239. package/src/hosts/claude-nested-skills.ts +0 -218
  240. package/src/hosts/codex-command-output.ts +0 -399
  241. package/src/hosts/codex-executor-command.ts +0 -195
  242. package/src/hosts/codex-skill-reads.ts +0 -391
  243. package/src/preparation.ts +0 -211
@@ -0,0 +1,312 @@
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";
7
+ import {
8
+ HostExecutionFailure,
9
+ type HostAdapter,
10
+ type HostResult,
11
+ } from "./types";
12
+ import { readSemanticArtifact } from "../graders/artifact";
13
+ import {
14
+ parseSemanticVerdicts,
15
+ semanticCheckGroups,
16
+ semanticPrompt,
17
+ type PreparedSemanticCheck,
18
+ type SemanticVerdict,
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";
29
+
30
+ interface SemanticGradingInput {
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;
42
+ }
43
+ interface SemanticGradingEffects {
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;
50
+ retainWorkspace(workspace: string): Promise<void>;
51
+ }
52
+ type SemanticGroup = ReturnType<typeof semanticCheckGroups>[number];
53
+
54
+ type SemanticInputArtifact = Awaited<
55
+ ReturnType<typeof readSemanticArtifact>
56
+ > | null;
57
+
58
+ type SemanticHostOutcome =
59
+ | {
60
+ result: HostResult;
61
+ artifacts: ReturnType<typeof hostArtifacts>;
62
+ source: Record<string, unknown>;
63
+ hostId: string;
64
+ }
65
+ | {
66
+ result: null;
67
+ artifacts: ReturnType<typeof hostArtifacts>;
68
+ source: Record<string, unknown>;
69
+ hostId: null;
70
+ };
71
+
72
+ function semanticGroupSuffix(pattern: string | undefined): string {
73
+ return pattern === undefined ? "" : "." + sha256(pattern);
74
+ }
75
+
76
+ function semanticSource(
77
+ artifact: SemanticInputArtifact,
78
+ ): Record<string, unknown> {
79
+ return artifact
80
+ ? {
81
+ kind: "artifact",
82
+ path: artifact.path,
83
+ sha256: sha256(artifact.content),
84
+ }
85
+ : { kind: "response" };
86
+ }
87
+
88
+ function semanticHostPrompt(
89
+ message: string,
90
+ checks: SemanticGroup,
91
+ artifact: SemanticInputArtifact,
92
+ ): string {
93
+ return semanticPrompt(
94
+ artifact?.content ?? message,
95
+ checks,
96
+ artifact ? "document" : "response",
97
+ );
98
+ }
99
+ class SemanticGrading {
100
+ private observations: TrialObservation[] = [];
101
+ private checks: CheckOutcome[] = [];
102
+ private failure: GradingFailure | null = null;
103
+ constructor(
104
+ private readonly input: SemanticGradingInput,
105
+ private readonly effects: SemanticGradingEffects,
106
+ ) {}
107
+ async run(): Promise<GradingResult> {
108
+ for (const group of semanticCheckGroups([...this.input.checks]))
109
+ await this.gradeSemanticGroup(group);
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);
119
+ }
120
+ private async semanticInput(
121
+ pattern: string | undefined,
122
+ ): Promise<SemanticInputArtifact> {
123
+ return pattern === undefined
124
+ ? null
125
+ : readSemanticArtifact(this.input.candidateWorkspace, pattern);
126
+ }
127
+
128
+ private async semanticWorkspace(): Promise<string> {
129
+ return createFixture(
130
+ { files: {} },
131
+ [],
132
+ undefined,
133
+ null,
134
+ null,
135
+ null,
136
+ null,
137
+ this.input.projectRoot,
138
+ this.input.signal,
139
+ this.input.reservedWorkspace,
140
+ );
141
+ }
142
+
143
+ private async runSemanticHost(
144
+ group: SemanticGroup,
145
+ pattern: string | undefined,
146
+ suffix: string,
147
+ workspace: string,
148
+ message: string,
149
+ ): Promise<SemanticHostOutcome> {
150
+ let source: Record<string, unknown> = { kind: "response" };
151
+ try {
152
+ const artifact = await this.semanticInput(pattern);
153
+ source = semanticSource(artifact);
154
+ const host = this.input.host;
155
+ if (!host) throw new Error("semantic host is unavailable");
156
+ const response = await host
157
+ .run({
158
+ retainHostDiagnostics: (bytes) =>
159
+ this.effects.evidence.retainArtifacts([
160
+ {
161
+ id: `sevro.semantic${suffix}.sevro.host.diagnostics`,
162
+ bytes: Buffer.from(bytes),
163
+ },
164
+ ]),
165
+ candidateTranscriptRoot: this.input.candidateTranscriptRoot,
166
+ candidateArtifactRoots: this.input.candidateArtifactRoots,
167
+ prompt: semanticHostPrompt(message, group, artifact),
168
+ runtimePolicy: gradingRuntimePolicy(
169
+ this.input.runtimePolicy,
170
+ pattern === undefined,
171
+ ),
172
+ runtimeRole: "semantic",
173
+ workspace,
174
+ condition: "passive",
175
+ signal: this.input.signal,
176
+ })
177
+ .catch((cause: unknown) => {
178
+ if (cause instanceof HostExecutionFailure) return cause.result;
179
+ throw cause;
180
+ });
181
+ const artifacts = scopedHostArtifacts(
182
+ response,
183
+ `sevro.semantic${suffix}.`,
184
+ this.effects.evidence.artifactRefs,
185
+ this.input.declaredChecks,
186
+ `sevro.semantic.verdicts${suffix}`,
187
+ );
188
+ return { result: response, artifacts, source, hostId: host.id };
189
+ } catch (cause) {
190
+ if (cause instanceof HostDiagnosticPersistenceError) throw cause;
191
+ this.failGrading("semantic grading did not complete");
192
+ return { result: null, artifacts: [], source, hostId: null };
193
+ }
194
+ }
195
+
196
+ private recordSemanticVerdict(
197
+ verdict: SemanticVerdict,
198
+ pattern: string | undefined,
199
+ source: Record<string, unknown>,
200
+ hostId: string,
201
+ ): void {
202
+ const id = `sevro.observation.semantic.${sha256(verdict.id)}`;
203
+ this.observations.push({
204
+ id,
205
+ source: hostId,
206
+ completeness: "complete",
207
+ data: {
208
+ verdict: verdict.verdict,
209
+ reason: verdict.reason,
210
+ ...(pattern === undefined ? {} : { source }),
211
+ },
212
+ });
213
+ this.checks.push({
214
+ id: verdict.id,
215
+ grader: "sevro.semantic",
216
+ status: verdict.verdict === "pass" ? "passed" : "failed",
217
+ detail: verdict.reason,
218
+ evidenceRefs: [id],
219
+ });
220
+ }
221
+
222
+ private parseSemanticResults(
223
+ result: HostResult,
224
+ group: SemanticGroup,
225
+ pattern: string | undefined,
226
+ source: Record<string, unknown>,
227
+ hostId: string,
228
+ ): boolean {
229
+ try {
230
+ const message = this.completeSemanticGraderMessage(result);
231
+ const verdicts = parseSemanticVerdicts(message, group);
232
+ for (const verdict of verdicts)
233
+ this.recordSemanticVerdict(verdict, pattern, source, hostId);
234
+ return true;
235
+ } catch {
236
+ this.failGrading(
237
+ result.failureMessage ?? "semantic grading did not complete",
238
+ result.processFailure?.reason === "cancelled",
239
+ );
240
+ return false;
241
+ }
242
+ }
243
+
244
+ private completeSemanticGraderMessage(result: HostResult): string {
245
+ if (result.executionFailed || !result.complete || !result.finalMessage)
246
+ throw new Error("semantic grader result did not complete");
247
+ return result.finalMessage;
248
+ }
249
+
250
+ private async gradeSemanticGroup(group: SemanticGroup): Promise<void> {
251
+ const pattern = group[0].artifactPath;
252
+ const suffix = semanticGroupSuffix(pattern);
253
+ if (this.failure) return;
254
+ const message = this.input.message;
255
+ if (message === null) {
256
+ this.checks.push(
257
+ ...group.map((check) => ({
258
+ id: check.id,
259
+ grader: "sevro.semantic",
260
+ status: "unavailable" as const,
261
+ evidenceRefs: [],
262
+ })),
263
+ );
264
+ return;
265
+ }
266
+ const workspace = await this.semanticWorkspace();
267
+ let successful = false;
268
+ try {
269
+ const outcome = await this.runSemanticHost(
270
+ group,
271
+ pattern,
272
+ suffix,
273
+ workspace,
274
+ message,
275
+ );
276
+ if (outcome.result === null) return;
277
+ await this.effects.evidence.retainArtifacts(outcome.artifacts);
278
+ this.observations.push({
279
+ id: `sevro.observation.semantic.usage${suffix}`,
280
+ source: outcome.hostId,
281
+ completeness: outcome.result.usageComplete ? "complete" : "partial",
282
+ data: usage(outcome.result),
283
+ });
284
+ await this.effects.evidence.retainSemanticVerdicts(
285
+ outcome.result.finalMessage,
286
+ suffix,
287
+ );
288
+ successful = this.parseSemanticResults(
289
+ outcome.result,
290
+ group,
291
+ pattern,
292
+ outcome.source,
293
+ outcome.hostId,
294
+ );
295
+ } finally {
296
+ await this.finishWorkspace(workspace, successful);
297
+ }
298
+ }
299
+ private async finishWorkspace(
300
+ workspace: string,
301
+ successful: boolean,
302
+ ): Promise<void> {
303
+ if (successful) await clearFixtureContents(workspace);
304
+ else await this.effects.retainWorkspace(workspace);
305
+ }
306
+ }
307
+ export async function gradeSemanticChecks(
308
+ input: SemanticGradingInput,
309
+ effects: SemanticGradingEffects,
310
+ ) {
311
+ return new SemanticGrading(input, effects).run();
312
+ }