@evo-dev/core 0.0.1-alpha.2 → 0.0.1-alpha.4

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 (54) hide show
  1. package/assets/team/agents/code-reviewer.md +48 -0
  2. package/assets/team/agents/docs-maintainer.md +51 -0
  3. package/assets/team/agents/implementation-engineer.md +51 -0
  4. package/assets/team/agents/product-scope-analyst.md +58 -0
  5. package/assets/team/agents/release-engineer.md +55 -0
  6. package/assets/team/agents/security-boundary-reviewer.md +50 -0
  7. package/assets/team/agents/solution-architect.md +51 -0
  8. package/assets/team/agents/verification-engineer.md +51 -0
  9. package/assets/team/team.md +102 -0
  10. package/dist/config/index.js +181 -125
  11. package/dist/index.js +10971 -9455
  12. package/package.json +1 -1
  13. package/src/agents/index.ts +1 -1
  14. package/src/code-agent-traces/index.ts +3 -10
  15. package/src/config/settings.ts +14 -0
  16. package/src/config/store.ts +1 -1
  17. package/src/daemon/index.ts +1 -1
  18. package/src/evolution/candidates/index.ts +235 -0
  19. package/src/evolution/control/index.ts +19 -0
  20. package/src/evolution/evidence/analysis.ts +529 -0
  21. package/src/evolution/evidence/index.ts +3 -0
  22. package/src/evolution/evidence/session-memory/constants.ts +12 -0
  23. package/src/evolution/evidence/session-memory/index.ts +4 -0
  24. package/src/evolution/evidence/session-memory/paths.ts +29 -0
  25. package/src/evolution/evidence/session-memory/policy.ts +39 -0
  26. package/src/evolution/evidence/session-memory/segment.ts +192 -0
  27. package/src/evolution/evidence/session-memory/state-machine.ts +249 -0
  28. package/src/evolution/evidence/session-memory/storage.ts +145 -0
  29. package/src/evolution/evidence/session-memory/types.ts +207 -0
  30. package/src/evolution/evidence/session-memory/updater.ts +184 -0
  31. package/src/evolution/formatters.ts +169 -0
  32. package/src/evolution/index.ts +12 -2827
  33. package/src/{knowledge → evolution/knowledge}/index.ts +7 -7
  34. package/src/evolution/paths.ts +41 -0
  35. package/src/evolution/processor/distillation.ts +436 -0
  36. package/src/evolution/processor/index.ts +3 -0
  37. package/src/evolution/processor/process.ts +306 -0
  38. package/src/evolution/schema.ts +522 -0
  39. package/src/evolution/shared.ts +677 -0
  40. package/src/evolution/triggers/classification.ts +102 -0
  41. package/src/evolution/triggers/index.ts +295 -0
  42. package/src/hooks/index.ts +56 -9
  43. package/src/index.ts +10 -2
  44. package/src/runtime-logs/index.ts +4 -12
  45. package/src/team/index.ts +576 -3
  46. package/src/utils/errors.ts +13 -0
  47. package/src/utils/fs.ts +40 -0
  48. package/src/utils/hash.ts +9 -0
  49. package/src/utils/ids.ts +12 -0
  50. package/src/utils/index.ts +7 -0
  51. package/src/utils/parsing.ts +11 -0
  52. package/src/utils/text.ts +18 -0
  53. package/src/utils/time.ts +5 -0
  54. /package/src/{learning → evolution/review}/index.ts +0 -0
@@ -118,7 +118,39 @@ function expectString(value, path) {
118
118
  }
119
119
  // packages/core/src/config/settings.ts
120
120
  import { readFile as readFile2 } from "node:fs/promises";
121
-
121
+ // packages/core/src/utils/parsing.ts
122
+ function optionalBoolean(value, fallback) {
123
+ return typeof value === "boolean" ? value : fallback;
124
+ }
125
+ function positiveInteger(value, fallback) {
126
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : fallback;
127
+ }
128
+ // packages/core/src/evolution/evidence/session-memory/policy.ts
129
+ function createDefaultSessionMemoryPolicy() {
130
+ return {
131
+ enabled: true,
132
+ storeRawSegments: true,
133
+ maxRawSegmentBytes: 200000,
134
+ retentionDays: 30,
135
+ minimumMessageTokensToInit: 1e4,
136
+ minimumTokensBetweenUpdate: 5000,
137
+ toolCallsBetweenUpdates: 9
138
+ };
139
+ }
140
+ function parseSessionMemoryPolicy(value) {
141
+ const defaults = createDefaultSessionMemoryPolicy();
142
+ if (value === undefined)
143
+ return defaults;
144
+ return {
145
+ enabled: optionalBoolean(value.enabled, defaults.enabled),
146
+ storeRawSegments: optionalBoolean(value.storeRawSegments, defaults.storeRawSegments),
147
+ maxRawSegmentBytes: positiveInteger(value.maxRawSegmentBytes, defaults.maxRawSegmentBytes),
148
+ retentionDays: positiveInteger(value.retentionDays, defaults.retentionDays),
149
+ minimumMessageTokensToInit: positiveInteger(value.minimumMessageTokensToInit, defaults.minimumMessageTokensToInit),
150
+ minimumTokensBetweenUpdate: positiveInteger(value.minimumTokensBetweenUpdate, defaults.minimumTokensBetweenUpdate),
151
+ toolCallsBetweenUpdates: positiveInteger(value.toolCallsBetweenUpdates, defaults.toolCallsBetweenUpdates)
152
+ };
153
+ }
122
154
  // packages/core/src/runtime-logs/index.ts
123
155
  var SAFE_EXECUTION_METADATA_KEYS = new Set([
124
156
  "phase",
@@ -143,7 +175,46 @@ var SAFE_REDACTION_LABELS = new Set([
143
175
  "sensitive-text"
144
176
  ]);
145
177
 
146
- // packages/core/src/knowledge/index.ts
178
+ // packages/core/src/evolution/shared.ts
179
+ var PROCESS_LOCK_STALE_MS = 5 * 60 * 1000;
180
+ var FORBIDDEN_RAW_KEYS = new Set([
181
+ "commandhistory",
182
+ "commandoutput",
183
+ "credential",
184
+ "credentials",
185
+ "env",
186
+ "fullsource",
187
+ "memorybody",
188
+ "password",
189
+ "privatekey",
190
+ "prompt",
191
+ "promptbody",
192
+ "prompttext",
193
+ "rawcommand",
194
+ "rawcommandoutput",
195
+ "rawlog",
196
+ "rawlogs",
197
+ "rawoutput",
198
+ "rawpayload",
199
+ "rawprompt",
200
+ "secret",
201
+ "secretvalue",
202
+ "source",
203
+ "sourcebody",
204
+ "sourcecode",
205
+ "sourcecontent",
206
+ "sourcetext",
207
+ "stderr",
208
+ "stdout",
209
+ "token",
210
+ "transcript",
211
+ "transcriptbody",
212
+ "transcripttext"
213
+ ]);
214
+
215
+ // packages/core/src/evolution/evidence/session-memory/constants.ts
216
+ var DEFAULT_MAX_RAW_EVENT_BYTES = 64 * 1024;
217
+ // packages/core/src/evolution/knowledge/index.ts
147
218
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
148
219
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
149
220
  var RESERVED_OKF_FILENAMES = new Set(["index.md", "log.md"]);
@@ -192,19 +263,19 @@ var BEHAVIOR_CHANGE_KINDS = new Set([
192
263
  "repo-asset-suggestion"
193
264
  ]);
194
265
  function resolveOkfKnowledgePaths(homeDir) {
195
- const paths = resolveEvoDevPaths(homeDir);
266
+ const paths2 = resolveEvoDevPaths(homeDir);
196
267
  return {
197
- knowledgeDir: paths.knowledgeDir,
198
- okfDir: join(paths.knowledgeDir, "okf"),
199
- indexesDir: join(paths.knowledgeDir, "indexes"),
200
- tmpDir: join(paths.knowledgeDir, "tmp")
268
+ knowledgeDir: paths2.knowledgeDir,
269
+ okfDir: join(paths2.knowledgeDir, "okf"),
270
+ indexesDir: join(paths2.knowledgeDir, "indexes"),
271
+ tmpDir: join(paths2.knowledgeDir, "tmp")
201
272
  };
202
273
  }
203
274
  async function ensureOkfKnowledgeBase(homeDir) {
204
- const paths = resolveOkfKnowledgePaths(homeDir);
205
- await ensureLocalKnowledgeGitRepository(paths.knowledgeDir);
206
- await mkdir(paths.indexesDir, { recursive: true });
207
- await mkdir(paths.tmpDir, { recursive: true });
275
+ const paths2 = resolveOkfKnowledgePaths(homeDir);
276
+ await ensureLocalKnowledgeGitRepository(paths2.knowledgeDir);
277
+ await mkdir(paths2.indexesDir, { recursive: true });
278
+ await mkdir(paths2.tmpDir, { recursive: true });
208
279
  const directories = [
209
280
  {
210
281
  path: "",
@@ -234,13 +305,13 @@ async function ensureOkfKnowledgeBase(homeDir) {
234
305
  { path: "references", title: "References", description: "Cited references." }
235
306
  ];
236
307
  for (const directory of directories) {
237
- await ensureOkfDirectory(paths.okfDir, directory.path, directory.title, directory.description);
308
+ await ensureOkfDirectory(paths2.okfDir, directory.path, directory.title, directory.description);
238
309
  }
239
310
  await rebuildOkfKnowledgeIndexes({ homeDir });
240
311
  }
241
312
  async function rebuildOkfKnowledgeIndexes(input) {
242
- const paths = resolveOkfKnowledgePaths(input.homeDir);
243
- await mkdir(paths.indexesDir, { recursive: true });
313
+ const paths2 = resolveOkfKnowledgePaths(input.homeDir);
314
+ await mkdir(paths2.indexesDir, { recursive: true });
244
315
  const concepts = (await listOkfKnowledgeConcepts({ homeDir: input.homeDir })).filter(isActiveOkfConcept);
245
316
  const conceptSummaries = concepts.map((concept) => ({
246
317
  id: concept.id,
@@ -257,34 +328,34 @@ async function rebuildOkfKnowledgeIndexes(input) {
257
328
  pathScopes: concept.pathScopes
258
329
  }));
259
330
  const pathsWritten = [
260
- join(paths.indexesDir, "index.json"),
261
- join(paths.indexesDir, "concepts.json"),
262
- join(paths.indexesDir, "repos.json"),
263
- join(paths.indexesDir, "roles.json"),
264
- join(paths.indexesDir, "workflows.json")
331
+ join(paths2.indexesDir, "index.json"),
332
+ join(paths2.indexesDir, "concepts.json"),
333
+ join(paths2.indexesDir, "repos.json"),
334
+ join(paths2.indexesDir, "roles.json"),
335
+ join(paths2.indexesDir, "workflows.json")
265
336
  ];
266
- await writeJson(pathsWritten[0], {
337
+ await writeJson2(pathsWritten[0], {
267
338
  schemaVersion: 1,
268
339
  kind: "okf-knowledge-index",
269
340
  conceptCount: concepts.length,
270
341
  updatedAt: new Date().toISOString()
271
342
  }, { overwrite: true });
272
- await writeJson(pathsWritten[1], {
343
+ await writeJson2(pathsWritten[1], {
273
344
  schemaVersion: 1,
274
345
  kind: "okf-concepts-index",
275
346
  concepts: conceptSummaries
276
347
  }, { overwrite: true });
277
- await writeJson(pathsWritten[2], {
348
+ await writeJson2(pathsWritten[2], {
278
349
  schemaVersion: 1,
279
350
  kind: "okf-repos-index",
280
351
  repos: groupConceptsByTag(concepts, "repoTags")
281
352
  }, { overwrite: true });
282
- await writeJson(pathsWritten[3], {
353
+ await writeJson2(pathsWritten[3], {
283
354
  schemaVersion: 1,
284
355
  kind: "okf-roles-index",
285
356
  roles: groupConceptsByTag(concepts, "roleTags")
286
357
  }, { overwrite: true });
287
- await writeJson(pathsWritten[4], {
358
+ await writeJson2(pathsWritten[4], {
288
359
  schemaVersion: 1,
289
360
  kind: "okf-workflows-index",
290
361
  workflows: groupConceptsByTag(concepts, "workflowTags")
@@ -293,7 +364,7 @@ async function rebuildOkfKnowledgeIndexes(input) {
293
364
  }
294
365
  async function listOkfKnowledgeConcepts(input) {
295
366
  const okfDir = resolveOkfKnowledgePaths(input.homeDir).okfDir;
296
- if (!await pathExists(okfDir))
367
+ if (!await pathExists2(okfDir))
297
368
  return [];
298
369
  const files = await listMarkdownFiles(okfDir);
299
370
  const concepts = [];
@@ -310,7 +381,7 @@ async function listOkfKnowledgeConcepts(input) {
310
381
  async function ensureLocalKnowledgeGitRepository(knowledgeDir) {
311
382
  await mkdir(knowledgeDir, { recursive: true });
312
383
  const gitDir = join(knowledgeDir, ".git");
313
- if (await pathExists(gitDir))
384
+ if (await pathExists2(gitDir))
314
385
  return;
315
386
  await mkdir(join(gitDir, "objects", "info"), { recursive: true });
316
387
  await mkdir(join(gitDir, "objects", "pack"), { recursive: true });
@@ -336,7 +407,7 @@ async function ensureLocalKnowledgeGitRepository(knowledgeDir) {
336
407
  `));
337
408
  }
338
409
  async function writeTextIfMissing(path, value) {
339
- if (await pathExists(path))
410
+ if (await pathExists2(path))
340
411
  return;
341
412
  await mkdir(dirname(path), { recursive: true });
342
413
  await writeFile(path, value, { encoding: "utf8", flag: "wx" });
@@ -349,7 +420,7 @@ async function ensureOkfDirectory(okfDir, relativeDir, title, description) {
349
420
  await mkdir(dir, { recursive: true });
350
421
  const isRoot = dir === okfDir;
351
422
  const indexPath = join(dir, "index.md");
352
- if (!await pathExists(indexPath)) {
423
+ if (!await pathExists2(indexPath)) {
353
424
  await writeFile(indexPath, isRoot ? [
354
425
  "---",
355
426
  `okf_version: ${yamlString("0.1")}`,
@@ -366,7 +437,7 @@ async function ensureOkfDirectory(okfDir, relativeDir, title, description) {
366
437
  `), "utf8");
367
438
  }
368
439
  const logPath = join(dir, "log.md");
369
- if (!await pathExists(logPath)) {
440
+ if (!await pathExists2(logPath)) {
370
441
  await writeFile(logPath, [
371
442
  "# Directory Update Log",
372
443
  "",
@@ -473,13 +544,13 @@ function isLifecycleDateDue(value, now) {
473
544
  }
474
545
  function createDefaultOkfLifecycle(input) {
475
546
  const createdAt = normalizeIsoDateString(input.createdAt) ?? "1970-01-01T00:00:00.000Z";
476
- const policy = resolveOkfLifecyclePolicy(input);
547
+ const policy2 = resolveOkfLifecyclePolicy(input);
477
548
  return {
478
549
  status: lifecycleStatusFromReviewState(input.reviewState),
479
550
  createdAt,
480
551
  lastVerifiedAt: createdAt,
481
- reviewAfter: addDaysIso(createdAt, policy.reviewAfterDays),
482
- staleAfter: addDaysIso(createdAt, policy.staleAfterDays),
552
+ reviewAfter: addDaysIso(createdAt, policy2.reviewAfterDays),
553
+ staleAfter: addDaysIso(createdAt, policy2.staleAfterDays),
483
554
  supersedes: [],
484
555
  supersededBy: null,
485
556
  revokedAt: null,
@@ -537,10 +608,10 @@ function isOkfLifecycleStatus(value) {
537
608
  function normalizeIsoDateString(value) {
538
609
  if (value === undefined || value === null || value === "" || value === "null")
539
610
  return null;
540
- const time = Date.parse(value);
541
- if (!Number.isFinite(time))
611
+ const time2 = Date.parse(value);
612
+ if (!Number.isFinite(time2))
542
613
  return null;
543
- return new Date(time).toISOString();
614
+ return new Date(time2).toISOString();
544
615
  }
545
616
  function addDaysIso(value, days) {
546
617
  const date = new Date(value);
@@ -641,7 +712,7 @@ function parseYamlValue(value) {
641
712
  return trimmed.replace(/^['"]|['"]$/gu, "");
642
713
  }
643
714
  async function listMarkdownFiles(root) {
644
- if (!await pathExists(root))
715
+ if (!await pathExists2(root))
645
716
  return [];
646
717
  const entries = await readdir(root, { withFileTypes: true });
647
718
  const files = [];
@@ -694,13 +765,13 @@ function escapeRegExp(value) {
694
765
  function todayIsoDate() {
695
766
  return new Date().toISOString().slice(0, 10);
696
767
  }
697
- async function writeJson(path, value, options = {}) {
768
+ async function writeJson2(path, value, options = {}) {
698
769
  await mkdir(dirname(path), { recursive: true });
699
770
  const flag = options.overwrite === true ? "w" : "wx";
700
771
  await writeFile(path, `${JSON.stringify(value, null, 2)}
701
772
  `, { encoding: "utf8", flag });
702
773
  }
703
- async function pathExists(path) {
774
+ async function pathExists2(path) {
704
775
  try {
705
776
  await stat(path);
706
777
  return true;
@@ -711,43 +782,6 @@ async function pathExists(path) {
711
782
  }
712
783
  }
713
784
 
714
- // packages/core/src/evolution/index.ts
715
- var PROCESS_LOCK_STALE_MS = 5 * 60 * 1000;
716
- var FORBIDDEN_RAW_KEYS = new Set([
717
- "commandhistory",
718
- "commandoutput",
719
- "credential",
720
- "credentials",
721
- "env",
722
- "fullsource",
723
- "memorybody",
724
- "password",
725
- "privatekey",
726
- "prompt",
727
- "promptbody",
728
- "prompttext",
729
- "rawcommand",
730
- "rawcommandoutput",
731
- "rawlog",
732
- "rawlogs",
733
- "rawoutput",
734
- "rawpayload",
735
- "rawprompt",
736
- "secret",
737
- "secretvalue",
738
- "source",
739
- "sourcebody",
740
- "sourcecode",
741
- "sourcecontent",
742
- "sourcetext",
743
- "stderr",
744
- "stdout",
745
- "token",
746
- "transcript",
747
- "transcriptbody",
748
- "transcripttext"
749
- ]);
750
-
751
785
  // packages/core/src/task/index.ts
752
786
  var FORBIDDEN_TASK_WRITE_SEGMENTS = new Set([".claude", ".codex"]);
753
787
  var FORBIDDEN_PROJECT_ASSET_SEGMENTS = new Set(["packages", "src"]);
@@ -848,6 +882,23 @@ var TEAM_INTERNAL_WAKE_SIGNAL = [
848
882
  "No user request is included in this message. Continue only from EvoDev team inbox messages injected by hooks."
849
883
  ].join(`
850
884
  `);
885
+ var BUILT_IN_TEAM_DEFINITION = {
886
+ version: 1,
887
+ name: "builtin-minimal-team",
888
+ description: "Built-in minimal EvoDev team fallback.",
889
+ agents: {
890
+ executor: "builtin:executor",
891
+ reviewer: "builtin:reviewer",
892
+ tester: "builtin:tester"
893
+ },
894
+ body: [
895
+ "# Built-in Minimal Team",
896
+ "",
897
+ "Use role agents only when delegation improves correctness, coverage, safety, or latency.",
898
+ "Spawn roles on demand and send self-contained assignments through Teams MCP."
899
+ ].join(`
900
+ `)
901
+ };
851
902
 
852
903
  // packages/core/src/hooks/index.ts
853
904
  var CANONICAL_HOOK_EVENT_TYPES = [
@@ -947,10 +998,10 @@ function parseHookSettings(value) {
947
998
  if (!isRecord(value))
948
999
  throw new Error("Invalid hooks settings; expected object.");
949
1000
  const observability = isRecord(value.observability) ? value.observability : undefined;
950
- optionalBoolean(observability?.metadataOnly, defaults.observability.metadataOnly, "hooks.observability.metadataOnly");
951
- optionalBoolean(observability?.rawPayloadStorage, defaults.observability.rawPayloadStorage, "hooks.observability.rawPayloadStorage");
1001
+ optionalBoolean2(observability?.metadataOnly, defaults.observability.metadataOnly, "hooks.observability.metadataOnly");
1002
+ optionalBoolean2(observability?.rawPayloadStorage, defaults.observability.rawPayloadStorage, "hooks.observability.rawPayloadStorage");
952
1003
  return {
953
- enabled: optionalBoolean(value.enabled, defaults.enabled, "hooks.enabled"),
1004
+ enabled: optionalBoolean2(value.enabled, defaults.enabled, "hooks.enabled"),
954
1005
  targets: {
955
1006
  claude: parseHookTargetSettings(value.targets, defaults.targets.claude, "claude"),
956
1007
  codex: parseHookTargetSettings(value.targets, defaults.targets.codex, "codex")
@@ -958,7 +1009,7 @@ function parseHookSettings(value) {
958
1009
  observability: {
959
1010
  metadataOnly: true,
960
1011
  rawPayloadStorage: false,
961
- appendEvents: optionalBoolean(observability?.appendEvents, defaults.observability.appendEvents, "hooks.observability.appendEvents")
1012
+ appendEvents: optionalBoolean2(observability?.appendEvents, defaults.observability.appendEvents, "hooks.observability.appendEvents")
962
1013
  },
963
1014
  learning: {
964
1015
  emitCandidates: false,
@@ -972,14 +1023,14 @@ function parseHookTargetSettings(value, defaults, target) {
972
1023
  const events = isRecord(targetSettings.events) ? targetSettings.events : {};
973
1024
  const parsedEvents = { ...defaults.events };
974
1025
  for (const eventType of CANONICAL_HOOK_EVENT_TYPES) {
975
- parsedEvents[eventType] = optionalBoolean(events[eventType], defaults.events[eventType], `hooks.targets.${target}.events.${eventType}`);
1026
+ parsedEvents[eventType] = optionalBoolean2(events[eventType], defaults.events[eventType], `hooks.targets.${target}.events.${eventType}`);
976
1027
  }
977
1028
  return {
978
- enabled: optionalBoolean(targetSettings.enabled, defaults.enabled, `hooks.targets.${target}.enabled`),
1029
+ enabled: optionalBoolean2(targetSettings.enabled, defaults.enabled, `hooks.targets.${target}.enabled`),
979
1030
  events: parsedEvents
980
1031
  };
981
1032
  }
982
- function optionalBoolean(value, fallback, path) {
1033
+ function optionalBoolean2(value, fallback, path) {
983
1034
  if (value === undefined)
984
1035
  return fallback;
985
1036
  if (typeof value !== "boolean")
@@ -1037,7 +1088,8 @@ function createDefaultMemorySettings() {
1037
1088
  autoAccept: true,
1038
1089
  runtimeInjection: true,
1039
1090
  staleReview: true,
1040
- lexicalIndex: true
1091
+ lexicalIndex: true,
1092
+ sessionMemory: createDefaultSessionMemoryPolicy()
1041
1093
  };
1042
1094
  }
1043
1095
  function mergeSettings(existing, defaults = createDefaultSettings()) {
@@ -1085,11 +1137,11 @@ function mergeSettings(existing, defaults = createDefaultSettings()) {
1085
1137
  return parseSettings(merged);
1086
1138
  }
1087
1139
  async function readRuntimeInjectionSettings(homeDir) {
1088
- const paths = resolveEvoDevPaths(homeDir);
1140
+ const paths2 = resolveEvoDevPaths(homeDir);
1089
1141
  try {
1090
- return parseSettings(JSON.parse(await readFile2(paths.settingsPath, "utf8"))).memory;
1142
+ return parseSettings(JSON.parse(await readFile2(paths2.settingsPath, "utf8"))).memory;
1091
1143
  } catch (error) {
1092
- if (isNotFoundError(error))
1144
+ if (isNotFoundError2(error))
1093
1145
  return createDefaultMemorySettings();
1094
1146
  throw error;
1095
1147
  }
@@ -1137,7 +1189,8 @@ function parseMemorySettings(value, path) {
1137
1189
  autoAccept: input.autoAccept === undefined ? defaults.autoAccept : expectBoolean(input.autoAccept, `${path}.autoAccept`),
1138
1190
  runtimeInjection: input.runtimeInjection === undefined ? defaults.runtimeInjection : expectBoolean(input.runtimeInjection, `${path}.runtimeInjection`),
1139
1191
  staleReview: input.staleReview === undefined ? defaults.staleReview : expectBoolean(input.staleReview, `${path}.staleReview`),
1140
- lexicalIndex: input.lexicalIndex === undefined ? defaults.lexicalIndex : expectBoolean(input.lexicalIndex, `${path}.lexicalIndex`)
1192
+ lexicalIndex: input.lexicalIndex === undefined ? defaults.lexicalIndex : expectBoolean(input.lexicalIndex, `${path}.lexicalIndex`),
1193
+ sessionMemory: parseSessionMemoryPolicy(isPlainRecord(input.sessionMemory) ? input.sessionMemory : defaults.sessionMemory)
1141
1194
  };
1142
1195
  }
1143
1196
  function parseTeamRuntimeSettings(value, path) {
@@ -1181,7 +1234,10 @@ function expectRecord2(value, path) {
1181
1234
  }
1182
1235
  return value;
1183
1236
  }
1184
- function isNotFoundError(error) {
1237
+ function isPlainRecord(value) {
1238
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1239
+ }
1240
+ function isNotFoundError2(error) {
1185
1241
  return error instanceof Error && "code" in error && error.code === "ENOENT";
1186
1242
  }
1187
1243
  function expectString2(value, path) {
@@ -1286,50 +1342,50 @@ function expectNonNegativeInteger(value, path) {
1286
1342
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
1287
1343
  import { dirname as dirname2 } from "node:path";
1288
1344
  function createCoreConfigStore(homeDir) {
1289
- const paths = resolveEvoDevPaths(homeDir);
1345
+ const paths2 = resolveEvoDevPaths(homeDir);
1290
1346
  return {
1291
- paths,
1347
+ paths: paths2,
1292
1348
  async ensureBaseDirs() {
1293
- await mkdir2(paths.stateDir, { recursive: true });
1294
- await mkdir2(paths.logsDir, { recursive: true });
1295
- await mkdir2(paths.knowledgeDir, { recursive: true });
1296
- await mkdir2(paths.evosCasesDir, { recursive: true });
1297
- await mkdir2(paths.roleAgentsDir, { recursive: true });
1298
- await mkdir2(paths.teamsDir, { recursive: true });
1299
- await mkdir2(paths.runsDir, { recursive: true });
1349
+ await mkdir2(paths2.stateDir, { recursive: true });
1350
+ await mkdir2(paths2.logsDir, { recursive: true });
1351
+ await mkdir2(paths2.knowledgeDir, { recursive: true });
1352
+ await mkdir2(paths2.evosCasesDir, { recursive: true });
1353
+ await mkdir2(paths2.roleAgentsDir, { recursive: true });
1354
+ await mkdir2(paths2.teamsDir, { recursive: true });
1355
+ await mkdir2(paths2.runsDir, { recursive: true });
1300
1356
  },
1301
1357
  async ensureKnowledgeBase() {
1302
- await ensureKnowledgeBaseFiles(paths);
1358
+ await ensureKnowledgeBaseFiles(paths2);
1303
1359
  },
1304
1360
  async readSettings() {
1305
- return readJsonFile(paths.settingsPath, parseSettings);
1361
+ return readJsonFile(paths2.settingsPath, parseSettings);
1306
1362
  },
1307
1363
  async writeSettings(settings) {
1308
- await writeJsonFile(paths.settingsPath, parseSettings(settings));
1364
+ await writeJsonFile2(paths2.settingsPath, parseSettings(settings));
1309
1365
  },
1310
1366
  async mergeAndWriteSettings(input) {
1311
- const current = await readJsonFileOrDefault(paths.settingsPath, parseSettings, createDefaultSettings());
1367
+ const current = await readJsonFileOrDefault(paths2.settingsPath, parseSettings, createDefaultSettings());
1312
1368
  const merged = mergeSettings(input, current);
1313
- await writeJsonFile(paths.settingsPath, merged);
1369
+ await writeJsonFile2(paths2.settingsPath, merged);
1314
1370
  return merged;
1315
1371
  },
1316
1372
  async readRegistry() {
1317
- return readJsonFile(paths.registryPath, parseRegistry);
1373
+ return readJsonFile(paths2.registryPath, parseRegistry);
1318
1374
  },
1319
1375
  async writeRegistry(registry) {
1320
- await writeJsonFile(paths.registryPath, parseRegistry(registry));
1376
+ await writeJsonFile2(paths2.registryPath, parseRegistry(registry));
1321
1377
  },
1322
1378
  async readInstallState() {
1323
- return readJsonFile(paths.installStatePath, parseInstallState);
1379
+ return readJsonFile(paths2.installStatePath, parseInstallState);
1324
1380
  },
1325
1381
  async writeInstallState(state) {
1326
- await writeJsonFile(paths.installStatePath, parseInstallState(state));
1382
+ await writeJsonFile2(paths2.installStatePath, parseInstallState(state));
1327
1383
  },
1328
1384
  async readSyncState() {
1329
- return readJsonFile(paths.syncStatePath, parseSyncState);
1385
+ return readJsonFile(paths2.syncStatePath, parseSyncState);
1330
1386
  },
1331
1387
  async writeSyncState(state) {
1332
- await writeJsonFile(paths.syncStatePath, parseSyncState(state));
1388
+ await writeJsonFile2(paths2.syncStatePath, parseSyncState(state));
1333
1389
  }
1334
1390
  };
1335
1391
  }
@@ -1343,11 +1399,11 @@ async function initializeCoreConfig(homeDir) {
1343
1399
  await writeIfMissing(store.paths.syncStatePath, createDefaultSyncState());
1344
1400
  return store;
1345
1401
  }
1346
- async function ensureKnowledgeBaseFiles(paths) {
1347
- await mkdir2(paths.knowledgeDir, { recursive: true });
1348
- await mkdir2(paths.evosCasesDir, { recursive: true });
1349
- await ensureOkfKnowledgeBase(paths.homeDir);
1350
- await writeTextIfMissing2(`${paths.knowledgeDir}/README.md`, [
1402
+ async function ensureKnowledgeBaseFiles(paths2) {
1403
+ await mkdir2(paths2.knowledgeDir, { recursive: true });
1404
+ await mkdir2(paths2.evosCasesDir, { recursive: true });
1405
+ await ensureOkfKnowledgeBase(paths2.homeDir);
1406
+ await writeTextIfMissing2(`${paths2.knowledgeDir}/README.md`, [
1351
1407
  "# EvoDev Knowledge",
1352
1408
  "",
1353
1409
  "Local-private knowledge base for user-accepted facts, decisions, architecture notes, and reusable domain context.",
@@ -1356,13 +1412,13 @@ async function ensureKnowledgeBaseFiles(paths) {
1356
1412
  ""
1357
1413
  ].join(`
1358
1414
  `));
1359
- await writeIndexIfMissingOrMigrate(paths.knowledgeIndexPath, "knowledge-index", {
1415
+ await writeIndexIfMissingOrMigrate(paths2.knowledgeIndexPath, "knowledge-index", {
1360
1416
  version: 1,
1361
1417
  kind: "knowledge-index",
1362
1418
  roleTags: [],
1363
1419
  entries: []
1364
1420
  });
1365
- await writeTextIfMissing2(`${paths.evosDir}/README.md`, [
1421
+ await writeTextIfMissing2(`${paths2.evosDir}/README.md`, [
1366
1422
  "# EvoDev Evos",
1367
1423
  "",
1368
1424
  "Local-private evolution case library for reviewed improvement cases and reusable process changes.",
@@ -1371,20 +1427,20 @@ async function ensureKnowledgeBaseFiles(paths) {
1371
1427
  ""
1372
1428
  ].join(`
1373
1429
  `));
1374
- await writeTextIfMissing2(`${paths.evosCasesDir}/README.md`, [
1430
+ await writeTextIfMissing2(`${paths2.evosCasesDir}/README.md`, [
1375
1431
  "# Evolution Cases",
1376
1432
  "",
1377
1433
  "Store one reviewed evolution case per file. Do not store raw prompts, source dumps, secrets, transcripts, or raw command output here.",
1378
1434
  ""
1379
1435
  ].join(`
1380
1436
  `));
1381
- await writeIndexIfMissingOrMigrate(paths.evosIndexPath, "evos-index", {
1437
+ await writeIndexIfMissingOrMigrate(paths2.evosIndexPath, "evos-index", {
1382
1438
  version: 1,
1383
1439
  kind: "evos-index",
1384
1440
  roleTags: [],
1385
1441
  cases: []
1386
1442
  });
1387
- await writeTextIfMissing2(`${paths.roleAgentsDir}/README.md`, [
1443
+ await writeTextIfMissing2(`${paths2.roleAgentsDir}/README.md`, [
1388
1444
  "# Role Agents",
1389
1445
  "",
1390
1446
  "Local-private role agent registry for EvoDev-managed agent roles and user-reviewed role extensions.",
@@ -1393,13 +1449,13 @@ async function ensureKnowledgeBaseFiles(paths) {
1393
1449
  ""
1394
1450
  ].join(`
1395
1451
  `));
1396
- await writeIndexIfMissingOrMigrate(paths.roleAgentsIndexPath, "role-agent-index", {
1452
+ await writeIndexIfMissingOrMigrate(paths2.roleAgentsIndexPath, "role-agent-index", {
1397
1453
  version: 1,
1398
1454
  kind: "role-agent-index",
1399
1455
  roles: [],
1400
1456
  projectExtensions: []
1401
1457
  });
1402
- await writeTextIfMissing2(`${paths.teamsDir}/README.md`, [
1458
+ await writeTextIfMissing2(`${paths2.teamsDir}/README.md`, [
1403
1459
  "# Agent Teams",
1404
1460
  "",
1405
1461
  "Local-private EvoHub team registry for reviewed role-agent team definitions.",
@@ -1408,7 +1464,7 @@ async function ensureKnowledgeBaseFiles(paths) {
1408
1464
  ""
1409
1465
  ].join(`
1410
1466
  `));
1411
- await writeIndexIfMissingOrMigrate(paths.teamsIndexPath, "agent-team-index", {
1467
+ await writeIndexIfMissingOrMigrate(paths2.teamsIndexPath, "agent-team-index", {
1412
1468
  version: 1,
1413
1469
  kind: "agent-team-index",
1414
1470
  teams: []
@@ -1451,7 +1507,7 @@ async function writeIfMissing(filePath, value) {
1451
1507
  await readFile3(filePath, "utf8");
1452
1508
  } catch (error) {
1453
1509
  if (isNodeError(error) && error.code === "ENOENT") {
1454
- await writeJsonFile(filePath, value);
1510
+ await writeJsonFile2(filePath, value);
1455
1511
  return;
1456
1512
  }
1457
1513
  throw new EvoDevConfigError(`Cannot inspect config file (${describeFileError(error)})`, filePath);
@@ -1463,7 +1519,7 @@ async function writeIndexIfMissingOrMigrate(filePath, kind, defaults) {
1463
1519
  raw = await readFile3(filePath, "utf8");
1464
1520
  } catch (error) {
1465
1521
  if (isNodeError(error) && error.code === "ENOENT") {
1466
- await writeJsonFile(filePath, defaults);
1522
+ await writeJsonFile2(filePath, defaults);
1467
1523
  return;
1468
1524
  }
1469
1525
  throw new EvoDevConfigError(`Cannot inspect config file (${describeFileError(error)})`, filePath);
@@ -1479,7 +1535,7 @@ async function writeIndexIfMissingOrMigrate(filePath, kind, defaults) {
1479
1535
  const migrated = { ...defaults, ...existing };
1480
1536
  if (Object.keys(defaults).every((key) => (key in existing)))
1481
1537
  return;
1482
- await writeJsonFile(filePath, migrated);
1538
+ await writeJsonFile2(filePath, migrated);
1483
1539
  }
1484
1540
  async function writeTextIfMissing2(filePath, value) {
1485
1541
  try {
@@ -1493,7 +1549,7 @@ async function writeTextIfMissing2(filePath, value) {
1493
1549
  throw new EvoDevConfigError(`Cannot inspect config file (${describeFileError(error)})`, filePath);
1494
1550
  }
1495
1551
  }
1496
- async function writeJsonFile(filePath, value) {
1552
+ async function writeJsonFile2(filePath, value) {
1497
1553
  await mkdir2(dirname2(filePath), { recursive: true });
1498
1554
  await writeFile2(filePath, `${JSON.stringify(value, null, 2)}
1499
1555
  `, "utf8");