@evo-dev/core 0.0.1-alpha → 0.0.1-alpha.10
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/assets/agents/review/code-reviewer/examples.md +1 -1
- package/assets/agents/review/code-reviewer/prompt.md +1 -1
- package/assets/agents/review/code-reviewer/verification.md +1 -1
- package/assets/skills/coding/knowledge-distillation/SKILL.md +251 -0
- package/assets/skills/coding/knowledge-distillation/manifest.json +10 -0
- package/assets/skills/coding/knowledge-distillation/references/knowledge-distillation-methods.md +126 -0
- package/assets/team/agents/code-reviewer.md +48 -0
- package/assets/team/agents/docs-maintainer.md +51 -0
- package/assets/team/agents/implementation-engineer.md +51 -0
- package/assets/team/agents/product-scope-analyst.md +58 -0
- package/assets/team/agents/release-engineer.md +55 -0
- package/assets/team/agents/security-boundary-reviewer.md +50 -0
- package/assets/team/agents/solution-architect.md +51 -0
- package/assets/team/agents/verification-engineer.md +51 -0
- package/assets/team/team.md +102 -0
- package/assets/workflows/rd-bug-fix/WORKFLOW.json +1 -1
- package/assets/workflows/rd-code-review/WORKFLOW.json +1 -1
- package/assets/workflows/rd-docs-update/WORKFLOW.json +1 -1
- package/assets/workflows/rd-feature-implementation/WORKFLOW.json +1 -1
- package/assets/workflows/rd-refactor/WORKFLOW.json +1 -1
- package/assets/workflows/rd-release-readiness/WORKFLOW.json +1 -1
- package/assets/workflows/rd-security-boundary-review/WORKFLOW.json +2 -2
- package/assets/workflows/rd-test-generation/WORKFLOW.json +1 -1
- package/dist/config/index.js +1115 -81
- package/dist/index.js +13796 -2196
- package/dist/plugins/index.js +32 -32
- package/package.json +5 -1
- package/src/agents/index.ts +63 -292
- package/src/code-agent-traces/index.ts +520 -0
- package/src/config/index.ts +7 -0
- package/src/config/paths.ts +30 -0
- package/src/config/settings.ts +201 -0
- package/src/config/store.ts +152 -0
- package/src/daemon/index.ts +462 -40
- package/src/evolution/candidates/index.ts +564 -0
- package/src/evolution/control/index.ts +20 -0
- package/src/evolution/evidence/analysis.ts +533 -0
- package/src/evolution/evidence/index.ts +3 -0
- package/src/evolution/evidence/session-memory/analysis.ts +281 -0
- package/src/evolution/evidence/session-memory/constants.ts +9 -0
- package/src/evolution/evidence/session-memory/index.ts +7 -0
- package/src/evolution/evidence/session-memory/paths.ts +29 -0
- package/src/evolution/evidence/session-memory/policy.ts +39 -0
- package/src/evolution/evidence/session-memory/segment.ts +202 -0
- package/src/evolution/evidence/session-memory/sensitivity.ts +335 -0
- package/src/evolution/evidence/session-memory/state-machine.ts +249 -0
- package/src/evolution/evidence/session-memory/storage.ts +379 -0
- package/src/evolution/evidence/session-memory/types.ts +221 -0
- package/src/evolution/evidence/session-memory/updater.ts +191 -0
- package/src/evolution/formatters.ts +169 -0
- package/src/evolution/index.ts +16 -0
- package/src/evolution/knowledge/index.ts +5427 -0
- package/src/evolution/paths.ts +44 -0
- package/src/evolution/processor/distillation.ts +518 -0
- package/src/evolution/processor/index.ts +3 -0
- package/src/evolution/processor/process.ts +528 -0
- package/src/{learning → evolution/review}/index.ts +10 -14
- package/src/evolution/schema.ts +568 -0
- package/src/evolution/shared.ts +758 -0
- package/src/evolution/triggers/classification.ts +102 -0
- package/src/evolution/triggers/index.ts +295 -0
- package/src/hooks/index.ts +652 -376
- package/src/index.ts +16 -3
- package/src/pack/index.ts +13 -13
- package/src/plugins/capabilities.ts +40 -42
- package/src/plugins/index.ts +0 -1
- package/src/plugins/types.ts +4 -0
- package/src/projects/index.ts +453 -0
- package/src/protected-zones/index.ts +29 -11
- package/src/runtime-logs/index.ts +790 -0
- package/src/sync/orchestrator.ts +6 -0
- package/src/team/index.ts +3642 -0
- package/src/team/mcp.ts +405 -0
- package/src/team/prompts.ts +141 -0
- package/src/utils/errors.ts +13 -0
- package/src/utils/fs.ts +40 -0
- package/src/utils/hash.ts +9 -0
- package/src/utils/ids.ts +12 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/parsing.ts +11 -0
- package/src/utils/text.ts +18 -0
- package/src/utils/time.ts +5 -0
- package/src/workflow/index.ts +6 -24
- package/src/project/index.ts +0 -507
- package/src/task/index.ts +0 -840
package/src/config/settings.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import {
|
|
3
|
+
type SessionMemoryPolicySnapshot,
|
|
4
|
+
createDefaultSessionMemoryPolicy,
|
|
5
|
+
parseSessionMemoryPolicy,
|
|
6
|
+
} from "../evolution/evidence/session-memory/index.ts";
|
|
1
7
|
import { type HookSettings, createDefaultHookSettings, parseHookSettings } from "../hooks/index.ts";
|
|
2
8
|
import { EvoDevConfigError, describeType } from "./errors.ts";
|
|
9
|
+
import { resolveEvoDevPaths } from "./paths.ts";
|
|
3
10
|
|
|
4
11
|
export interface PluginSettings {
|
|
5
12
|
enabled: boolean;
|
|
@@ -7,6 +14,22 @@ export interface PluginSettings {
|
|
|
7
14
|
autoSyncAgents?: boolean;
|
|
8
15
|
}
|
|
9
16
|
|
|
17
|
+
export interface MemorySettings {
|
|
18
|
+
autoAccept: boolean;
|
|
19
|
+
runtimeInjection: boolean;
|
|
20
|
+
staleReview: boolean;
|
|
21
|
+
lexicalIndex: boolean;
|
|
22
|
+
sessionMemory: SessionMemoryPolicySnapshot;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface EvolutionSettings {
|
|
26
|
+
automation: {
|
|
27
|
+
knowledge: boolean;
|
|
28
|
+
semanticKnowledge: boolean;
|
|
29
|
+
recommendations: boolean;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
10
33
|
export interface EvoDevSettings {
|
|
11
34
|
version: 1;
|
|
12
35
|
platform: {
|
|
@@ -28,6 +51,9 @@ export interface EvoDevSettings {
|
|
|
28
51
|
lastRunAt: string | null;
|
|
29
52
|
};
|
|
30
53
|
hooks: HookSettings;
|
|
54
|
+
teamRuntime: TeamRuntimeSettings;
|
|
55
|
+
memory: MemorySettings;
|
|
56
|
+
evolution: EvolutionSettings;
|
|
31
57
|
}
|
|
32
58
|
|
|
33
59
|
export type SettingsInput = Partial<{
|
|
@@ -43,8 +69,21 @@ export type SettingsInput = Partial<{
|
|
|
43
69
|
}>;
|
|
44
70
|
doctor: Partial<EvoDevSettings["doctor"]>;
|
|
45
71
|
hooks: unknown;
|
|
72
|
+
teamRuntime: Partial<TeamRuntimeSettings>;
|
|
73
|
+
memory: Partial<MemorySettings>;
|
|
74
|
+
evolution: Partial<{
|
|
75
|
+
automation: Partial<EvolutionSettings["automation"]>;
|
|
76
|
+
}>;
|
|
46
77
|
}>;
|
|
47
78
|
|
|
79
|
+
export interface TeamRuntimeSettings {
|
|
80
|
+
defaultRuntime: "codex" | "claude";
|
|
81
|
+
defaultModel: string | null;
|
|
82
|
+
defaultThinkingLevel: string | null;
|
|
83
|
+
recordTranscript: boolean;
|
|
84
|
+
displayMode: "normal" | "development";
|
|
85
|
+
}
|
|
86
|
+
|
|
48
87
|
export function createDefaultSettings(os: string = process.platform): EvoDevSettings {
|
|
49
88
|
return {
|
|
50
89
|
version: 1,
|
|
@@ -73,6 +112,39 @@ export function createDefaultSettings(os: string = process.platform): EvoDevSett
|
|
|
73
112
|
lastRunAt: null,
|
|
74
113
|
},
|
|
75
114
|
hooks: createDefaultHookSettings(),
|
|
115
|
+
teamRuntime: createDefaultTeamRuntimeSettings(),
|
|
116
|
+
memory: createDefaultMemorySettings(),
|
|
117
|
+
evolution: createDefaultEvolutionSettings(),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function createDefaultTeamRuntimeSettings(): TeamRuntimeSettings {
|
|
122
|
+
return {
|
|
123
|
+
defaultRuntime: "codex",
|
|
124
|
+
defaultModel: null,
|
|
125
|
+
defaultThinkingLevel: null,
|
|
126
|
+
recordTranscript: false,
|
|
127
|
+
displayMode: "normal",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createDefaultMemorySettings(): MemorySettings {
|
|
132
|
+
return {
|
|
133
|
+
autoAccept: true,
|
|
134
|
+
runtimeInjection: true,
|
|
135
|
+
staleReview: true,
|
|
136
|
+
lexicalIndex: true,
|
|
137
|
+
sessionMemory: createDefaultSessionMemoryPolicy(),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function createDefaultEvolutionSettings(): EvolutionSettings {
|
|
142
|
+
return {
|
|
143
|
+
automation: {
|
|
144
|
+
knowledge: true,
|
|
145
|
+
semanticKnowledge: false,
|
|
146
|
+
recommendations: false,
|
|
147
|
+
},
|
|
76
148
|
};
|
|
77
149
|
}
|
|
78
150
|
|
|
@@ -112,11 +184,37 @@ export function mergeSettings(
|
|
|
112
184
|
...existing.doctor,
|
|
113
185
|
},
|
|
114
186
|
hooks: existing.hooks ?? defaults.hooks,
|
|
187
|
+
teamRuntime: {
|
|
188
|
+
...defaults.teamRuntime,
|
|
189
|
+
...existing.teamRuntime,
|
|
190
|
+
},
|
|
191
|
+
memory: {
|
|
192
|
+
...defaults.memory,
|
|
193
|
+
...existing.memory,
|
|
194
|
+
},
|
|
195
|
+
evolution: {
|
|
196
|
+
...defaults.evolution,
|
|
197
|
+
...existing.evolution,
|
|
198
|
+
automation: {
|
|
199
|
+
...defaults.evolution.automation,
|
|
200
|
+
...existing.evolution?.automation,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
115
203
|
};
|
|
116
204
|
|
|
117
205
|
return parseSettings(merged);
|
|
118
206
|
}
|
|
119
207
|
|
|
208
|
+
export async function readRuntimeInjectionSettings(homeDir?: string): Promise<MemorySettings> {
|
|
209
|
+
const paths = resolveEvoDevPaths(homeDir);
|
|
210
|
+
try {
|
|
211
|
+
return parseSettings(JSON.parse(await readFile(paths.settingsPath, "utf8"))).memory;
|
|
212
|
+
} catch (error) {
|
|
213
|
+
if (isNotFoundError(error)) return createDefaultMemorySettings();
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
120
218
|
export function parseSettings(value: unknown): EvoDevSettings {
|
|
121
219
|
const root = expectRecord(value, "settings");
|
|
122
220
|
const version = root.version;
|
|
@@ -157,11 +255,104 @@ export function parseSettings(value: unknown): EvoDevSettings {
|
|
|
157
255
|
lastRunAt: expectNullableString(doctor.lastRunAt, "settings.doctor.lastRunAt"),
|
|
158
256
|
},
|
|
159
257
|
hooks: parseHookSettings(root.hooks),
|
|
258
|
+
teamRuntime: parseTeamRuntimeSettings(
|
|
259
|
+
root.teamRuntime ?? createDefaultTeamRuntimeSettings(),
|
|
260
|
+
"settings.teamRuntime",
|
|
261
|
+
),
|
|
262
|
+
memory: parseMemorySettings(root.memory ?? createDefaultMemorySettings(), "settings.memory"),
|
|
263
|
+
evolution: parseEvolutionSettings(
|
|
264
|
+
root.evolution ?? createDefaultEvolutionSettings(),
|
|
265
|
+
"settings.evolution",
|
|
266
|
+
),
|
|
160
267
|
};
|
|
161
268
|
|
|
162
269
|
return parsed;
|
|
163
270
|
}
|
|
164
271
|
|
|
272
|
+
function parseEvolutionSettings(value: unknown, path: string): EvolutionSettings {
|
|
273
|
+
const input = expectRecord(value, path);
|
|
274
|
+
const defaults = createDefaultEvolutionSettings();
|
|
275
|
+
const automation = expectRecord(input.automation ?? defaults.automation, `${path}.automation`);
|
|
276
|
+
return {
|
|
277
|
+
automation: {
|
|
278
|
+
knowledge:
|
|
279
|
+
automation.knowledge === undefined
|
|
280
|
+
? defaults.automation.knowledge
|
|
281
|
+
: expectBoolean(automation.knowledge, `${path}.automation.knowledge`),
|
|
282
|
+
semanticKnowledge:
|
|
283
|
+
automation.semanticKnowledge === undefined
|
|
284
|
+
? defaults.automation.semanticKnowledge
|
|
285
|
+
: expectBoolean(automation.semanticKnowledge, `${path}.automation.semanticKnowledge`),
|
|
286
|
+
recommendations:
|
|
287
|
+
automation.recommendations === undefined
|
|
288
|
+
? defaults.automation.recommendations
|
|
289
|
+
: expectBoolean(automation.recommendations, `${path}.automation.recommendations`),
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function parseMemorySettings(value: unknown, path: string): MemorySettings {
|
|
295
|
+
const input = expectRecord(value, path);
|
|
296
|
+
const defaults = createDefaultMemorySettings();
|
|
297
|
+
return {
|
|
298
|
+
autoAccept:
|
|
299
|
+
input.autoAccept === undefined
|
|
300
|
+
? defaults.autoAccept
|
|
301
|
+
: expectBoolean(input.autoAccept, `${path}.autoAccept`),
|
|
302
|
+
runtimeInjection:
|
|
303
|
+
input.runtimeInjection === undefined
|
|
304
|
+
? defaults.runtimeInjection
|
|
305
|
+
: expectBoolean(input.runtimeInjection, `${path}.runtimeInjection`),
|
|
306
|
+
staleReview:
|
|
307
|
+
input.staleReview === undefined
|
|
308
|
+
? defaults.staleReview
|
|
309
|
+
: expectBoolean(input.staleReview, `${path}.staleReview`),
|
|
310
|
+
lexicalIndex:
|
|
311
|
+
input.lexicalIndex === undefined
|
|
312
|
+
? defaults.lexicalIndex
|
|
313
|
+
: expectBoolean(input.lexicalIndex, `${path}.lexicalIndex`),
|
|
314
|
+
sessionMemory: parseSessionMemoryPolicy(
|
|
315
|
+
isPlainRecord(input.sessionMemory) ? input.sessionMemory : defaults.sessionMemory,
|
|
316
|
+
),
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function parseTeamRuntimeSettings(value: unknown, path: string): TeamRuntimeSettings {
|
|
321
|
+
const input = expectRecord(value, path);
|
|
322
|
+
const defaults = createDefaultTeamRuntimeSettings();
|
|
323
|
+
const defaultRuntime = input.defaultRuntime ?? defaults.defaultRuntime;
|
|
324
|
+
if (defaultRuntime !== "codex" && defaultRuntime !== "claude") {
|
|
325
|
+
throw new EvoDevConfigError(`Invalid ${path}.defaultRuntime; expected codex or claude`);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return {
|
|
329
|
+
defaultRuntime,
|
|
330
|
+
defaultModel:
|
|
331
|
+
input.defaultModel === undefined
|
|
332
|
+
? defaults.defaultModel
|
|
333
|
+
: expectNullableString(input.defaultModel, `${path}.defaultModel`),
|
|
334
|
+
defaultThinkingLevel:
|
|
335
|
+
input.defaultThinkingLevel === undefined
|
|
336
|
+
? defaults.defaultThinkingLevel
|
|
337
|
+
: expectNullableString(input.defaultThinkingLevel, `${path}.defaultThinkingLevel`),
|
|
338
|
+
recordTranscript:
|
|
339
|
+
input.recordTranscript === undefined
|
|
340
|
+
? defaults.recordTranscript
|
|
341
|
+
: expectBoolean(input.recordTranscript, `${path}.recordTranscript`),
|
|
342
|
+
displayMode: parseTeamRuntimeDisplayMode(input.displayMode, defaults.displayMode, path),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function parseTeamRuntimeDisplayMode(
|
|
347
|
+
value: unknown,
|
|
348
|
+
fallback: TeamRuntimeSettings["displayMode"],
|
|
349
|
+
path: string,
|
|
350
|
+
): TeamRuntimeSettings["displayMode"] {
|
|
351
|
+
if (value === undefined) return fallback;
|
|
352
|
+
if (value === "normal" || value === "development") return value;
|
|
353
|
+
throw new EvoDevConfigError(`Invalid ${path}.displayMode; expected normal or development`);
|
|
354
|
+
}
|
|
355
|
+
|
|
165
356
|
function parsePluginSettings(value: unknown, path: string): PluginSettings {
|
|
166
357
|
const input = expectRecord(value, path);
|
|
167
358
|
const parsed: PluginSettings = {
|
|
@@ -187,6 +378,16 @@ function expectRecord(value: unknown, path: string): Record<string, unknown> {
|
|
|
187
378
|
return value as Record<string, unknown>;
|
|
188
379
|
}
|
|
189
380
|
|
|
381
|
+
function isPlainRecord(value: unknown): value is Record<string, unknown> {
|
|
382
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function isNotFoundError(error: unknown): boolean {
|
|
386
|
+
return (
|
|
387
|
+
error instanceof Error && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT"
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
190
391
|
function expectString(value: unknown, path: string): string {
|
|
191
392
|
if (typeof value !== "string" || value.length === 0) {
|
|
192
393
|
throw new EvoDevConfigError(`Invalid ${path}; expected non-empty string`);
|
package/src/config/store.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
+
import { ensureOkfKnowledgeBase } from "../evolution/knowledge/index.ts";
|
|
3
4
|
import { EvoDevConfigError } from "./errors.ts";
|
|
4
5
|
import { type EvoDevPaths, resolveEvoDevPaths } from "./paths.ts";
|
|
5
6
|
import { type EvoDevRegistry, createDefaultRegistry, parseRegistry } from "./registry.ts";
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
export interface CoreConfigStore {
|
|
23
24
|
readonly paths: EvoDevPaths;
|
|
24
25
|
ensureBaseDirs(): Promise<void>;
|
|
26
|
+
ensureKnowledgeBase(): Promise<void>;
|
|
25
27
|
readSettings(): Promise<EvoDevSettings>;
|
|
26
28
|
writeSettings(settings: EvoDevSettings): Promise<void>;
|
|
27
29
|
mergeAndWriteSettings(input: SettingsInput): Promise<EvoDevSettings>;
|
|
@@ -40,6 +42,15 @@ export function createCoreConfigStore(homeDir?: string): CoreConfigStore {
|
|
|
40
42
|
paths,
|
|
41
43
|
async ensureBaseDirs() {
|
|
42
44
|
await mkdir(paths.stateDir, { recursive: true });
|
|
45
|
+
await mkdir(paths.logsDir, { recursive: true });
|
|
46
|
+
await mkdir(paths.knowledgeDir, { recursive: true });
|
|
47
|
+
await mkdir(paths.evosCasesDir, { recursive: true });
|
|
48
|
+
await mkdir(paths.roleAgentsDir, { recursive: true });
|
|
49
|
+
await mkdir(paths.teamsDir, { recursive: true });
|
|
50
|
+
await mkdir(paths.runsDir, { recursive: true });
|
|
51
|
+
},
|
|
52
|
+
async ensureKnowledgeBase() {
|
|
53
|
+
await ensureKnowledgeBaseFiles(paths);
|
|
43
54
|
},
|
|
44
55
|
async readSettings() {
|
|
45
56
|
return readJsonFile(paths.settingsPath, parseSettings);
|
|
@@ -81,6 +92,7 @@ export function createCoreConfigStore(homeDir?: string): CoreConfigStore {
|
|
|
81
92
|
export async function initializeCoreConfig(homeDir?: string): Promise<CoreConfigStore> {
|
|
82
93
|
const store = createCoreConfigStore(homeDir);
|
|
83
94
|
await store.ensureBaseDirs();
|
|
95
|
+
await store.ensureKnowledgeBase();
|
|
84
96
|
await writeIfMissing(store.paths.settingsPath, createDefaultSettings());
|
|
85
97
|
await writeIfMissing(store.paths.registryPath, createDefaultRegistry());
|
|
86
98
|
await writeIfMissing(store.paths.installStatePath, createDefaultInstallState());
|
|
@@ -88,6 +100,88 @@ export async function initializeCoreConfig(homeDir?: string): Promise<CoreConfig
|
|
|
88
100
|
return store;
|
|
89
101
|
}
|
|
90
102
|
|
|
103
|
+
export async function ensureKnowledgeBaseFiles(paths: EvoDevPaths): Promise<void> {
|
|
104
|
+
await mkdir(paths.knowledgeDir, { recursive: true });
|
|
105
|
+
await mkdir(paths.evosCasesDir, { recursive: true });
|
|
106
|
+
await ensureOkfKnowledgeBase(paths.homeDir);
|
|
107
|
+
await writeTextIfMissing(
|
|
108
|
+
`${paths.knowledgeDir}/README.md`,
|
|
109
|
+
[
|
|
110
|
+
"# EvoDev Knowledge",
|
|
111
|
+
"",
|
|
112
|
+
"Local-private knowledge base for user-accepted facts, decisions, architecture notes, and reusable domain context.",
|
|
113
|
+
"",
|
|
114
|
+
"EvoDev must not populate this directory from source code, prompts, command output, logs, or transcripts without an explicit consent flow.",
|
|
115
|
+
"",
|
|
116
|
+
].join("\n"),
|
|
117
|
+
);
|
|
118
|
+
await writeIndexIfMissingOrMigrate(paths.knowledgeIndexPath, "knowledge-index", {
|
|
119
|
+
version: 1,
|
|
120
|
+
kind: "knowledge-index",
|
|
121
|
+
roleTags: [],
|
|
122
|
+
entries: [],
|
|
123
|
+
});
|
|
124
|
+
await writeTextIfMissing(
|
|
125
|
+
`${paths.evosDir}/README.md`,
|
|
126
|
+
[
|
|
127
|
+
"# EvoDev Evos",
|
|
128
|
+
"",
|
|
129
|
+
"Local-private evolution case library for reviewed improvement cases and reusable process changes.",
|
|
130
|
+
"",
|
|
131
|
+
"Cases start empty. Future automation may propose candidates, but accepted evos require explicit review before they can influence workflows or routing.",
|
|
132
|
+
"",
|
|
133
|
+
].join("\n"),
|
|
134
|
+
);
|
|
135
|
+
await writeTextIfMissing(
|
|
136
|
+
`${paths.evosCasesDir}/README.md`,
|
|
137
|
+
[
|
|
138
|
+
"# Evolution Cases",
|
|
139
|
+
"",
|
|
140
|
+
"Store one reviewed evolution case per file. Do not store raw prompts, source dumps, secrets, transcripts, or raw command output here.",
|
|
141
|
+
"",
|
|
142
|
+
].join("\n"),
|
|
143
|
+
);
|
|
144
|
+
await writeIndexIfMissingOrMigrate(paths.evosIndexPath, "evos-index", {
|
|
145
|
+
version: 1,
|
|
146
|
+
kind: "evos-index",
|
|
147
|
+
roleTags: [],
|
|
148
|
+
cases: [],
|
|
149
|
+
});
|
|
150
|
+
await writeTextIfMissing(
|
|
151
|
+
`${paths.roleAgentsDir}/README.md`,
|
|
152
|
+
[
|
|
153
|
+
"# Role Agents",
|
|
154
|
+
"",
|
|
155
|
+
"Local-private role agent registry for EvoDev-managed agent roles and user-reviewed role extensions.",
|
|
156
|
+
"",
|
|
157
|
+
"Repository-specific role agents should be proposed first and written into a user repository only after explicit project opt-in.",
|
|
158
|
+
"",
|
|
159
|
+
].join("\n"),
|
|
160
|
+
);
|
|
161
|
+
await writeIndexIfMissingOrMigrate(paths.roleAgentsIndexPath, "role-agent-index", {
|
|
162
|
+
version: 1,
|
|
163
|
+
kind: "role-agent-index",
|
|
164
|
+
roles: [],
|
|
165
|
+
projectExtensions: [],
|
|
166
|
+
});
|
|
167
|
+
await writeTextIfMissing(
|
|
168
|
+
`${paths.teamsDir}/README.md`,
|
|
169
|
+
[
|
|
170
|
+
"# Agent Teams",
|
|
171
|
+
"",
|
|
172
|
+
"Local-private EvoHub team registry for reviewed role-agent team definitions.",
|
|
173
|
+
"",
|
|
174
|
+
"Teams may reference role agents and role-tagged knowledge, but they must not contain raw source, prompts, transcripts, secrets, or raw command output.",
|
|
175
|
+
"",
|
|
176
|
+
].join("\n"),
|
|
177
|
+
);
|
|
178
|
+
await writeIndexIfMissingOrMigrate(paths.teamsIndexPath, "agent-team-index", {
|
|
179
|
+
version: 1,
|
|
180
|
+
kind: "agent-team-index",
|
|
181
|
+
teams: [],
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
91
185
|
async function readJsonFile<T>(filePath: string, parse: (value: unknown) => T): Promise<T> {
|
|
92
186
|
let raw: string;
|
|
93
187
|
|
|
@@ -148,6 +242,60 @@ async function writeIfMissing(filePath: string, value: unknown): Promise<void> {
|
|
|
148
242
|
}
|
|
149
243
|
}
|
|
150
244
|
|
|
245
|
+
async function writeIndexIfMissingOrMigrate(
|
|
246
|
+
filePath: string,
|
|
247
|
+
kind: string,
|
|
248
|
+
defaults: Record<string, unknown>,
|
|
249
|
+
): Promise<void> {
|
|
250
|
+
let raw: string;
|
|
251
|
+
try {
|
|
252
|
+
raw = await readFile(filePath, "utf8");
|
|
253
|
+
} catch (error) {
|
|
254
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
255
|
+
await writeJsonFile(filePath, defaults);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
throw new EvoDevConfigError(
|
|
260
|
+
`Cannot inspect config file (${describeFileError(error)})`,
|
|
261
|
+
filePath,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
let existing: unknown;
|
|
266
|
+
try {
|
|
267
|
+
existing = JSON.parse(raw);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
throw new EvoDevConfigError(
|
|
270
|
+
`Invalid bootstrap index JSON (${describeFileError(error)})`,
|
|
271
|
+
filePath,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (!isRecord(existing) || existing.kind !== kind) return;
|
|
276
|
+
|
|
277
|
+
const migrated = { ...defaults, ...existing };
|
|
278
|
+
if (Object.keys(defaults).every((key) => key in existing)) return;
|
|
279
|
+
await writeJsonFile(filePath, migrated);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async function writeTextIfMissing(filePath: string, value: string): Promise<void> {
|
|
283
|
+
try {
|
|
284
|
+
await readFile(filePath, "utf8");
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
287
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
288
|
+
await writeFile(filePath, value, "utf8");
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
throw new EvoDevConfigError(
|
|
293
|
+
`Cannot inspect config file (${describeFileError(error)})`,
|
|
294
|
+
filePath,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
151
299
|
async function writeJsonFile(filePath: string, value: unknown): Promise<void> {
|
|
152
300
|
await mkdir(dirname(filePath), { recursive: true });
|
|
153
301
|
await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
@@ -164,3 +312,7 @@ function describeFileError(error: unknown): string {
|
|
|
164
312
|
function isNodeError(error: unknown): error is NodeJS.ErrnoException {
|
|
165
313
|
return error instanceof Error && "code" in error;
|
|
166
314
|
}
|
|
315
|
+
|
|
316
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
317
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
318
|
+
}
|