@evo-dev/core 0.0.1-alpha.2 → 0.0.1-alpha.4

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 (54) hide show
  1. package/assets/team/agents/code-reviewer.md +48 -0
  2. package/assets/team/agents/docs-maintainer.md +51 -0
  3. package/assets/team/agents/implementation-engineer.md +51 -0
  4. package/assets/team/agents/product-scope-analyst.md +58 -0
  5. package/assets/team/agents/release-engineer.md +55 -0
  6. package/assets/team/agents/security-boundary-reviewer.md +50 -0
  7. package/assets/team/agents/solution-architect.md +51 -0
  8. package/assets/team/agents/verification-engineer.md +51 -0
  9. package/assets/team/team.md +102 -0
  10. package/dist/config/index.js +181 -125
  11. package/dist/index.js +10971 -9455
  12. package/package.json +1 -1
  13. package/src/agents/index.ts +1 -1
  14. package/src/code-agent-traces/index.ts +3 -10
  15. package/src/config/settings.ts +14 -0
  16. package/src/config/store.ts +1 -1
  17. package/src/daemon/index.ts +1 -1
  18. package/src/evolution/candidates/index.ts +235 -0
  19. package/src/evolution/control/index.ts +19 -0
  20. package/src/evolution/evidence/analysis.ts +529 -0
  21. package/src/evolution/evidence/index.ts +3 -0
  22. package/src/evolution/evidence/session-memory/constants.ts +12 -0
  23. package/src/evolution/evidence/session-memory/index.ts +4 -0
  24. package/src/evolution/evidence/session-memory/paths.ts +29 -0
  25. package/src/evolution/evidence/session-memory/policy.ts +39 -0
  26. package/src/evolution/evidence/session-memory/segment.ts +192 -0
  27. package/src/evolution/evidence/session-memory/state-machine.ts +249 -0
  28. package/src/evolution/evidence/session-memory/storage.ts +145 -0
  29. package/src/evolution/evidence/session-memory/types.ts +207 -0
  30. package/src/evolution/evidence/session-memory/updater.ts +184 -0
  31. package/src/evolution/formatters.ts +169 -0
  32. package/src/evolution/index.ts +12 -2827
  33. package/src/{knowledge → evolution/knowledge}/index.ts +7 -7
  34. package/src/evolution/paths.ts +41 -0
  35. package/src/evolution/processor/distillation.ts +436 -0
  36. package/src/evolution/processor/index.ts +3 -0
  37. package/src/evolution/processor/process.ts +306 -0
  38. package/src/evolution/schema.ts +522 -0
  39. package/src/evolution/shared.ts +677 -0
  40. package/src/evolution/triggers/classification.ts +102 -0
  41. package/src/evolution/triggers/index.ts +295 -0
  42. package/src/hooks/index.ts +56 -9
  43. package/src/index.ts +10 -2
  44. package/src/runtime-logs/index.ts +4 -12
  45. package/src/team/index.ts +576 -3
  46. package/src/utils/errors.ts +13 -0
  47. package/src/utils/fs.ts +40 -0
  48. package/src/utils/hash.ts +9 -0
  49. package/src/utils/ids.ts +12 -0
  50. package/src/utils/index.ts +7 -0
  51. package/src/utils/parsing.ts +11 -0
  52. package/src/utils/text.ts +18 -0
  53. package/src/utils/time.ts +5 -0
  54. /package/src/{learning → evolution/review}/index.ts +0 -0
@@ -2,13 +2,13 @@ import { createHash } from "node:crypto";
2
2
  import { existsSync, readFileSync, readdirSync } from "node:fs";
3
3
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
4
4
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
5
- import { resolveEvoDevPaths } from "../config/paths.ts";
6
- import {
7
- type EvolutionDistillationBatch,
8
- type EvolutionEvosCase,
9
- type EvolutionKnowledgeRecord,
10
- listEvolutionEvosCases,
11
- } from "../evolution/index.ts";
5
+ import { resolveEvoDevPaths } from "../../config/paths.ts";
6
+ import { listEvolutionEvosCases } from "../candidates/index.ts";
7
+ import type {
8
+ EvolutionDistillationBatch,
9
+ EvolutionEvosCase,
10
+ EvolutionKnowledgeRecord,
11
+ } from "../schema.ts";
12
12
 
13
13
  export type OkfKnowledgeDecision =
14
14
  | "auto-accept"
@@ -0,0 +1,41 @@
1
+ import { join } from "node:path";
2
+ import { resolveEvoDevPaths } from "../config/paths.ts";
3
+ import type { EvolutionResolvedPaths } from "./schema.ts";
4
+ import { assertPathDescendant, sanitizeStorageId } from "./shared.ts";
5
+
6
+ export function resolveEvolutionPaths(input: {
7
+ homeDir: string;
8
+ projectKey: string;
9
+ runId: string;
10
+ }): EvolutionResolvedPaths {
11
+ const paths = resolveEvoDevPaths(input.homeDir);
12
+ const projectKey = sanitizeStorageId("projectKey", input.projectKey);
13
+ const runId = sanitizeStorageId("runId", input.runId);
14
+ const evolutionStateDir = join(paths.stateDir, "evolution");
15
+ const runStateDir = join(evolutionStateDir, projectKey, runId);
16
+ const repoProposalsDir = join(runStateDir, "proposals");
17
+ const reviewCandidatesDir = join(runStateDir, "review-candidates");
18
+ const knowledgeProjectDir = join(paths.knowledgeDir, projectKey);
19
+ const evosCasesProjectDir = join(paths.evosCasesDir, projectKey);
20
+ assertPathDescendant(evolutionStateDir, runStateDir, "runStateDir");
21
+ assertPathDescendant(evolutionStateDir, reviewCandidatesDir, "reviewCandidatesDir");
22
+ assertPathDescendant(paths.knowledgeDir, knowledgeProjectDir, "knowledgeProjectDir");
23
+ assertPathDescendant(paths.evosCasesDir, evosCasesProjectDir, "evosCasesProjectDir");
24
+ return {
25
+ projectKey,
26
+ runId,
27
+ evolutionStateDir,
28
+ runStateDir,
29
+ evidenceWindowPath: join(runStateDir, "evidence-window.json"),
30
+ batchPath: join(runStateDir, "distillation-batch.json"),
31
+ triggersDir: join(runStateDir, "triggers"),
32
+ reviewCandidatesDir,
33
+ repoProposalsDir,
34
+ repoProposalsIndexPath: join(runStateDir, "proposals.index.json"),
35
+ knowledgeProjectDir,
36
+ knowledgeRecordsDir: join(knowledgeProjectDir, "records"),
37
+ knowledgeIndexPath: join(knowledgeProjectDir, "index.json"),
38
+ evosCasesProjectDir,
39
+ evosIndexPath: paths.evosIndexPath,
40
+ };
41
+ }
@@ -0,0 +1,436 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { resolveEvoDevPaths } from "../../config/paths.ts";
4
+ import {
5
+ createStableId,
6
+ normalizeTimestamp,
7
+ readJsonFiles,
8
+ writeJsonFile as writeJson,
9
+ } from "../../utils/index.ts";
10
+ import {
11
+ activateOkfKnowledgePlan,
12
+ createOkfKnowledgePlanFromDistillationBatch,
13
+ } from "../knowledge/index.ts";
14
+ import { resolveEvolutionPaths } from "../paths.ts";
15
+ import type {
16
+ EvolutionActivationResult,
17
+ EvolutionConfidence,
18
+ EvolutionDistillationBatch,
19
+ EvolutionEvidenceWindow,
20
+ EvolutionEvosCase,
21
+ EvolutionKnowledgeRecord,
22
+ EvolutionRepoProposal,
23
+ EvolutionWriteResult,
24
+ } from "../schema.ts";
25
+ import {
26
+ collectRoleIds,
27
+ createEvolutionEvosCase,
28
+ createEvolutionKnowledgeRecord,
29
+ createEvolutionRepoProposal,
30
+ createPrivacyFields,
31
+ listDirectoryNames,
32
+ parseEvosCase,
33
+ parseKnowledgeRecord,
34
+ parseRepoProposal,
35
+ sanitizeText,
36
+ validateEvolutionDistillationBatch,
37
+ validateEvolutionEvidenceWindow,
38
+ validateEvolutionEvosCase,
39
+ } from "../shared.ts";
40
+ import { chooseEvosTriggerKind, createTriggerSummary } from "../triggers/classification.ts";
41
+
42
+ export function createEvolutionDistillationBatch(input: {
43
+ evidenceWindow: EvolutionEvidenceWindow;
44
+ now?: string | Date;
45
+ warnings?: string[];
46
+ }): EvolutionDistillationBatch {
47
+ validateEvolutionEvidenceWindow(input.evidenceWindow);
48
+ const createdAt = normalizeTimestamp(input.now);
49
+ const roleIds = collectRoleIds(input.evidenceWindow);
50
+ const sourceRefs = input.evidenceWindow.sourceRefs.map((sourceRef) => sourceRef.id);
51
+ const failedSignals = input.evidenceWindow.events.filter(
52
+ (event) =>
53
+ event.kind === "error" ||
54
+ event.triggerReason === "stop-failure" ||
55
+ event.triggerReason === "tool-failure" ||
56
+ event.triggerReason === "permission-denied" ||
57
+ /fail|failed|failure|error|issue/i.test(event.summary),
58
+ );
59
+ const verificationSignals = input.evidenceWindow.events
60
+ .filter(
61
+ (event) => event.kind === "verification" || /test|lint|typecheck|build/i.test(event.summary),
62
+ )
63
+ .slice(0, 8)
64
+ .map((event) => event.summary);
65
+ const autoKnowledgeEligible =
66
+ input.evidenceWindow.events.length > 0 &&
67
+ failedSignals.length === 0 &&
68
+ verificationSignals.length > 0 &&
69
+ input.evidenceWindow.triggerPolicy.distillRecommended &&
70
+ input.evidenceWindow.triggerPolicy.evidenceSignals.failures === 0;
71
+ const confidence: EvolutionConfidence = autoKnowledgeEligible
72
+ ? "high"
73
+ : failedSignals.length === 0
74
+ ? "medium"
75
+ : "low";
76
+
77
+ const knowledgeRecords = !autoKnowledgeEligible
78
+ ? []
79
+ : [
80
+ createEvolutionKnowledgeRecord({
81
+ id: createStableId("k", [input.evidenceWindow.id, "run-summary"]),
82
+ kind: "run-summary",
83
+ title: `Project run ${input.evidenceWindow.runId} evidence summary`,
84
+ projectKey: input.evidenceWindow.projectKey,
85
+ summary: createRunSummary(input.evidenceWindow, roleIds, failedSignals.length),
86
+ body: [
87
+ `Run ${input.evidenceWindow.runId} produced ${input.evidenceWindow.events.length} redacted metadata evidence event(s).`,
88
+ `Observed role(s): ${roleIds.length === 0 ? "none" : roleIds.join(", ")}.`,
89
+ "This record is derived from metadata-only evidence; active use depends on OKF plan review state.",
90
+ ].join("\n"),
91
+ roleTags: roleIds,
92
+ tags: ["project-run", "auto-stored", "unreviewed"],
93
+ reviewState: "auto-stored/unreviewed",
94
+ authority: "contextual",
95
+ confidence,
96
+ provenance: createProvenance(input.evidenceWindow, createdAt, sourceRefs),
97
+ relations: {
98
+ relatedKnowledgeIds: [],
99
+ evosCaseIds: [createStableId("evo", [input.evidenceWindow.id, "case"])],
100
+ proposalIds:
101
+ failedSignals.length === 0
102
+ ? []
103
+ : [createStableId("proposal", [input.evidenceWindow.id, "engineering-practice"])],
104
+ supersedes: [],
105
+ },
106
+ privacy: createPrivacyFields(),
107
+ runtime: { canLoad: true, hardBlocking: false },
108
+ }),
109
+ ];
110
+
111
+ const evosCases =
112
+ input.evidenceWindow.events.length === 0
113
+ ? []
114
+ : [
115
+ createEvolutionEvosCase({
116
+ id: createStableId("evo", [input.evidenceWindow.id, "case"]),
117
+ projectKey: input.evidenceWindow.projectKey,
118
+ title: `Run ${input.evidenceWindow.runId} evolution case`,
119
+ roleTags: roleIds,
120
+ tags: [
121
+ "project-run",
122
+ "evidence-window",
123
+ `trigger-${input.evidenceWindow.triggerPolicy.strongest}`,
124
+ ],
125
+ reviewState: "auto-stored/unreviewed",
126
+ confidence,
127
+ trigger: {
128
+ kind: chooseEvosTriggerKind(input.evidenceWindow),
129
+ summary: createTriggerSummary(input.evidenceWindow),
130
+ },
131
+ intervention: {
132
+ summary: `Collected ${input.evidenceWindow.events.length} metadata event(s) and ${input.evidenceWindow.episodes.length} episode(s) from EvoDev execution logs.`,
133
+ roleIds,
134
+ },
135
+ result: {
136
+ summary:
137
+ failedSignals.length === 0
138
+ ? "No failure signal was detected in the redacted evidence summaries."
139
+ : `${failedSignals.length} potential failure or issue signal(s) were detected.`,
140
+ verificationSignals,
141
+ },
142
+ expectedFutureBehavior:
143
+ "Future role agents should inspect accepted knowledge first and treat unreviewed cases as contextual evidence only.",
144
+ provenance: createProvenance(input.evidenceWindow, createdAt, sourceRefs),
145
+ privacy: createPrivacyFields(),
146
+ }),
147
+ ];
148
+
149
+ const repoProposals =
150
+ failedSignals.length === 0
151
+ ? []
152
+ : [
153
+ createEvolutionRepoProposal({
154
+ id: createStableId("proposal", [input.evidenceWindow.id, "engineering-practice"]),
155
+ kind: "engineering-practice",
156
+ projectKey: input.evidenceWindow.projectKey,
157
+ title: `Review repeated failure signals for ${input.evidenceWindow.runId}`,
158
+ summary:
159
+ "Failure or issue signals appeared in redacted run evidence; review whether repository rules, tests, skills, or role agents need improvement.",
160
+ rationale:
161
+ "EvoDev stores this as a proposal only. It must not modify the user repository until an explicit apply command is implemented and invoked.",
162
+ roleTags: roleIds,
163
+ tags: ["proposal", "failure-signal"],
164
+ reviewState: "pending",
165
+ confidence: "low",
166
+ targetRepoPath: null,
167
+ plannedFiles: [],
168
+ apply: {
169
+ autoApply: false,
170
+ requiresExplicitCommand: true,
171
+ rollbackPlan: "No repository files are changed by this proposal.",
172
+ },
173
+ provenance: createProvenance(input.evidenceWindow, createdAt, sourceRefs),
174
+ privacy: createPrivacyFields(),
175
+ }),
176
+ ];
177
+
178
+ const batch: EvolutionDistillationBatch = {
179
+ schemaVersion: 1,
180
+ id: createStableId("batch", [input.evidenceWindow.id, createdAt]),
181
+ projectKey: input.evidenceWindow.projectKey,
182
+ runId: input.evidenceWindow.runId,
183
+ createdAt,
184
+ evidenceWindow: input.evidenceWindow,
185
+ knowledgeRecords,
186
+ evosCases,
187
+ repoProposals,
188
+ warnings: (input.warnings ?? []).map(sanitizeText),
189
+ };
190
+ validateEvolutionDistillationBatch(batch);
191
+ return batch;
192
+ }
193
+
194
+ export async function writeEvolutionDistillationBatch(input: {
195
+ homeDir: string;
196
+ batch: EvolutionDistillationBatch;
197
+ overwrite?: boolean;
198
+ }): Promise<EvolutionWriteResult> {
199
+ validateEvolutionDistillationBatch(input.batch);
200
+ const paths = resolveEvolutionPaths({
201
+ homeDir: input.homeDir,
202
+ projectKey: input.batch.projectKey,
203
+ runId: input.batch.runId,
204
+ });
205
+ const overwrite = input.overwrite === true;
206
+ await writeJson(paths.evidenceWindowPath, input.batch.evidenceWindow, { overwrite });
207
+ await writeJson(paths.batchPath, input.batch, { overwrite });
208
+
209
+ const knowledgePaths: string[] = [];
210
+ for (const record of input.batch.knowledgeRecords) {
211
+ const path = join(paths.knowledgeRecordsDir, `${record.id}.json`);
212
+ await writeJson(path, record, { overwrite });
213
+ knowledgePaths.push(path);
214
+ }
215
+
216
+ const evosCasePaths: string[] = [];
217
+ for (const evosCase of input.batch.evosCases) {
218
+ const path = join(paths.evosCasesProjectDir, `${evosCase.id}.json`);
219
+ await writeJson(path, evosCase, { overwrite });
220
+ evosCasePaths.push(path);
221
+ }
222
+
223
+ const repoProposalPaths: string[] = [];
224
+ for (const proposal of input.batch.repoProposals) {
225
+ const path = join(paths.repoProposalsDir, `${proposal.id}.json`);
226
+ await writeJson(path, proposal, { overwrite });
227
+ repoProposalPaths.push(path);
228
+ }
229
+
230
+ const allProjectKnowledgeRecords = await readJsonFiles(
231
+ paths.knowledgeRecordsDir,
232
+ parseKnowledgeRecord,
233
+ );
234
+ await writeJson(
235
+ paths.knowledgeIndexPath,
236
+ {
237
+ schemaVersion: 1,
238
+ projectKey: input.batch.projectKey,
239
+ updatedAt: input.batch.createdAt,
240
+ records: allProjectKnowledgeRecords.map((record) => ({
241
+ id: record.id,
242
+ kind: record.kind,
243
+ title: record.title,
244
+ reviewState: record.reviewState,
245
+ roleTags: record.roleTags,
246
+ })),
247
+ },
248
+ { overwrite: true },
249
+ );
250
+
251
+ const evosCasesRootDir = resolveEvoDevPaths(input.homeDir).evosCasesDir;
252
+ const evosProjectKeys = await listDirectoryNames(evosCasesRootDir);
253
+ const evosProjects = await Promise.all(
254
+ evosProjectKeys.map(async (projectKey) => {
255
+ const cases = await readJsonFiles(join(evosCasesRootDir, projectKey), parseEvosCase);
256
+ return {
257
+ projectKey,
258
+ cases: cases.map((evosCase) => ({
259
+ id: evosCase.id,
260
+ title: evosCase.title,
261
+ reviewState: evosCase.reviewState,
262
+ })),
263
+ };
264
+ }),
265
+ );
266
+ await writeJson(
267
+ paths.evosIndexPath,
268
+ {
269
+ schemaVersion: 1,
270
+ updatedAt: input.batch.createdAt,
271
+ projects: evosProjects,
272
+ },
273
+ { overwrite: true },
274
+ );
275
+
276
+ const allRunProposals = await readJsonFiles(paths.repoProposalsDir, parseRepoProposal);
277
+ await writeJson(
278
+ paths.repoProposalsIndexPath,
279
+ {
280
+ schemaVersion: 1,
281
+ projectKey: input.batch.projectKey,
282
+ runId: input.batch.runId,
283
+ updatedAt: input.batch.createdAt,
284
+ proposals: allRunProposals.map((proposal) => ({
285
+ id: proposal.id,
286
+ kind: proposal.kind,
287
+ title: proposal.title,
288
+ reviewState: proposal.reviewState,
289
+ })),
290
+ },
291
+ { overwrite: true },
292
+ );
293
+
294
+ return {
295
+ evidenceWindowPath: paths.evidenceWindowPath,
296
+ batchPath: paths.batchPath,
297
+ knowledgePaths,
298
+ evosCasePaths,
299
+ repoProposalPaths,
300
+ knowledgeIndexPath: paths.knowledgeIndexPath,
301
+ evosIndexPath: paths.evosIndexPath,
302
+ };
303
+ }
304
+
305
+ export async function activateEvolutionDistillationBatch(input: {
306
+ homeDir: string;
307
+ batch: EvolutionDistillationBatch;
308
+ overwrite?: boolean;
309
+ }): Promise<EvolutionActivationResult> {
310
+ validateEvolutionDistillationBatch(input.batch);
311
+ const paths = resolveEvolutionPaths({
312
+ homeDir: input.homeDir,
313
+ projectKey: input.batch.projectKey,
314
+ runId: input.batch.runId,
315
+ });
316
+ const overwrite = input.overwrite === true;
317
+ await writeJson(paths.evidenceWindowPath, input.batch.evidenceWindow, { overwrite });
318
+ await writeJson(paths.batchPath, input.batch, { overwrite });
319
+
320
+ const plan = createOkfKnowledgePlanFromDistillationBatch(input.batch, {
321
+ homeDir: input.homeDir,
322
+ });
323
+ const okf = await activateOkfKnowledgePlan({
324
+ homeDir: input.homeDir,
325
+ plan,
326
+ overwrite,
327
+ evidenceWindowPath: paths.evidenceWindowPath,
328
+ });
329
+
330
+ const evosCasePaths: string[] = [];
331
+ for (const evosCase of input.batch.evosCases) {
332
+ const matchingCandidate = plan.candidates.find((candidate) => candidate.id === evosCase.id);
333
+ const persistedEvosCase =
334
+ matchingCandidate?.decision === "auto-accept"
335
+ ? { ...evosCase, reviewState: "auto-accepted" as const }
336
+ : matchingCandidate?.decision === "needs-human"
337
+ ? { ...evosCase, reviewState: "needs-human" as const }
338
+ : evosCase;
339
+ validateEvolutionEvosCase(persistedEvosCase);
340
+ const path = join(paths.evosCasesProjectDir, `${evosCase.id}.json`);
341
+ await writeJson(path, persistedEvosCase, { overwrite });
342
+ evosCasePaths.push(path);
343
+ }
344
+
345
+ const repoProposalPaths: string[] = [];
346
+ for (const proposal of input.batch.repoProposals) {
347
+ const path = join(paths.repoProposalsDir, `${proposal.id}.json`);
348
+ await writeJson(path, proposal, { overwrite });
349
+ repoProposalPaths.push(path);
350
+ }
351
+
352
+ const evosCasesRootDir = resolveEvoDevPaths(input.homeDir).evosCasesDir;
353
+ const evosProjectKeys = await listDirectoryNames(evosCasesRootDir);
354
+ const evosProjects = await Promise.all(
355
+ evosProjectKeys.map(async (projectKey) => {
356
+ const cases = await readJsonFiles(join(evosCasesRootDir, projectKey), parseEvosCase);
357
+ return {
358
+ projectKey,
359
+ cases: cases.map((evosCase) => ({
360
+ id: evosCase.id,
361
+ title: evosCase.title,
362
+ reviewState: evosCase.reviewState,
363
+ })),
364
+ };
365
+ }),
366
+ );
367
+ await writeJson(
368
+ paths.evosIndexPath,
369
+ {
370
+ schemaVersion: 1,
371
+ updatedAt: input.batch.createdAt,
372
+ projects: evosProjects,
373
+ },
374
+ { overwrite: true },
375
+ );
376
+
377
+ const allRunProposals = await readJsonFiles(paths.repoProposalsDir, parseRepoProposal);
378
+ await writeJson(
379
+ paths.repoProposalsIndexPath,
380
+ {
381
+ schemaVersion: 1,
382
+ projectKey: input.batch.projectKey,
383
+ runId: input.batch.runId,
384
+ updatedAt: input.batch.createdAt,
385
+ proposals: allRunProposals.map((proposal) => ({
386
+ id: proposal.id,
387
+ kind: proposal.kind,
388
+ title: proposal.title,
389
+ reviewState: proposal.reviewState,
390
+ })),
391
+ },
392
+ { overwrite: true },
393
+ );
394
+
395
+ return {
396
+ evidenceWindowPath: paths.evidenceWindowPath,
397
+ batchPath: paths.batchPath,
398
+ okf,
399
+ evosCasePaths,
400
+ repoProposalPaths,
401
+ evosIndexPath: paths.evosIndexPath,
402
+ };
403
+ }
404
+
405
+ function createRunSummary(
406
+ evidenceWindow: EvolutionEvidenceWindow,
407
+ roleIds: string[],
408
+ failedSignalCount: number,
409
+ ): string {
410
+ const failureClause =
411
+ failedSignalCount === 0
412
+ ? "No failure signal was detected in metadata summaries."
413
+ : `${failedSignalCount} potential failure or issue signal(s) were detected.`;
414
+ return sanitizeText(
415
+ `Run ${evidenceWindow.runId} produced ${evidenceWindow.events.length} redacted event(s) across ${roleIds.length} role(s). ${failureClause}`,
416
+ );
417
+ }
418
+
419
+ function createProvenance(
420
+ evidenceWindow: EvolutionEvidenceWindow,
421
+ createdAt: string,
422
+ sourceRefs: string[],
423
+ ): EvolutionKnowledgeRecord["provenance"] {
424
+ return {
425
+ runId: evidenceWindow.runId,
426
+ taskId: evidenceWindow.taskId,
427
+ evidenceWindowId: evidenceWindow.id,
428
+ sourceRefs,
429
+ createdAt,
430
+ createdBy: "evodev",
431
+ rawLogsStored: false,
432
+ rawPromptsStored: false,
433
+ sourceDumpsStored: false,
434
+ rawCommandOutputStored: false,
435
+ };
436
+ }
@@ -0,0 +1,3 @@
1
+ export { analyzeEvolutionRun } from "../evidence/analysis.ts";
2
+ export * from "./distillation.ts";
3
+ export * from "./process.ts";