@shahmilsaari/memory-core 1.0.25 → 1.0.27

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.
@@ -1,4 +1,27 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ callChatModel,
4
+ getChatProviderLabel
5
+ } from "./chunk-PQBWHAZN.js";
6
+ import {
7
+ Config,
8
+ deleteMemories,
9
+ deleteMemory,
10
+ getMemory,
11
+ getPool,
12
+ listMemories,
13
+ saveMemory,
14
+ searchMemories,
15
+ updateMemory,
16
+ upsertMemory
17
+ } from "./chunk-M7NKSXFS.js";
18
+ import {
19
+ buildModuleDependencyEdges,
20
+ collectResolvedImports,
21
+ detectModuleCycles,
22
+ isExternalFrameworkSpecifier,
23
+ parseChangedFilesFromDiff
24
+ } from "./chunk-ZZBQEXEO.js";
2
25
 
3
26
  // src/project-detector.ts
4
27
  import { existsSync, readFileSync } from "fs";
@@ -62,33 +85,6 @@ function detectProject(cwd = process.cwd()) {
62
85
  return { language: "Unknown", framework: "Unknown" };
63
86
  }
64
87
 
65
- // src/config.ts
66
- import { config } from "dotenv";
67
- import { existsSync as existsSync2 } from "fs";
68
- import { join as join2 } from "path";
69
- var localEnv = join2(process.cwd(), ".memory-core.env");
70
- config({ path: existsSync2(localEnv) ? localEnv : join2(process.cwd(), ".env") });
71
- var Config = {
72
- get databaseUrl() {
73
- return process.env.DATABASE_URL ?? "";
74
- },
75
- get ollamaUrl() {
76
- return process.env.OLLAMA_URL ?? "http://localhost:11434";
77
- },
78
- get ollamaModel() {
79
- return process.env.OLLAMA_MODEL ?? "nomic-embed-text";
80
- },
81
- get chatModel() {
82
- return process.env.CHAT_MODEL ?? process.env.OLLAMA_CHAT_MODEL ?? "llama3.2";
83
- },
84
- get chatProvider() {
85
- return process.env.CHAT_PROVIDER ?? "ollama";
86
- },
87
- get chatApiKey() {
88
- return process.env.CHAT_API_KEY ?? "";
89
- }
90
- };
91
-
92
88
  // src/embedding.ts
93
89
  function getEmbeddingTimeoutMs() {
94
90
  const raw = Number(process.env.EMBEDDING_TIMEOUT_MS ?? process.env.MEMORY_CORE_RETRIEVAL_TIMEOUT_MS ?? 5e3);
@@ -116,409 +112,6 @@ async function embed(text) {
116
112
  return data.embedding;
117
113
  }
118
114
 
119
- // src/chat.ts
120
- function getChatConfig() {
121
- const provider = process.env.CHAT_PROVIDER ?? "ollama";
122
- const model = process.env.CHAT_MODEL ?? process.env.OLLAMA_CHAT_MODEL ?? "llama3.2";
123
- return {
124
- provider,
125
- model,
126
- ollamaUrl: process.env.OLLAMA_URL ?? "http://localhost:11434",
127
- apiKey: process.env.CHAT_API_KEY ?? "",
128
- baseUrl: process.env.CHAT_BASE_URL ?? ""
129
- };
130
- }
131
- function getDefaultTimeoutMs() {
132
- const raw = Number(process.env.CHAT_TIMEOUT_MS ?? 6e4);
133
- return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 6e4;
134
- }
135
- function timeoutSignal(timeoutMs) {
136
- return AbortSignal.timeout(timeoutMs ?? getDefaultTimeoutMs());
137
- }
138
- function normalizeChatError(err, timeoutMs) {
139
- const ms = timeoutMs ?? getDefaultTimeoutMs();
140
- if (err instanceof Error && err.name === "AbortError") {
141
- return new Error(`TIMEOUT:${ms}`);
142
- }
143
- return err instanceof Error ? err : new Error(String(err));
144
- }
145
- async function callOllama(cfg, messages, options = {}) {
146
- const res = await fetch(`${cfg.ollamaUrl}/api/chat`, {
147
- method: "POST",
148
- headers: { "Content-Type": "application/json" },
149
- signal: timeoutSignal(options.timeoutMs),
150
- body: JSON.stringify({ model: cfg.model, messages, stream: false, format: "json" })
151
- });
152
- if (!res.ok) {
153
- const body = await res.text();
154
- if (body.includes("not found") || body.includes("model")) {
155
- throw new Error(`MODEL_NOT_FOUND:${cfg.model}`);
156
- }
157
- throw new Error(body);
158
- }
159
- const data = await res.json();
160
- const inputTokens = data.prompt_eval_count ?? 0;
161
- const outputTokens = data.eval_count ?? 0;
162
- return {
163
- content: data.message.content.trim(),
164
- usage: inputTokens || outputTokens ? { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens } : void 0
165
- };
166
- }
167
- async function callOpenAICompat(cfg, messages, options = {}) {
168
- const base = (cfg.baseUrl ?? "").replace(/\/$/, "") || "https://api.openai.com/v1";
169
- const res = await fetch(`${base}/chat/completions`, {
170
- method: "POST",
171
- headers: {
172
- "Content-Type": "application/json",
173
- "Authorization": `Bearer ${cfg.apiKey}`
174
- },
175
- signal: timeoutSignal(options.timeoutMs),
176
- body: JSON.stringify({
177
- model: cfg.model,
178
- messages,
179
- response_format: { type: "json_object" }
180
- })
181
- });
182
- if (!res.ok) throw new Error(`OpenAI API error ${res.status}: ${await res.text()}`);
183
- const data = await res.json();
184
- const u = data.usage;
185
- return {
186
- content: data.choices[0].message.content.trim(),
187
- usage: u ? { inputTokens: u.prompt_tokens, outputTokens: u.completion_tokens, totalTokens: u.total_tokens } : void 0
188
- };
189
- }
190
- async function callAnthropic(cfg, messages, options = {}) {
191
- const system = messages.find((m) => m.role === "system")?.content ?? "";
192
- const userMessages = messages.filter((m) => m.role !== "system");
193
- const res = await fetch("https://api.anthropic.com/v1/messages", {
194
- method: "POST",
195
- headers: {
196
- "Content-Type": "application/json",
197
- "x-api-key": cfg.apiKey,
198
- "anthropic-version": "2023-06-01"
199
- },
200
- signal: timeoutSignal(options.timeoutMs),
201
- body: JSON.stringify({
202
- model: cfg.model,
203
- max_tokens: 4096,
204
- system,
205
- messages: userMessages
206
- })
207
- });
208
- if (!res.ok) throw new Error(`Anthropic API error ${res.status}: ${await res.text()}`);
209
- const data = await res.json();
210
- const u = data.usage;
211
- return {
212
- content: data.content[0].text.trim(),
213
- usage: u ? { inputTokens: u.input_tokens, outputTokens: u.output_tokens, totalTokens: u.input_tokens + u.output_tokens } : void 0
214
- };
215
- }
216
- async function callMiniMax(cfg, messages, options = {}) {
217
- const res = await fetch("https://api.minimax.io/v1/chat/completions", {
218
- method: "POST",
219
- headers: {
220
- "Content-Type": "application/json",
221
- "Authorization": `Bearer ${cfg.apiKey}`
222
- },
223
- signal: timeoutSignal(options.timeoutMs),
224
- body: JSON.stringify({
225
- model: cfg.model,
226
- messages,
227
- response_format: { type: "json_object" }
228
- })
229
- });
230
- if (!res.ok) throw new Error(`MiniMax API error ${res.status}: ${await res.text()}`);
231
- const data = await res.json();
232
- const u = data.usage;
233
- return {
234
- content: data.choices[0].message.content.trim(),
235
- usage: u ? { inputTokens: u.prompt_tokens, outputTokens: u.completion_tokens, totalTokens: u.total_tokens } : void 0
236
- };
237
- }
238
- async function callChatModel(messages, options = {}) {
239
- const cfg = getChatConfig();
240
- try {
241
- switch (cfg.provider) {
242
- case "openai":
243
- case "openai-compatible":
244
- return await callOpenAICompat(cfg, messages, options);
245
- case "anthropic":
246
- return await callAnthropic(cfg, messages, options);
247
- case "minimax":
248
- return await callMiniMax(cfg, messages, options);
249
- default:
250
- return await callOllama(cfg, messages, options);
251
- }
252
- } catch (err) {
253
- throw normalizeChatError(err, options.timeoutMs);
254
- }
255
- }
256
- function getChatProviderLabel() {
257
- const cfg = getChatConfig();
258
- if (cfg.provider === "ollama") return `ollama (${cfg.model})`;
259
- if (cfg.provider === "openai-compatible") {
260
- const host = cfg.baseUrl ? new URL(cfg.baseUrl).hostname : "custom";
261
- return `openai-compat/${host} (${cfg.model})`;
262
- }
263
- return `${cfg.provider} (${cfg.model})`;
264
- }
265
-
266
- // src/db.ts
267
- import pg from "pg";
268
- import { createHash } from "crypto";
269
- var { Pool } = pg;
270
- var pool = null;
271
- var migrationsRun = false;
272
- function readPositiveIntEnv(name, fallback) {
273
- const raw = Number(process.env[name]);
274
- return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : fallback;
275
- }
276
- function hashMemoryContent(content) {
277
- return createHash("md5").update(content.trim()).digest("hex");
278
- }
279
- function getPool() {
280
- if (!pool) {
281
- if (!Config.databaseUrl) {
282
- throw new Error("DATABASE_URL is not set. Add it to your .env or .memory-core.env file.");
283
- }
284
- const timeoutMs = readPositiveIntEnv("DATABASE_TIMEOUT_MS", 5e3);
285
- pool = new Pool({
286
- connectionString: Config.databaseUrl,
287
- connectionTimeoutMillis: timeoutMs,
288
- query_timeout: timeoutMs,
289
- statement_timeout: timeoutMs
290
- });
291
- }
292
- return pool;
293
- }
294
- async function runMigrations() {
295
- if (migrationsRun) return;
296
- const client = await getPool().connect();
297
- try {
298
- await client.query("BEGIN");
299
- await client.query(`ALTER TABLE memories ALTER COLUMN scope SET DEFAULT 'project'`);
300
- await client.query(`ALTER TABLE memories ADD COLUMN IF NOT EXISTS reason TEXT`);
301
- await client.query(`ALTER TABLE memories ADD COLUMN IF NOT EXISTS content_hash TEXT`);
302
- await client.query(`ALTER TABLE memories ADD COLUMN IF NOT EXISTS context JSONB NOT NULL DEFAULT '{}'::jsonb`);
303
- await client.query(
304
- `UPDATE memories
305
- SET content_hash = md5(trim(content))
306
- WHERE content_hash IS NULL`
307
- );
308
- await client.query(`CREATE INDEX IF NOT EXISTS memories_content_hash_idx ON memories (content_hash)`);
309
- await client.query("COMMIT");
310
- migrationsRun = true;
311
- } catch (err) {
312
- await client.query("ROLLBACK");
313
- throw err;
314
- } finally {
315
- client.release();
316
- }
317
- }
318
- async function saveMemory(memory) {
319
- await runMigrations();
320
- const { type, scope, architecture, projectName, title, content, reason, context, tags, embedding } = memory;
321
- const contentHash = hashMemoryContent(content);
322
- await getPool().query(
323
- `INSERT INTO memories (type, scope, architecture, project_name, title, content, reason, context, tags, embedding, content_hash)
324
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10, $11)`,
325
- [
326
- type,
327
- scope,
328
- architecture ?? null,
329
- projectName ?? null,
330
- title ?? null,
331
- content,
332
- reason ?? null,
333
- JSON.stringify(context ?? {}),
334
- tags ?? [],
335
- `[${embedding.join(",")}]`,
336
- contentHash
337
- ]
338
- );
339
- }
340
- async function upsertMemory(memory) {
341
- await runMigrations();
342
- const contentHash = hashMemoryContent(memory.content);
343
- const existing = await getPool().query(
344
- `SELECT id FROM memories
345
- WHERE content_hash = $1
346
- AND COALESCE(architecture, '') = COALESCE($2, '')
347
- AND scope = $3
348
- AND type = $4
349
- LIMIT 1`,
350
- [contentHash, memory.architecture ?? null, memory.scope, memory.type]
351
- );
352
- if (existing.rowCount) return "skipped";
353
- await saveMemory(memory);
354
- return "inserted";
355
- }
356
- async function listMemories(filters = {}) {
357
- await runMigrations();
358
- const where = [];
359
- const params = [];
360
- if (filters.type) {
361
- params.push(filters.type);
362
- where.push(`type = $${params.length}`);
363
- }
364
- if (filters.scope) {
365
- params.push(filters.scope);
366
- where.push(`scope = $${params.length}`);
367
- }
368
- if (filters.architecture) {
369
- if (Array.isArray(filters.architecture)) {
370
- params.push(filters.architecture);
371
- where.push(filters.includeGlobal ? `(architecture IS NULL OR architecture = ANY($${params.length}))` : `architecture = ANY($${params.length})`);
372
- } else {
373
- params.push(filters.architecture);
374
- where.push(filters.includeGlobal ? `(architecture IS NULL OR architecture = $${params.length})` : `architecture = $${params.length}`);
375
- }
376
- }
377
- if (filters.projectName) {
378
- params.push(filters.projectName);
379
- where.push(filters.includeGlobal ? `(project_name IS NULL OR project_name = $${params.length})` : `project_name = $${params.length}`);
380
- }
381
- if (filters.tags?.length) {
382
- params.push(filters.tags);
383
- where.push(`tags && $${params.length}::text[]`);
384
- }
385
- const limit = filters.limit ?? 200;
386
- params.push(limit);
387
- const result = await getPool().query(
388
- `SELECT id, type, scope, architecture, project_name, title, content, reason, context, tags, content_hash
389
- FROM memories
390
- ${where.length ? `WHERE ${where.join(" AND ")}` : ""}
391
- ORDER BY id ASC
392
- LIMIT $${params.length}`,
393
- params
394
- );
395
- return result.rows;
396
- }
397
- async function getMemory(id) {
398
- await runMigrations();
399
- const result = await getPool().query(
400
- `SELECT id, type, scope, architecture, project_name, title, content, reason, context, tags, content_hash
401
- FROM memories
402
- WHERE id = $1`,
403
- [id]
404
- );
405
- return result.rows[0] ?? null;
406
- }
407
- async function deleteMemory(id) {
408
- await runMigrations();
409
- const result = await getPool().query(`DELETE FROM memories WHERE id = $1`, [id]);
410
- return (result.rowCount ?? 0) > 0;
411
- }
412
- async function deleteMemories(filters) {
413
- await runMigrations();
414
- const where = [];
415
- const params = [];
416
- if (filters.type) {
417
- params.push(filters.type);
418
- where.push(`type = $${params.length}`);
419
- }
420
- if (filters.scope) {
421
- params.push(filters.scope);
422
- where.push(`scope = $${params.length}`);
423
- }
424
- if (filters.architecture) {
425
- if (Array.isArray(filters.architecture)) {
426
- params.push(filters.architecture);
427
- where.push(`architecture = ANY($${params.length})`);
428
- } else {
429
- params.push(filters.architecture);
430
- where.push(`architecture = $${params.length}`);
431
- }
432
- }
433
- if (filters.tag) {
434
- params.push(filters.tag);
435
- where.push(`$${params.length} = ANY(tags)`);
436
- }
437
- if (where.length === 0) {
438
- throw new Error("Refusing to bulk-delete without filters");
439
- }
440
- const result = await getPool().query(
441
- `DELETE FROM memories WHERE ${where.join(" AND ")}`,
442
- params
443
- );
444
- return result.rowCount ?? 0;
445
- }
446
- async function updateMemory(id, patch) {
447
- await runMigrations();
448
- const current = await getMemory(id);
449
- if (!current) return null;
450
- const content = patch.content ?? current.content;
451
- const contentHash = hashMemoryContent(content);
452
- const embedding = patch.embedding ? `[${patch.embedding.join(",")}]` : null;
453
- const result = await getPool().query(
454
- `UPDATE memories
455
- SET type = $2,
456
- scope = $3,
457
- title = $4,
458
- content = $5,
459
- reason = $6,
460
- context = $7::jsonb,
461
- tags = $8,
462
- content_hash = $9,
463
- embedding = COALESCE($10::vector, embedding)
464
- WHERE id = $1
465
- RETURNING id, type, scope, architecture, project_name, title, content, reason, context, tags, content_hash`,
466
- [
467
- id,
468
- patch.type ?? current.type,
469
- patch.scope ?? current.scope,
470
- patch.title ?? current.title ?? null,
471
- content,
472
- patch.reason ?? current.reason ?? null,
473
- JSON.stringify(patch.context ?? current.context ?? {}),
474
- patch.tags ?? current.tags ?? [],
475
- contentHash,
476
- embedding
477
- ]
478
- );
479
- return result.rows[0] ?? null;
480
- }
481
- async function searchMemories(embedding, architectures, limit = 10) {
482
- await runMigrations();
483
- const vector = `[${embedding.join(",")}]`;
484
- const params = [vector];
485
- let whereClause = "";
486
- const selectedArchitectures = architectures ? (Array.isArray(architectures) ? architectures : [architectures]).filter(Boolean) : [];
487
- if (selectedArchitectures.length > 0) {
488
- whereClause = `WHERE (
489
- architecture = ANY($2)
490
- OR architecture IS NULL
491
- OR architecture = 'global'
492
- )`;
493
- params.push(selectedArchitectures);
494
- }
495
- const client = await getPool().connect();
496
- try {
497
- await client.query("BEGIN");
498
- await client.query("SET LOCAL ivfflat.probes = 10");
499
- const result = await client.query(
500
- `SELECT id, type, scope, architecture, project_name, title, content, reason, context, tags,
501
- 1 - (embedding <=> $1) AS similarity
502
- FROM memories
503
- ${whereClause}
504
- ORDER BY embedding <=> $1
505
- LIMIT $${params.length + 1}`,
506
- [...params, limit]
507
- );
508
- await client.query("COMMIT");
509
- return result.rows;
510
- } finally {
511
- client.release();
512
- }
513
- }
514
- async function closePool() {
515
- if (pool) {
516
- await pool.end();
517
- pool = null;
518
- migrationsRun = false;
519
- }
520
- }
521
-
522
115
  // src/infrastructure/persistence/postgres/postgres-graph-repository.ts
523
116
  var graphMigrationsRun = false;
524
117
  function asPosix(value) {
@@ -1026,8 +619,8 @@ var seeds = [
1026
619
  ];
1027
620
 
1028
621
  // src/memory-file.ts
1029
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
1030
- import { join as join3 } from "path";
622
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
623
+ import { join as join2 } from "path";
1031
624
  var MEMORY_FILE = "memories.json";
1032
625
  function toPortableMemory(memory) {
1033
626
  return {
@@ -1061,13 +654,13 @@ function parseContext(value) {
1061
654
  return Object.keys(context).length ? context : void 0;
1062
655
  }
1063
656
  function writeMemoryFile(memories, cwd = process.cwd()) {
1064
- const path = join3(cwd, MEMORY_FILE);
657
+ const path = join2(cwd, MEMORY_FILE);
1065
658
  writeFileSync(path, JSON.stringify(memories, null, 2) + "\n", "utf-8");
1066
659
  return path;
1067
660
  }
1068
661
  function readMemoryFile(cwd = process.cwd()) {
1069
- const path = join3(cwd, MEMORY_FILE);
1070
- if (!existsSync3(path)) {
662
+ const path = join2(cwd, MEMORY_FILE);
663
+ if (!existsSync2(path)) {
1071
664
  throw new Error(`${MEMORY_FILE} not found. Run: memory-core export`);
1072
665
  }
1073
666
  return parseMemoryFile(readFileSync2(path, "utf-8"));
@@ -1105,8 +698,8 @@ function parseMemoryFile(raw) {
1105
698
  }
1106
699
 
1107
700
  // src/modules/rule-engine/infrastructure/schema-violations.ts
1108
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
1109
- import { join as join4 } from "path";
701
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
702
+ import { join as join3 } from "path";
1110
703
  function parseSchemaRule(content) {
1111
704
  try {
1112
705
  const parsed = JSON.parse(content);
@@ -1157,9 +750,9 @@ async function findSchemaViolations(opts) {
1157
750
  for (const memory of schemaMemories) {
1158
751
  const rule = parseSchemaRule(memory.content);
1159
752
  if (!rule) continue;
1160
- const tsPath = join4(opts.cwd, rule.tsFile);
1161
- const goPath = join4(opts.cwd, rule.goFile);
1162
- if (!existsSync4(tsPath) || !existsSync4(goPath)) continue;
753
+ const tsPath = join3(opts.cwd, rule.tsFile);
754
+ const goPath = join3(opts.cwd, rule.goFile);
755
+ if (!existsSync3(tsPath) || !existsSync3(goPath)) continue;
1163
756
  const tsSource = readFileSync3(tsPath, "utf-8");
1164
757
  const goSource = readFileSync3(goPath, "utf-8");
1165
758
  const tsFields = new Set(extractTsFields(tsSource));
@@ -1192,13 +785,13 @@ async function findSchemaViolations(opts) {
1192
785
 
1193
786
  // src/hook.ts
1194
787
  import { execSync, spawnSync as spawnSync2 } from "child_process";
1195
- import { writeFileSync as writeFileSync5, existsSync as existsSync9, unlinkSync, readFileSync as readFileSync8, chmodSync, statSync as statSync3 } from "fs";
1196
- import { join as join10 } from "path";
788
+ import { writeFileSync as writeFileSync5, existsSync as existsSync7, unlinkSync, readFileSync as readFileSync7, chmodSync, statSync as statSync3 } from "fs";
789
+ import { join as join8 } from "path";
1197
790
  import chalk2 from "chalk";
1198
791
 
1199
792
  // src/generator.ts
1200
- import { readFileSync as readFileSync7, readdirSync as readdirSync3, writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as existsSync8 } from "fs";
1201
- import { join as join9, dirname as dirname4, basename } from "path";
793
+ import { readFileSync as readFileSync6, readdirSync as readdirSync3, writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as existsSync6 } from "fs";
794
+ import { join as join7, dirname as dirname3, basename } from "path";
1202
795
  import { fileURLToPath } from "url";
1203
796
  import Handlebars from "handlebars";
1204
797
  import yaml from "js-yaml";
@@ -1307,9 +900,9 @@ var PostgresMemoryRepository = class {
1307
900
  };
1308
901
 
1309
902
  // src/infrastructure/persistence/filesystem/file-graph-repository.ts
1310
- import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
1311
- import { dirname, join as join5 } from "path";
1312
- var DEFAULT_FILE = join5(".memory-core", "graph-snapshots.json");
903
+ import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
904
+ import { dirname, join as join4 } from "path";
905
+ var DEFAULT_FILE = join4(".memory-core", "graph-snapshots.json");
1313
906
  function asPosix2(value) {
1314
907
  return value.replace(/\\/g, "/");
1315
908
  }
@@ -1348,7 +941,7 @@ var FileGraphRepository = class {
1348
941
  }
1349
942
  readData() {
1350
943
  const filePath = this.absolutePath();
1351
- if (!existsSync5(filePath)) {
944
+ if (!existsSync4(filePath)) {
1352
945
  return { version: 1, snapshots: [] };
1353
946
  }
1354
947
  try {
@@ -1373,7 +966,7 @@ var FileGraphRepository = class {
1373
966
  `, "utf-8");
1374
967
  }
1375
968
  absolutePath() {
1376
- return join5(this.rootPath, this.relativeFilePath);
969
+ return join4(this.rootPath, this.relativeFilePath);
1377
970
  }
1378
971
  };
1379
972
 
@@ -1421,214 +1014,39 @@ var ResilientGraphRepository = class {
1421
1014
  // src/watcher.ts
1422
1015
  import { watch } from "chokidar";
1423
1016
  import { spawnSync } from "child_process";
1424
- import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync6, statSync, writeFileSync as writeFileSync3 } from "fs";
1425
- import { dirname as dirname3, join as join7, relative, resolve as resolve3, sep } from "path";
1017
+ import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync5, statSync, writeFileSync as writeFileSync3 } from "fs";
1018
+ import { dirname as dirname2, join as join5, relative, resolve as resolve2, sep } from "path";
1426
1019
  import chalk from "chalk";
1427
1020
 
1428
1021
  // src/modules/rule-engine/infrastructure/ast-deterministic-violations.ts
1429
- import { resolve as resolve2 } from "path";
1430
-
1431
- // src/infrastructure/ast/import-analysis.ts
1432
- import { builtinModules } from "module";
1433
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
1434
- import { dirname as dirname2, extname, isAbsolute, join as join6, normalize, resolve } from "path";
1435
- var SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
1436
- var NODE_BUILTINS = /* @__PURE__ */ new Set([...builtinModules, ...builtinModules.map((entry) => `node:${entry}`)]);
1437
- function countNewlines(value) {
1438
- let count = 0;
1439
- for (const char of value) {
1440
- if (char === "\n") count += 1;
1441
- }
1442
- return count;
1443
- }
1444
- function parseImports(source) {
1445
- const imports = [];
1446
- const patterns = [
1447
- { kind: "import", regex: /(^|\n)\s*import\s+(?:type\s+)?(?:[^'"\n]+?\s+from\s+)?['"]([^'"\n]+)['"]/g },
1448
- { kind: "export-from", regex: /(^|\n)\s*export\s+(?:type\s+)?(?:[^'"\n]+?\s+from\s+)['"]([^'"\n]+)['"]/g },
1449
- { kind: "require", regex: /(^|\n)[^\n]*?\brequire\(\s*['"]([^'"\n]+)['"]\s*\)/g },
1450
- { kind: "dynamic-import", regex: /(^|\n)[^\n]*?\bimport\(\s*['"]([^'"\n]+)['"]\s*\)/g }
1451
- ];
1452
- for (const { kind, regex } of patterns) {
1453
- for (const match of source.matchAll(regex)) {
1454
- const prefix = source.slice(0, match.index ?? 0);
1455
- imports.push({
1456
- kind,
1457
- specifier: match[2],
1458
- line: countNewlines(prefix) + 1
1459
- });
1460
- }
1461
- }
1462
- return imports;
1463
- }
1464
- function tryResolveFilePath(candidate) {
1465
- if (existsSync6(candidate)) return normalize(candidate);
1466
- if (!extname(candidate)) {
1467
- for (const ext of SOURCE_EXTENSIONS) {
1468
- const withExt = `${candidate}${ext}`;
1469
- if (existsSync6(withExt)) return normalize(withExt);
1470
- }
1471
- for (const ext of SOURCE_EXTENSIONS) {
1472
- const indexFile = join6(candidate, `index${ext}`);
1473
- if (existsSync6(indexFile)) return normalize(indexFile);
1474
- }
1475
- }
1476
- return void 0;
1477
- }
1478
- function looksLikeExternal(specifier) {
1479
- return !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("@/");
1480
- }
1481
- function resolveImportPath(fromFile, specifier, cwd = process.cwd()) {
1482
- if (specifier.startsWith(".")) {
1483
- return tryResolveFilePath(resolve(dirname2(fromFile), specifier));
1484
- }
1485
- if (specifier.startsWith("/")) {
1486
- return tryResolveFilePath(resolve(cwd, `.${specifier}`));
1487
- }
1488
- if (specifier.startsWith("@/")) {
1489
- return tryResolveFilePath(resolve(cwd, "src", specifier.slice(2)));
1490
- }
1491
- if (isAbsolute(specifier)) {
1492
- return tryResolveFilePath(specifier);
1493
- }
1494
- return void 0;
1495
- }
1496
- function collectResolvedImports(filePath, cwd = process.cwd()) {
1497
- if (!existsSync6(filePath)) return [];
1498
- const source = readFileSync5(filePath, "utf-8");
1499
- const imports = parseImports(source);
1500
- return imports.map((entry) => {
1501
- if (looksLikeExternal(entry.specifier) || NODE_BUILTINS.has(entry.specifier)) {
1502
- return { ...entry, isExternal: true };
1503
- }
1504
- return {
1505
- ...entry,
1506
- isExternal: false,
1507
- resolvedPath: resolveImportPath(filePath, entry.specifier, cwd)
1508
- };
1509
- });
1510
- }
1022
+ import { resolve } from "path";
1511
1023
  function asPosix3(value) {
1512
1024
  return value.replace(/\\/g, "/");
1513
1025
  }
1514
- function moduleNameFromPath(absPath, cwd = process.cwd()) {
1515
- const rel = asPosix3(normalize(absPath)).replace(asPosix3(normalize(cwd)) + "/", "");
1516
- const match = rel.match(/^src\/modules\/([^/]+)\//);
1517
- return match?.[1];
1518
- }
1519
- function buildModuleDependencyEdges(files, cwd = process.cwd()) {
1520
- const edges = [];
1521
- for (const file of files) {
1522
- const absoluteFile = resolve(cwd, file);
1523
- const fromModule = moduleNameFromPath(absoluteFile, cwd);
1524
- if (!fromModule) continue;
1525
- const imports = collectResolvedImports(absoluteFile, cwd);
1526
- for (const imp of imports) {
1527
- if (!imp.resolvedPath) continue;
1528
- const toModule = moduleNameFromPath(imp.resolvedPath, cwd);
1529
- if (!toModule || toModule === fromModule) continue;
1530
- edges.push({
1531
- fromModule,
1532
- toModule,
1533
- file,
1534
- line: imp.line
1535
- });
1536
- }
1537
- }
1538
- return edges;
1539
- }
1540
- function parseChangedFilesFromDiff(diff) {
1541
- const files = /* @__PURE__ */ new Set();
1542
- for (const line of diff.split("\n")) {
1543
- if (!line.startsWith("+++ b/")) continue;
1544
- const file = line.slice("+++ b/".length).trim();
1545
- if (!file || file === "/dev/null") continue;
1546
- files.add(file);
1547
- }
1548
- return [...files];
1549
- }
1550
- function detectModuleCycles(edges) {
1551
- const graph = /* @__PURE__ */ new Map();
1552
- for (const edge of edges) {
1553
- const next = graph.get(edge.fromModule) ?? /* @__PURE__ */ new Set();
1554
- next.add(edge.toModule);
1555
- graph.set(edge.fromModule, next);
1556
- }
1557
- const visited = /* @__PURE__ */ new Set();
1558
- const stack = /* @__PURE__ */ new Set();
1559
- const cycles = /* @__PURE__ */ new Set();
1560
- const visit = (node, path) => {
1561
- visited.add(node);
1562
- stack.add(node);
1563
- const next = graph.get(node) ?? /* @__PURE__ */ new Set();
1564
- for (const target of next) {
1565
- if (!visited.has(target)) {
1566
- visit(target, [...path, target]);
1567
- continue;
1568
- }
1569
- if (stack.has(target)) {
1570
- const start = path.indexOf(target);
1571
- const cycle = start >= 0 ? path.slice(start).concat(target) : [node, target, node];
1572
- cycles.add(cycle.join("->"));
1573
- }
1574
- }
1575
- stack.delete(node);
1576
- };
1577
- for (const node of graph.keys()) {
1578
- if (!visited.has(node)) {
1579
- visit(node, [node]);
1580
- }
1581
- }
1582
- return [...cycles].map((value) => value.split("->"));
1583
- }
1584
- function isExternalFrameworkSpecifier(specifier) {
1585
- const frameworkPrefixes = [
1586
- "express",
1587
- "fastify",
1588
- "@nestjs/",
1589
- "react",
1590
- "vue",
1591
- "svelte",
1592
- "@angular/",
1593
- "next/",
1594
- "nuxt",
1595
- "typeorm",
1596
- "@prisma/",
1597
- "mongoose",
1598
- "sequelize",
1599
- "axios"
1600
- ];
1601
- return frameworkPrefixes.some((prefix) => specifier === prefix || specifier.startsWith(`${prefix}/`));
1602
- }
1603
-
1604
- // src/modules/rule-engine/infrastructure/ast-deterministic-violations.ts
1605
- function asPosix4(value) {
1606
- return value.replace(/\\/g, "/");
1607
- }
1608
1026
  function hasPath(value, pathSegment) {
1609
- const normalized = asPosix4(value);
1027
+ const normalized = asPosix3(value);
1610
1028
  const trimmed = pathSegment.startsWith("/") ? pathSegment.slice(1) : pathSegment;
1611
1029
  return normalized.includes(pathSegment) || normalized.includes(trimmed);
1612
1030
  }
1613
1031
  function isLegacyOrCompatibilitySpecifier(specifier) {
1614
- const normalized = asPosix4(specifier);
1032
+ const normalized = asPosix3(specifier);
1615
1033
  return normalized.includes("/compatibility/") || normalized.includes("compatibility/") || normalized.includes("legacy-");
1616
1034
  }
1617
1035
  function isLegacyOrCompatibilityPath(pathValue) {
1618
1036
  if (!pathValue) return false;
1619
- const normalized = asPosix4(pathValue);
1037
+ const normalized = asPosix3(pathValue);
1620
1038
  return normalized.includes("/src/compatibility/") || normalized.includes("/legacy-");
1621
1039
  }
1622
- function moduleNameFromPath2(pathValue) {
1623
- const match = asPosix4(pathValue).match(/src\/modules\/([^/]+)\//);
1040
+ function moduleNameFromPath(pathValue) {
1041
+ const match = asPosix3(pathValue).match(/src\/modules\/([^/]+)\//);
1624
1042
  return match?.[1];
1625
1043
  }
1626
1044
  function isModulePublicPath(pathValue) {
1627
- const normalized = asPosix4(pathValue);
1045
+ const normalized = asPosix3(pathValue);
1628
1046
  return /src\/modules\/[^/]+\/(public|api)\//.test(normalized) || /src\/modules\/[^/]+\/index\.(ts|tsx|js|jsx|mjs|cjs)$/.test(normalized);
1629
1047
  }
1630
1048
  function detectCleanLayer(pathValue) {
1631
- const normalized = asPosix4(pathValue);
1049
+ const normalized = asPosix3(pathValue);
1632
1050
  if (hasPath(normalized, "/src/domain/") || hasPath(normalized, "/src/core/domain/")) return "domain";
1633
1051
  if (hasPath(normalized, "/src/application/") || hasPath(normalized, "/src/core/application/")) return "application";
1634
1052
  if (hasPath(normalized, "/src/infrastructure/")) return "infrastructure";
@@ -1636,17 +1054,17 @@ function detectCleanLayer(pathValue) {
1636
1054
  return "unknown";
1637
1055
  }
1638
1056
  function detectHexLayer(pathValue) {
1639
- const normalized = asPosix4(pathValue);
1057
+ const normalized = asPosix3(pathValue);
1640
1058
  if (hasPath(normalized, "/src/core/")) return "core";
1641
1059
  if (hasPath(normalized, "/src/adapters/inbound/")) return "adapter-inbound";
1642
1060
  if (hasPath(normalized, "/src/adapters/outbound/")) return "adapter-outbound";
1643
1061
  if (hasPath(normalized, "/src/adapters/")) return "adapter-other";
1644
1062
  return "unknown";
1645
1063
  }
1646
- function activeArchitectures(config2, rules = []) {
1064
+ function activeArchitectures(config, rules = []) {
1647
1065
  const names = /* @__PURE__ */ new Set();
1648
- if (config2?.backendArchitecture) names.add(config2.backendArchitecture);
1649
- if (config2?.frontendFramework) names.add(config2.frontendFramework);
1066
+ if (config?.backendArchitecture) names.add(config.backendArchitecture);
1067
+ if (config?.frontendFramework) names.add(config.frontendFramework);
1650
1068
  const text = rules.join("\n").toLowerCase();
1651
1069
  if (text.includes("modular monolith")) names.add("modular-monolith");
1652
1070
  if (text.includes("clean architecture")) names.add("clean-architecture");
@@ -1667,13 +1085,13 @@ function evaluateFile(file, options) {
1667
1085
  const architectures = activeArchitectures(options.config, rules);
1668
1086
  const reasonLookup = options.reasonLookup ?? /* @__PURE__ */ new Map();
1669
1087
  const violations = [];
1670
- const absFile = resolve2(cwd, file);
1671
- const normalizedFile = asPosix4(file);
1088
+ const absFile = resolve(cwd, file);
1089
+ const normalizedFile = asPosix3(file);
1672
1090
  const imports = collectResolvedImports(absFile, cwd);
1673
1091
  const fromCleanLayer = detectCleanLayer(normalizedFile);
1674
1092
  const fromHexLayer = detectHexLayer(normalizedFile);
1675
1093
  for (const imp of imports) {
1676
- const target = imp.resolvedPath ? asPosix4(imp.resolvedPath) : void 0;
1094
+ const target = imp.resolvedPath ? asPosix3(imp.resolvedPath) : void 0;
1677
1095
  if (isLegacyOrCompatibilitySpecifier(imp.specifier) || isLegacyOrCompatibilityPath(target)) {
1678
1096
  const rule = "Application code must not import compatibility or legacy adapter paths";
1679
1097
  pushUnique(violations, {
@@ -1686,8 +1104,8 @@ function evaluateFile(file, options) {
1686
1104
  });
1687
1105
  }
1688
1106
  if (architectures.has("modular-monolith")) {
1689
- const fromModule = moduleNameFromPath2(normalizedFile);
1690
- const toModule = target ? moduleNameFromPath2(target) : void 0;
1107
+ const fromModule = moduleNameFromPath(normalizedFile);
1108
+ const toModule = target ? moduleNameFromPath(target) : void 0;
1691
1109
  if (fromModule && toModule && target && fromModule !== toModule && !isModulePublicPath(target)) {
1692
1110
  const rule = "Modules communicate only through public interfaces or events \u2014 never by importing internals";
1693
1111
  pushUnique(violations, {
@@ -1811,7 +1229,7 @@ function findAstDeterministicViolationsForDiff(diff, options = {}) {
1811
1229
  // src/watcher.ts
1812
1230
  function getFileLines(filePath) {
1813
1231
  try {
1814
- return readFileSync6(filePath, "utf-8").split("\n");
1232
+ return readFileSync5(filePath, "utf-8").split("\n");
1815
1233
  } catch {
1816
1234
  return [];
1817
1235
  }
@@ -1845,36 +1263,36 @@ function formatCodeContext(filePath, line, contextLines = 2) {
1845
1263
  return `${lineNum} ${marker} ${lines[current]}`;
1846
1264
  }).join("\n");
1847
1265
  }
1848
- var SOURCE_EXTENSIONS2 = /\.(ts|tsx|js|jsx|py|php|rb|go|java|cs|swift|kt|rs|vue|svelte)$/;
1266
+ var SOURCE_EXTENSIONS = /\.(ts|tsx|js|jsx|py|php|rb|go|java|cs|swift|kt|rs|vue|svelte)$/;
1849
1267
  var reasonMap = new Map(
1850
1268
  seeds.filter((s) => s.reason).map((s) => [s.content, s.reason])
1851
1269
  );
1852
1270
  function findProjectRoot(startPath) {
1853
- let current = resolve3(startPath);
1271
+ let current = resolve2(startPath);
1854
1272
  while (true) {
1855
- if (existsSync7(join7(current, ".memory-core.json"))) return current;
1856
- const parent = dirname3(current);
1273
+ if (existsSync5(join5(current, ".memory-core.json"))) return current;
1274
+ const parent = dirname2(current);
1857
1275
  if (parent === current) return null;
1858
1276
  current = parent;
1859
1277
  }
1860
1278
  }
1861
1279
  function resolveWatchPaths(pathOption, projectRootOption) {
1862
1280
  if (projectRootOption) {
1863
- const projectRoot2 = resolve3(projectRootOption);
1281
+ const projectRoot2 = resolve2(projectRootOption);
1864
1282
  return {
1865
1283
  projectRoot: projectRoot2,
1866
- watchPath: resolve3(projectRoot2, pathOption ?? ".")
1284
+ watchPath: resolve2(projectRoot2, pathOption ?? ".")
1867
1285
  };
1868
1286
  }
1869
- const cwdRoot = resolve3(process.cwd());
1870
- const watchPath = resolve3(cwdRoot, pathOption ?? ".");
1287
+ const cwdRoot = resolve2(process.cwd());
1288
+ const watchPath = resolve2(cwdRoot, pathOption ?? ".");
1871
1289
  const projectRoot = findProjectRoot(watchPath) ?? findProjectRoot(cwdRoot) ?? cwdRoot;
1872
1290
  return { projectRoot, watchPath };
1873
1291
  }
1874
1292
  function readStatsFile(statsPath) {
1875
- if (!existsSync7(statsPath)) return { rules: {}, files: {} };
1293
+ if (!existsSync5(statsPath)) return { rules: {}, files: {} };
1876
1294
  try {
1877
- return JSON.parse(readFileSync6(statsPath, "utf-8"));
1295
+ return JSON.parse(readFileSync5(statsPath, "utf-8"));
1878
1296
  } catch {
1879
1297
  return { rules: {}, files: {} };
1880
1298
  }
@@ -1892,7 +1310,7 @@ function rebuildLiveCounters(byFile) {
1892
1310
  return { rules, files };
1893
1311
  }
1894
1312
  function resetLiveStats(cwd) {
1895
- const statsPath = join7(cwd, ".memory-core-stats.json");
1313
+ const statsPath = join5(cwd, ".memory-core-stats.json");
1896
1314
  const stats = readStatsFile(statsPath);
1897
1315
  stats.rules ??= {};
1898
1316
  stats.files ??= {};
@@ -1904,7 +1322,7 @@ function resetLiveStats(cwd) {
1904
1322
  writeFileSync3(statsPath, JSON.stringify(stats, null, 2) + "\n", "utf-8");
1905
1323
  }
1906
1324
  function recordWatchResult(cwd, file, violations) {
1907
- const statsPath = join7(cwd, ".memory-core-stats.json");
1325
+ const statsPath = join5(cwd, ".memory-core-stats.json");
1908
1326
  const stats = readStatsFile(statsPath);
1909
1327
  stats.rules ??= {};
1910
1328
  stats.files ??= {};
@@ -1930,26 +1348,26 @@ function recordWatchResult(cwd, file, violations) {
1930
1348
  writeFileSync3(statsPath, JSON.stringify(stats, null, 2) + "\n", "utf-8");
1931
1349
  }
1932
1350
  function loadConfig(cwd) {
1933
- const configPath = join7(cwd, ".memory-core.json");
1934
- if (!existsSync7(configPath)) return null;
1351
+ const configPath = join5(cwd, ".memory-core.json");
1352
+ if (!existsSync5(configPath)) return null;
1935
1353
  try {
1936
- return JSON.parse(readFileSync6(configPath, "utf-8"));
1354
+ return JSON.parse(readFileSync5(configPath, "utf-8"));
1937
1355
  } catch {
1938
1356
  return null;
1939
1357
  }
1940
1358
  }
1941
- function getProfileRules(config2) {
1359
+ function getProfileRules(config) {
1942
1360
  const rules = [];
1943
1361
  const avoids = [];
1944
- if (config2.backendArchitecture) {
1945
- const profile = listProfiles("backend").find((p) => p.name === config2.backendArchitecture);
1362
+ if (config.backendArchitecture) {
1363
+ const profile = listProfiles("backend").find((p) => p.name === config.backendArchitecture);
1946
1364
  if (profile) {
1947
1365
  rules.push(...profile.rules);
1948
1366
  avoids.push(...profile.avoid);
1949
1367
  }
1950
1368
  }
1951
- if (config2.frontendFramework) {
1952
- const profile = listProfiles("frontend").find((p) => p.name === config2.frontendFramework);
1369
+ if (config.frontendFramework) {
1370
+ const profile = listProfiles("frontend").find((p) => p.name === config.frontendFramework);
1953
1371
  if (profile) {
1954
1372
  rules.push(...profile.rules);
1955
1373
  avoids.push(...profile.avoid);
@@ -1957,19 +1375,19 @@ function getProfileRules(config2) {
1957
1375
  }
1958
1376
  return { rules, avoids };
1959
1377
  }
1960
- async function loadRelevantRules(cwd, config2, rel, diff, fallbackRules) {
1378
+ async function loadRelevantRules(cwd, config, rel, diff, fallbackRules) {
1961
1379
  try {
1962
1380
  const query = buildContextQuery([
1963
1381
  rel,
1964
1382
  diff.slice(0, 1200),
1965
- config2.backendArchitecture,
1966
- config2.frontendFramework,
1967
- config2.language
1383
+ config.backendArchitecture,
1384
+ config.frontendFramework,
1385
+ config.language
1968
1386
  ]);
1969
1387
  const memories = await retrieveContextualMemories({
1970
1388
  query,
1971
1389
  cwd,
1972
- config: config2,
1390
+ config,
1973
1391
  limit: 15
1974
1392
  });
1975
1393
  const selected = memories.filter((memory) => ["rule", "pattern", "decision"].includes(memory.type)).map((memory) => memory.content);
@@ -2037,7 +1455,7 @@ function normalizeForGit(pathLike) {
2037
1455
  return pathLike.split(sep).join("/");
2038
1456
  }
2039
1457
  function listSourceFilesFromFilesystem(dir) {
2040
- if (!existsSync7(dir)) return [];
1458
+ if (!existsSync5(dir)) return [];
2041
1459
  const files = [];
2042
1460
  const stack = [dir];
2043
1461
  while (stack.length > 0) {
@@ -2049,7 +1467,7 @@ function listSourceFilesFromFilesystem(dir) {
2049
1467
  continue;
2050
1468
  }
2051
1469
  for (const entry of entries) {
2052
- const absolute = join7(current, entry);
1470
+ const absolute = join5(current, entry);
2053
1471
  let isDirectory = false;
2054
1472
  let isFile = false;
2055
1473
  try {
@@ -2066,7 +1484,7 @@ function listSourceFilesFromFilesystem(dir) {
2066
1484
  stack.push(absolute);
2067
1485
  continue;
2068
1486
  }
2069
- if (isFile && SOURCE_EXTENSIONS2.test(absolute)) files.push(absolute);
1487
+ if (isFile && SOURCE_EXTENSIONS.test(absolute)) files.push(absolute);
2070
1488
  }
2071
1489
  }
2072
1490
  return files;
@@ -2079,10 +1497,10 @@ function listTrackedSourceFiles(projectRoot, watchPath) {
2079
1497
  if (listed.status !== 0) {
2080
1498
  return listSourceFilesFromFilesystem(watchPath).sort();
2081
1499
  }
2082
- const files = (listed.stdout ?? "").split("\n").filter((file) => file.length > 0).filter((file) => SOURCE_EXTENSIONS2.test(file)).filter((file) => inRoot || file.startsWith(prefixWithSlash)).map((file) => join7(projectRoot, file)).filter((file) => existsSync7(file));
1500
+ const files = (listed.stdout ?? "").split("\n").filter((file) => file.length > 0).filter((file) => SOURCE_EXTENSIONS.test(file)).filter((file) => inRoot || file.startsWith(prefixWithSlash)).map((file) => join5(projectRoot, file)).filter((file) => existsSync5(file));
2083
1501
  return [...new Set(files)].sort();
2084
1502
  }
2085
- async function runSnapshotScan(projectRoot, watchPath, config2, verbose, debug, onEvent) {
1503
+ async function runSnapshotScan(projectRoot, watchPath, config, verbose, debug, onEvent) {
2086
1504
  const files = listTrackedSourceFiles(projectRoot, watchPath);
2087
1505
  if (files.length === 0) {
2088
1506
  console.log(chalk.yellow("\n No tracked source files found for scan.\n"));
@@ -2104,7 +1522,7 @@ async function runSnapshotScan(projectRoot, watchPath, config2, verbose, debug,
2104
1522
  const rel = normalizeForGit(relative(projectRoot, filePath));
2105
1523
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2106
1524
  onEvent?.({ type: "saved", timestamp, file: rel });
2107
- const result = await checkFile(filePath, projectRoot, config2, verbose, debug, "snapshot", onEvent);
1525
+ const result = await checkFile(filePath, projectRoot, config, verbose, debug, "snapshot", onEvent);
2108
1526
  if (result.type !== "checked") {
2109
1527
  if (result.type === "skipped") {
2110
1528
  onEvent?.({ type: "skipped", timestamp: (/* @__PURE__ */ new Date()).toISOString(), file: rel, reason: result.reason });
@@ -2125,8 +1543,8 @@ async function runSnapshotScan(projectRoot, watchPath, config2, verbose, debug,
2125
1543
  return summary;
2126
1544
  }
2127
1545
  async function autoFixFile(filePath, projectRoot, violations, rules, avoids, debug) {
2128
- if (!existsSync7(filePath)) return false;
2129
- const content = readFileSync6(filePath, "utf-8");
1546
+ if (!existsSync5(filePath)) return false;
1547
+ const content = readFileSync5(filePath, "utf-8");
2130
1548
  const rel = relative(projectRoot, filePath).split(sep).join("/");
2131
1549
  const violationSummary = violations.map(
2132
1550
  (v, i) => `${i + 1}. Rule: "${v.rule}"
@@ -2182,13 +1600,13 @@ ${content}`;
2182
1600
  return false;
2183
1601
  }
2184
1602
  }
2185
- async function checkFile(filePath, projectRoot, config2, verbose, debug, mode = "diff", onEvent) {
1603
+ async function checkFile(filePath, projectRoot, config, verbose, debug, mode = "diff", onEvent) {
2186
1604
  const rel = relative(projectRoot, filePath).split(sep).join("/");
2187
1605
  if (rel.startsWith("..")) return { type: "skipped", reason: "File is outside project root" };
2188
1606
  let inputText;
2189
1607
  if (mode === "snapshot") {
2190
- if (!existsSync7(filePath)) return { type: "skipped", reason: "File no longer exists" };
2191
- inputText = readFileSync6(filePath, "utf-8");
1608
+ if (!existsSync5(filePath)) return { type: "skipped", reason: "File no longer exists" };
1609
+ inputText = readFileSync5(filePath, "utf-8");
2192
1610
  if (!inputText.trim()) return { type: "skipped", reason: "File is empty" };
2193
1611
  } else {
2194
1612
  const headResult = spawnSync("git", ["diff", "HEAD", "--", rel], { encoding: "utf-8", cwd: projectRoot });
@@ -2203,8 +1621,8 @@ async function checkFile(filePath, projectRoot, config2, verbose, debug, mode =
2203
1621
  }
2204
1622
  if (!inputText.trim()) return { type: "skipped", reason: "No changes compared with HEAD" };
2205
1623
  }
2206
- const { rules: fallbackRules, avoids } = getProfileRules(config2);
2207
- const rules = await loadRelevantRules(projectRoot, config2, rel, inputText, fallbackRules);
1624
+ const { rules: fallbackRules, avoids } = getProfileRules(config);
1625
+ const rules = await loadRelevantRules(projectRoot, config, rel, inputText, fallbackRules);
2208
1626
  if (rules.length === 0) return { type: "skipped", reason: "No applicable architecture rules" };
2209
1627
  const MAX_INPUT = 6e3;
2210
1628
  const truncated = inputText.length > MAX_INPUT;
@@ -2219,10 +1637,10 @@ async function checkFile(filePath, projectRoot, config2, verbose, debug, mode =
2219
1637
  return why ? `${i + 1}. ${r}
2220
1638
  WHY: ${why}` : `${i + 1}. ${r}`;
2221
1639
  }).join("\n");
2222
- const allowPatterns = [.../* @__PURE__ */ new Set([...getAllowPatterns(config2), ...await loadIgnorePatterns()])];
1640
+ const allowPatterns = [.../* @__PURE__ */ new Set([...getAllowPatterns(config), ...await loadIgnorePatterns()])];
2223
1641
  const astViolations = findAstDeterministicViolationsForFile(rel, {
2224
1642
  cwd: projectRoot,
2225
- config: config2,
1643
+ config,
2226
1644
  rules,
2227
1645
  reasonLookup: reasonMap
2228
1646
  }).map((violation) => ({
@@ -2309,7 +1727,7 @@ ${inputToSend}`;
2309
1727
  console.log(chalk.yellow(" Rule: ") + v.rule);
2310
1728
  const why = v.reason ?? reasonMap.get(v.rule);
2311
1729
  if (why) console.log(chalk.dim(" Why: ") + chalk.dim(why));
2312
- if (v.line && existsSync7(filePath)) {
1730
+ if (v.line && existsSync5(filePath)) {
2313
1731
  printCodeContext(filePath, v.line, 1);
2314
1732
  }
2315
1733
  if (v.issue) console.log(chalk.red(" Issue: ") + v.issue);
@@ -2345,7 +1763,7 @@ ${inputToSend}`;
2345
1763
  console.log(chalk.yellow(" Rule: ") + v.rule);
2346
1764
  const why = v.reason ?? reasonMap.get(v.rule);
2347
1765
  if (why) console.log(chalk.dim(" Why: ") + chalk.dim(why));
2348
- if (v.line && existsSync7(filePath)) {
1766
+ if (v.line && existsSync5(filePath)) {
2349
1767
  printCodeContext(filePath, v.line, 1);
2350
1768
  }
2351
1769
  if (v.issue) console.log(chalk.red(" Issue: ") + v.issue);
@@ -2360,11 +1778,11 @@ ${inputToSend}`;
2360
1778
  }
2361
1779
  async function scanFiles(options = {}) {
2362
1780
  const { projectRoot, watchPath } = resolveWatchPaths(options.path, options.projectRoot);
2363
- const config2 = loadConfig(projectRoot);
2364
- if (!config2) {
1781
+ const config = loadConfig(projectRoot);
1782
+ if (!config) {
2365
1783
  throw new Error("No .memory-core.json found. Run: memory-core init");
2366
1784
  }
2367
- const { rules } = getProfileRules(config2);
1785
+ const { rules } = getProfileRules(config);
2368
1786
  if (rules.length === 0) {
2369
1787
  console.log(chalk.yellow("\n No architecture rules configured in .memory-core.json \u2014 nothing to scan.\n"));
2370
1788
  return {
@@ -2383,7 +1801,7 @@ async function scanFiles(options = {}) {
2383
1801
  const summary = await runSnapshotScan(
2384
1802
  projectRoot,
2385
1803
  watchPath,
2386
- config2,
1804
+ config,
2387
1805
  options.verbose ?? false,
2388
1806
  options.debug ?? false,
2389
1807
  options.onEvent
@@ -2399,9 +1817,9 @@ async function scanFiles(options = {}) {
2399
1817
  }
2400
1818
  async function startWatch(options = {}) {
2401
1819
  const { projectRoot, watchPath } = resolveWatchPaths(options.path, options.projectRoot);
2402
- const config2 = loadConfig(projectRoot);
1820
+ const config = loadConfig(projectRoot);
2403
1821
  const exitOnSetupFailure = options.exitOnSetupFailure ?? true;
2404
- if (!config2) {
1822
+ if (!config) {
2405
1823
  const message = "No .memory-core.json found. Run: memory-core init";
2406
1824
  console.error(chalk.red(`
2407
1825
  ${message}
@@ -2410,7 +1828,7 @@ async function startWatch(options = {}) {
2410
1828
  if (exitOnSetupFailure) process.exit(1);
2411
1829
  return;
2412
1830
  }
2413
- const { rules, avoids } = getProfileRules(config2);
1831
+ const { rules, avoids } = getProfileRules(config);
2414
1832
  if (rules.length === 0) {
2415
1833
  const message = "No architecture rules configured in .memory-core.json \u2014 nothing to watch.";
2416
1834
  console.log(chalk.yellow(`
@@ -2440,7 +1858,7 @@ async function startWatch(options = {}) {
2440
1858
  await runSnapshotScan(
2441
1859
  projectRoot,
2442
1860
  watchPath,
2443
- config2,
1861
+ config,
2444
1862
  options.verbose ?? false,
2445
1863
  options.debug ?? false,
2446
1864
  options.onEvent
@@ -2464,7 +1882,7 @@ async function startWatch(options = {}) {
2464
1882
  const keepAlive = setInterval(() => {
2465
1883
  }, 1 << 30);
2466
1884
  const handle = (filePath) => {
2467
- if (!SOURCE_EXTENSIONS2.test(filePath)) return;
1885
+ if (!SOURCE_EXTENSIONS.test(filePath)) return;
2468
1886
  if (pending.has(filePath)) clearTimeout(pending.get(filePath));
2469
1887
  const timer = setTimeout(async () => {
2470
1888
  pending.delete(filePath);
@@ -2477,7 +1895,7 @@ async function startWatch(options = {}) {
2477
1895
  const result = await checkFile(
2478
1896
  filePath,
2479
1897
  projectRoot,
2480
- config2,
1898
+ config,
2481
1899
  options.verbose ?? false,
2482
1900
  options.debug ?? false,
2483
1901
  "diff",
@@ -2699,18 +2117,18 @@ var RuleEngineService = class {
2699
2117
 
2700
2118
  // src/modules/graph-engine/application/graph-engine-service.ts
2701
2119
  import { readdirSync as readdirSync2, statSync as statSync2 } from "fs";
2702
- import { join as join8, relative as relative2, resolve as resolve4 } from "path";
2703
- var SOURCE_EXTENSIONS3 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
2120
+ import { join as join6, relative as relative2, resolve as resolve3 } from "path";
2121
+ var SOURCE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
2704
2122
  var IGNORED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", "coverage", ".memory-core"]);
2705
2123
  function isSourceFile(pathValue) {
2706
2124
  const extension = pathValue.slice(pathValue.lastIndexOf("."));
2707
- return SOURCE_EXTENSIONS3.has(extension);
2125
+ return SOURCE_EXTENSIONS2.has(extension);
2708
2126
  }
2709
- function asPosix5(value) {
2127
+ function asPosix4(value) {
2710
2128
  return value.replace(/\\/g, "/");
2711
2129
  }
2712
2130
  function normalizeNode(pathValue) {
2713
- return asPosix5(pathValue);
2131
+ return asPosix4(pathValue);
2714
2132
  }
2715
2133
  function edgeKey(edge) {
2716
2134
  return `${edge.from}\0${edge.to}\0${edge.kind}`;
@@ -2734,19 +2152,19 @@ var GraphEngineService = class {
2734
2152
  }
2735
2153
  graphRepository;
2736
2154
  async buildGraph(options = {}) {
2737
- const cwd = resolve4(options.cwd ?? process.cwd());
2155
+ const cwd = resolve3(options.cwd ?? process.cwd());
2738
2156
  const files = this.collectSourceFiles(cwd);
2739
2157
  const nodes = /* @__PURE__ */ new Set();
2740
2158
  const edges = /* @__PURE__ */ new Map();
2741
2159
  for (const relativeFile of files) {
2742
- const absoluteFile = resolve4(cwd, relativeFile);
2160
+ const absoluteFile = resolve3(cwd, relativeFile);
2743
2161
  const fromNode = normalizeNode(relativeFile);
2744
2162
  nodes.add(fromNode);
2745
2163
  const imports = collectResolvedImports(absoluteFile, cwd);
2746
2164
  for (const imp of imports) {
2747
2165
  let toNode;
2748
2166
  if (imp.resolvedPath) {
2749
- toNode = normalizeNode(asPosix5(relative2(cwd, imp.resolvedPath)));
2167
+ toNode = normalizeNode(asPosix4(relative2(cwd, imp.resolvedPath)));
2750
2168
  } else if (imp.isExternal) {
2751
2169
  toNode = `pkg:${imp.specifier}`;
2752
2170
  }
@@ -2817,13 +2235,13 @@ var GraphEngineService = class {
2817
2235
  const walk = (dir) => {
2818
2236
  for (const entry of readdirSync2(dir)) {
2819
2237
  if (IGNORED_DIRS.has(entry)) continue;
2820
- const absolutePath = join8(dir, entry);
2238
+ const absolutePath = join6(dir, entry);
2821
2239
  const stat = statSync2(absolutePath);
2822
2240
  if (stat.isDirectory()) {
2823
2241
  walk(absolutePath);
2824
2242
  continue;
2825
2243
  }
2826
- const rel = asPosix5(relative2(cwd, absolutePath));
2244
+ const rel = asPosix4(relative2(cwd, absolutePath));
2827
2245
  if (isSourceFile(rel)) files.push(rel);
2828
2246
  }
2829
2247
  };
@@ -2965,11 +2383,11 @@ function getStackReason(memory, activeArchitectures2) {
2965
2383
  reason: `excluded: tagged for ${architectureKeys.join(", ")}; active stack is ${active}`
2966
2384
  };
2967
2385
  }
2968
- function inferProjectArchitectures(cwd = process.cwd(), config2) {
2386
+ function inferProjectArchitectures(cwd = process.cwd(), config) {
2969
2387
  const inferred = /* @__PURE__ */ new Set();
2970
- if (config2?.backendArchitecture && config2.backendArchitecture !== "custom") inferred.add(config2.backendArchitecture);
2971
- if (config2?.frontendFramework && config2.frontendFramework !== "custom") inferred.add(config2.frontendFramework);
2972
- if (config2?.projectType === "backend" && !config2.backendArchitecture) {
2388
+ if (config?.backendArchitecture && config.backendArchitecture !== "custom") inferred.add(config.backendArchitecture);
2389
+ if (config?.frontendFramework && config.frontendFramework !== "custom") inferred.add(config.frontendFramework);
2390
+ if (config?.projectType === "backend" && !config.backendArchitecture) {
2973
2391
  inferred.add("clean-architecture");
2974
2392
  }
2975
2393
  const detected = detectProject(cwd);
@@ -2978,14 +2396,14 @@ function inferProjectArchitectures(cwd = process.cwd(), config2) {
2978
2396
  }
2979
2397
  return [...inferred];
2980
2398
  }
2981
- function getAllowPatterns(config2) {
2982
- return [...new Set(config2?.allowPatterns?.filter(Boolean) ?? [])];
2399
+ function getAllowPatterns(config) {
2400
+ return [...new Set(config?.allowPatterns?.filter(Boolean) ?? [])];
2983
2401
  }
2984
- function filterRelevantMemories(memories, config2, cwd = process.cwd()) {
2985
- return explainMemorySelection(memories, config2, cwd).included;
2402
+ function filterRelevantMemories(memories, config, cwd = process.cwd()) {
2403
+ return explainMemorySelection(memories, config, cwd).included;
2986
2404
  }
2987
- function explainMemorySelection(memories, config2, cwd = process.cwd(), threshold = 0.8) {
2988
- const activeArchitectures2 = inferProjectArchitectures(cwd, config2);
2405
+ function explainMemorySelection(memories, config, cwd = process.cwd(), threshold = 0.8) {
2406
+ const activeArchitectures2 = inferProjectArchitectures(cwd, config);
2989
2407
  const activeSet = new Set(activeArchitectures2);
2990
2408
  const included = [];
2991
2409
  const decisions = [];
@@ -3061,8 +2479,8 @@ async function retrieveMemorySelection(options) {
3061
2479
 
3062
2480
  // src/generator.ts
3063
2481
  var __filename = fileURLToPath(import.meta.url);
3064
- var __dirname = dirname4(__filename);
3065
- var PKG_ROOT = join9(__dirname, "..");
2482
+ var __dirname = dirname3(__filename);
2483
+ var PKG_ROOT = join7(__dirname, "..");
3066
2484
  function stringifyProfileScalar(value) {
3067
2485
  if (typeof value === "string") {
3068
2486
  const trimmed = value.trim();
@@ -3153,15 +2571,15 @@ function loadProfile(name) {
3153
2571
  if (name === "custom") {
3154
2572
  return { name: "custom", displayName: "Custom", layer: "backend", description: "Custom architecture \u2014 rules added via memory-core remember", rules: [], folders: [], avoid: [] };
3155
2573
  }
3156
- const profilePath = join9(PKG_ROOT, "profiles", `${name}.yml`);
3157
- if (!existsSync8(profilePath)) throw new Error(`Profile not found: ${name}`);
3158
- return normalizeArchitectureProfile(yaml.load(readFileSync7(profilePath, "utf-8")), name);
2574
+ const profilePath = join7(PKG_ROOT, "profiles", `${name}.yml`);
2575
+ if (!existsSync6(profilePath)) throw new Error(`Profile not found: ${name}`);
2576
+ return normalizeArchitectureProfile(yaml.load(readFileSync6(profilePath, "utf-8")), name);
3159
2577
  }
3160
2578
  function listProfiles(layer) {
3161
- const files = readdirSync3(join9(PKG_ROOT, "profiles")).filter((f) => f.endsWith(".yml"));
2579
+ const files = readdirSync3(join7(PKG_ROOT, "profiles")).filter((f) => f.endsWith(".yml"));
3162
2580
  const all = files.map(
3163
2581
  (f) => normalizeArchitectureProfile(
3164
- yaml.load(readFileSync7(join9(PKG_ROOT, "profiles", f), "utf-8")),
2582
+ yaml.load(readFileSync6(join7(PKG_ROOT, "profiles", f), "utf-8")),
3165
2583
  basename(f, ".yml")
3166
2584
  )
3167
2585
  );
@@ -3231,15 +2649,15 @@ function buildTemplateData(options, cwd = process.cwd()) {
3231
2649
  };
3232
2650
  }
3233
2651
  function renderTemplate(templateName, data) {
3234
- const templatePath = join9(PKG_ROOT, "templates", templateName);
3235
- if (!existsSync8(templatePath)) throw new Error(`Template not found: ${templateName}`);
3236
- return Handlebars.compile(readFileSync7(templatePath, "utf-8"))(data);
2652
+ const templatePath = join7(PKG_ROOT, "templates", templateName);
2653
+ if (!existsSync6(templatePath)) throw new Error(`Template not found: ${templateName}`);
2654
+ return Handlebars.compile(readFileSync6(templatePath, "utf-8"))(data);
3237
2655
  }
3238
2656
  function writeFile(filePath, content) {
3239
- const dir = dirname4(filePath);
3240
- if (!existsSync8(dir)) mkdirSync2(dir, { recursive: true });
3241
- if (existsSync8(filePath)) {
3242
- const existing = readFileSync7(filePath, "utf-8");
2657
+ const dir = dirname3(filePath);
2658
+ if (!existsSync6(dir)) mkdirSync2(dir, { recursive: true });
2659
+ if (existsSync6(filePath)) {
2660
+ const existing = readFileSync6(filePath, "utf-8");
3243
2661
  if (existing === content) return "skipped";
3244
2662
  }
3245
2663
  writeFileSync4(filePath, content, "utf-8");
@@ -3251,8 +2669,8 @@ async function generate(options, cwd = process.cwd(), onlyAgents) {
3251
2669
  const skipped = [];
3252
2670
  const files = onlyAgents ? OUTPUT_FILES.filter((f) => onlyAgents.includes(f.agent)) : OUTPUT_FILES;
3253
2671
  for (const output of files) {
3254
- const targetPath = join9(cwd, output.path);
3255
- if (output.skipIfExists && existsSync8(targetPath)) {
2672
+ const targetPath = join7(cwd, output.path);
2673
+ if (output.skipIfExists && existsSync6(targetPath)) {
3256
2674
  skipped.push(output.path);
3257
2675
  continue;
3258
2676
  }
@@ -3272,9 +2690,9 @@ async function generate(options, cwd = process.cwd(), onlyAgents) {
3272
2690
  var reasonMap2 = new Map(
3273
2691
  seeds.filter((s) => s.reason).map((s) => [s.content, s.reason])
3274
2692
  );
3275
- var HOOK_PATH = join10(".git", "hooks", "pre-commit");
2693
+ var HOOK_PATH = join8(".git", "hooks", "pre-commit");
3276
2694
  var HOOK_MARKER = "# archmind-memory-core";
3277
- var COMMIT_MSG_HOOK_PATH = join10(".git", "hooks", "commit-msg");
2695
+ var COMMIT_MSG_HOOK_PATH = join8(".git", "hooks", "commit-msg");
3278
2696
  var COMMIT_MSG_HOOK_MARKER = "# archmind-memory-core commit-msg";
3279
2697
  var RULE_CACHE_FILE = ".memory-core-rules-cache.json";
3280
2698
  var DB_VERSION_FILE = ".memory-core-db-version";
@@ -3334,7 +2752,7 @@ function toRuleStatEntry(raw) {
3334
2752
  if (typeof raw === "number") return { count: raw, falsePositives: 0 };
3335
2753
  return raw;
3336
2754
  }
3337
- function readPositiveIntEnv2(name, fallback) {
2755
+ function readPositiveIntEnv(name, fallback) {
3338
2756
  const raw = Number(process.env[name]);
3339
2757
  return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : fallback;
3340
2758
  }
@@ -3346,8 +2764,8 @@ async function withTimeout(promise, timeoutMs, fallback) {
3346
2764
  try {
3347
2765
  return await Promise.race([
3348
2766
  promise,
3349
- new Promise((resolve5) => {
3350
- timer = setTimeout(() => resolve5(fallback), timeoutMs);
2767
+ new Promise((resolve4) => {
2768
+ timer = setTimeout(() => resolve4(fallback), timeoutMs);
3351
2769
  })
3352
2770
  ]);
3353
2771
  } finally {
@@ -3355,11 +2773,11 @@ async function withTimeout(promise, timeoutMs, fallback) {
3355
2773
  }
3356
2774
  }
3357
2775
  function recordViolations(violations, source = "hook") {
3358
- const statsPath = join10(process.cwd(), ".memory-core-stats.json");
2776
+ const statsPath = join8(process.cwd(), ".memory-core-stats.json");
3359
2777
  let stats = { rules: {}, files: {} };
3360
- if (existsSync9(statsPath)) {
2778
+ if (existsSync7(statsPath)) {
3361
2779
  try {
3362
- stats = JSON.parse(readFileSync8(statsPath, "utf-8"));
2780
+ stats = JSON.parse(readFileSync7(statsPath, "utf-8"));
3363
2781
  } catch {
3364
2782
  stats = { rules: {}, files: {} };
3365
2783
  }
@@ -3377,11 +2795,11 @@ function recordViolations(violations, source = "hook") {
3377
2795
  writeFileSync5(statsPath, JSON.stringify(stats, null, 2) + "\n", "utf-8");
3378
2796
  }
3379
2797
  function resetViolationStats(cwd = process.cwd()) {
3380
- const statsPath = join10(cwd, ".memory-core-stats.json");
3381
- if (!existsSync9(statsPath)) return;
2798
+ const statsPath = join8(cwd, ".memory-core-stats.json");
2799
+ if (!existsSync7(statsPath)) return;
3382
2800
  let stats = {};
3383
2801
  try {
3384
- const parsed = JSON.parse(readFileSync8(statsPath, "utf-8"));
2802
+ const parsed = JSON.parse(readFileSync7(statsPath, "utf-8"));
3385
2803
  if (parsed && typeof parsed === "object") {
3386
2804
  stats = parsed;
3387
2805
  }
@@ -3394,11 +2812,11 @@ function resetViolationStats(cwd = process.cwd()) {
3394
2812
  writeFileSync5(statsPath, JSON.stringify(stats, null, 2) + "\n", "utf-8");
3395
2813
  }
3396
2814
  function recordBypass(hadReason, cwd = process.cwd()) {
3397
- const statsPath = join10(cwd, ".memory-core-stats.json");
2815
+ const statsPath = join8(cwd, ".memory-core-stats.json");
3398
2816
  let stats = { rules: {}, files: {} };
3399
- if (existsSync9(statsPath)) {
2817
+ if (existsSync7(statsPath)) {
3400
2818
  try {
3401
- stats = JSON.parse(readFileSync8(statsPath, "utf-8"));
2819
+ stats = JSON.parse(readFileSync7(statsPath, "utf-8"));
3402
2820
  } catch {
3403
2821
  }
3404
2822
  }
@@ -3412,10 +2830,10 @@ function recordBypass(hadReason, cwd = process.cwd()) {
3412
2830
  return stats.bypasses;
3413
2831
  }
3414
2832
  function readBypassStats(cwd = process.cwd()) {
3415
- const statsPath = join10(cwd, ".memory-core-stats.json");
3416
- if (!existsSync9(statsPath)) return { total: 0, withReason: 0, withoutReason: 0 };
2833
+ const statsPath = join8(cwd, ".memory-core-stats.json");
2834
+ if (!existsSync7(statsPath)) return { total: 0, withReason: 0, withoutReason: 0 };
3417
2835
  try {
3418
- const stats = JSON.parse(readFileSync8(statsPath, "utf-8"));
2836
+ const stats = JSON.parse(readFileSync7(statsPath, "utf-8"));
3419
2837
  return stats.bypasses ?? { total: 0, withReason: 0, withoutReason: 0 };
3420
2838
  } catch {
3421
2839
  return { total: 0, withReason: 0, withoutReason: 0 };
@@ -3423,11 +2841,11 @@ function readBypassStats(cwd = process.cwd()) {
3423
2841
  }
3424
2842
  function accumulateTokenUsage(usage, cwd = process.cwd()) {
3425
2843
  if (!usage) return;
3426
- const statsPath = join10(cwd, ".memory-core-stats.json");
2844
+ const statsPath = join8(cwd, ".memory-core-stats.json");
3427
2845
  let stats = { rules: {}, files: {} };
3428
- if (existsSync9(statsPath)) {
2846
+ if (existsSync7(statsPath)) {
3429
2847
  try {
3430
- stats = JSON.parse(readFileSync8(statsPath, "utf-8"));
2848
+ stats = JSON.parse(readFileSync7(statsPath, "utf-8"));
3431
2849
  } catch {
3432
2850
  }
3433
2851
  }
@@ -3471,17 +2889,17 @@ async function promptToSaveViolations(violations) {
3471
2889
  }
3472
2890
  }
3473
2891
  function readRuleCache(cwd) {
3474
- const cachePath = join10(cwd, RULE_CACHE_FILE);
3475
- const configPath = join10(cwd, ".memory-core.json");
3476
- if (!existsSync9(cachePath) || !existsSync9(configPath)) return null;
2892
+ const cachePath = join8(cwd, RULE_CACHE_FILE);
2893
+ const configPath = join8(cwd, ".memory-core.json");
2894
+ if (!existsSync7(cachePath) || !existsSync7(configPath)) return null;
3477
2895
  try {
3478
- const entry = JSON.parse(readFileSync8(cachePath, "utf-8"));
2896
+ const entry = JSON.parse(readFileSync7(cachePath, "utf-8"));
3479
2897
  const now = Date.now();
3480
2898
  if (now - entry.timestamp > RULE_CACHE_TTL_MS) return null;
3481
2899
  const configMtime = statSync3(configPath).mtimeMs;
3482
2900
  if (configMtime !== entry.configMtime) return null;
3483
- const dbVersionPath = join10(cwd, DB_VERSION_FILE);
3484
- const dbVersionMtime = existsSync9(dbVersionPath) ? statSync3(dbVersionPath).mtimeMs : 0;
2901
+ const dbVersionPath = join8(cwd, DB_VERSION_FILE);
2902
+ const dbVersionMtime = existsSync7(dbVersionPath) ? statSync3(dbVersionPath).mtimeMs : 0;
3485
2903
  if (dbVersionMtime !== entry.dbVersionMtime) return null;
3486
2904
  return entry;
3487
2905
  } catch {
@@ -3489,18 +2907,18 @@ function readRuleCache(cwd) {
3489
2907
  }
3490
2908
  }
3491
2909
  function saveRuleCache(cwd, data) {
3492
- const configPath = join10(cwd, ".memory-core.json");
2910
+ const configPath = join8(cwd, ".memory-core.json");
3493
2911
  try {
3494
2912
  const configMtime = statSync3(configPath).mtimeMs;
3495
- const dbVersionPath = join10(cwd, DB_VERSION_FILE);
3496
- const dbVersionMtime = existsSync9(dbVersionPath) ? statSync3(dbVersionPath).mtimeMs : 0;
2913
+ const dbVersionPath = join8(cwd, DB_VERSION_FILE);
2914
+ const dbVersionMtime = existsSync7(dbVersionPath) ? statSync3(dbVersionPath).mtimeMs : 0;
3497
2915
  const entry = {
3498
2916
  timestamp: Date.now(),
3499
2917
  configMtime,
3500
2918
  dbVersionMtime,
3501
2919
  ...data
3502
2920
  };
3503
- writeFileSync5(join10(cwd, RULE_CACHE_FILE), JSON.stringify(entry, null, 2) + "\n", "utf-8");
2921
+ writeFileSync5(join8(cwd, RULE_CACHE_FILE), JSON.stringify(entry, null, 2) + "\n", "utf-8");
3504
2922
  } catch {
3505
2923
  }
3506
2924
  }
@@ -3513,18 +2931,18 @@ async function loadIgnorePatterns2() {
3513
2931
  return [];
3514
2932
  }
3515
2933
  }
3516
- function getProfileRules2(config2) {
2934
+ function getProfileRules2(config) {
3517
2935
  const rules = [];
3518
2936
  const avoids = [];
3519
- if (config2.backendArchitecture) {
3520
- const profile = listProfiles("backend").find((p) => p.name === config2.backendArchitecture);
2937
+ if (config.backendArchitecture) {
2938
+ const profile = listProfiles("backend").find((p) => p.name === config.backendArchitecture);
3521
2939
  if (profile) {
3522
2940
  rules.push(...profile.rules);
3523
2941
  avoids.push(...profile.avoid);
3524
2942
  }
3525
2943
  }
3526
- if (config2.frontendFramework) {
3527
- const profile = listProfiles("frontend").find((p) => p.name === config2.frontendFramework);
2944
+ if (config.frontendFramework) {
2945
+ const profile = listProfiles("frontend").find((p) => p.name === config.frontendFramework);
3528
2946
  if (profile) {
3529
2947
  rules.push(...profile.rules);
3530
2948
  avoids.push(...profile.avoid);
@@ -3532,19 +2950,19 @@ function getProfileRules2(config2) {
3532
2950
  }
3533
2951
  return { rules, avoids };
3534
2952
  }
3535
- async function loadRelevantRules2(config2, diff, stagedFiles, fallbackRules) {
2953
+ async function loadRelevantRules2(config, diff, stagedFiles, fallbackRules) {
3536
2954
  try {
3537
2955
  const query = buildContextQuery([
3538
2956
  stagedFiles.join("\n"),
3539
2957
  diff.slice(0, 1200),
3540
- config2.backendArchitecture,
3541
- config2.frontendFramework,
3542
- config2.language
2958
+ config.backendArchitecture,
2959
+ config.frontendFramework,
2960
+ config.language
3543
2961
  ]);
3544
2962
  const memories = await retrieveContextualMemories({
3545
2963
  query,
3546
2964
  cwd: process.cwd(),
3547
- config: config2,
2965
+ config,
3548
2966
  limit: 15
3549
2967
  });
3550
2968
  const selected = memories.filter((memory) => ["rule", "pattern", "decision"].includes(memory.type)).map((memory) => memory.content);
@@ -3725,10 +3143,10 @@ function parseFalsePositiveDecisions(raw) {
3725
3143
  return { valid: false, decisions: [] };
3726
3144
  }
3727
3145
  function loadRecentViolationsFromStats(cwd = process.cwd()) {
3728
- const statsPath = join10(cwd, ".memory-core-stats.json");
3729
- if (!existsSync9(statsPath)) return [];
3146
+ const statsPath = join8(cwd, ".memory-core-stats.json");
3147
+ if (!existsSync7(statsPath)) return [];
3730
3148
  try {
3731
- const parsed = JSON.parse(readFileSync8(statsPath, "utf-8"));
3149
+ const parsed = JSON.parse(readFileSync7(statsPath, "utf-8"));
3732
3150
  if (!Array.isArray(parsed.recentViolations)) return [];
3733
3151
  return parsed.recentViolations.filter(
3734
3152
  (entry) => Boolean(entry) && typeof entry.rule === "string" && typeof entry.issue === "string" && typeof entry.file === "string" && typeof entry.timestamp === "string"
@@ -3739,11 +3157,11 @@ function loadRecentViolationsFromStats(cwd = process.cwd()) {
3739
3157
  }
3740
3158
  function incrementFalsePositivesForPatterns(learnedPatterns, violations, cwd = process.cwd()) {
3741
3159
  if (learnedPatterns.length === 0 || violations.length === 0) return;
3742
- const statsPath = join10(cwd, ".memory-core-stats.json");
3743
- if (!existsSync9(statsPath)) return;
3160
+ const statsPath = join8(cwd, ".memory-core-stats.json");
3161
+ if (!existsSync7(statsPath)) return;
3744
3162
  let stats;
3745
3163
  try {
3746
- stats = JSON.parse(readFileSync8(statsPath, "utf-8"));
3164
+ stats = JSON.parse(readFileSync7(statsPath, "utf-8"));
3747
3165
  } catch {
3748
3166
  return;
3749
3167
  }
@@ -3787,7 +3205,7 @@ ${JSON.stringify(options.allowPatterns, null, 2)}`;
3787
3205
  console.log(chalk2.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
3788
3206
  }
3789
3207
  try {
3790
- const recheckTimeoutMs = readPositiveIntEnv2("MEMORY_CORE_FALSE_POSITIVE_TIMEOUT_MS", 6e3);
3208
+ const recheckTimeoutMs = readPositiveIntEnv("MEMORY_CORE_FALSE_POSITIVE_TIMEOUT_MS", 6e3);
3791
3209
  const { content: raw, usage: recheckUsage } = await callChatModel([
3792
3210
  { role: "system", content: systemPrompt },
3793
3211
  { role: "user", content: userPrompt }
@@ -3963,14 +3381,14 @@ function filterModelViolationsByStagedDiff(violations, stagedFiles, diff) {
3963
3381
  return filtered;
3964
3382
  }
3965
3383
  function installHook(advisory = true, fast = false) {
3966
- if (!existsSync9(".git")) {
3384
+ if (!existsSync7(".git")) {
3967
3385
  console.error(chalk2.red("\n Not a git repository. Run from project root.\n"));
3968
3386
  process.exit(1);
3969
3387
  }
3970
3388
  const script = buildHookScript(advisory, fast);
3971
3389
  const body = buildHookBody(advisory, fast).trimEnd();
3972
- if (existsSync9(HOOK_PATH)) {
3973
- const existing = readFileSync8(HOOK_PATH, "utf-8");
3390
+ if (existsSync7(HOOK_PATH)) {
3391
+ const existing = readFileSync7(HOOK_PATH, "utf-8");
3974
3392
  if (existing.includes(HOOK_MARKER)) {
3975
3393
  const markerIndex = existing.indexOf(HOOK_MARKER);
3976
3394
  const beforeRaw = markerIndex > 0 ? existing.slice(0, markerIndex) : "";
@@ -4002,11 +3420,11 @@ ${body}
4002
3420
  console.log(chalk2.gray(" To uninstall: memory-core hook uninstall\n"));
4003
3421
  }
4004
3422
  function uninstallHook() {
4005
- if (!existsSync9(HOOK_PATH)) {
3423
+ if (!existsSync7(HOOK_PATH)) {
4006
3424
  console.log(chalk2.yellow("\n No pre-commit hook found.\n"));
4007
3425
  return;
4008
3426
  }
4009
- const content = readFileSync8(HOOK_PATH, "utf-8");
3427
+ const content = readFileSync7(HOOK_PATH, "utf-8");
4010
3428
  if (!content.includes(HOOK_MARKER)) {
4011
3429
  console.log(chalk2.yellow("\n ArchMind hook not found in pre-commit \u2014 nothing to remove.\n"));
4012
3430
  return;
@@ -4051,8 +3469,8 @@ function installCommitMsgHook(advisory = true) {
4051
3469
 
4052
3470
  ${body}
4053
3471
  `;
4054
- if (existsSync9(COMMIT_MSG_HOOK_PATH)) {
4055
- const existing = readFileSync8(COMMIT_MSG_HOOK_PATH, "utf-8");
3472
+ if (existsSync7(COMMIT_MSG_HOOK_PATH)) {
3473
+ const existing = readFileSync7(COMMIT_MSG_HOOK_PATH, "utf-8");
4056
3474
  if (existing.includes(COMMIT_MSG_HOOK_MARKER)) {
4057
3475
  const markerIndex = existing.indexOf(COMMIT_MSG_HOOK_MARKER);
4058
3476
  const beforeRaw = markerIndex > 0 ? existing.slice(0, markerIndex) : "";
@@ -4073,8 +3491,8 @@ ${body}
4073
3491
  chmodSync(COMMIT_MSG_HOOK_PATH, 493);
4074
3492
  }
4075
3493
  function uninstallCommitMsgHook() {
4076
- if (!existsSync9(COMMIT_MSG_HOOK_PATH)) return;
4077
- const content = readFileSync8(COMMIT_MSG_HOOK_PATH, "utf-8");
3494
+ if (!existsSync7(COMMIT_MSG_HOOK_PATH)) return;
3495
+ const content = readFileSync7(COMMIT_MSG_HOOK_PATH, "utf-8");
4078
3496
  if (!content.includes(COMMIT_MSG_HOOK_MARKER)) return;
4079
3497
  const markerIndex = content.indexOf(COMMIT_MSG_HOOK_MARKER);
4080
3498
  const before = markerIndex > 1 ? normalizeHookPreamble(content.slice(0, markerIndex)) : "";
@@ -4086,20 +3504,20 @@ function uninstallCommitMsgHook() {
4086
3504
  }
4087
3505
  }
4088
3506
  async function checkCommitMsg(msgFile, options = {}) {
4089
- if (!existsSync9(msgFile)) {
3507
+ if (!existsSync7(msgFile)) {
4090
3508
  if (options.verbose) console.log(chalk2.gray(" No commit message file \u2014 skipping."));
4091
3509
  return;
4092
3510
  }
4093
- const raw = readFileSync8(msgFile, "utf-8");
3511
+ const raw = readFileSync7(msgFile, "utf-8");
4094
3512
  const cleanMsg = raw.split("\n").filter((l) => !l.startsWith("#")).join("\n").trim();
4095
3513
  if (!cleanMsg) {
4096
3514
  if (options.verbose) console.log(chalk2.gray(" Empty commit message \u2014 skipping."));
4097
3515
  return;
4098
3516
  }
4099
- const configPath = join10(process.cwd(), ".memory-core.json");
4100
- if (!existsSync9(configPath)) return;
4101
- const config2 = JSON.parse(readFileSync8(configPath, "utf-8"));
4102
- const rules = (config2.commitRules ?? []).filter(Boolean);
3517
+ const configPath = join8(process.cwd(), ".memory-core.json");
3518
+ if (!existsSync7(configPath)) return;
3519
+ const config = JSON.parse(readFileSync7(configPath, "utf-8"));
3520
+ const rules = (config.commitRules ?? []).filter(Boolean);
4103
3521
  if (rules.length === 0) return;
4104
3522
  console.log(chalk2.cyan("\n archmind \u2014 checking commit message\u2026"));
4105
3523
  const violations = [];
@@ -4132,11 +3550,11 @@ async function checkCommitMsg(msgFile, options = {}) {
4132
3550
  process.exit(1);
4133
3551
  }
4134
3552
  async function checkStaged(options = {}) {
4135
- const SOURCE_EXTENSIONS4 = /\.(ts|tsx|js|jsx|py|php|rb|go|java|cs|swift|kt|rs|vue|svelte)$/;
3553
+ const SOURCE_EXTENSIONS3 = /\.(ts|tsx|js|jsx|py|php|rb|go|java|cs|swift|kt|rs|vue|svelte)$/;
4136
3554
  let diff;
4137
3555
  let stagedFiles = [];
4138
3556
  try {
4139
- stagedFiles = execSync("git diff --cached --name-only --diff-filter=ACMRT", { encoding: "utf-8" }).split("\n").filter((f) => f && SOURCE_EXTENSIONS4.test(f)).map((f) => normalizePath(f));
3557
+ stagedFiles = execSync("git diff --cached --name-only --diff-filter=ACMRT", { encoding: "utf-8" }).split("\n").filter((f) => f && SOURCE_EXTENSIONS3.test(f)).map((f) => normalizePath(f));
4140
3558
  if (stagedFiles.length === 0) {
4141
3559
  if (options.verbose) console.log(chalk2.gray(" No source files staged \u2014 skipping rule check."));
4142
3560
  return;
@@ -4155,20 +3573,20 @@ async function checkStaged(options = {}) {
4155
3573
  if (options.verbose) console.log(chalk2.gray(" No staged changes to check."));
4156
3574
  return;
4157
3575
  }
4158
- const configPath = join10(process.cwd(), ".memory-core.json");
4159
- if (!existsSync9(configPath)) return;
4160
- const config2 = JSON.parse(readFileSync8(configPath, "utf-8"));
4161
- const { rules: fallbackRules, avoids } = getProfileRules2(config2);
3576
+ const configPath = join8(process.cwd(), ".memory-core.json");
3577
+ if (!existsSync7(configPath)) return;
3578
+ const config = JSON.parse(readFileSync7(configPath, "utf-8"));
3579
+ const { rules: fallbackRules, avoids } = getProfileRules2(config);
4162
3580
  const fast = isFastCheck(options);
4163
- const ruleLoadTimeoutMs = readPositiveIntEnv2("MEMORY_CORE_RULE_LOAD_TIMEOUT_MS", 2e3);
4164
- const ignoreLoadTimeoutMs = readPositiveIntEnv2("MEMORY_CORE_IGNORE_LOAD_TIMEOUT_MS", 1500);
3581
+ const ruleLoadTimeoutMs = readPositiveIntEnv("MEMORY_CORE_RULE_LOAD_TIMEOUT_MS", 2e3);
3582
+ const ignoreLoadTimeoutMs = readPositiveIntEnv("MEMORY_CORE_IGNORE_LOAD_TIMEOUT_MS", 1500);
4165
3583
  let rules;
4166
3584
  let ignores;
4167
3585
  let allowPatterns;
4168
3586
  if (fast) {
4169
3587
  rules = fallbackRules;
4170
3588
  ignores = [];
4171
- allowPatterns = [...new Set(getAllowPatterns(config2))];
3589
+ allowPatterns = [...new Set(getAllowPatterns(config))];
4172
3590
  } else {
4173
3591
  const cwd = process.cwd();
4174
3592
  const cached = readRuleCache(cwd);
@@ -4181,17 +3599,17 @@ async function checkStaged(options = {}) {
4181
3599
  }
4182
3600
  } else {
4183
3601
  const [loadedRules, loadedIgnores] = await Promise.all([
4184
- withTimeout(loadRelevantRules2(config2, diff, stagedFiles, fallbackRules), ruleLoadTimeoutMs, fallbackRules),
3602
+ withTimeout(loadRelevantRules2(config, diff, stagedFiles, fallbackRules), ruleLoadTimeoutMs, fallbackRules),
4185
3603
  withTimeout(loadIgnorePatterns2(), ignoreLoadTimeoutMs, [])
4186
3604
  ]);
4187
3605
  rules = loadedRules;
4188
3606
  ignores = loadedIgnores;
4189
- allowPatterns = [.../* @__PURE__ */ new Set([...getAllowPatterns(config2), ...loadedIgnores])];
3607
+ allowPatterns = [.../* @__PURE__ */ new Set([...getAllowPatterns(config), ...loadedIgnores])];
4190
3608
  saveRuleCache(cwd, { rules, ignores, allowPatterns });
4191
3609
  }
4192
3610
  }
4193
3611
  if (rules.length === 0) return;
4194
- const modelInputMaxChars = readPositiveIntEnv2("MEMORY_CORE_MODEL_INPUT_MAX_CHARS", 8e3);
3612
+ const modelInputMaxChars = readPositiveIntEnv("MEMORY_CORE_MODEL_INPUT_MAX_CHARS", 8e3);
4195
3613
  const modelInput = buildModelInputFromDiff(diff, modelInputMaxChars);
4196
3614
  console.log(chalk2.cyan("\n archmind \u2014 checking staged changes against rules\u2026"));
4197
3615
  if (options.verbose || options.debug) {
@@ -4235,7 +3653,7 @@ Do not include any text outside the JSON object.`;
4235
3653
  const deterministicViolations = findDeterministicViolations(diff, rules, avoids, allowPatterns);
4236
3654
  const astViolations = findAstDeterministicViolationsForDiff(diff, {
4237
3655
  cwd: process.cwd(),
4238
- config: config2,
3656
+ config,
4239
3657
  rules,
4240
3658
  reasonLookup: reasonMap2
4241
3659
  });
@@ -4251,7 +3669,7 @@ Do not include any text outside the JSON object.`;
4251
3669
  console.log(chalk2.gray(" AI check skipped; running deterministic checks only."));
4252
3670
  }
4253
3671
  } else try {
4254
- const checkTimeoutMs = readPositiveIntEnv2("MEMORY_CORE_CHECK_TIMEOUT_MS", readPositiveIntEnv2("CHAT_TIMEOUT_MS", 2e4));
3672
+ const checkTimeoutMs = readPositiveIntEnv("MEMORY_CORE_CHECK_TIMEOUT_MS", readPositiveIntEnv("CHAT_TIMEOUT_MS", 2e4));
4255
3673
  const { content: raw, usage: checkUsage } = await callChatModel([
4256
3674
  { role: "system", content: systemPrompt },
4257
3675
  { role: "user", content: `Review these staged changes:
@@ -4350,10 +3768,10 @@ ${modelInput.text}` }
4350
3768
  }
4351
3769
  let ruleStatsSnapshot = {};
4352
3770
  {
4353
- const statsPath = join10(process.cwd(), ".memory-core-stats.json");
4354
- if (existsSync9(statsPath)) {
3771
+ const statsPath = join8(process.cwd(), ".memory-core-stats.json");
3772
+ if (existsSync7(statsPath)) {
4355
3773
  try {
4356
- const parsed = JSON.parse(readFileSync8(statsPath, "utf-8"));
3774
+ const parsed = JSON.parse(readFileSync7(statsPath, "utf-8"));
4357
3775
  ruleStatsSnapshot = parsed.rules ?? {};
4358
3776
  } catch {
4359
3777
  }
@@ -4467,7 +3885,7 @@ function getCiDiff() {
4467
3885
  }
4468
3886
  async function checkFile2(filePath, options = {}) {
4469
3887
  const { readFileSync: readFile, existsSync: fileExists } = await import("fs");
4470
- const resolvedPath = filePath.startsWith("/") ? filePath : join10(process.cwd(), filePath);
3888
+ const resolvedPath = filePath.startsWith("/") ? filePath : join8(process.cwd(), filePath);
4471
3889
  if (!fileExists(resolvedPath)) {
4472
3890
  console.error(chalk2.red(`
4473
3891
  File not found: ${filePath}
@@ -4482,14 +3900,14 @@ async function checkFile2(filePath, options = {}) {
4482
3900
  `@@ -0,0 +1,${lines.length} @@`,
4483
3901
  ...lines.map((l) => `+${l}`)
4484
3902
  ].join("\n");
4485
- const configPath = join10(process.cwd(), ".memory-core.json");
4486
- if (!existsSync9(configPath)) {
3903
+ const configPath = join8(process.cwd(), ".memory-core.json");
3904
+ if (!existsSync7(configPath)) {
4487
3905
  console.error(chalk2.red("\n No .memory-core.json found. Run: memory-core init\n"));
4488
3906
  process.exit(1);
4489
3907
  }
4490
- const config2 = JSON.parse(readFileSync8(configPath, "utf-8"));
4491
- const { rules: fallbackRules, avoids } = getProfileRules2(config2);
4492
- const allowPatterns = [...new Set(getAllowPatterns(config2))];
3908
+ const config = JSON.parse(readFileSync7(configPath, "utf-8"));
3909
+ const { rules: fallbackRules, avoids } = getProfileRules2(config);
3910
+ const allowPatterns = [...new Set(getAllowPatterns(config))];
4493
3911
  const fast = isFastCheck(options);
4494
3912
  let rules;
4495
3913
  if (fast) {
@@ -4499,9 +3917,9 @@ async function checkFile2(filePath, options = {}) {
4499
3917
  if (cached) {
4500
3918
  rules = cached.rules;
4501
3919
  } else {
4502
- const ruleLoadTimeoutMs = readPositiveIntEnv2("MEMORY_CORE_RULE_LOAD_TIMEOUT_MS", 2e3);
3920
+ const ruleLoadTimeoutMs = readPositiveIntEnv("MEMORY_CORE_RULE_LOAD_TIMEOUT_MS", 2e3);
4503
3921
  rules = await withTimeout(
4504
- loadRelevantRules2(config2, pseudoDiff, [filePath], fallbackRules),
3922
+ loadRelevantRules2(config, pseudoDiff, [filePath], fallbackRules),
4505
3923
  ruleLoadTimeoutMs,
4506
3924
  fallbackRules
4507
3925
  );
@@ -4516,7 +3934,7 @@ async function checkFile2(filePath, options = {}) {
4516
3934
  const deterministicViolations = findDeterministicViolations(pseudoDiff, rules, avoids, allowPatterns);
4517
3935
  const astViolations = findAstDeterministicViolationsForDiff(pseudoDiff, {
4518
3936
  cwd: process.cwd(),
4519
- config: config2,
3937
+ config,
4520
3938
  rules,
4521
3939
  reasonLookup: reasonMap2
4522
3940
  });
@@ -4606,22 +4024,13 @@ function printModelMissing(model) {
4606
4024
  console.log(chalk2.yellow(`
4607
4025
  \u26A0 Chat model "${model}" not found in Ollama.`));
4608
4026
  console.log(chalk2.gray(` Pull a model: ollama pull ${model}`));
4609
- console.log(chalk2.gray(" Or set OLLAMA_CHAT_MODEL=<model> in .env"));
4027
+ console.log(chalk2.gray(" Or set OLLAMA_CHAT_MODEL=<model> in .memory-core.env"));
4610
4028
  console.log(chalk2.gray(" Recommended: llama3.2 | qwen2.5-coder:3b | mistral\n"));
4611
4029
  }
4612
4030
 
4613
4031
  export {
4614
4032
  detectProject,
4615
- Config,
4616
4033
  embed,
4617
- getChatProviderLabel,
4618
- getPool,
4619
- runMigrations,
4620
- saveMemory,
4621
- listMemories,
4622
- deleteMemory,
4623
- updateMemory,
4624
- closePool,
4625
4034
  migrateGraphSnapshots,
4626
4035
  probeGraphSnapshotStore,
4627
4036
  seeds,