memorix 1.9.4 → 1.9.6

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 (90) hide show
  1. package/CHANGELOG.md +75 -1
  2. package/README.md +12 -6
  3. package/README.zh-CN.md +12 -6
  4. package/dist/cli/index.js +2533 -585
  5. package/dist/index.d.ts +15 -8
  6. package/dist/index.js +1201 -284
  7. package/dist/maintenance-runner.js +387 -216
  8. package/dist/media-audio-runner.js +300 -129
  9. package/dist/media-video-runner.js +300 -129
  10. package/dist/memcode-runtime/CHANGELOG.md +75 -1
  11. package/dist/sdk.d.ts +1 -0
  12. package/dist/sdk.js +1882 -998
  13. package/dist/types.d.ts +1 -1
  14. package/dist/vector-backfill-runner.js +300 -129
  15. package/docs/AGENT_OPERATOR_PLAYBOOK.md +47 -3
  16. package/docs/API_REFERENCE.md +39 -1
  17. package/docs/CONFIGURATION.md +58 -1
  18. package/docs/DEVELOPMENT.md +1 -1
  19. package/docs/DOCKER.md +23 -3
  20. package/docs/INTEGRATIONS.md +1 -1
  21. package/docs/KNOWN_ISSUES_AND_ROADMAP.md +61 -1
  22. package/docs/MULTI-DEVICE-SYNC-RESEARCH.md +4 -0
  23. package/docs/PERFORMANCE.md +46 -2
  24. package/docs/README.md +2 -1
  25. package/docs/SETUP.md +56 -1
  26. package/package.json +3 -2
  27. package/plugins/antigravity/memorix/plugin.json +1 -1
  28. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  29. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  30. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  31. package/plugins/copilot/memorix/plugin.json +1 -1
  32. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  33. package/plugins/hermes/memorix/plugin.yaml +1 -1
  34. package/plugins/omp/memorix/package.json +1 -1
  35. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  36. package/plugins/pi/memorix/package.json +1 -1
  37. package/server.json +2 -2
  38. package/src/cli/capability-map.ts +1 -0
  39. package/src/cli/command-guide.ts +15 -3
  40. package/src/cli/commands/agent-integrations.ts +57 -0
  41. package/src/cli/commands/background.ts +11 -2
  42. package/src/cli/commands/context.ts +2 -0
  43. package/src/cli/commands/continuity.ts +155 -0
  44. package/src/cli/commands/init.ts +5 -2
  45. package/src/cli/commands/serve-http.ts +435 -84
  46. package/src/cli/commands/setup.ts +77 -10
  47. package/src/cli/commands/sync-store.ts +47 -12
  48. package/src/cli/commands/sync.ts +26 -0
  49. package/src/cli/index.ts +3 -1
  50. package/src/cli/tui/ConfigureView.tsx +2 -0
  51. package/src/codegraph/auto-context.ts +17 -0
  52. package/src/config/legacy-loader.ts +2 -2
  53. package/src/config/resolved-config.ts +8 -5
  54. package/src/config/yaml-loader.ts +20 -10
  55. package/src/dashboard/server.ts +10 -12
  56. package/src/embedding/api-provider.ts +4 -2
  57. package/src/embedding/fastembed-provider.ts +47 -14
  58. package/src/embedding/transformers-provider.ts +29 -7
  59. package/src/evaluation/memory-quality-gate.ts +90 -0
  60. package/src/hooks/official-skills.ts +2 -0
  61. package/src/integrations/registry.ts +1 -1
  62. package/src/knowledge/context-assembly.ts +1 -0
  63. package/src/knowledge/context-receipt.ts +15 -0
  64. package/src/knowledge/task-continuity.ts +413 -0
  65. package/src/knowledge/workset.ts +77 -0
  66. package/src/llm/provider.ts +2 -1
  67. package/src/memory/graph.ts +10 -8
  68. package/src/memory/session.ts +1 -1
  69. package/src/orchestrate/coordinator.ts +60 -0
  70. package/src/orchestrate/effect-ledger.ts +160 -0
  71. package/src/orchestrate/pipeline-trace.ts +40 -6
  72. package/src/runtime/maintenance-jobs.ts +12 -6
  73. package/src/sdk.ts +24 -0
  74. package/src/server/mcp-binding-store.ts +14 -3
  75. package/src/server/modern-mcp-bridge.ts +153 -27
  76. package/src/server/tool-profile.ts +3 -2
  77. package/src/server.ts +131 -7
  78. package/src/store/file-lock.ts +28 -3
  79. package/src/store/graph-store.ts +178 -46
  80. package/src/store/persistence.ts +14 -9
  81. package/src/store/sqlite-db.ts +150 -7
  82. package/src/store/sqlite-store.ts +32 -27
  83. package/src/sync/engine.ts +9 -7
  84. package/src/sync/namespace.ts +23 -0
  85. package/src/sync/policy.ts +19 -4
  86. package/src/sync/store-port.ts +43 -13
  87. package/src/sync/types.ts +2 -0
  88. package/src/team/team-store.ts +62 -27
  89. package/src/types.ts +1 -1
  90. package/src/workspace/mcp-adapters/grok.ts +32 -0
@@ -155,15 +155,20 @@ var init_dotenv_loader = __esm({
155
155
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
156
156
  import { homedir as homedir2 } from "os";
157
157
  import { parse as parseYamlDocument } from "yaml";
158
+ function cacheKey(homeDir, projectRoot) {
159
+ return `${homeDir}\0${projectRoot ?? ""}`;
160
+ }
158
161
  function initProjectRoot(root) {
159
162
  globalProjectRoot = root;
160
- configCache.delete(root);
163
+ configCache.delete(cacheKey(homedir2(), root));
161
164
  }
162
- function loadYamlConfig(projectRoot) {
165
+ function loadYamlConfig(projectRoot, options = {}) {
166
+ const homeDir = options.homeDir ?? homedir2();
163
167
  const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
164
- const cached = configCache.get(resolvedRoot ?? null);
168
+ const key = cacheKey(homeDir, resolvedRoot);
169
+ const cached = configCache.get(key);
165
170
  if (cached) return cached;
166
- const userYaml = getGlobalYamlPath(homedir2());
171
+ const userYaml = getGlobalYamlPath(homeDir);
167
172
  const projectYaml = resolvedRoot ? getProjectYamlPath(resolvedRoot) : null;
168
173
  let userConfig = {};
169
174
  let projectConfig = {};
@@ -195,7 +200,7 @@ function loadYamlConfig(projectRoot) {
195
200
  server: { ...userConfig.server, ...projectConfig.server },
196
201
  team: { ...userConfig.team, ...projectConfig.team }
197
202
  };
198
- configCache.set(resolvedRoot ?? null, merged);
203
+ configCache.set(key, merged);
199
204
  return merged;
200
205
  }
201
206
  function parseYaml(content) {
@@ -572,11 +577,21 @@ function applySchemaMigrations(db2) {
572
577
  apply();
573
578
  }
574
579
  }
580
+ function normalizeDataDir(dataDir) {
581
+ return path3.resolve(dataDir);
582
+ }
583
+ function touchDatabase(normalized, db2) {
584
+ _dbCache.delete(normalized);
585
+ _dbCache.set(normalized, db2);
586
+ }
575
587
  function getDatabase(dataDir) {
576
- const normalized = path3.resolve(dataDir);
588
+ const normalized = normalizeDataDir(dataDir);
577
589
  assertNotHomeDataDir(normalized);
578
590
  const existing = _dbCache.get(normalized);
579
- if (existing) return existing;
591
+ if (existing) {
592
+ touchDatabase(normalized, existing);
593
+ return existing;
594
+ }
580
595
  loadBetterSqlite3();
581
596
  fs.mkdirSync(dataDir, { recursive: true });
582
597
  const dbPath = path3.join(dataDir, "memorix.db");
@@ -606,6 +621,8 @@ function getDatabase(dataDir) {
606
621
  db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
607
622
  db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
608
623
  db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
624
+ db2.exec(CREATE_TASK_CONTINUITY_EVENTS_TABLE);
625
+ db2.exec(CREATE_AGENT_EFFECTS_TABLE);
609
626
  try {
610
627
  db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
611
628
  } catch {
@@ -644,7 +661,7 @@ function getDatabase(dataDir) {
644
661
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
645
662
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
646
663
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
647
- _dbCache.set(normalized, db2);
664
+ touchDatabase(normalized, db2);
648
665
  return db2;
649
666
  } catch (error) {
650
667
  try {
@@ -662,8 +679,9 @@ function closeAllDatabases() {
662
679
  }
663
680
  _dbCache.delete(key);
664
681
  }
682
+ _dbLeases.clear();
665
683
  }
666
- var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
684
+ var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_TASK_CONTINUITY_EVENTS_TABLE, CREATE_AGENT_EFFECTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache, _dbLeases;
667
685
  var init_sqlite_db = __esm({
668
686
  "src/store/sqlite-db.ts"() {
669
687
  "use strict";
@@ -835,18 +853,21 @@ CREATE TABLE IF NOT EXISTS chat_transcript (
835
853
  `;
836
854
  CREATE_GRAPH_ENTITIES_TABLE = `
837
855
  CREATE TABLE IF NOT EXISTS graph_entities (
838
- name TEXT PRIMARY KEY,
856
+ projectId TEXT NOT NULL,
857
+ name TEXT NOT NULL,
839
858
  entityType TEXT NOT NULL DEFAULT '',
840
- observations TEXT NOT NULL DEFAULT '[]'
859
+ observations TEXT NOT NULL DEFAULT '[]',
860
+ PRIMARY KEY (projectId, name)
841
861
  );
842
862
  `;
843
863
  CREATE_GRAPH_RELATIONS_TABLE = `
844
864
  CREATE TABLE IF NOT EXISTS graph_relations (
845
865
  id INTEGER PRIMARY KEY AUTOINCREMENT,
866
+ projectId TEXT NOT NULL,
846
867
  from_entity TEXT NOT NULL,
847
868
  to_entity TEXT NOT NULL,
848
869
  relationType TEXT NOT NULL DEFAULT '',
849
- UNIQUE(from_entity, to_entity, relationType)
870
+ UNIQUE(projectId, from_entity, to_entity, relationType)
850
871
  );
851
872
  `;
852
873
  CREATE_CODE_FILES_TABLE = `
@@ -1377,6 +1398,43 @@ CREATE TABLE IF NOT EXISTS memory_feedback_events (
1377
1398
  delta REAL NOT NULL DEFAULT 0,
1378
1399
  observed_at TEXT NOT NULL
1379
1400
  );
1401
+ `;
1402
+ CREATE_TASK_CONTINUITY_EVENTS_TABLE = `
1403
+ CREATE TABLE IF NOT EXISTS task_continuity_events (
1404
+ id TEXT PRIMARY KEY,
1405
+ project_id TEXT NOT NULL,
1406
+ task_id TEXT NOT NULL,
1407
+ task TEXT NOT NULL,
1408
+ kind TEXT NOT NULL,
1409
+ content TEXT NOT NULL,
1410
+ item_status TEXT,
1411
+ source_ref TEXT,
1412
+ evidence_json TEXT NOT NULL DEFAULT '[]',
1413
+ actor TEXT,
1414
+ created_at TEXT NOT NULL,
1415
+ event_key TEXT,
1416
+ item_key TEXT,
1417
+ supersedes_id TEXT
1418
+ );
1419
+ `;
1420
+ CREATE_AGENT_EFFECTS_TABLE = `
1421
+ CREATE TABLE IF NOT EXISTS agent_effects (
1422
+ id TEXT PRIMARY KEY,
1423
+ pipeline_id TEXT NOT NULL,
1424
+ task_id TEXT NOT NULL,
1425
+ attempt INTEGER NOT NULL,
1426
+ effect_key TEXT NOT NULL,
1427
+ tool TEXT NOT NULL,
1428
+ risk_tier TEXT NOT NULL,
1429
+ replay_policy TEXT NOT NULL,
1430
+ status TEXT NOT NULL,
1431
+ call_id TEXT,
1432
+ idempotency_key TEXT NOT NULL,
1433
+ input_fingerprint TEXT,
1434
+ detail TEXT,
1435
+ started_at INTEGER NOT NULL,
1436
+ finished_at INTEGER
1437
+ );
1380
1438
  `;
1381
1439
  CREATE_MCP_BINDINGS_TABLE = `
1382
1440
  CREATE TABLE IF NOT EXISTS mcp_bindings (
@@ -1455,7 +1513,18 @@ CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(projec
1455
1513
  CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
1456
1514
  CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
1457
1515
  CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
1516
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_project_task ON task_continuity_events(project_id, task_id, created_at ASC);
1517
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_project_recent ON task_continuity_events(project_id, created_at DESC);
1518
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC);
1519
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
1520
+ ON task_continuity_events(project_id, task_id, event_key)
1521
+ WHERE event_key IS NOT NULL;
1522
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_effect_identity
1523
+ ON agent_effects(pipeline_id, task_id, attempt, effect_key);
1524
+ CREATE INDEX IF NOT EXISTS idx_agent_effect_pipeline ON agent_effects(pipeline_id, started_at ASC);
1458
1525
  CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
1526
+ CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC);
1527
+ CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at);
1459
1528
  CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1460
1529
  ON maintenance_jobs(project_id, kind, dedupe_key)
1461
1530
  WHERE status IN ('pending', 'running', 'retry');
@@ -1626,6 +1695,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1626
1695
  db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
1627
1696
  db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC)");
1628
1697
  db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
1698
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC)");
1699
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at)");
1629
1700
  }
1630
1701
  },
1631
1702
  {
@@ -1636,9 +1707,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1636
1707
  addColumnIfMissing(db2, "code_symbols", "source", "source TEXT");
1637
1708
  addColumnIfMissing(db2, "code_edges", "source", "source TEXT");
1638
1709
  }
1710
+ },
1711
+ {
1712
+ id: "1.9-continuity-v2",
1713
+ apply: (db2) => {
1714
+ addColumnIfMissing(db2, "task_continuity_events", "event_key", "event_key TEXT");
1715
+ addColumnIfMissing(db2, "task_continuity_events", "item_key", "item_key TEXT");
1716
+ addColumnIfMissing(db2, "task_continuity_events", "supersedes_id", "supersedes_id TEXT");
1717
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC)");
1718
+ db2.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
1719
+ ON task_continuity_events(project_id, task_id, event_key)
1720
+ WHERE event_key IS NOT NULL`);
1721
+ }
1639
1722
  }
1640
1723
  ];
1641
1724
  _dbCache = /* @__PURE__ */ new Map();
1725
+ _dbLeases = /* @__PURE__ */ new Map();
1642
1726
  }
1643
1727
  });
1644
1728
 
@@ -1714,6 +1798,21 @@ var init_sqlite_reliability = __esm({
1714
1798
  import { promises as fs2 } from "fs";
1715
1799
  import { randomUUID } from "crypto";
1716
1800
  import path4 from "path";
1801
+ function canReclaimStaleLock(raw) {
1802
+ try {
1803
+ const parsed = JSON.parse(raw);
1804
+ const pid = Number(parsed.pid);
1805
+ if (!Number.isSafeInteger(pid) || pid < 1) return true;
1806
+ try {
1807
+ process.kill(pid, 0);
1808
+ return false;
1809
+ } catch (error) {
1810
+ return error.code !== "EPERM";
1811
+ }
1812
+ } catch {
1813
+ return true;
1814
+ }
1815
+ }
1717
1816
  async function acquireLock(lockPath) {
1718
1817
  for (let i2 = 0; i2 < MAX_RETRIES; i2++) {
1719
1818
  try {
@@ -1727,9 +1826,12 @@ async function acquireLock(lockPath) {
1727
1826
  try {
1728
1827
  const stat5 = await fs2.stat(lockPath);
1729
1828
  if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
1730
- await fs2.unlink(lockPath).catch(() => {
1731
- });
1732
- continue;
1829
+ const raw2 = await fs2.readFile(lockPath, "utf8").catch(() => "");
1830
+ if (canReclaimStaleLock(raw2)) {
1831
+ await fs2.unlink(lockPath).catch(() => {
1832
+ });
1833
+ continue;
1834
+ }
1733
1835
  }
1734
1836
  } catch {
1735
1837
  continue;
@@ -1740,6 +1842,10 @@ async function acquireLock(lockPath) {
1740
1842
  }
1741
1843
  }
1742
1844
  }
1845
+ const raw = await fs2.readFile(lockPath, "utf8").catch(() => "");
1846
+ if (!canReclaimStaleLock(raw)) {
1847
+ throw new Error(`Failed to acquire lock: ${lockPath} (owner is still running)`);
1848
+ }
1743
1849
  await fs2.unlink(lockPath).catch(() => {
1744
1850
  });
1745
1851
  try {
@@ -2106,9 +2212,9 @@ var init_detector = __esm({
2106
2212
  // src/config/legacy-loader.ts
2107
2213
  import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
2108
2214
  import { homedir as homedir3 } from "os";
2109
- function loadFileConfig() {
2215
+ function loadFileConfig(homeDir = homedir3()) {
2110
2216
  if (cachedConfig !== null) return cachedConfig;
2111
- const configPath = getLegacyConfigJsonPath(homedir3());
2217
+ const configPath = getLegacyConfigJsonPath(homeDir);
2112
2218
  try {
2113
2219
  if (existsSync5(configPath)) {
2114
2220
  cachedConfig = JSON.parse(readFileSync5(configPath, "utf-8"));
@@ -2138,15 +2244,15 @@ import { homedir as homedir4 } from "os";
2138
2244
  function loadTomlConfig(options = {}) {
2139
2245
  const homeDir = options.homeDir ?? homedir4();
2140
2246
  const projectRoot = options.projectRoot ?? null;
2141
- const cacheKey = `${homeDir}\0${projectRoot ?? ""}`;
2142
- const cached = configCache2.get(cacheKey);
2247
+ const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
2248
+ const cached = configCache2.get(cacheKey3);
2143
2249
  if (cached) return cached;
2144
2250
  const userToml = getGlobalConfigTomlPath(homeDir);
2145
2251
  const projectToml = projectRoot ? getProjectConfigTomlPath(projectRoot) : null;
2146
2252
  const userConfig = existsSync6(userToml) ? parseTomlConfig(readFileSync6(userToml, "utf8"), userToml) : {};
2147
2253
  const projectConfig = projectToml && existsSync6(projectToml) ? parseTomlConfig(readFileSync6(projectToml, "utf8"), projectToml) : {};
2148
2254
  const merged = mergeTomlConfig(userConfig, projectConfig);
2149
- configCache2.set(cacheKey, merged);
2255
+ configCache2.set(cacheKey3, merged);
2150
2256
  return merged;
2151
2257
  }
2152
2258
  function mergeTomlConfig(base, override) {
@@ -2267,8 +2373,8 @@ function getResolvedConfig(options = {}) {
2267
2373
  const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
2268
2374
  loadDotenv(projectRoot === null ? void 0 : projectRoot ?? void 0, { userHomeDir: homeDir });
2269
2375
  const toml = loadTomlConfig({ projectRoot: projectRoot ?? null, homeDir });
2270
- const yaml = loadYamlConfig(projectRoot ?? null);
2271
- const legacy = loadFileConfig();
2376
+ const yaml = loadYamlConfig(projectRoot ?? null, { homeDir });
2377
+ const legacy = loadFileConfig(homeDir);
2272
2378
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
2273
2379
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2274
2380
  const memoryLlmProvider = first(
@@ -2290,15 +2396,17 @@ function getResolvedConfig(options = {}) {
2290
2396
  legacy.llm?.baseUrl
2291
2397
  );
2292
2398
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2399
+ const isAtlasCloud = memoryLlmProvider === "atlascloud";
2293
2400
  const memoryLlmApiKey = first(
2294
2401
  process.env.MEMORIX_LLM_API_KEY,
2295
2402
  process.env.MEMORIX_API_KEY,
2296
2403
  toml.memory?.llm?.api_key,
2297
2404
  yaml.llm?.apiKey,
2298
2405
  legacy.llm?.apiKey,
2299
- process.env.OPENAI_API_KEY,
2300
- process.env.ANTHROPIC_API_KEY,
2301
- openRouterMemoryLlmApiKey
2406
+ // Never borrow another provider's credentials for the Atlas Cloud preset.
2407
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
2408
+ isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
2409
+ isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
2302
2410
  );
2303
2411
  const resolved = {
2304
2412
  agent: {
@@ -2477,7 +2585,8 @@ function getEnvSourceNames() {
2477
2585
  "MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
2478
2586
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
2479
2587
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
2480
- "OPENROUTER_API_KEY"
2588
+ "OPENROUTER_API_KEY",
2589
+ "ATLASCLOUD_API_KEY"
2481
2590
  ].filter((name) => process.env[name]);
2482
2591
  }
2483
2592
  function isOpenRouterUrl(value) {
@@ -2696,12 +2805,45 @@ function textHash(text2) {
2696
2805
  async function loadDiskCache() {
2697
2806
  try {
2698
2807
  const raw = await readFile(CACHE_FILE, "utf-8");
2808
+ if (Buffer.byteLength(raw, "utf8") > MAX_CACHE_FILE_BYTES) {
2809
+ console.error("[memorix] FastEmbed cache exceeds the disk load limit; starting with an empty cache");
2810
+ return;
2811
+ }
2699
2812
  const entries = JSON.parse(raw);
2700
- for (const [k, v] of entries) cache.set(k, v);
2701
- console.error(`[memorix] Loaded ${entries.length} cached embeddings from disk`);
2813
+ if (!Array.isArray(entries)) return;
2814
+ for (const entry of entries) {
2815
+ if (!Array.isArray(entry) || typeof entry[0] !== "string" || !isVector(entry[1])) continue;
2816
+ cacheSet(entry[0], entry[1], false);
2817
+ }
2818
+ console.error(`[memorix] Loaded ${cache.size} cached embeddings from disk`);
2702
2819
  } catch {
2703
2820
  }
2704
2821
  }
2822
+ function isVector(value) {
2823
+ return Array.isArray(value) && value.every((entry) => typeof entry === "number");
2824
+ }
2825
+ function maxCachePayloadBytes() {
2826
+ const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
2827
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES;
2828
+ }
2829
+ function cacheSet(hash4, value, markDirty = true) {
2830
+ const incomingBytes = value.length * 8;
2831
+ if (incomingBytes > maxCachePayloadBytes()) return;
2832
+ const existing = cache.get(hash4);
2833
+ if (existing) cachePayloadBytes -= existing.length * 8;
2834
+ else {
2835
+ while (cache.size >= MAX_CACHE_SIZE || cachePayloadBytes + incomingBytes > maxCachePayloadBytes()) {
2836
+ const firstKey = cache.keys().next().value;
2837
+ if (firstKey === void 0) break;
2838
+ const old = cache.get(firstKey);
2839
+ cache.delete(firstKey);
2840
+ if (old) cachePayloadBytes -= old.length * 8;
2841
+ }
2842
+ }
2843
+ cache.set(hash4, value);
2844
+ cachePayloadBytes += incomingBytes;
2845
+ if (markDirty) diskCacheDirty = true;
2846
+ }
2705
2847
  async function saveDiskCache() {
2706
2848
  if (!diskCacheDirty) return;
2707
2849
  try {
@@ -2712,7 +2854,7 @@ async function saveDiskCache() {
2712
2854
  } catch {
2713
2855
  }
2714
2856
  }
2715
- var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, diskCacheDirty, FastEmbedProvider;
2857
+ var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, DEFAULT_CACHE_PAYLOAD_BYTES, MAX_CACHE_FILE_BYTES, cachePayloadBytes, diskCacheDirty, FastEmbedProvider;
2716
2858
  var init_fastembed_provider = __esm({
2717
2859
  "src/embedding/fastembed-provider.ts"() {
2718
2860
  "use strict";
@@ -2722,6 +2864,9 @@ var init_fastembed_provider = __esm({
2722
2864
  CACHE_FILE = join2(CACHE_DIR, ".embedding-cache.json");
2723
2865
  cache = /* @__PURE__ */ new Map();
2724
2866
  MAX_CACHE_SIZE = 5e3;
2867
+ DEFAULT_CACHE_PAYLOAD_BYTES = 64 * 1024 * 1024;
2868
+ MAX_CACHE_FILE_BYTES = 128 * 1024 * 1024;
2869
+ cachePayloadBytes = 0;
2725
2870
  diskCacheDirty = false;
2726
2871
  FastEmbedProvider = class _FastEmbedProvider {
2727
2872
  name = "fastembed-bge-small";
@@ -2763,7 +2908,7 @@ var init_fastembed_provider = __esm({
2763
2908
  if (result.length !== this.dimensions) {
2764
2909
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
2765
2910
  }
2766
- this.cacheSet(hash4, result);
2911
+ cacheSet(hash4, result);
2767
2912
  return result;
2768
2913
  }
2769
2914
  async embedBatch(texts) {
@@ -2788,7 +2933,7 @@ var init_fastembed_provider = __esm({
2788
2933
  const originalIdx = uncachedIndices[batchIdx];
2789
2934
  const plain = Array.from(vec);
2790
2935
  results[originalIdx] = plain;
2791
- this.cacheSet(textHash(uncachedTexts[batchIdx]), plain);
2936
+ cacheSet(textHash(uncachedTexts[batchIdx]), plain);
2792
2937
  batchIdx++;
2793
2938
  }
2794
2939
  }
@@ -2796,14 +2941,6 @@ var init_fastembed_provider = __esm({
2796
2941
  }
2797
2942
  return results;
2798
2943
  }
2799
- cacheSet(hash4, value) {
2800
- if (cache.size >= MAX_CACHE_SIZE) {
2801
- const firstKey = cache.keys().next().value;
2802
- if (firstKey !== void 0) cache.delete(firstKey);
2803
- }
2804
- cache.set(hash4, value);
2805
- diskCacheDirty = true;
2806
- }
2807
2944
  };
2808
2945
  }
2809
2946
  });
@@ -2813,7 +2950,15 @@ var transformers_provider_exports = {};
2813
2950
  __export(transformers_provider_exports, {
2814
2951
  TransformersProvider: () => TransformersProvider
2815
2952
  });
2816
- var cache2, MAX_CACHE_SIZE2, TransformersProvider;
2953
+ import { createHash as createHash2 } from "crypto";
2954
+ function cacheKey2(text2) {
2955
+ return createHash2("sha256").update(text2).digest("hex");
2956
+ }
2957
+ function maxCachePayloadBytes2() {
2958
+ const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
2959
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES2;
2960
+ }
2961
+ var cache2, MAX_CACHE_SIZE2, DEFAULT_CACHE_PAYLOAD_BYTES2, cachePayloadBytes2, TransformersProvider;
2817
2962
  var init_transformers_provider = __esm({
2818
2963
  "src/embedding/transformers-provider.ts"() {
2819
2964
  "use strict";
@@ -2821,6 +2966,8 @@ var init_transformers_provider = __esm({
2821
2966
  init_provider();
2822
2967
  cache2 = /* @__PURE__ */ new Map();
2823
2968
  MAX_CACHE_SIZE2 = 5e3;
2969
+ DEFAULT_CACHE_PAYLOAD_BYTES2 = 64 * 1024 * 1024;
2970
+ cachePayloadBytes2 = 0;
2824
2971
  TransformersProvider = class _TransformersProvider {
2825
2972
  name = "transformers-minilm";
2826
2973
  dimensions = 384;
@@ -2855,7 +3002,7 @@ var init_transformers_provider = __esm({
2855
3002
  return Promise.all(inputs.map((input) => this.embedInput(input, options)));
2856
3003
  }
2857
3004
  async embed(text2) {
2858
- const cached = cache2.get(text2);
3005
+ const cached = cache2.get(cacheKey2(text2));
2859
3006
  if (cached) return cached;
2860
3007
  const output = await this.extractor(text2, {
2861
3008
  pooling: "mean",
@@ -2865,7 +3012,7 @@ var init_transformers_provider = __esm({
2865
3012
  if (result.length !== this.dimensions) {
2866
3013
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
2867
3014
  }
2868
- this.cacheSet(text2, result);
3015
+ this.cacheSet(cacheKey2(text2), result);
2869
3016
  return result;
2870
3017
  }
2871
3018
  async embedBatch(texts) {
@@ -2873,7 +3020,7 @@ var init_transformers_provider = __esm({
2873
3020
  const uncachedIndices = [];
2874
3021
  const uncachedTexts = [];
2875
3022
  for (let i2 = 0; i2 < texts.length; i2++) {
2876
- const cached = cache2.get(texts[i2]);
3023
+ const cached = cache2.get(cacheKey2(texts[i2]));
2877
3024
  if (cached) {
2878
3025
  results[i2] = cached;
2879
3026
  } else {
@@ -2891,17 +3038,27 @@ var init_transformers_provider = __esm({
2891
3038
  const vec = Array.from(allVecs[i2]);
2892
3039
  const originalIdx = uncachedIndices[i2];
2893
3040
  results[originalIdx] = vec;
2894
- this.cacheSet(uncachedTexts[i2], vec);
3041
+ this.cacheSet(cacheKey2(uncachedTexts[i2]), vec);
2895
3042
  }
2896
3043
  }
2897
3044
  return results;
2898
3045
  }
2899
3046
  cacheSet(key, value) {
2900
- if (cache2.size >= MAX_CACHE_SIZE2) {
2901
- const firstKey = cache2.keys().next().value;
2902
- if (firstKey !== void 0) cache2.delete(firstKey);
3047
+ const incomingBytes = value.length * 8;
3048
+ if (incomingBytes > maxCachePayloadBytes2()) return;
3049
+ const existing = cache2.get(key);
3050
+ if (existing) cachePayloadBytes2 -= existing.length * 8;
3051
+ else {
3052
+ while (cache2.size >= MAX_CACHE_SIZE2 || cachePayloadBytes2 + incomingBytes > maxCachePayloadBytes2()) {
3053
+ const firstKey = cache2.keys().next().value;
3054
+ if (firstKey === void 0) break;
3055
+ const old = cache2.get(firstKey);
3056
+ cache2.delete(firstKey);
3057
+ if (old) cachePayloadBytes2 -= old.length * 8;
3058
+ }
2903
3059
  }
2904
3060
  cache2.set(key, value);
3061
+ cachePayloadBytes2 += incomingBytes;
2905
3062
  }
2906
3063
  };
2907
3064
  }
@@ -2923,7 +3080,7 @@ __export(api_provider_exports, {
2923
3080
  saveDiskCacheNow: () => saveDiskCacheNow,
2924
3081
  seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
2925
3082
  });
2926
- import { createHash as createHash2 } from "crypto";
3083
+ import { createHash as createHash3 } from "crypto";
2927
3084
  import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
2928
3085
  import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
2929
3086
  import { join as join3 } from "path";
@@ -2950,7 +3107,7 @@ function cacheStatFile() {
2950
3107
  function payloadBytes(vector) {
2951
3108
  return vector.length * BYTES_PER_DIM;
2952
3109
  }
2953
- function maxCachePayloadBytes() {
3110
+ function maxCachePayloadBytes3() {
2954
3111
  const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
2955
3112
  if (raw) {
2956
3113
  const parsed = Number.parseInt(raw, 10);
@@ -2960,7 +3117,7 @@ function maxCachePayloadBytes() {
2960
3117
  }
2961
3118
  function maxEntriesForDimensions(dimensions) {
2962
3119
  const dim = Math.max(1, Math.floor(dimensions));
2963
- const byBytes = Math.floor(maxCachePayloadBytes() / (dim * BYTES_PER_DIM));
3120
+ const byBytes = Math.floor(maxCachePayloadBytes3() / (dim * BYTES_PER_DIM));
2964
3121
  return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
2965
3122
  }
2966
3123
  function rememberDimensions(vector) {
@@ -2973,13 +3130,15 @@ function evictOldest() {
2973
3130
  if (firstKey === void 0) return;
2974
3131
  const old = cache3.get(firstKey);
2975
3132
  cache3.delete(firstKey);
2976
- if (old) cachePayloadBytes -= payloadBytes(old);
3133
+ if (old) cachePayloadBytes3 -= payloadBytes(old);
2977
3134
  }
2978
3135
  function evictToFit(incomingBytes, incomingDims) {
3136
+ if (incomingBytes > maxCachePayloadBytes3()) return false;
2979
3137
  const limit2 = maxEntriesForDimensions(incomingDims);
2980
- while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes + incomingBytes > maxCachePayloadBytes())) {
3138
+ while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes3 + incomingBytes > maxCachePayloadBytes3())) {
2981
3139
  evictOldest();
2982
3140
  }
3141
+ return true;
2983
3142
  }
2984
3143
  function isNumberArray(value) {
2985
3144
  return Array.isArray(value) && value.every((entry) => typeof entry === "number");
@@ -3006,12 +3165,12 @@ function cacheInsert(hash4, value, dirty) {
3006
3165
  const incoming = payloadBytes(value);
3007
3166
  const existing = cache3.get(hash4);
3008
3167
  if (existing) {
3009
- cachePayloadBytes -= payloadBytes(existing);
3168
+ cachePayloadBytes3 -= payloadBytes(existing);
3010
3169
  cache3.delete(hash4);
3011
3170
  }
3012
- evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
3171
+ if (!evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS)) return;
3013
3172
  cache3.set(hash4, value);
3014
- cachePayloadBytes += incoming;
3173
+ cachePayloadBytes3 += incoming;
3015
3174
  if (dirty) diskCacheDirty2 = true;
3016
3175
  }
3017
3176
  async function readCacheStat() {
@@ -3047,7 +3206,7 @@ function cacheNamespace(config) {
3047
3206
  ].join("|");
3048
3207
  }
3049
3208
  function textHash2(text2, namespace) {
3050
- return createHash2("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
3209
+ return createHash3("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
3051
3210
  }
3052
3211
  function inputIdentity(input, options = {}) {
3053
3212
  return JSON.stringify({
@@ -3389,7 +3548,7 @@ function getApiEmbeddingDiskCacheLoadCountForTests() {
3389
3548
  }
3390
3549
  function resetApiEmbeddingCacheForTests() {
3391
3550
  cache3.clear();
3392
- cachePayloadBytes = 0;
3551
+ cachePayloadBytes3 = 0;
3393
3552
  cacheDimensions = null;
3394
3553
  diskCacheEntryCount = 0;
3395
3554
  diskCacheLoaded = false;
@@ -3400,14 +3559,14 @@ function resetApiEmbeddingCacheForTests() {
3400
3559
  }
3401
3560
  function seedApiEmbeddingCacheForTests(entries) {
3402
3561
  cache3.clear();
3403
- cachePayloadBytes = 0;
3562
+ cachePayloadBytes3 = 0;
3404
3563
  cacheDimensions = null;
3405
3564
  for (const [key, value] of entries) cacheInsert(key, value, true);
3406
3565
  diskCacheLoaded = true;
3407
3566
  diskCacheDirty2 = true;
3408
3567
  }
3409
3568
  function getApiEmbeddingCachePayloadBytesForTests() {
3410
- return cachePayloadBytes;
3569
+ return cachePayloadBytes3;
3411
3570
  }
3412
3571
  function getApiEmbeddingJsonlLineCountCallsForTests() {
3413
3572
  return jsonlLineCountCalls;
@@ -3581,7 +3740,7 @@ function scheduleDiskSave() {
3581
3740
  diskSaveTimer = null;
3582
3741
  }, DISK_SAVE_DEBOUNCE_MS);
3583
3742
  }
3584
- function cacheSet(hash4, value) {
3743
+ function cacheSet2(hash4, value) {
3585
3744
  cacheInsert(hash4, value, true);
3586
3745
  }
3587
3746
  function resolveEnvEmbeddingApiKey() {
@@ -3701,7 +3860,7 @@ async function waitForRetry(waitMs, signal) {
3701
3860
  abortSignal.addEventListener("abort", onAbort, { once: true });
3702
3861
  });
3703
3862
  }
3704
- var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES, cachePayloadBytes, cacheDimensions, diskCacheEntryCount, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, diskCacheLoadCount, jsonlLineCountCalls, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
3863
+ var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES, cachePayloadBytes3, cacheDimensions, diskCacheEntryCount, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, diskCacheLoadCount, jsonlLineCountCalls, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
3705
3864
  var init_api_provider = __esm({
3706
3865
  "src/embedding/api-provider.ts"() {
3707
3866
  "use strict";
@@ -3713,7 +3872,7 @@ var init_api_provider = __esm({
3713
3872
  BYTES_PER_DIM = 8;
3714
3873
  DEFAULT_ASSUMED_DIMENSIONS = 4096;
3715
3874
  MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
3716
- cachePayloadBytes = 0;
3875
+ cachePayloadBytes3 = 0;
3717
3876
  cacheDimensions = null;
3718
3877
  diskCacheEntryCount = 0;
3719
3878
  diskCacheDirty2 = false;
@@ -3898,7 +4057,7 @@ var init_api_provider = __esm({
3898
4057
  } else {
3899
4058
  embedding = await apiCall();
3900
4059
  }
3901
- cacheSet(hash4, embedding);
4060
+ cacheSet2(hash4, embedding);
3902
4061
  scheduleDiskSave();
3903
4062
  return embedding;
3904
4063
  }
@@ -3946,7 +4105,7 @@ var init_api_provider = __esm({
3946
4105
  for (const item of response.data) {
3947
4106
  const originalIdx = chunkIndices[item.index];
3948
4107
  results[originalIdx] = item.embedding;
3949
- cacheSet(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
4108
+ cacheSet2(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
3950
4109
  }
3951
4110
  } catch (error) {
3952
4111
  const providerLimit = parseBatchLimit(error);
@@ -4024,7 +4183,7 @@ var init_api_provider = __esm({
4024
4183
  throw new Error(`Expected ${this.dimensions}d, got ${embedding.length}d; dimension mismatch`);
4025
4184
  }
4026
4185
  this.trackUsage(response);
4027
- cacheSet(hash4, embedding);
4186
+ cacheSet2(hash4, embedding);
4028
4187
  scheduleDiskSave();
4029
4188
  return embedding;
4030
4189
  }
@@ -5407,6 +5566,7 @@ var init_provider2 = __esm({
5407
5566
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
5408
5567
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
5409
5568
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
5569
+ atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
5410
5570
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
5411
5571
  };
5412
5572
  currentConfig = null;
@@ -5670,6 +5830,7 @@ var init_sqlite_store = __esm({
5670
5830
  init_sqlite_db();
5671
5831
  init_sqlite_reliability();
5672
5832
  init_sqlite_fts();
5833
+ init_file_lock();
5673
5834
  SqliteBackend = class {
5674
5835
  db = null;
5675
5836
  dataDir = "";
@@ -5833,38 +5994,43 @@ var init_sqlite_store = __esm({
5833
5994
  }
5834
5995
  // ── Migration ────────────────────────────────────────────────────
5835
5996
  async migrateFromJsonIfNeeded() {
5836
- const count2 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM observations`).get();
5837
- if (count2.cnt > 0) return;
5838
5997
  const jsonPath = path7.join(this.dataDir, "observations.json");
5839
5998
  if (!fs4.existsSync(jsonPath)) return;
5840
- try {
5999
+ await withFileLock(this.dataDir, async () => {
6000
+ const count2 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM observations`).get();
6001
+ if (count2.cnt > 0) return;
5841
6002
  const raw = fs4.readFileSync(jsonPath, "utf-8");
5842
- const observations2 = JSON.parse(raw);
6003
+ const parsed = JSON.parse(raw);
6004
+ if (!Array.isArray(parsed)) {
6005
+ throw new Error("[memorix] observations.json migration refused: expected a JSON array");
6006
+ }
6007
+ const observations2 = parsed;
5843
6008
  if (observations2.length === 0) return;
6009
+ if (observations2.some((obs) => !obs || !Number.isSafeInteger(obs.id) || obs.id < 1 || typeof obs.projectId !== "string")) {
6010
+ throw new Error("[memorix] observations.json migration refused: invalid observation record");
6011
+ }
5844
6012
  console.error(`[memorix] Migrating ${observations2.length} observations from JSON to SQLite...`);
5845
6013
  const insertMany = this.db.transaction((obsList) => {
5846
6014
  for (const obs of obsList) {
5847
6015
  this.stmtInsert.run(obsToRow(obs));
5848
6016
  }
5849
- });
5850
- insertMany(observations2);
5851
- const counterPath = path7.join(this.dataDir, "counter.json");
5852
- if (fs4.existsSync(counterPath)) {
5853
- try {
6017
+ const counterPath = path7.join(this.dataDir, "counter.json");
6018
+ let counterNextId;
6019
+ if (fs4.existsSync(counterPath)) {
5854
6020
  const counterData = JSON.parse(fs4.readFileSync(counterPath, "utf-8"));
5855
- const nextId2 = counterData.nextId ?? counterData.next_id ?? Math.max(...observations2.map((o) => o.id)) + 1;
5856
- this.rawSaveIdCounter(nextId2);
5857
- } catch {
5858
- this.rawSaveIdCounter(Math.max(...observations2.map((o) => o.id)) + 1);
6021
+ const candidate = counterData.nextId ?? counterData.next_id;
6022
+ if (candidate !== void 0 && (!Number.isSafeInteger(candidate) || Number(candidate) < 1)) {
6023
+ throw new Error("[memorix] counter.json migration refused: nextId must be a positive integer");
6024
+ }
6025
+ counterNextId = candidate === void 0 ? void 0 : Number(candidate);
5859
6026
  }
5860
- } else {
5861
- this.rawSaveIdCounter(Math.max(...observations2.map((o) => o.id)) + 1);
5862
- }
5863
- this.bumpGeneration();
6027
+ const maxId = Math.max(...obsList.map((obs) => obs.id));
6028
+ this.rawSaveIdCounter(Math.max(counterNextId ?? 1, maxId + 1));
6029
+ this.bumpGeneration();
6030
+ });
6031
+ insertMany(observations2);
5864
6032
  console.error(`[memorix] Migration complete. ${observations2.length} observations now in SQLite.`);
5865
- } catch (err) {
5866
- console.error(`[memorix] JSON\u2192SQLite migration failed (non-fatal, data preserved in JSON): ${err}`);
5867
- }
6033
+ });
5868
6034
  }
5869
6035
  // ── Public read ──────────────────────────────────────────────────
5870
6036
  async loadAll() {
@@ -6164,7 +6330,7 @@ var init_obs_store = __esm({
6164
6330
  });
6165
6331
 
6166
6332
  // src/search/semantic-index.ts
6167
- import { createHash as createHash3 } from "crypto";
6333
+ import { createHash as createHash4 } from "crypto";
6168
6334
  import { createRequire as createRequire3 } from "module";
6169
6335
  import path8 from "path";
6170
6336
  function createSemanticIndexProfile(provider2) {
@@ -6178,7 +6344,7 @@ function stateKey(dataDir, profile) {
6178
6344
  return `${path8.resolve(dataDir)}::${profile.key}`;
6179
6345
  }
6180
6346
  function tableName(profile) {
6181
- const digest2 = createHash3("sha256").update(profile.key).digest("hex").slice(0, 20);
6347
+ const digest2 = createHash4("sha256").update(profile.key).digest("hex").slice(0, 20);
6182
6348
  return `${TABLE_PREFIX}${digest2}`;
6183
6349
  }
6184
6350
  function indexRoot(dataDir) {
@@ -8218,6 +8384,7 @@ var init_secret_filter = __esm({
8218
8384
  // src/runtime/maintenance-jobs.ts
8219
8385
  var maintenance_jobs_exports = {};
8220
8386
  __export(maintenance_jobs_exports, {
8387
+ DEFAULT_FAILED_HISTORY_RETENTION_MS: () => DEFAULT_FAILED_HISTORY_RETENTION_MS,
8221
8388
  MAINTENANCE_JOB_KINDS: () => MAINTENANCE_JOB_KINDS,
8222
8389
  MaintenanceJobStore: () => MaintenanceJobStore,
8223
8390
  MaintenanceJobWorker: () => MaintenanceJobWorker,
@@ -8267,7 +8434,7 @@ function normalizedKinds(kinds) {
8267
8434
  function getMaintenanceRetryDelayMs(attempts) {
8268
8435
  return Math.min(6e4, 1e3 * 2 ** Math.max(0, attempts - 1));
8269
8436
  }
8270
- var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
8437
+ var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, DEFAULT_FAILED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
8271
8438
  var init_maintenance_jobs = __esm({
8272
8439
  "src/runtime/maintenance-jobs.ts"() {
8273
8440
  "use strict";
@@ -8294,6 +8461,7 @@ var init_maintenance_jobs = __esm({
8294
8461
  DEFAULT_POLL_INTERVAL_MS = 2e3;
8295
8462
  MAX_ERROR_LENGTH = 1e3;
8296
8463
  DEFAULT_COMPLETED_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
8464
+ DEFAULT_FAILED_HISTORY_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
8297
8465
  MaintenanceJobStore = class {
8298
8466
  db;
8299
8467
  constructor(dataDir) {
@@ -8420,18 +8588,21 @@ var init_maintenance_jobs = __esm({
8420
8588
  }
8421
8589
  /**
8422
8590
  * Completed jobs are useful recent operator history, not permanent data.
8423
- * Failed jobs stay available for diagnosis until an operator explicitly
8424
- * resolves them or clears the database.
8591
+ * Failed diagnostics are retained longer, but are still bounded so a
8592
+ * permanently failing job kind cannot grow the database forever.
8425
8593
  */
8426
8594
  pruneCompletedHistory(options = {}) {
8427
8595
  const now3 = options.now ?? Date.now();
8428
8596
  const maxAgeMs = Number.isFinite(options.maxAgeMs) ? Math.max(0, Math.floor(options.maxAgeMs)) : DEFAULT_COMPLETED_HISTORY_RETENTION_MS;
8597
+ const failedMaxAgeMs = Number.isFinite(options.failedMaxAgeMs) ? Math.max(0, Math.floor(options.failedMaxAgeMs)) : DEFAULT_FAILED_HISTORY_RETENTION_MS;
8429
8598
  const result = this.db.prepare(`
8430
8599
  DELETE FROM maintenance_jobs
8431
- WHERE status = 'completed'
8600
+ WHERE (status = 'completed'
8432
8601
  AND completed_at IS NOT NULL
8433
- AND completed_at < ?
8434
- `).run(now3 - maxAgeMs);
8602
+ AND completed_at < ?)
8603
+ OR (status = 'failed'
8604
+ AND updated_at < ?)
8605
+ `).run(now3 - maxAgeMs, now3 - failedMaxAgeMs);
8435
8606
  return Number(result.changes ?? 0);
8436
8607
  }
8437
8608
  claimNext(options) {
@@ -8757,7 +8928,7 @@ var init_lifecycle = __esm({
8757
8928
  });
8758
8929
 
8759
8930
  // src/store/evidence-store.ts
8760
- import { createHash as createHash4, randomUUID as randomUUID3 } from "crypto";
8931
+ import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
8761
8932
  function safeJson(value, fallback) {
8762
8933
  if (typeof value !== "string" || value.length === 0) return fallback;
8763
8934
  try {
@@ -8791,7 +8962,7 @@ function rowToCard(row) {
8791
8962
  };
8792
8963
  }
8793
8964
  function observationHash(observation) {
8794
- return createHash4("sha256").update(JSON.stringify({
8965
+ return createHash5("sha256").update(JSON.stringify({
8795
8966
  projectId: observation.projectId,
8796
8967
  id: observation.id,
8797
8968
  title: observation.title,
@@ -8977,9 +9148,9 @@ var init_evidence_store = __esm({
8977
9148
  });
8978
9149
 
8979
9150
  // src/codegraph/ids.ts
8980
- import { createHash as createHash5 } from "crypto";
9151
+ import { createHash as createHash6 } from "crypto";
8981
9152
  function digest(input) {
8982
- return createHash5("sha256").update(input).digest("hex").slice(0, 16);
9153
+ return createHash6("sha256").update(input).digest("hex").slice(0, 16);
8983
9154
  }
8984
9155
  function normalizeCodePath(path22) {
8985
9156
  return path22.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
@@ -11549,13 +11720,13 @@ __export(workspace_exports, {
11549
11720
  loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
11550
11721
  resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
11551
11722
  });
11552
- import { createHash as createHash6 } from "crypto";
11723
+ import { createHash as createHash7 } from "crypto";
11553
11724
  import { execFile } from "child_process";
11554
11725
  import { promises as fs6 } from "fs";
11555
11726
  import path10 from "path";
11556
11727
  import { promisify } from "util";
11557
11728
  function hash(value) {
11558
- return createHash6("sha256").update(value).digest("hex");
11729
+ return createHash7("sha256").update(value).digest("hex");
11559
11730
  }
11560
11731
  function workspaceId(projectId, mode) {
11561
11732
  return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
@@ -12690,14 +12861,14 @@ var init_types2 = __esm({
12690
12861
  });
12691
12862
 
12692
12863
  // src/media/asset-store.ts
12693
- import { createHash as createHash7, randomUUID as randomUUID7 } from "crypto";
12864
+ import { createHash as createHash8, randomUUID as randomUUID7 } from "crypto";
12694
12865
  import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
12695
12866
  import path11 from "path";
12696
12867
  function mediaRoot(dataDir) {
12697
12868
  return path11.resolve(dataDir, "media");
12698
12869
  }
12699
12870
  function projectStorageKey(projectId) {
12700
- return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
12871
+ return createHash8("sha256").update(projectId).digest("hex").slice(0, 16);
12701
12872
  }
12702
12873
  function validateUnderRoot(root, candidate) {
12703
12874
  const resolved = path11.resolve(candidate);
@@ -12806,7 +12977,7 @@ async function importMediaBuffer(input) {
12806
12977
  if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
12807
12978
  if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
12808
12979
  const detected = detectMedia(input.bytes.subarray(0, 32));
12809
- const sha256 = createHash7("sha256").update(input.bytes).digest("hex");
12980
+ const sha256 = createHash8("sha256").update(input.bytes).digest("hex");
12810
12981
  return importKnownMedia({
12811
12982
  dataDir: input.dataDir,
12812
12983
  projectId: input.projectId,
@@ -12824,7 +12995,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
12824
12995
  if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
12825
12996
  const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
12826
12997
  if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
12827
- const sha256 = createHash7("sha256").update(bytes).digest("hex");
12998
+ const sha256 = createHash8("sha256").update(bytes).digest("hex");
12828
12999
  if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
12829
13000
  return bytes;
12830
13001
  }
@@ -71520,16 +71691,16 @@ var require_jwtaccess = __commonJS({
71520
71691
  * @returns A string that returns the cached key.
71521
71692
  */
71522
71693
  getCachedKey(url, scopes) {
71523
- let cacheKey = url;
71694
+ let cacheKey3 = url;
71524
71695
  if (scopes && Array.isArray(scopes) && scopes.length) {
71525
- cacheKey = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
71696
+ cacheKey3 = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
71526
71697
  } else if (typeof scopes === "string") {
71527
- cacheKey = url ? `${url}_${scopes}` : scopes;
71698
+ cacheKey3 = url ? `${url}_${scopes}` : scopes;
71528
71699
  }
71529
- if (!cacheKey) {
71700
+ if (!cacheKey3) {
71530
71701
  throw Error("Scopes or url must be provided");
71531
71702
  }
71532
- return cacheKey;
71703
+ return cacheKey3;
71533
71704
  }
71534
71705
  /**
71535
71706
  * Get a non-expired access token, after refreshing if necessary.
@@ -78075,7 +78246,7 @@ var require_websocket = __commonJS({
78075
78246
  var http3 = __require("http");
78076
78247
  var net = __require("net");
78077
78248
  var tls = __require("tls");
78078
- var { randomBytes, createHash: createHash16 } = __require("crypto");
78249
+ var { randomBytes, createHash: createHash17 } = __require("crypto");
78079
78250
  var { Duplex, Readable: Readable2 } = __require("stream");
78080
78251
  var { URL: URL2 } = __require("url");
78081
78252
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -78743,7 +78914,7 @@ var require_websocket = __commonJS({
78743
78914
  abortHandshake(websocket, socket, "Invalid Upgrade header");
78744
78915
  return;
78745
78916
  }
78746
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
78917
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
78747
78918
  if (res.headers["sec-websocket-accept"] !== digest2) {
78748
78919
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
78749
78920
  return;
@@ -79115,7 +79286,7 @@ var require_websocket_server = __commonJS({
79115
79286
  var EventEmitter = __require("events");
79116
79287
  var http3 = __require("http");
79117
79288
  var { Duplex } = __require("stream");
79118
- var { createHash: createHash16 } = __require("crypto");
79289
+ var { createHash: createHash17 } = __require("crypto");
79119
79290
  var extension3 = require_extension();
79120
79291
  var PerMessageDeflate2 = require_permessage_deflate();
79121
79292
  var subprotocol2 = require_subprotocol();
@@ -79422,7 +79593,7 @@ var require_websocket_server = __commonJS({
79422
79593
  );
79423
79594
  }
79424
79595
  if (this._state > RUNNING) return abortHandshake(socket, 503);
79425
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
79596
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
79426
79597
  const headers = [
79427
79598
  "HTTP/1.1 101 Switching Protocols",
79428
79599
  "Upgrade: websocket",
@@ -148002,7 +148173,7 @@ var init_long_term = __esm({
148002
148173
 
148003
148174
  // src/codegraph/code-state.ts
148004
148175
  import { execFile as execFile2 } from "child_process";
148005
- import { createHash as createHash8 } from "crypto";
148176
+ import { createHash as createHash9 } from "crypto";
148006
148177
  import { promisify as promisify3 } from "util";
148007
148178
  async function runGit(rootPath, args) {
148008
148179
  try {
@@ -148031,7 +148202,7 @@ function changedPathCount(status) {
148031
148202
  return count2;
148032
148203
  }
148033
148204
  function fingerprint(baseRevision, status) {
148034
- return createHash8("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
148205
+ return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
148035
148206
  }
148036
148207
  async function collectCodeStateSnapshot(input) {
148037
148208
  const [revision, status] = await Promise.all([
@@ -148125,12 +148296,12 @@ var init_exclude3 = __esm({
148125
148296
  });
148126
148297
 
148127
148298
  // src/codegraph/semantic-provider.ts
148128
- import { createHash as createHash9 } from "crypto";
148299
+ import { createHash as createHash10 } from "crypto";
148129
148300
  import "fs";
148130
148301
  import { resolve } from "path";
148131
148302
  import ts from "typescript";
148132
148303
  function hashText(value) {
148133
- return createHash9("sha256").update(value).digest("hex");
148304
+ return createHash10("sha256").update(value).digest("hex");
148134
148305
  }
148135
148306
  function canonicalPath(value) {
148136
148307
  const normalized = resolve(value).replace(/\\/g, "/");
@@ -148475,11 +148646,11 @@ __export(lite_provider_exports, {
148475
148646
  indexProjectLite: () => indexProjectLite,
148476
148647
  refreshProjectLite: () => refreshProjectLite
148477
148648
  });
148478
- import { createHash as createHash10 } from "crypto";
148649
+ import { createHash as createHash11 } from "crypto";
148479
148650
  import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
148480
148651
  import { join as join4, relative as relative2 } from "path";
148481
148652
  function hashText2(text2) {
148482
- return createHash10("sha256").update(text2).digest("hex");
148653
+ return createHash11("sha256").update(text2).digest("hex");
148483
148654
  }
148484
148655
  function extension2(path22) {
148485
148656
  const index = path22.lastIndexOf(".");
@@ -148955,7 +149126,7 @@ var claim_store_exports = {};
148955
149126
  __export(claim_store_exports, {
148956
149127
  ClaimStore: () => ClaimStore
148957
149128
  });
148958
- import { createHash as createHash11, randomUUID as randomUUID12 } from "crypto";
149129
+ import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
148959
149130
  function optionalText3(value) {
148960
149131
  return typeof value === "string" && value ? value : void 0;
148961
149132
  }
@@ -149008,7 +149179,7 @@ function rowToEvent3(row) {
149008
149179
  };
149009
149180
  }
149010
149181
  function evidenceKey(input) {
149011
- return createHash11("sha256").update(JSON.stringify([
149182
+ return createHash12("sha256").update(JSON.stringify([
149012
149183
  input.evidenceKind,
149013
149184
  input.evidenceId,
149014
149185
  input.relation,
@@ -149206,7 +149377,7 @@ __export(claims_exports, {
149206
149377
  supersedeClaim: () => supersedeClaim,
149207
149378
  writeClaim: () => writeClaim
149208
149379
  });
149209
- import { createHash as createHash12, randomUUID as randomUUID13 } from "crypto";
149380
+ import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
149210
149381
  function compactText2(value, field) {
149211
149382
  if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
149212
149383
  const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
@@ -149218,7 +149389,7 @@ function normalizedTerm(value) {
149218
149389
  return compactText2(value, "identity").toLocaleLowerCase("en-US");
149219
149390
  }
149220
149391
  function hashIdentity(parts) {
149221
- return createHash12("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
149392
+ return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
149222
149393
  }
149223
149394
  function buildClaimIdentity(input) {
149224
149395
  const subject = normalizedTerm(input.subject);
@@ -149459,7 +149630,7 @@ function supersedeClaim(store, input) {
149459
149630
  });
149460
149631
  }
149461
149632
  function hashObservation(observation) {
149462
- return createHash12("sha256").update(JSON.stringify([
149633
+ return createHash13("sha256").update(JSON.stringify([
149463
149634
  observation.title,
149464
149635
  observation.narrative,
149465
149636
  observation.facts,
@@ -149703,11 +149874,11 @@ var init_frontmatter = __esm({
149703
149874
  });
149704
149875
 
149705
149876
  // src/knowledge/markdown.ts
149706
- import { createHash as createHash13 } from "crypto";
149877
+ import { createHash as createHash14 } from "crypto";
149707
149878
  import { promises as fs10 } from "fs";
149708
149879
  import path18 from "path";
149709
149880
  function hashContent(content) {
149710
- return createHash13("sha256").update(content).digest("hex");
149881
+ return createHash14("sha256").update(content).digest("hex");
149711
149882
  }
149712
149883
  function stringField(data, key) {
149713
149884
  const value = data[key];
@@ -149833,11 +150004,11 @@ __export(wiki_exports, {
149833
150004
  lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
149834
150005
  readKnowledgePage: () => readKnowledgePage
149835
150006
  });
149836
- import { createHash as createHash14 } from "crypto";
150007
+ import { createHash as createHash15 } from "crypto";
149837
150008
  import { promises as fs11 } from "fs";
149838
150009
  import path19 from "path";
149839
150010
  function hash2(value) {
149840
- return createHash14("sha256").update(value).digest("hex");
150011
+ return createHash15("sha256").update(value).digest("hex");
149841
150012
  }
149842
150013
  function now() {
149843
150014
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -150694,11 +150865,11 @@ __export(workflows_exports, {
150694
150865
  syncCanonicalWorkflows: () => syncCanonicalWorkflows,
150695
150866
  writeCanonicalWorkflow: () => writeCanonicalWorkflow
150696
150867
  });
150697
- import { createHash as createHash15 } from "crypto";
150868
+ import { createHash as createHash16 } from "crypto";
150698
150869
  import { promises as fs12 } from "fs";
150699
150870
  import path20 from "path";
150700
150871
  function hash3(value) {
150701
- return createHash15("sha256").update(value).digest("hex");
150872
+ return createHash16("sha256").update(value).digest("hex");
150702
150873
  }
150703
150874
  function now2() {
150704
150875
  return (/* @__PURE__ */ new Date()).toISOString();