grepmax 0.26.27 → 0.26.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -12,11 +45,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
45
  exports.surprises = void 0;
13
46
  const commander_1 = require("commander");
14
47
  const surprising_connections_1 = require("../lib/analysis/surprising-connections");
15
- const vector_db_1 = require("../lib/store/vector-db");
48
+ const rows_handler_1 = require("../lib/daemon/rows-handler");
49
+ const vector_handler_1 = require("../lib/daemon/vector-handler");
50
+ const daemon_client_1 = require("../lib/utils/daemon-client");
16
51
  const exit_1 = require("../lib/utils/exit");
17
52
  const project_registry_1 = require("../lib/utils/project-registry");
18
53
  const project_root_1 = require("../lib/utils/project-root");
19
54
  const stale_hint_1 = require("../lib/utils/stale-hint");
55
+ const store_access_1 = require("../lib/utils/store-access");
20
56
  const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
21
57
  const style = {
22
58
  bold: (s) => (useColors ? `\x1b[1m${s}\x1b[22m` : s),
@@ -108,7 +144,6 @@ exports.surprises = new commander_1.Command("surprises")
108
144
  process.exitCode = 1;
109
145
  return;
110
146
  }
111
- let vectorDb = null;
112
147
  try {
113
148
  const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
114
149
  if (root === null)
@@ -117,10 +152,27 @@ exports.surprises = new commander_1.Command("surprises")
117
152
  (0, stale_hint_1.maybeWarnStaleChunker)(projectRoot, { agent: opts.agent });
118
153
  (0, stale_hint_1.maybeWarnStaleEmbedding)(projectRoot, { agent: opts.agent });
119
154
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
120
- vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
121
- const table = yield vectorDb.ensureTable();
122
155
  const top = parseIntOption(opts.top, 20, 100);
123
- const result = yield (0, surprising_connections_1.analyzeSurprisingConnections)(table, projectRoot, {
156
+ // --in/--exclude resolve against this process's cwd and filesystem, so
157
+ // they are resolved here and shipped as absolute prefixes.
158
+ // analyzeSurprisingConnections re-resolves them daemon-side; absolute
159
+ // input makes that a no-op, so both paths scan under the same scope.
160
+ const { resolveScope } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
161
+ const scope = resolveScope({
162
+ projectRoot,
163
+ in: opts.in,
164
+ exclude: opts.exclude,
165
+ });
166
+ const projectPrefix = projectRoot.endsWith("/")
167
+ ? projectRoot
168
+ : `${projectRoot}/`;
169
+ const analysisIn = scope.inPrefixes.length > 0
170
+ ? scope.inPrefixes
171
+ : scope.pathPrefix !== projectPrefix
172
+ ? [scope.pathPrefix]
173
+ : undefined;
174
+ const analysisExclude = scope.excludePrefixes.length > 0 ? scope.excludePrefixes : undefined;
175
+ const options = {
124
176
  sample: parseIntOption(opts.sample, surprising_connections_1.DEFAULT_SURPRISE_OPTIONS.sample),
125
177
  neighbors: parseIntOption(opts.neighbors, surprising_connections_1.DEFAULT_SURPRISE_OPTIONS.neighbors, 200),
126
178
  dirDepth: parseIntOption(opts.dirDepth, surprising_connections_1.DEFAULT_SURPRISE_OPTIONS.dirDepth, 20),
@@ -128,23 +180,28 @@ exports.surprises = new commander_1.Command("surprises")
128
180
  maxRows: parseIntOption(opts.maxRows, surprising_connections_1.DEFAULT_SURPRISE_OPTIONS.maxRows, surprising_connections_1.MAX_SURPRISE_ROWS),
129
181
  includeTests: Boolean(opts.includeTests),
130
182
  includeEval: Boolean(opts.includeEval),
131
- in: opts.in,
132
- exclude: opts.exclude,
183
+ in: analysisIn,
184
+ exclude: analysisExclude,
185
+ };
186
+ // The scan reads up to MAX_SURPRISE_ROWS rows with their vectors; the
187
+ // daemon runs it against its warm store and returns the summary plus the
188
+ // findings that will actually be printed.
189
+ const result = yield (0, store_access_1.withStoreRead)("surprises", {
190
+ daemon: () => (0, daemon_client_1.sendDaemonCommand)({ cmd: "vector.surprises", projectRoot, options, top }, { timeoutMs: 300000 }),
191
+ render: (resp) => resp,
192
+ inProcess: () => (0, rows_handler_1.withLocalStore)(paths.lancedbDir, (deps) => (0, vector_handler_1.runSurprises)(deps, { projectRoot, options, top })),
193
+ fallbackOnUnknownVerb: true,
133
194
  });
134
195
  console.log(opts.agent ? formatAgent(result, top) : formatHuman(result, top));
135
196
  }
136
197
  catch (error) {
137
- const msg = error instanceof Error ? error.message : "Unknown error";
138
- console.error("Surprises failed:", msg);
139
- process.exitCode = 1;
198
+ if (!(0, store_access_1.reportStoreAccessRefusal)(error)) {
199
+ const msg = error instanceof Error ? error.message : "Unknown error";
200
+ console.error("Surprises failed:", msg);
201
+ process.exitCode = 1;
202
+ }
140
203
  }
141
204
  finally {
142
- if (vectorDb) {
143
- try {
144
- yield vectorDb.close();
145
- }
146
- catch (_b) { }
147
- }
148
205
  yield (0, exit_1.gracefulExit)();
149
206
  }
150
207
  }));
@@ -45,81 +45,49 @@ Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.symbols = void 0;
46
46
  const path = __importStar(require("node:path"));
47
47
  const commander_1 = require("commander");
48
- const vector_db_1 = require("../lib/store/vector-db");
48
+ const rows_handler_1 = require("../lib/daemon/rows-handler");
49
+ const daemon_client_1 = require("../lib/utils/daemon-client");
49
50
  const exit_1 = require("../lib/utils/exit");
50
- const filter_builder_1 = require("../lib/utils/filter-builder");
51
51
  const project_registry_1 = require("../lib/utils/project-registry");
52
52
  const project_root_1 = require("../lib/utils/project-root");
53
+ const store_access_1 = require("../lib/utils/store-access");
53
54
  const style = {
54
55
  bold: (s) => `\x1b[1m${s}\x1b[22m`,
55
56
  dim: (s) => `\x1b[2m${s}\x1b[22m`,
56
57
  green: (s) => `\x1b[32m${s}\x1b[39m`,
57
58
  };
58
- function toStringArray(val) {
59
- if (Array.isArray(val))
60
- return val.filter((v) => typeof v === "string");
61
- if (val && typeof val.toArray === "function") {
62
- try {
63
- const arr = val.toArray();
64
- return Array.isArray(arr) ? arr.filter((v) => typeof v === "string") : [];
65
- }
66
- catch (_a) {
67
- return [];
68
- }
69
- }
70
- return [];
71
- }
59
+ /**
60
+ * Ask the daemon for the symbol table; open the store only when no daemon is
61
+ * listening. Both branches run the same `runSymbols`, so the two paths cannot
62
+ * disagree — only the process the query runs in changes.
63
+ */
72
64
  function collectSymbols(options) {
73
65
  return __awaiter(this, void 0, void 0, function* () {
74
66
  const paths = (0, project_root_1.ensureProjectPaths)(options.projectRoot);
75
- const db = new vector_db_1.VectorDB(paths.lancedbDir);
76
- try {
77
- const table = yield db.ensureTable();
78
- let query = table
79
- .query()
80
- .select(["defined_symbols", "path", "start_line"])
81
- .where("array_length(defined_symbols) > 0")
82
- // Fetch more rows to ensure we have enough after filtering/aggregation
83
- .limit(options.pattern ? 10000 : Math.max(options.limit * 50, 2000));
84
- if (options.pathPrefix) {
85
- // Resolve to absolute path for centralized index
86
- const absPrefix = path.isAbsolute(options.pathPrefix)
87
- ? options.pathPrefix
88
- : path.resolve(options.projectRoot, options.pathPrefix);
89
- query = query.where((0, filter_builder_1.pathStartsWith)((0, filter_builder_1.normalizePath)(absPrefix)));
90
- }
91
- const rows = yield query.toArray();
92
- const map = new Map();
93
- for (const row of rows) {
94
- const defs = toStringArray(row.defined_symbols);
95
- const path = String(row.path || "");
96
- const line = Number(row.start_line || 0);
97
- for (const sym of defs) {
98
- if (options.pattern &&
99
- !sym.toLowerCase().includes(options.pattern.toLowerCase())) {
100
- continue;
101
- }
102
- const existing = map.get(sym);
103
- if (existing) {
104
- existing.count += 1;
105
- }
106
- else {
107
- map.set(sym, { symbol: sym, count: 1, path, line });
108
- }
109
- }
110
- }
111
- return Array.from(map.values())
112
- .sort((a, b) => {
113
- // Sort by count desc, then symbol asc
114
- if (b.count !== a.count)
115
- return b.count - a.count;
116
- return a.symbol.localeCompare(b.symbol);
117
- })
118
- .slice(0, options.limit);
119
- }
120
- finally {
121
- yield db.close();
122
- }
67
+ // Resolve to absolute for the centralized index. No trailing slash: the
68
+ // query has always matched starts_with on the bare prefix.
69
+ const absPrefix = options.pathPrefix
70
+ ? path.isAbsolute(options.pathPrefix)
71
+ ? options.pathPrefix
72
+ : path.resolve(options.projectRoot, options.pathPrefix)
73
+ : undefined;
74
+ return (0, store_access_1.withStoreRead)("symbols", {
75
+ daemon: () => (0, daemon_client_1.sendDaemonCommand)({
76
+ cmd: "rows.symbols",
77
+ projectRoot: options.projectRoot,
78
+ pathPrefix: absPrefix,
79
+ pattern: options.pattern,
80
+ limit: options.limit,
81
+ }, { timeoutMs: 60000 }),
82
+ render: (resp) => { var _a; return ((_a = resp.entries) !== null && _a !== void 0 ? _a : []); },
83
+ inProcess: () => (0, rows_handler_1.withLocalStore)(paths.lancedbDir, (deps) => (0, rows_handler_1.runSymbols)(deps, {
84
+ projectRoot: options.projectRoot,
85
+ pathPrefix: absPrefix,
86
+ pattern: options.pattern,
87
+ limit: options.limit,
88
+ })),
89
+ fallbackOnUnknownVerb: true,
90
+ });
123
91
  });
124
92
  }
125
93
  function formatTable(entries) {
@@ -182,20 +150,33 @@ exports.symbols = new commander_1.Command("symbols")
182
150
  const limit = Number.parseInt(cmd.limit, 10);
183
151
  // Auto-scope to project root; --path narrows further within it
184
152
  const pathPrefix = (_b = cmd.path) !== null && _b !== void 0 ? _b : projectRoot;
185
- const entries = yield collectSymbols({
186
- projectRoot,
187
- limit: Number.isFinite(limit) && limit > 0 ? limit : 20,
188
- pathPrefix,
189
- pattern: pattern,
190
- });
191
- if (cmd.agent) {
192
- console.log(formatAgent(entries, projectRoot));
153
+ try {
154
+ const entries = yield collectSymbols({
155
+ projectRoot,
156
+ limit: Number.isFinite(limit) && limit > 0 ? limit : 20,
157
+ pathPrefix,
158
+ pattern: pattern,
159
+ });
160
+ if (cmd.agent) {
161
+ console.log(formatAgent(entries, projectRoot));
162
+ }
163
+ else {
164
+ console.log(`${style.bold("Project")}: ${style.green(projectRoot)}\n${formatTable(entries)}`);
165
+ }
166
+ if (entries.length === 0) {
167
+ process.exitCode = 1;
168
+ }
193
169
  }
194
- else {
195
- console.log(`${style.bold("Project")}: ${style.green(projectRoot)}\n${formatTable(entries)}`);
170
+ catch (error) {
171
+ // `symbols` was the one read command with no catch at all, so a denied
172
+ // lease escaped as a raw node:fs stack trace instead of the one-line hint.
173
+ if (!(0, store_access_1.reportStoreAccessRefusal)(error)) {
174
+ const msg = error instanceof Error ? error.message : "Unknown error";
175
+ console.error("Symbols failed:", msg);
176
+ process.exitCode = 1;
177
+ }
196
178
  }
197
- if (entries.length === 0) {
198
- process.exitCode = 1;
179
+ finally {
180
+ yield (0, exit_1.gracefulExit)();
199
181
  }
200
- yield (0, exit_1.gracefulExit)();
201
182
  }));
@@ -44,13 +44,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.testFind = void 0;
46
46
  const commander_1 = require("commander");
47
- const impact_1 = require("../lib/graph/impact");
47
+ const graph_handler_1 = require("../lib/daemon/graph-handler");
48
48
  const test_hits_1 = require("../lib/graph/test-hits");
49
49
  const vector_db_1 = require("../lib/store/vector-db");
50
50
  const exit_1 = require("../lib/utils/exit");
51
51
  const project_registry_1 = require("../lib/utils/project-registry");
52
52
  const project_root_1 = require("../lib/utils/project-root");
53
53
  const stale_hint_1 = require("../lib/utils/stale-hint");
54
+ const store_access_1 = require("../lib/utils/store-access");
54
55
  exports.testFind = new commander_1.Command("test")
55
56
  .description("Find tests that exercise a symbol or file")
56
57
  .argument("<target>", "Symbol name or file path")
@@ -62,7 +63,8 @@ exports.testFind = new commander_1.Command("test")
62
63
  .action((target, opts) => __awaiter(void 0, void 0, void 0, function* () {
63
64
  var _a;
64
65
  const depth = Math.min(Math.max(Number.parseInt(opts.depth || "1", 10), 1), 3);
65
- let vectorDb = null;
66
+ // Opened only if the daemon is unreachable; withStoreRead decides.
67
+ const local = { db: null };
66
68
  try {
67
69
  const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
68
70
  if (root === null)
@@ -70,9 +72,31 @@ exports.testFind = new commander_1.Command("test")
70
72
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
71
73
  (0, stale_hint_1.maybeWarnStaleChunker)(projectRoot, { agent: opts.agent });
72
74
  (0, stale_hint_1.maybeWarnStaleEmbedding)(projectRoot, { agent: opts.agent });
73
- const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
74
- vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
75
- const { symbols, resolvedAsFile, symbolFamilies } = yield (0, impact_1.resolveTargetSymbols)(target, vectorDb, projectRoot);
75
+ const localDb = () => {
76
+ var _a;
77
+ (_a = local.db) !== null && _a !== void 0 ? _a : (local.db = new vector_db_1.VectorDB((0, project_root_1.ensureProjectPaths)(projectRoot).lancedbDir));
78
+ return local.db;
79
+ };
80
+ const { resolveScope } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
81
+ const scope = resolveScope({
82
+ projectRoot,
83
+ in: opts.in,
84
+ exclude: opts.exclude,
85
+ });
86
+ const { symbols, resolvedAsFile, symbolFamilies } = yield (0, graph_handler_1.callGraphVerb)("graph.resolve", {
87
+ projectRoot,
88
+ scope,
89
+ payload: { target },
90
+ render: (resp) => {
91
+ var _a, _b;
92
+ return ({
93
+ symbols: (_a = resp.symbols) !== null && _a !== void 0 ? _a : [],
94
+ resolvedAsFile: resp.resolvedAsFile === true,
95
+ symbolFamilies: (_b = resp.symbolFamilies) !== null && _b !== void 0 ? _b : null,
96
+ });
97
+ },
98
+ inProcess: () => (0, graph_handler_1.runGraphResolve)(localDb(), { target, projectRoot }),
99
+ });
76
100
  if (symbols.length === 0) {
77
101
  console.log(resolvedAsFile
78
102
  ? `No symbols found in file: ${target}`
@@ -80,16 +104,22 @@ exports.testFind = new commander_1.Command("test")
80
104
  process.exitCode = 1;
81
105
  return;
82
106
  }
83
- const { resolveScope } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
84
- const scope = resolveScope({
85
- projectRoot,
86
- in: opts.in,
87
- exclude: opts.exclude,
88
- });
89
107
  const queryRoot = opts.in && opts.in.length > 0
90
108
  ? scope.pathPrefix.replace(/\/$/, "")
91
109
  : projectRoot;
92
- const tests = yield (0, impact_1.findTests)(symbols, vectorDb, queryRoot, depth, scope.excludePrefixes, symbolFamilies);
110
+ const tests = yield (0, graph_handler_1.callGraphVerb)("graph.tests", {
111
+ projectRoot,
112
+ scope,
113
+ payload: { symbols, depth, families: symbolFamilies },
114
+ render: (resp) => { var _a; return (_a = resp.hits) !== null && _a !== void 0 ? _a : []; },
115
+ inProcess: () => (0, graph_handler_1.runGraphTests)(localDb(), {
116
+ symbols,
117
+ queryRoot,
118
+ depth,
119
+ excludePrefixes: scope.excludePrefixes,
120
+ families: (0, graph_handler_1.decodeSymbolFamilies)(symbolFamilies),
121
+ }),
122
+ });
93
123
  if (tests.length === 0) {
94
124
  console.log(`No tests found for ${target}.`);
95
125
  return;
@@ -111,14 +141,18 @@ exports.testFind = new commander_1.Command("test")
111
141
  }
112
142
  }
113
143
  catch (error) {
114
- const msg = error instanceof Error ? error.message : "Unknown error";
115
- console.error("Test find failed:", msg);
116
- process.exitCode = 1;
144
+ // A sandbox refusal is already one actionable line; a "Test find failed:"
145
+ // prefix would bury the settings key that fixes it.
146
+ if (!(0, store_access_1.reportStoreAccessRefusal)(error)) {
147
+ const msg = error instanceof Error ? error.message : "Unknown error";
148
+ console.error("Test find failed:", msg);
149
+ process.exitCode = 1;
150
+ }
117
151
  }
118
152
  finally {
119
- if (vectorDb) {
153
+ if (local.db) {
120
154
  try {
121
- yield vectorDb.close();
155
+ yield local.db.close();
122
156
  }
123
157
  catch (_b) { }
124
158
  }
@@ -44,8 +44,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.trace = void 0;
46
46
  const commander_1 = require("commander");
47
+ const graph_handler_1 = require("../lib/daemon/graph-handler");
47
48
  const callsites_1 = require("../lib/graph/callsites");
48
- const graph_builder_1 = require("../lib/graph/graph-builder");
49
49
  const formatter_1 = require("../lib/output/formatter");
50
50
  const vector_db_1 = require("../lib/store/vector-db");
51
51
  const agent_errors_1 = require("../lib/utils/agent-errors");
@@ -53,6 +53,7 @@ const exit_1 = require("../lib/utils/exit");
53
53
  const project_registry_1 = require("../lib/utils/project-registry");
54
54
  const project_root_1 = require("../lib/utils/project-root");
55
55
  const stale_hint_1 = require("../lib/utils/stale-hint");
56
+ const store_access_1 = require("../lib/utils/store-access");
56
57
  const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
57
58
  const dim = (s) => (useColors ? `\x1b[2m${s}\x1b[22m` : s);
58
59
  const bold = (s) => (useColors ? `\x1b[1m${s}\x1b[22m` : s);
@@ -231,21 +232,31 @@ exports.trace = new commander_1.Command("trace")
231
232
  const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
232
233
  if (root === null)
233
234
  return;
234
- let vectorDb = null;
235
+ // Opened only if the daemon is unreachable; withStoreRead decides.
236
+ const local = { db: null };
235
237
  try {
236
238
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
237
239
  (0, stale_hint_1.maybeWarnStaleChunker)(projectRoot, { agent: opts.agent });
238
240
  (0, stale_hint_1.maybeWarnStaleEmbedding)(projectRoot, { agent: opts.agent });
239
- const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
240
- vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
241
241
  const { resolveScope } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
242
242
  const scope = resolveScope({
243
243
  projectRoot,
244
244
  in: opts.in,
245
245
  exclude: opts.exclude,
246
246
  });
247
- const graphBuilder = new graph_builder_1.GraphBuilder(vectorDb, scope.pathPrefix, scope.excludePrefixes);
248
- const graph = yield graphBuilder.buildGraphMultiHop(symbol, depth);
247
+ // The daemon returns the graph; call-site snippets below are read from
248
+ // the working tree by this process, which can already see it.
249
+ const graph = yield (0, graph_handler_1.callGraphVerb)("graph.trace", {
250
+ projectRoot,
251
+ scope,
252
+ payload: { target: symbol, hops: depth },
253
+ render: (resp) => resp.graph,
254
+ inProcess: () => {
255
+ var _a;
256
+ (_a = local.db) !== null && _a !== void 0 ? _a : (local.db = new vector_db_1.VectorDB((0, project_root_1.ensureProjectPaths)(projectRoot).lancedbDir));
257
+ return (0, graph_handler_1.runGraphTrace)(local.db, { symbol, hops: depth, scope });
258
+ },
259
+ });
249
260
  if (opts.inbound) {
250
261
  if (!graph.center) {
251
262
  console.log((0, agent_errors_1.symbolNotFoundLines)(symbol, { agent: opts.agent }).join("\n"));
@@ -275,14 +286,18 @@ exports.trace = new commander_1.Command("trace")
275
286
  }
276
287
  }
277
288
  catch (error) {
278
- const message = error instanceof Error ? error.message : "Unknown error";
279
- console.error("Trace failed:", message);
280
- process.exitCode = 1;
289
+ // A sandbox refusal is already one actionable line; a "Trace failed:"
290
+ // prefix would bury the settings key that fixes it.
291
+ if (!(0, store_access_1.reportStoreAccessRefusal)(error)) {
292
+ const message = error instanceof Error ? error.message : "Unknown error";
293
+ console.error("Trace failed:", message);
294
+ process.exitCode = 1;
295
+ }
281
296
  }
282
297
  finally {
283
- if (vectorDb) {
298
+ if (local.db) {
284
299
  try {
285
- yield vectorDb.close();
300
+ yield local.db.close();
286
301
  }
287
302
  catch (err) {
288
303
  console.error("Failed to close VectorDB:", err);
@@ -76,7 +76,10 @@ const pool_1 = require("../workers/pool");
76
76
  const ipc_handler_1 = require("./ipc-handler");
77
77
  const mlx_server_manager_1 = require("./mlx-server-manager");
78
78
  const process_manager_1 = require("./process-manager");
79
+ const read_verbs_1 = require("./read-verbs");
80
+ const rows_handler_1 = require("./rows-handler");
79
81
  const search_handler_1 = require("./search-handler");
82
+ const vector_handler_1 = require("./vector-handler");
80
83
  const watcher_manager_1 = require("./watcher-manager");
81
84
  // 30 min was too aggressive — every shutdown is a chance for races, FSEvents
82
85
  // drops, and orphan MLX cleanup. 4 hours keeps the daemon resident through a
@@ -220,6 +223,15 @@ class Daemon {
220
223
  return __awaiter(this, void 0, void 0, function* () {
221
224
  var _a;
222
225
  process.title = "gmax-daemon";
226
+ // Read verbs register here rather than at read-verbs.ts module scope: the
227
+ // registry is asserted on exactly in tests/ipc-read-verbs.test.ts, and a
228
+ // module-scope registration would make it non-empty on import. Register
229
+ // before the socket server starts (step 2) so no client can race in and
230
+ // get "unknown command" for a verb this daemon does support. Idempotent:
231
+ // re-registering replaces by name.
232
+ (0, read_verbs_1.registerGraphVerbs)();
233
+ (0, rows_handler_1.registerRowsVerbs)();
234
+ (0, vector_handler_1.registerVectorVerbs)();
223
235
  // 0. Singleton enforcement: find and kill ALL stale daemon/worker processes
224
236
  yield this.processManager.killStaleProcesses();
225
237
  this.assertStartupActive();
@@ -724,6 +736,20 @@ class Daemon {
724
736
  }));
725
737
  });
726
738
  }
739
+ /**
740
+ * The slice of the daemon a read verb handler needs: the warm store and the
741
+ * activity touch that keeps the idle timer honest. One accessor for every
742
+ * read verb (graph, rows, vector) — extend this rather than adding a second;
743
+ * handlers get no other access to daemon internals.
744
+ */
745
+ storeReadDeps() {
746
+ return {
747
+ vectorDb: this.vectorDb,
748
+ touchActivity: () => {
749
+ this.lastActivity = Date.now();
750
+ },
751
+ };
752
+ }
727
753
  listProjects() {
728
754
  return [...this.processors.keys()].map((root) => ({
729
755
  root,