@phren/cli 0.0.28 → 0.0.33

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 (153) 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} +25 -21
  7. package/mcp/dist/{cli.js → cli/cli.js} +13 -13
  8. package/mcp/dist/{cli-config.js → cli/config.js} +12 -12
  9. package/mcp/dist/{cli-extract.js → cli/extract.js} +8 -8
  10. package/mcp/dist/{cli-govern.js → cli/govern.js} +28 -17
  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} +58 -117
  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} +12 -11
  21. package/mcp/dist/cli-hooks-git.js +243 -0
  22. package/mcp/dist/cli-hooks-prompt.js +323 -0
  23. package/mcp/dist/cli-hooks-session-handlers.js +337 -0
  24. package/mcp/dist/cli-hooks-stop.js +519 -0
  25. package/mcp/dist/{content-archive.js → content/archive.js} +16 -29
  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} +41 -20
  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} +142 -15
  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 +11 -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} +13 -7
  41. package/mcp/dist/governance/audit.js +30 -0
  42. package/mcp/dist/{governance-locks.js → governance/locks.js} +14 -9
  43. package/mcp/dist/{governance-policy.js → governance/policy.js} +23 -12
  44. package/mcp/dist/{governance-rbac.js → governance/rbac.js} +4 -4
  45. package/mcp/dist/{governance-scores.js → governance/scores.js} +10 -11
  46. package/mcp/dist/hooks.js +53 -37
  47. package/mcp/dist/index-query.js +4 -1
  48. package/mcp/dist/index.js +54 -30
  49. package/mcp/dist/{init-config.js → init/config.js} +6 -6
  50. package/mcp/dist/{init.js → init/init.js} +80 -69
  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} +4 -4
  54. package/mcp/dist/init-bootstrap.js +21 -0
  55. package/mcp/dist/init-detect.js +38 -0
  56. package/mcp/dist/init-env.js +114 -0
  57. package/mcp/dist/init-fresh.js +234 -0
  58. package/mcp/dist/init-hooks.js +26 -0
  59. package/mcp/dist/init-mcp.js +65 -0
  60. package/mcp/dist/init-modes.js +135 -0
  61. package/mcp/dist/init-npm.js +37 -0
  62. package/mcp/dist/init-project-local.js +99 -0
  63. package/mcp/dist/init-semantic.js +48 -0
  64. package/mcp/dist/init-types.js +1 -0
  65. package/mcp/dist/init-uninstall.js +504 -0
  66. package/mcp/dist/init-update.js +96 -0
  67. package/mcp/dist/init-walkthrough.js +524 -0
  68. package/mcp/dist/{link-checksums.js → link/checksums.js} +5 -5
  69. package/mcp/dist/{link-context.js → link/context.js} +4 -4
  70. package/mcp/dist/{link-doctor.js → link/doctor.js} +20 -22
  71. package/mcp/dist/{link.js → link/link.js} +26 -31
  72. package/mcp/dist/{link-skills.js → link/skills.js} +10 -10
  73. package/mcp/dist/logger.js +11 -3
  74. package/mcp/dist/package-metadata.js +1 -1
  75. package/mcp/dist/phren-art.js +4 -126
  76. package/mcp/dist/phren-paths.js +30 -12
  77. package/mcp/dist/proactivity.js +3 -3
  78. package/mcp/dist/profile-store.js +5 -6
  79. package/mcp/dist/project-config.js +2 -2
  80. package/mcp/dist/project-topics.js +17 -47
  81. package/mcp/dist/provider-adapters.js +1 -1
  82. package/mcp/dist/query-correlation.js +1 -1
  83. package/mcp/dist/runtime-profile.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} +28 -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} +19 -42
  90. package/mcp/dist/shared/governance.js +4 -0
  91. package/mcp/dist/{shared-index.js → shared/index.js} +105 -132
  92. package/mcp/dist/{shared-ollama.js → shared/ollama.js} +25 -7
  93. package/mcp/dist/shared/process.js +24 -0
  94. package/mcp/dist/{shared-retrieval.js → shared/retrieval.js} +22 -24
  95. package/mcp/dist/{shared-search-fallback.js → shared/search-fallback.js} +18 -20
  96. package/mcp/dist/{shared-sqljs.js → shared/sqljs.js} +3 -3
  97. package/mcp/dist/{shared-vector-index.js → shared/vector-index.js} +3 -3
  98. package/mcp/dist/shared.js +6 -60
  99. package/mcp/dist/{shell-entry.js → shell/entry.js} +6 -6
  100. package/mcp/dist/{shell-input.js → shell/input.js} +13 -13
  101. package/mcp/dist/{shell-palette.js → shell/palette.js} +3 -3
  102. package/mcp/dist/{shell-render.js → shell/render.js} +2 -2
  103. package/mcp/dist/{shell.js → shell/shell.js} +11 -11
  104. package/mcp/dist/{shell-state-store.js → shell/state-store.js} +5 -5
  105. package/mcp/dist/{shell-view-list.js → shell/view-list.js} +1 -1
  106. package/mcp/dist/{shell-view.js → shell/view.js} +13 -13
  107. package/mcp/dist/{skill-files.js → skill/files.js} +9 -9
  108. package/mcp/dist/{skill-registry.js → skill/registry.js} +5 -5
  109. package/mcp/dist/{skill-state.js → skill/state.js} +1 -4
  110. package/mcp/dist/startup-embedding.js +2 -2
  111. package/mcp/dist/status.js +15 -14
  112. package/mcp/dist/{tasks-github.js → task/github.js} +3 -2
  113. package/mcp/dist/{task-hygiene.js → task/hygiene.js} +4 -4
  114. package/mcp/dist/{task-lifecycle.js → task/lifecycle.js} +8 -13
  115. package/mcp/dist/telemetry.js +3 -4
  116. package/mcp/dist/tool-registry.js +29 -17
  117. package/mcp/dist/tools/config.js +530 -0
  118. package/mcp/dist/{mcp-data.js → tools/data.js} +8 -10
  119. package/mcp/dist/{mcp-extract-facts.js → tools/extract-facts.js} +6 -6
  120. package/mcp/dist/{mcp-extract.js → tools/extract.js} +6 -6
  121. package/mcp/dist/tools/finding.js +584 -0
  122. package/mcp/dist/{mcp-graph.js → tools/graph.js} +11 -14
  123. package/mcp/dist/{mcp-hooks.js → tools/hooks.js} +6 -6
  124. package/mcp/dist/{mcp-memory.js → tools/memory.js} +5 -5
  125. package/mcp/dist/tools/ops.js +468 -0
  126. package/mcp/dist/tools/search.js +672 -0
  127. package/mcp/dist/{mcp-session.js → tools/session.js} +51 -25
  128. package/mcp/dist/{mcp-skills.js → tools/skills.js} +42 -35
  129. package/mcp/dist/{mcp-tasks.js → tools/tasks.js} +155 -282
  130. package/mcp/dist/{memory-ui-data.js → ui/data.js} +31 -17
  131. package/mcp/dist/{memory-ui.js → ui/memory-ui.js} +3 -3
  132. package/mcp/dist/{memory-ui-page.js → ui/page.js} +5 -7
  133. package/mcp/dist/ui/server.js +1024 -0
  134. package/mcp/dist/update.js +2 -2
  135. package/mcp/dist/utils.js +63 -19
  136. package/package.json +2 -2
  137. package/scripts/preuninstall.mjs +31 -0
  138. package/starter/global/CLAUDE.md +3 -2
  139. package/mcp/dist/governance-audit.js +0 -22
  140. package/mcp/dist/mcp-config.js +0 -551
  141. package/mcp/dist/mcp-finding.js +0 -594
  142. package/mcp/dist/mcp-ops.js +0 -363
  143. package/mcp/dist/mcp-search.js +0 -668
  144. package/mcp/dist/memory-ui-server.js +0 -1411
  145. package/mcp/dist/shared-governance.js +0 -4
  146. /package/mcp/dist/{content-metadata.js → content/metadata.js} +0 -0
  147. /package/mcp/dist/{shared-stemmer.js → shared/stemmer.js} +0 -0
  148. /package/mcp/dist/{shell-types.js → shell/types.js} +0 -0
  149. /package/mcp/dist/{mcp-types.js → tools/types.js} +0 -0
  150. /package/mcp/dist/{memory-ui-assets.js → ui/assets.js} +0 -0
  151. /package/mcp/dist/{memory-ui-graph.js → ui/graph.js} +0 -0
  152. /package/mcp/dist/{memory-ui-scripts.js → ui/scripts.js} +0 -0
  153. /package/mcp/dist/{memory-ui-styles.js → ui/styles.js} +0 -0
@@ -4,16 +4,17 @@
4
4
  */
5
5
  import * as fs from "fs";
6
6
  import * as path from "path";
7
- import { canonicalTaskFilePath, listProjectCards, readTasks, readFindings, readReviewQueue, readRuntimeHealth, resolveTaskFilePath, } from "./data-access.js";
8
- import { style, badge, separator, stripAnsi, truncateLine, renderWidth, wrapSegments, lineViewport, shellHelpText, gradient, } from "./shell-render.js";
9
- import { formatSelectableLine, viewportWithStatus, } from "./shell-view-list.js";
10
- import { SUB_VIEWS, TAB_ICONS, } from "./shell-types.js";
11
- import { tasksByFilter, queueByFilter, } from "./shell-palette.js";
12
- import { listMachines, listProfiles, } from "./data-access.js";
13
- import { readInstallPreferences } from "./init-preferences.js";
14
- import { isProjectHookEnabled, readProjectConfig } from "./project-config.js";
15
- import { getScopedSkills } from "./skill-registry.js";
16
- import { errorMessage } from "./utils.js";
7
+ import { canonicalTaskFilePath, listProjectCards, readTasks, readFindings, readReviewQueue, readRuntimeHealth, resolveTaskFilePath, } from "../data/access.js";
8
+ import { style, badge, separator, stripAnsi, truncateLine, renderWidth, wrapSegments, lineViewport, shellHelpText, gradient, } from "./render.js";
9
+ import { formatSelectableLine, viewportWithStatus, } from "./view-list.js";
10
+ import { SUB_VIEWS, TAB_ICONS, } from "./types.js";
11
+ import { tasksByFilter, queueByFilter, } from "./palette.js";
12
+ import { listMachines, listProfiles, } from "../data/access.js";
13
+ import { readInstallPreferences } from "../init/preferences.js";
14
+ import { isProjectHookEnabled, readProjectConfig } from "../project-config.js";
15
+ import { getScopedSkills } from "../skill/registry.js";
16
+ import { errorMessage } from "../utils.js";
17
+ import { logger } from "../logger.js";
17
18
  // ── Tab bar ────────────────────────────────────────────────────────────────
18
19
  function renderTabBar(state) {
19
20
  const cols = renderWidth();
@@ -249,8 +250,7 @@ function parseSubsections(taskPath, project, cache) {
249
250
  }
250
251
  }
251
252
  catch (err) {
252
- if ((process.env.PHREN_DEBUG))
253
- process.stderr.write(`[phren] buildSubsectionMap: ${errorMessage(err)}\n`);
253
+ logger.debug("shell-view", `buildSubsectionMap: ${errorMessage(err)}`);
254
254
  }
255
255
  const newCache = { project, map };
256
256
  return { map, cache: newCache };
@@ -564,7 +564,7 @@ function renderHooksView(ctx, cursor, height) {
564
564
  ctx.setScroll(vp.scrollStart);
565
565
  return vp.lines;
566
566
  }
567
- export { writeInstallPreferences } from "./init-preferences.js";
567
+ export { writeInstallPreferences } from "../init/preferences.js";
568
568
  // ── Machines/Profiles view ─────────────────────────────────────────────────
569
569
  function renderMachinesView(phrenPath) {
570
570
  const machines = listMachines(phrenPath);
@@ -1,11 +1,12 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { homePath } from "./shared.js";
4
- import { findProjectDir } from "./project-locator.js";
5
- import { buildSkillManifest } from "./skill-registry.js";
6
- import { setSkillEnabled } from "./skill-state.js";
7
- import { errorMessage } from "./utils.js";
8
- import { isManagedSymlink } from "./link-skills.js";
3
+ import { homePath } from "../shared.js";
4
+ import { findProjectDir } from "../project-locator.js";
5
+ import { buildSkillManifest } from "./registry.js";
6
+ import { setSkillEnabled } from "./state.js";
7
+ import { errorMessage } from "../utils.js";
8
+ import { isManagedSymlink } from "../link/skills.js";
9
+ import { logger } from "../logger.js";
9
10
  function normalizeSkillRemovalTarget(skillPath) {
10
11
  if (!skillPath)
11
12
  return skillPath;
@@ -44,9 +45,8 @@ function removeManagedSkillLink(dest, managedRoot) {
44
45
  fs.unlinkSync(dest);
45
46
  }
46
47
  catch (err) {
47
- if (err.code !== "ENOENT" && (process.env.PHREN_DEBUG)) {
48
- process.stderr.write(`[phren] removeManagedSkillLink: ${errorMessage(err)}\n`);
49
- }
48
+ if (err.code !== "ENOENT")
49
+ logger.debug("skill-files", `removeManagedSkillLink: ${errorMessage(err)}`);
50
50
  }
51
51
  }
52
52
  function writeSkillArtifacts(destDir, manifest) {
@@ -1,9 +1,9 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { getProjectDirs } from "./shared.js";
4
- import { parseSkillFrontmatter } from "./link-skills.js";
5
- import { isSkillEnabled } from "./skill-state.js";
6
- import { safeProjectPath } from "./utils.js";
3
+ import { getProjectDirs } from "../shared.js";
4
+ import { parseSkillFrontmatter } from "../link/skills.js";
5
+ import { isSkillEnabled } from "./state.js";
6
+ import { safeProjectPath } from "../utils.js";
7
7
  function normalizeCommand(raw, fallbackName) {
8
8
  const value = typeof raw === "string" && raw.trim() ? raw.trim() : `/${fallbackName}`;
9
9
  return value.startsWith("/") ? value : `/${value}`;
@@ -223,7 +223,7 @@ export function getAllSkills(phrenPath, profile) {
223
223
  }
224
224
  return all;
225
225
  }
226
- export function getLocalSkills(phrenPath, scope) {
226
+ function getLocalSkills(phrenPath, scope) {
227
227
  if (scope.toLowerCase() === "global")
228
228
  return getGlobalSkills(phrenPath);
229
229
  return getProjectLocalSkills(phrenPath, scope);
@@ -1,4 +1,4 @@
1
- import { readInstallPreferences, writeInstallPreferences } from "./init-preferences.js";
1
+ import { readInstallPreferences, writeInstallPreferences } from "../init/preferences.js";
2
2
  function skillStateKey(scope, name) {
3
3
  return `${scope}:${name.replace(/\.md$/i, "").trim().toLowerCase()}`;
4
4
  }
@@ -23,6 +23,3 @@ export function setSkillEnabled(phrenPath, scope, name, enabled) {
23
23
  disabledSkills: Object.keys(disabled).length ? disabled : undefined,
24
24
  });
25
25
  }
26
- export function getSkillStateKey(scope, name) {
27
- return skillStateKey(scope, name);
28
- }
@@ -1,10 +1,10 @@
1
1
  import { debugLog } from "./shared.js";
2
- import { decodeStringRow, queryRows } from "./shared-index.js";
2
+ import { decodeStringRow, queryRows } from "./shared/index.js";
3
3
  import { errorMessage } from "./utils.js";
4
4
  /** Throttle delay between embedding requests in the background embed loop. */
5
5
  const BACKGROUND_EMBED_THROTTLE_MS = 50;
6
6
  async function loadWarmupDeps() {
7
- const { checkOllamaAvailable, embedText, getEmbeddingModel, getOllamaUrl } = await import("./shared-ollama.js");
7
+ const { checkOllamaAvailable, embedText, getEmbeddingModel, getOllamaUrl } = await import("./shared/ollama.js");
8
8
  return {
9
9
  checkOllamaAvailable,
10
10
  embedText,
@@ -2,15 +2,16 @@ import * as fs from "fs";
2
2
  import * as path from "path";
3
3
  import { fileURLToPath } from "url";
4
4
  import { findPhrenPath, getProjectDirs, EXEC_TIMEOUT_QUICK_MS, debugLog, isRecord, hookConfigPath, homeDir, readRootManifest, } from "./shared.js";
5
- import { buildIndex, detectProject, findFtsCacheForPath, listIndexedDocumentPaths, queryRows } from "./shared-index.js";
6
- import { mergeConfig, getWorkflowPolicy } from "./shared-governance.js";
7
- import { getMcpEnabledPreference, getHooksEnabledPreference } from "./init.js";
5
+ import { buildIndex, detectProject, findFtsCacheForPath, listIndexedDocumentPaths, queryRows } from "./shared/index.js";
6
+ import { mergeConfig, getWorkflowPolicy } from "./shared/governance.js";
7
+ import { getMcpEnabledPreference, getHooksEnabledPreference } from "./init/init.js";
8
8
  import { getTelemetrySummary } from "./telemetry.js";
9
9
  import { runGit as runGitShared, errorMessage } from "./utils.js";
10
- import { readRuntimeHealth, resolveTaskFilePath } from "./data-access.js";
10
+ import { logger } from "./logger.js";
11
+ import { readRuntimeHealth, resolveTaskFilePath } from "./data/access.js";
11
12
  import { resolveRuntimeProfile } from "./runtime-profile.js";
12
13
  import { renderPhrenArt } from "./phren-art.js";
13
- import { RESET, BOLD, DIM, GREEN, YELLOW, RED, CYAN } from "./shell-render.js";
14
+ import { RESET, BOLD, DIM, GREEN, YELLOW, RED, CYAN } from "./shell/render.js";
14
15
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
16
  function readPackageVersion() {
16
17
  try {
@@ -20,7 +21,7 @@ function readPackageVersion() {
20
21
  }
21
22
  catch (err) {
22
23
  if ((process.env.PHREN_DEBUG))
23
- process.stderr.write(`[phren] readPackageVersion: ${errorMessage(err)}\n`);
24
+ logger.debug("status", `readPackageVersion: ${errorMessage(err)}`);
24
25
  return "unknown";
25
26
  }
26
27
  }
@@ -91,7 +92,7 @@ export async function runStatus() {
91
92
  }
92
93
  catch (err) {
93
94
  if ((process.env.PHREN_DEBUG))
94
- process.stderr.write(`[phren] statusConfig: ${errorMessage(err)}\n`);
95
+ logger.debug("status", `statusConfig: ${errorMessage(err)}`);
95
96
  }
96
97
  }
97
98
  // Phren path and config
@@ -125,7 +126,7 @@ export async function runStatus() {
125
126
  }
126
127
  catch (err) {
127
128
  if ((process.env.PHREN_DEBUG))
128
- process.stderr.write(`[phren] statusWorkspaceMcp parse: ${errorMessage(err)}\n`);
129
+ logger.debug("status", `statusWorkspaceMcp parse: ${errorMessage(err)}`);
129
130
  }
130
131
  }
131
132
  }
@@ -143,7 +144,7 @@ export async function runStatus() {
143
144
  }
144
145
  catch (err) {
145
146
  if ((process.env.PHREN_DEBUG))
146
- process.stderr.write(`[phren] statusHooks settingsParse: ${errorMessage(err)}\n`);
147
+ logger.debug("status", `statusHooks settingsParse: ${errorMessage(err)}`);
147
148
  }
148
149
  }
149
150
  }
@@ -174,15 +175,15 @@ export async function runStatus() {
174
175
  }
175
176
  catch (err) {
176
177
  if ((process.env.PHREN_DEBUG))
177
- process.stderr.write(`[phren] statusFtsIndex: ${errorMessage(err)}\n`);
178
+ logger.debug("status", `statusFtsIndex: ${errorMessage(err)}`);
178
179
  }
179
180
  const ftsLabel = ftsIndexOk
180
181
  ? `${GREEN}ok${RESET} ${DIM}(${ftsIndexSize > 0 ? `${(ftsIndexSize / 1024).toFixed(0)} KB` : `${ftsDocCount ?? 0} docs`})${RESET}`
181
182
  : `${YELLOW}not built${RESET} ${DIM}(run a search to build)${RESET}`;
182
183
  console.log(` ${DIM}fts${RESET} ${ftsLabel}`);
183
184
  try {
184
- const { getOllamaUrl, checkOllamaAvailable, checkModelAvailable, getEmbeddingModel } = await import("./shared-ollama.js");
185
- const { getEmbeddingCache, formatEmbeddingCoverage } = await import("./shared-embedding-cache.js");
185
+ const { getOllamaUrl, checkOllamaAvailable, checkModelAvailable, getEmbeddingModel } = await import("./shared/ollama.js");
186
+ const { getEmbeddingCache, formatEmbeddingCoverage } = await import("./shared/embedding-cache.js");
186
187
  const ollamaUrl = getOllamaUrl();
187
188
  if (!ollamaUrl) {
188
189
  console.log(` ${DIM}semantic${RESET} ${DIM}disabled (optional)${RESET}`);
@@ -209,7 +210,7 @@ export async function runStatus() {
209
210
  }
210
211
  catch (err) {
211
212
  if ((process.env.PHREN_DEBUG))
212
- process.stderr.write(`[phren] statusSemantic: ${errorMessage(err)}\n`);
213
+ logger.debug("status", `statusSemantic: ${errorMessage(err)}`);
213
214
  }
214
215
  // Agent integration status
215
216
  function hasPhrenEntry(filePath) {
@@ -221,7 +222,7 @@ export async function runStatus() {
221
222
  }
222
223
  catch (err) {
223
224
  if ((process.env.PHREN_DEBUG))
224
- process.stderr.write(`[phren] hasPhrenEntry: ${errorMessage(err)}\n`);
225
+ logger.debug("status", `hasPhrenEntry: ${errorMessage(err)}`);
225
226
  return false;
226
227
  }
227
228
  }
@@ -1,8 +1,8 @@
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, phrenErr, phrenOk, PhrenError } from "./shared.js";
5
- import { errorMessage, resolveExecCommand } from "./utils.js";
4
+ import { EXEC_TIMEOUT_MS, phrenErr, phrenOk, PhrenError } from "../shared.js";
5
+ import { errorMessage, resolveExecCommand } from "../utils.js";
6
6
  const GITHUB_REPO_URL = /https:\/\/github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)(?:\/|\b|$)/;
7
7
  const GITHUB_ISSUE_URL = /https:\/\/github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)\/issues\/(\d+)(?:[?#][^\s]*)?$/;
8
8
  export function parseGithubIssueUrl(url) {
@@ -16,6 +16,7 @@ export function parseGithubIssueUrl(url) {
16
16
  url: match[0],
17
17
  };
18
18
  }
19
+ /** @internal Exported for tests. */
19
20
  export function extractGithubRepoFromText(content) {
20
21
  const match = content.match(GITHUB_REPO_URL);
21
22
  return match?.[1];
@@ -1,7 +1,8 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { isTaskFileName, readTasks } from "./data-tasks.js";
4
- import { STOP_WORDS, extractKeywords, errorMessage } from "./utils.js";
3
+ import { isTaskFileName, readTasks } from "../data/tasks.js";
4
+ import { STOP_WORDS, extractKeywords, errorMessage } from "../utils.js";
5
+ import { logger } from "../logger.js";
5
6
  const TEXT_EXTENSIONS = new Set([
6
7
  ".cjs",
7
8
  ".css",
@@ -141,8 +142,7 @@ function collectCorpus(root) {
141
142
  texts.push(fs.readFileSync(fullPath, "utf8").slice(0, MAX_TEXT_BYTES).toLowerCase());
142
143
  }
143
144
  catch (err) {
144
- if ((process.env.PHREN_DEBUG))
145
- process.stderr.write(`[phren] task hygiene read ${fullPath}: ${errorMessage(err)}\n`);
145
+ logger.debug("task-hygiene", `task hygiene read ${fullPath}: ${errorMessage(err)}`);
146
146
  }
147
147
  if (filesSeen >= MAX_FILES_PER_ROOT)
148
148
  break;
@@ -1,11 +1,11 @@
1
1
  import * as fs from "fs";
2
- import { addTask, completeTask, readTasks, resolveTaskItem, updateTask, } from "./data-access.js";
3
- import { parseGithubIssueUrl, resolveProjectGithubRepo } from "./tasks-github.js";
4
- import { getProactivityLevelForTask, shouldAutoCaptureTaskForLevel, hasExecutionIntent, hasDiscoveryIntent, hasSuppressTaskIntent, hasCodeChangeContext } from "./proactivity.js";
5
- import { getWorkflowPolicy } from "./shared-governance.js";
6
- import { debugLog, sessionMarker } from "./shared.js";
7
- import { errorMessage } from "./utils.js";
8
- import { incrementSessionTasksCompleted } from "./mcp-session.js";
2
+ import { addTask, completeTask, readTasks, resolveTaskItem, updateTask, } from "../data/access.js";
3
+ import { parseGithubIssueUrl, resolveProjectGithubRepo } from "./github.js";
4
+ import { getProactivityLevelForTask, shouldAutoCaptureTaskForLevel, hasExecutionIntent, hasDiscoveryIntent, hasSuppressTaskIntent, hasCodeChangeContext } from "../proactivity.js";
5
+ import { getWorkflowPolicy } from "../shared/governance.js";
6
+ import { debugLog, sessionMarker } from "../shared.js";
7
+ import { errorMessage } from "../utils.js";
8
+ import { incrementSessionTasksCompleted } from "../tools/session.js";
9
9
  const ACTION_PREFIX_RE = /^(?:please\s+|can you\s+|could you\s+|would you\s+|i want you to\s+|i want to\s+|let(?:'|’)s\s+|lets\s+|help me\s+)/i;
10
10
  const EXPLICIT_TASK_PREFIX_RE = /^(?:add(?:\s+(?:this|that|it))?\s+(?:to\s+(?:the\s+)?)?(?:task|todo(?:\s+list)?|task(?:\s+list)?)|add\s+(?:a\s+)?task|put(?:\s+(?:this|that|it))?\s+(?:in|on)\s+(?:the\s+)?(?:task|todo(?:\s+list)?|task(?:\s+list)?))\s*(?::|-|,)?\s*/i;
11
11
  const NON_ACTIONABLE_RE = /\b(brainstorm|idea|ideas|maybe|what if|should we|could we|would it make sense|question|explain|why is|how does)\b/i;
@@ -80,7 +80,7 @@ function clearTaskSessionState(phrenPath, sessionId) {
80
80
  debugLog(`task lifecycle clear session ${sessionId}: ${errorMessage(err)}`);
81
81
  }
82
82
  }
83
- export function getTaskMode(phrenPath) {
83
+ function getTaskMode(phrenPath) {
84
84
  return getWorkflowPolicy(phrenPath).taskMode;
85
85
  }
86
86
  function isActionablePrompt(prompt, intent) {
@@ -330,11 +330,6 @@ export function finalizeTaskSession(args) {
330
330
  return;
331
331
  }
332
332
  }
333
- export function clearTaskSession(phrenPath, sessionId) {
334
- if (!sessionId)
335
- return;
336
- clearTaskSessionState(phrenPath, sessionId);
337
- }
338
333
  /**
339
334
  * Return the active TaskItem tracked for a session+project, if any.
340
335
  * Used by mcp-finding.ts to link findings to active tasks.
@@ -2,6 +2,7 @@ import * as fs from "fs";
2
2
  import * as path from "path";
3
3
  import { runtimeDir } from "./shared.js";
4
4
  import { errorMessage } from "./utils.js";
5
+ import { logger } from "./logger.js";
5
6
  // In-memory buffers keyed by phrenPath to batch disk writes
6
7
  // Keeping per-path buffers avoids silently losing events when the active path changes.
7
8
  const buffers = new Map();
@@ -26,8 +27,7 @@ function loadFromDisk(phrenPath) {
26
27
  };
27
28
  }
28
29
  catch (err) {
29
- if ((process.env.PHREN_DEBUG))
30
- process.stderr.write(`[phren] telemetry loadFromDisk: ${errorMessage(err)}\n`);
30
+ logger.debug("telemetry loadFromDisk", errorMessage(err));
31
31
  return defaults;
32
32
  }
33
33
  }
@@ -58,8 +58,7 @@ function flushTelemetryForPath(phrenPath) {
58
58
  fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
59
59
  }
60
60
  catch (err) {
61
- if ((process.env.PHREN_DEBUG))
62
- process.stderr.write(`[phren] telemetry flush: ${errorMessage(err)}\n`);
61
+ logger.debug("telemetry flush", errorMessage(err));
63
62
  }
64
63
  pendingCounts.set(phrenPath, 0);
65
64
  }
@@ -2,18 +2,18 @@ import * as fs from "fs";
2
2
  import * as path from "path";
3
3
  import { fileURLToPath } from "url";
4
4
  const CATEGORY_BY_MODULE = {
5
- "mcp-search": "Search and browse",
6
- "mcp-tasks": "Task management",
7
- "mcp-finding": "Finding capture",
8
- "mcp-memory": "Memory quality",
9
- "mcp-data": "Data management",
10
- "mcp-graph": "Fragments and graph",
11
- "mcp-session": "Session management",
12
- "mcp-ops": "Operations and review",
13
- "mcp-skills": "Skills management",
14
- "mcp-hooks": "Hooks management",
15
- "mcp-config": "Configuration",
16
- "mcp-extract": "Extraction",
5
+ "search": "Search and browse",
6
+ "tasks": "Task management",
7
+ "finding": "Finding capture",
8
+ "memory": "Memory quality",
9
+ "data": "Data management",
10
+ "graph": "Fragments and graph",
11
+ "session": "Session management",
12
+ "ops": "Operations and review",
13
+ "skills": "Skills management",
14
+ "hooks": "Hooks management",
15
+ "config": "Configuration",
16
+ "extract": "Extraction",
17
17
  };
18
18
  const MODULE_ORDER = Object.keys(CATEGORY_BY_MODULE);
19
19
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -45,7 +45,7 @@ function parseModuleTools(moduleName, source) {
45
45
  });
46
46
  }
47
47
  // Handle loop-registered tools: { tool: "name", ... } patterns followed by registerTool(action.tool, ...)
48
- const loopPattern = /for\s*\(const\s+(\w+)\s+of\s+\[([\s\S]*?)\]\s*(?:as\s+const\s*)?\)\s*\{\s*server\.registerTool\(\s*\1\.tool\s*,\s*\{([\s\S]*?)\}\s*,/g;
48
+ const loopPattern = /for\s*\(const\s+(\w+)\s+of\s+\[([\s\S]*?)\]\s*(?:as\s+const\s*)?\)\s*\{[\s\S]*?server\.registerTool\(\s*\1\.tool\s*,\s*\{([\s\S]*?)\}\s*,/g;
49
49
  for (const loopMatch of source.matchAll(loopPattern)) {
50
50
  const [, , itemsBlock, configBlock] = loopMatch;
51
51
  const itemPattern = /\{\s*tool:\s*"([^"]+)"[^}]*verb:\s*"([^"]+)"/g;
@@ -66,11 +66,23 @@ function parseModuleTools(moduleName, source) {
66
66
  export function getRegisteredTools() {
67
67
  const dir = sourceDir();
68
68
  const entries = [];
69
+ const toolsDir = path.join(dir, "tools");
69
70
  for (const moduleName of MODULE_ORDER) {
70
- const tsPath = path.join(dir, `${moduleName}.ts`);
71
- const jsPath = path.join(dir, `${moduleName}.js`);
72
- const sourcePath = fs.existsSync(tsPath) ? tsPath : jsPath;
73
- if (!fs.existsSync(sourcePath))
71
+ // Tool files may live in the tools/ subdirectory or alongside tool-registry.ts
72
+ let sourcePath;
73
+ for (const base of [toolsDir, dir]) {
74
+ const tsPath = path.join(base, `${moduleName}.ts`);
75
+ const jsPath = path.join(base, `${moduleName}.js`);
76
+ if (fs.existsSync(tsPath)) {
77
+ sourcePath = tsPath;
78
+ break;
79
+ }
80
+ if (fs.existsSync(jsPath)) {
81
+ sourcePath = jsPath;
82
+ break;
83
+ }
84
+ }
85
+ if (!sourcePath)
74
86
  continue;
75
87
  entries.push(...parseModuleTools(moduleName, fs.readFileSync(sourcePath, "utf8")));
76
88
  }