@evo-dev/core 0.0.1-alpha → 0.0.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +249 -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/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 +968 -39
- package/dist/index.js +10914 -1476
- package/dist/plugins/index.js +32 -32
- package/package.json +5 -1
- package/src/agents/index.ts +84 -49
- package/src/code-agent-traces/index.ts +521 -0
- package/src/config/index.ts +5 -0
- package/src/config/paths.ts +30 -0
- package/src/config/settings.ts +130 -0
- package/src/config/store.ts +152 -0
- package/src/daemon/index.ts +465 -3
- package/src/evolution/index.ts +2827 -0
- package/src/hooks/index.ts +543 -247
- package/src/index.ts +6 -0
- package/src/knowledge/index.ts +4784 -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 +798 -0
- package/src/sync/orchestrator.ts +6 -0
- package/src/task/index.ts +3 -3
- package/src/team/index.ts +3069 -0
- package/src/team/mcp.ts +405 -0
- package/src/team/prompts.ts +141 -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evo-dev/core",
|
|
3
|
-
"version": "0.0.1-alpha",
|
|
3
|
+
"version": "0.0.1-alpha.2",
|
|
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,4 +1,9 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
|
+
import {
|
|
3
|
+
type ScopedKnowledgeContextPack,
|
|
4
|
+
createScopedKnowledgeContextPack,
|
|
5
|
+
formatScopedKnowledgePromptBlock,
|
|
6
|
+
} from "../knowledge/index.ts";
|
|
2
7
|
import type { TaskContract, TaskExecutionMode } from "../task/index.ts";
|
|
3
8
|
|
|
4
9
|
export type AgentPersistence = "named" | "dynamic";
|
|
@@ -14,7 +19,7 @@ export type AgentOutputSchemaId =
|
|
|
14
19
|
| "review-findings-v1"
|
|
15
20
|
| "verification-summary-v1"
|
|
16
21
|
| "design-options-v1";
|
|
17
|
-
export type AgentFindingSeverity = "
|
|
22
|
+
export type AgentFindingSeverity = "critical" | "high" | "medium" | "low" | "info";
|
|
18
23
|
|
|
19
24
|
export interface AgentPermissions {
|
|
20
25
|
canReadMetadata: boolean;
|
|
@@ -64,11 +69,11 @@ export interface AgentPlannedInvocation {
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
export interface AgentMergePlan {
|
|
67
|
-
strategy: "none" | "single-output" | "dedupe-preserve-conflicts
|
|
72
|
+
strategy: "none" | "single-output" | "dedupe-preserve-conflicts";
|
|
68
73
|
outputSchema: AgentOutputSchemaId | null;
|
|
69
74
|
dedupeBy: string[];
|
|
70
75
|
conflictPolicy: string[];
|
|
71
|
-
|
|
76
|
+
advisoryCategories: string[];
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
export interface AgentComposeDryRunPlan {
|
|
@@ -80,7 +85,7 @@ export interface AgentComposeDryRunPlan {
|
|
|
80
85
|
permissions: AgentPermissions;
|
|
81
86
|
mergePlan: AgentMergePlan;
|
|
82
87
|
warnings: string[];
|
|
83
|
-
|
|
88
|
+
advisories: string[];
|
|
84
89
|
rationale: string;
|
|
85
90
|
}
|
|
86
91
|
|
|
@@ -93,7 +98,16 @@ export interface AgentContextDryRunBundle {
|
|
|
93
98
|
provenance: string[];
|
|
94
99
|
};
|
|
95
100
|
warnings: string[];
|
|
96
|
-
|
|
101
|
+
advisories: string[];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface AgentLoadedContextBundle {
|
|
105
|
+
profile: AgentProfile;
|
|
106
|
+
contextPack: ScopedKnowledgeContextPack | null;
|
|
107
|
+
promptBlock: string | null;
|
|
108
|
+
warnings: string[];
|
|
109
|
+
advisories: string[];
|
|
110
|
+
rawContentStored: false;
|
|
97
111
|
}
|
|
98
112
|
|
|
99
113
|
export interface ReviewFindingOutput {
|
|
@@ -124,7 +138,7 @@ const DEFAULT_AGENT_PERMISSIONS: AgentPermissions = {
|
|
|
124
138
|
};
|
|
125
139
|
const FORBIDDEN_INPUTS = ["rawPrompts", "secrets", "rawCommandLogs", "sourceCorpus"];
|
|
126
140
|
const SAFE_AGENT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
127
|
-
const
|
|
141
|
+
const PRIVACY_ADVISORY_PATTERN =
|
|
128
142
|
/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
143
|
const LENS_TO_EXPERTISE: Record<AgentLens, string[]> = {
|
|
130
144
|
review: ["code-review"],
|
|
@@ -170,16 +184,6 @@ export function parseAgentProfile(value: unknown): AgentProfile {
|
|
|
170
184
|
throw new Error("Agent profile must be metadata-only and must not store raw prompts/source.");
|
|
171
185
|
}
|
|
172
186
|
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
187
|
if (!SAFE_AGENT_ID_PATTERN.test(profile.id)) throw new Error("Agent profile id is unsafe.");
|
|
184
188
|
assertStringArray(profile.traits?.expertise, "profile.traits.expertise");
|
|
185
189
|
assertStringArray(profile.traits?.stance, "profile.traits.stance");
|
|
@@ -188,11 +192,6 @@ export function parseAgentProfile(value: unknown): AgentProfile {
|
|
|
188
192
|
assertStringArray(profile.inputs?.required, "profile.inputs.required");
|
|
189
193
|
assertStringArray(profile.inputs?.optional, "profile.inputs.optional");
|
|
190
194
|
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
195
|
if (!isKnownOutputSchema(profile.output?.schema))
|
|
197
196
|
throw new Error("Agent profile output schema is unsupported.");
|
|
198
197
|
assertStringArray(profile.output.requiredFields, "profile.output.requiredFields");
|
|
@@ -211,19 +210,13 @@ export function composeAgentDryRun(input: {
|
|
|
211
210
|
const mode = input.contract.route.mode;
|
|
212
211
|
const workflowId = input.workflowId ?? input.contract.route.workflowId;
|
|
213
212
|
const warnings: string[] = [];
|
|
214
|
-
const blockers: string[] = [];
|
|
215
213
|
const permissions = createDefaultAgentPermissions();
|
|
216
214
|
const requestedLenses = dedupeLenses(input.lenses ?? []);
|
|
217
|
-
const
|
|
218
|
-
input.contract,
|
|
219
|
-
requestedLenses,
|
|
220
|
-
workflowId,
|
|
221
|
-
);
|
|
222
|
-
blockers.push(...privacyBlockers);
|
|
215
|
+
const advisories = collectPrivacyBoundaryAdvisories(input.contract, requestedLenses, workflowId);
|
|
223
216
|
|
|
224
217
|
if (mode === "minimal") {
|
|
225
218
|
return {
|
|
226
|
-
ok:
|
|
219
|
+
ok: advisories.length === 0,
|
|
227
220
|
taskId: input.contract.taskId,
|
|
228
221
|
mode,
|
|
229
222
|
workflowId,
|
|
@@ -231,7 +224,7 @@ export function composeAgentDryRun(input: {
|
|
|
231
224
|
permissions,
|
|
232
225
|
mergePlan: createMergePlan([]),
|
|
233
226
|
warnings,
|
|
234
|
-
|
|
227
|
+
advisories,
|
|
235
228
|
rationale: "Minimal mode does not force dynamic agents by default.",
|
|
236
229
|
};
|
|
237
230
|
}
|
|
@@ -250,11 +243,11 @@ export function composeAgentDryRun(input: {
|
|
|
250
243
|
}));
|
|
251
244
|
|
|
252
245
|
if (mode === "standard" && agents.length > 1) {
|
|
253
|
-
|
|
246
|
+
warnings.push("Standard mode advisory selected more than one reviewer/triager.");
|
|
254
247
|
}
|
|
255
248
|
|
|
256
249
|
return {
|
|
257
|
-
ok:
|
|
250
|
+
ok: advisories.length === 0,
|
|
258
251
|
taskId: input.contract.taskId,
|
|
259
252
|
mode,
|
|
260
253
|
workflowId,
|
|
@@ -262,7 +255,7 @@ export function composeAgentDryRun(input: {
|
|
|
262
255
|
permissions,
|
|
263
256
|
mergePlan: createMergePlan(agents),
|
|
264
257
|
warnings,
|
|
265
|
-
|
|
258
|
+
advisories,
|
|
266
259
|
rationale:
|
|
267
260
|
agents.length === 0
|
|
268
261
|
? "No dynamic agents selected; deterministic verification may be sufficient."
|
|
@@ -288,10 +281,52 @@ export function loadAgentContextDryRun(profile: AgentProfile): AgentContextDryRu
|
|
|
288
281
|
provenance: [`agent-profile:${parsed.id}`],
|
|
289
282
|
},
|
|
290
283
|
warnings: [],
|
|
291
|
-
|
|
284
|
+
advisories: [],
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export async function loadAgentContext(input: {
|
|
289
|
+
homeDir: string;
|
|
290
|
+
profile: AgentProfile;
|
|
291
|
+
projectKey?: string;
|
|
292
|
+
roleId?: string;
|
|
293
|
+
workflowId?: string;
|
|
294
|
+
paths?: string[];
|
|
295
|
+
queryText?: string;
|
|
296
|
+
limit?: number;
|
|
297
|
+
}): Promise<AgentLoadedContextBundle> {
|
|
298
|
+
const parsed = parseAgentProfile(input.profile);
|
|
299
|
+
const pack = await createScopedKnowledgeContextPack({
|
|
300
|
+
homeDir: input.homeDir,
|
|
301
|
+
projectKey: input.projectKey,
|
|
302
|
+
roleId: input.roleId ?? parsed.id,
|
|
303
|
+
workflowId: input.workflowId,
|
|
304
|
+
paths: input.paths,
|
|
305
|
+
queryText: input.queryText,
|
|
306
|
+
limit: input.limit,
|
|
307
|
+
});
|
|
308
|
+
return {
|
|
309
|
+
profile: parsed,
|
|
310
|
+
contextPack: pack,
|
|
311
|
+
promptBlock: pack === null ? null : formatScopedKnowledgePromptBlock(pack),
|
|
312
|
+
warnings: pack?.warnings ?? [],
|
|
313
|
+
advisories: [],
|
|
314
|
+
rawContentStored: false,
|
|
292
315
|
};
|
|
293
316
|
}
|
|
294
317
|
|
|
318
|
+
export function formatAgentLoadedContextPromptBlock(bundle: AgentLoadedContextBundle): string {
|
|
319
|
+
if (bundle.promptBlock !== null) return bundle.promptBlock;
|
|
320
|
+
return [
|
|
321
|
+
"EvoDev Scoped Knowledge Context",
|
|
322
|
+
`Agent: ${bundle.profile.id}`,
|
|
323
|
+
"Raw content stored: false",
|
|
324
|
+
"",
|
|
325
|
+
"Applicable items:",
|
|
326
|
+
"- none",
|
|
327
|
+
].join("\n");
|
|
328
|
+
}
|
|
329
|
+
|
|
295
330
|
export function validateAgentOutput(
|
|
296
331
|
schema: AgentOutputSchemaId,
|
|
297
332
|
output: unknown,
|
|
@@ -375,10 +410,10 @@ export function formatAgentComposeDryRun(plan: AgentComposeDryRunPlan): string {
|
|
|
375
410
|
...(plan.warnings.length === 0
|
|
376
411
|
? [" - none"]
|
|
377
412
|
: plan.warnings.map((warning) => ` - ${warning}`)),
|
|
378
|
-
"
|
|
379
|
-
...(plan.
|
|
413
|
+
"Advisories:",
|
|
414
|
+
...(plan.advisories.length === 0
|
|
380
415
|
? [" - none"]
|
|
381
|
-
: plan.
|
|
416
|
+
: plan.advisories.map((advisory) => ` - ${advisory}`)),
|
|
382
417
|
].join("\n");
|
|
383
418
|
}
|
|
384
419
|
|
|
@@ -394,10 +429,10 @@ export function formatAgentContextDryRun(bundle: AgentContextDryRunBundle): stri
|
|
|
394
429
|
...bundle.context.forbiddenSections.map((section) => ` - ${section}`),
|
|
395
430
|
"Permissions:",
|
|
396
431
|
...Object.entries(bundle.profile.permissions).map(([key, value]) => ` - ${key}: ${value}`),
|
|
397
|
-
"
|
|
398
|
-
...(bundle.
|
|
432
|
+
"Advisories:",
|
|
433
|
+
...(bundle.advisories.length === 0
|
|
399
434
|
? [" - none"]
|
|
400
|
-
: bundle.
|
|
435
|
+
: bundle.advisories.map((advisory) => ` - ${advisory}`)),
|
|
401
436
|
].join("\n");
|
|
402
437
|
}
|
|
403
438
|
|
|
@@ -415,7 +450,7 @@ function createDynamicProfile(
|
|
|
415
450
|
traits: {
|
|
416
451
|
expertise: LENS_TO_EXPERTISE[lens],
|
|
417
452
|
stance: ["skeptical-reviewer"],
|
|
418
|
-
approach: ["evidence-first", "
|
|
453
|
+
approach: ["evidence-first", "advisory"],
|
|
419
454
|
domain: ["software-rd"],
|
|
420
455
|
},
|
|
421
456
|
inputs: {
|
|
@@ -462,7 +497,7 @@ function createMergePlan(agents: AgentPlannedInvocation[]): AgentMergePlan {
|
|
|
462
497
|
outputSchema: null,
|
|
463
498
|
dedupeBy: [],
|
|
464
499
|
conflictPolicy: [],
|
|
465
|
-
|
|
500
|
+
advisoryCategories: [],
|
|
466
501
|
};
|
|
467
502
|
if (agents.length === 1)
|
|
468
503
|
return {
|
|
@@ -470,14 +505,14 @@ function createMergePlan(agents: AgentPlannedInvocation[]): AgentMergePlan {
|
|
|
470
505
|
outputSchema: agents[0].profile.output.schema,
|
|
471
506
|
dedupeBy: [],
|
|
472
507
|
conflictPolicy: [],
|
|
473
|
-
|
|
508
|
+
advisoryCategories: [],
|
|
474
509
|
};
|
|
475
510
|
return {
|
|
476
|
-
strategy: "dedupe-preserve-conflicts
|
|
511
|
+
strategy: "dedupe-preserve-conflicts",
|
|
477
512
|
outputSchema: "review-findings-v1",
|
|
478
513
|
dedupeBy: ["category", "path", "line", "title"],
|
|
479
514
|
conflictPolicy: ["preserve dissent", "keep higher severity unless evidence refutes"],
|
|
480
|
-
|
|
515
|
+
advisoryCategories: ["security", "privacy", "release"],
|
|
481
516
|
};
|
|
482
517
|
}
|
|
483
518
|
|
|
@@ -489,7 +524,7 @@ function createLensReason(
|
|
|
489
524
|
return `${lens} lens selected for ${mode ?? "unrouted"} mode${workflowId ? ` and workflow ${workflowId}` : ""}.`;
|
|
490
525
|
}
|
|
491
526
|
|
|
492
|
-
function
|
|
527
|
+
function collectPrivacyBoundaryAdvisories(
|
|
493
528
|
contract: TaskContract,
|
|
494
529
|
lenses: AgentLens[],
|
|
495
530
|
workflowId: string | null,
|
|
@@ -504,9 +539,9 @@ function collectPrivacyBoundaryBlockers(
|
|
|
504
539
|
...contract.scope.requiresUserConfirmation,
|
|
505
540
|
...lenses,
|
|
506
541
|
].join(" ");
|
|
507
|
-
return
|
|
542
|
+
return PRIVACY_ADVISORY_PATTERN.test(text)
|
|
508
543
|
? [
|
|
509
|
-
"Agent planning
|
|
544
|
+
"Agent planning detected privacy/risky context requiring raw data, writes, commands, network, spawning, or memory.",
|
|
510
545
|
]
|
|
511
546
|
: [];
|
|
512
547
|
}
|
|
@@ -539,7 +574,7 @@ function dedupeLenses(lenses: AgentLens[]): AgentLens[] {
|
|
|
539
574
|
}
|
|
540
575
|
|
|
541
576
|
function severityRank(severity: AgentFindingSeverity): number {
|
|
542
|
-
return { info: 0, low: 1, medium: 2, high: 3,
|
|
577
|
+
return { info: 0, low: 1, medium: 2, high: 3, critical: 4 }[severity];
|
|
543
578
|
}
|
|
544
579
|
|
|
545
580
|
function assertString(value: unknown, path: string): void {
|