gencode-ai 0.2.0 → 0.3.0

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 (150) hide show
  1. package/dist/agent/agent.d.ts +9 -2
  2. package/dist/agent/agent.d.ts.map +1 -1
  3. package/dist/agent/agent.js +37 -8
  4. package/dist/agent/agent.js.map +1 -1
  5. package/dist/agent/types.d.ts +5 -1
  6. package/dist/agent/types.d.ts.map +1 -1
  7. package/dist/cli/components/App.d.ts.map +1 -1
  8. package/dist/cli/components/App.js +15 -9
  9. package/dist/cli/components/App.js.map +1 -1
  10. package/dist/cli/components/Messages.js +1 -1
  11. package/dist/cli/components/Messages.js.map +1 -1
  12. package/dist/cli/components/ModelSelector.d.ts +4 -3
  13. package/dist/cli/components/ModelSelector.d.ts.map +1 -1
  14. package/dist/cli/components/ModelSelector.js +54 -37
  15. package/dist/cli/components/ModelSelector.js.map +1 -1
  16. package/dist/cli/components/ProviderManager.d.ts +2 -2
  17. package/dist/cli/components/ProviderManager.d.ts.map +1 -1
  18. package/dist/cli/components/ProviderManager.js +137 -156
  19. package/dist/cli/components/ProviderManager.js.map +1 -1
  20. package/dist/cli/index.js +30 -13
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/config/index.d.ts +2 -2
  23. package/dist/config/index.d.ts.map +1 -1
  24. package/dist/config/index.js +1 -1
  25. package/dist/config/index.js.map +1 -1
  26. package/dist/config/levels.d.ts +5 -5
  27. package/dist/config/levels.d.ts.map +1 -1
  28. package/dist/config/levels.js +20 -20
  29. package/dist/config/levels.js.map +1 -1
  30. package/dist/config/merger.js +1 -1
  31. package/dist/config/merger.js.map +1 -1
  32. package/dist/config/providers-config.d.ts +8 -5
  33. package/dist/config/providers-config.d.ts.map +1 -1
  34. package/dist/config/providers-config.js +19 -22
  35. package/dist/config/providers-config.js.map +1 -1
  36. package/dist/config/test-utils.d.ts +2 -2
  37. package/dist/config/test-utils.d.ts.map +1 -1
  38. package/dist/config/test-utils.js +4 -4
  39. package/dist/config/test-utils.js.map +1 -1
  40. package/dist/config/types.d.ts +23 -17
  41. package/dist/config/types.d.ts.map +1 -1
  42. package/dist/config/types.js +14 -14
  43. package/dist/config/types.js.map +1 -1
  44. package/dist/memory/memory-manager.d.ts +25 -12
  45. package/dist/memory/memory-manager.d.ts.map +1 -1
  46. package/dist/memory/memory-manager.js +241 -112
  47. package/dist/memory/memory-manager.js.map +1 -1
  48. package/dist/memory/test-utils.d.ts +1 -1
  49. package/dist/memory/test-utils.d.ts.map +1 -1
  50. package/dist/memory/test-utils.js +3 -3
  51. package/dist/memory/test-utils.js.map +1 -1
  52. package/dist/memory/types.d.ts +20 -10
  53. package/dist/memory/types.d.ts.map +1 -1
  54. package/dist/memory/types.js +13 -13
  55. package/dist/memory/types.js.map +1 -1
  56. package/dist/migration/migrate.d.ts +24 -0
  57. package/dist/migration/migrate.d.ts.map +1 -0
  58. package/dist/migration/migrate.js +164 -0
  59. package/dist/migration/migrate.js.map +1 -0
  60. package/dist/permissions/persistence.d.ts +2 -2
  61. package/dist/permissions/persistence.js +4 -4
  62. package/dist/permissions/persistence.js.map +1 -1
  63. package/dist/planning/plan-file.d.ts +1 -1
  64. package/dist/planning/plan-file.js +2 -2
  65. package/dist/planning/plan-file.js.map +1 -1
  66. package/dist/prompts/index.d.ts +5 -4
  67. package/dist/prompts/index.d.ts.map +1 -1
  68. package/dist/prompts/index.js +11 -8
  69. package/dist/prompts/index.js.map +1 -1
  70. package/dist/providers/anthropic.d.ts +2 -1
  71. package/dist/providers/anthropic.d.ts.map +1 -1
  72. package/dist/providers/anthropic.js +7 -0
  73. package/dist/providers/anthropic.js.map +1 -1
  74. package/dist/providers/gemini.d.ts +2 -1
  75. package/dist/providers/gemini.d.ts.map +1 -1
  76. package/dist/providers/gemini.js +7 -0
  77. package/dist/providers/gemini.js.map +1 -1
  78. package/dist/providers/index.d.ts +20 -10
  79. package/dist/providers/index.d.ts.map +1 -1
  80. package/dist/providers/index.js +48 -24
  81. package/dist/providers/index.js.map +1 -1
  82. package/dist/providers/openai.d.ts +2 -1
  83. package/dist/providers/openai.d.ts.map +1 -1
  84. package/dist/providers/openai.js +7 -0
  85. package/dist/providers/openai.js.map +1 -1
  86. package/dist/providers/registry.d.ts +48 -34
  87. package/dist/providers/registry.d.ts.map +1 -1
  88. package/dist/providers/registry.js +72 -88
  89. package/dist/providers/registry.js.map +1 -1
  90. package/dist/providers/store.d.ts +43 -17
  91. package/dist/providers/store.d.ts.map +1 -1
  92. package/dist/providers/store.js +112 -19
  93. package/dist/providers/store.js.map +1 -1
  94. package/dist/providers/types.d.ts +23 -0
  95. package/dist/providers/types.d.ts.map +1 -1
  96. package/dist/providers/vertex-ai.d.ts +15 -7
  97. package/dist/providers/vertex-ai.d.ts.map +1 -1
  98. package/dist/providers/vertex-ai.js +46 -13
  99. package/dist/providers/vertex-ai.js.map +1 -1
  100. package/dist/session/types.js +1 -1
  101. package/dist/session/types.js.map +1 -1
  102. package/docs/config-system-comparison.md +50 -50
  103. package/docs/cost-tracking-comparison.md +2 -2
  104. package/docs/memory-system.md +124 -31
  105. package/docs/permissions.md +2 -2
  106. package/docs/proposals/0006-memory-system.md +4 -4
  107. package/docs/proposals/0008-checkpointing.md +109 -2
  108. package/docs/proposals/0011-custom-commands.md +2 -1
  109. package/docs/proposals/0021-skills-system.md +2 -1
  110. package/docs/proposals/0023-permission-enhancements.md +2 -2
  111. package/docs/proposals/0033-enterprise-deployment.md +1 -1
  112. package/docs/proposals/0041-configuration-system.md +17 -19
  113. package/docs/proposals/0042-prompt-optimization.md +17 -9
  114. package/docs/proposals/README.md +5 -5
  115. package/docs/providers.md +94 -9
  116. package/package.json +3 -2
  117. package/scripts/migrate.ts +449 -0
  118. package/src/agent/agent.ts +51 -9
  119. package/src/agent/types.ts +5 -1
  120. package/src/cli/components/App.tsx +17 -8
  121. package/src/cli/components/Messages.tsx +1 -1
  122. package/src/cli/components/ModelSelector.tsx +62 -43
  123. package/src/cli/components/ProviderManager.tsx +278 -323
  124. package/src/cli/index.tsx +36 -17
  125. package/src/config/index.ts +5 -3
  126. package/src/config/levels.test.ts +22 -22
  127. package/src/config/levels.ts +22 -22
  128. package/src/config/loader.test.ts +14 -14
  129. package/src/config/manager.test.ts +19 -19
  130. package/src/config/merger.test.ts +23 -23
  131. package/src/config/merger.ts +1 -1
  132. package/src/config/providers-config.ts +23 -21
  133. package/src/config/test-utils.ts +6 -6
  134. package/src/config/types.ts +30 -20
  135. package/src/memory/memory-manager.test.ts +242 -24
  136. package/src/memory/memory-manager.ts +270 -141
  137. package/src/memory/test-utils.ts +4 -4
  138. package/src/memory/types.ts +28 -17
  139. package/src/permissions/persistence.ts +4 -4
  140. package/src/planning/plan-file.ts +2 -2
  141. package/src/prompts/index.ts +13 -9
  142. package/src/providers/anthropic.ts +9 -0
  143. package/src/providers/gemini.ts +9 -0
  144. package/src/providers/index.ts +76 -33
  145. package/src/providers/openai.ts +9 -0
  146. package/src/providers/registry.ts +116 -111
  147. package/src/providers/store.ts +130 -28
  148. package/src/providers/types.ts +33 -1
  149. package/src/providers/vertex-ai.ts +49 -13
  150. package/src/session/types.ts +1 -1
@@ -2,18 +2,18 @@
2
2
  * Memory Manager - Core memory system implementation
3
3
  *
4
4
  * Implements Claude Code compatible memory loading with merge semantics:
5
- * At each level, both .gencode and .claude directories are loaded.
6
- * Content from .gencode appears later in the context (higher priority for LLM).
5
+ * At each level, both .gen and .claude directories are loaded.
6
+ * Content from .gen appears later in the context (higher priority for LLM).
7
7
  *
8
8
  * Loading order within each level:
9
9
  * 1. .claude files first (lower priority - LLM sees earlier)
10
- * 2. .gencode files second (higher priority - LLM sees later)
10
+ * 2. .gen files second (higher priority - LLM sees later)
11
11
  *
12
12
  * Level loading order:
13
13
  * 1. Enterprise (system-wide managed, enforced)
14
- * 2. User (~/.gencode/ + ~/.claude/)
14
+ * 2. User (~/.gen/ + ~/.claude/)
15
15
  * 3. User Rules
16
- * 4. Extra (GENCODE_CONFIG_DIRS)
16
+ * 4. Extra (GEN_CONFIG)
17
17
  * 5. Project (recursive upward search)
18
18
  * 6. Project Rules
19
19
  * 7. Local (*.local.md files)
@@ -25,7 +25,7 @@ import { glob } from 'glob';
25
25
  import { ImportResolver } from './import-resolver.js';
26
26
  import { parseRuleFrontmatter, activateRules } from './rules-parser.js';
27
27
  import { DEFAULT_MEMORY_CONFIG } from './types.js';
28
- import { getManagedPaths, GENCODE_CONFIG_DIRS_ENV } from '../config/types.js';
28
+ import { getManagedPaths, GEN_CONFIG_ENV } from '../config/types.js';
29
29
  export class MemoryManager {
30
30
  config;
31
31
  importResolver;
@@ -39,18 +39,19 @@ export class MemoryManager {
39
39
  * Load all memory files for the given working directory
40
40
  */
41
41
  async load(options) {
42
- const { cwd, currentFile } = options;
42
+ const { cwd, currentFile, strategy = 'fallback' } = options;
43
43
  const files = [];
44
44
  const rules = [];
45
45
  const errors = [];
46
46
  const sources = [];
47
+ const skippedFiles = [];
47
48
  let totalSize = 0;
48
49
  this.importResolver.reset();
49
50
  const projectRoot = await this.findProjectRoot(cwd);
50
51
  this.importResolver.setProjectRoot(projectRoot);
51
52
  // 1. Load enterprise memory (system-wide, enforced)
52
- const enterpriseFiles = await this.loadEnterpriseMemory();
53
- for (const file of enterpriseFiles) {
53
+ const enterpriseResult = await this.loadEnterpriseMemory(strategy);
54
+ for (const file of enterpriseResult.files) {
54
55
  files.push(file);
55
56
  totalSize += file.content.length;
56
57
  sources.push({
@@ -61,8 +62,10 @@ export class MemoryManager {
61
62
  size: file.content.length,
62
63
  });
63
64
  }
64
- // 2. Load user-level memory (both claude and gencode)
65
- const userFiles = await this.loadUserMemory();
65
+ skippedFiles.push(...enterpriseResult.skipped);
66
+ // 2. Load user-level memory (both claude and gen)
67
+ const userResult = await this.loadUserMemory(strategy);
68
+ const userFiles = userResult.files;
66
69
  for (const file of userFiles) {
67
70
  if (totalSize + file.content.length <= this.config.maxTotalSize) {
68
71
  files.push(file);
@@ -79,7 +82,8 @@ export class MemoryManager {
79
82
  errors.push(`Skipped ${file.path}: would exceed max total size`);
80
83
  }
81
84
  }
82
- // 3. Load user-level rules (both claude and gencode)
85
+ skippedFiles.push(...userResult.skipped);
86
+ // 3. Load user-level rules (both claude and gen)
83
87
  const userRules = await this.loadUserRules();
84
88
  for (const rule of userRules) {
85
89
  rules.push(rule);
@@ -92,7 +96,8 @@ export class MemoryManager {
92
96
  });
93
97
  }
94
98
  // 4. Load extra config dirs memory
95
- const extraFiles = await this.loadExtraMemory();
99
+ const extraResult = await this.loadExtraMemory(strategy);
100
+ const extraFiles = extraResult.files;
96
101
  for (const file of extraFiles) {
97
102
  if (totalSize + file.content.length <= this.config.maxTotalSize) {
98
103
  files.push(file);
@@ -109,8 +114,10 @@ export class MemoryManager {
109
114
  errors.push(`Skipped ${file.path}: would exceed max total size`);
110
115
  }
111
116
  }
112
- // 5. Load project-level memory (both claude and gencode, recursive upward)
113
- const projectFiles = await this.loadProjectMemory(cwd, projectRoot);
117
+ skippedFiles.push(...extraResult.skipped);
118
+ // 5. Load project-level memory (both claude and gen, recursive upward)
119
+ const projectResult = await this.loadProjectMemory(cwd, projectRoot, strategy);
120
+ const projectFiles = projectResult.files;
114
121
  for (const file of projectFiles) {
115
122
  if (totalSize + file.content.length <= this.config.maxTotalSize) {
116
123
  files.push(file);
@@ -127,7 +134,8 @@ export class MemoryManager {
127
134
  errors.push(`Skipped ${file.path}: would exceed max total size`);
128
135
  }
129
136
  }
130
- // 6. Load project-level rules (both claude and gencode)
137
+ skippedFiles.push(...projectResult.skipped);
138
+ // 6. Load project-level rules (both claude and gen)
131
139
  const projectRules = await this.loadProjectRules(projectRoot);
132
140
  for (const rule of projectRules) {
133
141
  rules.push(rule);
@@ -139,8 +147,9 @@ export class MemoryManager {
139
147
  size: rule.content.length,
140
148
  });
141
149
  }
142
- // 7. Load local memory (both claude and gencode)
143
- const localFiles = await this.loadLocalMemory(projectRoot);
150
+ // 7. Load local memory (both claude and gen)
151
+ const localResult = await this.loadLocalMemory(projectRoot, strategy);
152
+ const localFiles = localResult.files;
144
153
  for (const file of localFiles) {
145
154
  if (totalSize + file.content.length <= this.config.maxTotalSize) {
146
155
  files.push(file);
@@ -157,6 +166,7 @@ export class MemoryManager {
157
166
  errors.push(`Skipped ${file.path}: would exceed max total size`);
158
167
  }
159
168
  }
169
+ skippedFiles.push(...localResult.skipped);
160
170
  // Activate rules based on current file
161
171
  const activatedRules = activateRules(rules, currentFile);
162
172
  // Build combined context
@@ -168,6 +178,7 @@ export class MemoryManager {
168
178
  context,
169
179
  errors,
170
180
  sources,
181
+ skippedFiles,
171
182
  };
172
183
  return this.loadedMemory;
173
184
  }
@@ -216,47 +227,112 @@ export class MemoryManager {
216
227
  'project-rules': 'project rules',
217
228
  local: 'local personal notes',
218
229
  };
219
- const namespaceLabel = namespace === 'gencode' ? 'gencode' : namespace === 'claude' ? 'claude' : 'extra';
230
+ const namespaceLabel = namespace === 'gen' ? 'gen' : namespace === 'claude' ? 'claude' : 'extra';
220
231
  return `${levelLabels[level]} - ${namespaceLabel}`;
221
232
  }
222
233
  /**
223
- * Load enterprise-level memory files
234
+ * Apply merge strategy to decide which files to load
235
+ * Returns the files to load and the files to skip
224
236
  */
225
- async loadEnterpriseMemory() {
237
+ async applyMergeStrategy(claudeFilePath, genFilePath, level, strategy) {
226
238
  const files = [];
239
+ const skipped = [];
240
+ switch (strategy) {
241
+ case 'fallback': {
242
+ // Try gen first, fallback to claude
243
+ const genFile = await this.loadFile(genFilePath, level, 'gen');
244
+ if (genFile) {
245
+ files.push(genFile);
246
+ // Only skip claude file if it exists
247
+ const claudeExists = await this.fileExists(claudeFilePath);
248
+ if (claudeExists) {
249
+ skipped.push(claudeFilePath);
250
+ }
251
+ }
252
+ else {
253
+ const claudeFile = await this.loadFile(claudeFilePath, level, 'claude');
254
+ if (claudeFile) {
255
+ files.push(claudeFile);
256
+ }
257
+ }
258
+ break;
259
+ }
260
+ case 'both': {
261
+ // Load both (claude first for lower priority)
262
+ const claudeFile = await this.loadFile(claudeFilePath, level, 'claude');
263
+ if (claudeFile)
264
+ files.push(claudeFile);
265
+ const genFile = await this.loadFile(genFilePath, level, 'gen');
266
+ if (genFile)
267
+ files.push(genFile);
268
+ break;
269
+ }
270
+ case 'gen-only': {
271
+ // Only load gen
272
+ const genFile = await this.loadFile(genFilePath, level, 'gen');
273
+ if (genFile) {
274
+ files.push(genFile);
275
+ }
276
+ // Only mark as skipped if claude file exists
277
+ const claudeExists = await this.fileExists(claudeFilePath);
278
+ if (claudeExists) {
279
+ skipped.push(claudeFilePath);
280
+ }
281
+ break;
282
+ }
283
+ case 'claude-only': {
284
+ // Only load claude
285
+ const claudeFile = await this.loadFile(claudeFilePath, level, 'claude');
286
+ if (claudeFile) {
287
+ files.push(claudeFile);
288
+ }
289
+ // Only mark as skipped if gen file exists
290
+ const genExists = await this.fileExists(genFilePath);
291
+ if (genExists) {
292
+ skipped.push(genFilePath);
293
+ }
294
+ break;
295
+ }
296
+ }
297
+ return { files, skipped };
298
+ }
299
+ /**
300
+ * Check if a file exists
301
+ */
302
+ async fileExists(filePath) {
303
+ try {
304
+ await fs.stat(filePath);
305
+ return true;
306
+ }
307
+ catch {
308
+ return false;
309
+ }
310
+ }
311
+ /**
312
+ * Load enterprise-level memory files
313
+ */
314
+ async loadEnterpriseMemory(strategy) {
227
315
  const managedPaths = getManagedPaths();
228
- // Load Claude first (lower priority)
229
- const claudeFile = await this.loadFile(path.join(managedPaths.claude, this.config.claudeFilename), 'enterprise', 'claude');
230
- if (claudeFile) {
231
- claudeFile.enforced = true;
232
- files.push(claudeFile);
233
- }
234
- // Load GenCode second (higher priority)
235
- const gencodeFile = await this.loadFile(path.join(managedPaths.gencode, this.config.gencodeFilename), 'enterprise', 'gencode');
236
- if (gencodeFile) {
237
- gencodeFile.enforced = true;
238
- files.push(gencodeFile);
239
- }
240
- return files;
316
+ const claudePath = path.join(managedPaths.claude, this.config.claudeFilename);
317
+ const genPath = path.join(managedPaths.gen, this.config.genFilename);
318
+ const result = await this.applyMergeStrategy(claudePath, genPath, 'enterprise', strategy);
319
+ // Mark all enterprise files as enforced
320
+ for (const file of result.files) {
321
+ file.enforced = true;
322
+ }
323
+ return result;
241
324
  }
242
325
  /**
243
- * Load user-level memory files (both claude and gencode)
326
+ * Load user-level memory files (both claude and gen)
244
327
  */
245
- async loadUserMemory() {
328
+ async loadUserMemory(strategy) {
246
329
  const home = os.homedir();
247
- const files = [];
248
- // Load Claude first (lower priority)
249
- const claudeFile = await this.loadFile(path.join(home, this.config.claudeDir, this.config.claudeFilename), 'user', 'claude');
250
- if (claudeFile)
251
- files.push(claudeFile);
252
- // Load GenCode second (higher priority)
253
- const gencodeFile = await this.loadFile(path.join(home, this.config.gencodeDir, this.config.gencodeFilename), 'user', 'gencode');
254
- if (gencodeFile)
255
- files.push(gencodeFile);
256
- return files;
330
+ const claudePath = path.join(home, this.config.claudeDir, this.config.claudeFilename);
331
+ const genPath = path.join(home, this.config.genDir, this.config.genFilename);
332
+ return await this.applyMergeStrategy(claudePath, genPath, 'user', strategy);
257
333
  }
258
334
  /**
259
- * Load user-level rules (both claude and gencode)
335
+ * Load user-level rules (both claude and gen)
260
336
  */
261
337
  async loadUserRules() {
262
338
  const home = os.homedir();
@@ -266,34 +342,32 @@ export class MemoryManager {
266
342
  const claudeRules = await this.loadRulesFromDir(claudeRulesDir, 'user-rules', 'claude');
267
343
  rules.push(...claudeRules);
268
344
  // Load GenCode rules second (higher priority)
269
- const gencodeRulesDir = path.join(home, this.config.gencodeDir, this.config.rulesDir);
270
- const gencodeRules = await this.loadRulesFromDir(gencodeRulesDir, 'user-rules', 'gencode');
271
- rules.push(...gencodeRules);
345
+ const genRulesDir = path.join(home, this.config.genDir, this.config.rulesDir);
346
+ const genRules = await this.loadRulesFromDir(genRulesDir, 'user-rules', 'gen');
347
+ rules.push(...genRules);
272
348
  return rules;
273
349
  }
274
350
  /**
275
351
  * Load extra config dirs memory
276
352
  */
277
- async loadExtraMemory() {
353
+ async loadExtraMemory(strategy) {
278
354
  const extraDirs = this.parseExtraConfigDirs();
279
355
  const files = [];
356
+ const skipped = [];
280
357
  for (const dir of extraDirs) {
281
- // Try CLAUDE.md
282
- const claudeFile = await this.loadFile(path.join(dir, this.config.claudeFilename), 'extra', 'extra');
283
- if (claudeFile)
284
- files.push(claudeFile);
285
- // Try AGENT.md
286
- const gencodeFile = await this.loadFile(path.join(dir, this.config.gencodeFilename), 'extra', 'extra');
287
- if (gencodeFile)
288
- files.push(gencodeFile);
289
- }
290
- return files;
358
+ const claudePath = path.join(dir, this.config.claudeFilename);
359
+ const genPath = path.join(dir, this.config.genFilename);
360
+ const result = await this.applyMergeStrategy(claudePath, genPath, 'extra', strategy);
361
+ files.push(...result.files);
362
+ skipped.push(...result.skipped);
363
+ }
364
+ return { files, skipped };
291
365
  }
292
366
  /**
293
- * Parse GENCODE_CONFIG_DIRS environment variable
367
+ * Parse GEN_CONFIG environment variable
294
368
  */
295
369
  parseExtraConfigDirs() {
296
- const value = process.env[GENCODE_CONFIG_DIRS_ENV];
370
+ const value = process.env[GEN_CONFIG_ENV];
297
371
  if (!value)
298
372
  return [];
299
373
  return value
@@ -303,38 +377,45 @@ export class MemoryManager {
303
377
  .map((dir) => dir.replace(/^~/, os.homedir()));
304
378
  }
305
379
  /**
306
- * Load project-level memory files (both claude and gencode)
380
+ * Load project-level memory files (both claude and gen)
307
381
  */
308
- async loadProjectMemory(cwd, projectRoot) {
309
- const files = [];
310
- // Load from project root - Claude files first
382
+ async loadProjectMemory(cwd, projectRoot, strategy) {
383
+ // Find first existing claude file
311
384
  const claudeCandidates = [
312
385
  path.join(projectRoot, this.config.claudeFilename),
313
386
  path.join(projectRoot, this.config.claudeDir, this.config.claudeFilename),
314
387
  ];
315
- for (const filePath of claudeCandidates) {
316
- const file = await this.loadFile(filePath, 'project', 'claude');
317
- if (file) {
318
- files.push(file);
319
- break; // Only load one claude file
388
+ let claudePath = claudeCandidates[0]; // Default for skipped tracking
389
+ for (const candidate of claudeCandidates) {
390
+ try {
391
+ await fs.stat(candidate);
392
+ claudePath = candidate;
393
+ break;
394
+ }
395
+ catch {
396
+ continue;
320
397
  }
321
398
  }
322
- // Load from project root - GenCode files second
323
- const gencodeCandidates = [
324
- path.join(projectRoot, this.config.gencodeFilename),
325
- path.join(projectRoot, this.config.gencodeDir, this.config.gencodeFilename),
399
+ // Find first existing gen file
400
+ const genCandidates = [
401
+ path.join(projectRoot, this.config.genFilename),
402
+ path.join(projectRoot, this.config.genDir, this.config.genFilename),
326
403
  ];
327
- for (const filePath of gencodeCandidates) {
328
- const file = await this.loadFile(filePath, 'project', 'gencode');
329
- if (file) {
330
- files.push(file);
331
- break; // Only load one gencode file
404
+ let genPath = genCandidates[0]; // Default for skipped tracking
405
+ for (const candidate of genCandidates) {
406
+ try {
407
+ await fs.stat(candidate);
408
+ genPath = candidate;
409
+ break;
410
+ }
411
+ catch {
412
+ continue;
332
413
  }
333
414
  }
334
- return files;
415
+ return await this.applyMergeStrategy(claudePath, genPath, 'project', strategy);
335
416
  }
336
417
  /**
337
- * Load project-level rules (both claude and gencode)
418
+ * Load project-level rules (both claude and gen)
338
419
  */
339
420
  async loadProjectRules(projectRoot) {
340
421
  const rules = [];
@@ -343,41 +424,48 @@ export class MemoryManager {
343
424
  const claudeRules = await this.loadRulesFromDir(claudeRulesDir, 'project-rules', 'claude');
344
425
  rules.push(...claudeRules);
345
426
  // Load GenCode rules second (higher priority)
346
- const gencodeRulesDir = path.join(projectRoot, this.config.gencodeDir, this.config.rulesDir);
347
- const gencodeRules = await this.loadRulesFromDir(gencodeRulesDir, 'project-rules', 'gencode');
348
- rules.push(...gencodeRules);
427
+ const genRulesDir = path.join(projectRoot, this.config.genDir, this.config.rulesDir);
428
+ const genRules = await this.loadRulesFromDir(genRulesDir, 'project-rules', 'gen');
429
+ rules.push(...genRules);
349
430
  return rules;
350
431
  }
351
432
  /**
352
- * Load local memory files (both claude and gencode)
433
+ * Load local memory files (both claude and gen)
353
434
  */
354
- async loadLocalMemory(projectRoot) {
355
- const files = [];
356
- // Load Claude local files first
435
+ async loadLocalMemory(projectRoot, strategy) {
436
+ // Find first existing claude local file
357
437
  const claudeCandidates = [
358
438
  path.join(projectRoot, this.config.claudeLocalFilename),
359
439
  path.join(projectRoot, this.config.claudeDir, this.config.claudeLocalFilename),
360
440
  ];
361
- for (const filePath of claudeCandidates) {
362
- const file = await this.loadFile(filePath, 'local', 'claude');
363
- if (file) {
364
- files.push(file);
441
+ let claudePath = claudeCandidates[0];
442
+ for (const candidate of claudeCandidates) {
443
+ try {
444
+ await fs.stat(candidate);
445
+ claudePath = candidate;
365
446
  break;
366
447
  }
448
+ catch {
449
+ continue;
450
+ }
367
451
  }
368
- // Load GenCode local files second
369
- const gencodeCandidates = [
370
- path.join(projectRoot, this.config.gencodeLocalFilename),
371
- path.join(projectRoot, this.config.gencodeDir, this.config.gencodeLocalFilename),
452
+ // Find first existing gen local file
453
+ const genCandidates = [
454
+ path.join(projectRoot, this.config.genLocalFilename),
455
+ path.join(projectRoot, this.config.genDir, this.config.genLocalFilename),
372
456
  ];
373
- for (const filePath of gencodeCandidates) {
374
- const file = await this.loadFile(filePath, 'local', 'gencode');
375
- if (file) {
376
- files.push(file);
457
+ let genPath = genCandidates[0];
458
+ for (const candidate of genCandidates) {
459
+ try {
460
+ await fs.stat(candidate);
461
+ genPath = candidate;
377
462
  break;
378
463
  }
464
+ catch {
465
+ continue;
466
+ }
379
467
  }
380
- return files;
468
+ return await this.applyMergeStrategy(claudePath, genPath, 'local', strategy);
381
469
  }
382
470
  /**
383
471
  * Load rules from a directory
@@ -464,13 +552,13 @@ export class MemoryManager {
464
552
  let filePath;
465
553
  const home = os.homedir();
466
554
  if (level === 'user') {
467
- const dir = path.join(home, this.config.gencodeDir);
555
+ const dir = path.join(home, this.config.genDir);
468
556
  await fs.mkdir(dir, { recursive: true });
469
- filePath = path.join(dir, this.config.gencodeFilename);
557
+ filePath = path.join(dir, this.config.genFilename);
470
558
  }
471
559
  else {
472
560
  const projectRoot = await this.findProjectRoot(cwd);
473
- filePath = path.join(projectRoot, this.config.gencodeFilename);
561
+ filePath = path.join(projectRoot, this.config.genFilename);
474
562
  }
475
563
  // Read existing content
476
564
  let existing = '';
@@ -479,7 +567,7 @@ export class MemoryManager {
479
567
  }
480
568
  catch {
481
569
  // File doesn't exist, create with header
482
- existing = `# ${this.config.gencodeFilename.replace('.md', '')}\n\nThis file provides guidance when working with code in this repository.\n\n`;
570
+ existing = `# ${this.config.genFilename.replace('.md', '')}\n\nThis file provides guidance when working with code in this repository.\n\n`;
483
571
  }
484
572
  // Append new content
485
573
  const newContent = `${existing.trimEnd()}\n\n${content}\n`;
@@ -517,7 +605,7 @@ export class MemoryManager {
517
605
  * Get the path where /init would create a file
518
606
  */
519
607
  getInitFilePath(cwd) {
520
- return path.join(cwd, this.config.gencodeFilename);
608
+ return path.join(cwd, this.config.genFilename);
521
609
  }
522
610
  /**
523
611
  * Check if project memory already exists
@@ -525,8 +613,8 @@ export class MemoryManager {
525
613
  async hasProjectMemory(cwd) {
526
614
  const projectRoot = await this.findProjectRoot(cwd);
527
615
  const candidates = [
528
- path.join(projectRoot, this.config.gencodeFilename),
529
- path.join(projectRoot, this.config.gencodeDir, this.config.gencodeFilename),
616
+ path.join(projectRoot, this.config.genFilename),
617
+ path.join(projectRoot, this.config.genDir, this.config.genFilename),
530
618
  path.join(projectRoot, this.config.claudeFilename),
531
619
  path.join(projectRoot, this.config.claudeDir, this.config.claudeFilename),
532
620
  ];
@@ -547,8 +635,8 @@ export class MemoryManager {
547
635
  async getExistingProjectMemoryPath(cwd) {
548
636
  const projectRoot = await this.findProjectRoot(cwd);
549
637
  const candidates = [
550
- path.join(projectRoot, this.config.gencodeFilename),
551
- path.join(projectRoot, this.config.gencodeDir, this.config.gencodeFilename),
638
+ path.join(projectRoot, this.config.genFilename),
639
+ path.join(projectRoot, this.config.genDir, this.config.genFilename),
552
640
  path.join(projectRoot, this.config.claudeFilename),
553
641
  path.join(projectRoot, this.config.claudeDir, this.config.claudeFilename),
554
642
  ];
@@ -583,5 +671,46 @@ export class MemoryManager {
583
671
  }
584
672
  return lines.join('\n');
585
673
  }
674
+ /**
675
+ * Get verbose loading summary with strategy info
676
+ */
677
+ getVerboseSummary(strategy) {
678
+ if (!this.loadedMemory)
679
+ return 'Memory not loaded';
680
+ const lines = [];
681
+ const kbLoaded = (this.loadedMemory.totalSize / 1024).toFixed(1);
682
+ lines.push(`[Memory] Strategy: ${strategy}`);
683
+ // Group sources by level
684
+ const byLevel = new Map();
685
+ for (const source of this.loadedMemory.sources) {
686
+ const key = source.level;
687
+ if (!byLevel.has(key)) {
688
+ byLevel.set(key, []);
689
+ }
690
+ byLevel.get(key).push(source);
691
+ }
692
+ // Show what was loaded per level
693
+ for (const [level, sources] of byLevel) {
694
+ for (const source of sources) {
695
+ const sizeKb = (source.size / 1024).toFixed(1);
696
+ const marker = source.level === 'enterprise' ? ' [enforced]' : '';
697
+ lines.push(`[Memory] ${level}: ${source.path} (${sizeKb} KB)${marker}`);
698
+ }
699
+ }
700
+ // Show what was skipped
701
+ if (this.loadedMemory.skippedFiles.length > 0) {
702
+ for (const skipped of this.loadedMemory.skippedFiles) {
703
+ lines.push(`[Memory] Skipped: ${skipped}`);
704
+ }
705
+ }
706
+ lines.push(`[Memory] Total: ${kbLoaded} KB (${this.loadedMemory.files.length} files loaded, ${this.loadedMemory.skippedFiles.length} skipped)`);
707
+ if (this.loadedMemory.errors.length > 0) {
708
+ lines.push('[Memory] Errors:');
709
+ for (const error of this.loadedMemory.errors) {
710
+ lines.push(` - ${error}`);
711
+ }
712
+ }
713
+ return lines.join('\n');
714
+ }
586
715
  }
587
716
  //# sourceMappingURL=memory-manager.js.map