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,
@@ -9221,13 +9392,13 @@ __export(workspace_exports, {
9221
9392
  loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
9222
9393
  resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
9223
9394
  });
9224
- import { createHash as createHash5 } from "crypto";
9395
+ import { createHash as createHash6 } from "crypto";
9225
9396
  import { execFile } from "child_process";
9226
9397
  import { promises as fs6 } from "fs";
9227
9398
  import path10 from "path";
9228
9399
  import { promisify } from "util";
9229
9400
  function hash(value) {
9230
- return createHash5("sha256").update(value).digest("hex");
9401
+ return createHash6("sha256").update(value).digest("hex");
9231
9402
  }
9232
9403
  function workspaceId(projectId, mode) {
9233
9404
  return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
@@ -10362,14 +10533,14 @@ var init_types2 = __esm({
10362
10533
  });
10363
10534
 
10364
10535
  // src/media/asset-store.ts
10365
- import { createHash as createHash6, randomUUID as randomUUID6 } from "crypto";
10536
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
10366
10537
  import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
10367
10538
  import path11 from "path";
10368
10539
  function mediaRoot(dataDir) {
10369
10540
  return path11.resolve(dataDir, "media");
10370
10541
  }
10371
10542
  function projectStorageKey(projectId) {
10372
- return createHash6("sha256").update(projectId).digest("hex").slice(0, 16);
10543
+ return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
10373
10544
  }
10374
10545
  function validateUnderRoot(root, candidate) {
10375
10546
  const resolved = path11.resolve(candidate);
@@ -10478,7 +10649,7 @@ async function importMediaBuffer(input) {
10478
10649
  if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
10479
10650
  if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
10480
10651
  const detected = detectMedia(input.bytes.subarray(0, 32));
10481
- const sha256 = createHash6("sha256").update(input.bytes).digest("hex");
10652
+ const sha256 = createHash7("sha256").update(input.bytes).digest("hex");
10482
10653
  return importKnownMedia({
10483
10654
  dataDir: input.dataDir,
10484
10655
  projectId: input.projectId,
@@ -10496,7 +10667,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
10496
10667
  if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
10497
10668
  const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
10498
10669
  if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
10499
- const sha256 = createHash6("sha256").update(bytes).digest("hex");
10670
+ const sha256 = createHash7("sha256").update(bytes).digest("hex");
10500
10671
  if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
10501
10672
  return bytes;
10502
10673
  }
@@ -69192,16 +69363,16 @@ var require_jwtaccess = __commonJS({
69192
69363
  * @returns A string that returns the cached key.
69193
69364
  */
69194
69365
  getCachedKey(url, scopes) {
69195
- let cacheKey = url;
69366
+ let cacheKey3 = url;
69196
69367
  if (scopes && Array.isArray(scopes) && scopes.length) {
69197
- cacheKey = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
69368
+ cacheKey3 = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
69198
69369
  } else if (typeof scopes === "string") {
69199
- cacheKey = url ? `${url}_${scopes}` : scopes;
69370
+ cacheKey3 = url ? `${url}_${scopes}` : scopes;
69200
69371
  }
69201
- if (!cacheKey) {
69372
+ if (!cacheKey3) {
69202
69373
  throw Error("Scopes or url must be provided");
69203
69374
  }
69204
- return cacheKey;
69375
+ return cacheKey3;
69205
69376
  }
69206
69377
  /**
69207
69378
  * Get a non-expired access token, after refreshing if necessary.
@@ -75747,7 +75918,7 @@ var require_websocket = __commonJS({
75747
75918
  var http3 = __require("http");
75748
75919
  var net = __require("net");
75749
75920
  var tls = __require("tls");
75750
- var { randomBytes, createHash: createHash16 } = __require("crypto");
75921
+ var { randomBytes, createHash: createHash17 } = __require("crypto");
75751
75922
  var { Duplex, Readable: Readable2 } = __require("stream");
75752
75923
  var { URL: URL2 } = __require("url");
75753
75924
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -76415,7 +76586,7 @@ var require_websocket = __commonJS({
76415
76586
  abortHandshake(websocket, socket, "Invalid Upgrade header");
76416
76587
  return;
76417
76588
  }
76418
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
76589
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
76419
76590
  if (res.headers["sec-websocket-accept"] !== digest2) {
76420
76591
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
76421
76592
  return;
@@ -76787,7 +76958,7 @@ var require_websocket_server = __commonJS({
76787
76958
  var EventEmitter = __require("events");
76788
76959
  var http3 = __require("http");
76789
76960
  var { Duplex } = __require("stream");
76790
- var { createHash: createHash16 } = __require("crypto");
76961
+ var { createHash: createHash17 } = __require("crypto");
76791
76962
  var extension3 = require_extension();
76792
76963
  var PerMessageDeflate2 = require_permessage_deflate();
76793
76964
  var subprotocol2 = require_subprotocol();
@@ -77094,7 +77265,7 @@ var require_websocket_server = __commonJS({
77094
77265
  );
77095
77266
  }
77096
77267
  if (this._state > RUNNING) return abortHandshake(socket, 503);
77097
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
77268
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
77098
77269
  const headers = [
77099
77270
  "HTTP/1.1 101 Switching Protocols",
77100
77271
  "Upgrade: websocket",
@@ -145673,9 +145844,9 @@ var init_long_term = __esm({
145673
145844
  });
145674
145845
 
145675
145846
  // src/codegraph/ids.ts
145676
- import { createHash as createHash7 } from "crypto";
145847
+ import { createHash as createHash8 } from "crypto";
145677
145848
  function digest(input) {
145678
- return createHash7("sha256").update(input).digest("hex").slice(0, 16);
145849
+ return createHash8("sha256").update(input).digest("hex").slice(0, 16);
145679
145850
  }
145680
145851
  function normalizeCodePath(path23) {
145681
145852
  return path23.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
@@ -146723,7 +146894,7 @@ var init_store = __esm({
146723
146894
 
146724
146895
  // src/codegraph/code-state.ts
146725
146896
  import { execFile as execFile2 } from "child_process";
146726
- import { createHash as createHash8 } from "crypto";
146897
+ import { createHash as createHash9 } from "crypto";
146727
146898
  import { promisify as promisify3 } from "util";
146728
146899
  async function runGit(rootPath, args) {
146729
146900
  try {
@@ -146752,7 +146923,7 @@ function changedPathCount(status) {
146752
146923
  return count2;
146753
146924
  }
146754
146925
  function fingerprint(baseRevision, status) {
146755
- return createHash8("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
146926
+ return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
146756
146927
  }
146757
146928
  async function collectCodeStateSnapshot(input) {
146758
146929
  const [revision, status] = await Promise.all([
@@ -146846,12 +147017,12 @@ var init_exclude3 = __esm({
146846
147017
  });
146847
147018
 
146848
147019
  // src/codegraph/semantic-provider.ts
146849
- import { createHash as createHash9 } from "crypto";
147020
+ import { createHash as createHash10 } from "crypto";
146850
147021
  import "fs";
146851
147022
  import { resolve } from "path";
146852
147023
  import ts from "typescript";
146853
147024
  function hashText(value) {
146854
- return createHash9("sha256").update(value).digest("hex");
147025
+ return createHash10("sha256").update(value).digest("hex");
146855
147026
  }
146856
147027
  function canonicalPath(value) {
146857
147028
  const normalized = resolve(value).replace(/\\/g, "/");
@@ -147196,11 +147367,11 @@ __export(lite_provider_exports, {
147196
147367
  indexProjectLite: () => indexProjectLite,
147197
147368
  refreshProjectLite: () => refreshProjectLite
147198
147369
  });
147199
- import { createHash as createHash10 } from "crypto";
147370
+ import { createHash as createHash11 } from "crypto";
147200
147371
  import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
147201
147372
  import { join as join4, relative as relative2 } from "path";
147202
147373
  function hashText2(text2) {
147203
- return createHash10("sha256").update(text2).digest("hex");
147374
+ return createHash11("sha256").update(text2).digest("hex");
147204
147375
  }
147205
147376
  function extension2(path23) {
147206
147377
  const index = path23.lastIndexOf(".");
@@ -147833,7 +148004,7 @@ var claim_store_exports = {};
147833
148004
  __export(claim_store_exports, {
147834
148005
  ClaimStore: () => ClaimStore
147835
148006
  });
147836
- import { createHash as createHash11, randomUUID as randomUUID12 } from "crypto";
148007
+ import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
147837
148008
  function optionalText3(value) {
147838
148009
  return typeof value === "string" && value ? value : void 0;
147839
148010
  }
@@ -147886,7 +148057,7 @@ function rowToEvent3(row) {
147886
148057
  };
147887
148058
  }
147888
148059
  function evidenceKey(input) {
147889
- return createHash11("sha256").update(JSON.stringify([
148060
+ return createHash12("sha256").update(JSON.stringify([
147890
148061
  input.evidenceKind,
147891
148062
  input.evidenceId,
147892
148063
  input.relation,
@@ -148084,7 +148255,7 @@ __export(claims_exports, {
148084
148255
  supersedeClaim: () => supersedeClaim,
148085
148256
  writeClaim: () => writeClaim
148086
148257
  });
148087
- import { createHash as createHash12, randomUUID as randomUUID13 } from "crypto";
148258
+ import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
148088
148259
  function compactText2(value, field) {
148089
148260
  if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
148090
148261
  const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
@@ -148096,7 +148267,7 @@ function normalizedTerm(value) {
148096
148267
  return compactText2(value, "identity").toLocaleLowerCase("en-US");
148097
148268
  }
148098
148269
  function hashIdentity(parts) {
148099
- return createHash12("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
148270
+ return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
148100
148271
  }
148101
148272
  function buildClaimIdentity(input) {
148102
148273
  const subject = normalizedTerm(input.subject);
@@ -148337,7 +148508,7 @@ function supersedeClaim(store, input) {
148337
148508
  });
148338
148509
  }
148339
148510
  function hashObservation(observation) {
148340
- return createHash12("sha256").update(JSON.stringify([
148511
+ return createHash13("sha256").update(JSON.stringify([
148341
148512
  observation.title,
148342
148513
  observation.narrative,
148343
148514
  observation.facts,
@@ -148581,11 +148752,11 @@ var init_frontmatter = __esm({
148581
148752
  });
148582
148753
 
148583
148754
  // src/knowledge/markdown.ts
148584
- import { createHash as createHash13 } from "crypto";
148755
+ import { createHash as createHash14 } from "crypto";
148585
148756
  import { promises as fs10 } from "fs";
148586
148757
  import path18 from "path";
148587
148758
  function hashContent(content) {
148588
- return createHash13("sha256").update(content).digest("hex");
148759
+ return createHash14("sha256").update(content).digest("hex");
148589
148760
  }
148590
148761
  function stringField(data, key) {
148591
148762
  const value = data[key];
@@ -148711,11 +148882,11 @@ __export(wiki_exports, {
148711
148882
  lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
148712
148883
  readKnowledgePage: () => readKnowledgePage
148713
148884
  });
148714
- import { createHash as createHash14 } from "crypto";
148885
+ import { createHash as createHash15 } from "crypto";
148715
148886
  import { promises as fs11 } from "fs";
148716
148887
  import path19 from "path";
148717
148888
  function hash2(value) {
148718
- return createHash14("sha256").update(value).digest("hex");
148889
+ return createHash15("sha256").update(value).digest("hex");
148719
148890
  }
148720
148891
  function now() {
148721
148892
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -149572,11 +149743,11 @@ __export(workflows_exports, {
149572
149743
  syncCanonicalWorkflows: () => syncCanonicalWorkflows,
149573
149744
  writeCanonicalWorkflow: () => writeCanonicalWorkflow
149574
149745
  });
149575
- import { createHash as createHash15 } from "crypto";
149746
+ import { createHash as createHash16 } from "crypto";
149576
149747
  import { promises as fs12 } from "fs";
149577
149748
  import path20 from "path";
149578
149749
  function hash3(value) {
149579
- return createHash15("sha256").update(value).digest("hex");
149750
+ return createHash16("sha256").update(value).digest("hex");
149580
149751
  }
149581
149752
  function now2() {
149582
149753
  return (/* @__PURE__ */ new Date()).toISOString();