@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
@@ -1,20 +1,21 @@
1
- import { buildHookContext, handleGuardSkip, debugLog, appendAuditLog, runtimeFile, sessionMarker, EXEC_TIMEOUT_MS, getPhrenPath, getProjectDirs, findProjectNameCaseInsensitive, homePath, updateRuntimeHealth, withFileLock, getWorkflowPolicy, appendReviewQueue, recordFeedback, getQualityMultiplier, detectProject, isProjectHookEnabled, readProjectConfig, getProjectSourcePath, detectProjectDir, ensureLocalGitRepo, isProjectTracked, repairPreexistingInstall, getProactivityLevelForTask, getProactivityLevelForFindings, hasExplicitFindingSignal, shouldAutoCaptureFindingsForLevel, FINDING_SENSITIVITY_CONFIG, isFeatureEnabled, errorMessage, bootstrapPhrenDotEnv, finalizeTaskSession, appendFindingJournal, runDoctor, resolveRuntimeProfile, } from "./cli-hooks-context.js";
2
- import { sessionMetricsFile, qualityMarkers, } from "./shared.js";
3
- import { autoMergeConflicts, mergeTask, mergeFindings, } from "./shared-content.js";
4
- import { runGit } from "./utils.js";
5
- import { readInstallPreferences } from "./init-preferences.js";
1
+ import { buildHookContext, handleGuardSkip, debugLog, appendAuditLog, runtimeFile, sessionMarker, EXEC_TIMEOUT_MS, getPhrenPath, getProjectDirs, findProjectNameCaseInsensitive, homePath, updateRuntimeHealth, withFileLock, getWorkflowPolicy, appendReviewQueue, recordFeedback, getQualityMultiplier, detectProject, isProjectHookEnabled, readProjectConfig, getProjectSourcePath, detectProjectDir, ensureLocalGitRepo, isProjectTracked, repairPreexistingInstall, getProactivityLevelForTask, getProactivityLevelForFindings, hasExplicitFindingSignal, shouldAutoCaptureFindingsForLevel, FINDING_SENSITIVITY_CONFIG, isFeatureEnabled, errorMessage, bootstrapPhrenDotEnv, finalizeTaskSession, appendFindingJournal, runDoctor, resolveRuntimeProfile, } from "./hooks-context.js";
2
+ import { sessionMetricsFile, qualityMarkers, } from "../shared.js";
3
+ import { autoMergeConflicts, mergeTask, mergeFindings, } from "../shared/content.js";
4
+ import { runGit } from "../utils.js";
5
+ import { readInstallPreferences } from "../init/preferences.js";
6
6
  import * as fs from "fs";
7
7
  import * as path from "path";
8
8
  import * as os from "os";
9
9
  import { execFileSync, spawn } from "child_process";
10
10
  import { fileURLToPath } from "url";
11
- import { isTaskFileName, TASKS_FILENAME } from "./data-tasks.js";
12
- import { buildIndex, queryRows, } from "./shared-index.js";
13
- import { filterTaskByPriority } from "./shared-retrieval.js";
11
+ import { isTaskFileName, TASKS_FILENAME } from "../data/tasks.js";
12
+ import { buildIndex, queryRows, } from "../shared/index.js";
13
+ import { filterTaskByPriority } from "../shared/retrieval.js";
14
+ import { logger } from "../logger.js";
14
15
  function getRuntimeProfile() {
15
16
  return resolveRuntimeProfile(getPhrenPath());
16
17
  }
17
- export { buildHookContext, checkHookGuard, handleGuardSkip } from "./cli-hooks-context.js";
18
+ export { buildHookContext, checkHookGuard, handleGuardSkip } from "./hooks-context.js";
18
19
  /** Read JSON from stdin if it's not a TTY. Returns null if stdin is a TTY or parsing fails. */
19
20
  function readStdinJson() {
20
21
  if (process.stdin.isTTY)
@@ -23,8 +24,7 @@ function readStdinJson() {
23
24
  return JSON.parse(fs.readFileSync(0, "utf-8"));
24
25
  }
25
26
  catch (err) {
26
- if (process.env.PHREN_DEBUG)
27
- process.stderr.write(`[phren] readStdinJson: ${errorMessage(err)}\n`);
27
+ logger.debug("hooks-session", `readStdinJson: ${errorMessage(err)}`);
28
28
  return null;
29
29
  }
30
30
  }
@@ -230,13 +230,17 @@ export function trackSessionMetrics(phrenPathLocal, sessionId, selected) {
230
230
  }
231
231
  // ── Background maintenance ───────────────────────────────────────────────────
232
232
  export function resolveSubprocessArgs(command) {
233
- const distEntry = path.join(path.dirname(fileURLToPath(import.meta.url)), "index.js");
234
- if (fs.existsSync(distEntry))
235
- return [distEntry, command];
236
- const sourceEntry = process.argv.find((a) => /[\\/]index\.(ts|js)$/.test(a) && fs.existsSync(a));
237
- const runner = process.argv[1];
238
- if (sourceEntry && runner)
239
- return [runner, sourceEntry, command];
233
+ // Prefer the entry script that started this process
234
+ const entry = process.argv[1];
235
+ if (entry && fs.existsSync(entry) && /index\.(ts|js)$/.test(entry))
236
+ return [entry, command];
237
+ // Fallback: look for index.js next to this file or one level up (for subdirectory builds)
238
+ const thisDir = path.dirname(fileURLToPath(import.meta.url));
239
+ for (const dir of [thisDir, path.dirname(thisDir)]) {
240
+ const candidate = path.join(dir, "index.js");
241
+ if (fs.existsSync(candidate))
242
+ return [candidate, command];
243
+ }
240
244
  return null;
241
245
  }
242
246
  function scheduleBackgroundSync(phrenPathLocal) {
@@ -319,8 +323,7 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
319
323
  }
320
324
  catch (err) {
321
325
  // Another process already claimed the lock
322
- if (process.env.PHREN_DEBUG)
323
- process.stderr.write(`[phren] backgroundMaintenance lockClaim: ${errorMessage(err)}\n`);
326
+ logger.debug("hooks-session", `backgroundMaintenance lockClaim: ${errorMessage(err)}`);
324
327
  return false;
325
328
  }
326
329
  try {
@@ -352,24 +355,21 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
352
355
  fs.appendFileSync(logPath, msg);
353
356
  }
354
357
  catch (err) {
355
- if (process.env.PHREN_DEBUG)
356
- process.stderr.write(`[phren] backgroundMaintenance exitLog: ${errorMessage(err)}\n`);
358
+ logger.debug("hooks-session", `backgroundMaintenance exitLog: ${errorMessage(err)}`);
357
359
  }
358
360
  if (code === 0) {
359
361
  try {
360
362
  fs.writeFileSync(markers.done, new Date().toISOString() + "\n");
361
363
  }
362
364
  catch (err) {
363
- if (process.env.PHREN_DEBUG)
364
- process.stderr.write(`[phren] backgroundMaintenance doneMarker: ${errorMessage(err)}\n`);
365
+ logger.debug("hooks-session", `backgroundMaintenance doneMarker: ${errorMessage(err)}`);
365
366
  }
366
367
  }
367
368
  try {
368
369
  fs.unlinkSync(markers.lock);
369
370
  }
370
371
  catch (err) {
371
- if (process.env.PHREN_DEBUG)
372
- process.stderr.write(`[phren] backgroundMaintenance unlockOnExit: ${errorMessage(err)}\n`);
372
+ logger.debug("hooks-session", `backgroundMaintenance unlockOnExit: ${errorMessage(err)}`);
373
373
  }
374
374
  });
375
375
  child.on("error", (spawnErr) => {
@@ -378,15 +378,13 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
378
378
  fs.appendFileSync(logPath, msg);
379
379
  }
380
380
  catch (err) {
381
- if (process.env.PHREN_DEBUG)
382
- process.stderr.write(`[phren] backgroundMaintenance errorLog: ${errorMessage(err)}\n`);
381
+ logger.debug("hooks-session", `backgroundMaintenance errorLog: ${errorMessage(err)}`);
383
382
  }
384
383
  try {
385
384
  fs.unlinkSync(markers.lock);
386
385
  }
387
386
  catch (err) {
388
- if (process.env.PHREN_DEBUG)
389
- process.stderr.write(`[phren] backgroundMaintenance unlockOnError: ${errorMessage(err)}\n`);
387
+ logger.debug("hooks-session", `backgroundMaintenance unlockOnError: ${errorMessage(err)}`);
390
388
  }
391
389
  });
392
390
  fs.closeSync(logFd);
@@ -401,15 +399,13 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
401
399
  fs.appendFileSync(path.join(logDir, "background-maintenance.log"), `[${new Date().toISOString()}] spawn failed: ${errMsg}\n`);
402
400
  }
403
401
  catch (err) {
404
- if (process.env.PHREN_DEBUG)
405
- process.stderr.write(`[phren] backgroundMaintenance logSpawnFailure: ${errorMessage(err)}\n`);
402
+ logger.debug("hooks-session", `backgroundMaintenance logSpawnFailure: ${errorMessage(err)}`);
406
403
  }
407
404
  try {
408
405
  fs.unlinkSync(markers.lock);
409
406
  }
410
407
  catch (err) {
411
- if (process.env.PHREN_DEBUG)
412
- process.stderr.write(`[phren] backgroundMaintenance unlockOnFailure: ${errorMessage(err)}\n`);
408
+ logger.debug("hooks-session", `backgroundMaintenance unlockOnFailure: ${errorMessage(err)}`);
413
409
  }
414
410
  return false;
415
411
  }
@@ -608,12 +604,11 @@ export async function handleHookSessionStart() {
608
604
  const maintenanceScheduled = scheduleBackgroundMaintenance(phrenPath);
609
605
  const unsyncedCommits = hasRemote ? await countUnsyncedCommits(phrenPath) : 0;
610
606
  try {
611
- const { trackSession } = await import("./telemetry.js");
607
+ const { trackSession } = await import("../telemetry.js");
612
608
  trackSession(phrenPath);
613
609
  }
614
610
  catch (err) {
615
- if (process.env.PHREN_DEBUG)
616
- process.stderr.write(`[phren] hookSessionStart trackSession: ${errorMessage(err)}\n`);
611
+ logger.debug("hooks-session", `hookSessionStart trackSession: ${errorMessage(err)}`);
617
612
  }
618
613
  updateRuntimeHealth(phrenPath, {
619
614
  lastSessionStartAt: startedAt,
@@ -779,8 +774,7 @@ export async function handleHookStop() {
779
774
  }
780
775
  }
781
776
  catch (err) {
782
- if (process.env.PHREN_DEBUG)
783
- process.stderr.write(`[phren] hookStop transcriptParse: ${errorMessage(err)}\n`);
777
+ logger.debug("hooks-session", `hookStop transcriptParse: ${errorMessage(err)}`);
784
778
  }
785
779
  }
786
780
  captureInput = assistantTexts.join("\n");
@@ -804,8 +798,7 @@ export async function handleHookStop() {
804
798
  }
805
799
  }
806
800
  catch (err) {
807
- if (process.env.PHREN_DEBUG)
808
- process.stderr.write(`[phren] hookStop sessionCapCheck: ${errorMessage(err)}\n`);
801
+ logger.debug("hooks-session", `hookStop sessionCapCheck: ${errorMessage(err)}`);
809
802
  }
810
803
  }
811
804
  if (!capReached) {
@@ -1225,8 +1218,7 @@ export async function handleHookTool() {
1225
1218
  raw = fs.readFileSync(0, "utf-8");
1226
1219
  }
1227
1220
  catch (err) {
1228
- if (process.env.PHREN_DEBUG)
1229
- process.stderr.write(`[phren] hookTool stdinRead: ${errorMessage(err)}\n`);
1221
+ logger.debug("hooks-session", `hookTool stdinRead: ${errorMessage(err)}`);
1230
1222
  process.exit(0);
1231
1223
  }
1232
1224
  }
@@ -1235,8 +1227,7 @@ export async function handleHookTool() {
1235
1227
  data = JSON.parse(raw);
1236
1228
  }
1237
1229
  catch (err) {
1238
- if (process.env.PHREN_DEBUG)
1239
- process.stderr.write(`[phren] hookTool stdinParse: ${errorMessage(err)}\n`);
1230
+ logger.debug("hooks-session", `hookTool stdinParse: ${errorMessage(err)}`);
1240
1231
  process.exit(0);
1241
1232
  }
1242
1233
  const toolName = String(data.tool_name ?? data.tool ?? "");
@@ -1287,8 +1278,7 @@ export async function handleHookTool() {
1287
1278
  fs.appendFileSync(logFile, JSON.stringify(entry) + "\n");
1288
1279
  }
1289
1280
  catch (err) {
1290
- if (process.env.PHREN_DEBUG)
1291
- process.stderr.write(`[phren] hookTool toolLog: ${errorMessage(err)}\n`);
1281
+ logger.debug("hooks-session", `hookTool toolLog: ${errorMessage(err)}`);
1292
1282
  }
1293
1283
  const cooldownFile = runtimeFile(ctx.phrenPath, "hook-tool-cooldown");
1294
1284
  try {
@@ -1301,8 +1291,7 @@ export async function handleHookTool() {
1301
1291
  }
1302
1292
  }
1303
1293
  catch (err) {
1304
- if (process.env.PHREN_DEBUG)
1305
- process.stderr.write(`[phren] hookTool cooldownStat: ${errorMessage(err)}\n`);
1294
+ logger.debug("hooks-session", `hookTool cooldownStat: ${errorMessage(err)}`);
1306
1295
  }
1307
1296
  if (activeProject && sessionId) {
1308
1297
  try {
@@ -1318,8 +1307,7 @@ export async function handleHookTool() {
1318
1307
  }
1319
1308
  }
1320
1309
  catch (err) {
1321
- if (process.env.PHREN_DEBUG)
1322
- process.stderr.write(`[phren] hookTool sessionCapCheck: ${errorMessage(err)}\n`);
1310
+ logger.debug("hooks-session", `hookTool sessionCapCheck: ${errorMessage(err)}`);
1323
1311
  }
1324
1312
  }
1325
1313
  const findingsLevelForTool = getProactivityLevelForFindings(ctx.phrenPath);
@@ -1335,8 +1323,7 @@ export async function handleHookTool() {
1335
1323
  fs.writeFileSync(cooldownFile, Date.now().toString());
1336
1324
  }
1337
1325
  catch (err) {
1338
- if (process.env.PHREN_DEBUG)
1339
- process.stderr.write(`[phren] hookTool cooldownWrite: ${errorMessage(err)}\n`);
1326
+ logger.debug("hooks-session", `hookTool cooldownWrite: ${errorMessage(err)}`);
1340
1327
  }
1341
1328
  if (sessionId) {
1342
1329
  try {
@@ -1346,15 +1333,13 @@ export async function handleHookTool() {
1346
1333
  count = Number.parseInt(fs.readFileSync(capFile, "utf8").trim(), 10) || 0;
1347
1334
  }
1348
1335
  catch (err) {
1349
- if (process.env.PHREN_DEBUG)
1350
- process.stderr.write(`[phren] hookTool capFileRead: ${errorMessage(err)}\n`);
1336
+ logger.debug("hooks-session", `hookTool capFileRead: ${errorMessage(err)}`);
1351
1337
  }
1352
1338
  count += candidates.length;
1353
1339
  fs.writeFileSync(capFile, count.toString());
1354
1340
  }
1355
1341
  catch (err) {
1356
- if (process.env.PHREN_DEBUG)
1357
- process.stderr.write(`[phren] hookTool capFileWrite: ${errorMessage(err)}\n`);
1342
+ logger.debug("hooks-session", `hookTool capFileWrite: ${errorMessage(err)}`);
1358
1343
  }
1359
1344
  }
1360
1345
  }
@@ -4,38 +4,39 @@
4
4
  // cli-hooks-session.ts — session lifecycle hooks, metrics, background maintenance
5
5
  // cli-hooks-output.ts — hook output formatting
6
6
  // cli-hooks-globs.ts — project glob matching
7
- import { debugLog, sessionMarker, sessionsDir, getPhrenPath, } from "./shared.js";
8
- import { mergeConfig, } from "./shared-governance.js";
9
- import { buildIndex, detectProject, } from "./shared-index.js";
10
- import { isProjectHookEnabled } from "./project-config.js";
11
- import { checkConsolidationNeeded, } from "./shared-content.js";
12
- import { buildRobustFtsQuery, extractKeywordEntries, isFeatureEnabled, clampInt, errorMessage, loadSynonymMap, learnSynonym, STOP_WORDS, } from "./utils.js";
13
- import { getHooksEnabledPreference } from "./init.js";
14
- import { isToolHookEnabled } from "./hooks.js";
15
- import { handleExtractMemories } from "./cli-extract.js";
16
- import { appendAuditLog } from "./shared.js";
17
- import { updateRuntimeHealth } from "./shared-governance.js";
18
- import { getProactivityLevelForTask, getProactivityLevelForFindings } from "./proactivity.js";
19
- import { FINDING_SENSITIVITY_CONFIG } from "./cli-config.js";
7
+ import { debugLog, sessionMarker, sessionsDir, getPhrenPath, } from "../shared.js";
8
+ import { mergeConfig, } from "../shared/governance.js";
9
+ import { buildIndex, detectProject, } from "../shared/index.js";
10
+ import { isProjectHookEnabled } from "../project-config.js";
11
+ import { checkConsolidationNeeded, } from "../shared/content.js";
12
+ import { buildRobustFtsQuery, extractKeywordEntries, isFeatureEnabled, clampInt, errorMessage, loadSynonymMap, learnSynonym, STOP_WORDS, } from "../utils.js";
13
+ import { getHooksEnabledPreference } from "../init/init.js";
14
+ import { logger } from "../logger.js";
15
+ import { isToolHookEnabled } from "../hooks.js";
16
+ import { handleExtractMemories } from "./extract.js";
17
+ import { appendAuditLog } from "../shared.js";
18
+ import { updateRuntimeHealth } from "../shared/governance.js";
19
+ import { getProactivityLevelForTask, getProactivityLevelForFindings } from "../proactivity.js";
20
+ import { FINDING_SENSITIVITY_CONFIG } from "./config.js";
20
21
  import * as fs from "fs";
21
22
  // ── Re-exports from focused modules ─────────────────────────────────────────
22
23
  // Citations
23
- export { parseCitations, validateCitation, annotateStale, clearCitationValidCache, } from "./cli-hooks-citations.js";
24
+ export { parseCitations, validateCitation, annotateStale, clearCitationValidCache, } from "./hooks-citations.js";
24
25
  // Globs
25
- export { getProjectGlobBoost, clearProjectGlobCache, } from "./cli-hooks-globs.js";
26
+ export { getProjectGlobBoost, clearProjectGlobCache, } from "./hooks-globs.js";
26
27
  // Retrieval
27
- export { detectTaskIntent, filterTaskByPriority, searchDocuments, applyTrustFilter, rankResults, selectSnippets, } from "./shared-retrieval.js";
28
+ export { detectTaskIntent, filterTaskByPriority, searchDocuments, applyTrustFilter, rankResults, selectSnippets, } from "../shared/retrieval.js";
28
29
  // Output
29
- export { buildHookOutput, } from "./cli-hooks-output.js";
30
+ export { buildHookOutput, } from "./hooks-output.js";
30
31
  // Session
31
- export { handleHookSessionStart, handleHookStop, handleBackgroundSync, handleHookContext, handleHookTool, trackSessionMetrics, filterConversationInsightsForProactivity, extractToolFindings, filterToolFindingsForProactivity, resolveSubprocessArgs, } from "./cli-hooks-session.js";
32
+ export { handleHookSessionStart, handleHookStop, handleBackgroundSync, handleHookContext, handleHookTool, trackSessionMetrics, filterConversationInsightsForProactivity, extractToolFindings, filterToolFindingsForProactivity, resolveSubprocessArgs, } from "./hooks-session.js";
32
33
  // ── Imports for the orchestrator ─────────────────────────────────────────────
33
- import { searchDocumentsAsync, applyTrustFilter, rankResults, selectSnippets, detectTaskIntent, } from "./shared-retrieval.js";
34
- import { buildHookOutput } from "./cli-hooks-output.js";
35
- import { getGitContext, trackSessionMetrics, } from "./cli-hooks-session.js";
36
- import { approximateTokens } from "./shared-retrieval.js";
37
- import { resolveRuntimeProfile } from "./runtime-profile.js";
38
- import { handleTaskPromptLifecycle } from "./task-lifecycle.js";
34
+ import { searchDocumentsAsync, applyTrustFilter, rankResults, selectSnippets, detectTaskIntent, } from "../shared/retrieval.js";
35
+ import { buildHookOutput } from "./hooks-output.js";
36
+ import { getGitContext, trackSessionMetrics, } from "./hooks-session.js";
37
+ import { approximateTokens } from "../shared/retrieval.js";
38
+ import { resolveRuntimeProfile } from "../runtime-profile.js";
39
+ import { handleTaskPromptLifecycle } from "../task/lifecycle.js";
39
40
  function synonymTermKnown(term, map) {
40
41
  if (Object.prototype.hasOwnProperty.call(map, term))
41
42
  return true;
@@ -126,7 +127,7 @@ export async function handleHookPrompt() {
126
127
  }
127
128
  catch (err) {
128
129
  if (process.env.PHREN_DEBUG)
129
- process.stderr.write(`[phren] hookPrompt stdinRead: ${errorMessage(err)}\n`);
130
+ logger.debug("cli-hooks", `hookPrompt stdinRead: ${errorMessage(err)}`);
130
131
  process.exit(0);
131
132
  }
132
133
  const input = parseHookInput(raw);
@@ -362,7 +363,7 @@ export async function handleHookPrompt() {
362
363
  }
363
364
  catch (err) {
364
365
  if (process.env.PHREN_DEBUG)
365
- process.stderr.write(`[phren] hookPrompt noticeFileWrite: ${errorMessage(err)}\n`);
366
+ logger.debug("cli-hooks", `hookPrompt noticeFileWrite: ${errorMessage(err)}`);
366
367
  }
367
368
  }
368
369
  }
@@ -1,20 +1,21 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
3
  import { execFileSync } from "child_process";
4
- import { expandHomePath, findArchivedProjectNameCaseInsensitive, findProjectNameCaseInsensitive, getPhrenPath, getProjectDirs, homePath, hookConfigPath, normalizeProjectNameForCreate, readRootManifest, } from "./shared.js";
5
- import { isValidProjectName, errorMessage } from "./utils.js";
6
- import { readInstallPreferences, writeInstallPreferences } from "./init-preferences.js";
7
- import { buildSkillManifest, findLocalSkill, findSkill, getAllSkills } from "./skill-registry.js";
8
- import { detectSkillCollisions } from "./link-skills.js";
9
- import { setSkillEnabledAndSync, syncSkillLinksForScope } from "./skill-files.js";
10
- import { findProjectDir } from "./project-locator.js";
11
- import { TASK_FILE_ALIASES, addTask, completeTask, updateTask, reorderTask, pinTask, removeTask, workNextTask, tidyDoneTasks, linkTaskIssue, promoteTask, resolveTaskItem } from "./data-tasks.js";
12
- import { buildTaskIssueBody, createGithubIssueForTask, parseGithubIssueUrl, resolveProjectGithubRepo } from "./tasks-github.js";
13
- import { PROJECT_HOOK_EVENTS, PROJECT_OWNERSHIP_MODES, isProjectHookEnabled, parseProjectOwnershipMode, readProjectConfig, writeProjectConfig, writeProjectHookConfig, } from "./project-config.js";
14
- import { addFinding, removeFinding } from "./core-finding.js";
15
- import { supersedeFinding, retractFinding, resolveFindingContradiction } from "./finding-lifecycle.js";
16
- import { readCustomHooks, getHookTarget, HOOK_EVENT_VALUES, validateCustomHookCommand } from "./hooks.js";
17
- import { runtimeFile } from "./shared.js";
4
+ import { expandHomePath, findArchivedProjectNameCaseInsensitive, findProjectNameCaseInsensitive, getPhrenPath, getProjectDirs, homePath, hookConfigPath, normalizeProjectNameForCreate, readRootManifest, } from "../shared.js";
5
+ import { isValidProjectName, errorMessage } from "../utils.js";
6
+ import { logger } from "../logger.js";
7
+ import { readInstallPreferences, writeInstallPreferences } from "../init/preferences.js";
8
+ import { buildSkillManifest, findLocalSkill, findSkill, getAllSkills } from "../skill/registry.js";
9
+ import { detectSkillCollisions } from "../link/skills.js";
10
+ import { setSkillEnabledAndSync, syncSkillLinksForScope } from "../skill/files.js";
11
+ import { findProjectDir } from "../project-locator.js";
12
+ import { TASK_FILE_ALIASES, addTask, completeTask, updateTask, reorderTask, pinTask, removeTask, workNextTask, tidyDoneTasks, linkTaskIssue, promoteTask, resolveTaskItem } from "../data/tasks.js";
13
+ import { buildTaskIssueBody, createGithubIssueForTask, parseGithubIssueUrl, resolveProjectGithubRepo } from "../task/github.js";
14
+ import { PROJECT_HOOK_EVENTS, PROJECT_OWNERSHIP_MODES, isProjectHookEnabled, parseProjectOwnershipMode, readProjectConfig, writeProjectConfig, writeProjectHookConfig, } from "../project-config.js";
15
+ import { addFinding, removeFinding } from "../core/finding.js";
16
+ import { supersedeFinding, retractFinding, resolveFindingContradiction } from "../finding/lifecycle.js";
17
+ import { readCustomHooks, getHookTarget, HOOK_EVENT_VALUES, validateCustomHookCommand } from "../hooks.js";
18
+ import { runtimeFile } from "../shared.js";
18
19
  const HOOK_TOOLS = ["claude", "copilot", "cursor", "codex"];
19
20
  function printSkillsUsage() {
20
21
  console.log("Usage:");
@@ -78,7 +79,7 @@ function openInEditor(filePath) {
78
79
  }
79
80
  catch (err) {
80
81
  if ((process.env.PHREN_DEBUG))
81
- process.stderr.write(`[phren] openInEditor: ${errorMessage(err)}\n`);
82
+ logger.debug("cli-namespaces", `openInEditor: ${errorMessage(err)}`);
82
83
  console.error(`Editor "${editor}" failed. Set $EDITOR to your preferred editor.`);
83
84
  process.exit(1);
84
85
  }
@@ -147,7 +148,7 @@ export function handleSkillsNamespace(args, profile) {
147
148
  }
148
149
  catch (err) {
149
150
  if ((process.env.PHREN_DEBUG))
150
- process.stderr.write(`[phren] skill add symlinkFailed: ${errorMessage(err)}\n`);
151
+ logger.debug("cli-namespaces", `skill add symlinkFailed: ${errorMessage(err)}`);
151
152
  fs.copyFileSync(source, dest);
152
153
  console.log(`Copied skill ${fileName} into ${project}.`);
153
154
  }
@@ -457,7 +458,7 @@ export function handleDetectSkills(args, profile) {
457
458
  }
458
459
  catch (err) {
459
460
  if ((process.env.PHREN_DEBUG))
460
- process.stderr.write(`[phren] skillList lstat: ${errorMessage(err)}\n`);
461
+ logger.debug("cli-namespaces", `skillList lstat: ${errorMessage(err)}`);
461
462
  }
462
463
  const name = entry.replace(/\.md$/, "");
463
464
  if (trackedSkills.has(name))
@@ -666,7 +667,7 @@ export async function handleProjectsNamespace(args, profile) {
666
667
  console.error(`Project "${name}" not found.`);
667
668
  process.exit(1);
668
669
  }
669
- const { readFindings, readTasks, resolveTaskFilePath, TASKS_FILENAME } = await import("./data-access.js");
670
+ const { readFindings, readTasks, resolveTaskFilePath, TASKS_FILENAME } = await import("../data/access.js");
670
671
  const exported = { project: name, exportedAt: new Date().toISOString(), version: 1 };
671
672
  const summaryPath = path.join(projectDir, "summary.md");
672
673
  if (fs.existsSync(summaryPath))
@@ -721,7 +722,7 @@ export async function handleProjectsNamespace(args, profile) {
721
722
  console.error("Invalid import payload: missing project field.");
722
723
  process.exit(1);
723
724
  }
724
- const { TASKS_FILENAME } = await import("./data-access.js");
725
+ const { TASKS_FILENAME } = await import("../data/access.js");
725
726
  const phrenPath = getPhrenPath();
726
727
  const projectName = normalizeProjectNameForCreate(String(decoded.project));
727
728
  if (!isValidProjectName(projectName)) {
@@ -874,7 +875,7 @@ function handleProjectsList(profile) {
874
875
  }
875
876
  catch (err) {
876
877
  if ((process.env.PHREN_DEBUG))
877
- process.stderr.write(`[phren] projects list readdir: ${errorMessage(err)}\n`);
878
+ logger.debug("cli-namespaces", `projects list readdir: ${errorMessage(err)}`);
878
879
  dirFiles = new Set();
879
880
  }
880
881
  const tags = [];
@@ -917,7 +918,7 @@ async function handleProjectsRemove(name, profile) {
917
918
  }
918
919
  catch (err) {
919
920
  if ((process.env.PHREN_DEBUG))
920
- process.stderr.write(`[phren] projects remove countFiles: ${errorMessage(err)}\n`);
921
+ logger.debug("cli-namespaces", `projects remove countFiles: ${errorMessage(err)}`);
921
922
  }
922
923
  const readline = await import("readline");
923
924
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -956,7 +957,7 @@ export async function handleTaskNamespace(args) {
956
957
  }
957
958
  if (subcommand === "list") {
958
959
  // Delegate to the cross-project task view (same as `phren tasks`)
959
- const { handleTaskView } = await import("./cli-ops.js");
960
+ const { handleTaskView } = await import("./ops.js");
960
961
  return handleTaskView(args[1] || "default");
961
962
  }
962
963
  if (subcommand === "add") {
@@ -1321,7 +1322,7 @@ export async function handleFindingNamespace(args) {
1321
1322
  console.error("Usage: phren finding list <project>");
1322
1323
  process.exit(1);
1323
1324
  }
1324
- const { readFindings } = await import("./data-access.js");
1325
+ const { readFindings } = await import("../data/access.js");
1325
1326
  const result = readFindings(getPhrenPath(), project);
1326
1327
  if (!result.ok) {
1327
1328
  console.error(result.error);
@@ -1441,7 +1442,7 @@ export async function handleFindingNamespace(args) {
1441
1442
  const project = args[1];
1442
1443
  const phrenPath = getPhrenPath();
1443
1444
  const RESERVED_DIRS = new Set(["global", ".runtime", ".sessions", ".config"]);
1444
- const { readFindings } = await import("./data-access.js");
1445
+ const { readFindings } = await import("../data/access.js");
1445
1446
  const projects = project
1446
1447
  ? [project]
1447
1448
  : fs.readdirSync(phrenPath, { withFileTypes: true })
@@ -1,13 +1,13 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
3
  import { execFileSync } from "child_process";
4
- import { EXEC_TIMEOUT_MS, findProjectNameCaseInsensitive, getPhrenPath, normalizeProjectNameForCreate, } from "./shared.js";
5
- import { isValidProjectName, errorMessage } from "./utils.js";
6
- import { readTasksAcrossProjects, TASKS_FILENAME } from "./data-access.js";
7
- import { applyGravity } from "./data-tasks.js";
8
- import { buildIndex, queryRows } from "./shared-index.js";
9
- import { resolveSubprocessArgs } from "./cli-hooks.js";
10
- import { listAllSessions, getSessionArtifacts } from "./mcp-session.js";
4
+ import { EXEC_TIMEOUT_MS, findProjectNameCaseInsensitive, getPhrenPath, normalizeProjectNameForCreate, } from "../shared.js";
5
+ import { isValidProjectName, errorMessage } from "../utils.js";
6
+ import { readTasksAcrossProjects, TASKS_FILENAME } from "../data/access.js";
7
+ import { applyGravity } from "../data/tasks.js";
8
+ import { buildIndex, queryRows } from "../shared/index.js";
9
+ import { resolveSubprocessArgs } from "./hooks.js";
10
+ import { listAllSessions, getSessionArtifacts } from "../tools/session.js";
11
11
  export function handleTaskView(profile) {
12
12
  const docs = readTasksAcrossProjects(getPhrenPath(), profile);
13
13
  if (!docs.length) {
@@ -100,8 +100,8 @@ export function handleSessionsView(args) {
100
100
  console.log(`\n${sessions.length} session(s). Use \`phren sessions <id>\` to drill into one.`);
101
101
  }
102
102
  export async function handleQuickstart() {
103
- const { runInit } = await import("./init.js");
104
- const { runLink } = await import("./link.js");
103
+ const { runInit } = await import("../init/init.js");
104
+ const { runLink } = await import("../link/link.js");
105
105
  const dirBasename = path.basename(process.cwd());
106
106
  const readline = await import("readline");
107
107
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -1,9 +1,10 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { runtimeFile } from "./shared.js";
4
- import { buildIndex, extractSnippet, queryDocRows, queryRows, queryEntityLinks, queryDocBySourceKey, logEntityMiss } from "./shared-index.js";
5
- import { buildFtsQueryVariants, errorMessage, isValidProjectName } from "./utils.js";
6
- import { keywordFallbackSearch } from "./core-search.js";
3
+ import { runtimeFile } from "../shared.js";
4
+ import { buildIndex, extractSnippet, queryDocRows, queryRows, queryEntityLinks, queryDocBySourceKey, logEntityMiss } from "../shared/index.js";
5
+ import { buildFtsQueryVariants, errorMessage, isValidProjectName } from "../utils.js";
6
+ import { logger } from "../logger.js";
7
+ import { keywordFallbackSearch } from "../core/search.js";
7
8
  const MAX_HISTORY = 20;
8
9
  const SEARCH_TYPE_ALIASES = {
9
10
  skills: "skill",
@@ -35,7 +36,7 @@ export function readSearchHistory(phrenPath) {
35
36
  }
36
37
  catch (err) {
37
38
  if ((process.env.PHREN_DEBUG))
38
- process.stderr.write(`[phren] readSearchHistory: ${errorMessage(err)}\n`);
39
+ logger.debug("cli-search", `readSearchHistory: ${errorMessage(err)}`);
39
40
  return [];
40
41
  }
41
42
  }
@@ -249,12 +250,12 @@ export async function runSearch(opts, phrenPath, profile) {
249
250
  if (!rows) {
250
251
  if (opts.query) {
251
252
  try {
252
- const { logSearchMiss } = await import("./mcp-search.js");
253
+ const { logSearchMiss } = await import("../tools/search.js");
253
254
  logSearchMiss(phrenPath, opts.query, opts.project);
254
255
  }
255
256
  catch (err) {
256
257
  if ((process.env.PHREN_DEBUG))
257
- process.stderr.write(`[phren] search logSearchMiss: ${errorMessage(err)}\n`);
258
+ logger.debug("cli-search", `search logSearchMiss: ${errorMessage(err)}`);
258
259
  }
259
260
  }
260
261
  const scope = [