opencode-swarm 7.136.1 → 7.136.2

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 (67) hide show
  1. package/.opencode/skills/swarm-pr-feedback/SKILL.md +41 -1
  2. package/.opencode/skills/swarm-pr-review/SKILL.md +72 -24
  3. package/README.md +18 -0
  4. package/dist/background/workspace-snapshot.d.ts +54 -0
  5. package/dist/cli/{config-doctor-6fphg5xm.js → config-doctor-b67nb84b.js} +2 -2
  6. package/dist/cli/{curation-policy-m24jbyag.js → curation-policy-kvzhfaj1.js} +2 -2
  7. package/dist/cli/{curator-llm-factory-w5arq7tr.js → curator-llm-factory-x7kvry9x.js} +17 -14
  8. package/dist/cli/{curator-zrt5sqj2.js → curator-nrmj8bds.js} +17 -14
  9. package/dist/cli/{evidence-summary-service-w006jnpg.js → evidence-summary-service-cf8sz2bq.js} +3 -1
  10. package/dist/cli/{guardrail-explain-462jwhbh.js → guardrail-explain-5kd44rcj.js} +18 -15
  11. package/dist/cli/{guardrail-log-ax21jd9e.js → guardrail-log-aksrzqdx.js} +3 -3
  12. package/dist/cli/hashing-mjwn6j4y.js +34 -0
  13. package/dist/cli/{hive-promoter-2vacnbws.js → hive-promoter-cy21rhnd.js} +17 -14
  14. package/dist/cli/{index-hzkvbycn.js → index-0755132s.js} +4 -4
  15. package/dist/cli/{index-9gxp450h.js → index-1kn24ja0.js} +1 -1
  16. package/dist/cli/{index-h3bweb88.js → index-21115szq.js} +5 -5
  17. package/dist/cli/{index-g7g4hqh3.js → index-37v2wxqe.js} +1 -1
  18. package/dist/cli/{index-gf7hqbmz.js → index-7ayaq27q.js} +5 -1
  19. package/dist/cli/{index-kzc2ygea.js → index-84nz7bhe.js} +1 -1
  20. package/dist/cli/{index-1sq47n6t.js → index-ad6j0m7k.js} +12 -6
  21. package/dist/cli/{index-zkddc5ye.js → index-azghvnja.js} +2 -2
  22. package/dist/cli/{index-rhgctfn3.js → index-ckybsn6p.js} +19 -16
  23. package/dist/cli/{index-cggqh2dz.js → index-kwwxevne.js} +53 -996
  24. package/dist/cli/{index-tfa40hwb.js → index-m5fw4mer.js} +19 -2
  25. package/dist/cli/{index-jwrydqjp.js → index-rw3f73aq.js} +1 -1
  26. package/dist/cli/{index-dyy3hvk3.js → index-s0rbdp61.js} +2 -2
  27. package/dist/cli/{index-p1pqqwgp.js → index-s0vahtdm.js} +1 -1
  28. package/dist/cli/{index-prnjt2jr.js → index-sr2cynyw.js} +4509 -2306
  29. package/dist/cli/index-wjm896ey.js +1100 -0
  30. package/dist/cli/{index-f4cmtd89.js → index-wnz282j3.js} +2 -2
  31. package/dist/cli/{index-y6a7gjtj.js → index-wsdnttf4.js} +228 -81
  32. package/dist/cli/{index-r9v98d0y.js → index-y0xaq4f3.js} +39 -4
  33. package/dist/cli/index-y8552snf.js +264 -0
  34. package/dist/cli/index-z1tm47nj.js +783 -0
  35. package/dist/cli/index.js +17 -14
  36. package/dist/cli/{knowledge-escalator-1zt8qy1c.js → knowledge-escalator-ta3xjrdj.js} +3 -3
  37. package/dist/cli/{knowledge-events-ej3s9tsm.js → knowledge-events-dk6banmz.js} +1 -1
  38. package/dist/cli/{knowledge-store-ey4cbkp4.js → knowledge-store-h3jz10bv.js} +1 -1
  39. package/dist/cli/{knowledge-validator-zwmq7s2c.js → knowledge-validator-jsz1dxkr.js} +4 -4
  40. package/dist/cli/runner-2v413r74.js +21 -0
  41. package/dist/cli/{scan-cursor-809hf2n1.js → scan-cursor-48gwzh9c.js} +2 -2
  42. package/dist/cli/{schema-mhd7xqwr.js → schema-f937b9cs.js} +5 -1
  43. package/dist/cli/{skill-generator-yyc8zd9j.js → skill-generator-4p10ktw1.js} +5 -5
  44. package/dist/cli/{workspace-snapshot-jmyamqnv.js → workspace-snapshot-h5rzw37b.js} +5 -1
  45. package/dist/commands/registry.d.ts +72 -0
  46. package/dist/commands/skill-opt.d.ts +41 -0
  47. package/dist/config/schema.d.ts +47 -0
  48. package/dist/hooks/guardrails/file-authority.d.ts +11 -2
  49. package/dist/hooks/pr-workflow-gate.d.ts +261 -4
  50. package/dist/hooks/pr-workflow-response-gate.d.ts +27 -9
  51. package/dist/hooks/write-target-resolver.d.ts +19 -0
  52. package/dist/index.js +353 -318
  53. package/dist/services/skill-evaluator.d.ts +17 -0
  54. package/dist/services/skill-optimizer/activation.d.ts +58 -0
  55. package/dist/services/skill-optimizer/candidates.d.ts +88 -0
  56. package/dist/services/skill-optimizer/controller.d.ts +146 -0
  57. package/dist/services/skill-optimizer/deterministic-seed.d.ts +29 -0
  58. package/dist/services/skill-optimizer/lifecycle.d.ts +70 -0
  59. package/dist/services/skill-optimizer/promoted-external-staleness.d.ts +98 -0
  60. package/dist/services/skill-optimizer/retirement.d.ts +54 -0
  61. package/dist/services/skill-optimizer/skill-eval-tasks.d.ts +47 -0
  62. package/dist/services/skill-optimizer/smoke.d.ts +46 -0
  63. package/dist/services/skill-optimizer/store.d.ts +118 -0
  64. package/dist/tools/write-pr-review-trigger-eval.d.ts +2 -1
  65. package/dist/utils/stable-stringify.d.ts +46 -0
  66. package/evaluation-fixtures/skill-eval/scoring/score-skill-eval.cjs +97 -0
  67. package/package.json +1 -1
@@ -0,0 +1,783 @@
1
+ // @bun
2
+ import {
3
+ canonicalJson,
4
+ computeRunIntegrityHash,
5
+ computeTaskInputContentHash,
6
+ computeTaskLineageInputHash,
7
+ computeTaskSetContentHash,
8
+ resolveContainedExistingPath
9
+ } from "./index-y8552snf.js";
10
+ import {
11
+ atomicWriteFile
12
+ } from "./index-ey29aap6.js";
13
+ import {
14
+ withEvidenceLock
15
+ } from "./index-09b9zncg.js";
16
+ import {
17
+ exports_external,
18
+ init_zod
19
+ } from "./index-bpmtbmy9.js";
20
+
21
+ // src/evaluation/contracts.ts
22
+ init_zod();
23
+ var IdentifierSchema = exports_external.string().min(1).max(160).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/);
24
+ var Sha256Schema = exports_external.string().regex(/^[a-f0-9]{64}$/);
25
+ var IsoDateSchema = exports_external.iso.datetime({ offset: true });
26
+ var RelativePathSchema = exports_external.string().min(1).max(1024).refine((value) => !value.includes("\x00"), "path contains a NUL byte").refine((value) => !/^(?:[A-Za-z]:[\\/]|[\\/]{1,2})/.test(value), {
27
+ message: "path must be project-relative"
28
+ }).refine((value) => !value.replace(/\\/g, "/").split("/").some((segment) => segment === ".."), "path must not traverse outside its root");
29
+ var EvaluationSplitSchema = exports_external.enum(["train", "validation", "test"]);
30
+ var CostRecordSchema = exports_external.object({
31
+ source: exports_external.enum(["reported", "estimated", "unavailable"]),
32
+ usd: exports_external.number().finite().nonnegative().optional()
33
+ }).strict().superRefine((value, ctx) => {
34
+ if (value.source === "unavailable" && value.usd !== undefined) {
35
+ ctx.addIssue({
36
+ code: "custom",
37
+ path: ["usd"],
38
+ message: "unavailable costs cannot declare a USD value"
39
+ });
40
+ }
41
+ if (value.source !== "unavailable" && value.usd === undefined) {
42
+ ctx.addIssue({
43
+ code: "custom",
44
+ path: ["usd"],
45
+ message: "reported and estimated costs require a USD value"
46
+ });
47
+ }
48
+ });
49
+ var HumanReviewReceiptSchema = exports_external.object({
50
+ reviewer: exports_external.string().min(1).max(200),
51
+ reviewedAt: IsoDateSchema,
52
+ instruction: exports_external.literal(true),
53
+ fixture: exports_external.literal(true),
54
+ scorer: exports_external.literal(true),
55
+ secretsPrivacy: exports_external.literal(true),
56
+ license: exports_external.literal(true),
57
+ split: exports_external.literal(true)
58
+ }).strict();
59
+ var EvaluationTaskV1Schema = exports_external.object({
60
+ v: exports_external.literal(1),
61
+ id: IdentifierSchema,
62
+ derivedFromTaskId: IdentifierSchema.optional(),
63
+ source: exports_external.enum(["curated", "trace-proposal"]),
64
+ split: EvaluationSplitSchema,
65
+ category: IdentifierSchema,
66
+ protected: exports_external.boolean().default(false),
67
+ instructionPath: RelativePathSchema,
68
+ environment: exports_external.discriminatedUnion("kind", [
69
+ exports_external.object({ kind: exports_external.literal("fixture"), path: RelativePathSchema }).strict(),
70
+ exports_external.object({ kind: exports_external.literal("container"), path: RelativePathSchema }).strict()
71
+ ]),
72
+ scorer: exports_external.object({
73
+ kind: exports_external.enum(["builtin", "project"]),
74
+ argv: exports_external.array(exports_external.string().min(1).max(4096)).min(1).max(64),
75
+ timeoutMs: exports_external.number().int().min(100).max(600000),
76
+ scoreRange: exports_external.tuple([exports_external.number().finite(), exports_external.number().finite()]).refine(([minimum, maximum]) => maximum > minimum, {
77
+ message: "score range maximum must be greater than minimum"
78
+ })
79
+ }).strict(),
80
+ provenance: exports_external.object({
81
+ origin: exports_external.string().min(1).max(2048),
82
+ license: exports_external.string().min(1).max(200),
83
+ collectedAt: IsoDateSchema.optional(),
84
+ review: HumanReviewReceiptSchema.optional()
85
+ }).strict(),
86
+ contentHash: Sha256Schema
87
+ }).strict().superRefine((task, ctx) => {
88
+ if (task.derivedFromTaskId === task.id) {
89
+ ctx.addIssue({
90
+ code: "custom",
91
+ path: ["derivedFromTaskId"],
92
+ message: "a derived task must reference a different parent task"
93
+ });
94
+ }
95
+ if (task.source === "trace-proposal" && !task.provenance.review) {
96
+ ctx.addIssue({
97
+ code: "custom",
98
+ path: ["provenance", "review"],
99
+ message: "trace-derived tasks require an explicit human review receipt"
100
+ });
101
+ }
102
+ if (task.scorer.kind === "project" && !RelativePathSchema.safeParse(task.scorer.argv[0]).success) {
103
+ ctx.addIssue({
104
+ code: "custom",
105
+ path: ["scorer", "argv", 0],
106
+ message: "project scorer executable must be project-relative"
107
+ });
108
+ }
109
+ });
110
+ var EvaluationCandidateV1Schema = exports_external.object({
111
+ v: exports_external.literal(1),
112
+ id: IdentifierSchema,
113
+ kind: exports_external.enum(["baseline", "skill", "harness"]),
114
+ payloadPath: RelativePathSchema,
115
+ model: exports_external.string().min(1).max(300),
116
+ agent: exports_external.string().min(1).max(160).optional(),
117
+ contentHash: Sha256Schema
118
+ }).strict();
119
+ var EvaluationOutcomeSchema = exports_external.enum([
120
+ "scored",
121
+ "infrastructure_failure",
122
+ "timeout",
123
+ "cancelled",
124
+ "malformed",
125
+ "unsupported",
126
+ "integrity_failure"
127
+ ]);
128
+ var EvaluationResultV1Schema = exports_external.object({
129
+ v: exports_external.literal(1),
130
+ taskId: IdentifierSchema,
131
+ category: IdentifierSchema,
132
+ protected: exports_external.boolean().default(false),
133
+ repetition: exports_external.number().int().nonnegative(),
134
+ candidateId: IdentifierSchema,
135
+ seed: exports_external.string().min(1).max(500),
136
+ outcome: EvaluationOutcomeSchema,
137
+ score: exports_external.number().finite().optional(),
138
+ scoreRange: exports_external.tuple([exports_external.number().finite(), exports_external.number().finite()]),
139
+ cost: CostRecordSchema,
140
+ durationMs: exports_external.number().int().nonnegative(),
141
+ retries: exports_external.number().int().nonnegative().default(0),
142
+ failureCode: exports_external.string().min(1).max(160).optional(),
143
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
144
+ }).strict().superRefine((result, ctx) => {
145
+ const [minimum, maximum] = result.scoreRange;
146
+ if (maximum <= minimum) {
147
+ ctx.addIssue({
148
+ code: "custom",
149
+ path: ["scoreRange"],
150
+ message: "score range maximum must be greater than minimum"
151
+ });
152
+ }
153
+ if (result.outcome === "scored") {
154
+ if (result.score === undefined || result.score < minimum || result.score > maximum) {
155
+ ctx.addIssue({
156
+ code: "custom",
157
+ path: ["score"],
158
+ message: "scored outcomes require an in-range score"
159
+ });
160
+ }
161
+ } else if (result.score !== undefined) {
162
+ ctx.addIssue({
163
+ code: "custom",
164
+ path: ["score"],
165
+ message: "non-score outcomes must not be imputed with a score"
166
+ });
167
+ }
168
+ });
169
+ var EvaluationBudgetsV1Schema = exports_external.object({
170
+ maxTasks: exports_external.number().int().positive(),
171
+ maxRepetitions: exports_external.number().int().positive(),
172
+ maxConcurrency: exports_external.number().int().positive(),
173
+ maxTaskTimeMs: exports_external.number().int().positive(),
174
+ maxRetries: exports_external.number().int().nonnegative(),
175
+ maxOutputBytes: exports_external.number().int().positive(),
176
+ maxSpendUsd: exports_external.number().finite().nonnegative().optional()
177
+ }).strict();
178
+ var EnvironmentFingerprintV1Schema = exports_external.object({
179
+ platform: exports_external.string().min(1),
180
+ arch: exports_external.string().min(1),
181
+ runtime: exports_external.string().min(1),
182
+ baseSha: exports_external.string().regex(/^[a-f0-9]{40,64}$/),
183
+ activeTreeHash: Sha256Schema,
184
+ taskSetHash: Sha256Schema
185
+ }).strict();
186
+ var EvaluationRunV1Schema = exports_external.object({
187
+ v: exports_external.literal(1),
188
+ runId: IdentifierSchema,
189
+ createdAt: IsoDateSchema,
190
+ status: exports_external.enum(["complete", "inconclusive", "cancelled"]),
191
+ baseline: EvaluationCandidateV1Schema,
192
+ candidate: EvaluationCandidateV1Schema,
193
+ taskSet: exports_external.object({
194
+ id: IdentifierSchema,
195
+ contentHash: Sha256Schema,
196
+ taskIds: exports_external.array(IdentifierSchema).min(1)
197
+ }).strict(),
198
+ split: EvaluationSplitSchema,
199
+ seed: exports_external.string().min(1).max(500),
200
+ models: exports_external.array(exports_external.string().min(1).max(300)).min(1),
201
+ environment: EnvironmentFingerprintV1Schema,
202
+ budgets: EvaluationBudgetsV1Schema,
203
+ results: exports_external.array(EvaluationResultV1Schema),
204
+ cost: CostRecordSchema,
205
+ integrityHash: Sha256Schema
206
+ }).strict().superRefine((run, ctx) => {
207
+ if (run.environment.taskSetHash !== run.taskSet.contentHash) {
208
+ ctx.addIssue({
209
+ code: "custom",
210
+ path: ["environment", "taskSetHash"],
211
+ message: "environment and task-set hashes must agree"
212
+ });
213
+ }
214
+ const allowed = new Set([run.baseline.id, run.candidate.id]);
215
+ if (allowed.size !== 2) {
216
+ ctx.addIssue({
217
+ code: "custom",
218
+ path: ["candidate", "id"],
219
+ message: "baseline and candidate ids must differ"
220
+ });
221
+ }
222
+ if (run.results.some((result) => !allowed.has(result.candidateId))) {
223
+ ctx.addIssue({
224
+ code: "custom",
225
+ path: ["results"],
226
+ message: "results may only reference the declared baseline and candidate"
227
+ });
228
+ }
229
+ const taskIds = new Set(run.taskSet.taskIds);
230
+ if (run.results.some((result) => !taskIds.has(result.taskId))) {
231
+ ctx.addIssue({
232
+ code: "custom",
233
+ path: ["results"],
234
+ message: "results may only reference tasks in the frozen task set"
235
+ });
236
+ }
237
+ const resultKeys = run.results.map((result) => `${result.candidateId}\x00${result.taskId}\x00${result.repetition}`);
238
+ if (new Set(resultKeys).size !== resultKeys.length) {
239
+ ctx.addIssue({
240
+ code: "custom",
241
+ path: ["results"],
242
+ message: "run contains duplicate candidate/task/repetition results"
243
+ });
244
+ }
245
+ if (run.results.some((result) => result.repetition >= run.budgets.maxRepetitions)) {
246
+ ctx.addIssue({
247
+ code: "custom",
248
+ path: ["results"],
249
+ message: "result repetition exceeds the declared run budget"
250
+ });
251
+ }
252
+ });
253
+ var PromotionPolicyV1Schema = exports_external.object({
254
+ v: exports_external.literal(1),
255
+ minValidPairs: exports_external.number().int().positive().default(6),
256
+ minCoverage: exports_external.number().min(0).max(1).default(0.8),
257
+ deadband: exports_external.number().min(0).max(1).default(0),
258
+ confidence: exports_external.literal(0.95).default(0.95),
259
+ bootstrapResamples: exports_external.literal(1e4).default(1e4),
260
+ requireAvailableCosts: exports_external.boolean().default(true),
261
+ protectedCategoryTolerances: exports_external.record(exports_external.string(), exports_external.number().min(0).max(1)).default({})
262
+ }).strict();
263
+ var PromotionComparisonSchema = exports_external.object({
264
+ baselineRunId: IdentifierSchema,
265
+ baselineCandidateId: IdentifierSchema,
266
+ baselineMean: exports_external.number().min(0).max(1),
267
+ candidateMean: exports_external.number().min(0).max(1),
268
+ pairedDelta: exports_external.number().min(-1).max(1),
269
+ confidenceInterval: exports_external.tuple([
270
+ exports_external.number().min(-1).max(1),
271
+ exports_external.number().min(-1).max(1)
272
+ ]),
273
+ validPairs: exports_external.number().int().nonnegative(),
274
+ missingPairs: exports_external.number().int().nonnegative(),
275
+ coverage: exports_external.number().min(0).max(1)
276
+ }).strict();
277
+ var PromotionDecisionV1Schema = exports_external.object({
278
+ v: exports_external.literal(1),
279
+ decisionId: IdentifierSchema,
280
+ runId: IdentifierSchema,
281
+ decidedAt: IsoDateSchema,
282
+ status: exports_external.enum(["accept", "reject", "inconclusive"]),
283
+ reasons: exports_external.array(exports_external.string().min(1).max(300)),
284
+ baseline: PromotionComparisonSchema,
285
+ historicalBest: PromotionComparisonSchema,
286
+ deadband: exports_external.number().min(0).max(1),
287
+ bootstrap: exports_external.object({
288
+ resamples: exports_external.literal(1e4),
289
+ confidence: exports_external.literal(0.95),
290
+ seedHash: Sha256Schema
291
+ }).strict(),
292
+ categories: exports_external.array(exports_external.object({
293
+ category: IdentifierSchema,
294
+ protected: exports_external.boolean(),
295
+ tolerance: exports_external.number().min(0).max(1),
296
+ baselineMean: exports_external.number().min(0).max(1),
297
+ candidateMean: exports_external.number().min(0).max(1),
298
+ pairedDelta: exports_external.number().min(-1).max(1),
299
+ regression: exports_external.boolean()
300
+ }).strict()),
301
+ lineage: exports_external.object({
302
+ baselineRunId: IdentifierSchema,
303
+ historicalBestRunId: IdentifierSchema,
304
+ taskSetHash: Sha256Schema,
305
+ baselineHash: Sha256Schema,
306
+ candidateHash: Sha256Schema,
307
+ historicalBestHash: Sha256Schema
308
+ }).strict(),
309
+ policyHash: Sha256Schema,
310
+ unavailableQualityMetrics: exports_external.array(exports_external.enum(["complexity_delta", "public_api_delta"])).default(["complexity_delta", "public_api_delta"])
311
+ }).strict();
312
+ var GateNameSchema = exports_external.enum([
313
+ "reviewer",
314
+ "test-engineer",
315
+ "sast",
316
+ "mutation",
317
+ "quality"
318
+ ]);
319
+ var GateAuditManifestV1Schema = exports_external.object({
320
+ v: exports_external.literal(1),
321
+ id: IdentifierSchema,
322
+ createdAt: IsoDateSchema,
323
+ taskIds: exports_external.array(IdentifierSchema).min(1),
324
+ gates: exports_external.array(GateNameSchema).min(1),
325
+ models: exports_external.array(exports_external.string().min(1).max(300)).min(1),
326
+ preferredSwarm: IdentifierSchema.optional(),
327
+ repetitions: exports_external.number().int().positive().max(100),
328
+ seed: exports_external.string().min(1).max(500),
329
+ maxConcurrency: exports_external.number().int().positive().max(64),
330
+ maxRetries: exports_external.number().int().nonnegative().max(20),
331
+ maxTimeMs: exports_external.number().int().positive(),
332
+ maxCostUsd: exports_external.number().finite().nonnegative().optional(),
333
+ contentHash: Sha256Schema
334
+ }).strict();
335
+ var GateAuditCellV1Schema = exports_external.object({
336
+ v: exports_external.literal(1),
337
+ taskId: IdentifierSchema,
338
+ candidateId: IdentifierSchema.optional(),
339
+ defectType: IdentifierSchema,
340
+ gate: GateNameSchema,
341
+ model: exports_external.string().min(1).max(300),
342
+ repetition: exports_external.number().int().nonnegative(),
343
+ outcome: exports_external.enum([
344
+ "caught",
345
+ "missed",
346
+ "false_rejection",
347
+ "unsupported",
348
+ "infrastructure_failure"
349
+ ]),
350
+ retries: exports_external.number().int().nonnegative(),
351
+ cost: CostRecordSchema,
352
+ durationMs: exports_external.number().int().nonnegative(),
353
+ failureClassification: exports_external.enum([
354
+ "clean",
355
+ "pre_existing_failure",
356
+ "new_regression",
357
+ "flaky_failure",
358
+ "infrastructure_failure",
359
+ "unknown_failure"
360
+ ]).optional(),
361
+ failureCode: exports_external.string().min(1).max(160).optional()
362
+ }).strict();
363
+ var GateAuditResultV1Schema = exports_external.object({
364
+ v: exports_external.literal(1),
365
+ runId: IdentifierSchema,
366
+ manifestHash: Sha256Schema,
367
+ createdAt: IsoDateSchema,
368
+ status: exports_external.enum(["complete", "inconclusive", "cancelled"]),
369
+ cells: exports_external.array(GateAuditCellV1Schema),
370
+ cost: CostRecordSchema,
371
+ qualityMetricAvailability: exports_external.object({
372
+ complexity_delta: exports_external.literal("unavailable"),
373
+ public_api_delta: exports_external.literal("unavailable")
374
+ }).strict()
375
+ }).strict();
376
+ var TestConsumptionClaimV1Schema = exports_external.object({
377
+ v: exports_external.literal(1),
378
+ runId: IdentifierSchema,
379
+ taskSetHash: Sha256Schema,
380
+ baselineHash: Sha256Schema,
381
+ candidateHash: Sha256Schema,
382
+ claimedAt: IsoDateSchema
383
+ }).strict();
384
+ var TaskSetSnapshotV1Schema = exports_external.object({
385
+ v: exports_external.literal(1),
386
+ id: IdentifierSchema,
387
+ split: EvaluationSplitSchema,
388
+ tasks: exports_external.array(EvaluationTaskV1Schema).min(1),
389
+ contentHash: Sha256Schema,
390
+ createdAt: IsoDateSchema
391
+ }).strict();
392
+
393
+ // src/evaluation/store.ts
394
+ import { mkdir as mkdir2, readdir, readFile as readFile2 } from "fs/promises";
395
+ import * as path2 from "path";
396
+
397
+ // src/evidence/immutable-store.ts
398
+ import { mkdir, readFile } from "fs/promises";
399
+ import * as path from "path";
400
+ async function readOptionalFile(filePath) {
401
+ try {
402
+ return await readFile(filePath, "utf8");
403
+ } catch (error) {
404
+ if (error.code === "ENOENT")
405
+ return;
406
+ throw error;
407
+ }
408
+ }
409
+ async function writeImmutableArtifact(options) {
410
+ await mkdir(path.dirname(options.filePath), { recursive: true });
411
+ return withEvidenceLock(options.directory, options.relativeLockPath, options.agent, options.taskId, async () => {
412
+ const desired = options.serialize(options.value);
413
+ const existing = await readOptionalFile(options.filePath);
414
+ if (existing !== undefined) {
415
+ let parsed;
416
+ try {
417
+ parsed = options.parse(JSON.parse(existing));
418
+ } catch (error) {
419
+ throw options.conflictError({
420
+ kind: "corrupt",
421
+ filePath: options.filePath,
422
+ cause: error
423
+ });
424
+ }
425
+ if (options.serialize(parsed) === desired || options.isEquivalent?.(parsed, options.value)) {
426
+ return parsed;
427
+ }
428
+ throw options.conflictError({
429
+ kind: "divergent",
430
+ filePath: options.filePath
431
+ });
432
+ }
433
+ await atomicWriteFile(options.filePath, desired);
434
+ return options.value;
435
+ });
436
+ }
437
+
438
+ // src/evaluation/store.ts
439
+ var AGENT = "evaluation-store";
440
+ var TEST_LEDGER_RELATIVE = path2.join("evolution", "test-consumption.jsonl");
441
+ var TASK_SPLIT_REGISTRY_RELATIVE = path2.join("evolution", "tasks", "split-registry.json");
442
+
443
+ class EvaluationConflictError extends Error {
444
+ constructor(message) {
445
+ super(message);
446
+ this.name = "EvaluationConflictError";
447
+ }
448
+ }
449
+
450
+ class TestAlreadyConsumedError extends Error {
451
+ priorClaim;
452
+ constructor(priorClaim) {
453
+ super(`held-out test task set ${priorClaim.taskSetHash} was already consumed by run ${priorClaim.runId}`);
454
+ this.name = "TestAlreadyConsumedError";
455
+ this.priorClaim = priorClaim;
456
+ }
457
+ }
458
+ function swarmPath(directory, ...segments) {
459
+ return path2.join(directory, ".swarm", ...segments);
460
+ }
461
+ function serialized(value) {
462
+ return `${canonicalJson(value)}
463
+ `;
464
+ }
465
+ function parseTaskSplitRegistry(content) {
466
+ if (content === undefined)
467
+ return { v: 1, entries: [] };
468
+ let value;
469
+ try {
470
+ value = JSON.parse(content);
471
+ } catch (error) {
472
+ throw new EvaluationConflictError(`task split registry is corrupt: ${String(error)}`);
473
+ }
474
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
475
+ throw new EvaluationConflictError("task split registry is corrupt");
476
+ }
477
+ const record = value;
478
+ if (record.v !== 1 || !Array.isArray(record.entries)) {
479
+ throw new EvaluationConflictError("task split registry is corrupt");
480
+ }
481
+ const entries = record.entries.map((candidate) => {
482
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
483
+ throw new EvaluationConflictError("task split registry is corrupt");
484
+ }
485
+ const entry = candidate;
486
+ if (typeof entry.lineageHash !== "string" || !["train", "validation", "test"].includes(String(entry.split)) || !Array.isArray(entry.taskIds) || !entry.taskIds.every((id) => typeof id === "string") || !Array.isArray(entry.inputHashes) || !entry.inputHashes.every((hash) => typeof hash === "string")) {
487
+ throw new EvaluationConflictError("task split registry is corrupt");
488
+ }
489
+ return {
490
+ lineageHash: entry.lineageHash,
491
+ split: entry.split,
492
+ taskIds: [...new Set(entry.taskIds)].sort(),
493
+ inputHashes: [...new Set(entry.inputHashes)].sort()
494
+ };
495
+ });
496
+ return { v: 1, entries };
497
+ }
498
+ function evaluationConflictError(conflict) {
499
+ return conflict.kind === "corrupt" ? new EvaluationConflictError(`existing evaluation artifact is corrupt: ${conflict.filePath}: ${String(conflict.cause)}`) : new EvaluationConflictError(`immutable evaluation artifact conflicts with existing content: ${conflict.filePath}`);
500
+ }
501
+ function writeImmutable(options) {
502
+ return writeImmutableArtifact({
503
+ ...options,
504
+ agent: AGENT,
505
+ serialize: serialized,
506
+ conflictError: evaluationConflictError
507
+ });
508
+ }
509
+ function validateTaskInputs(directory, task) {
510
+ resolveContainedExistingPath(directory, task.instructionPath);
511
+ const environmentRoot = resolveContainedExistingPath(directory, task.environment.path);
512
+ if (task.scorer.kind === "project") {
513
+ const executable = task.scorer.argv[0];
514
+ if (!executable)
515
+ throw new Error("project scorer requires an executable");
516
+ const scorerPath = resolveContainedExistingPath(directory, executable);
517
+ const relative2 = path2.relative(environmentRoot, scorerPath);
518
+ if (!relative2 || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || path2.isAbsolute(relative2)) {
519
+ throw new Error("project scorer executable must be inside the admitted task environment");
520
+ }
521
+ }
522
+ }
523
+ async function admitEvaluationTask(directory, input, inputRoot = directory) {
524
+ const task = EvaluationTaskV1Schema.parse(input);
525
+ if (await computeTaskInputContentHash(inputRoot, task) !== task.contentHash) {
526
+ throw new Error(`task ${task.id} content hash does not match its canonical inputs`);
527
+ }
528
+ validateTaskInputs(inputRoot, task);
529
+ const lineageInputHash = await computeTaskLineageInputHash(inputRoot, task);
530
+ const relative2 = path2.join("evolution", "tasks", task.split, `${task.id}.json`);
531
+ const admissionLock = TASK_SPLIT_REGISTRY_RELATIVE;
532
+ const filePath = swarmPath(directory, relative2);
533
+ await mkdir2(path2.dirname(filePath), { recursive: true });
534
+ return withEvidenceLock(directory, admissionLock, AGENT, task.id, async () => {
535
+ const registryPath = swarmPath(directory, TASK_SPLIT_REGISTRY_RELATIVE);
536
+ const registry = parseTaskSplitRegistry(await readOptionalFile(registryPath));
537
+ const existingTaskEntry = registry.entries.find((entry) => entry.taskIds.includes(task.id));
538
+ if (existingTaskEntry && existingTaskEntry.split !== task.split) {
539
+ throw new EvaluationConflictError(`task ${task.id} is already admitted to a different split`);
540
+ }
541
+ const parentEntry = task.derivedFromTaskId ? registry.entries.find((entry) => entry.taskIds.includes(task.derivedFromTaskId)) : undefined;
542
+ if (task.derivedFromTaskId && !parentEntry) {
543
+ throw new EvaluationConflictError(`derived task ${task.id} references an unadmitted parent ${task.derivedFromTaskId}`);
544
+ }
545
+ const lineageEntry = parentEntry ?? registry.entries.find((entry) => entry.lineageHash === lineageInputHash || entry.inputHashes.includes(lineageInputHash));
546
+ if (lineageEntry && lineageEntry.split !== task.split) {
547
+ throw new EvaluationConflictError(`task ${task.id} lineage is already admitted to ${lineageEntry.split}; derived and aliased tasks must inherit that split`);
548
+ }
549
+ for (const split of ["train", "validation", "test"]) {
550
+ if (split === task.split)
551
+ continue;
552
+ if (await readOptionalFile(swarmPath(directory, "evolution", "tasks", split, `${task.id}.json`))) {
553
+ throw new EvaluationConflictError(`task ${task.id} is already admitted to a different split`);
554
+ }
555
+ }
556
+ const desired = serialized(task);
557
+ const existing = await readOptionalFile(filePath);
558
+ if (existing !== undefined) {
559
+ const parsed = EvaluationTaskV1Schema.parse(JSON.parse(existing));
560
+ if (serialized(parsed) === desired) {
561
+ if (lineageEntry) {
562
+ lineageEntry.taskIds = [
563
+ ...new Set([...lineageEntry.taskIds, task.id])
564
+ ].sort();
565
+ lineageEntry.inputHashes = [
566
+ ...new Set([...lineageEntry.inputHashes, lineageInputHash])
567
+ ].sort();
568
+ } else {
569
+ registry.entries.push({
570
+ lineageHash: lineageInputHash,
571
+ split: task.split,
572
+ taskIds: [task.id],
573
+ inputHashes: [lineageInputHash]
574
+ });
575
+ }
576
+ registry.entries.sort((left, right) => left.lineageHash.localeCompare(right.lineageHash));
577
+ await atomicWriteFile(registryPath, serialized(registry));
578
+ return parsed;
579
+ }
580
+ if (task.split !== "train") {
581
+ throw new EvaluationConflictError(`${task.split} task ${task.id} is immutable after admission`);
582
+ }
583
+ }
584
+ await atomicWriteFile(filePath, desired);
585
+ if (lineageEntry) {
586
+ lineageEntry.taskIds = [
587
+ ...new Set([...lineageEntry.taskIds, task.id])
588
+ ].sort();
589
+ lineageEntry.inputHashes = [
590
+ ...new Set([...lineageEntry.inputHashes, lineageInputHash])
591
+ ].sort();
592
+ } else {
593
+ registry.entries.push({
594
+ lineageHash: lineageInputHash,
595
+ split: task.split,
596
+ taskIds: [task.id],
597
+ inputHashes: [lineageInputHash]
598
+ });
599
+ }
600
+ registry.entries.sort((left, right) => left.lineageHash.localeCompare(right.lineageHash));
601
+ await atomicWriteFile(registryPath, serialized(registry));
602
+ return task;
603
+ });
604
+ }
605
+ async function saveTaskSetSnapshot(directory, input, inputRoot = directory) {
606
+ const snapshot = TaskSetSnapshotV1Schema.parse(input);
607
+ const ids = snapshot.tasks.map((task) => task.id);
608
+ if (new Set(ids).size !== ids.length)
609
+ throw new Error("task-set contains duplicate task ids");
610
+ if (snapshot.tasks.some((task) => task.split !== snapshot.split)) {
611
+ throw new Error("task-set tasks must all belong to the declared split");
612
+ }
613
+ for (const task of snapshot.tasks) {
614
+ if (await computeTaskInputContentHash(inputRoot, task) !== task.contentHash) {
615
+ throw new Error(`task ${task.id} content hash is invalid`);
616
+ }
617
+ }
618
+ if (computeTaskSetContentHash(snapshot) !== snapshot.contentHash) {
619
+ throw new Error("task-set content hash does not match its canonical inputs");
620
+ }
621
+ const relative2 = path2.join("evolution", "task-sets", `${snapshot.contentHash}.json`);
622
+ return writeImmutable({
623
+ directory,
624
+ relativeLockPath: relative2,
625
+ filePath: swarmPath(directory, relative2),
626
+ taskId: snapshot.id,
627
+ value: snapshot,
628
+ parse: (value) => TaskSetSnapshotV1Schema.parse(value),
629
+ isEquivalent: (existing, desired) => existing.contentHash === desired.contentHash
630
+ });
631
+ }
632
+ async function saveEvaluationRun(directory, input) {
633
+ const run = EvaluationRunV1Schema.parse(input);
634
+ if (computeRunIntegrityHash(run) !== run.integrityHash) {
635
+ throw new Error(`run ${run.runId} integrity hash is invalid`);
636
+ }
637
+ const relative2 = path2.join("evolution", "runs", `${run.runId}.json`);
638
+ return writeImmutable({
639
+ directory,
640
+ relativeLockPath: relative2,
641
+ filePath: swarmPath(directory, relative2),
642
+ taskId: run.runId,
643
+ value: run,
644
+ parse: (value) => EvaluationRunV1Schema.parse(value)
645
+ });
646
+ }
647
+ async function readEvaluationRun(directory, runId) {
648
+ const content = await readOptionalFile(swarmPath(directory, "evolution", "runs", `${runId}.json`));
649
+ return content === undefined ? undefined : EvaluationRunV1Schema.parse(JSON.parse(content));
650
+ }
651
+ async function savePromotionDecision(directory, input) {
652
+ const decision = PromotionDecisionV1Schema.parse(input);
653
+ const relative2 = path2.join("evolution", "decisions", `${decision.decisionId}.json`);
654
+ return writeImmutable({
655
+ directory,
656
+ relativeLockPath: relative2,
657
+ filePath: swarmPath(directory, relative2),
658
+ taskId: decision.runId,
659
+ value: decision,
660
+ parse: (value) => PromotionDecisionV1Schema.parse(value),
661
+ isEquivalent: (existing, desired) => {
662
+ const { decidedAt: _existingTimestamp, ...existingCore } = existing;
663
+ const { decidedAt: _desiredTimestamp, ...desiredCore } = desired;
664
+ return canonicalJson(existingCore) === canonicalJson(desiredCore);
665
+ }
666
+ });
667
+ }
668
+ async function saveGateAuditResult(directory, input) {
669
+ const result = GateAuditResultV1Schema.parse(input);
670
+ const relative2 = path2.join("evidence", "gate-audit", result.runId, "results.json");
671
+ return writeImmutable({
672
+ directory,
673
+ relativeLockPath: relative2,
674
+ filePath: swarmPath(directory, relative2),
675
+ taskId: result.runId,
676
+ value: result,
677
+ parse: (value) => GateAuditResultV1Schema.parse(value)
678
+ });
679
+ }
680
+ async function saveGateAuditManifest(directory, input) {
681
+ const manifest = GateAuditManifestV1Schema.parse(input);
682
+ const relative2 = path2.join("evolution", "gate-audit-manifests", `${manifest.id}.json`);
683
+ return writeImmutable({
684
+ directory,
685
+ relativeLockPath: relative2,
686
+ filePath: swarmPath(directory, relative2),
687
+ taskId: manifest.id,
688
+ value: manifest,
689
+ parse: (value) => GateAuditManifestV1Schema.parse(value)
690
+ });
691
+ }
692
+ async function readGateAuditManifest(directory, runId) {
693
+ const content = await readOptionalFile(swarmPath(directory, "evolution", "gate-audit-manifests", `${runId}.json`));
694
+ return content === undefined ? undefined : GateAuditManifestV1Schema.parse(JSON.parse(content));
695
+ }
696
+ async function readGateAuditResult(directory, runId) {
697
+ const content = await readOptionalFile(swarmPath(directory, "evidence", "gate-audit", runId, "results.json"));
698
+ return content === undefined ? undefined : GateAuditResultV1Schema.parse(JSON.parse(content));
699
+ }
700
+ async function listGateAuditResults(directory) {
701
+ const root = swarmPath(directory, "evidence", "gate-audit");
702
+ let entries = [];
703
+ try {
704
+ entries = await readdir(root, { withFileTypes: true });
705
+ } catch (error) {
706
+ if (error.code === "ENOENT") {
707
+ return { results: [], corruptRunIds: [] };
708
+ }
709
+ throw error;
710
+ }
711
+ const results = [];
712
+ const corruptRunIds = [];
713
+ for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
714
+ if (!entry.isDirectory() || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,159}$/.test(entry.name)) {
715
+ continue;
716
+ }
717
+ try {
718
+ const parsed = GateAuditResultV1Schema.parse(JSON.parse(await readFile2(path2.join(root, entry.name, "results.json"), "utf8")));
719
+ if (parsed.runId !== entry.name)
720
+ throw new Error("run id/path mismatch");
721
+ results.push(parsed);
722
+ } catch {
723
+ corruptRunIds.push(entry.name);
724
+ }
725
+ }
726
+ return { results, corruptRunIds };
727
+ }
728
+ function parseTestLedger(content) {
729
+ return content.split(/\r?\n/).filter((line) => line.trim().length > 0).map((line, index) => {
730
+ try {
731
+ return TestConsumptionClaimV1Schema.parse(JSON.parse(line));
732
+ } catch (error) {
733
+ throw new EvaluationConflictError(`test-consumption ledger is corrupt at line ${index + 1}: ${String(error)}`);
734
+ }
735
+ });
736
+ }
737
+ async function claimHeldOutTest(directory, input) {
738
+ const claim = TestConsumptionClaimV1Schema.parse(input);
739
+ const filePath = swarmPath(directory, TEST_LEDGER_RELATIVE);
740
+ await mkdir2(path2.dirname(filePath), { recursive: true });
741
+ return withEvidenceLock(directory, TEST_LEDGER_RELATIVE, AGENT, claim.runId, async () => {
742
+ const content = await readOptionalFile(filePath) ?? "";
743
+ const claims = parseTestLedger(content);
744
+ const identicalRun = claims.find((entry) => entry.runId === claim.runId);
745
+ if (identicalRun) {
746
+ if (identicalRun.taskSetHash === claim.taskSetHash && identicalRun.baselineHash === claim.baselineHash && identicalRun.candidateHash === claim.candidateHash) {
747
+ return identicalRun;
748
+ }
749
+ throw new EvaluationConflictError(`run ${claim.runId} conflicts with its prior held-out test claim`);
750
+ }
751
+ const prior = claims.find((entry) => entry.taskSetHash === claim.taskSetHash);
752
+ if (prior)
753
+ throw new TestAlreadyConsumedError(prior);
754
+ await atomicWriteFile(filePath, `${content.replace(/\s*$/, "")}${content.trim() ? `
755
+ ` : ""}${serialized(claim)}`);
756
+ return claim;
757
+ });
758
+ }
759
+ async function getProtectedEvaluationRunIds(directory) {
760
+ const protectedIds = new Set;
761
+ const ledger = await readOptionalFile(swarmPath(directory, TEST_LEDGER_RELATIVE));
762
+ for (const claim of parseTestLedger(ledger ?? ""))
763
+ protectedIds.add(claim.runId);
764
+ const decisionsDirectory = swarmPath(directory, "evolution", "decisions");
765
+ let files = [];
766
+ try {
767
+ files = await readdir(decisionsDirectory);
768
+ } catch (error) {
769
+ if (error.code !== "ENOENT")
770
+ throw error;
771
+ }
772
+ for (const filename of files.filter((value) => value.endsWith(".json")).sort()) {
773
+ const decision = PromotionDecisionV1Schema.parse(JSON.parse(await readFile2(path2.join(decisionsDirectory, filename), "utf8")));
774
+ protectedIds.add(decision.runId);
775
+ protectedIds.add(decision.lineage.baselineRunId);
776
+ if (decision.lineage.historicalBestRunId !== "unavailable") {
777
+ protectedIds.add(decision.lineage.historicalBestRunId);
778
+ }
779
+ }
780
+ return protectedIds;
781
+ }
782
+
783
+ export { IdentifierSchema, CostRecordSchema, EvaluationTaskV1Schema, EvaluationCandidateV1Schema, EvaluationRunV1Schema, PromotionPolicyV1Schema, PromotionDecisionV1Schema, GateNameSchema, GateAuditManifestV1Schema, GateAuditResultV1Schema, admitEvaluationTask, saveTaskSetSnapshot, saveEvaluationRun, readEvaluationRun, savePromotionDecision, saveGateAuditResult, saveGateAuditManifest, readGateAuditManifest, readGateAuditResult, listGateAuditResults, claimHeldOutTest, getProtectedEvaluationRunIds };