@evo-dev/core 0.0.1-alpha → 0.0.1-alpha.1
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 +248 -0
- package/assets/skills/coding/knowledge-distillation/manifest.json +10 -0
- package/assets/skills/coding/knowledge-distillation/references/knowledge-distillation-methods.md +122 -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 +242 -36
- package/dist/index.js +5045 -934
- package/dist/plugins/index.js +32 -32
- package/package.json +1 -1
- package/src/agents/index.ts +28 -49
- package/src/config/index.ts +2 -0
- package/src/config/paths.ts +30 -0
- package/src/config/settings.ts +52 -0
- package/src/config/store.ts +150 -0
- package/src/daemon/index.ts +376 -3
- package/src/evolution/index.ts +2356 -0
- package/src/hooks/index.ts +255 -238
- package/src/index.ts +4 -0
- 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/protected-zones/index.ts +29 -11
- package/src/runtime-logs/index.ts +324 -0
- package/src/sync/orchestrator.ts +6 -0
- package/src/task/index.ts +3 -3
- package/src/team/index.ts +2398 -0
- package/src/team/mcp.ts +401 -0
- package/src/workflow/index.ts +6 -6
package/dist/plugins/index.js
CHANGED
|
@@ -9,37 +9,28 @@ function createUnknownNegotiatedCapabilities(pluginId) {
|
|
|
9
9
|
hooks: "unsupported",
|
|
10
10
|
canPlanWrites: false,
|
|
11
11
|
warnings: [],
|
|
12
|
-
|
|
12
|
+
advisories: [`Plugin ${pluginId} capabilities are unknown and unsupported.`]
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
function isCapabilityUsable(state) {
|
|
16
16
|
return state === "enabled";
|
|
17
17
|
}
|
|
18
|
-
function assertNoUnverifiedWrites(negotiation) {
|
|
19
|
-
if (!negotiation.canPlanWrites) {
|
|
20
|
-
throw new Error(`Plugin ${negotiation.pluginId} has no verified enabled write capabilities.`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
18
|
function negotiatePluginCapabilities(input) {
|
|
24
19
|
if (input.pluginId === "codex") {
|
|
25
|
-
const
|
|
26
|
-
input.declared.skills.supported ? "skills" : null,
|
|
27
|
-
input.declared.agents.supported ? "agents" : null,
|
|
28
|
-
input.declared.hooks.supported ? "hooks" : null
|
|
29
|
-
].filter(Boolean);
|
|
30
|
-
const blockers = ["Codex capabilities are unverified; writes are unsupported in I10."];
|
|
20
|
+
const advisories = [];
|
|
31
21
|
const warnings = [
|
|
32
|
-
input.verified ? "Codex
|
|
33
|
-
|
|
22
|
+
input.verified ? "Codex metadata-only verification artifact exists; implemented Codex skill/agent distribution remains governed by adapter tests." : null,
|
|
23
|
+
input.declared.skills.supported ? "Codex skills are distributed through the EvoDev Codex plugin bundle, not direct user-directory skill sync." : null,
|
|
24
|
+
input.declared.agents.supported ? "Codex agents can sync to user-level TOML files with no-overwrite semantics." : null
|
|
34
25
|
].filter((warning) => warning !== null);
|
|
35
26
|
return {
|
|
36
27
|
pluginId: input.pluginId,
|
|
37
|
-
skills: input.declared.skills.supported
|
|
38
|
-
agents: input.declared.agents.supported
|
|
39
|
-
hooks: input.declared.hooks.supported
|
|
40
|
-
canPlanWrites:
|
|
28
|
+
skills: resolveNonCodexCapabilityState(input.declared.skills.supported, input.enabled),
|
|
29
|
+
agents: resolveNonCodexCapabilityState(input.declared.agents.supported, input.enabled),
|
|
30
|
+
hooks: resolveNonCodexCapabilityState(input.declared.hooks.supported, input.enabled),
|
|
31
|
+
canPlanWrites: input.enabled && input.declared.agents.supported,
|
|
41
32
|
warnings,
|
|
42
|
-
|
|
33
|
+
advisories
|
|
43
34
|
};
|
|
44
35
|
}
|
|
45
36
|
return {
|
|
@@ -49,9 +40,9 @@ function negotiatePluginCapabilities(input) {
|
|
|
49
40
|
hooks: resolveNonCodexCapabilityState(input.declared.hooks.supported, input.enabled),
|
|
50
41
|
canPlanWrites: input.enabled && input.declared.skills.supported && input.declared.agents.supported,
|
|
51
42
|
warnings: input.enabled ? [] : [
|
|
52
|
-
`Plugin ${input.pluginId} has declared capabilities but is not enabled
|
|
43
|
+
`Plugin ${input.pluginId} has declared capabilities but is not enabled for write planning.`
|
|
53
44
|
],
|
|
54
|
-
|
|
45
|
+
advisories: []
|
|
55
46
|
};
|
|
56
47
|
}
|
|
57
48
|
function resolveNonCodexCapabilityState(supported, enabled) {
|
|
@@ -63,7 +54,9 @@ async function createCodexCapabilityVerificationArtifact(input) {
|
|
|
63
54
|
const timestamp = input.createdAt ?? new Date().toISOString();
|
|
64
55
|
const detectionMessage = sanitizeText(input.detection.message);
|
|
65
56
|
const diagnostics = [
|
|
66
|
-
"Codex
|
|
57
|
+
"Codex skills are packaged in the EvoDev Codex plugin payload.",
|
|
58
|
+
"Codex agents sync to user-level TOML files under ~/.codex/agents.",
|
|
59
|
+
"Codex hooks are supplied by the EvoDev Codex plugin manifest and enabled through Codex plugin hooks."
|
|
67
60
|
];
|
|
68
61
|
return {
|
|
69
62
|
version: 1,
|
|
@@ -80,7 +73,11 @@ async function createCodexCapabilityVerificationArtifact(input) {
|
|
|
80
73
|
externalUpload: false,
|
|
81
74
|
networkUsed: false,
|
|
82
75
|
toolSummary: { tool: "codex", detectionStatus: input.detection.status, version: null },
|
|
83
|
-
capabilities: {
|
|
76
|
+
capabilities: {
|
|
77
|
+
skills: "plugin-bundled",
|
|
78
|
+
agents: "user-level-toml-sync",
|
|
79
|
+
hooks: "plugin-manifest-hooks"
|
|
80
|
+
},
|
|
84
81
|
writeBoundary: {
|
|
85
82
|
writesAllowed: false,
|
|
86
83
|
allowedPaths: [],
|
|
@@ -98,7 +95,7 @@ async function createCodexCapabilityVerificationArtifact(input) {
|
|
|
98
95
|
secretsStored: false,
|
|
99
96
|
externalUpload: false
|
|
100
97
|
},
|
|
101
|
-
|
|
98
|
+
advisories: [],
|
|
102
99
|
diagnostics,
|
|
103
100
|
evidenceRefs: [],
|
|
104
101
|
evidence: {
|
|
@@ -106,7 +103,8 @@ async function createCodexCapabilityVerificationArtifact(input) {
|
|
|
106
103
|
detectionMessage,
|
|
107
104
|
writesAllowed: false,
|
|
108
105
|
notes: [
|
|
109
|
-
"Metadata-only
|
|
106
|
+
"Metadata-only verification artifact; it does not probe or write Code Agent directories.",
|
|
107
|
+
"Implemented Codex asset distribution is covered by adapter tests: plugin-bundled skills and user-level TOML agents."
|
|
110
108
|
]
|
|
111
109
|
}
|
|
112
110
|
};
|
|
@@ -149,12 +147,12 @@ function formatCodexCapabilityVerificationArtifact(artifact, path) {
|
|
|
149
147
|
`Status: ${artifact.status}`,
|
|
150
148
|
`Artifact: ${path ?? "dry-run only"}`,
|
|
151
149
|
`Verified at: ${artifact.verifiedAt}`,
|
|
152
|
-
|
|
153
|
-
"
|
|
150
|
+
`Capabilities: skills=${artifact.capabilities.skills} agents=${artifact.capabilities.agents} hooks=${artifact.capabilities.hooks}`,
|
|
151
|
+
"Verification writes allowed: false",
|
|
154
152
|
"Allowed paths: none",
|
|
155
|
-
"User-level
|
|
153
|
+
"User-level agent sync path: ~/.codex/agents",
|
|
156
154
|
"Project writes allowed: false",
|
|
157
|
-
"No-overwrite
|
|
155
|
+
"No-overwrite policy: skip existing files unless force refresh is requested",
|
|
158
156
|
`External upload: ${artifact.externalUpload}`,
|
|
159
157
|
`Detection: ${artifact.evidence.detectionStatus}`,
|
|
160
158
|
...artifact.evidence.notes.map((note) => `Note: ${note}`)
|
|
@@ -171,8 +169,11 @@ async function runPluginConformance(plugin) {
|
|
|
171
169
|
}
|
|
172
170
|
if (plugin.id === "codex") {
|
|
173
171
|
const capabilities = await plugin.getCapabilities();
|
|
174
|
-
if (capabilities.skills.supported || capabilities.agents.supported
|
|
175
|
-
findings.push("Codex must
|
|
172
|
+
if (!capabilities.skills.supported || !capabilities.agents.supported) {
|
|
173
|
+
findings.push("Codex must declare plugin-bundled skills and user-level TOML agents.");
|
|
174
|
+
}
|
|
175
|
+
if (!capabilities.hooks.supported || capabilities.hooks.events.length === 0) {
|
|
176
|
+
findings.push("Codex must declare plugin-manifest hook support.");
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
179
|
return { ok: findings.length === 0, findings };
|
|
@@ -259,7 +260,6 @@ export {
|
|
|
259
260
|
createUnknownNegotiatedCapabilities,
|
|
260
261
|
createPluginRegistry,
|
|
261
262
|
createCodexCapabilityVerificationArtifact,
|
|
262
|
-
assertNoUnverifiedWrites,
|
|
263
263
|
PluginRegistryError,
|
|
264
264
|
PluginRegistry
|
|
265
265
|
};
|
package/package.json
CHANGED
package/src/agents/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type AgentOutputSchemaId =
|
|
|
14
14
|
| "review-findings-v1"
|
|
15
15
|
| "verification-summary-v1"
|
|
16
16
|
| "design-options-v1";
|
|
17
|
-
export type AgentFindingSeverity = "
|
|
17
|
+
export type AgentFindingSeverity = "critical" | "high" | "medium" | "low" | "info";
|
|
18
18
|
|
|
19
19
|
export interface AgentPermissions {
|
|
20
20
|
canReadMetadata: boolean;
|
|
@@ -64,11 +64,11 @@ export interface AgentPlannedInvocation {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
export interface AgentMergePlan {
|
|
67
|
-
strategy: "none" | "single-output" | "dedupe-preserve-conflicts
|
|
67
|
+
strategy: "none" | "single-output" | "dedupe-preserve-conflicts";
|
|
68
68
|
outputSchema: AgentOutputSchemaId | null;
|
|
69
69
|
dedupeBy: string[];
|
|
70
70
|
conflictPolicy: string[];
|
|
71
|
-
|
|
71
|
+
advisoryCategories: string[];
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
export interface AgentComposeDryRunPlan {
|
|
@@ -80,7 +80,7 @@ export interface AgentComposeDryRunPlan {
|
|
|
80
80
|
permissions: AgentPermissions;
|
|
81
81
|
mergePlan: AgentMergePlan;
|
|
82
82
|
warnings: string[];
|
|
83
|
-
|
|
83
|
+
advisories: string[];
|
|
84
84
|
rationale: string;
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -93,7 +93,7 @@ export interface AgentContextDryRunBundle {
|
|
|
93
93
|
provenance: string[];
|
|
94
94
|
};
|
|
95
95
|
warnings: string[];
|
|
96
|
-
|
|
96
|
+
advisories: string[];
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
export interface ReviewFindingOutput {
|
|
@@ -124,7 +124,7 @@ const DEFAULT_AGENT_PERMISSIONS: AgentPermissions = {
|
|
|
124
124
|
};
|
|
125
125
|
const FORBIDDEN_INPUTS = ["rawPrompts", "secrets", "rawCommandLogs", "sourceCorpus"];
|
|
126
126
|
const SAFE_AGENT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
127
|
-
const
|
|
127
|
+
const PRIVACY_ADVISORY_PATTERN =
|
|
128
128
|
/raw prompt|rawprompt|source corpus|sourcecorpus|secret|\.env|raw command|raw log|internal url|private url|network|write files|run commands|spawn agents|write memory/i;
|
|
129
129
|
const LENS_TO_EXPERTISE: Record<AgentLens, string[]> = {
|
|
130
130
|
review: ["code-review"],
|
|
@@ -170,16 +170,6 @@ export function parseAgentProfile(value: unknown): AgentProfile {
|
|
|
170
170
|
throw new Error("Agent profile must be metadata-only and must not store raw prompts/source.");
|
|
171
171
|
}
|
|
172
172
|
const permissions = normalizeAgentPermissions(profile.permissions);
|
|
173
|
-
if (
|
|
174
|
-
permissions.canWriteFiles ||
|
|
175
|
-
permissions.canRunCommands ||
|
|
176
|
-
permissions.canUseNetwork ||
|
|
177
|
-
permissions.canSpawnAgents ||
|
|
178
|
-
permissions.canWriteMemory ||
|
|
179
|
-
permissions.canReadSourceContent
|
|
180
|
-
) {
|
|
181
|
-
throw new Error("Agent profile requests permissions outside I8 dry-run boundaries.");
|
|
182
|
-
}
|
|
183
173
|
if (!SAFE_AGENT_ID_PATTERN.test(profile.id)) throw new Error("Agent profile id is unsafe.");
|
|
184
174
|
assertStringArray(profile.traits?.expertise, "profile.traits.expertise");
|
|
185
175
|
assertStringArray(profile.traits?.stance, "profile.traits.stance");
|
|
@@ -188,11 +178,6 @@ export function parseAgentProfile(value: unknown): AgentProfile {
|
|
|
188
178
|
assertStringArray(profile.inputs?.required, "profile.inputs.required");
|
|
189
179
|
assertStringArray(profile.inputs?.optional, "profile.inputs.optional");
|
|
190
180
|
assertStringArray(profile.inputs?.forbidden, "profile.inputs.forbidden");
|
|
191
|
-
if (!FORBIDDEN_INPUTS.every((item) => profile.inputs.forbidden.includes(item))) {
|
|
192
|
-
throw new Error(
|
|
193
|
-
"Agent profile must forbid raw prompts, secrets, raw command logs, and source corpus.",
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
181
|
if (!isKnownOutputSchema(profile.output?.schema))
|
|
197
182
|
throw new Error("Agent profile output schema is unsupported.");
|
|
198
183
|
assertStringArray(profile.output.requiredFields, "profile.output.requiredFields");
|
|
@@ -211,19 +196,13 @@ export function composeAgentDryRun(input: {
|
|
|
211
196
|
const mode = input.contract.route.mode;
|
|
212
197
|
const workflowId = input.workflowId ?? input.contract.route.workflowId;
|
|
213
198
|
const warnings: string[] = [];
|
|
214
|
-
const blockers: string[] = [];
|
|
215
199
|
const permissions = createDefaultAgentPermissions();
|
|
216
200
|
const requestedLenses = dedupeLenses(input.lenses ?? []);
|
|
217
|
-
const
|
|
218
|
-
input.contract,
|
|
219
|
-
requestedLenses,
|
|
220
|
-
workflowId,
|
|
221
|
-
);
|
|
222
|
-
blockers.push(...privacyBlockers);
|
|
201
|
+
const advisories = collectPrivacyBoundaryAdvisories(input.contract, requestedLenses, workflowId);
|
|
223
202
|
|
|
224
203
|
if (mode === "minimal") {
|
|
225
204
|
return {
|
|
226
|
-
ok:
|
|
205
|
+
ok: advisories.length === 0,
|
|
227
206
|
taskId: input.contract.taskId,
|
|
228
207
|
mode,
|
|
229
208
|
workflowId,
|
|
@@ -231,7 +210,7 @@ export function composeAgentDryRun(input: {
|
|
|
231
210
|
permissions,
|
|
232
211
|
mergePlan: createMergePlan([]),
|
|
233
212
|
warnings,
|
|
234
|
-
|
|
213
|
+
advisories,
|
|
235
214
|
rationale: "Minimal mode does not force dynamic agents by default.",
|
|
236
215
|
};
|
|
237
216
|
}
|
|
@@ -250,11 +229,11 @@ export function composeAgentDryRun(input: {
|
|
|
250
229
|
}));
|
|
251
230
|
|
|
252
231
|
if (mode === "standard" && agents.length > 1) {
|
|
253
|
-
|
|
232
|
+
warnings.push("Standard mode advisory selected more than one reviewer/triager.");
|
|
254
233
|
}
|
|
255
234
|
|
|
256
235
|
return {
|
|
257
|
-
ok:
|
|
236
|
+
ok: advisories.length === 0,
|
|
258
237
|
taskId: input.contract.taskId,
|
|
259
238
|
mode,
|
|
260
239
|
workflowId,
|
|
@@ -262,7 +241,7 @@ export function composeAgentDryRun(input: {
|
|
|
262
241
|
permissions,
|
|
263
242
|
mergePlan: createMergePlan(agents),
|
|
264
243
|
warnings,
|
|
265
|
-
|
|
244
|
+
advisories,
|
|
266
245
|
rationale:
|
|
267
246
|
agents.length === 0
|
|
268
247
|
? "No dynamic agents selected; deterministic verification may be sufficient."
|
|
@@ -288,7 +267,7 @@ export function loadAgentContextDryRun(profile: AgentProfile): AgentContextDryRu
|
|
|
288
267
|
provenance: [`agent-profile:${parsed.id}`],
|
|
289
268
|
},
|
|
290
269
|
warnings: [],
|
|
291
|
-
|
|
270
|
+
advisories: [],
|
|
292
271
|
};
|
|
293
272
|
}
|
|
294
273
|
|
|
@@ -375,10 +354,10 @@ export function formatAgentComposeDryRun(plan: AgentComposeDryRunPlan): string {
|
|
|
375
354
|
...(plan.warnings.length === 0
|
|
376
355
|
? [" - none"]
|
|
377
356
|
: plan.warnings.map((warning) => ` - ${warning}`)),
|
|
378
|
-
"
|
|
379
|
-
...(plan.
|
|
357
|
+
"Advisories:",
|
|
358
|
+
...(plan.advisories.length === 0
|
|
380
359
|
? [" - none"]
|
|
381
|
-
: plan.
|
|
360
|
+
: plan.advisories.map((advisory) => ` - ${advisory}`)),
|
|
382
361
|
].join("\n");
|
|
383
362
|
}
|
|
384
363
|
|
|
@@ -394,10 +373,10 @@ export function formatAgentContextDryRun(bundle: AgentContextDryRunBundle): stri
|
|
|
394
373
|
...bundle.context.forbiddenSections.map((section) => ` - ${section}`),
|
|
395
374
|
"Permissions:",
|
|
396
375
|
...Object.entries(bundle.profile.permissions).map(([key, value]) => ` - ${key}: ${value}`),
|
|
397
|
-
"
|
|
398
|
-
...(bundle.
|
|
376
|
+
"Advisories:",
|
|
377
|
+
...(bundle.advisories.length === 0
|
|
399
378
|
? [" - none"]
|
|
400
|
-
: bundle.
|
|
379
|
+
: bundle.advisories.map((advisory) => ` - ${advisory}`)),
|
|
401
380
|
].join("\n");
|
|
402
381
|
}
|
|
403
382
|
|
|
@@ -415,7 +394,7 @@ function createDynamicProfile(
|
|
|
415
394
|
traits: {
|
|
416
395
|
expertise: LENS_TO_EXPERTISE[lens],
|
|
417
396
|
stance: ["skeptical-reviewer"],
|
|
418
|
-
approach: ["evidence-first", "
|
|
397
|
+
approach: ["evidence-first", "advisory"],
|
|
419
398
|
domain: ["software-rd"],
|
|
420
399
|
},
|
|
421
400
|
inputs: {
|
|
@@ -462,7 +441,7 @@ function createMergePlan(agents: AgentPlannedInvocation[]): AgentMergePlan {
|
|
|
462
441
|
outputSchema: null,
|
|
463
442
|
dedupeBy: [],
|
|
464
443
|
conflictPolicy: [],
|
|
465
|
-
|
|
444
|
+
advisoryCategories: [],
|
|
466
445
|
};
|
|
467
446
|
if (agents.length === 1)
|
|
468
447
|
return {
|
|
@@ -470,14 +449,14 @@ function createMergePlan(agents: AgentPlannedInvocation[]): AgentMergePlan {
|
|
|
470
449
|
outputSchema: agents[0].profile.output.schema,
|
|
471
450
|
dedupeBy: [],
|
|
472
451
|
conflictPolicy: [],
|
|
473
|
-
|
|
452
|
+
advisoryCategories: [],
|
|
474
453
|
};
|
|
475
454
|
return {
|
|
476
|
-
strategy: "dedupe-preserve-conflicts
|
|
455
|
+
strategy: "dedupe-preserve-conflicts",
|
|
477
456
|
outputSchema: "review-findings-v1",
|
|
478
457
|
dedupeBy: ["category", "path", "line", "title"],
|
|
479
458
|
conflictPolicy: ["preserve dissent", "keep higher severity unless evidence refutes"],
|
|
480
|
-
|
|
459
|
+
advisoryCategories: ["security", "privacy", "release"],
|
|
481
460
|
};
|
|
482
461
|
}
|
|
483
462
|
|
|
@@ -489,7 +468,7 @@ function createLensReason(
|
|
|
489
468
|
return `${lens} lens selected for ${mode ?? "unrouted"} mode${workflowId ? ` and workflow ${workflowId}` : ""}.`;
|
|
490
469
|
}
|
|
491
470
|
|
|
492
|
-
function
|
|
471
|
+
function collectPrivacyBoundaryAdvisories(
|
|
493
472
|
contract: TaskContract,
|
|
494
473
|
lenses: AgentLens[],
|
|
495
474
|
workflowId: string | null,
|
|
@@ -504,9 +483,9 @@ function collectPrivacyBoundaryBlockers(
|
|
|
504
483
|
...contract.scope.requiresUserConfirmation,
|
|
505
484
|
...lenses,
|
|
506
485
|
].join(" ");
|
|
507
|
-
return
|
|
486
|
+
return PRIVACY_ADVISORY_PATTERN.test(text)
|
|
508
487
|
? [
|
|
509
|
-
"Agent planning
|
|
488
|
+
"Agent planning detected privacy/risky context requiring raw data, writes, commands, network, spawning, or memory.",
|
|
510
489
|
]
|
|
511
490
|
: [];
|
|
512
491
|
}
|
|
@@ -539,7 +518,7 @@ function dedupeLenses(lenses: AgentLens[]): AgentLens[] {
|
|
|
539
518
|
}
|
|
540
519
|
|
|
541
520
|
function severityRank(severity: AgentFindingSeverity): number {
|
|
542
|
-
return { info: 0, low: 1, medium: 2, high: 3,
|
|
521
|
+
return { info: 0, low: 1, medium: 2, high: 3, critical: 4 }[severity];
|
|
543
522
|
}
|
|
544
523
|
|
|
545
524
|
function assertString(value: unknown, path: string): void {
|
package/src/config/index.ts
CHANGED
package/src/config/paths.ts
CHANGED
|
@@ -4,6 +4,18 @@ export interface EvoDevPaths {
|
|
|
4
4
|
settingsPath: string;
|
|
5
5
|
registryPath: string;
|
|
6
6
|
stateDir: string;
|
|
7
|
+
logsDir: string;
|
|
8
|
+
knowledgeDir: string;
|
|
9
|
+
knowledgeIndexPath: string;
|
|
10
|
+
evosDir: string;
|
|
11
|
+
evosCasesDir: string;
|
|
12
|
+
evosIndexPath: string;
|
|
13
|
+
roleAgentsDir: string;
|
|
14
|
+
roleAgentsIndexPath: string;
|
|
15
|
+
teamsDir: string;
|
|
16
|
+
teamsIndexPath: string;
|
|
17
|
+
runsDir: string;
|
|
18
|
+
latestRunPath: string;
|
|
7
19
|
installStatePath: string;
|
|
8
20
|
syncStatePath: string;
|
|
9
21
|
}
|
|
@@ -12,6 +24,12 @@ export function resolveEvoDevPaths(homeDir: string = getHomeDir()): EvoDevPaths
|
|
|
12
24
|
const normalizedHome = stripTrailingSlash(homeDir);
|
|
13
25
|
const rootDir = `${normalizedHome}/.evodev`;
|
|
14
26
|
const stateDir = `${rootDir}/state`;
|
|
27
|
+
const logsDir = `${rootDir}/logs`;
|
|
28
|
+
const knowledgeDir = `${rootDir}/knowledge`;
|
|
29
|
+
const evosDir = `${rootDir}/evos`;
|
|
30
|
+
const roleAgentsDir = `${rootDir}/agents/roles`;
|
|
31
|
+
const teamsDir = `${rootDir}/teams`;
|
|
32
|
+
const runsDir = `${rootDir}/runs`;
|
|
15
33
|
|
|
16
34
|
return {
|
|
17
35
|
homeDir: normalizedHome,
|
|
@@ -19,6 +37,18 @@ export function resolveEvoDevPaths(homeDir: string = getHomeDir()): EvoDevPaths
|
|
|
19
37
|
settingsPath: `${rootDir}/settings.json`,
|
|
20
38
|
registryPath: `${rootDir}/registry.json`,
|
|
21
39
|
stateDir,
|
|
40
|
+
logsDir,
|
|
41
|
+
knowledgeDir,
|
|
42
|
+
knowledgeIndexPath: `${knowledgeDir}/index.json`,
|
|
43
|
+
evosDir,
|
|
44
|
+
evosCasesDir: `${evosDir}/cases`,
|
|
45
|
+
evosIndexPath: `${evosDir}/index.json`,
|
|
46
|
+
roleAgentsDir,
|
|
47
|
+
roleAgentsIndexPath: `${roleAgentsDir}/index.json`,
|
|
48
|
+
teamsDir,
|
|
49
|
+
teamsIndexPath: `${teamsDir}/index.json`,
|
|
50
|
+
runsDir,
|
|
51
|
+
latestRunPath: `${runsDir}/latest.json`,
|
|
22
52
|
installStatePath: `${stateDir}/install.json`,
|
|
23
53
|
syncStatePath: `${stateDir}/sync.json`,
|
|
24
54
|
};
|
package/src/config/settings.ts
CHANGED
|
@@ -28,6 +28,7 @@ export interface EvoDevSettings {
|
|
|
28
28
|
lastRunAt: string | null;
|
|
29
29
|
};
|
|
30
30
|
hooks: HookSettings;
|
|
31
|
+
teamRuntime: TeamRuntimeSettings;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export type SettingsInput = Partial<{
|
|
@@ -43,8 +44,16 @@ export type SettingsInput = Partial<{
|
|
|
43
44
|
}>;
|
|
44
45
|
doctor: Partial<EvoDevSettings["doctor"]>;
|
|
45
46
|
hooks: unknown;
|
|
47
|
+
teamRuntime: Partial<TeamRuntimeSettings>;
|
|
46
48
|
}>;
|
|
47
49
|
|
|
50
|
+
export interface TeamRuntimeSettings {
|
|
51
|
+
defaultRuntime: "codex" | "claude";
|
|
52
|
+
defaultModel: string | null;
|
|
53
|
+
defaultThinkingLevel: string | null;
|
|
54
|
+
recordTranscript: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
48
57
|
export function createDefaultSettings(os: string = process.platform): EvoDevSettings {
|
|
49
58
|
return {
|
|
50
59
|
version: 1,
|
|
@@ -73,6 +82,16 @@ export function createDefaultSettings(os: string = process.platform): EvoDevSett
|
|
|
73
82
|
lastRunAt: null,
|
|
74
83
|
},
|
|
75
84
|
hooks: createDefaultHookSettings(),
|
|
85
|
+
teamRuntime: createDefaultTeamRuntimeSettings(),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function createDefaultTeamRuntimeSettings(): TeamRuntimeSettings {
|
|
90
|
+
return {
|
|
91
|
+
defaultRuntime: "codex",
|
|
92
|
+
defaultModel: null,
|
|
93
|
+
defaultThinkingLevel: null,
|
|
94
|
+
recordTranscript: false,
|
|
76
95
|
};
|
|
77
96
|
}
|
|
78
97
|
|
|
@@ -112,6 +131,10 @@ export function mergeSettings(
|
|
|
112
131
|
...existing.doctor,
|
|
113
132
|
},
|
|
114
133
|
hooks: existing.hooks ?? defaults.hooks,
|
|
134
|
+
teamRuntime: {
|
|
135
|
+
...defaults.teamRuntime,
|
|
136
|
+
...existing.teamRuntime,
|
|
137
|
+
},
|
|
115
138
|
};
|
|
116
139
|
|
|
117
140
|
return parseSettings(merged);
|
|
@@ -157,11 +180,40 @@ export function parseSettings(value: unknown): EvoDevSettings {
|
|
|
157
180
|
lastRunAt: expectNullableString(doctor.lastRunAt, "settings.doctor.lastRunAt"),
|
|
158
181
|
},
|
|
159
182
|
hooks: parseHookSettings(root.hooks),
|
|
183
|
+
teamRuntime: parseTeamRuntimeSettings(
|
|
184
|
+
root.teamRuntime ?? createDefaultTeamRuntimeSettings(),
|
|
185
|
+
"settings.teamRuntime",
|
|
186
|
+
),
|
|
160
187
|
};
|
|
161
188
|
|
|
162
189
|
return parsed;
|
|
163
190
|
}
|
|
164
191
|
|
|
192
|
+
function parseTeamRuntimeSettings(value: unknown, path: string): TeamRuntimeSettings {
|
|
193
|
+
const input = expectRecord(value, path);
|
|
194
|
+
const defaults = createDefaultTeamRuntimeSettings();
|
|
195
|
+
const defaultRuntime = input.defaultRuntime ?? defaults.defaultRuntime;
|
|
196
|
+
if (defaultRuntime !== "codex" && defaultRuntime !== "claude") {
|
|
197
|
+
throw new EvoDevConfigError(`Invalid ${path}.defaultRuntime; expected codex or claude`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
defaultRuntime,
|
|
202
|
+
defaultModel:
|
|
203
|
+
input.defaultModel === undefined
|
|
204
|
+
? defaults.defaultModel
|
|
205
|
+
: expectNullableString(input.defaultModel, `${path}.defaultModel`),
|
|
206
|
+
defaultThinkingLevel:
|
|
207
|
+
input.defaultThinkingLevel === undefined
|
|
208
|
+
? defaults.defaultThinkingLevel
|
|
209
|
+
: expectNullableString(input.defaultThinkingLevel, `${path}.defaultThinkingLevel`),
|
|
210
|
+
recordTranscript:
|
|
211
|
+
input.recordTranscript === undefined
|
|
212
|
+
? defaults.recordTranscript
|
|
213
|
+
: expectBoolean(input.recordTranscript, `${path}.recordTranscript`),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
165
217
|
function parsePluginSettings(value: unknown, path: string): PluginSettings {
|
|
166
218
|
const input = expectRecord(value, path);
|
|
167
219
|
const parsed: PluginSettings = {
|