@evo-dev/evodev 0.0.1-alpha.2 → 0.0.1-alpha.20
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/dist/.claude-plugin/marketplace.json +2 -2
- package/dist/assets/skills/coding/knowledge-distillation/SKILL.md +5 -3
- package/dist/assets/team/agents/code-reviewer.md +48 -0
- package/dist/assets/team/agents/docs-maintainer.md +51 -0
- package/dist/assets/team/agents/implementation-engineer.md +51 -0
- package/dist/assets/team/agents/product-scope-analyst.md +58 -0
- package/dist/assets/team/agents/release-engineer.md +55 -0
- package/dist/assets/team/agents/security-boundary-reviewer.md +50 -0
- package/dist/assets/team/agents/solution-architect.md +51 -0
- package/dist/assets/team/agents/verification-engineer.md +51 -0
- package/dist/assets/team/team.md +102 -0
- package/dist/index.js +41238 -20427
- package/dist/plugins/evodev/.claude-plugin/plugin.json +1 -1
- package/dist/plugins/evodev/.codex-plugin/plugin.json +1 -1
- package/dist/plugins/evodev/hooks/codex.ts +69 -2
- package/dist/plugins/evodev/hooks/hooks.ts +55 -2
- package/dist/plugins/evodev/hooks/plugin.ts +78 -3
- package/dist/plugins/evodev/hooks/runtime.ts +8 -1
- package/dist/plugins/evodev/package.json +1 -1
- package/dist/plugins/evodev/skills/knowledge-distillation/SKILL.md +5 -3
- package/dist/ui/app.js +9 -0
- package/dist/ui/styles.css +2 -0
- package/package.json +12 -3
- package/dist/.agents/skills/grilling/SKILL.md +0 -10
- package/dist/evodev +0 -11
|
@@ -54,6 +54,7 @@ export interface CodexPluginOptions {
|
|
|
54
54
|
pluginSelector?: string;
|
|
55
55
|
pluginMarketplaceSource?: string;
|
|
56
56
|
pluginMarketplaceFallbackSource?: string;
|
|
57
|
+
pluginVersion?: string;
|
|
57
58
|
paths?: CodexPaths;
|
|
58
59
|
syncFileSystem?: CodexSyncFileSystem;
|
|
59
60
|
}
|
|
@@ -195,6 +196,7 @@ async function installCodexPlugin(
|
|
|
195
196
|
| "pluginSelector"
|
|
196
197
|
| "pluginMarketplaceSource"
|
|
197
198
|
| "pluginMarketplaceFallbackSource"
|
|
199
|
+
| "pluginVersion"
|
|
198
200
|
| "paths"
|
|
199
201
|
>,
|
|
200
202
|
): Promise<PluginInstallResult> {
|
|
@@ -202,8 +204,46 @@ async function installCodexPlugin(
|
|
|
202
204
|
const selector = options.pluginSelector ?? "evodev@evodev";
|
|
203
205
|
const args = ["plugin", "add", selector];
|
|
204
206
|
const runner = options.commandRunner ?? new NodeCodexCommandRunner();
|
|
207
|
+
const installedPlugin =
|
|
208
|
+
input.force === true || options.pluginVersion === undefined
|
|
209
|
+
? null
|
|
210
|
+
: await readInstalledCodexPlugin(runner, selector);
|
|
211
|
+
let needsRepair = false;
|
|
212
|
+
|
|
213
|
+
if (
|
|
214
|
+
installedPlugin !== null &&
|
|
215
|
+
installedPlugin.version === options.pluginVersion &&
|
|
216
|
+
installedPlugin.enabled
|
|
217
|
+
) {
|
|
218
|
+
try {
|
|
219
|
+
const hydration = await hydrateCodexWorkspaceCoreDependency({
|
|
220
|
+
paths: options.paths,
|
|
221
|
+
selector,
|
|
222
|
+
});
|
|
223
|
+
if (hydration.warnings.length === 0 && hydration.errors.length === 0) {
|
|
224
|
+
return createPluginInstallResult(
|
|
225
|
+
input.targetPlugin,
|
|
226
|
+
"already-installed",
|
|
227
|
+
command,
|
|
228
|
+
args,
|
|
229
|
+
`Codex plugin ${selector} already matches EvoDev ${options.pluginVersion}; skipped marketplace refresh.`,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
} catch {
|
|
233
|
+
// Fall through to the normal repair path, which returns a structured install failure.
|
|
234
|
+
}
|
|
235
|
+
needsRepair = true;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const effectiveInput =
|
|
239
|
+
input.force === true ||
|
|
240
|
+
needsRepair ||
|
|
241
|
+
(installedPlugin !== null &&
|
|
242
|
+
(installedPlugin.version !== options.pluginVersion || !installedPlugin.enabled))
|
|
243
|
+
? { ...input, force: true }
|
|
244
|
+
: input;
|
|
205
245
|
const primaryResult = await installCodexPluginOnce({
|
|
206
|
-
input,
|
|
246
|
+
input: effectiveInput,
|
|
207
247
|
command,
|
|
208
248
|
selector,
|
|
209
249
|
args,
|
|
@@ -224,7 +264,7 @@ async function installCodexPlugin(
|
|
|
224
264
|
}
|
|
225
265
|
|
|
226
266
|
const fallbackResult = await installCodexPluginOnce({
|
|
227
|
-
input,
|
|
267
|
+
input: effectiveInput,
|
|
228
268
|
command,
|
|
229
269
|
selector,
|
|
230
270
|
args,
|
|
@@ -243,6 +283,33 @@ async function installCodexPlugin(
|
|
|
243
283
|
};
|
|
244
284
|
}
|
|
245
285
|
|
|
286
|
+
interface InstalledCodexPlugin {
|
|
287
|
+
version: string | null;
|
|
288
|
+
enabled: boolean;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function readInstalledCodexPlugin(
|
|
292
|
+
runner: CodexCommandRunner,
|
|
293
|
+
selector: string,
|
|
294
|
+
): Promise<InstalledCodexPlugin | null> {
|
|
295
|
+
try {
|
|
296
|
+
const result = await runner.run("codex", ["plugin", "list", "--json"]);
|
|
297
|
+
if (result.exitCode !== 0 || result.stdout === undefined) return null;
|
|
298
|
+
const parsed = JSON.parse(result.stdout) as unknown;
|
|
299
|
+
const plugins = isRecord(parsed) && Array.isArray(parsed.installed) ? parsed.installed : [];
|
|
300
|
+
const plugin = plugins.find(
|
|
301
|
+
(candidate) => isRecord(candidate) && candidate.pluginId === selector,
|
|
302
|
+
);
|
|
303
|
+
if (!isRecord(plugin)) return null;
|
|
304
|
+
return {
|
|
305
|
+
version: typeof plugin.version === "string" ? plugin.version : null,
|
|
306
|
+
enabled: plugin.enabled !== false,
|
|
307
|
+
};
|
|
308
|
+
} catch {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
246
313
|
async function installCodexPluginOnce(input: {
|
|
247
314
|
input: PluginInstallInput;
|
|
248
315
|
command: string;
|
|
@@ -158,7 +158,7 @@ export function planClaudeHookInstallDryRun(
|
|
|
158
158
|
action: "merge-with-backup",
|
|
159
159
|
targetPath: paths.settingsPath,
|
|
160
160
|
reason:
|
|
161
|
-
"would
|
|
161
|
+
"would reconcile EvoDev-managed user-level hook entries with Claude plugin ownership without touching user-owned hooks",
|
|
162
162
|
},
|
|
163
163
|
],
|
|
164
164
|
warnings: ["Project .claude, .codex, CLAUDE.md, and AGENTS.md are not targeted."],
|
|
@@ -191,12 +191,34 @@ export async function installClaudeHooks(input: {
|
|
|
191
191
|
paths?: ClaudePaths;
|
|
192
192
|
now?: string;
|
|
193
193
|
pluginSelector?: string;
|
|
194
|
+
pluginManaged?: boolean;
|
|
194
195
|
}): Promise<HookInstallResult> {
|
|
195
196
|
const paths = input.paths ?? resolveClaudePaths({ homeDir: input.homeDir });
|
|
196
197
|
const existing = await readTextIfExists(paths.settingsPath);
|
|
198
|
+
const pluginSelector = input.pluginSelector ?? DEFAULT_CLAUDE_PLUGIN_SELECTOR;
|
|
199
|
+
if (input.pluginManaged === true || isClaudePluginEnabled(existing, pluginSelector)) {
|
|
200
|
+
const next = removeClaudeManagedUserHooks(existing);
|
|
201
|
+
if (next === null) {
|
|
202
|
+
return {
|
|
203
|
+
target: "claude",
|
|
204
|
+
targetPath: paths.settingsPath,
|
|
205
|
+
backupPath: null,
|
|
206
|
+
changed: false,
|
|
207
|
+
warnings: [],
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return writeMergedConfig({
|
|
211
|
+
target: "claude",
|
|
212
|
+
path: paths.settingsPath,
|
|
213
|
+
existing,
|
|
214
|
+
next,
|
|
215
|
+
now: input.now,
|
|
216
|
+
warnings: [],
|
|
217
|
+
});
|
|
218
|
+
}
|
|
197
219
|
const runtimeCommand = await resolveClaudeUserHookRuntimeCommand({
|
|
198
220
|
paths,
|
|
199
|
-
pluginSelector
|
|
221
|
+
pluginSelector,
|
|
200
222
|
});
|
|
201
223
|
const next = mergeClaudeSettingsHooks(existing, createClaudeHookConfig(runtimeCommand).hooks);
|
|
202
224
|
return writeMergedConfig({
|
|
@@ -497,6 +519,37 @@ function mergeClaudeSettingsHooks(
|
|
|
497
519
|
return `${JSON.stringify({ ...settings, hooks: nextHooks }, null, 2)}\n`;
|
|
498
520
|
}
|
|
499
521
|
|
|
522
|
+
function isClaudePluginEnabled(existing: string | null, pluginSelector: string): boolean {
|
|
523
|
+
if (existing === null) return false;
|
|
524
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
525
|
+
const enabledPlugins = isRecord(settings.enabledPlugins) ? settings.enabledPlugins : {};
|
|
526
|
+
return enabledPlugins[pluginSelector] === true;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function removeClaudeManagedUserHooks(existing: string | null): string | null {
|
|
530
|
+
if (existing === null) return null;
|
|
531
|
+
const settings = parseJsonConfig(existing, "Claude settings");
|
|
532
|
+
if (!isRecord(settings.hooks)) return existing;
|
|
533
|
+
|
|
534
|
+
const nextHooks: Record<string, unknown> = {};
|
|
535
|
+
let changed = false;
|
|
536
|
+
for (const [eventName, groups] of Object.entries(settings.hooks)) {
|
|
537
|
+
if (!Array.isArray(groups)) {
|
|
538
|
+
nextHooks[eventName] = groups;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
const retained = groups.filter((group) => !isEvoDevHookGroup(group, "claude"));
|
|
542
|
+
changed ||= retained.length !== groups.length;
|
|
543
|
+
if (retained.length > 0 || groups.length === 0) nextHooks[eventName] = retained;
|
|
544
|
+
}
|
|
545
|
+
if (!changed) return existing;
|
|
546
|
+
|
|
547
|
+
const nextSettings = { ...settings };
|
|
548
|
+
if (Object.keys(nextHooks).length === 0) nextSettings.hooks = undefined;
|
|
549
|
+
else nextSettings.hooks = nextHooks;
|
|
550
|
+
return `${JSON.stringify(nextSettings, null, 2)}\n`;
|
|
551
|
+
}
|
|
552
|
+
|
|
500
553
|
function parseJsonConfig(existing: string | null, label: string): Record<string, unknown> {
|
|
501
554
|
if (existing === null || existing.trim() === "") return {};
|
|
502
555
|
const parsed = JSON.parse(existing) as unknown;
|
|
@@ -56,6 +56,7 @@ export interface ClaudePluginOptions {
|
|
|
56
56
|
pluginSelector?: string;
|
|
57
57
|
pluginMarketplaceSource?: string;
|
|
58
58
|
pluginScope?: "user";
|
|
59
|
+
pluginVersion?: string;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
export function createClaudePlugin(options: ClaudePluginOptions = {}): CodeAgentPlugin {
|
|
@@ -186,7 +187,12 @@ async function installClaudeCodePlugin(
|
|
|
186
187
|
input: PluginInstallInput,
|
|
187
188
|
options: Pick<
|
|
188
189
|
ClaudePluginOptions,
|
|
189
|
-
|
|
190
|
+
| "commandRunner"
|
|
191
|
+
| "paths"
|
|
192
|
+
| "pluginSelector"
|
|
193
|
+
| "pluginMarketplaceSource"
|
|
194
|
+
| "pluginScope"
|
|
195
|
+
| "pluginVersion"
|
|
190
196
|
>,
|
|
191
197
|
): Promise<PluginInstallResult> {
|
|
192
198
|
const command = "claude";
|
|
@@ -195,6 +201,42 @@ async function installClaudeCodePlugin(
|
|
|
195
201
|
const args = ["plugin", "install", selector, "--scope", scope];
|
|
196
202
|
const runner = options.commandRunner ?? new NodeClaudeCommandRunner();
|
|
197
203
|
const warnings: string[] = [];
|
|
204
|
+
const installedPlugin =
|
|
205
|
+
input.force === true || options.pluginVersion === undefined
|
|
206
|
+
? null
|
|
207
|
+
: await readInstalledClaudePlugin(runner, selector);
|
|
208
|
+
let needsRepair = false;
|
|
209
|
+
|
|
210
|
+
if (
|
|
211
|
+
installedPlugin !== null &&
|
|
212
|
+
installedPlugin.version === options.pluginVersion &&
|
|
213
|
+
installedPlugin.enabled
|
|
214
|
+
) {
|
|
215
|
+
try {
|
|
216
|
+
const hydration = await hydrateClaudeWorkspaceCoreDependency({
|
|
217
|
+
paths: options.paths,
|
|
218
|
+
selector,
|
|
219
|
+
});
|
|
220
|
+
if (hydration.warnings.length === 0 && hydration.errors.length === 0) {
|
|
221
|
+
return createPluginInstallResult(
|
|
222
|
+
input.targetPlugin,
|
|
223
|
+
"already-installed",
|
|
224
|
+
command,
|
|
225
|
+
args,
|
|
226
|
+
`Claude Code plugin ${selector} already matches EvoDev ${options.pluginVersion}; skipped marketplace refresh.`,
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
} catch {
|
|
230
|
+
// Fall through to the normal repair path, which returns a structured install failure.
|
|
231
|
+
}
|
|
232
|
+
needsRepair = true;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const forceRefresh =
|
|
236
|
+
input.force === true ||
|
|
237
|
+
needsRepair ||
|
|
238
|
+
(installedPlugin !== null &&
|
|
239
|
+
(installedPlugin.version !== options.pluginVersion || !installedPlugin.enabled));
|
|
198
240
|
|
|
199
241
|
try {
|
|
200
242
|
if (options.pluginMarketplaceSource !== undefined) {
|
|
@@ -244,7 +286,7 @@ async function installClaudeCodePlugin(
|
|
|
244
286
|
}
|
|
245
287
|
}
|
|
246
288
|
|
|
247
|
-
if (
|
|
289
|
+
if (forceRefresh) {
|
|
248
290
|
const uninstallArgs = [
|
|
249
291
|
"plugin",
|
|
250
292
|
"uninstall",
|
|
@@ -293,7 +335,7 @@ async function installClaudeCodePlugin(
|
|
|
293
335
|
result.stdout,
|
|
294
336
|
[
|
|
295
337
|
...warnings,
|
|
296
|
-
|
|
338
|
+
forceRefresh
|
|
297
339
|
? "Claude Code reported the plugin is already installed after forced refresh; check the local plugin cache if changes are not visible."
|
|
298
340
|
: "Claude Code reported the plugin is already installed; if local plugin files changed without a version bump, Claude may keep the existing cached copy. Bump the plugin version or uninstall and reinstall to refresh the cache.",
|
|
299
341
|
],
|
|
@@ -330,6 +372,35 @@ async function installClaudeCodePlugin(
|
|
|
330
372
|
}
|
|
331
373
|
}
|
|
332
374
|
|
|
375
|
+
interface InstalledClaudePlugin {
|
|
376
|
+
version: string | null;
|
|
377
|
+
enabled: boolean;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function readInstalledClaudePlugin(
|
|
381
|
+
runner: ClaudeCommandRunner,
|
|
382
|
+
selector: string,
|
|
383
|
+
): Promise<InstalledClaudePlugin | null> {
|
|
384
|
+
try {
|
|
385
|
+
const result = await runner.run("claude", ["plugin", "list", "--json"]);
|
|
386
|
+
if (result.exitCode !== 0 || result.stdout === undefined) return null;
|
|
387
|
+
const parsed = JSON.parse(result.stdout) as unknown;
|
|
388
|
+
const plugins = Array.isArray(parsed)
|
|
389
|
+
? parsed
|
|
390
|
+
: isRecord(parsed) && Array.isArray(parsed.plugins)
|
|
391
|
+
? parsed.plugins
|
|
392
|
+
: [];
|
|
393
|
+
const plugin = plugins.find((candidate) => isRecord(candidate) && candidate.id === selector);
|
|
394
|
+
if (!isRecord(plugin)) return null;
|
|
395
|
+
return {
|
|
396
|
+
version: typeof plugin.version === "string" ? plugin.version : null,
|
|
397
|
+
enabled: plugin.enabled !== false,
|
|
398
|
+
};
|
|
399
|
+
} catch {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
333
404
|
function isAlreadyInstalledMessage(message: string | undefined): boolean {
|
|
334
405
|
return message !== undefined && /already\s+installed/i.test(message);
|
|
335
406
|
}
|
|
@@ -655,6 +726,10 @@ function isNotDirectoryError(error: unknown): boolean {
|
|
|
655
726
|
);
|
|
656
727
|
}
|
|
657
728
|
|
|
729
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
730
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
731
|
+
}
|
|
732
|
+
|
|
658
733
|
function describeError(error: unknown): string {
|
|
659
734
|
if (error instanceof Error) {
|
|
660
735
|
return error.message;
|
|
@@ -79,6 +79,7 @@ export async function runHookRuntimeCli(options: HookRuntimeCliOptions = {}): Pr
|
|
|
79
79
|
receivedAt: event.time.receivedAt,
|
|
80
80
|
environment,
|
|
81
81
|
runtimeInjectionEnabled: settings.memory.runtimeInjection,
|
|
82
|
+
sessionMemoryPolicy: settings.memory.sessionMemory,
|
|
82
83
|
});
|
|
83
84
|
const formatted = runtimeApi.core.formatHookRuntimeOutput(result);
|
|
84
85
|
await appendExecutionEventSafely({
|
|
@@ -183,6 +184,12 @@ async function appendExecutionEventSafely(input: {
|
|
|
183
184
|
environment: input.environment,
|
|
184
185
|
payload: input.payload,
|
|
185
186
|
});
|
|
187
|
+
const cwd =
|
|
188
|
+
input.payload !== null && typeof input.payload.cwd === "string" ? input.payload.cwd : null;
|
|
189
|
+
const workspace =
|
|
190
|
+
team === null && cwd !== null
|
|
191
|
+
? await input.core.resolveProjectWorkspaceFromCwd({ homeDir: input.homeDir, cwd })
|
|
192
|
+
: null;
|
|
186
193
|
const traceRefId = await recordTraceRefSafely(input);
|
|
187
194
|
await input.core.appendEvoDevExecutionEvent(
|
|
188
195
|
input.homeDir,
|
|
@@ -191,7 +198,7 @@ async function appendExecutionEventSafely(input: {
|
|
|
191
198
|
target: input.target,
|
|
192
199
|
eventType: input.event?.type ?? runtimePhaseEventType(input.phase),
|
|
193
200
|
sessionKey,
|
|
194
|
-
projectKey: team?.projectKey ?? null,
|
|
201
|
+
projectKey: team?.projectKey ?? workspace?.projectKey ?? null,
|
|
195
202
|
runId: team?.runId ?? null,
|
|
196
203
|
roleId: team?.roleId ?? null,
|
|
197
204
|
taskId: input.event?.scope.taskId ?? null,
|
|
@@ -23,7 +23,7 @@ It is not a trace summarizer, automatic memory writer, OKF file writer, or team
|
|
|
23
23
|
## Do Not Use This Skill For
|
|
24
24
|
|
|
25
25
|
- Writing `CLAUDE.md`, `AGENTS.md`, `.claude/`, `.codex/`, `.evodev/`, source files, or project assets without explicit project opt-in.
|
|
26
|
-
- Storing
|
|
26
|
+
- Storing credentials or wholesale prompts, transcripts, source files, source dumps, or raw command output. Distilled private facts and necessary short excerpts may remain in user-local knowledge.
|
|
27
27
|
- Treating unreviewed observations, model reflection, or trace logs as accepted memory.
|
|
28
28
|
- Writing final OKF concept documents directly; output a transient plan for the organizer.
|
|
29
29
|
- Starting subagents or teams automatically.
|
|
@@ -62,14 +62,14 @@ Classify every input before extraction:
|
|
|
62
62
|
## Distillation Pipeline
|
|
63
63
|
|
|
64
64
|
1. **Scope**: identify repo, task, role audience, workflow audience, path scope, evidence ids, and user-local OKF target scope.
|
|
65
|
-
2. **Minimize**: remove
|
|
65
|
+
2. **Minimize**: remove credentials, wholesale prompts/logs/source/command output, and one-off noise. Preserve private facts or short excerpts only when needed to keep the knowledge accurate and reusable.
|
|
66
66
|
3. **Analyze execution structure**: when event evidence is present, identify task slices, owner roles, dependencies, key tool calls, skill invocations, subagent lifecycle events, verification gates, and merge outcomes.
|
|
67
67
|
4. **Extract atomic candidates**: one claim per candidate. Allowed `kind` values are `rule`, `decision`, `pattern`, `anti-pattern`, `warning`, `checklist`, `concept`, `workflow-improvement`, `task-split-improvement`, `tool-use-improvement`, `skill-improvement`, `repo-asset-suggestion`, `role-agent-suggestion`, `team-suggestion`, `eval-set`, and `open-question`.
|
|
68
68
|
5. **Separate fact from inference**: mark whether the candidate is directly evidenced or inferred from evidence.
|
|
69
69
|
6. **Classify**: add `okfType`, `targetPath`, `stableKey`, `roleTags`, `repoTags`, `workflowTags`, `pathScopes`, `domainTags`, `stability`, `sensitivity`, and `targetStore`.
|
|
70
70
|
7. **Score**: estimate evidence strength, reuse value, actionability, stability, novelty, privacy risk, and duplication risk.
|
|
71
71
|
8. **Pair improvements with evals**: every proposed skill, role-agent, team, workflow, routing, tool-use, or subagent behavior change should include an `evoEvalSets` entry, unless the plan explains why eval coverage is not applicable.
|
|
72
|
-
9. **Privacy gate**:
|
|
72
|
+
9. **Privacy gate**: reject credentials and unbounded raw copying. Private facts, internal links, local paths, emails, and short excerpts may remain in local-private knowledge when necessary.
|
|
73
73
|
10. **Route**: emit `no_write`, `create`, `update`, `skip`, or `needs-human` for each candidate.
|
|
74
74
|
11. **Plan OKF organization**: provide canonical concept targets and repo/role/workflow overlay updates. Do not emit final OKF files.
|
|
75
75
|
12. **Recovery notes**: explain conflicts, stale information, required repo fact checks, and why human intervention is needed when applicable.
|
|
@@ -197,6 +197,8 @@ Return executable JSON with `schemaVersion: 1` and `kind: "knowledge-distillatio
|
|
|
197
197
|
|
|
198
198
|
Required candidate fields are `id`, `decision`, `kind`, `okfType`, `targetStore`, `targetPath`, `stableKey`, `confidence`, `title`, `description`, `claim`, `basis`, `metadataOnlyEvidence`, `howToApply`, `antiCriteria`, `roleTags`, `repoTags`, `workflowTags`, `pathScopes`, `relatedConceptLinks`, `overlayUpdates`, `scores`, `decisionReason`, `evidenceRefs`, `reviewState`, `bodySections`, and `privacyCheck`.
|
|
199
199
|
|
|
200
|
+
All raw-content and credential privacy flags must remain `false`. `internalLinksStored` is instead a disclosure flag: set it to `true` when the durable candidate retains an HTTP(S) link. EvoDev recomputes this field locally before persistence.
|
|
201
|
+
|
|
200
202
|
Valid decisions are `auto-accept`, `create`, `update`, `needs-human`, `skip`, and canonical `no_write`. `no-write` may be normalized by the runtime but new output should emit `no_write`. Active writes (`auto-accept`, `create`, `update`) must target `okf`, use reviewState `auto-accepted` or `accepted`, use metadata-only evidence, include evidence refs, have a safe relative `.md` target path outside reserved `index.md` and `log.md`, and include verification or `verificationNotApplicableReason`.
|
|
201
203
|
|
|
202
204
|
Behavior-changing active writes, including skill, role-agent, team, workflow, routing, tool-use, task-split, and subagent changes, must include `evalSetRefs` that point to provided `evoEvalSets`. Eval sets must be metadata-only and use privacy flags `usesRawPrompt: false`, `usesSourceDump: false`, and `usesRawCommandOutput: false`.
|