grepmax 0.26.42 → 0.26.44

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 (95) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/NOTICE +6 -0
  3. package/README.md +7 -1
  4. package/dist/bin.js +4 -0
  5. package/dist/commands/doctor.js +23 -33
  6. package/dist/commands/mcp.js +144 -67
  7. package/dist/commands/project.js +0 -1
  8. package/dist/commands/similar.js +0 -1
  9. package/dist/commands/skeleton.js +0 -1
  10. package/dist/commands/status.js +35 -19
  11. package/dist/commands/surprises.js +0 -1
  12. package/dist/commands/symbols.js +0 -1
  13. package/dist/commands/watch.js +2 -1
  14. package/dist/eval-like-limit-probe.js +60 -41
  15. package/dist/lib/analysis/surprising-connections.js +4 -3
  16. package/dist/lib/daemon/daemon.js +36 -9
  17. package/dist/lib/daemon/graph-handler.js +33 -33
  18. package/dist/lib/daemon/ipc-handler.js +11 -10
  19. package/dist/lib/daemon/rows-handler.js +13 -51
  20. package/dist/lib/daemon/vector-handler.js +18 -17
  21. package/dist/lib/graph/graph-builder.js +33 -16
  22. package/dist/lib/graph/impact.js +9 -8
  23. package/dist/lib/index/index-config.js +2 -2
  24. package/dist/lib/llm/config.js +9 -3
  25. package/dist/lib/llm/tools.js +5 -4
  26. package/dist/lib/search/pagerank.js +2 -1
  27. package/dist/lib/search/searcher.js +5 -4
  28. package/dist/lib/skeleton/retriever.js +2 -1
  29. package/dist/lib/store/compaction-result.js +35 -0
  30. package/dist/lib/store/lance-sdk.js +46 -0
  31. package/dist/lib/store/vector-db.js +118 -31
  32. package/dist/lib/utils/cross-project.js +2 -2
  33. package/dist/lib/utils/doctor-optimize.js +81 -0
  34. package/dist/lib/utils/project-registry.js +8 -8
  35. package/dist/lib/utils/query-timeout.js +53 -13
  36. package/dist/lib/utils/store-access.js +6 -5
  37. package/dist/lib/utils/store-context.js +102 -0
  38. package/dist/lib/utils/stores.js +1 -1
  39. package/dist/vendor/lancedb/LICENSE +202 -0
  40. package/dist/vendor/lancedb/NODEJS_THIRD_PARTY_LICENSES.md +668 -0
  41. package/dist/vendor/lancedb/RUST_THIRD_PARTY_LICENSES.html +14607 -0
  42. package/dist/vendor/lancedb/arrow.d.ts +296 -0
  43. package/dist/vendor/lancedb/arrow.js +1145 -0
  44. package/dist/vendor/lancedb/arrow_type.d.ts +9 -0
  45. package/dist/vendor/lancedb/arrow_type.js +29 -0
  46. package/dist/vendor/lancedb/connection.d.ts +508 -0
  47. package/dist/vendor/lancedb/connection.js +298 -0
  48. package/dist/vendor/lancedb/embedding/embedding_function.d.ts +103 -0
  49. package/dist/vendor/lancedb/embedding/embedding_function.js +192 -0
  50. package/dist/vendor/lancedb/embedding/index.d.ts +37 -0
  51. package/dist/vendor/lancedb/embedding/index.js +108 -0
  52. package/dist/vendor/lancedb/embedding/openai.d.ts +16 -0
  53. package/dist/vendor/lancedb/embedding/openai.js +81 -0
  54. package/dist/vendor/lancedb/embedding/registry.d.ts +94 -0
  55. package/dist/vendor/lancedb/embedding/registry.js +221 -0
  56. package/dist/vendor/lancedb/embedding/transformers.d.ts +36 -0
  57. package/dist/vendor/lancedb/embedding/transformers.js +110 -0
  58. package/dist/vendor/lancedb/header.d.ts +162 -0
  59. package/dist/vendor/lancedb/header.js +217 -0
  60. package/dist/vendor/lancedb/index.d.ts +246 -0
  61. package/dist/vendor/lancedb/index.js +176 -0
  62. package/dist/vendor/lancedb/indices.d.ts +721 -0
  63. package/dist/vendor/lancedb/indices.js +166 -0
  64. package/dist/vendor/lancedb/license_header.txt +2 -0
  65. package/dist/vendor/lancedb/materialized_view.d.ts +69 -0
  66. package/dist/vendor/lancedb/materialized_view.js +112 -0
  67. package/dist/vendor/lancedb/merge.d.ts +104 -0
  68. package/dist/vendor/lancedb/merge.js +120 -0
  69. package/dist/vendor/lancedb/native.d.ts +1193 -0
  70. package/dist/vendor/lancedb/native.js +688 -0
  71. package/dist/vendor/lancedb/oauth.d.ts +66 -0
  72. package/dist/vendor/lancedb/oauth.js +15 -0
  73. package/dist/vendor/lancedb/otel.d.ts +26 -0
  74. package/dist/vendor/lancedb/otel.js +114 -0
  75. package/dist/vendor/lancedb/permutation.d.ts +143 -0
  76. package/dist/vendor/lancedb/permutation.js +184 -0
  77. package/dist/vendor/lancedb/provenance.json +6 -0
  78. package/dist/vendor/lancedb/query.d.ts +663 -0
  79. package/dist/vendor/lancedb/query.js +966 -0
  80. package/dist/vendor/lancedb/rerankers/index.d.ts +5 -0
  81. package/dist/vendor/lancedb/rerankers/index.js +19 -0
  82. package/dist/vendor/lancedb/rerankers/rrf.d.ts +14 -0
  83. package/dist/vendor/lancedb/rerankers/rrf.js +28 -0
  84. package/dist/vendor/lancedb/sanitize.d.ts +32 -0
  85. package/dist/vendor/lancedb/sanitize.js +544 -0
  86. package/dist/vendor/lancedb/scannable.d.ts +92 -0
  87. package/dist/vendor/lancedb/scannable.js +200 -0
  88. package/dist/vendor/lancedb/schema.d.ts +16 -0
  89. package/dist/vendor/lancedb/schema.js +387 -0
  90. package/dist/vendor/lancedb/table.d.ts +1069 -0
  91. package/dist/vendor/lancedb/table.js +498 -0
  92. package/dist/vendor/lancedb/util.d.ts +14 -0
  93. package/dist/vendor/lancedb/util.js +77 -0
  94. package/package.json +19 -7
  95. package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
@@ -79,6 +79,7 @@ const graph_handler_1 = require("../lib/daemon/graph-handler");
79
79
  const rows_handler_1 = require("../lib/daemon/rows-handler");
80
80
  const vector_handler_1 = require("../lib/daemon/vector-handler");
81
81
  const test_hits_1 = require("../lib/graph/test-hits");
82
+ const embedding_generation_1 = require("../lib/index/embedding-generation");
82
83
  const embedding_status_1 = require("../lib/index/embedding-status");
83
84
  const index_config_1 = require("../lib/index/index-config");
84
85
  const syncer_1 = require("../lib/index/syncer");
@@ -88,6 +89,7 @@ const searcher_1 = require("../lib/search/searcher");
88
89
  const annotator_1 = require("../lib/skeleton/annotator");
89
90
  const skeletonizer_1 = require("../lib/skeleton/skeletonizer");
90
91
  const symbol_extractor_1 = require("../lib/skeleton/symbol-extractor");
92
+ const compaction_result_1 = require("../lib/store/compaction-result");
91
93
  const meta_cache_1 = require("../lib/store/meta-cache");
92
94
  const cross_project_1 = require("../lib/utils/cross-project");
93
95
  const daemon_client_1 = require("../lib/utils/daemon-client");
@@ -99,8 +101,11 @@ const project_registry_1 = require("../lib/utils/project-registry");
99
101
  const project_root_1 = require("../lib/utils/project-root");
100
102
  const scope_filter_1 = require("../lib/utils/scope-filter");
101
103
  const store_access_1 = require("../lib/utils/store-access");
104
+ const store_context_1 = require("../lib/utils/store-context");
105
+ const stores_1 = require("../lib/utils/stores");
102
106
  const watcher_launcher_1 = require("../lib/utils/watcher-launcher");
103
107
  const watcher_store_1 = require("../lib/utils/watcher-store");
108
+ const pool_1 = require("../lib/workers/pool");
104
109
  // ---------------------------------------------------------------------------
105
110
  // Helpers
106
111
  // ---------------------------------------------------------------------------
@@ -142,9 +147,6 @@ function isMcpSessionFallback(error) {
142
147
  /**
143
148
  * MCP's read-tool fallback policy, in one object so every tool shares it.
144
149
  *
145
- * - `fallbackOnUnknownVerb` — a daemon older than this build does not know the
146
- * read verbs (the live 0.26.27 daemon does not); answer from the store rather
147
- * than failing the tool call. Removed one release after the verbs ship.
148
150
  * - `fallbackOnOversize` — the daemon's 2 MB response cap. See
149
151
  * `isOversizeError` for why MCP opts in and the CLI does not.
150
152
  * - `extraFallback` — the two session-readiness answers above.
@@ -160,7 +162,6 @@ function isMcpSessionFallback(error) {
160
162
  const MCP_WATCH_LEASE_RENEW_MS = 5 * 60 * 1000;
161
163
  const MCP_WATCH_LEASE_TTL_MS = 3 * MCP_WATCH_LEASE_RENEW_MS;
162
164
  const MCP_STORE_FALLBACK = {
163
- fallbackOnUnknownVerb: true,
164
165
  fallbackOnOversize: true,
165
166
  extraFallback: isMcpSessionFallback,
166
167
  };
@@ -171,7 +172,6 @@ const MCP_STORE_FALLBACK = {
171
172
  */
172
173
  function shouldFallbackMcpDaemonSearch(error) {
173
174
  return ((0, store_access_1.classifyDaemonError)(error) === "no-daemon" ||
174
- (0, store_access_1.isUnknownCommandError)(error) ||
175
175
  (0, store_access_1.isOversizeError)(error) ||
176
176
  isMcpSessionFallback(error));
177
177
  }
@@ -191,14 +191,30 @@ function resolveMcpProject(requested, currentRoot, projects = (0, project_regist
191
191
  if (byName.length > 1)
192
192
  return undefined;
193
193
  const resolved = path.resolve(value);
194
- return projects.find((project) => path.resolve(project.root) === resolved);
194
+ const physical = (value) => {
195
+ try {
196
+ return fs.realpathSync(value);
197
+ }
198
+ catch (_a) {
199
+ return path.resolve(value);
200
+ }
201
+ };
202
+ return projects.find((project) => physical(project.root) === physical(resolved));
195
203
  }
196
204
  const resolvedCurrent = path.resolve(currentRoot);
197
- const exact = projects.find((project) => path.resolve(project.root) === resolvedCurrent);
205
+ const physical = (value) => {
206
+ try {
207
+ return fs.realpathSync(value);
208
+ }
209
+ catch (_a) {
210
+ return path.resolve(value);
211
+ }
212
+ };
213
+ const exact = projects.find((project) => physical(project.root) === physical(resolvedCurrent));
198
214
  if (exact)
199
215
  return exact;
200
216
  return projects
201
- .filter((project) => (0, path_containment_1.isPathWithin)(project.root, resolvedCurrent))
217
+ .filter((project) => (0, path_containment_1.isPathWithin)(physical(project.root), physical(resolvedCurrent)))
202
218
  .sort((a, b) => b.root.length - a.root.length)[0];
203
219
  }
204
220
  function containMcpTarget(root, target) {
@@ -379,6 +395,11 @@ exports.mcp = new commander_1.Command("mcp")
379
395
  // --- Project context ---
380
396
  const projectRoot = (0, project_root_1.findProjectRoot)(process.cwd());
381
397
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
398
+ const currentRoot = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.root) !== null && _b !== void 0 ? _b : projectRoot; };
399
+ const storeProjects = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.projects) !== null && _b !== void 0 ? _b : (0, project_registry_1.listProjects)(); };
400
+ const storeConfig = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.config) !== null && _b !== void 0 ? _b : (0, index_config_1.readGlobalConfig)(); };
401
+ const secondary = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.secondary) !== null && _b !== void 0 ? _b : false; };
402
+ const storeDir = () => { var _a; var _b; return (_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.lancedbDir) !== null && _b !== void 0 ? _b : paths.lancedbDir; };
382
403
  // Propagate project root to worker processes
383
404
  process.env.GMAX_PROJECT_ROOT = paths.root;
384
405
  // --- Store access ---
@@ -387,15 +408,15 @@ exports.mcp = new commander_1.Command("mcp")
387
408
  * `inProcess` branch is entered only when no daemon serves the verb.
388
409
  */
389
410
  function readStore(name, opts) {
390
- return (0, store_access_1.withStoreRead)(name, Object.assign(Object.assign({}, opts), MCP_STORE_FALLBACK));
411
+ return (0, store_access_1.withStoreRead)(name, Object.assign(Object.assign(Object.assign({}, opts), MCP_STORE_FALLBACK), { skipDaemon: secondary() }));
391
412
  }
392
413
  /** Open the shared store for the duration of one fallback, then close it. */
393
414
  function localStore(fn) {
394
- return (0, rows_handler_1.withLocalStore)(paths.lancedbDir, fn);
415
+ return (0, rows_handler_1.withLocalStore)(storeDir(), fn, storeConfig().vectorDim);
395
416
  }
396
417
  /** A graph verb with MCP's fallback allowances. */
397
418
  function graphVerb(verb, call) {
398
- return (0, graph_handler_1.callGraphVerb)(verb, Object.assign(Object.assign({}, call), { fallback: MCP_STORE_FALLBACK }));
419
+ return (0, graph_handler_1.callGraphVerb)(verb, Object.assign(Object.assign({}, call), { fallback: Object.assign(Object.assign({}, MCP_STORE_FALLBACK), (secondary() ? { skipDaemon: true } : {})) }));
399
420
  }
400
421
  /**
401
422
  * MCP tools take no `--in`/`--exclude`, so a tool's scope is always the
@@ -439,8 +460,16 @@ exports.mcp = new commander_1.Command("mcp")
439
460
  };
440
461
  },
441
462
  inProcess: () => localStore((deps) => __awaiter(this, void 0, void 0, function* () {
442
- const searcher = new searcher_1.Searcher(deps.vectorDb);
443
- return searcher.search(args.query, args.limit, { rerank: args.rerank, seeds: args.seeds }, args.filters, args.pathPrefix);
463
+ const pool = secondary()
464
+ ? new pool_1.WorkerPool((0, embedding_generation_1.resolveEmbeddingGeneration)(storeConfig()), storeConfig().embedMode)
465
+ : undefined;
466
+ try {
467
+ const searcher = new searcher_1.Searcher(deps.vectorDb, pool);
468
+ return yield searcher.search(args.query, args.limit, { rerank: args.rerank, seeds: args.seeds }, args.filters, args.pathPrefix);
469
+ }
470
+ finally {
471
+ yield pool === null || pool === void 0 ? void 0 : pool.destroy();
472
+ }
444
473
  })),
445
474
  daemonErrorMessage: (resp) => [resp.error, resp.hint]
446
475
  .filter((value) => typeof value === "string" && value)
@@ -508,7 +537,7 @@ exports.mcp = new commander_1.Command("mcp")
508
537
  * order. Batched so a per-symbol loop costs one round trip, not hundreds.
509
538
  */
510
539
  function locateRows(root, req) {
511
- return (0, rows_handler_1.readRows)(Object.assign({ name: "locate", projectRoot: root, lancedbDir: paths.lancedbDir, scope: projectScope(root), fallback: MCP_STORE_FALLBACK }, req));
540
+ return (0, rows_handler_1.readRows)(Object.assign({ name: "locate", projectRoot: root, lancedbDir: storeDir(), vectorDim: storeConfig().vectorDim, scope: projectScope(root), fallback: Object.assign(Object.assign({}, MCP_STORE_FALLBACK), { skipDaemon: secondary() }) }, req));
512
541
  }
513
542
  /**
514
543
  * Chunk and file totals for `index_status`, summed per registered project.
@@ -573,8 +602,8 @@ exports.mcp = new commander_1.Command("mcp")
573
602
  return __awaiter(this, void 0, void 0, function* () {
574
603
  if (_indexReady)
575
604
  return;
576
- const projects = (0, project_registry_1.listProjects)();
577
- const isRegistered = projects.some((p) => p.root === projectRoot);
605
+ const projects = storeProjects();
606
+ const isRegistered = projects.some((p) => p.root === currentRoot());
578
607
  if (isRegistered) {
579
608
  _indexReady = true;
580
609
  }
@@ -592,8 +621,10 @@ exports.mcp = new commander_1.Command("mcp")
592
621
  return __awaiter(this, void 0, void 0, function* () {
593
622
  var _a;
594
623
  try {
595
- const watchRoot = root !== null && root !== void 0 ? root : (_a = resolveMcpProject(undefined, projectRoot)) === null || _a === void 0 ? void 0 : _a.root;
596
- if (!watchRoot)
624
+ const watchRoot = root !== null && root !== void 0 ? root : (_a = resolveMcpProject(undefined, currentRoot(), storeProjects())) === null || _a === void 0 ? void 0 : _a.root;
625
+ if (!watchRoot ||
626
+ secondary() ||
627
+ (0, stores_1.matchStore)(watchRoot).kind !== "primary")
597
628
  return;
598
629
  const result = yield (0, watcher_launcher_1.launchWatcher)(watchRoot, WATCH_LEASE);
599
630
  if (result.ok && !result.reused) {
@@ -613,10 +644,10 @@ exports.mcp = new commander_1.Command("mcp")
613
644
  // covers the cwd, and scope to it instead of silently widening to the whole
614
645
  // index. `root` is the registered project root to scope to.
615
646
  function resolveRegisteredProject(requested) {
616
- const project = resolveMcpProject(requested, projectRoot);
647
+ const project = resolveMcpProject(requested, currentRoot(), storeProjects());
617
648
  if (project)
618
649
  return { proj: project, root: project.root };
619
- return { proj: undefined, root: projectRoot };
650
+ return { proj: undefined, root: currentRoot() };
620
651
  }
621
652
  // --- Tool handlers ---
622
653
  function handleSemanticSearch(args_1) {
@@ -647,7 +678,7 @@ exports.mcp = new commander_1.Command("mcp")
647
678
  if (typeof args.root === "string") {
648
679
  return err("Project not added to gmax yet. Run `gmax add` to index it first.");
649
680
  }
650
- const indexed = (0, project_registry_1.listProjects)().filter((p) => { var _a; return p.status !== "pending" && ((_a = p.chunkCount) !== null && _a !== void 0 ? _a : 0) > 0; });
681
+ const indexed = storeProjects().filter((p) => { var _a; return p.status !== "pending" && ((_a = p.chunkCount) !== null && _a !== void 0 ? _a : 0) > 0; });
651
682
  if (indexed.length === 0) {
652
683
  return err("No indexed projects yet. cd into a repo and run `gmax add` to index it first.");
653
684
  }
@@ -691,7 +722,7 @@ exports.mcp = new commander_1.Command("mcp")
691
722
  excludeProjects: typeof args.exclude_projects === "string"
692
723
  ? args.exclude_projects
693
724
  : undefined,
694
- });
725
+ }, storeProjects());
695
726
  if (crossScope.projectRoots.length === 0) {
696
727
  return err("No matching indexed projects.");
697
728
  }
@@ -708,7 +739,7 @@ exports.mcp = new commander_1.Command("mcp")
708
739
  const selectedRoots = searchAll
709
740
  ? new Set((_a = filters.projectRoots) !== null && _a !== void 0 ? _a : [])
710
741
  : new Set([resolvedRoot]);
711
- (0, embedding_status_1.assertEmbeddingSearchCompatible)((0, project_registry_1.listProjects)().filter((project) => selectedRoots.has(project.root)), (0, index_config_1.readGlobalConfig)());
742
+ (0, embedding_status_1.assertEmbeddingSearchCompatible)(storeProjects().filter((project) => selectedRoots.has(project.root)), storeConfig());
712
743
  // Aider-style seeding: the agent passes its open files / discussed
713
744
  // symbols; the searcher biases candidate generation toward them.
714
745
  const parseSeedList = (v) => {
@@ -1710,26 +1741,38 @@ exports.mcp = new commander_1.Command("mcp")
1710
1741
  });
1711
1742
  }
1712
1743
  function handleListProjects() {
1713
- return __awaiter(this, void 0, void 0, function* () {
1744
+ return __awaiter(this, arguments, void 0, function* (args = {}) {
1714
1745
  var _a;
1715
1746
  try {
1716
- const projects = (0, project_registry_1.listProjects)();
1717
- if (projects.length === 0) {
1747
+ const inventory = args.root === undefined ? (0, store_context_1.storeInventory)() : [];
1748
+ const projects = [
1749
+ ...storeProjects(),
1750
+ ...inventory
1751
+ .filter((store) => { var _a; var _b; return store.home !==
1752
+ ((_b = (_a = (0, store_context_1.currentStoreContext)()) === null || _a === void 0 ? void 0 : _a.home) !== null && _b !== void 0 ? _b : config_1.PATHS.globalRoot); })
1753
+ .flatMap((store) => store.projects),
1754
+ ];
1755
+ if (projects.length === 0 && inventory.length === 0) {
1718
1756
  return ok("No projects indexed yet. cd into a repo and run `gmax add` to index it.");
1719
1757
  }
1720
- const currentName = (_a = resolveMcpProject(undefined, projectRoot)) === null || _a === void 0 ? void 0 : _a.name;
1721
- const globalConfig = (0, index_config_1.readGlobalConfig)();
1758
+ const currentName = (_a = resolveMcpProject(undefined, currentRoot(), storeProjects())) === null || _a === void 0 ? void 0 : _a.name;
1759
+ const globalConfig = storeConfig();
1722
1760
  const lines = projects.map((p) => {
1723
1761
  const here = p.name === currentName ? " (current)" : "";
1724
1762
  const chunks = typeof p.chunkCount === "number"
1725
1763
  ? `\t(${p.chunkCount} chunks)`
1726
1764
  : "";
1727
- const identity = (0, embedding_status_1.projectEmbeddingStatus)(p, globalConfig);
1765
+ const matching = inventory.find((store) => store.projects.some((project) => project.root === p.root));
1766
+ const identity = (0, embedding_status_1.projectEmbeddingStatus)(p, matching ? (0, index_config_1.readGlobalConfig)(matching.home) : globalConfig);
1728
1767
  return `${p.name}${here}\t${p.root}\t${p.status}\tembedding=${identity.state}${chunks}`;
1729
1768
  });
1730
1769
  return ok(`${projects.length} indexed project(s). ` +
1731
1770
  `Pass a name to semantic_search via projects:"name", or use scope:"all".\n\n` +
1732
- lines.join("\n"));
1771
+ lines.join("\n") +
1772
+ inventory
1773
+ .filter((store) => store.state !== "mounted")
1774
+ .map((store) => `\nStore ${store.home}: ${store.state}${store.error ? ` — ${store.error}` : ""}`)
1775
+ .join(""));
1733
1776
  }
1734
1777
  catch (e) {
1735
1778
  const msg = e instanceof Error ? e.message : String(e);
@@ -1741,18 +1784,20 @@ exports.mcp = new commander_1.Command("mcp")
1741
1784
  return __awaiter(this, void 0, void 0, function* () {
1742
1785
  var _a, _b;
1743
1786
  try {
1744
- const globalConfig = (0, index_config_1.readGlobalConfig)();
1745
- const projects = (0, project_registry_1.listProjects)();
1746
- const currentProject = resolveMcpProject(undefined, projectRoot);
1787
+ const globalConfig = storeConfig();
1788
+ const projects = storeProjects();
1789
+ const currentProject = resolveMcpProject(undefined, currentRoot(), storeProjects());
1747
1790
  const identity = (0, embedding_status_1.projectEmbeddingStatus)(currentProject, globalConfig);
1748
1791
  const { chunks, files } = yield indexTotals(projects);
1749
- const daemonStatus = yield (0, daemon_client_1.sendDaemonCommand)({ cmd: "status" });
1792
+ const daemonStatus = secondary()
1793
+ ? { ok: true, projects: [] }
1794
+ : yield (0, daemon_client_1.sendDaemonCommand)({ cmd: "status" });
1750
1795
  const watched = (Array.isArray(daemonStatus.projects) ? daemonStatus.projects : []);
1751
1796
  const daemonProject = watched.find((p) => p.root === (currentProject === null || currentProject === void 0 ? void 0 : currentProject.root));
1752
1797
  // Only use the registry when no daemon answered; sandboxed reads stay IPC-only.
1753
1798
  const watcher = daemonStatus.ok
1754
1799
  ? undefined
1755
- : (0, watcher_store_1.getWatcherCoveringPath)(projectRoot);
1800
+ : (0, watcher_store_1.getWatcherCoveringPath)(currentRoot());
1756
1801
  let watcherLine = "Watcher: not running";
1757
1802
  if (watcher) {
1758
1803
  const status = (_a = watcher.status) !== null && _a !== void 0 ? _a : "unknown";
@@ -1777,7 +1822,7 @@ exports.mcp = new commander_1.Command("mcp")
1777
1822
  // per-project chunk counts) lives in `list_projects` — keep this tool
1778
1823
  // focused on index health and avoid the N-project LanceDB scans.
1779
1824
  const lines = [
1780
- `Index: ~/.gmax/lancedb (${chunks} chunks, ${files} files)`,
1825
+ `Index: ${storeDir()} (${chunks} chunks, ${files} files)`,
1781
1826
  `Configured embedding: ${identity.configured.tier} ${identity.configured.vectorDim}d [${(0, embedding_status_1.embeddingFingerprintLabel)(identity.configured.fingerprint)}] (${globalConfig.embedMode})`,
1782
1827
  identity.built
1783
1828
  ? `Built embedding: ${identity.built.tier} ${identity.built.vectorDim}d [${(0, embedding_status_1.embeddingFingerprintLabel)(identity.built.fingerprint)}] (${identity.state})`
@@ -1786,6 +1831,7 @@ exports.mcp = new commander_1.Command("mcp")
1786
1831
  ? `Last indexed: ${currentProject.lastIndexed}`
1787
1832
  : "",
1788
1833
  watcherLine,
1834
+ (0, compaction_result_1.formatCompactionStatus)(daemonStatus.compaction),
1789
1835
  `Projects: ${projects.length} indexed (call list_projects for names + per-project chunk counts)`,
1790
1836
  ].filter(Boolean);
1791
1837
  return ok(lines.join("\n"));
@@ -1999,6 +2045,8 @@ exports.mcp = new commander_1.Command("mcp")
1999
2045
  function handleRecentChanges(args) {
2000
2046
  return __awaiter(this, void 0, void 0, function* () {
2001
2047
  var _a, e_1, _b, _c;
2048
+ var _d;
2049
+ var _e;
2002
2050
  ensureWatcher();
2003
2051
  const limit = Math.min(Math.max(Number(args.limit) || 20, 1), 50);
2004
2052
  const { proj, root } = resolveRegisteredProject(args.root);
@@ -2006,13 +2054,13 @@ exports.mcp = new commander_1.Command("mcp")
2006
2054
  return err("Project not added to gmax yet.");
2007
2055
  const prefix = root.endsWith("/") ? root : `${root}/`;
2008
2056
  try {
2009
- const metaCache = new meta_cache_1.MetaCache(config_1.PATHS.lmdbPath);
2057
+ const metaCache = new meta_cache_1.MetaCache((_e = (_d = (0, store_context_1.currentStoreContext)()) === null || _d === void 0 ? void 0 : _d.lmdbPath) !== null && _e !== void 0 ? _e : config_1.PATHS.lmdbPath);
2010
2058
  try {
2011
2059
  const files = [];
2012
2060
  try {
2013
- for (var _d = true, _e = __asyncValues(metaCache.entries()), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
2014
- _c = _f.value;
2015
- _d = false;
2061
+ for (var _f = true, _g = __asyncValues(metaCache.entries()), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
2062
+ _c = _h.value;
2063
+ _f = false;
2016
2064
  const { path: p, entry } = _c;
2017
2065
  if (p.startsWith(prefix)) {
2018
2066
  files.push({ path: p, mtimeMs: entry.mtimeMs });
@@ -2022,7 +2070,7 @@ exports.mcp = new commander_1.Command("mcp")
2022
2070
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
2023
2071
  finally {
2024
2072
  try {
2025
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
2073
+ if (!_f && !_a && (_b = _g.return)) yield _b.call(_g);
2026
2074
  }
2027
2075
  finally { if (e_1) throw e_1.error; }
2028
2076
  }
@@ -2067,7 +2115,7 @@ exports.mcp = new commander_1.Command("mcp")
2067
2115
  const { proj, root } = resolveRegisteredProject();
2068
2116
  if (!proj)
2069
2117
  return err("Project not added to gmax yet.");
2070
- (0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], (0, index_config_1.readGlobalConfig)());
2118
+ (0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], storeConfig());
2071
2119
  const changedFiles = getChangedFiles(ref, root);
2072
2120
  if (changedFiles.length === 0) {
2073
2121
  return ok(ref
@@ -2267,7 +2315,7 @@ exports.mcp = new commander_1.Command("mcp")
2267
2315
  const { proj, root } = resolveRegisteredProject();
2268
2316
  if (!proj)
2269
2317
  return err("Project not added to gmax yet.");
2270
- (0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], (0, index_config_1.readGlobalConfig)());
2318
+ (0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], storeConfig());
2271
2319
  const isFile = target.includes("/") ||
2272
2320
  (target.includes(".") && !target.includes(" "));
2273
2321
  // Resolved here: containment is this process's filesystem question.
@@ -2333,7 +2381,7 @@ exports.mcp = new commander_1.Command("mcp")
2333
2381
  const { proj, root } = resolveRegisteredProject();
2334
2382
  if (!proj)
2335
2383
  return err("Project not added to gmax yet.");
2336
- (0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], (0, index_config_1.readGlobalConfig)());
2384
+ (0, embedding_status_1.assertEmbeddingSearchCompatible)([proj], storeConfig());
2337
2385
  const searchOptions = { rerank: process.env.GMAX_RERANK === "1" };
2338
2386
  const response = yield searchStore(Object.assign({ projectRoot: root, query: topic, limit, filters: {}, pathPrefix: root }, searchOptions));
2339
2387
  if (response.data.length === 0)
@@ -2403,7 +2451,11 @@ exports.mcp = new commander_1.Command("mcp")
2403
2451
  return err("LLM server not available. Run `gmax llm on && gmax llm start`.");
2404
2452
  }
2405
2453
  const { investigate } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/investigate")));
2406
- const inv = yield investigate({ question, projectRoot, maxRounds });
2454
+ const inv = yield investigate({
2455
+ question,
2456
+ projectRoot: currentRoot(),
2457
+ maxRounds,
2458
+ });
2407
2459
  return ok(inv.answer);
2408
2460
  }
2409
2461
  catch (e) {
@@ -2427,12 +2479,15 @@ exports.mcp = new commander_1.Command("mcp")
2427
2479
  return err("LLM server not available. Run `gmax llm on && gmax llm start`.");
2428
2480
  }
2429
2481
  const { reviewCommit } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/review")));
2430
- const rev = yield reviewCommit({ commitRef, projectRoot });
2482
+ const rev = yield reviewCommit({
2483
+ commitRef,
2484
+ projectRoot: currentRoot(),
2485
+ });
2431
2486
  if (rev.clean) {
2432
2487
  return ok(`Clean commit (${rev.commit}) — no issues found in ${rev.duration}s.`);
2433
2488
  }
2434
2489
  const { readReport } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
2435
- const report = readReport(projectRoot);
2490
+ const report = readReport(currentRoot());
2436
2491
  const entry = report === null || report === void 0 ? void 0 : report.reviews.find((r) => r.commit === rev.commit);
2437
2492
  return ok(JSON.stringify({
2438
2493
  commit: rev.commit,
@@ -2457,26 +2512,26 @@ exports.mcp = new commander_1.Command("mcp")
2457
2512
  // returns the location.
2458
2513
  const { extractDiff, extractSymbols, fileChurn } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/diff")));
2459
2514
  const { computeRiskTable, formatRiskTable } = yield Promise.resolve().then(() => __importStar(require("../lib/review/risk")));
2460
- const diff = extractDiff(commitRef, projectRoot);
2515
+ const diff = extractDiff(commitRef, currentRoot());
2461
2516
  const symbols = diff ? extractSymbols(diff) : [];
2462
2517
  if (symbols.length === 0) {
2463
2518
  return ok("(no changed symbols in this diff)");
2464
2519
  }
2465
- const scope = projectScope(projectRoot);
2520
+ const scope = projectScope(currentRoot());
2466
2521
  const facts = yield graphVerb("graph.risk", {
2467
- projectRoot,
2522
+ projectRoot: currentRoot(),
2468
2523
  scope,
2469
2524
  payload: { symbols },
2470
2525
  render: (resp) => { var _a; return (_a = resp.facts) !== null && _a !== void 0 ? _a : []; },
2471
2526
  inProcess: () => localStore((deps) => (0, graph_handler_1.runGraphRisk)(deps.vectorDb, {
2472
2527
  symbols,
2473
- queryRoot: projectRoot,
2528
+ queryRoot: currentRoot(),
2474
2529
  scope,
2475
2530
  })),
2476
2531
  });
2477
- const prefix = projectRoot.endsWith("/")
2478
- ? projectRoot
2479
- : `${projectRoot}/`;
2532
+ const prefix = currentRoot().endsWith("/")
2533
+ ? currentRoot()
2534
+ : `${currentRoot()}/`;
2480
2535
  const rows = computeRiskTable(facts.map((fact) => ({
2481
2536
  symbol: fact.symbol,
2482
2537
  file: fact.file
@@ -2487,7 +2542,7 @@ exports.mcp = new commander_1.Command("mcp")
2487
2542
  line: fact.line,
2488
2543
  callerCount: fact.callerCount,
2489
2544
  hasTests: fact.hasTests,
2490
- churn: fileChurn(fact.file, projectRoot),
2545
+ churn: fileChurn(fact.file, currentRoot()),
2491
2546
  })));
2492
2547
  return rows.length === 0
2493
2548
  ? ok("(no changed symbols in this diff)")
@@ -2502,7 +2557,7 @@ exports.mcp = new commander_1.Command("mcp")
2502
2557
  return __awaiter(this, void 0, void 0, function* () {
2503
2558
  try {
2504
2559
  const { readReport, formatReportText } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
2505
- const report = readReport(projectRoot);
2560
+ const report = readReport(currentRoot());
2506
2561
  if (!report || report.reviews.length === 0) {
2507
2562
  return ok("No review findings yet.");
2508
2563
  }
@@ -2517,6 +2572,7 @@ exports.mcp = new commander_1.Command("mcp")
2517
2572
  });
2518
2573
  }
2519
2574
  // --- MCP server setup ---
2575
+ // Local-only MCP: client-owned pipes, no HTTP/SSE/TCP listener or host option.
2520
2576
  const transport = new stdio_js_1.StdioServerTransport();
2521
2577
  const server = new mcp_js_1.McpServer({
2522
2578
  name: "gmax",
@@ -2552,7 +2608,7 @@ exports.mcp = new commander_1.Command("mcp")
2552
2608
  source: "mcp",
2553
2609
  tool: name,
2554
2610
  query: mcpLogQuery(name, toolArgs),
2555
- project: projectRoot,
2611
+ project: currentRoot(),
2556
2612
  results: resultLines,
2557
2613
  ms: Date.now() - startMs,
2558
2614
  error: result.isError ? text.slice(0, 200) : undefined,
@@ -2564,21 +2620,42 @@ exports.mcp = new commander_1.Command("mcp")
2564
2620
  // shapes give us free input validation (the SDK rejects calls that violate
2565
2621
  // the schema before the handler runs); handlers stay defensively coded.
2566
2622
  function tool(name, config, handler) {
2567
- server.registerTool(name, config, (rawArgs) => __awaiter(this, void 0, void 0, function* () {
2623
+ server.registerTool(name, Object.assign(Object.assign({}, config), { inputSchema: Object.assign({ root: zod_1.z.string().optional() }, config.inputSchema) }), (rawArgs) => __awaiter(this, void 0, void 0, function* () {
2568
2624
  let args = (rawArgs !== null && rawArgs !== void 0 ? rawArgs : {});
2569
2625
  const startMs = Date.now();
2570
- if (typeof args.root === "string" && args.root.trim()) {
2571
- const selected = resolveMcpProject(args.root, projectRoot);
2572
- if (!selected) {
2573
- const result = err(`Unknown registered project: ${args.root}. Use list_projects to select a project name or exact root.`);
2626
+ let target = projectRoot;
2627
+ try {
2628
+ if (typeof args.root === "string" && args.root.trim()) {
2629
+ const raw = args.root.trim();
2630
+ if (path.isAbsolute(raw) || raw.includes(path.sep))
2631
+ target = path.resolve(raw);
2632
+ else {
2633
+ const projects = [
2634
+ ...(0, project_registry_1.listProjects)(),
2635
+ ...(0, store_context_1.storeInventory)().flatMap((store) => store.projects),
2636
+ ].filter((project, i, all) => all.findIndex((p) => p.root === project.root) === i);
2637
+ const selected = resolveMcpProject(raw, projectRoot, projects);
2638
+ if (!selected)
2639
+ return err(`Unknown or ambiguous registered project: ${raw}. Use list_projects or an exact root.`);
2640
+ target = selected.root;
2641
+ }
2642
+ }
2643
+ return yield (0, store_context_1.withStoreContext)(target, () => __awaiter(this, void 0, void 0, function* () {
2644
+ if (args.root !== undefined) {
2645
+ const selected = resolveMcpProject(args.root, currentRoot(), storeProjects());
2646
+ if (!selected)
2647
+ return err(`Unknown registered project: ${args.root}. Use list_projects to select a project name or exact root.`);
2648
+ args = Object.assign(Object.assign({}, args), { root: selected.root });
2649
+ (0, store_context_1.currentStoreContext)().root = selected.root;
2650
+ }
2651
+ const result = yield handler(args);
2574
2652
  yield logToolCall(name, args, startMs, result);
2575
2653
  return result;
2576
- }
2577
- args = Object.assign(Object.assign({}, args), { root: selected.root });
2654
+ }));
2655
+ }
2656
+ catch (error) {
2657
+ return toolError("Tool failed", error);
2578
2658
  }
2579
- const result = yield handler(args);
2580
- yield logToolCall(name, args, startMs, result);
2581
- return result;
2582
2659
  }));
2583
2660
  }
2584
2661
  tool("semantic_search", {
@@ -71,7 +71,6 @@ exports.project = new commander_1.Command("project")
71
71
  daemon: () => (0, daemon_client_1.sendDaemonCommand)({ cmd: "rows.project", projectRoot: root }, { timeoutMs: 120000 }),
72
72
  render: (resp) => resp.overview,
73
73
  inProcess: () => (0, rows_handler_1.withLocalStore)(paths.lancedbDir, (deps) => (0, rows_handler_1.runProject)(deps, root)),
74
- fallbackOnUnknownVerb: true,
75
74
  });
76
75
  if (overview.chunks === 0) {
77
76
  console.log(`No indexed data found for ${root}. Run: gmax index --path ${root}`);
@@ -112,7 +112,6 @@ exports.similar = new commander_1.Command("similar")
112
112
  limit,
113
113
  threshold,
114
114
  })),
115
- fallbackOnUnknownVerb: true,
116
115
  });
117
116
  if (result.status === "not-found") {
118
117
  console.log((isFile
@@ -158,7 +158,6 @@ function lookupSkeleton(projectRoot, lancedbDir, req) {
158
158
  skeleton: ((_b = resp.skeleton) !== null && _b !== void 0 ? _b : null),
159
159
  }); },
160
160
  inProcess: () => (0, rows_handler_1.withLocalStore)(lancedbDir, (deps) => (0, rows_handler_1.runSkeleton)(deps, Object.assign({ projectRoot }, req))),
161
- fallbackOnUnknownVerb: true,
162
161
  });
163
162
  });
164
163
  }