@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.
Files changed (38) hide show
  1. package/assets/agents/review/code-reviewer/examples.md +1 -1
  2. package/assets/agents/review/code-reviewer/prompt.md +1 -1
  3. package/assets/agents/review/code-reviewer/verification.md +1 -1
  4. package/assets/skills/coding/knowledge-distillation/SKILL.md +248 -0
  5. package/assets/skills/coding/knowledge-distillation/manifest.json +10 -0
  6. package/assets/skills/coding/knowledge-distillation/references/knowledge-distillation-methods.md +122 -0
  7. package/assets/workflows/rd-bug-fix/WORKFLOW.json +1 -1
  8. package/assets/workflows/rd-code-review/WORKFLOW.json +1 -1
  9. package/assets/workflows/rd-docs-update/WORKFLOW.json +1 -1
  10. package/assets/workflows/rd-feature-implementation/WORKFLOW.json +1 -1
  11. package/assets/workflows/rd-refactor/WORKFLOW.json +1 -1
  12. package/assets/workflows/rd-release-readiness/WORKFLOW.json +1 -1
  13. package/assets/workflows/rd-security-boundary-review/WORKFLOW.json +2 -2
  14. package/assets/workflows/rd-test-generation/WORKFLOW.json +1 -1
  15. package/dist/config/index.js +242 -36
  16. package/dist/index.js +5045 -934
  17. package/dist/plugins/index.js +32 -32
  18. package/package.json +1 -1
  19. package/src/agents/index.ts +28 -49
  20. package/src/config/index.ts +2 -0
  21. package/src/config/paths.ts +30 -0
  22. package/src/config/settings.ts +52 -0
  23. package/src/config/store.ts +150 -0
  24. package/src/daemon/index.ts +376 -3
  25. package/src/evolution/index.ts +2356 -0
  26. package/src/hooks/index.ts +255 -238
  27. package/src/index.ts +4 -0
  28. package/src/pack/index.ts +13 -13
  29. package/src/plugins/capabilities.ts +40 -42
  30. package/src/plugins/index.ts +0 -1
  31. package/src/plugins/types.ts +4 -0
  32. package/src/protected-zones/index.ts +29 -11
  33. package/src/runtime-logs/index.ts +324 -0
  34. package/src/sync/orchestrator.ts +6 -0
  35. package/src/task/index.ts +3 -3
  36. package/src/team/index.ts +2398 -0
  37. package/src/team/mcp.ts +401 -0
  38. package/src/workflow/index.ts +6 -6
@@ -21,12 +21,30 @@ function resolveEvoDevPaths(homeDir = getHomeDir()) {
21
21
  const normalizedHome = stripTrailingSlash(homeDir);
22
22
  const rootDir = `${normalizedHome}/.evodev`;
23
23
  const stateDir = `${rootDir}/state`;
24
+ const logsDir = `${rootDir}/logs`;
25
+ const knowledgeDir = `${rootDir}/knowledge`;
26
+ const evosDir = `${rootDir}/evos`;
27
+ const roleAgentsDir = `${rootDir}/agents/roles`;
28
+ const teamsDir = `${rootDir}/teams`;
29
+ const runsDir = `${rootDir}/runs`;
24
30
  return {
25
31
  homeDir: normalizedHome,
26
32
  rootDir,
27
33
  settingsPath: `${rootDir}/settings.json`,
28
34
  registryPath: `${rootDir}/registry.json`,
29
35
  stateDir,
36
+ logsDir,
37
+ knowledgeDir,
38
+ knowledgeIndexPath: `${knowledgeDir}/index.json`,
39
+ evosDir,
40
+ evosCasesDir: `${evosDir}/cases`,
41
+ evosIndexPath: `${evosDir}/index.json`,
42
+ roleAgentsDir,
43
+ roleAgentsIndexPath: `${roleAgentsDir}/index.json`,
44
+ teamsDir,
45
+ teamsIndexPath: `${teamsDir}/index.json`,
46
+ runsDir,
47
+ latestRunPath: `${runsDir}/latest.json`,
30
48
  installStatePath: `${stateDir}/install.json`,
31
49
  syncStatePath: `${stateDir}/sync.json`
32
50
  };
@@ -98,11 +116,48 @@ function expectString(value, path) {
98
116
  }
99
117
  return value;
100
118
  }
119
+ // packages/core/src/evolution/index.ts
120
+ var PROCESS_LOCK_STALE_MS = 5 * 60 * 1000;
121
+ var FORBIDDEN_RAW_KEYS = new Set([
122
+ "commandhistory",
123
+ "commandoutput",
124
+ "credential",
125
+ "credentials",
126
+ "env",
127
+ "fullsource",
128
+ "memorybody",
129
+ "password",
130
+ "privatekey",
131
+ "prompt",
132
+ "promptbody",
133
+ "prompttext",
134
+ "rawcommand",
135
+ "rawcommandoutput",
136
+ "rawlog",
137
+ "rawlogs",
138
+ "rawoutput",
139
+ "rawpayload",
140
+ "rawprompt",
141
+ "secret",
142
+ "secretvalue",
143
+ "source",
144
+ "sourcebody",
145
+ "sourcecode",
146
+ "sourcecontent",
147
+ "sourcetext",
148
+ "stderr",
149
+ "stdout",
150
+ "token",
151
+ "transcript",
152
+ "transcriptbody",
153
+ "transcripttext"
154
+ ]);
155
+
101
156
  // packages/core/src/task/index.ts
102
157
  var FORBIDDEN_TASK_WRITE_SEGMENTS = new Set([".claude", ".codex"]);
103
158
  var FORBIDDEN_PROJECT_ASSET_SEGMENTS = new Set(["packages", "src"]);
104
159
  var FORBIDDEN_TASK_WRITE_FILES = new Set(["agents.md", "claude.md", "package.json", "readme.md"]);
105
- var FORBIDDEN_RAW_KEYS = new Set([
160
+ var FORBIDDEN_RAW_KEYS2 = new Set([
106
161
  "rawoutput",
107
162
  "raw_output",
108
163
  "stdout",
@@ -162,47 +217,47 @@ var CANONICAL_HOOK_EVENT_TYPES = [
162
217
  "WorktreeRemove"
163
218
  ];
164
219
  var DEFAULT_EVENT_SETTINGS = {
165
- SessionStart: false,
166
- UserPromptSubmit: false,
167
- UserPromptExpansion: false,
168
- PreToolUse: false,
169
- PermissionRequest: false,
170
- PostToolUse: false,
171
- PostToolUseFailure: false,
172
- PostToolBatch: false,
173
- PermissionDenied: false,
174
- SubagentStart: false,
175
- Stop: false,
176
- StopFailure: false,
177
- TeammateIdle: false,
178
- SubagentStop: false,
179
- TaskCreated: false,
180
- TaskCompleted: false,
181
- PreCompact: false,
182
- PostCompact: false,
183
- SessionEnd: false,
184
- ConfigChange: false,
185
- CwdChanged: false,
186
- FileChanged: false,
187
- WorktreeCreate: false,
188
- WorktreeRemove: false
220
+ SessionStart: true,
221
+ UserPromptSubmit: true,
222
+ UserPromptExpansion: true,
223
+ PreToolUse: true,
224
+ PermissionRequest: true,
225
+ PostToolUse: true,
226
+ PostToolUseFailure: true,
227
+ PostToolBatch: true,
228
+ PermissionDenied: true,
229
+ SubagentStart: true,
230
+ Stop: true,
231
+ StopFailure: true,
232
+ TeammateIdle: true,
233
+ SubagentStop: true,
234
+ TaskCreated: true,
235
+ TaskCompleted: true,
236
+ PreCompact: true,
237
+ PostCompact: true,
238
+ SessionEnd: true,
239
+ ConfigChange: true,
240
+ CwdChanged: true,
241
+ FileChanged: true,
242
+ WorktreeCreate: true,
243
+ WorktreeRemove: true
189
244
  };
190
245
  function createDefaultHookSettings() {
191
246
  return {
192
- enabled: false,
247
+ enabled: true,
193
248
  targets: {
194
249
  claude: {
195
- enabled: false,
250
+ enabled: true,
196
251
  events: { ...DEFAULT_EVENT_SETTINGS }
197
252
  },
198
253
  codex: {
199
- enabled: false,
254
+ enabled: true,
200
255
  events: { ...DEFAULT_EVENT_SETTINGS }
201
256
  }
202
257
  },
203
258
  observability: {
204
- metadataOnly: true,
205
- rawPayloadStorage: false,
259
+ metadataOnly: false,
260
+ rawPayloadStorage: true,
206
261
  appendEvents: false
207
262
  },
208
263
  learning: {
@@ -217,6 +272,9 @@ function parseHookSettings(value) {
217
272
  return defaults;
218
273
  if (!isRecord(value))
219
274
  throw new Error("Invalid hooks settings; expected object.");
275
+ const observability = isRecord(value.observability) ? value.observability : undefined;
276
+ optionalBoolean(observability?.metadataOnly, defaults.observability.metadataOnly, "hooks.observability.metadataOnly");
277
+ optionalBoolean(observability?.rawPayloadStorage, defaults.observability.rawPayloadStorage, "hooks.observability.rawPayloadStorage");
220
278
  return {
221
279
  enabled: optionalBoolean(value.enabled, defaults.enabled, "hooks.enabled"),
222
280
  targets: {
@@ -224,9 +282,9 @@ function parseHookSettings(value) {
224
282
  codex: parseHookTargetSettings(value.targets, defaults.targets.codex, "codex")
225
283
  },
226
284
  observability: {
227
- metadataOnly: true,
228
- rawPayloadStorage: false,
229
- appendEvents: false
285
+ metadataOnly: false,
286
+ rawPayloadStorage: true,
287
+ appendEvents: optionalBoolean(observability?.appendEvents, defaults.observability.appendEvents, "hooks.observability.appendEvents")
230
288
  },
231
289
  learning: {
232
290
  emitCandidates: false,
@@ -286,7 +344,16 @@ function createDefaultSettings(os = process.platform) {
286
344
  doctor: {
287
345
  lastRunAt: null
288
346
  },
289
- hooks: createDefaultHookSettings()
347
+ hooks: createDefaultHookSettings(),
348
+ teamRuntime: createDefaultTeamRuntimeSettings()
349
+ };
350
+ }
351
+ function createDefaultTeamRuntimeSettings() {
352
+ return {
353
+ defaultRuntime: "codex",
354
+ defaultModel: null,
355
+ defaultThinkingLevel: null,
356
+ recordTranscript: false
290
357
  };
291
358
  }
292
359
  function mergeSettings(existing, defaults = createDefaultSettings()) {
@@ -321,7 +388,11 @@ function mergeSettings(existing, defaults = createDefaultSettings()) {
321
388
  ...defaults.doctor,
322
389
  ...existing.doctor
323
390
  },
324
- hooks: existing.hooks ?? defaults.hooks
391
+ hooks: existing.hooks ?? defaults.hooks,
392
+ teamRuntime: {
393
+ ...defaults.teamRuntime,
394
+ ...existing.teamRuntime
395
+ }
325
396
  };
326
397
  return parseSettings(merged);
327
398
  }
@@ -355,10 +426,25 @@ function parseSettings(value) {
355
426
  doctor: {
356
427
  lastRunAt: expectNullableString(doctor.lastRunAt, "settings.doctor.lastRunAt")
357
428
  },
358
- hooks: parseHookSettings(root.hooks)
429
+ hooks: parseHookSettings(root.hooks),
430
+ teamRuntime: parseTeamRuntimeSettings(root.teamRuntime ?? createDefaultTeamRuntimeSettings(), "settings.teamRuntime")
359
431
  };
360
432
  return parsed;
361
433
  }
434
+ function parseTeamRuntimeSettings(value, path) {
435
+ const input = expectRecord2(value, path);
436
+ const defaults = createDefaultTeamRuntimeSettings();
437
+ const defaultRuntime = input.defaultRuntime ?? defaults.defaultRuntime;
438
+ if (defaultRuntime !== "codex" && defaultRuntime !== "claude") {
439
+ throw new EvoDevConfigError(`Invalid ${path}.defaultRuntime; expected codex or claude`);
440
+ }
441
+ return {
442
+ defaultRuntime,
443
+ defaultModel: input.defaultModel === undefined ? defaults.defaultModel : expectNullableString(input.defaultModel, `${path}.defaultModel`),
444
+ defaultThinkingLevel: input.defaultThinkingLevel === undefined ? defaults.defaultThinkingLevel : expectNullableString(input.defaultThinkingLevel, `${path}.defaultThinkingLevel`),
445
+ recordTranscript: input.recordTranscript === undefined ? defaults.recordTranscript : expectBoolean(input.recordTranscript, `${path}.recordTranscript`)
446
+ };
447
+ }
362
448
  function parsePluginSettings(value, path) {
363
449
  const input = expectRecord2(value, path);
364
450
  const parsed = {
@@ -485,6 +571,15 @@ function createCoreConfigStore(homeDir) {
485
571
  paths,
486
572
  async ensureBaseDirs() {
487
573
  await mkdir(paths.stateDir, { recursive: true });
574
+ await mkdir(paths.logsDir, { recursive: true });
575
+ await mkdir(paths.knowledgeDir, { recursive: true });
576
+ await mkdir(paths.evosCasesDir, { recursive: true });
577
+ await mkdir(paths.roleAgentsDir, { recursive: true });
578
+ await mkdir(paths.teamsDir, { recursive: true });
579
+ await mkdir(paths.runsDir, { recursive: true });
580
+ },
581
+ async ensureKnowledgeBase() {
582
+ await ensureKnowledgeBaseFiles(paths);
488
583
  },
489
584
  async readSettings() {
490
585
  return readJsonFile(paths.settingsPath, parseSettings);
@@ -521,12 +616,83 @@ function createCoreConfigStore(homeDir) {
521
616
  async function initializeCoreConfig(homeDir) {
522
617
  const store = createCoreConfigStore(homeDir);
523
618
  await store.ensureBaseDirs();
619
+ await store.ensureKnowledgeBase();
524
620
  await writeIfMissing(store.paths.settingsPath, createDefaultSettings());
525
621
  await writeIfMissing(store.paths.registryPath, createDefaultRegistry());
526
622
  await writeIfMissing(store.paths.installStatePath, createDefaultInstallState());
527
623
  await writeIfMissing(store.paths.syncStatePath, createDefaultSyncState());
528
624
  return store;
529
625
  }
626
+ async function ensureKnowledgeBaseFiles(paths) {
627
+ await mkdir(paths.knowledgeDir, { recursive: true });
628
+ await mkdir(paths.evosCasesDir, { recursive: true });
629
+ await writeTextIfMissing(`${paths.knowledgeDir}/README.md`, [
630
+ "# EvoDev Knowledge",
631
+ "",
632
+ "Local-private knowledge base for user-accepted facts, decisions, architecture notes, and reusable domain context.",
633
+ "",
634
+ "EvoDev must not populate this directory from source code, prompts, command output, logs, or transcripts without an explicit consent flow.",
635
+ ""
636
+ ].join(`
637
+ `));
638
+ await writeIndexIfMissingOrMigrate(paths.knowledgeIndexPath, "knowledge-index", {
639
+ version: 1,
640
+ kind: "knowledge-index",
641
+ roleTags: [],
642
+ entries: []
643
+ });
644
+ await writeTextIfMissing(`${paths.evosDir}/README.md`, [
645
+ "# EvoDev Evos",
646
+ "",
647
+ "Local-private evolution case library for reviewed improvement cases and reusable process changes.",
648
+ "",
649
+ "Cases start empty. Future automation may propose candidates, but accepted evos require explicit review before they can influence workflows or routing.",
650
+ ""
651
+ ].join(`
652
+ `));
653
+ await writeTextIfMissing(`${paths.evosCasesDir}/README.md`, [
654
+ "# Evolution Cases",
655
+ "",
656
+ "Store one reviewed evolution case per file. Do not store raw prompts, source dumps, secrets, transcripts, or raw command output here.",
657
+ ""
658
+ ].join(`
659
+ `));
660
+ await writeIndexIfMissingOrMigrate(paths.evosIndexPath, "evos-index", {
661
+ version: 1,
662
+ kind: "evos-index",
663
+ roleTags: [],
664
+ cases: []
665
+ });
666
+ await writeTextIfMissing(`${paths.roleAgentsDir}/README.md`, [
667
+ "# Role Agents",
668
+ "",
669
+ "Local-private role agent registry for EvoDev-managed agent roles and user-reviewed role extensions.",
670
+ "",
671
+ "Repository-specific role agents should be proposed first and written into a user repository only after explicit project opt-in.",
672
+ ""
673
+ ].join(`
674
+ `));
675
+ await writeIndexIfMissingOrMigrate(paths.roleAgentsIndexPath, "role-agent-index", {
676
+ version: 1,
677
+ kind: "role-agent-index",
678
+ roles: [],
679
+ projectExtensions: []
680
+ });
681
+ await writeTextIfMissing(`${paths.teamsDir}/README.md`, [
682
+ "# Agent Teams",
683
+ "",
684
+ "Local-private EvoHub team registry for reviewed role-agent team definitions.",
685
+ "",
686
+ "Teams may reference role agents and role-tagged knowledge, but they must not contain raw source, prompts, transcripts, secrets, or raw command output.",
687
+ ""
688
+ ].join(`
689
+ `));
690
+ await writeIndexIfMissingOrMigrate(paths.teamsIndexPath, "agent-team-index", {
691
+ version: 1,
692
+ kind: "agent-team-index",
693
+ teams: []
694
+ });
695
+ }
530
696
  async function readJsonFile(filePath, parse) {
531
697
  let raw;
532
698
  try {
@@ -570,6 +736,42 @@ async function writeIfMissing(filePath, value) {
570
736
  throw new EvoDevConfigError(`Cannot inspect config file (${describeFileError(error)})`, filePath);
571
737
  }
572
738
  }
739
+ async function writeIndexIfMissingOrMigrate(filePath, kind, defaults) {
740
+ let raw;
741
+ try {
742
+ raw = await readFile(filePath, "utf8");
743
+ } catch (error) {
744
+ if (isNodeError(error) && error.code === "ENOENT") {
745
+ await writeJsonFile(filePath, defaults);
746
+ return;
747
+ }
748
+ throw new EvoDevConfigError(`Cannot inspect config file (${describeFileError(error)})`, filePath);
749
+ }
750
+ let existing;
751
+ try {
752
+ existing = JSON.parse(raw);
753
+ } catch (error) {
754
+ throw new EvoDevConfigError(`Invalid bootstrap index JSON (${describeFileError(error)})`, filePath);
755
+ }
756
+ if (!isRecord2(existing) || existing.kind !== kind)
757
+ return;
758
+ const migrated = { ...defaults, ...existing };
759
+ if (Object.keys(defaults).every((key) => (key in existing)))
760
+ return;
761
+ await writeJsonFile(filePath, migrated);
762
+ }
763
+ async function writeTextIfMissing(filePath, value) {
764
+ try {
765
+ await readFile(filePath, "utf8");
766
+ } catch (error) {
767
+ if (isNodeError(error) && error.code === "ENOENT") {
768
+ await mkdir(dirname(filePath), { recursive: true });
769
+ await writeFile(filePath, value, "utf8");
770
+ return;
771
+ }
772
+ throw new EvoDevConfigError(`Cannot inspect config file (${describeFileError(error)})`, filePath);
773
+ }
774
+ }
573
775
  async function writeJsonFile(filePath, value) {
574
776
  await mkdir(dirname(filePath), { recursive: true });
575
777
  await writeFile(filePath, `${JSON.stringify(value, null, 2)}
@@ -584,6 +786,9 @@ function describeFileError(error) {
584
786
  function isNodeError(error) {
585
787
  return error instanceof Error && "code" in error;
586
788
  }
789
+ function isRecord2(value) {
790
+ return typeof value === "object" && value !== null && !Array.isArray(value);
791
+ }
587
792
  export {
588
793
  resolveEvoDevPaths,
589
794
  parseSyncState,
@@ -592,6 +797,7 @@ export {
592
797
  parseInstallState,
593
798
  mergeSettings,
594
799
  initializeCoreConfig,
800
+ createDefaultTeamRuntimeSettings,
595
801
  createDefaultSyncState,
596
802
  createDefaultSettings,
597
803
  createDefaultRegistry,