memorix 1.9.1 → 1.9.2

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.
package/dist/index.js CHANGED
@@ -10882,7 +10882,8 @@ function clampCursor(afterId) {
10882
10882
  }
10883
10883
  async function loadConsolidationPage(projectId, options) {
10884
10884
  const limit2 = clampBatchSize(options.limit);
10885
- const page = await getObservationStore().loadByProject(projectId, {
10885
+ const store = options.store ?? getObservationStore();
10886
+ const page = await store.loadByProject(projectId, {
10886
10887
  status: "active",
10887
10888
  afterId: clampCursor(options.afterId),
10888
10889
  limit: limit2 + 1
@@ -10942,7 +10943,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
10942
10943
  return findClusters(page.observations, threshold);
10943
10944
  }
10944
10945
  async function executeConsolidation(_projectDir, projectId, opts) {
10945
- const store = getObservationStore();
10946
+ const store = opts?.store ?? getObservationStore();
10946
10947
  const page = await loadConsolidationPage(projectId, opts ?? {});
10947
10948
  const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
10948
10949
  if (clusters.length === 0) {
@@ -148882,7 +148883,7 @@ __export(lite_provider_exports, {
148882
148883
  refreshProjectLite: () => refreshProjectLite
148883
148884
  });
148884
148885
  import { createHash as createHash10 } from "crypto";
148885
- import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
148886
+ import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
148886
148887
  import { join as join4, relative as relative2 } from "path";
148887
148888
  function hashText2(text3) {
148888
148889
  return createHash10("sha256").update(text3).digest("hex");
@@ -148899,6 +148900,9 @@ function resolveMaxFileBytes(value) {
148899
148900
  if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
148900
148901
  return Math.max(1, Math.floor(value));
148901
148902
  }
148903
+ function isPythonVirtualenvDir(dir) {
148904
+ return existsSync12(join4(dir, "pyvenv.cfg"));
148905
+ }
148902
148906
  function walk(root, exclude, maxFiles) {
148903
148907
  const out = [];
148904
148908
  const visit = (dir) => {
@@ -148916,6 +148920,7 @@ function walk(root, exclude, maxFiles) {
148916
148920
  if (entry.isDirectory()) {
148917
148921
  if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
148918
148922
  if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
148923
+ if (isPythonVirtualenvDir(abs)) continue;
148919
148924
  visit(abs);
148920
148925
  if (out.length >= maxFiles) return;
148921
148926
  continue;
@@ -152812,7 +152817,7 @@ __export(vector_backfill_runner_exports, {
152812
152817
  import { spawn as spawn4 } from "child_process";
152813
152818
  import {
152814
152819
  closeSync,
152815
- existsSync as existsSync12,
152820
+ existsSync as existsSync13,
152816
152821
  mkdirSync as mkdirSync2,
152817
152822
  openSync,
152818
152823
  readFileSync as readFileSync9,
@@ -152940,7 +152945,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
152940
152945
  }
152941
152946
  function launchDetachedVectorBackfill(request, options = {}) {
152942
152947
  const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
152943
- const exists = options.exists ?? existsSync12;
152948
+ const exists = options.exists ?? existsSync13;
152944
152949
  if (!exists(runnerPath)) return false;
152945
152950
  const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
152946
152951
  if (!lock) return false;
@@ -157861,7 +157866,7 @@ var init_sanitizer = __esm({
157861
157866
  });
157862
157867
 
157863
157868
  // src/workspace/applier.ts
157864
- import { existsSync as existsSync13, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, renameSync } from "fs";
157869
+ import { existsSync as existsSync14, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, renameSync } from "fs";
157865
157870
  import { dirname } from "path";
157866
157871
  var WorkspaceSyncApplier;
157867
157872
  var init_applier = __esm({
@@ -157892,7 +157897,7 @@ var init_applier = __esm({
157892
157897
  for (const file of files) {
157893
157898
  try {
157894
157899
  const dir = dirname(file.filePath);
157895
- if (!existsSync13(dir)) {
157900
+ if (!existsSync14(dir)) {
157896
157901
  mkdirSync3(dir, { recursive: true });
157897
157902
  }
157898
157903
  } catch (err) {
@@ -157901,7 +157906,7 @@ var init_applier = __esm({
157901
157906
  }
157902
157907
  }
157903
157908
  for (const file of files) {
157904
- if (existsSync13(file.filePath)) {
157909
+ if (existsSync14(file.filePath)) {
157905
157910
  try {
157906
157911
  const backupPath = file.filePath + `.backup-${Date.now()}`;
157907
157912
  copyFileSync(file.filePath, backupPath);
@@ -157952,7 +157957,7 @@ var init_applier = __esm({
157952
157957
  cleanBackups(backups) {
157953
157958
  for (const backup of backups) {
157954
157959
  try {
157955
- if (existsSync13(backup.backupPath)) {
157960
+ if (existsSync14(backup.backupPath)) {
157956
157961
  unlinkSync2(backup.backupPath);
157957
157962
  }
157958
157963
  } catch {
@@ -157964,7 +157969,7 @@ var init_applier = __esm({
157964
157969
  });
157965
157970
 
157966
157971
  // src/workspace/engine.ts
157967
- import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as existsSync14, cpSync, mkdirSync as mkdirSync4 } from "fs";
157972
+ import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as existsSync15, cpSync, mkdirSync as mkdirSync4 } from "fs";
157968
157973
  import { join as join19 } from "path";
157969
157974
  import { homedir as homedir21 } from "os";
157970
157975
  var WorkspaceSyncEngine;
@@ -158044,7 +158049,7 @@ var init_engine4 = __esm({
158044
158049
  }
158045
158050
  const merged = /* @__PURE__ */ new Map();
158046
158051
  for (const path38 of pathsToCheck) {
158047
- if (existsSync14(path38)) {
158052
+ if (existsSync15(path38)) {
158048
158053
  try {
158049
158054
  const content = readFileSync10(path38, "utf-8");
158050
158055
  const servers = adapter.parse(content);
@@ -158098,7 +158103,7 @@ var init_engine4 = __esm({
158098
158103
  const adapter = this.adapters.get(target);
158099
158104
  const configPath = adapter.getConfigPath(this.projectRoot);
158100
158105
  let configContent;
158101
- if (target === "antigravity" && existsSync14(configPath)) {
158106
+ if (target === "antigravity" && existsSync15(configPath)) {
158102
158107
  try {
158103
158108
  const existing = JSON.parse(readFileSync10(configPath, "utf-8"));
158104
158109
  const generated = JSON.parse(adapter.generate(result.mcpServers.scanned));
@@ -158174,13 +158179,13 @@ var init_engine4 = __esm({
158174
158179
  join19(home, dir)
158175
158180
  ];
158176
158181
  for (const skillsRoot of paths) {
158177
- if (!existsSync14(skillsRoot)) continue;
158182
+ if (!existsSync15(skillsRoot)) continue;
158178
158183
  try {
158179
158184
  const entries = readdirSync3(skillsRoot, { withFileTypes: true });
158180
158185
  for (const entry of entries) {
158181
158186
  if (!entry.isDirectory()) continue;
158182
158187
  const skillMd = join19(skillsRoot, entry.name, "SKILL.md");
158183
- if (!existsSync14(skillMd)) continue;
158188
+ if (!existsSync15(skillMd)) continue;
158184
158189
  let description = "";
158185
158190
  try {
158186
158191
  const content = readFileSync10(skillMd, "utf-8");
@@ -158229,7 +158234,7 @@ var init_engine4 = __esm({
158229
158234
  for (const skill2 of skills) {
158230
158235
  if (skill2.sourceAgent === target) continue;
158231
158236
  const dest = join19(targetDir, skill2.name);
158232
- if (existsSync14(dest)) {
158237
+ if (existsSync15(dest)) {
158233
158238
  skipped.push(`${skill2.name} (already exists in ${target})`);
158234
158239
  continue;
158235
158240
  }
@@ -158245,7 +158250,7 @@ var init_engine4 = __esm({
158245
158250
  scanWorkflows() {
158246
158251
  const workflows = [];
158247
158252
  const wfDir = join19(this.projectRoot, ".windsurf", "workflows");
158248
- if (!existsSync14(wfDir)) return workflows;
158253
+ if (!existsSync15(wfDir)) return workflows;
158249
158254
  try {
158250
158255
  const files = readdirSync3(wfDir).filter((f3) => f3.endsWith(".md"));
158251
158256
  for (const file of files) {
@@ -159643,7 +159648,7 @@ var init_request_context = __esm({
159643
159648
  function getMcpServerInfo() {
159644
159649
  return {
159645
159650
  name: "memorix",
159646
- version: true ? "1.9.1" : "1.0.1"
159651
+ version: true ? "1.9.2" : "1.0.1"
159647
159652
  };
159648
159653
  }
159649
159654
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -159711,7 +159716,7 @@ __export(behavior_exports, {
159711
159716
  getBehaviorConfig: () => getBehaviorConfig,
159712
159717
  resetBehaviorConfigCache: () => resetBehaviorConfigCache
159713
159718
  });
159714
- import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
159719
+ import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
159715
159720
  import { homedir as homedir22 } from "os";
159716
159721
  function isSessionInject(value) {
159717
159722
  return value === "full" || value === "minimal" || value === "silent";
@@ -159722,7 +159727,7 @@ function isFormationMode(value) {
159722
159727
  function legacyBehavior(homeDir) {
159723
159728
  const configPath = getLegacyConfigJsonPath(homeDir);
159724
159729
  try {
159725
- if (!existsSync15(configPath)) return {};
159730
+ if (!existsSync16(configPath)) return {};
159726
159731
  const parsed = JSON.parse(readFileSync11(configPath, "utf-8"));
159727
159732
  return parsed.behavior && typeof parsed.behavior === "object" && !Array.isArray(parsed.behavior) ? parsed.behavior : {};
159728
159733
  } catch {
@@ -161076,11 +161081,11 @@ __export(current_facts_exports, {
161076
161081
  formatGitFact: () => formatGitFact
161077
161082
  });
161078
161083
  import { execFileSync } from "child_process";
161079
- import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
161084
+ import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
161080
161085
  import path29 from "path";
161081
161086
  function readTextIfExists(filePath) {
161082
161087
  try {
161083
- if (!existsSync16(filePath)) return null;
161088
+ if (!existsSync17(filePath)) return null;
161084
161089
  return readFileSync12(filePath, "utf8");
161085
161090
  } catch {
161086
161091
  return null;
@@ -161371,7 +161376,7 @@ __export(external_provider_exports, {
161371
161376
  runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
161372
161377
  });
161373
161378
  import { spawn as spawn5 } from "child_process";
161374
- import { existsSync as existsSync17, readFileSync as readFileSync13 } from "fs";
161379
+ import { existsSync as existsSync18, readFileSync as readFileSync13 } from "fs";
161375
161380
  import { delimiter, dirname as dirname2, extname, isAbsolute as isAbsolute3, join as join20, relative as relative4, resolve as resolve3, sep } from "path";
161376
161381
  function boundedTimeout(value) {
161377
161382
  if (!Number.isFinite(value)) return DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS;
@@ -161408,13 +161413,13 @@ function resolveCommandCandidates(command) {
161408
161413
  }
161409
161414
  function resolveLaunch(command) {
161410
161415
  for (const candidate of resolveCommandCandidates(command)) {
161411
- if (!existsSync17(candidate)) continue;
161416
+ if (!existsSync18(candidate)) continue;
161412
161417
  const extension3 = extname(candidate).toLowerCase();
161413
161418
  if (extension3 === ".cmd") {
161414
161419
  const bundleRoot = resolve3(dirname2(candidate), "..");
161415
161420
  const node = join20(bundleRoot, "node.exe");
161416
161421
  const entry = join20(bundleRoot, "lib", "dist", "bin", "codegraph.js");
161417
- if (existsSync17(node) && existsSync17(entry)) {
161422
+ if (existsSync18(node) && existsSync18(entry)) {
161418
161423
  return { executable: node, prefixArgs: ["--liftoff-only", entry] };
161419
161424
  }
161420
161425
  try {
@@ -161423,7 +161428,7 @@ function resolveLaunch(command) {
161423
161428
  if (match2?.[1]) {
161424
161429
  const base = dirname2(candidate).endsWith(sep) ? dirname2(candidate) : dirname2(candidate) + sep;
161425
161430
  const entry2 = resolve3(match2[1].replace(/%(?:~)?dp0%?/gi, base));
161426
- if (existsSync17(entry2)) return { executable: process.execPath, prefixArgs: [entry2] };
161431
+ if (existsSync18(entry2)) return { executable: process.execPath, prefixArgs: [entry2] };
161427
161432
  }
161428
161433
  } catch {
161429
161434
  }
@@ -161571,7 +161576,7 @@ async function inspectExternalCodeGraph(input) {
161571
161576
  const health2 = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
161572
161577
  return { health: health2, quality: providerQuality({ mode, health: health2 }) };
161573
161578
  }
161574
- if (!existsSync17(join20(input.projectRoot, ".codegraph"))) {
161579
+ if (!existsSync18(join20(input.projectRoot, ".codegraph"))) {
161575
161580
  const health2 = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
161576
161581
  return { health: health2, quality: providerQuality({ mode, health: health2 }) };
161577
161582
  }
@@ -161607,7 +161612,7 @@ async function runExternalCodeGraphLifecycle(input) {
161607
161612
  };
161608
161613
  }
161609
161614
  const indexPath = join20(input.projectRoot, ".codegraph");
161610
- if (input.action === "sync" && !existsSync17(indexPath)) {
161615
+ if (input.action === "sync" && !existsSync18(indexPath)) {
161611
161616
  const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
161612
161617
  return {
161613
161618
  action: input.action,
@@ -161617,7 +161622,7 @@ async function runExternalCodeGraphLifecycle(input) {
161617
161622
  quality: providerQuality({ mode, health })
161618
161623
  };
161619
161624
  }
161620
- if (input.action === "init" && existsSync17(indexPath)) {
161625
+ if (input.action === "init" && existsSync18(indexPath)) {
161621
161626
  const inspected2 = await inspectExternalCodeGraph(input);
161622
161627
  return {
161623
161628
  action: input.action,
@@ -162678,7 +162683,7 @@ __export(auto_context_exports, {
162678
162683
  formatAutoProjectContextSummary: () => formatAutoProjectContextSummary,
162679
162684
  formatLegacyAutoProjectContextPrompt: () => formatLegacyAutoProjectContextPrompt
162680
162685
  });
162681
- import { existsSync as existsSync18, statSync as statSync5 } from "fs";
162686
+ import { existsSync as existsSync19, statSync as statSync5 } from "fs";
162682
162687
  import path30 from "path";
162683
162688
  function activeProjectObservations(observations2, projectId) {
162684
162689
  return observations2.filter((obs) => obs.projectId === projectId && (obs.status ?? "active") === "active");
@@ -163024,7 +163029,7 @@ function existingLensCandidates(rootPath, lens) {
163024
163029
  for (const candidate of lensPathCandidates(lens)) {
163025
163030
  const absolute = path30.join(rootPath, candidate);
163026
163031
  try {
163027
- if (!existsSync18(absolute)) continue;
163032
+ if (!existsSync19(absolute)) continue;
163028
163033
  const stat5 = statSync5(absolute);
163029
163034
  if (stat5.isFile()) out.push(candidate);
163030
163035
  if (stat5.isDirectory()) out.push(candidate.replace(/\\/g, "/"));
@@ -163558,7 +163563,7 @@ var engine_exports2 = {};
163558
163563
  __export(engine_exports2, {
163559
163564
  SkillsEngine: () => SkillsEngine
163560
163565
  });
163561
- import { existsSync as existsSync19, readFileSync as readFileSync14, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
163566
+ import { existsSync as existsSync20, readFileSync as readFileSync14, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
163562
163567
  import { join as join21 } from "path";
163563
163568
  import { homedir as homedir23 } from "os";
163564
163569
  var SKILLS_DIRS, SKILL_WORTHY_TYPES, MIN_OBS_FOR_SKILL, MIN_SCORE_FOR_SKILL, LOW_SIGNAL_TITLE_PATTERNS, LOW_SIGNAL_ENTITY_PATTERNS, COMMAND_TRACE_PATTERNS2, SkillsEngine;
@@ -163639,7 +163644,7 @@ var init_engine5 = __esm({
163639
163644
  paths.push(join21(home, dir));
163640
163645
  }
163641
163646
  for (const skillsRoot of paths) {
163642
- if (!existsSync19(skillsRoot)) continue;
163647
+ if (!existsSync20(skillsRoot)) continue;
163643
163648
  try {
163644
163649
  const entries = readdirSync4(skillsRoot, { withFileTypes: true });
163645
163650
  for (const entry of entries) {
@@ -163647,7 +163652,7 @@ var init_engine5 = __esm({
163647
163652
  const name = entry.name;
163648
163653
  if (seen.has(name)) continue;
163649
163654
  const skillMd = join21(skillsRoot, name, "SKILL.md");
163650
- if (!existsSync19(skillMd)) continue;
163655
+ if (!existsSync20(skillMd)) continue;
163651
163656
  try {
163652
163657
  const content = readFileSync14(skillMd, "utf-8");
163653
163658
  const description = this.parseDescription(content);
@@ -165448,7 +165453,8 @@ async function executeDeduplicate(context, payload, token) {
165448
165453
  async function previewConsolidate(context) {
165449
165454
  const clusters = await findConsolidationCandidates(
165450
165455
  context.projectRoot ?? context.dataDir,
165451
- context.projectId
165456
+ context.projectId,
165457
+ { store: context.store }
165452
165458
  );
165453
165459
  const payload = { clusterIds: normalizeClusters(clusters.map((cluster) => cluster.ids)) };
165454
165460
  return {
@@ -165471,11 +165477,19 @@ async function executeConsolidate(context, payload, token) {
165471
165477
  const clusterIds = record80.clusterIds.map((ids, index) => payloadIds(ids, `clusterIds[${index}]`));
165472
165478
  const normalized = { clusterIds: normalizeClusters(clusterIds) };
165473
165479
  verify("consolidate", context.projectId, normalized, token);
165474
- const current = await findConsolidationCandidates(context.projectRoot ?? context.dataDir, context.projectId);
165480
+ const current = await findConsolidationCandidates(
165481
+ context.projectRoot ?? context.dataDir,
165482
+ context.projectId,
165483
+ { store: context.store }
165484
+ );
165475
165485
  if (JSON.stringify(normalized.clusterIds) !== JSON.stringify(normalizeClusters(current.map((cluster) => cluster.ids)))) {
165476
165486
  throw new DashboardMaintenanceError("Memory changed after the preview. Refresh before consolidating.", 409);
165477
165487
  }
165478
- const result = await executeConsolidation(context.projectRoot ?? context.dataDir, context.projectId);
165488
+ const result = await executeConsolidation(
165489
+ context.projectRoot ?? context.dataDir,
165490
+ context.projectId,
165491
+ { store: context.store }
165492
+ );
165479
165493
  return { action: "consolidate", projectId: context.projectId, ...result };
165480
165494
  }
165481
165495
  async function retentionCandidates(context) {
@@ -166632,7 +166646,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
166632
166646
  }
166633
166647
  case "/config": {
166634
166648
  const os6 = await import("os");
166635
- const { existsSync: existsSync22 } = await import("fs");
166649
+ const { existsSync: existsSync23 } = await import("fs");
166636
166650
  const { join: join26 } = await import("path");
166637
166651
  const configProjectRoot = effectiveProjectRoot;
166638
166652
  const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
@@ -166660,7 +166674,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
166660
166674
  if (fpath === null) {
166661
166675
  files[key] = { exists: false, path: "unavailable", unavailable: true };
166662
166676
  } else {
166663
- files[key] = { exists: existsSync22(fpath), path: fpath };
166677
+ files[key] = { exists: existsSync23(fpath), path: fpath };
166664
166678
  }
166665
166679
  }
166666
166680
  } catch {
@@ -167470,7 +167484,7 @@ var init_task_graph = __esm({
167470
167484
 
167471
167485
  // src/orchestrate/context-collector.ts
167472
167486
  import { execFileSync as execFileSync2 } from "child_process";
167473
- import { readFileSync as readFileSync15, existsSync as existsSync20 } from "fs";
167487
+ import { readFileSync as readFileSync15, existsSync as existsSync21 } from "fs";
167474
167488
  import { join as join22 } from "path";
167475
167489
  function normalizeEntryLimit(value, fallback) {
167476
167490
  if (!Number.isSafeInteger(value) || value < 1) return fallback;
@@ -167547,7 +167561,7 @@ function collectFileTree(projectDir2, maxEntries) {
167547
167561
  function collectDependencies(projectDir2) {
167548
167562
  try {
167549
167563
  const pkgPath = join22(projectDir2, "package.json");
167550
- if (!existsSync20(pkgPath)) return "";
167564
+ if (!existsSync21(pkgPath)) return "";
167551
167565
  const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
167552
167566
  const parts = [];
167553
167567
  if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {
@@ -170048,11 +170062,11 @@ __export(hooks_path_exports, {
170048
170062
  resolveGitDir: () => resolveGitDir,
170049
170063
  resolveHooksDir: () => resolveHooksDir
170050
170064
  });
170051
- import { existsSync as existsSync21, readFileSync as readFileSync16, statSync as statSync6, mkdirSync as mkdirSync6 } from "fs";
170065
+ import { existsSync as existsSync22, readFileSync as readFileSync16, statSync as statSync6, mkdirSync as mkdirSync6 } from "fs";
170052
170066
  import path35 from "path";
170053
170067
  function resolveGitDir(projectRoot) {
170054
170068
  const dotGit = path35.join(projectRoot, ".git");
170055
- if (!existsSync21(dotGit)) return null;
170069
+ if (!existsSync22(dotGit)) return null;
170056
170070
  const stat5 = statSync6(dotGit);
170057
170071
  if (stat5.isDirectory()) {
170058
170072
  return dotGit;
@@ -170064,7 +170078,7 @@ function resolveGitDir(projectRoot) {
170064
170078
  if (match2) {
170065
170079
  const gitdir = match2[1].trim();
170066
170080
  const resolved = path35.isAbsolute(gitdir) ? gitdir : path35.resolve(projectRoot, gitdir);
170067
- if (existsSync21(resolved)) {
170081
+ if (existsSync22(resolved)) {
170068
170082
  return resolved;
170069
170083
  }
170070
170084
  }
@@ -174659,10 +174673,10 @@ Preview: ${analysis.description.slice(0, 300)}${analysis.description.length > 30
174659
174673
  const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
174660
174674
  const resolved = ensureHooksDir2(project.rootPath);
174661
174675
  if (resolved) {
174662
- const { existsSync: existsSync22, readFileSync: readFileSync17, writeFileSync: writeFileSync5, chmodSync } = await import("fs");
174676
+ const { existsSync: existsSync23, readFileSync: readFileSync17, writeFileSync: writeFileSync5, chmodSync } = await import("fs");
174663
174677
  const { hookPath } = resolved;
174664
174678
  const HOOK_MARKER = "# [memorix-git-hook]";
174665
- const needsInstall = !existsSync22(hookPath) || !readFileSync17(hookPath, "utf-8").includes(HOOK_MARKER);
174679
+ const needsInstall = !existsSync23(hookPath) || !readFileSync17(hookPath, "utf-8").includes(HOOK_MARKER);
174666
174680
  if (needsInstall) {
174667
174681
  const hookScript = `#!/bin/sh
174668
174682
  ${HOOK_MARKER}
@@ -174671,7 +174685,7 @@ if command -v memorix >/dev/null 2>&1; then
174671
174685
  memorix ingest commit --auto >/dev/null 2>&1 &
174672
174686
  fi
174673
174687
  `;
174674
- if (existsSync22(hookPath)) {
174688
+ if (existsSync23(hookPath)) {
174675
174689
  const existing = readFileSync17(hookPath, "utf-8");
174676
174690
  writeFileSync5(hookPath, existing.trimEnd() + `
174677
174691
 
@@ -175343,7 +175357,7 @@ var init_serve_shared = __esm({
175343
175357
 
175344
175358
  // src/cli/version.ts
175345
175359
  function getCliVersion() {
175346
- return true ? "1.9.1" : pkg.version;
175360
+ return true ? "1.9.2" : pkg.version;
175347
175361
  }
175348
175362
  var init_version3 = __esm({
175349
175363
  "src/cli/version.ts"() {
@@ -9418,7 +9418,8 @@ function clampCursor(afterId) {
9418
9418
  }
9419
9419
  async function loadConsolidationPage(projectId, options) {
9420
9420
  const limit2 = clampBatchSize(options.limit);
9421
- const page = await getObservationStore().loadByProject(projectId, {
9421
+ const store = options.store ?? getObservationStore();
9422
+ const page = await store.loadByProject(projectId, {
9422
9423
  status: "active",
9423
9424
  afterId: clampCursor(options.afterId),
9424
9425
  limit: limit2 + 1
@@ -9478,7 +9479,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
9478
9479
  return findClusters(page.observations, threshold);
9479
9480
  }
9480
9481
  async function executeConsolidation(_projectDir, projectId, opts) {
9481
- const store = getObservationStore();
9482
+ const store = opts?.store ?? getObservationStore();
9482
9483
  const page = await loadConsolidationPage(projectId, opts ?? {});
9483
9484
  const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
9484
9485
  if (clusters.length === 0) {
@@ -147104,7 +147105,7 @@ __export(lite_provider_exports, {
147104
147105
  refreshProjectLite: () => refreshProjectLite
147105
147106
  });
147106
147107
  import { createHash as createHash10 } from "crypto";
147107
- import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
147108
+ import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
147108
147109
  import { join as join4, relative as relative2 } from "path";
147109
147110
  function hashText2(text2) {
147110
147111
  return createHash10("sha256").update(text2).digest("hex");
@@ -147121,6 +147122,9 @@ function resolveMaxFileBytes(value) {
147121
147122
  if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
147122
147123
  return Math.max(1, Math.floor(value));
147123
147124
  }
147125
+ function isPythonVirtualenvDir(dir) {
147126
+ return existsSync12(join4(dir, "pyvenv.cfg"));
147127
+ }
147124
147128
  function walk(root, exclude, maxFiles) {
147125
147129
  const out = [];
147126
147130
  const visit = (dir) => {
@@ -147138,6 +147142,7 @@ function walk(root, exclude, maxFiles) {
147138
147142
  if (entry.isDirectory()) {
147139
147143
  if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
147140
147144
  if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
147145
+ if (isPythonVirtualenvDir(abs)) continue;
147141
147146
  visit(abs);
147142
147147
  if (out.length >= maxFiles) return;
147143
147148
  continue;
@@ -150657,7 +150662,7 @@ __export(vector_backfill_runner_exports, {
150657
150662
  import { spawn as spawn4 } from "child_process";
150658
150663
  import {
150659
150664
  closeSync,
150660
- existsSync as existsSync12,
150665
+ existsSync as existsSync13,
150661
150666
  mkdirSync as mkdirSync2,
150662
150667
  openSync,
150663
150668
  readFileSync as readFileSync9,
@@ -150785,7 +150790,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
150785
150790
  }
150786
150791
  function launchDetachedVectorBackfill(request, options = {}) {
150787
150792
  const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
150788
- const exists = options.exists ?? existsSync12;
150793
+ const exists = options.exists ?? existsSync13;
150789
150794
  if (!exists(runnerPath)) return false;
150790
150795
  const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
150791
150796
  if (!lock) return false;
@@ -9870,7 +9870,8 @@ function clampCursor(afterId) {
9870
9870
  }
9871
9871
  async function loadConsolidationPage(projectId, options) {
9872
9872
  const limit2 = clampBatchSize(options.limit);
9873
- const page = await getObservationStore().loadByProject(projectId, {
9873
+ const store = options.store ?? getObservationStore();
9874
+ const page = await store.loadByProject(projectId, {
9874
9875
  status: "active",
9875
9876
  afterId: clampCursor(options.afterId),
9876
9877
  limit: limit2 + 1
@@ -9930,7 +9931,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
9930
9931
  return findClusters(page.observations, threshold);
9931
9932
  }
9932
9933
  async function executeConsolidation(_projectDir, projectId, opts) {
9933
- const store = getObservationStore();
9934
+ const store = opts?.store ?? getObservationStore();
9934
9935
  const page = await loadConsolidationPage(projectId, opts ?? {});
9935
9936
  const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
9936
9937
  if (clusters.length === 0) {
@@ -146735,7 +146736,7 @@ __export(lite_provider_exports, {
146735
146736
  refreshProjectLite: () => refreshProjectLite
146736
146737
  });
146737
146738
  import { createHash as createHash10 } from "crypto";
146738
- import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
146739
+ import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
146739
146740
  import { join as join4, relative as relative2 } from "path";
146740
146741
  function hashText2(text2) {
146741
146742
  return createHash10("sha256").update(text2).digest("hex");
@@ -146752,6 +146753,9 @@ function resolveMaxFileBytes(value) {
146752
146753
  if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
146753
146754
  return Math.max(1, Math.floor(value));
146754
146755
  }
146756
+ function isPythonVirtualenvDir(dir) {
146757
+ return existsSync10(join4(dir, "pyvenv.cfg"));
146758
+ }
146755
146759
  function walk(root, exclude, maxFiles) {
146756
146760
  const out = [];
146757
146761
  const visit = (dir) => {
@@ -146769,6 +146773,7 @@ function walk(root, exclude, maxFiles) {
146769
146773
  if (entry.isDirectory()) {
146770
146774
  if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
146771
146775
  if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
146776
+ if (isPythonVirtualenvDir(abs)) continue;
146772
146777
  visit(abs);
146773
146778
  if (out.length >= maxFiles) return;
146774
146779
  continue;
@@ -150288,7 +150293,7 @@ __export(vector_backfill_runner_exports, {
150288
150293
  import { spawn as spawn2 } from "child_process";
150289
150294
  import {
150290
150295
  closeSync,
150291
- existsSync as existsSync10,
150296
+ existsSync as existsSync11,
150292
150297
  mkdirSync as mkdirSync2,
150293
150298
  openSync,
150294
150299
  readFileSync as readFileSync9,
@@ -150416,7 +150421,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
150416
150421
  }
150417
150422
  function launchDetachedVectorBackfill(request, options = {}) {
150418
150423
  const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
150419
- const exists = options.exists ?? existsSync10;
150424
+ const exists = options.exists ?? existsSync11;
150420
150425
  if (!exists(runnerPath)) return false;
150421
150426
  const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
150422
150427
  if (!lock) return false;
@@ -151711,7 +151716,7 @@ __export(audio_jobs_exports, {
151711
151716
  transcribeAudio: () => transcribeAudio
151712
151717
  });
151713
151718
  import { spawn as spawn3 } from "child_process";
151714
- import { existsSync as existsSync11 } from "fs";
151719
+ import { existsSync as existsSync12 } from "fs";
151715
151720
  import path21 from "path";
151716
151721
  import { fileURLToPath as fileURLToPath4 } from "url";
151717
151722
  function safeError3(error) {
@@ -151962,7 +151967,7 @@ function resolveMediaAudioRunnerPath(moduleUrl = import.meta.url) {
151962
151967
  }
151963
151968
  function launchMediaAudioRunner(request, options = {}) {
151964
151969
  const runnerPath = options.runnerPath ?? resolveMediaAudioRunnerPath();
151965
- if (!existsSync11(runnerPath)) return { launched: false, reason: "Audio runner is unavailable until Memorix is built or reinstalled." };
151970
+ if (!existsSync12(runnerPath)) return { launched: false, reason: "Audio runner is unavailable until Memorix is built or reinstalled." };
151966
151971
  try {
151967
151972
  const child = spawn3(process.execPath, [runnerPath, JSON.stringify(request)], {
151968
151973
  cwd: request.projectRoot,
@@ -9388,7 +9388,8 @@ function clampCursor(afterId) {
9388
9388
  }
9389
9389
  async function loadConsolidationPage(projectId, options) {
9390
9390
  const limit2 = clampBatchSize(options.limit);
9391
- const page = await getObservationStore().loadByProject(projectId, {
9391
+ const store = options.store ?? getObservationStore();
9392
+ const page = await store.loadByProject(projectId, {
9392
9393
  status: "active",
9393
9394
  afterId: clampCursor(options.afterId),
9394
9395
  limit: limit2 + 1
@@ -9448,7 +9449,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
9448
9449
  return findClusters(page.observations, threshold);
9449
9450
  }
9450
9451
  async function executeConsolidation(_projectDir, projectId, opts) {
9451
- const store = getObservationStore();
9452
+ const store = opts?.store ?? getObservationStore();
9452
9453
  const page = await loadConsolidationPage(projectId, opts ?? {});
9453
9454
  const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
9454
9455
  if (clusters.length === 0) {
@@ -147074,7 +147075,7 @@ __export(lite_provider_exports, {
147074
147075
  refreshProjectLite: () => refreshProjectLite
147075
147076
  });
147076
147077
  import { createHash as createHash10 } from "crypto";
147077
- import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
147078
+ import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
147078
147079
  import { join as join4, relative as relative2 } from "path";
147079
147080
  function hashText2(text2) {
147080
147081
  return createHash10("sha256").update(text2).digest("hex");
@@ -147091,6 +147092,9 @@ function resolveMaxFileBytes(value) {
147091
147092
  if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
147092
147093
  return Math.max(1, Math.floor(value));
147093
147094
  }
147095
+ function isPythonVirtualenvDir(dir) {
147096
+ return existsSync11(join4(dir, "pyvenv.cfg"));
147097
+ }
147094
147098
  function walk(root, exclude, maxFiles) {
147095
147099
  const out = [];
147096
147100
  const visit = (dir) => {
@@ -147108,6 +147112,7 @@ function walk(root, exclude, maxFiles) {
147108
147112
  if (entry.isDirectory()) {
147109
147113
  if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
147110
147114
  if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
147115
+ if (isPythonVirtualenvDir(abs)) continue;
147111
147116
  visit(abs);
147112
147117
  if (out.length >= maxFiles) return;
147113
147118
  continue;
@@ -150627,7 +150632,7 @@ __export(vector_backfill_runner_exports, {
150627
150632
  import { spawn as spawn3 } from "child_process";
150628
150633
  import {
150629
150634
  closeSync,
150630
- existsSync as existsSync11,
150635
+ existsSync as existsSync12,
150631
150636
  mkdirSync as mkdirSync2,
150632
150637
  openSync,
150633
150638
  readFileSync as readFileSync9,
@@ -150755,7 +150760,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
150755
150760
  }
150756
150761
  function launchDetachedVectorBackfill(request, options = {}) {
150757
150762
  const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
150758
- const exists = options.exists ?? existsSync11;
150763
+ const exists = options.exists ?? existsSync12;
150759
150764
  if (!exists(runnerPath)) return false;
150760
150765
  const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
150761
150766
  if (!lock) return false;
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.9.2] - 2026-09-11
8
+
9
+ ### Fixed
10
+ - **Non-interactive MCP startup** -- running the package without arguments
11
+ through piped stdio now starts the MCP server, while a real terminal keeps
12
+ opening the bundled memcode agent. This makes generic npm MCP launchers and
13
+ registry handshake checks use the correct protocol entry point.
14
+ - **Maintenance initialization** -- dashboard Consolidate uses its
15
+ request-scoped observation store, and CLI deduplication initializes the
16
+ project memory LLM before checking availability.
17
+
7
18
  ## [1.9.1] - 2026-09-08
8
19
 
9
20
  ### Changed