@phren/cli 0.0.27 → 0.0.32

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 (149) hide show
  1. package/mcp/dist/capabilities/cli.js +2 -5
  2. package/mcp/dist/capabilities/mcp.js +5 -8
  3. package/mcp/dist/capabilities/types.js +2 -5
  4. package/mcp/dist/capabilities/vscode.js +2 -5
  5. package/mcp/dist/capabilities/web-ui.js +2 -5
  6. package/mcp/dist/{cli-actions.js → cli/actions.js} +22 -21
  7. package/mcp/dist/{cli.js → cli/cli.js} +13 -13
  8. package/mcp/dist/{cli-config.js → cli/config.js} +9 -9
  9. package/mcp/dist/{cli-extract.js → cli/extract.js} +8 -8
  10. package/mcp/dist/{cli-govern.js → cli/govern.js} +10 -9
  11. package/mcp/dist/{cli-graph.js → cli/graph.js} +10 -9
  12. package/mcp/dist/{cli-hooks-citations.js → cli/hooks-citations.js} +2 -2
  13. package/mcp/dist/{cli-hooks-context.js → cli/hooks-context.js} +23 -23
  14. package/mcp/dist/{cli-hooks-globs.js → cli/hooks-globs.js} +4 -4
  15. package/mcp/dist/{cli-hooks-output.js → cli/hooks-output.js} +9 -10
  16. package/mcp/dist/{cli-hooks-session.js → cli/hooks-session.js} +42 -57
  17. package/mcp/dist/{cli-hooks.js → cli/hooks.js} +27 -26
  18. package/mcp/dist/{cli-namespaces.js → cli/namespaces.js} +25 -24
  19. package/mcp/dist/{cli-ops.js → cli/ops.js} +9 -9
  20. package/mcp/dist/{cli-search.js → cli/search.js} +8 -7
  21. package/mcp/dist/cli-hooks-git.js +243 -0
  22. package/mcp/dist/cli-hooks-prompt.js +319 -0
  23. package/mcp/dist/cli-hooks-session-handlers.js +349 -0
  24. package/mcp/dist/cli-hooks-stop.js +557 -0
  25. package/mcp/dist/{content-archive.js → content/archive.js} +8 -9
  26. package/mcp/dist/{content-citation.js → content/citation.js} +5 -5
  27. package/mcp/dist/{content-dedup.js → content/dedup.js} +9 -12
  28. package/mcp/dist/{content-learning.js → content/learning.js} +12 -12
  29. package/mcp/dist/{content-validate.js → content/validate.js} +5 -5
  30. package/mcp/dist/{core-finding.js → core/finding.js} +4 -4
  31. package/mcp/dist/{core-project.js → core/project.js} +4 -4
  32. package/mcp/dist/{core-search.js → core/search.js} +2 -2
  33. package/mcp/dist/{data-access.js → data/access.js} +131 -13
  34. package/mcp/dist/{data-tasks.js → data/tasks.js} +7 -5
  35. package/mcp/dist/embedding.js +9 -14
  36. package/mcp/dist/entrypoint.js +13 -11
  37. package/mcp/dist/{finding-context.js → finding/context.js} +2 -2
  38. package/mcp/dist/{finding-impact.js → finding/impact.js} +3 -3
  39. package/mcp/dist/{finding-journal.js → finding/journal.js} +4 -4
  40. package/mcp/dist/{finding-lifecycle.js → finding/lifecycle.js} +4 -4
  41. package/mcp/dist/{governance-audit.js → governance/audit.js} +2 -2
  42. package/mcp/dist/{governance-locks.js → governance/locks.js} +14 -9
  43. package/mcp/dist/{governance-policy.js → governance/policy.js} +10 -12
  44. package/mcp/dist/{governance-rbac.js → governance/rbac.js} +3 -3
  45. package/mcp/dist/{governance-scores.js → governance/scores.js} +8 -10
  46. package/mcp/dist/hooks.js +39 -31
  47. package/mcp/dist/index-query.js +4 -1
  48. package/mcp/dist/index.js +53 -29
  49. package/mcp/dist/{init-config.js → init/config.js} +6 -6
  50. package/mcp/dist/{init.js → init/init.js} +28 -29
  51. package/mcp/dist/{init-preferences.js → init/preferences.js} +3 -3
  52. package/mcp/dist/{init-setup.js → init/setup.js} +17 -19
  53. package/mcp/dist/{init-shared.js → init/shared.js} +3 -3
  54. package/mcp/dist/init-bootstrap.js +68 -0
  55. package/mcp/dist/init-detect.js +38 -0
  56. package/mcp/dist/init-dryrun.js +55 -0
  57. package/mcp/dist/init-env.js +114 -0
  58. package/mcp/dist/init-fresh.js +239 -0
  59. package/mcp/dist/init-hooks.js +26 -0
  60. package/mcp/dist/init-mcp.js +65 -0
  61. package/mcp/dist/init-migrate.js +51 -0
  62. package/mcp/dist/init-modes.js +135 -0
  63. package/mcp/dist/init-npm.js +37 -0
  64. package/mcp/dist/init-project-local.js +99 -0
  65. package/mcp/dist/init-semantic.js +48 -0
  66. package/mcp/dist/init-types.js +1 -0
  67. package/mcp/dist/init-uninstall.js +482 -0
  68. package/mcp/dist/init-update.js +96 -0
  69. package/mcp/dist/init-walkthrough-merge.js +90 -0
  70. package/mcp/dist/init-walkthrough.js +529 -0
  71. package/mcp/dist/{link-checksums.js → link/checksums.js} +5 -5
  72. package/mcp/dist/{link-context.js → link/context.js} +4 -4
  73. package/mcp/dist/{link-doctor.js → link/doctor.js} +20 -22
  74. package/mcp/dist/{link.js → link/link.js} +26 -31
  75. package/mcp/dist/{link-skills.js → link/skills.js} +10 -10
  76. package/mcp/dist/logger.js +11 -3
  77. package/mcp/dist/phren-art.js +0 -6
  78. package/mcp/dist/phren-paths.js +30 -12
  79. package/mcp/dist/proactivity.js +2 -2
  80. package/mcp/dist/profile-store.js +5 -6
  81. package/mcp/dist/project-config.js +2 -2
  82. package/mcp/dist/project-topics.js +1 -1
  83. package/mcp/dist/query-correlation.js +1 -1
  84. package/mcp/dist/{session-checkpoints.js → session/checkpoints.js} +3 -3
  85. package/mcp/dist/{session-utils.js → session/utils.js} +1 -1
  86. package/mcp/dist/{shared-content.js → shared/content.js} +7 -7
  87. package/mcp/dist/{shared-data-utils.js → shared/data-utils.js} +3 -3
  88. package/mcp/dist/{shared-embedding-cache.js → shared/embedding-cache.js} +3 -3
  89. package/mcp/dist/{shared-fragment-graph.js → shared/fragment-graph.js} +15 -24
  90. package/mcp/dist/shared/governance.js +4 -0
  91. package/mcp/dist/{shared-index.js → shared/index.js} +92 -123
  92. package/mcp/dist/{shared-ollama.js → shared/ollama.js} +2 -2
  93. package/mcp/dist/{shared-retrieval.js → shared/retrieval.js} +16 -21
  94. package/mcp/dist/{shared-search-fallback.js → shared/search-fallback.js} +17 -20
  95. package/mcp/dist/{shared-sqljs.js → shared/sqljs.js} +3 -3
  96. package/mcp/dist/{shared-vector-index.js → shared/vector-index.js} +3 -3
  97. package/mcp/dist/shared.js +4 -59
  98. package/mcp/dist/{shell-entry.js → shell/entry.js} +6 -6
  99. package/mcp/dist/{shell-input.js → shell/input.js} +13 -13
  100. package/mcp/dist/{shell-palette.js → shell/palette.js} +3 -3
  101. package/mcp/dist/{shell-render.js → shell/render.js} +1 -1
  102. package/mcp/dist/{shell.js → shell/shell.js} +11 -11
  103. package/mcp/dist/{shell-state-store.js → shell/state-store.js} +5 -5
  104. package/mcp/dist/{shell-view-list.js → shell/view-list.js} +1 -1
  105. package/mcp/dist/{shell-view.js → shell/view.js} +13 -13
  106. package/mcp/dist/{skill-files.js → skill/files.js} +9 -9
  107. package/mcp/dist/{skill-registry.js → skill/registry.js} +4 -4
  108. package/mcp/dist/{skill-state.js → skill/state.js} +1 -1
  109. package/mcp/dist/startup-embedding.js +2 -2
  110. package/mcp/dist/status.js +15 -14
  111. package/mcp/dist/{tasks-github.js → task/github.js} +2 -2
  112. package/mcp/dist/{task-hygiene.js → task/hygiene.js} +4 -4
  113. package/mcp/dist/{task-lifecycle.js → task/lifecycle.js} +7 -7
  114. package/mcp/dist/telemetry.js +3 -4
  115. package/mcp/dist/tool-registry.js +29 -17
  116. package/mcp/dist/tools/config.js +515 -0
  117. package/mcp/dist/{mcp-data.js → tools/data.js} +8 -10
  118. package/mcp/dist/{mcp-extract-facts.js → tools/extract-facts.js} +6 -6
  119. package/mcp/dist/{mcp-extract.js → tools/extract.js} +6 -6
  120. package/mcp/dist/{mcp-finding.js → tools/finding.js} +97 -124
  121. package/mcp/dist/{mcp-graph.js → tools/graph.js} +11 -14
  122. package/mcp/dist/{mcp-hooks.js → tools/hooks.js} +6 -6
  123. package/mcp/dist/{mcp-memory.js → tools/memory.js} +5 -5
  124. package/mcp/dist/{mcp-ops.js → tools/ops.js} +169 -71
  125. package/mcp/dist/{mcp-search.js → tools/search.js} +19 -23
  126. package/mcp/dist/{mcp-session.js → tools/session.js} +48 -23
  127. package/mcp/dist/{mcp-skills.js → tools/skills.js} +33 -35
  128. package/mcp/dist/{mcp-tasks.js → tools/tasks.js} +155 -282
  129. package/mcp/dist/{memory-ui-data.js → ui/data.js} +31 -17
  130. package/mcp/dist/{memory-ui.js → ui/memory-ui.js} +3 -3
  131. package/mcp/dist/{memory-ui-page.js → ui/page.js} +4 -6
  132. package/mcp/dist/{memory-ui-server.js → ui/server.js} +30 -22
  133. package/mcp/dist/update.js +2 -2
  134. package/mcp/dist/utils.js +51 -11
  135. package/package.json +17 -11
  136. package/scripts/preuninstall.mjs +139 -0
  137. package/starter/global/CLAUDE.md +3 -2
  138. package/mcp/dist/mcp-config.js +0 -551
  139. package/mcp/dist/shared-governance.js +0 -4
  140. package/starter/global/skills/pipeline.md +0 -35
  141. package/starter/global/skills/release.md +0 -35
  142. /package/mcp/dist/{content-metadata.js → content/metadata.js} +0 -0
  143. /package/mcp/dist/{shared-stemmer.js → shared/stemmer.js} +0 -0
  144. /package/mcp/dist/{shell-types.js → shell/types.js} +0 -0
  145. /package/mcp/dist/{mcp-types.js → tools/types.js} +0 -0
  146. /package/mcp/dist/{memory-ui-assets.js → ui/assets.js} +0 -0
  147. /package/mcp/dist/{memory-ui-graph.js → ui/graph.js} +0 -0
  148. /package/mcp/dist/{memory-ui-scripts.js → ui/scripts.js} +0 -0
  149. /package/mcp/dist/{memory-ui-styles.js → ui/styles.js} +0 -0
@@ -3,21 +3,22 @@ import * as path from "path";
3
3
  import * as os from "os";
4
4
  import * as crypto from "crypto";
5
5
  import { globSync } from "glob";
6
- import { debugLog, appendIndexEvent, getProjectDirs, collectNativeMemoryFiles, runtimeFile, homeDir, readRootManifest, } from "./shared.js";
7
- import { getIndexPolicy, withFileLock } from "./shared-governance.js";
8
- import { stripTaskDoneSection } from "./shared-content.js";
9
- import { isInactiveFindingLine } from "./finding-lifecycle.js";
10
- import { invalidateDfCache } from "./shared-search-fallback.js";
11
- import { errorMessage } from "./utils.js";
12
- import { beginUserFragmentBuildCache, endUserFragmentBuildCache, extractAndLinkFragments, ensureGlobalEntitiesTable, } from "./shared-fragment-graph.js";
13
- import { bootstrapSqlJs } from "./shared-sqljs.js";
14
- import { getProjectOwnershipMode, getProjectSourcePath, readProjectConfig } from "./project-config.js";
15
- import { buildSourceDocKey, queryDocBySourceKey, queryDocRows, } from "./index-query.js";
16
- import { classifyTopicForText, readProjectTopics, } from "./project-topics.js";
17
- export { porterStem } from "./shared-stemmer.js";
18
- export { cosineFallback } from "./shared-search-fallback.js";
19
- export { queryFragmentLinks, queryFragmentLinks as queryEntityLinks, getFragmentBoostDocs, getFragmentBoostDocs as getEntityBoostDocs, ensureGlobalEntitiesTable, queryCrossProjectFragments, logFragmentMiss, logFragmentMiss as logEntityMiss, extractFragmentNames, extractFragmentNames as extractEntityNames, } from "./shared-fragment-graph.js";
20
- export { buildSourceDocKey, decodeFiniteNumber, decodeStringRow, extractSnippet, getDocSourceKey, normalizeMemoryId, queryDocBySourceKey, queryDocRows, queryRows, rowToDoc, rowToDocWithRowid, } from "./index-query.js";
6
+ import { debugLog, appendIndexEvent, getProjectDirs, collectNativeMemoryFiles, runtimeFile, homeDir, readRootManifest, } from "../shared.js";
7
+ import { getIndexPolicy, withFileLock } from "./governance.js";
8
+ import { stripTaskDoneSection } from "./content.js";
9
+ import { isInactiveFindingLine } from "../finding/lifecycle.js";
10
+ import { invalidateDfCache } from "./search-fallback.js";
11
+ import { errorMessage } from "../utils.js";
12
+ import { logger } from "../logger.js";
13
+ import { beginUserFragmentBuildCache, endUserFragmentBuildCache, extractAndLinkFragments, ensureGlobalEntitiesTable, } from "./fragment-graph.js";
14
+ import { bootstrapSqlJs } from "./sqljs.js";
15
+ import { getProjectOwnershipMode, getProjectSourcePath, readProjectConfig } from "../project-config.js";
16
+ import { buildSourceDocKey, queryDocBySourceKey, queryDocRows, } from "../index-query.js";
17
+ import { classifyTopicForText, readProjectTopics, } from "../project-topics.js";
18
+ export { porterStem } from "./stemmer.js";
19
+ export { cosineFallback } from "./search-fallback.js";
20
+ export { queryFragmentLinks, queryFragmentLinks as queryEntityLinks, getFragmentBoostDocs, getFragmentBoostDocs as getEntityBoostDocs, ensureGlobalEntitiesTable, queryCrossProjectFragments, logFragmentMiss, logFragmentMiss as logEntityMiss, extractFragmentNames, extractFragmentNames as extractEntityNames, } from "./fragment-graph.js";
21
+ export { buildSourceDocKey, decodeFiniteNumber, decodeStringRow, extractSnippet, getDocSourceKey, normalizeMemoryId, queryDocBySourceKey, queryDocRows, queryRows, rowToDoc, rowToDocWithRowid, } from "../index-query.js";
21
22
  // ── Async embedding queue ───────────────────────────────────────────────────
22
23
  const _embQueue = new Map();
23
24
  let _embTimer = null;
@@ -32,8 +33,8 @@ function scheduleEmbedding(phrenPath, docPath, content) {
32
33
  async function _drainEmbQueue() {
33
34
  if (_embQueue.size === 0)
34
35
  return;
35
- const { embedText, getEmbeddingModel } = await import("./shared-ollama.js");
36
- const { getEmbeddingCache } = await import("./shared-embedding-cache.js");
36
+ const { embedText, getEmbeddingModel } = await import("./ollama.js");
37
+ const { getEmbeddingCache } = await import("./embedding-cache.js");
37
38
  const entries = [..._embQueue.entries()];
38
39
  _embQueue.clear();
39
40
  // Group by phrenPath so we flush each cache once after all its entries are set.
@@ -49,8 +50,7 @@ async function _drainEmbQueue() {
49
50
  await cache.load();
50
51
  }
51
52
  catch (err) {
52
- if ((process.env.PHREN_DEBUG))
53
- process.stderr.write(`[phren] embeddingQueue cacheLoad: ${errorMessage(err)}\n`);
53
+ logger.debug("embeddingQueue cacheLoad", errorMessage(err));
54
54
  }
55
55
  const model = getEmbeddingModel();
56
56
  for (const { docPath, content } of docs) {
@@ -62,16 +62,14 @@ async function _drainEmbQueue() {
62
62
  cache.set(docPath, getEmbeddingModel(), vec);
63
63
  }
64
64
  catch (err) {
65
- if ((process.env.PHREN_DEBUG))
66
- process.stderr.write(`[phren] embeddingQueue embedText: ${errorMessage(err)}\n`);
65
+ logger.debug("embeddingQueue embedText", errorMessage(err));
67
66
  }
68
67
  }
69
68
  try {
70
69
  await cache.flush();
71
70
  }
72
71
  catch (err) {
73
- if ((process.env.PHREN_DEBUG))
74
- process.stderr.write(`[phren] embeddingQueue cacheFlush: ${errorMessage(err)}\n`);
72
+ logger.debug("embeddingQueue cacheFlush", errorMessage(err));
75
73
  }
76
74
  }
77
75
  }
@@ -133,8 +131,7 @@ function _resolveImportsRecursive(content, phrenPath, seen, depth) {
133
131
  normalized = fs.realpathSync.native(resolved);
134
132
  }
135
133
  catch (err) {
136
- if ((process.env.PHREN_DEBUG))
137
- process.stderr.write(`[phren] resolveImports realpath: ${errorMessage(err)}\n`);
134
+ logger.debug("resolveImports realpath", errorMessage(err));
138
135
  return `<!-- @import not found: ${trimmed} -->`;
139
136
  }
140
137
  let normalizedGlobalRoot = globalRoot;
@@ -158,8 +155,7 @@ function _resolveImportsRecursive(content, phrenPath, seen, depth) {
158
155
  return _resolveImportsRecursive(imported, phrenPath, childSeen, depth + 1);
159
156
  }
160
157
  catch (err) {
161
- if ((process.env.PHREN_DEBUG))
162
- process.stderr.write(`[phren] resolveImports fileRead: ${errorMessage(err)}\n`);
158
+ logger.debug("resolveImports fileRead", errorMessage(err));
163
159
  return `<!-- @import error: ${trimmed} -->`;
164
160
  }
165
161
  });
@@ -180,8 +176,7 @@ function touchSentinel(phrenPath) {
180
176
  fs.writeFileSync(sentinelPath, Date.now().toString());
181
177
  }
182
178
  catch (err) {
183
- if ((process.env.PHREN_DEBUG))
184
- process.stderr.write(`[phren] touchSentinel: ${errorMessage(err)}\n`);
179
+ logger.debug("touchSentinel", errorMessage(err));
185
180
  }
186
181
  }
187
182
  function computePhrenHash(phrenPath, profile, preGlobbed) {
@@ -197,8 +192,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
197
192
  hash.update(`${f}:${stat.mtimeMs}:${stat.size}`);
198
193
  }
199
194
  catch (err) {
200
- if ((process.env.PHREN_DEBUG))
201
- process.stderr.write(`[phren] computePhrenHash skip: ${errorMessage(err)}\n`);
195
+ logger.debug("computePhrenHash skip", errorMessage(err));
202
196
  }
203
197
  }
204
198
  for (const configPath of topicConfigEntries) {
@@ -207,8 +201,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
207
201
  hash.update(`topic-config:${configPath}:${stat.mtimeMs}:${stat.size}`);
208
202
  }
209
203
  catch (err) {
210
- if ((process.env.PHREN_DEBUG))
211
- process.stderr.write(`[phren] computePhrenHash topicConfig: ${errorMessage(err)}\n`);
204
+ logger.debug("computePhrenHash topicConfig", errorMessage(err));
212
205
  }
213
206
  }
214
207
  }
@@ -239,8 +232,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
239
232
  }
240
233
  }
241
234
  catch (err) {
242
- if ((process.env.PHREN_DEBUG))
243
- process.stderr.write(`[phren] computePhrenHash globDir: ${errorMessage(err)}\n`);
235
+ logger.debug("computePhrenHash globDir", errorMessage(err));
244
236
  }
245
237
  }
246
238
  files.sort();
@@ -250,8 +242,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
250
242
  hash.update(`${f}:${stat.mtimeMs}:${stat.size}`);
251
243
  }
252
244
  catch (err) {
253
- if ((process.env.PHREN_DEBUG))
254
- process.stderr.write(`[phren] computePhrenHash skip: ${errorMessage(err)}\n`);
245
+ logger.debug("computePhrenHash skip", errorMessage(err));
255
246
  }
256
247
  }
257
248
  for (const configPath of topicConfigEntries) {
@@ -260,8 +251,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
260
251
  hash.update(`topic-config:${configPath}:${stat.mtimeMs}:${stat.size}`);
261
252
  }
262
253
  catch (err) {
263
- if ((process.env.PHREN_DEBUG))
264
- process.stderr.write(`[phren] computePhrenHash topicConfig: ${errorMessage(err)}\n`);
254
+ logger.debug("computePhrenHash topicConfig", errorMessage(err));
265
255
  }
266
256
  }
267
257
  }
@@ -271,8 +261,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
271
261
  hash.update(`native:${mem.fullPath}:${stat.mtimeMs}:${stat.size}`);
272
262
  }
273
263
  catch (err) {
274
- if ((process.env.PHREN_DEBUG))
275
- process.stderr.write(`[phren] computePhrenHash skip: ${errorMessage(err)}\n`);
264
+ logger.debug("computePhrenHash skip", errorMessage(err));
276
265
  }
277
266
  }
278
267
  // Include global/ files (pulled via @import) so changes invalidate the cache
@@ -286,8 +275,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
286
275
  hash.update(`global:${f}:${stat.mtimeMs}:${stat.size}`);
287
276
  }
288
277
  catch (err) {
289
- if ((process.env.PHREN_DEBUG))
290
- process.stderr.write(`[phren] computePhrenHash skip: ${errorMessage(err)}\n`);
278
+ logger.debug("computePhrenHash skip", errorMessage(err));
291
279
  }
292
280
  }
293
281
  }
@@ -299,8 +287,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
299
287
  hash.update(`manual-links:${stat.mtimeMs}:${stat.size}`);
300
288
  }
301
289
  catch (err) {
302
- if ((process.env.PHREN_DEBUG))
303
- process.stderr.write(`[phren] computePhrenHash skip: ${errorMessage(err)}\n`);
290
+ logger.debug("computePhrenHash skip", errorMessage(err));
304
291
  }
305
292
  }
306
293
  const indexPolicyPath = path.join(phrenPath, ".config", "index-policy.json");
@@ -310,8 +297,7 @@ function computePhrenHash(phrenPath, profile, preGlobbed) {
310
297
  hash.update(`index-policy-file:${stat.mtimeMs}:${stat.size}`);
311
298
  }
312
299
  catch (err) {
313
- if ((process.env.PHREN_DEBUG))
314
- process.stderr.write(`[phren] computePhrenHash skip: ${errorMessage(err)}\n`);
300
+ logger.debug("computePhrenHash skip", errorMessage(err));
315
301
  }
316
302
  }
317
303
  if (profile)
@@ -334,8 +320,7 @@ function loadHashMap(phrenPath) {
334
320
  }
335
321
  }
336
322
  catch (err) {
337
- if ((process.env.PHREN_DEBUG))
338
- process.stderr.write(`[phren] loadHashMap: ${errorMessage(err)}\n`);
323
+ logger.debug("loadHashMap", errorMessage(err));
339
324
  }
340
325
  return { hashes: {} };
341
326
  }
@@ -355,8 +340,7 @@ function saveHashMap(phrenPath, hashes) {
355
340
  existing = data.hashes;
356
341
  }
357
342
  catch (err) {
358
- if ((process.env.PHREN_DEBUG))
359
- process.stderr.write(`[phren] saveHashMap readExisting: ${errorMessage(err)}\n`);
343
+ logger.debug("saveHashMap readExisting", errorMessage(err));
360
344
  }
361
345
  const merged = { ...existing, ...hashes };
362
346
  // Remove entries for paths that no longer exist on disk
@@ -494,8 +478,7 @@ function insertFileIntoIndex(db, entry, phrenPath, opts) {
494
478
  return true;
495
479
  }
496
480
  catch (err) {
497
- if ((process.env.PHREN_DEBUG))
498
- process.stderr.write(`[phren] insertFileIntoIndex: ${errorMessage(err)}\n`);
481
+ logger.debug("insertFileIntoIndex", errorMessage(err));
499
482
  return false;
500
483
  }
501
484
  }
@@ -575,8 +558,7 @@ function deleteEntityLinksForDocPath(db, phrenPath, docPath, fallbackProject, fa
575
558
  db.run("DELETE FROM global_entities WHERE doc_key = ?", [sourceDoc]);
576
559
  }
577
560
  catch (err) {
578
- if ((process.env.PHREN_DEBUG))
579
- process.stderr.write(`[phren] deleteEntityLinksForDocPath globalEntities: ${errorMessage(err)}\n`);
561
+ logger.debug("deleteEntityLinksForDocPath globalEntities", errorMessage(err));
580
562
  }
581
563
  }
582
564
  /**
@@ -591,15 +573,13 @@ export function updateFileInIndex(db, filePath, phrenPath) {
591
573
  deleteEntityLinksForDocPath(db, phrenPath, resolvedPath);
592
574
  }
593
575
  catch (err) {
594
- if ((process.env.PHREN_DEBUG))
595
- process.stderr.write(`[phren] updateFileInIndex deleteEntityLinks: ${errorMessage(err)}\n`);
576
+ logger.debug("updateFileInIndex deleteEntityLinks", errorMessage(err));
596
577
  }
597
578
  try {
598
579
  db.run("DELETE FROM docs WHERE path = ?", [resolvedPath]);
599
580
  }
600
581
  catch (err) {
601
- if ((process.env.PHREN_DEBUG))
602
- process.stderr.write(`[phren] updateFileInIndex deleteDocs: ${errorMessage(err)}\n`);
582
+ logger.debug("updateFileInIndex deleteDocs", errorMessage(err));
603
583
  }
604
584
  // Re-insert if file still exists
605
585
  if (fs.existsSync(resolvedPath)) {
@@ -618,8 +598,7 @@ export function updateFileInIndex(db, filePath, phrenPath) {
618
598
  extractAndLinkFragments(db, content, getEntrySourceDocKey(entry, phrenPath), phrenPath);
619
599
  }
620
600
  catch (err) {
621
- if ((process.env.PHREN_DEBUG))
622
- process.stderr.write(`[phren] updateFileInIndex entityExtraction: ${errorMessage(err)}\n`);
601
+ logger.debug("updateFileInIndex entityExtraction", errorMessage(err));
623
602
  }
624
603
  }
625
604
  }
@@ -630,22 +609,20 @@ export function updateFileInIndex(db, filePath, phrenPath) {
630
609
  saveHashMap(phrenPath, hashData.hashes);
631
610
  }
632
611
  catch (err) {
633
- if ((process.env.PHREN_DEBUG))
634
- process.stderr.write(`[phren] updateFileInIndex hashMap: ${errorMessage(err)}\n`);
612
+ logger.debug("updateFileInIndex hashMap", errorMessage(err));
635
613
  }
636
614
  }
637
615
  else {
638
616
  // Remove stale embedding if file was deleted
639
617
  void (async () => {
640
618
  try {
641
- const { getEmbeddingCache } = await import("./shared-embedding-cache.js");
619
+ const { getEmbeddingCache } = await import("./embedding-cache.js");
642
620
  const c = getEmbeddingCache(phrenPath);
643
621
  c.delete(resolvedPath);
644
622
  await c.flush();
645
623
  }
646
624
  catch (err) {
647
- if ((process.env.PHREN_DEBUG))
648
- process.stderr.write(`[phren] updateFileInIndex embeddingDelete: ${errorMessage(err)}\n`);
625
+ logger.debug("updateFileInIndex embeddingDelete", errorMessage(err));
649
626
  }
650
627
  })();
651
628
  }
@@ -664,8 +641,7 @@ function readHashSentinel(phrenPath) {
664
641
  }
665
642
  }
666
643
  catch (err) {
667
- if ((process.env.PHREN_DEBUG))
668
- process.stderr.write(`[phren] readHashSentinel: ${errorMessage(err)}\n`);
644
+ logger.debug("readHashSentinel", errorMessage(err));
669
645
  }
670
646
  return null;
671
647
  }
@@ -675,8 +651,7 @@ function writeHashSentinel(phrenPath, hash) {
675
651
  fs.writeFileSync(sentinelPath, JSON.stringify({ hash, computedAt: Date.now() }));
676
652
  }
677
653
  catch (err) {
678
- if ((process.env.PHREN_DEBUG))
679
- process.stderr.write(`[phren] writeHashSentinel: ${errorMessage(err)}\n`);
654
+ logger.debug("writeHashSentinel", errorMessage(err));
680
655
  }
681
656
  }
682
657
  function isSentinelFresh(phrenPath, sentinel) {
@@ -693,8 +668,7 @@ function isSentinelFresh(phrenPath, sentinel) {
693
668
  return false;
694
669
  }
695
670
  catch (err) {
696
- if ((process.env.PHREN_DEBUG))
697
- process.stderr.write(`[phren] isSentinelFresh statDir: ${errorMessage(err)}\n`);
671
+ logger.debug("isSentinelFresh statDir", errorMessage(err));
698
672
  }
699
673
  }
700
674
  return true;
@@ -715,8 +689,7 @@ function loadCachedEntityGraph(db, graphPath, allFiles, phrenPath) {
715
689
  return fs.statSync(f.fullPath).mtimeMs > graphMtime;
716
690
  }
717
691
  catch (err) {
718
- if ((process.env.PHREN_DEBUG))
719
- process.stderr.write(`[phren] loadCachedEntityGraph statFile: ${errorMessage(err)}\n`);
692
+ logger.debug("loadCachedEntityGraph statFile", errorMessage(err));
720
693
  return true;
721
694
  }
722
695
  });
@@ -743,8 +716,7 @@ function loadCachedEntityGraph(db, graphPath, allFiles, phrenPath) {
743
716
  db.run("INSERT OR IGNORE INTO global_entities (entity, project, doc_key) VALUES (?, ?, ?)", [entity, project, docKey]);
744
717
  }
745
718
  catch (err) {
746
- if ((process.env.PHREN_DEBUG))
747
- process.stderr.write(`[phren] loadCachedEntityGraph globalEntitiesInsert2: ${errorMessage(err)}\n`);
719
+ logger.debug("loadCachedEntityGraph globalEntitiesInsert2", errorMessage(err));
748
720
  }
749
721
  }
750
722
  }
@@ -762,23 +734,20 @@ function loadCachedEntityGraph(db, graphPath, allFiles, phrenPath) {
762
734
  db.run("INSERT OR IGNORE INTO global_entities (entity, project, doc_key) VALUES (?, ?, ?)", [name, proj, sourceDoc]);
763
735
  }
764
736
  catch (err) {
765
- if ((process.env.PHREN_DEBUG))
766
- process.stderr.write(`[phren] loadCachedEntityGraph globalEntitiesInsert: ${errorMessage(err)}\n`);
737
+ logger.debug("loadCachedEntityGraph globalEntitiesInsert", errorMessage(err));
767
738
  }
768
739
  }
769
740
  }
770
741
  }
771
742
  catch (err) {
772
- if ((process.env.PHREN_DEBUG))
773
- process.stderr.write(`[phren] entityGraph globalEntitiesRestore: ${errorMessage(err)}\n`);
743
+ logger.debug("entityGraph globalEntitiesRestore", errorMessage(err));
774
744
  }
775
745
  }
776
746
  return true;
777
747
  }
778
748
  }
779
749
  catch (err) {
780
- if ((process.env.PHREN_DEBUG))
781
- process.stderr.write(`[phren] entityGraph cacheLoad: ${errorMessage(err)}\n`);
750
+ logger.debug("entityGraph cacheLoad", errorMessage(err));
782
751
  }
783
752
  return false;
784
753
  }
@@ -797,8 +766,7 @@ function mergeManualLinks(db, phrenPath) {
797
766
  // Validate: skip manual links whose sourceDoc no longer exists in the index
798
767
  const docCheck = queryDocBySourceKey(db, phrenPath, link.sourceDoc);
799
768
  if (!docCheck) {
800
- if ((process.env.PHREN_DEBUG))
801
- process.stderr.write(`[phren] manualLinks: pruning stale link to "${link.sourceDoc}"\n`);
769
+ logger.debug("manualLinks", `pruning stale link to "${link.sourceDoc}"`);
802
770
  pruned = true;
803
771
  continue;
804
772
  }
@@ -819,14 +787,12 @@ function mergeManualLinks(db, phrenPath) {
819
787
  db.run("INSERT OR IGNORE INTO global_entities (entity, project, doc_key) VALUES (?, ?, ?)", [link.entity, projectMatch[1], link.sourceDoc]);
820
788
  }
821
789
  catch (err) {
822
- if ((process.env.PHREN_DEBUG))
823
- process.stderr.write(`[phren] manualLinks globalEntities: ${errorMessage(err)}\n`);
790
+ logger.debug("manualLinks globalEntities", errorMessage(err));
824
791
  }
825
792
  }
826
793
  }
827
794
  catch (err) {
828
- if ((process.env.PHREN_DEBUG))
829
- process.stderr.write(`[phren] manualLinks entry: ${errorMessage(err)}\n`);
795
+ logger.debug("manualLinks entry", errorMessage(err));
830
796
  }
831
797
  }
832
798
  // Rewrite manual-links.json if stale entries were pruned
@@ -839,14 +805,12 @@ function mergeManualLinks(db, phrenPath) {
839
805
  });
840
806
  }
841
807
  catch (err) {
842
- if ((process.env.PHREN_DEBUG))
843
- process.stderr.write(`[phren] manualLinks prune write: ${errorMessage(err)}\n`);
808
+ logger.debug("manualLinks prune write", errorMessage(err));
844
809
  }
845
810
  }
846
811
  }
847
812
  catch (err) {
848
- if ((process.env.PHREN_DEBUG))
849
- process.stderr.write(`[phren] mergeManualLinks: ${errorMessage(err)}\n`);
813
+ logger.debug("mergeManualLinks", errorMessage(err));
850
814
  }
851
815
  }
852
816
  async function buildIndexImpl(phrenPath, profile) {
@@ -859,8 +823,7 @@ async function buildIndexImpl(phrenPath, profile) {
859
823
  userSuffix = String(os.userInfo().uid);
860
824
  }
861
825
  catch (err) {
862
- if ((process.env.PHREN_DEBUG))
863
- process.stderr.write(`[phren] buildIndexImpl userInfo: ${errorMessage(err)}\n`);
826
+ logger.debug("buildIndexImpl userInfo", errorMessage(err));
864
827
  userSuffix = crypto.createHash("sha1").update(homeDir()).digest("hex").slice(0, 12);
865
828
  }
866
829
  const cacheDir = path.join(os.tmpdir(), `phren-fts-${userSuffix}`);
@@ -965,8 +928,7 @@ async function buildIndexImpl(phrenPath, profile) {
965
928
  }
966
929
  }
967
930
  catch (err) {
968
- if ((process.env.PHREN_DEBUG))
969
- process.stderr.write(`[phren] buildIndex hashFile: ${errorMessage(err)}\n`);
931
+ logger.debug("buildIndex hashFile", errorMessage(err));
970
932
  }
971
933
  }
972
934
  // Check for files missing from the index (deleted files)
@@ -1001,28 +963,24 @@ async function buildIndexImpl(phrenPath, profile) {
1001
963
  deleteEntityLinksForDocPath(db, phrenPath, missingPath);
1002
964
  }
1003
965
  catch (err) {
1004
- if ((process.env.PHREN_DEBUG))
1005
- process.stderr.write(`[phren] buildIndex deleteEntityLinksForMissing: ${errorMessage(err)}\n`);
966
+ logger.debug("buildIndex deleteEntityLinksForMissing", errorMessage(err));
1006
967
  }
1007
968
  try {
1008
969
  db.run("DELETE FROM docs WHERE path = ?", [missingPath]);
1009
970
  }
1010
971
  catch (err) {
1011
- if ((process.env.PHREN_DEBUG))
1012
- process.stderr.write(`[phren] buildIndex deleteDocForMissing: ${errorMessage(err)}\n`);
972
+ logger.debug("buildIndex deleteDocForMissing", errorMessage(err));
1013
973
  }
1014
974
  }
1015
975
  db.run("COMMIT");
1016
976
  }
1017
977
  catch (err) {
1018
- if ((process.env.PHREN_DEBUG))
1019
- process.stderr.write(`[phren] buildIndex incrementalDeleteCommit: ${errorMessage(err)}\n`);
978
+ logger.debug("buildIndex incrementalDeleteCommit", errorMessage(err));
1020
979
  try {
1021
980
  db.run("ROLLBACK");
1022
981
  }
1023
982
  catch (e2) {
1024
- if ((process.env.PHREN_DEBUG))
1025
- process.stderr.write(`[phren] buildIndex incrementalDeleteRollback: ${e2 instanceof Error ? e2.message : String(e2)}\n`);
983
+ logger.debug("buildIndex incrementalDeleteRollback", e2 instanceof Error ? e2.message : String(e2));
1026
984
  }
1027
985
  }
1028
986
  let updatedCount = 0;
@@ -1058,8 +1016,7 @@ async function buildIndexImpl(phrenPath, profile) {
1058
1016
  db.run("ROLLBACK");
1059
1017
  }
1060
1018
  catch (e2) {
1061
- if ((process.env.PHREN_DEBUG))
1062
- process.stderr.write(`[phren] buildIndex perFileRollback: ${e2 instanceof Error ? e2.message : String(e2)}\n`);
1019
+ logger.debug("buildIndex perFileRollback", e2 instanceof Error ? e2.message : String(e2));
1063
1020
  }
1064
1021
  throw err;
1065
1022
  }
@@ -1073,8 +1030,7 @@ async function buildIndexImpl(phrenPath, profile) {
1073
1030
  fs.writeFileSync(cacheFile, db.export());
1074
1031
  }
1075
1032
  catch (err) {
1076
- if ((process.env.PHREN_DEBUG))
1077
- process.stderr.write(`[phren] buildIndex incrementalCacheSave: ${errorMessage(err)}\n`);
1033
+ logger.debug("buildIndex incrementalCacheSave", errorMessage(err));
1078
1034
  }
1079
1035
  const incMs = Date.now() - t0;
1080
1036
  debugLog(`Incremental FTS update: ${updatedCount} changed, ${missingFromIndex.length} removed in ${incMs}ms`);
@@ -1131,8 +1087,7 @@ async function buildIndexImpl(phrenPath, profile) {
1131
1087
  newHashes[entry.fullPath] = hashFileContent(entry.fullPath);
1132
1088
  }
1133
1089
  catch (err) {
1134
- if ((process.env.PHREN_DEBUG))
1135
- process.stderr.write(`[phren] computePhrenHash skip: ${errorMessage(err)}\n`);
1090
+ logger.debug("computePhrenHash skip", errorMessage(err));
1136
1091
  }
1137
1092
  if (insertFileIntoIndex(db, entry, phrenPath, { scheduleEmbeddings: true })) {
1138
1093
  fileCount++;
@@ -1159,8 +1114,7 @@ async function buildIndexImpl(phrenPath, profile) {
1159
1114
  fs.writeFileSync(graphPath, JSON.stringify({ entities: entityRows, links: linkRows, globalEntities: globalEntityRows, ts: Date.now() }));
1160
1115
  }
1161
1116
  catch (err) {
1162
- if ((process.env.PHREN_DEBUG))
1163
- process.stderr.write(`[phren] buildIndex entityGraphPersist: ${errorMessage(err)}\n`);
1117
+ logger.debug("buildIndex entityGraphPersist", errorMessage(err));
1164
1118
  }
1165
1119
  }
1166
1120
  // Always merge manual links (survive rebuild)
@@ -1192,8 +1146,7 @@ async function buildIndexImpl(phrenPath, profile) {
1192
1146
  fs.unlinkSync(path.join(cacheDir, f));
1193
1147
  }
1194
1148
  catch (err) {
1195
- if ((process.env.PHREN_DEBUG))
1196
- process.stderr.write(`[phren] buildIndex staleCacheCleanup: ${errorMessage(err)}\n`);
1149
+ logger.debug("buildIndex staleCacheCleanup", errorMessage(err));
1197
1150
  }
1198
1151
  }
1199
1152
  debugLog(`Saved FTS index cache (${hash.slice(0, 8)}) — total ${Date.now() - t0}ms`);
@@ -1229,8 +1182,7 @@ function isRebuildLockHeld(phrenPath) {
1229
1182
  return Date.now() - stat.mtimeMs <= staleThreshold;
1230
1183
  }
1231
1184
  catch (err) {
1232
- if ((process.env.PHREN_DEBUG))
1233
- process.stderr.write(`[phren] isRebuildLockHeld stat: ${errorMessage(err)}\n`);
1185
+ logger.debug("isRebuildLockHeld stat", errorMessage(err));
1234
1186
  return false;
1235
1187
  }
1236
1188
  }
@@ -1241,8 +1193,7 @@ async function loadIndexSnapshotOrEmpty(phrenPath, profile) {
1241
1193
  userSuffix = String(os.userInfo().uid);
1242
1194
  }
1243
1195
  catch (err) {
1244
- if ((process.env.PHREN_DEBUG))
1245
- process.stderr.write(`[phren] loadIndexSnapshotOrEmpty userInfo: ${errorMessage(err)}\n`);
1196
+ logger.debug("loadIndexSnapshotOrEmpty userInfo", errorMessage(err));
1246
1197
  userSuffix = crypto.createHash("sha1").update(homeDir()).digest("hex").slice(0, 12);
1247
1198
  }
1248
1199
  const cacheDir = path.join(os.tmpdir(), `phren-fts-${userSuffix}`);
@@ -1257,7 +1208,27 @@ async function loadIndexSnapshotOrEmpty(phrenPath, profile) {
1257
1208
  debugLog(`Failed to open cached FTS snapshot while rebuild lock held: ${errorMessage(err)}`);
1258
1209
  }
1259
1210
  }
1260
- debugLog("FTS rebuild already in progress; returning empty snapshot");
1211
+ // Before returning empty, try to load any stale-but-usable cache file
1212
+ try {
1213
+ if (fs.existsSync(cacheDir)) {
1214
+ const cacheFiles = fs.readdirSync(cacheDir)
1215
+ .filter(f => f.endsWith(".db"))
1216
+ .map(f => ({ name: f, mtime: fs.statSync(path.join(cacheDir, f)).mtimeMs }))
1217
+ .sort((a, b) => b.mtime - a.mtime);
1218
+ for (const cf of cacheFiles) {
1219
+ try {
1220
+ const staleDb = new SQL.Database(fs.readFileSync(path.join(cacheDir, cf.name)));
1221
+ debugLog(`FTS rebuild in progress; falling back to stale cache: ${cf.name}`);
1222
+ return staleDb;
1223
+ }
1224
+ catch { /* try next */ }
1225
+ }
1226
+ }
1227
+ }
1228
+ catch (err) {
1229
+ debugLog(`Failed to scan stale FTS caches: ${errorMessage(err)}`);
1230
+ }
1231
+ debugLog("FTS rebuild already in progress; no usable cache found, returning empty snapshot");
1261
1232
  return createEmptyIndexDb(SQL);
1262
1233
  }
1263
1234
  // Serialize concurrent in-process buildIndex calls to prevent SQLite corruption
@@ -1342,8 +1313,7 @@ export function findFtsCacheForPath(phrenPath, profile) {
1342
1313
  userSuffix = String(os.userInfo().uid);
1343
1314
  }
1344
1315
  catch (err) {
1345
- if ((process.env.PHREN_DEBUG))
1346
- process.stderr.write(`[phren] findFtsCacheForPath userInfo: ${errorMessage(err)}\n`);
1316
+ logger.debug("findFtsCacheForPath userInfo", errorMessage(err));
1347
1317
  userSuffix = crypto.createHash("sha1").update(homeDir()).digest("hex").slice(0, 12);
1348
1318
  }
1349
1319
  const cacheDir = path.join(os.tmpdir(), `phren-fts-${userSuffix}`);
@@ -1357,8 +1327,7 @@ export function findFtsCacheForPath(phrenPath, profile) {
1357
1327
  }
1358
1328
  }
1359
1329
  catch (err) {
1360
- if ((process.env.PHREN_DEBUG))
1361
- process.stderr.write(`[phren] findFtsCacheForPath: ${errorMessage(err)}\n`);
1330
+ logger.debug("findFtsCacheForPath", errorMessage(err));
1362
1331
  }
1363
1332
  return { exists: false };
1364
1333
  }
@@ -1,4 +1,4 @@
1
- import { debugLog } from "./shared.js";
1
+ import { debugLog } from "../shared.js";
2
2
  const DEFAULT_OLLAMA_URL = "http://localhost:11434";
3
3
  const DEFAULT_EMBEDDING_MODEL = "nomic-embed-text";
4
4
  const DEFAULT_EXTRACT_MODEL = "llama3.2";
@@ -178,4 +178,4 @@ export async function generateText(prompt, model, url) {
178
178
  return null;
179
179
  }
180
180
  }
181
- export { cosineSimilarity } from "./embedding.js";
181
+ export { cosineSimilarity } from "../embedding.js";
@@ -1,17 +1,18 @@
1
1
  // shared-retrieval.ts — shared retrieval core used by hooks and MCP search.
2
- import { getQualityMultiplier, entryScoreKey, } from "./shared-governance.js";
3
- import { queryDocRows, queryRows, cosineFallback, extractSnippet, getDocSourceKey, getEntityBoostDocs, decodeFiniteNumber, rowToDocWithRowid, buildIndex, } from "./shared-index.js";
4
- import { filterTrustedFindingsDetailed, } from "./shared-content.js";
5
- import { parseCitationComment } from "./content-citation.js";
6
- import { getHighImpactFindings } from "./finding-impact.js";
7
- import { buildFtsQueryVariants, buildRelaxedFtsQuery, isFeatureEnabled, STOP_WORDS, errorMessage } from "./utils.js";
2
+ import { getQualityMultiplier, entryScoreKey, } from "./governance.js";
3
+ import { queryDocRows, queryRows, cosineFallback, extractSnippet, getDocSourceKey, getEntityBoostDocs, decodeFiniteNumber, rowToDocWithRowid, buildIndex, } from "./index.js";
4
+ import { filterTrustedFindingsDetailed, } from "./content.js";
5
+ import { parseCitationComment } from "../content/citation.js";
6
+ import { getHighImpactFindings } from "../finding/impact.js";
7
+ import { buildFtsQueryVariants, buildRelaxedFtsQuery, isFeatureEnabled, STOP_WORDS, errorMessage } from "../utils.js";
8
+ import { logger } from "../logger.js";
8
9
  import * as fs from "fs";
9
10
  import * as path from "path";
10
- import { getProjectGlobBoost } from "./cli-hooks-globs.js";
11
- import { vectorFallback, deterministicSeed } from "./shared-search-fallback.js";
12
- import { getOllamaUrl, getCloudEmbeddingUrl } from "./shared-ollama.js";
13
- import { keywordFallbackSearch } from "./core-search.js";
14
- import { debugLog } from "./shared.js";
11
+ import { getProjectGlobBoost } from "../cli/hooks-globs.js";
12
+ import { vectorFallback, deterministicSeed } from "./search-fallback.js";
13
+ import { getOllamaUrl, getCloudEmbeddingUrl } from "./ollama.js";
14
+ import { keywordFallbackSearch } from "../core/search.js";
15
+ import { debugLog } from "../shared.js";
15
16
  // ── Scoring constants ─────────────────────────────────────────────────────────
16
17
  /** Number of docs sampled for token-overlap semantic fallback search. */
17
18
  const SEMANTIC_FALLBACK_SAMPLE_LIMIT = 100;
@@ -383,8 +384,7 @@ export async function searchDocumentsAsync(db, safeQuery, prompt, keywords, dete
383
384
  }
384
385
  catch (err) {
385
386
  // Vector search failure is non-fatal — return sync result
386
- if ((process.env.PHREN_DEBUG))
387
- process.stderr.write(`[phren] hybridSearch vectorFallback: ${errorMessage(err)}\n`);
387
+ logger.debug("hybridSearch vectorFallback", errorMessage(err));
388
388
  return syncResult;
389
389
  }
390
390
  }
@@ -483,9 +483,7 @@ export async function searchKnowledgeRows(db, options) {
483
483
  }
484
484
  }
485
485
  catch (err) {
486
- if ((process.env.PHREN_DEBUG)) {
487
- process.stderr.write(`[phren] vectorFallback: ${errorMessage(err)}\n`);
488
- }
486
+ logger.debug("vectorFallback", errorMessage(err));
489
487
  }
490
488
  }
491
489
  return { safeQuery, rows, usedFallback };
@@ -523,9 +521,7 @@ export async function searchFederatedStores(localPhrenPath, options) {
523
521
  }
524
522
  }
525
523
  catch (err) {
526
- if (process.env.PHREN_DEBUG) {
527
- process.stderr.write(`[phren] federatedSearch storePath=${storePath}: ${errorMessage(err)}\n`);
528
- }
524
+ logger.debug(`federatedSearch storePath=${storePath}`, errorMessage(err));
529
525
  // Federation errors are non-fatal — continue with other stores
530
526
  }
531
527
  }
@@ -771,8 +767,7 @@ export function markStaleCitations(snippet) {
771
767
  }
772
768
  }
773
769
  catch (err) {
774
- if ((process.env.PHREN_DEBUG))
775
- process.stderr.write(`[phren] applyCitationAnnotations fileRead: ${errorMessage(err)}\n`);
770
+ logger.debug("applyCitationAnnotations fileRead", errorMessage(err));
776
771
  stale = true;
777
772
  }
778
773
  }