@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/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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evo-dev/core",
|
|
3
|
-
"version": "0.0.1-alpha",
|
|
3
|
+
"version": "0.0.1-alpha.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,18 +10,22 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
12
|
"types": "./src/index.ts",
|
|
13
|
+
"bun": "./src/index.ts",
|
|
13
14
|
"import": "./dist/index.js"
|
|
14
15
|
},
|
|
15
16
|
"./assets": {
|
|
16
17
|
"types": "./src/assets/index.ts",
|
|
18
|
+
"bun": "./src/assets/index.ts",
|
|
17
19
|
"import": "./dist/assets/index.js"
|
|
18
20
|
},
|
|
19
21
|
"./config": {
|
|
20
22
|
"types": "./src/config/index.ts",
|
|
23
|
+
"bun": "./src/config/index.ts",
|
|
21
24
|
"import": "./dist/config/index.js"
|
|
22
25
|
},
|
|
23
26
|
"./plugins": {
|
|
24
27
|
"types": "./src/plugins/index.ts",
|
|
28
|
+
"bun": "./src/plugins/index.ts",
|
|
25
29
|
"import": "./dist/plugins/index.js"
|
|
26
30
|
}
|
|
27
31
|
},
|
package/src/agents/index.ts
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
type ScopedKnowledgeContextPack,
|
|
4
|
+
createScopedKnowledgeContextPack,
|
|
5
|
+
formatScopedKnowledgePromptBlock,
|
|
6
|
+
} from "../evolution/knowledge/index.ts";
|
|
3
7
|
|
|
4
8
|
export type AgentPersistence = "named" | "dynamic";
|
|
5
|
-
export type AgentLens =
|
|
6
|
-
| "review"
|
|
7
|
-
| "qa"
|
|
8
|
-
| "security"
|
|
9
|
-
| "release"
|
|
10
|
-
| "architecture"
|
|
11
|
-
| "migration"
|
|
12
|
-
| "test";
|
|
13
9
|
export type AgentOutputSchemaId =
|
|
14
10
|
| "review-findings-v1"
|
|
15
11
|
| "verification-summary-v1"
|
|
16
12
|
| "design-options-v1";
|
|
17
|
-
export type AgentFindingSeverity = "
|
|
13
|
+
export type AgentFindingSeverity = "critical" | "high" | "medium" | "low" | "info";
|
|
18
14
|
|
|
19
15
|
export interface AgentPermissions {
|
|
20
16
|
canReadMetadata: boolean;
|
|
@@ -56,34 +52,6 @@ export interface AgentProfile {
|
|
|
56
52
|
};
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
export interface AgentPlannedInvocation {
|
|
60
|
-
profile: AgentProfile;
|
|
61
|
-
lens: AgentLens;
|
|
62
|
-
reason: string;
|
|
63
|
-
plannedOnly: true;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface AgentMergePlan {
|
|
67
|
-
strategy: "none" | "single-output" | "dedupe-preserve-conflicts-fail-closed";
|
|
68
|
-
outputSchema: AgentOutputSchemaId | null;
|
|
69
|
-
dedupeBy: string[];
|
|
70
|
-
conflictPolicy: string[];
|
|
71
|
-
failClosedCategories: string[];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface AgentComposeDryRunPlan {
|
|
75
|
-
ok: boolean;
|
|
76
|
-
taskId: string;
|
|
77
|
-
mode: TaskExecutionMode | null;
|
|
78
|
-
workflowId: string | null;
|
|
79
|
-
agents: AgentPlannedInvocation[];
|
|
80
|
-
permissions: AgentPermissions;
|
|
81
|
-
mergePlan: AgentMergePlan;
|
|
82
|
-
warnings: string[];
|
|
83
|
-
blockers: string[];
|
|
84
|
-
rationale: string;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
55
|
export interface AgentContextDryRunBundle {
|
|
88
56
|
profile: AgentProfile;
|
|
89
57
|
context: {
|
|
@@ -93,7 +61,16 @@ export interface AgentContextDryRunBundle {
|
|
|
93
61
|
provenance: string[];
|
|
94
62
|
};
|
|
95
63
|
warnings: string[];
|
|
96
|
-
|
|
64
|
+
advisories: string[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface AgentLoadedContextBundle {
|
|
68
|
+
profile: AgentProfile;
|
|
69
|
+
contextPack: ScopedKnowledgeContextPack | null;
|
|
70
|
+
promptBlock: string | null;
|
|
71
|
+
warnings: string[];
|
|
72
|
+
advisories: string[];
|
|
73
|
+
rawContentStored: false;
|
|
97
74
|
}
|
|
98
75
|
|
|
99
76
|
export interface ReviewFindingOutput {
|
|
@@ -124,17 +101,6 @@ const DEFAULT_AGENT_PERMISSIONS: AgentPermissions = {
|
|
|
124
101
|
};
|
|
125
102
|
const FORBIDDEN_INPUTS = ["rawPrompts", "secrets", "rawCommandLogs", "sourceCorpus"];
|
|
126
103
|
const SAFE_AGENT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
127
|
-
const PRIVACY_BLOCKER_PATTERN =
|
|
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
|
-
const LENS_TO_EXPERTISE: Record<AgentLens, string[]> = {
|
|
130
|
-
review: ["code-review"],
|
|
131
|
-
qa: ["qa", "verification"],
|
|
132
|
-
security: ["security", "privacy"],
|
|
133
|
-
release: ["release", "packaging"],
|
|
134
|
-
architecture: ["architecture"],
|
|
135
|
-
migration: ["migration", "impact-analysis"],
|
|
136
|
-
test: ["testing"],
|
|
137
|
-
};
|
|
138
104
|
|
|
139
105
|
export function createDefaultAgentPermissions(): AgentPermissions {
|
|
140
106
|
return { ...DEFAULT_AGENT_PERMISSIONS };
|
|
@@ -170,16 +136,6 @@ export function parseAgentProfile(value: unknown): AgentProfile {
|
|
|
170
136
|
throw new Error("Agent profile must be metadata-only and must not store raw prompts/source.");
|
|
171
137
|
}
|
|
172
138
|
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
139
|
if (!SAFE_AGENT_ID_PATTERN.test(profile.id)) throw new Error("Agent profile id is unsafe.");
|
|
184
140
|
assertStringArray(profile.traits?.expertise, "profile.traits.expertise");
|
|
185
141
|
assertStringArray(profile.traits?.stance, "profile.traits.stance");
|
|
@@ -188,11 +144,6 @@ export function parseAgentProfile(value: unknown): AgentProfile {
|
|
|
188
144
|
assertStringArray(profile.inputs?.required, "profile.inputs.required");
|
|
189
145
|
assertStringArray(profile.inputs?.optional, "profile.inputs.optional");
|
|
190
146
|
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
147
|
if (!isKnownOutputSchema(profile.output?.schema))
|
|
197
148
|
throw new Error("Agent profile output schema is unsupported.");
|
|
198
149
|
assertStringArray(profile.output.requiredFields, "profile.output.requiredFields");
|
|
@@ -203,73 +154,6 @@ export async function readAgentProfile(path: string): Promise<AgentProfile> {
|
|
|
203
154
|
return parseAgentProfile(JSON.parse(await readFile(path, "utf8")));
|
|
204
155
|
}
|
|
205
156
|
|
|
206
|
-
export function composeAgentDryRun(input: {
|
|
207
|
-
contract: TaskContract;
|
|
208
|
-
workflowId?: string;
|
|
209
|
-
lenses?: AgentLens[];
|
|
210
|
-
}): AgentComposeDryRunPlan {
|
|
211
|
-
const mode = input.contract.route.mode;
|
|
212
|
-
const workflowId = input.workflowId ?? input.contract.route.workflowId;
|
|
213
|
-
const warnings: string[] = [];
|
|
214
|
-
const blockers: string[] = [];
|
|
215
|
-
const permissions = createDefaultAgentPermissions();
|
|
216
|
-
const requestedLenses = dedupeLenses(input.lenses ?? []);
|
|
217
|
-
const privacyBlockers = collectPrivacyBoundaryBlockers(
|
|
218
|
-
input.contract,
|
|
219
|
-
requestedLenses,
|
|
220
|
-
workflowId,
|
|
221
|
-
);
|
|
222
|
-
blockers.push(...privacyBlockers);
|
|
223
|
-
|
|
224
|
-
if (mode === "minimal") {
|
|
225
|
-
return {
|
|
226
|
-
ok: blockers.length === 0,
|
|
227
|
-
taskId: input.contract.taskId,
|
|
228
|
-
mode,
|
|
229
|
-
workflowId,
|
|
230
|
-
agents: [],
|
|
231
|
-
permissions,
|
|
232
|
-
mergePlan: createMergePlan([]),
|
|
233
|
-
warnings,
|
|
234
|
-
blockers,
|
|
235
|
-
rationale: "Minimal mode does not force dynamic agents by default.",
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const selectedLenses = selectLenses(
|
|
240
|
-
mode,
|
|
241
|
-
requestedLenses,
|
|
242
|
-
workflowId,
|
|
243
|
-
input.contract.route.requiredReview,
|
|
244
|
-
);
|
|
245
|
-
const agents = selectedLenses.map((lens) => ({
|
|
246
|
-
profile: createDynamicProfile(lens, input.contract, permissions),
|
|
247
|
-
lens,
|
|
248
|
-
reason: createLensReason(lens, mode, workflowId),
|
|
249
|
-
plannedOnly: true as const,
|
|
250
|
-
}));
|
|
251
|
-
|
|
252
|
-
if (mode === "standard" && agents.length > 1) {
|
|
253
|
-
blockers.push("Standard mode allows at most one optional reviewer/triager in I8 dry-run.");
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return {
|
|
257
|
-
ok: blockers.length === 0,
|
|
258
|
-
taskId: input.contract.taskId,
|
|
259
|
-
mode,
|
|
260
|
-
workflowId,
|
|
261
|
-
agents,
|
|
262
|
-
permissions,
|
|
263
|
-
mergePlan: createMergePlan(agents),
|
|
264
|
-
warnings,
|
|
265
|
-
blockers,
|
|
266
|
-
rationale:
|
|
267
|
-
agents.length === 0
|
|
268
|
-
? "No dynamic agents selected; deterministic verification may be sufficient."
|
|
269
|
-
: `Selected ${agents.length} planned-only agent(s) based on mode/workflow/lenses.`,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
|
|
273
157
|
export function loadAgentContextDryRun(profile: AgentProfile): AgentContextDryRunBundle {
|
|
274
158
|
const parsed = parseAgentProfile(profile);
|
|
275
159
|
return {
|
|
@@ -288,10 +172,52 @@ export function loadAgentContextDryRun(profile: AgentProfile): AgentContextDryRu
|
|
|
288
172
|
provenance: [`agent-profile:${parsed.id}`],
|
|
289
173
|
},
|
|
290
174
|
warnings: [],
|
|
291
|
-
|
|
175
|
+
advisories: [],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export async function loadAgentContext(input: {
|
|
180
|
+
homeDir: string;
|
|
181
|
+
profile: AgentProfile;
|
|
182
|
+
projectKey?: string;
|
|
183
|
+
roleId?: string;
|
|
184
|
+
workflowId?: string;
|
|
185
|
+
paths?: string[];
|
|
186
|
+
queryText?: string;
|
|
187
|
+
limit?: number;
|
|
188
|
+
}): Promise<AgentLoadedContextBundle> {
|
|
189
|
+
const parsed = parseAgentProfile(input.profile);
|
|
190
|
+
const pack = await createScopedKnowledgeContextPack({
|
|
191
|
+
homeDir: input.homeDir,
|
|
192
|
+
projectKey: input.projectKey,
|
|
193
|
+
roleId: input.roleId ?? parsed.id,
|
|
194
|
+
workflowId: input.workflowId,
|
|
195
|
+
paths: input.paths,
|
|
196
|
+
queryText: input.queryText,
|
|
197
|
+
limit: input.limit,
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
profile: parsed,
|
|
201
|
+
contextPack: pack,
|
|
202
|
+
promptBlock: pack === null ? null : formatScopedKnowledgePromptBlock(pack),
|
|
203
|
+
warnings: pack?.warnings ?? [],
|
|
204
|
+
advisories: [],
|
|
205
|
+
rawContentStored: false,
|
|
292
206
|
};
|
|
293
207
|
}
|
|
294
208
|
|
|
209
|
+
export function formatAgentLoadedContextPromptBlock(bundle: AgentLoadedContextBundle): string {
|
|
210
|
+
if (bundle.promptBlock !== null) return bundle.promptBlock;
|
|
211
|
+
return [
|
|
212
|
+
"EvoDev Scoped Knowledge Context",
|
|
213
|
+
`Agent: ${bundle.profile.id}`,
|
|
214
|
+
"Raw content stored: false",
|
|
215
|
+
"",
|
|
216
|
+
"Applicable items:",
|
|
217
|
+
"- none",
|
|
218
|
+
].join("\n");
|
|
219
|
+
}
|
|
220
|
+
|
|
295
221
|
export function validateAgentOutput(
|
|
296
222
|
schema: AgentOutputSchemaId,
|
|
297
223
|
output: unknown,
|
|
@@ -341,47 +267,6 @@ export function mergeReviewFindings(outputs: ReviewFindingOutput[]): {
|
|
|
341
267
|
return { acceptedFindings: [...byKey.values()], unresolvedConflicts: conflicts };
|
|
342
268
|
}
|
|
343
269
|
|
|
344
|
-
export function formatAgentComposeDryRun(plan: AgentComposeDryRunPlan): string {
|
|
345
|
-
return [
|
|
346
|
-
"EvoDev agent compose dry-run",
|
|
347
|
-
"",
|
|
348
|
-
`Task: ${plan.taskId}`,
|
|
349
|
-
`Mode: ${plan.mode ?? "not routed"}`,
|
|
350
|
-
`Workflow: ${plan.workflowId ?? "none"}`,
|
|
351
|
-
`Rationale: ${plan.rationale}`,
|
|
352
|
-
"No-write/no-spawn: true",
|
|
353
|
-
"Privacy: local-private, metadata-only, raw prompts/source/secrets/logs forbidden",
|
|
354
|
-
"Agents:",
|
|
355
|
-
...(plan.agents.length === 0
|
|
356
|
-
? [" - none"]
|
|
357
|
-
: plan.agents.map(
|
|
358
|
-
(agent) =>
|
|
359
|
-
` - ${agent.profile.id} [${agent.lens}] traits=${agent.profile.traits.expertise.join(",")} schema=${agent.profile.output.schema} plannedOnly=${agent.plannedOnly}`,
|
|
360
|
-
)),
|
|
361
|
-
"Inputs:",
|
|
362
|
-
...(plan.agents.length === 0
|
|
363
|
-
? [" - none"]
|
|
364
|
-
: [
|
|
365
|
-
` - required: ${plan.agents[0].profile.inputs.required.join(",")}`,
|
|
366
|
-
` - optional: ${plan.agents[0].profile.inputs.optional.join(",")}`,
|
|
367
|
-
` - forbidden: ${plan.agents[0].profile.inputs.forbidden.join(",")}`,
|
|
368
|
-
]),
|
|
369
|
-
"Permissions:",
|
|
370
|
-
...Object.entries(plan.permissions).map(([key, value]) => ` - ${key}: ${value}`),
|
|
371
|
-
"Merge plan:",
|
|
372
|
-
` - strategy: ${plan.mergePlan.strategy}`,
|
|
373
|
-
` - outputSchema: ${plan.mergePlan.outputSchema ?? "none"}`,
|
|
374
|
-
"Warnings:",
|
|
375
|
-
...(plan.warnings.length === 0
|
|
376
|
-
? [" - none"]
|
|
377
|
-
: plan.warnings.map((warning) => ` - ${warning}`)),
|
|
378
|
-
"Blockers:",
|
|
379
|
-
...(plan.blockers.length === 0
|
|
380
|
-
? [" - none"]
|
|
381
|
-
: plan.blockers.map((blocker) => ` - ${blocker}`)),
|
|
382
|
-
].join("\n");
|
|
383
|
-
}
|
|
384
|
-
|
|
385
270
|
export function formatAgentContextDryRun(bundle: AgentContextDryRunBundle): string {
|
|
386
271
|
return [
|
|
387
272
|
"EvoDev agent load-context dry-run",
|
|
@@ -394,123 +279,13 @@ export function formatAgentContextDryRun(bundle: AgentContextDryRunBundle): stri
|
|
|
394
279
|
...bundle.context.forbiddenSections.map((section) => ` - ${section}`),
|
|
395
280
|
"Permissions:",
|
|
396
281
|
...Object.entries(bundle.profile.permissions).map(([key, value]) => ` - ${key}: ${value}`),
|
|
397
|
-
"
|
|
398
|
-
...(bundle.
|
|
282
|
+
"Advisories:",
|
|
283
|
+
...(bundle.advisories.length === 0
|
|
399
284
|
? [" - none"]
|
|
400
|
-
: bundle.
|
|
285
|
+
: bundle.advisories.map((advisory) => ` - ${advisory}`)),
|
|
401
286
|
].join("\n");
|
|
402
287
|
}
|
|
403
288
|
|
|
404
|
-
function createDynamicProfile(
|
|
405
|
-
lens: AgentLens,
|
|
406
|
-
contract: TaskContract,
|
|
407
|
-
permissions: AgentPermissions,
|
|
408
|
-
): AgentProfile {
|
|
409
|
-
return {
|
|
410
|
-
version: 1,
|
|
411
|
-
id: `dynamic-${lens}-${contract.taskId}`.slice(0, 100),
|
|
412
|
-
name: `Dynamic ${lens} reviewer`,
|
|
413
|
-
persistence: "dynamic",
|
|
414
|
-
description: `Task-scoped ${lens} profile for metadata-only dry-run planning.`,
|
|
415
|
-
traits: {
|
|
416
|
-
expertise: LENS_TO_EXPERTISE[lens],
|
|
417
|
-
stance: ["skeptical-reviewer"],
|
|
418
|
-
approach: ["evidence-first", "fail-closed"],
|
|
419
|
-
domain: ["software-rd"],
|
|
420
|
-
},
|
|
421
|
-
inputs: {
|
|
422
|
-
required: ["taskContract", "scope", "evidenceSummary"],
|
|
423
|
-
optional: ["workflowPlan"],
|
|
424
|
-
forbidden: FORBIDDEN_INPUTS,
|
|
425
|
-
},
|
|
426
|
-
permissions,
|
|
427
|
-
output: {
|
|
428
|
-
schema: "review-findings-v1",
|
|
429
|
-
requiredFields: ["summary", "findings", "confidence", "evidenceRefs"],
|
|
430
|
-
},
|
|
431
|
-
privacy: {
|
|
432
|
-
classification: "local-private",
|
|
433
|
-
metadataOnly: true,
|
|
434
|
-
rawPromptStored: false,
|
|
435
|
-
sourceContentStored: false,
|
|
436
|
-
},
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
function selectLenses(
|
|
441
|
-
mode: TaskExecutionMode | null,
|
|
442
|
-
requested: AgentLens[],
|
|
443
|
-
workflowId: string | null,
|
|
444
|
-
requiredReview: string[],
|
|
445
|
-
): AgentLens[] {
|
|
446
|
-
if (requested.length > 0) return mode === "standard" ? requested.slice(0, 1) : requested;
|
|
447
|
-
if (mode === "standard") return requiredReview.length > 0 ? ["review"] : [];
|
|
448
|
-
if (mode === "rigorous") {
|
|
449
|
-
if (workflowId?.includes("security")) return ["security", "review"];
|
|
450
|
-
if (workflowId?.includes("release")) return ["release", "security"];
|
|
451
|
-
if (workflowId?.includes("migration")) return ["migration", "architecture"];
|
|
452
|
-
if (workflowId?.includes("architecture")) return ["architecture", "review"];
|
|
453
|
-
return requiredReview.length > 0 ? ["review", "qa"] : [];
|
|
454
|
-
}
|
|
455
|
-
return [];
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
function createMergePlan(agents: AgentPlannedInvocation[]): AgentMergePlan {
|
|
459
|
-
if (agents.length === 0)
|
|
460
|
-
return {
|
|
461
|
-
strategy: "none",
|
|
462
|
-
outputSchema: null,
|
|
463
|
-
dedupeBy: [],
|
|
464
|
-
conflictPolicy: [],
|
|
465
|
-
failClosedCategories: [],
|
|
466
|
-
};
|
|
467
|
-
if (agents.length === 1)
|
|
468
|
-
return {
|
|
469
|
-
strategy: "single-output",
|
|
470
|
-
outputSchema: agents[0].profile.output.schema,
|
|
471
|
-
dedupeBy: [],
|
|
472
|
-
conflictPolicy: [],
|
|
473
|
-
failClosedCategories: [],
|
|
474
|
-
};
|
|
475
|
-
return {
|
|
476
|
-
strategy: "dedupe-preserve-conflicts-fail-closed",
|
|
477
|
-
outputSchema: "review-findings-v1",
|
|
478
|
-
dedupeBy: ["category", "path", "line", "title"],
|
|
479
|
-
conflictPolicy: ["preserve dissent", "keep higher severity unless evidence refutes"],
|
|
480
|
-
failClosedCategories: ["security", "privacy", "release"],
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
function createLensReason(
|
|
485
|
-
lens: AgentLens,
|
|
486
|
-
mode: TaskExecutionMode | null,
|
|
487
|
-
workflowId: string | null,
|
|
488
|
-
): string {
|
|
489
|
-
return `${lens} lens selected for ${mode ?? "unrouted"} mode${workflowId ? ` and workflow ${workflowId}` : ""}.`;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
function collectPrivacyBoundaryBlockers(
|
|
493
|
-
contract: TaskContract,
|
|
494
|
-
lenses: AgentLens[],
|
|
495
|
-
workflowId: string | null,
|
|
496
|
-
): string[] {
|
|
497
|
-
const text = [
|
|
498
|
-
contract.source.summary,
|
|
499
|
-
contract.currentState.summary,
|
|
500
|
-
contract.targetState.summary,
|
|
501
|
-
contract.route.rationale,
|
|
502
|
-
workflowId ?? "",
|
|
503
|
-
...contract.scope.allowedOperations,
|
|
504
|
-
...contract.scope.requiresUserConfirmation,
|
|
505
|
-
...lenses,
|
|
506
|
-
].join(" ");
|
|
507
|
-
return PRIVACY_BLOCKER_PATTERN.test(text)
|
|
508
|
-
? [
|
|
509
|
-
"Agent planning refuses privacy/risky context requiring raw data, writes, commands, network, spawning, or memory.",
|
|
510
|
-
]
|
|
511
|
-
: [];
|
|
512
|
-
}
|
|
513
|
-
|
|
514
289
|
function validateRequiredObject(
|
|
515
290
|
output: unknown,
|
|
516
291
|
fields: string[],
|
|
@@ -534,12 +309,8 @@ function isKnownOutputSchema(value: unknown): value is AgentOutputSchemaId {
|
|
|
534
309
|
);
|
|
535
310
|
}
|
|
536
311
|
|
|
537
|
-
function dedupeLenses(lenses: AgentLens[]): AgentLens[] {
|
|
538
|
-
return [...new Set(lenses)];
|
|
539
|
-
}
|
|
540
|
-
|
|
541
312
|
function severityRank(severity: AgentFindingSeverity): number {
|
|
542
|
-
return { info: 0, low: 1, medium: 2, high: 3,
|
|
313
|
+
return { info: 0, low: 1, medium: 2, high: 3, critical: 4 }[severity];
|
|
543
314
|
}
|
|
544
315
|
|
|
545
316
|
function assertString(value: unknown, path: string): void {
|