@phren/cli 0.0.1

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 (185) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +590 -0
  3. package/mcp/dist/capabilities/cli.js +61 -0
  4. package/mcp/dist/capabilities/index.js +15 -0
  5. package/mcp/dist/capabilities/mcp.js +61 -0
  6. package/mcp/dist/capabilities/types.js +57 -0
  7. package/mcp/dist/capabilities/vscode.js +61 -0
  8. package/mcp/dist/capabilities/web-ui.js +61 -0
  9. package/mcp/dist/cli-actions.js +302 -0
  10. package/mcp/dist/cli-config.js +580 -0
  11. package/mcp/dist/cli-extract.js +305 -0
  12. package/mcp/dist/cli-govern.js +371 -0
  13. package/mcp/dist/cli-graph.js +169 -0
  14. package/mcp/dist/cli-hooks-citations.js +44 -0
  15. package/mcp/dist/cli-hooks-context.js +56 -0
  16. package/mcp/dist/cli-hooks-globs.js +83 -0
  17. package/mcp/dist/cli-hooks-output.js +130 -0
  18. package/mcp/dist/cli-hooks-retrieval.js +2 -0
  19. package/mcp/dist/cli-hooks-session.js +1402 -0
  20. package/mcp/dist/cli-hooks.js +350 -0
  21. package/mcp/dist/cli-namespaces.js +989 -0
  22. package/mcp/dist/cli-ops.js +253 -0
  23. package/mcp/dist/cli-search.js +407 -0
  24. package/mcp/dist/cli.js +108 -0
  25. package/mcp/dist/content-archive.js +278 -0
  26. package/mcp/dist/content-citation.js +391 -0
  27. package/mcp/dist/content-dedup.js +622 -0
  28. package/mcp/dist/content-learning.js +472 -0
  29. package/mcp/dist/content-metadata.js +186 -0
  30. package/mcp/dist/content-validate.js +462 -0
  31. package/mcp/dist/core-finding.js +54 -0
  32. package/mcp/dist/core-project.js +36 -0
  33. package/mcp/dist/core-search.js +50 -0
  34. package/mcp/dist/data-access.js +400 -0
  35. package/mcp/dist/data-tasks.js +821 -0
  36. package/mcp/dist/embedding.js +344 -0
  37. package/mcp/dist/entrypoint.js +387 -0
  38. package/mcp/dist/finding-context.js +172 -0
  39. package/mcp/dist/finding-impact.js +181 -0
  40. package/mcp/dist/finding-journal.js +122 -0
  41. package/mcp/dist/finding-lifecycle.js +259 -0
  42. package/mcp/dist/governance-audit.js +22 -0
  43. package/mcp/dist/governance-locks.js +96 -0
  44. package/mcp/dist/governance-policy.js +648 -0
  45. package/mcp/dist/governance-scores.js +355 -0
  46. package/mcp/dist/hooks.js +449 -0
  47. package/mcp/dist/impact-scoring.js +22 -0
  48. package/mcp/dist/index-query.js +168 -0
  49. package/mcp/dist/index.js +205 -0
  50. package/mcp/dist/init-config.js +336 -0
  51. package/mcp/dist/init-preferences.js +62 -0
  52. package/mcp/dist/init-setup.js +1305 -0
  53. package/mcp/dist/init-shared.js +29 -0
  54. package/mcp/dist/init.js +1730 -0
  55. package/mcp/dist/link-checksums.js +62 -0
  56. package/mcp/dist/link-context.js +257 -0
  57. package/mcp/dist/link-doctor.js +591 -0
  58. package/mcp/dist/link-skills.js +212 -0
  59. package/mcp/dist/link.js +596 -0
  60. package/mcp/dist/logger.js +15 -0
  61. package/mcp/dist/machine-identity.js +38 -0
  62. package/mcp/dist/mcp-config.js +254 -0
  63. package/mcp/dist/mcp-data.js +315 -0
  64. package/mcp/dist/mcp-extract-facts.js +78 -0
  65. package/mcp/dist/mcp-extract.js +133 -0
  66. package/mcp/dist/mcp-finding.js +557 -0
  67. package/mcp/dist/mcp-graph.js +339 -0
  68. package/mcp/dist/mcp-hooks.js +256 -0
  69. package/mcp/dist/mcp-memory.js +58 -0
  70. package/mcp/dist/mcp-ops.js +328 -0
  71. package/mcp/dist/mcp-search.js +628 -0
  72. package/mcp/dist/mcp-session.js +651 -0
  73. package/mcp/dist/mcp-skills.js +189 -0
  74. package/mcp/dist/mcp-tasks.js +551 -0
  75. package/mcp/dist/mcp-types.js +7 -0
  76. package/mcp/dist/memory-ui-assets.js +6 -0
  77. package/mcp/dist/memory-ui-data.js +513 -0
  78. package/mcp/dist/memory-ui-graph.js +1910 -0
  79. package/mcp/dist/memory-ui-page.js +353 -0
  80. package/mcp/dist/memory-ui-scripts.js +1387 -0
  81. package/mcp/dist/memory-ui-server.js +1218 -0
  82. package/mcp/dist/memory-ui-styles.js +555 -0
  83. package/mcp/dist/memory-ui.js +9 -0
  84. package/mcp/dist/package-metadata.js +13 -0
  85. package/mcp/dist/phren-art.js +52 -0
  86. package/mcp/dist/phren-core.js +108 -0
  87. package/mcp/dist/phren-dotenv.js +67 -0
  88. package/mcp/dist/phren-paths.js +476 -0
  89. package/mcp/dist/proactivity.js +172 -0
  90. package/mcp/dist/profile-store.js +228 -0
  91. package/mcp/dist/project-config.js +85 -0
  92. package/mcp/dist/project-locator.js +25 -0
  93. package/mcp/dist/project-topics.js +1134 -0
  94. package/mcp/dist/provider-adapters.js +176 -0
  95. package/mcp/dist/runtime-profile.js +18 -0
  96. package/mcp/dist/session-checkpoints.js +131 -0
  97. package/mcp/dist/session-utils.js +68 -0
  98. package/mcp/dist/shared-content.js +8 -0
  99. package/mcp/dist/shared-embedding-cache.js +143 -0
  100. package/mcp/dist/shared-fragment-graph.js +456 -0
  101. package/mcp/dist/shared-governance.js +4 -0
  102. package/mcp/dist/shared-index.js +1334 -0
  103. package/mcp/dist/shared-ollama.js +192 -0
  104. package/mcp/dist/shared-paths.js +1 -0
  105. package/mcp/dist/shared-retrieval.js +796 -0
  106. package/mcp/dist/shared-search-fallback.js +375 -0
  107. package/mcp/dist/shared-sqljs.js +42 -0
  108. package/mcp/dist/shared-stemmer.js +171 -0
  109. package/mcp/dist/shared-vector-index.js +199 -0
  110. package/mcp/dist/shared.js +114 -0
  111. package/mcp/dist/shell-entry.js +209 -0
  112. package/mcp/dist/shell-input.js +943 -0
  113. package/mcp/dist/shell-palette.js +119 -0
  114. package/mcp/dist/shell-render.js +252 -0
  115. package/mcp/dist/shell-state-store.js +81 -0
  116. package/mcp/dist/shell-types.js +13 -0
  117. package/mcp/dist/shell-view-list.js +14 -0
  118. package/mcp/dist/shell-view.js +707 -0
  119. package/mcp/dist/shell.js +352 -0
  120. package/mcp/dist/skill-files.js +117 -0
  121. package/mcp/dist/skill-registry.js +279 -0
  122. package/mcp/dist/skill-state.js +28 -0
  123. package/mcp/dist/startup-embedding.js +57 -0
  124. package/mcp/dist/status.js +323 -0
  125. package/mcp/dist/synonyms.json +670 -0
  126. package/mcp/dist/task-hygiene.js +251 -0
  127. package/mcp/dist/task-lifecycle.js +347 -0
  128. package/mcp/dist/tasks-github.js +76 -0
  129. package/mcp/dist/telemetry.js +165 -0
  130. package/mcp/dist/test-global-setup.js +37 -0
  131. package/mcp/dist/tool-registry.js +104 -0
  132. package/mcp/dist/update.js +97 -0
  133. package/mcp/dist/utils.js +543 -0
  134. package/package.json +67 -0
  135. package/skills/README.md +7 -0
  136. package/skills/consolidate/SKILL.md +152 -0
  137. package/skills/discover/SKILL.md +175 -0
  138. package/skills/init/SKILL.md +216 -0
  139. package/skills/profiles/SKILL.md +121 -0
  140. package/skills/sync/SKILL.md +261 -0
  141. package/starter/README.md +74 -0
  142. package/starter/global/CLAUDE.md +89 -0
  143. package/starter/global/skills/humanize.md +30 -0
  144. package/starter/global/skills/pipeline.md +35 -0
  145. package/starter/global/skills/release.md +35 -0
  146. package/starter/machines.yaml +8 -0
  147. package/starter/my-api/.claude/skills/README.md +7 -0
  148. package/starter/my-api/CLAUDE.md +33 -0
  149. package/starter/my-api/FINDINGS.md +9 -0
  150. package/starter/my-api/summary.md +7 -0
  151. package/starter/my-api/tasks.md +7 -0
  152. package/starter/my-first-project/.claude/skills/README.md +7 -0
  153. package/starter/my-first-project/CLAUDE.md +49 -0
  154. package/starter/my-first-project/FINDINGS.md +24 -0
  155. package/starter/my-first-project/summary.md +11 -0
  156. package/starter/my-first-project/tasks.md +25 -0
  157. package/starter/my-frontend/.claude/skills/README.md +7 -0
  158. package/starter/my-frontend/CLAUDE.md +33 -0
  159. package/starter/my-frontend/FINDINGS.md +9 -0
  160. package/starter/my-frontend/summary.md +7 -0
  161. package/starter/my-frontend/tasks.md +7 -0
  162. package/starter/profiles/default.yaml +4 -0
  163. package/starter/profiles/personal.yaml +4 -0
  164. package/starter/profiles/work.yaml +4 -0
  165. package/starter/templates/README.md +7 -0
  166. package/starter/templates/frontend/CLAUDE.md +23 -0
  167. package/starter/templates/frontend/FINDINGS.md +7 -0
  168. package/starter/templates/frontend/reference/README.md +4 -0
  169. package/starter/templates/frontend/summary.md +7 -0
  170. package/starter/templates/frontend/tasks.md +11 -0
  171. package/starter/templates/library/CLAUDE.md +22 -0
  172. package/starter/templates/library/FINDINGS.md +7 -0
  173. package/starter/templates/library/reference/README.md +4 -0
  174. package/starter/templates/library/summary.md +7 -0
  175. package/starter/templates/library/tasks.md +11 -0
  176. package/starter/templates/monorepo/CLAUDE.md +21 -0
  177. package/starter/templates/monorepo/FINDINGS.md +7 -0
  178. package/starter/templates/monorepo/reference/README.md +4 -0
  179. package/starter/templates/monorepo/summary.md +7 -0
  180. package/starter/templates/monorepo/tasks.md +11 -0
  181. package/starter/templates/python-project/CLAUDE.md +21 -0
  182. package/starter/templates/python-project/FINDINGS.md +7 -0
  183. package/starter/templates/python-project/reference/README.md +4 -0
  184. package/starter/templates/python-project/summary.md +7 -0
  185. package/starter/templates/python-project/tasks.md +10 -0
@@ -0,0 +1,61 @@
1
+ export const cliManifest = {
2
+ surface: "cli",
3
+ version: "1.31.1",
4
+ actions: {
5
+ // Finding management
6
+ "finding.add": { implemented: true, handler: "cli-actions.ts:handleAddFinding" },
7
+ "finding.remove": { implemented: true, handler: "cli-namespaces.ts:handleFindingNamespace remove" },
8
+ "finding.list": { implemented: true, handler: "cli.ts:search (findings visible via search)" },
9
+ "finding.filter_by_date": { implemented: false, reason: "Search has no date filter flag" },
10
+ "finding.pin": { implemented: true, handler: "cli-actions.ts:handlePin" },
11
+ // Task management
12
+ "task.add": { implemented: true, handler: "cli-namespaces.ts:handleTaskNamespace add" },
13
+ "task.complete": { implemented: true, handler: "cli-namespaces.ts:handleTaskNamespace complete" },
14
+ "task.remove": { implemented: false, reason: "No dedicated CLI task remove command" },
15
+ "task.update": { implemented: true, handler: "cli-namespaces.ts:handleTaskNamespace update" },
16
+ "task.list": { implemented: true, handler: "cli-actions.ts:handleTasks" },
17
+ "task.pin": { implemented: false, reason: "Pin task is MCP-only" },
18
+ "task.github_link": { implemented: false, reason: "GitHub link/promote is MCP-only" },
19
+ // Hook management
20
+ "hook.list": { implemented: true, handler: "cli-actions.ts:handleHooks list" },
21
+ "hook.toggle": { implemented: true, handler: "cli-actions.ts:handleHooks enable/disable" },
22
+ "hook.toggle_per_project": { implemented: false, reason: "Per-project hook toggle not exposed in CLI" },
23
+ "hook.custom_crud": { implemented: false, reason: "Custom hooks CRUD not exposed in CLI" },
24
+ "hook.errors": { implemented: false, reason: "Hook errors not exposed in CLI" },
25
+ // Search
26
+ "search.fts": { implemented: true, handler: "cli-actions.ts:handleSearch" },
27
+ "search.fragment": { implemented: true, handler: "cli-actions.ts:handleFragmentSearch" },
28
+ "search.related_docs": { implemented: true, handler: "cli-actions.ts:handleRelatedDocs" },
29
+ "search.history": { implemented: true, handler: "cli-actions.ts:handleSearch --history" },
30
+ // Graph
31
+ "graph.read": { implemented: true, handler: "cli-graph.ts:handleGraphRead" },
32
+ "graph.visualize": { implemented: false, reason: "Graph visualization is VS Code / web only" },
33
+ "graph.link_findings": { implemented: true, handler: "cli-graph.ts:handleGraphLink" },
34
+ // Config
35
+ "config.proactivity": { implemented: true, handler: "cli-config.ts:handleProactivity" },
36
+ "config.task_mode": { implemented: true, handler: "cli-config.ts:handleConfigTaskMode" },
37
+ "config.retention": { implemented: true, handler: "cli-config.ts:handleRetentionPolicy" },
38
+ "config.workflow": { implemented: true, handler: "cli-config.ts:handleWorkflowPolicy" },
39
+ "config.index": { implemented: true, handler: "cli-config.ts:handleIndexPolicy" },
40
+ // Health / Sync / Session
41
+ "health.check": { implemented: true, handler: "cli-actions.ts:handleDoctor" },
42
+ "health.doctor_fix": { implemented: true, handler: "cli-actions.ts:handleDoctor --fix" },
43
+ "health.sync": { implemented: true, handler: "hook-stop auto-commit" },
44
+ "session.start": { implemented: true, handler: "cli-hooks-session.ts (hook)" },
45
+ "session.end": { implemented: true, handler: "cli-hooks-stop.ts (hook)" },
46
+ // Skill management
47
+ "skill.list": { implemented: true, handler: "cli-actions.ts:handleSkillList" },
48
+ "skill.read": { implemented: true, handler: "cli-actions.ts:handleSkills read" },
49
+ "skill.enable": { implemented: false, reason: "No CLI command for skill enable/disable" },
50
+ "skill.write": { implemented: false, reason: "No CLI command for skill write" },
51
+ // Project management
52
+ "project.list": { implemented: true, handler: "cli-actions.ts:handleProjects list" },
53
+ "project.manage": { implemented: true, handler: "cli-actions.ts:handleProjects remove" },
54
+ "project.summary": { implemented: false, reason: "No CLI command for project summary" },
55
+ "export.project": { implemented: false, reason: "Export/import not exposed in CLI" },
56
+ "import.project": { implemented: false, reason: "Export/import not exposed in CLI" },
57
+ // Profile / Machine
58
+ "profile.switch": { implemented: false, reason: "No CLI command for profile switch" },
59
+ "profile.list": { implemented: true, handler: "cli-config.ts:config profiles" },
60
+ },
61
+ };
@@ -0,0 +1,15 @@
1
+ export { ACTION_KEYS } from "./types.js";
2
+ export { cliManifest } from "./cli.js";
3
+ export { mcpManifest } from "./mcp.js";
4
+ export { vscodeManifest } from "./vscode.js";
5
+ export { webUiManifest } from "./web-ui.js";
6
+ import { cliManifest } from "./cli.js";
7
+ import { mcpManifest } from "./mcp.js";
8
+ import { vscodeManifest } from "./vscode.js";
9
+ import { webUiManifest } from "./web-ui.js";
10
+ export const ALL_MANIFESTS = [
11
+ cliManifest,
12
+ mcpManifest,
13
+ vscodeManifest,
14
+ webUiManifest,
15
+ ];
@@ -0,0 +1,61 @@
1
+ export const mcpManifest = {
2
+ surface: "mcp",
3
+ version: "1.31.1",
4
+ actions: {
5
+ // Finding management
6
+ "finding.add": { implemented: true, handler: "index.ts:add_finding" },
7
+ "finding.remove": { implemented: true, handler: "index.ts:remove_finding" },
8
+ "finding.list": { implemented: true, handler: "index.ts:get_findings" },
9
+ "finding.filter_by_date": { implemented: false, reason: "get_findings has no date filter parameter" },
10
+ "finding.pin": { implemented: true, handler: "index.ts:pin_memory" },
11
+ // Task management
12
+ "task.add": { implemented: true, handler: "index.ts:add_task" },
13
+ "task.complete": { implemented: true, handler: "index.ts:complete_task" },
14
+ "task.remove": { implemented: true, handler: "index.ts:remove_task" },
15
+ "task.update": { implemented: true, handler: "index.ts:update_task" },
16
+ "task.list": { implemented: true, handler: "index.ts:get_tasks" },
17
+ "task.pin": { implemented: true, handler: "index.ts:pin_task" },
18
+ "task.github_link": { implemented: true, handler: "index.ts:link_task_issue, promote_task_to_issue" },
19
+ // Hook management
20
+ "hook.list": { implemented: true, handler: "index.ts:list_hooks" },
21
+ "hook.toggle": { implemented: true, handler: "index.ts:toggle_hooks" },
22
+ "hook.toggle_per_project": { implemented: true, handler: "index.ts:toggle_hooks (project param)" },
23
+ "hook.custom_crud": { implemented: true, handler: "index.ts:add_custom_hook, remove_custom_hook" },
24
+ "hook.errors": { implemented: true, handler: "index.ts:list_hook_errors" },
25
+ // Search
26
+ "search.fts": { implemented: true, handler: "index.ts:search_knowledge" },
27
+ "search.fragment": { implemented: true, handler: "index.ts:search_fragments" },
28
+ "search.related_docs": { implemented: true, handler: "index.ts:get_related_docs" },
29
+ "search.history": { implemented: false, reason: "Search history is CLI-only (search-history.jsonl)" },
30
+ // Graph
31
+ "graph.read": { implemented: true, handler: "index.ts:read_graph" },
32
+ "graph.visualize": { implemented: false, reason: "MCP returns data only; visualization is client-side" },
33
+ "graph.link_findings": { implemented: true, handler: "index.ts:link_findings" },
34
+ // Config
35
+ "config.proactivity": { implemented: false, reason: "No MCP tool for proactivity config" },
36
+ "config.task_mode": { implemented: false, reason: "No MCP tool for workflow policy" },
37
+ "config.retention": { implemented: false, reason: "Config tools are CLI-only" },
38
+ "config.workflow": { implemented: false, reason: "Config tools are CLI-only" },
39
+ "config.index": { implemented: false, reason: "Config tools are CLI-only" },
40
+ // Health / Sync / Session
41
+ "health.check": { implemented: true, handler: "index.ts:health_check" },
42
+ "health.doctor_fix": { implemented: true, handler: "index.ts:doctor_fix" },
43
+ "health.sync": { implemented: true, handler: "index.ts:push_changes" },
44
+ "session.start": { implemented: true, handler: "index.ts:session_start" },
45
+ "session.end": { implemented: true, handler: "index.ts:session_end" },
46
+ // Skill management
47
+ "skill.list": { implemented: true, handler: "index.ts:list_skills" },
48
+ "skill.read": { implemented: true, handler: "index.ts:read_skill" },
49
+ "skill.enable": { implemented: true, handler: "index.ts:enable_skill, disable_skill" },
50
+ "skill.write": { implemented: true, handler: "index.ts:write_skill" },
51
+ // Project management
52
+ "project.list": { implemented: true, handler: "index.ts:list_projects" },
53
+ "project.manage": { implemented: true, handler: "index.ts:manage_project" },
54
+ "project.summary": { implemented: true, handler: "index.ts:get_project_summary" },
55
+ "export.project": { implemented: true, handler: "index.ts:export_project" },
56
+ "import.project": { implemented: true, handler: "index.ts:import_project" },
57
+ // Profile / Machine
58
+ "profile.switch": { implemented: false, reason: "No MCP tool for profile switching" },
59
+ "profile.list": { implemented: false, reason: "No MCP tool for profile listing" },
60
+ },
61
+ };
@@ -0,0 +1,57 @@
1
+ export const ACTION_KEYS = [
2
+ // Finding management
3
+ "finding.add",
4
+ "finding.remove",
5
+ "finding.list",
6
+ "finding.filter_by_date",
7
+ "finding.pin",
8
+ // Task management
9
+ "task.add",
10
+ "task.complete",
11
+ "task.remove",
12
+ "task.update",
13
+ "task.list",
14
+ "task.pin",
15
+ "task.github_link",
16
+ // Hook management
17
+ "hook.list",
18
+ "hook.toggle",
19
+ "hook.toggle_per_project",
20
+ "hook.custom_crud",
21
+ "hook.errors",
22
+ // Search
23
+ "search.fts",
24
+ "search.fragment",
25
+ "search.related_docs",
26
+ "search.history",
27
+ // Graph
28
+ "graph.read",
29
+ "graph.visualize",
30
+ "graph.link_findings",
31
+ // Config
32
+ "config.proactivity",
33
+ "config.task_mode",
34
+ "config.retention",
35
+ "config.workflow",
36
+ "config.index",
37
+ // Health / Sync / Session
38
+ "health.check",
39
+ "health.doctor_fix",
40
+ "health.sync",
41
+ "session.start",
42
+ "session.end",
43
+ // Skill management
44
+ "skill.list",
45
+ "skill.read",
46
+ "skill.enable",
47
+ "skill.write",
48
+ // Project management
49
+ "project.list",
50
+ "project.manage",
51
+ "project.summary",
52
+ "export.project",
53
+ "import.project",
54
+ // Profile / Machine
55
+ "profile.switch",
56
+ "profile.list",
57
+ ];
@@ -0,0 +1,61 @@
1
+ export const vscodeManifest = {
2
+ surface: "vscode",
3
+ version: "1.31.1",
4
+ actions: {
5
+ // Finding management
6
+ "finding.add": { implemented: true, handler: "extension.ts:phren.addFinding" },
7
+ "finding.remove": { implemented: true, handler: "extension.ts:phren.removeFinding" },
8
+ "finding.list": { implemented: true, handler: "PhrenTreeProvider.ts:findings section" },
9
+ "finding.filter_by_date": { implemented: true, handler: "extension.ts:phren.filterFindingsByDate" },
10
+ "finding.pin": { implemented: true, handler: "extension.ts:phren.pinMemory" },
11
+ // Task management
12
+ "task.add": { implemented: true, handler: "extension.ts:phren.addTask" },
13
+ "task.complete": { implemented: true, handler: "extension.ts:phren.completeTask" },
14
+ "task.remove": { implemented: true, handler: "extension.ts:phren.removeTask" },
15
+ "task.update": { implemented: false, reason: "No VS Code command for task field updates" },
16
+ "task.list": { implemented: true, handler: "PhrenTreeProvider.ts:tasks section" },
17
+ "task.pin": { implemented: false, reason: "No VS Code command for task pinning" },
18
+ "task.github_link": { implemented: false, reason: "GitHub link/promote is MCP-only" },
19
+ // Hook management
20
+ "hook.list": { implemented: true, handler: "extension.ts:phren.hooksStatus" },
21
+ "hook.toggle": { implemented: true, handler: "extension.ts:phren.toggleHook, phren.toggleHooksCommand" },
22
+ "hook.toggle_per_project": { implemented: false, reason: "Per-project hook toggle not exposed in VS Code" },
23
+ "hook.custom_crud": { implemented: false, reason: "Custom hooks CRUD not exposed in VS Code" },
24
+ "hook.errors": { implemented: false, reason: "Hook errors not exposed in VS Code" },
25
+ // Search
26
+ "search.fts": { implemented: true, handler: "searchQuickPick.ts:showSearchQuickPick" },
27
+ "search.fragment": { implemented: true, handler: "phrenClient.ts:searchFragments" },
28
+ "search.related_docs": { implemented: true, handler: "phrenClient.ts:getRelatedDocs" },
29
+ "search.history": { implemented: true, handler: "searchQuickPick.ts:searchHistory (in-memory)" },
30
+ // Graph
31
+ "graph.read": { implemented: true, handler: "graphWebview.ts:showGraphWebview" },
32
+ "graph.visualize": { implemented: true, handler: "graphWebview.ts:showGraphWebview (webview panel)" },
33
+ "graph.link_findings": { implemented: false, reason: "Link findings is MCP-only" },
34
+ // Config
35
+ "config.proactivity": { implemented: false, reason: "Config tools are CLI-only" },
36
+ "config.task_mode": { implemented: false, reason: "Config tools are CLI-only" },
37
+ "config.retention": { implemented: false, reason: "Config tools are CLI-only" },
38
+ "config.workflow": { implemented: false, reason: "Config tools are CLI-only" },
39
+ "config.index": { implemented: false, reason: "Config tools are CLI-only" },
40
+ // Health / Sync / Session
41
+ "health.check": { implemented: true, handler: "extension.ts:phren.doctor" },
42
+ "health.doctor_fix": { implemented: true, handler: "extension.ts:phren.doctorFix" },
43
+ "health.sync": { implemented: true, handler: "extension.ts:phren.sync" },
44
+ "session.start": { implemented: true, handler: "extension.ts:phren.sessionStart" },
45
+ "session.end": { implemented: true, handler: "extension.ts:phren.sessionEnd" },
46
+ // Skill management
47
+ "skill.list": { implemented: true, handler: "PhrenTreeProvider.ts:skills section" },
48
+ "skill.read": { implemented: true, handler: "skillEditor.ts:showSkillEditor" },
49
+ "skill.enable": { implemented: true, handler: "extension.ts:phren.toggleSkill" },
50
+ "skill.write": { implemented: false, reason: "No VS Code command for skill write" },
51
+ // Project management
52
+ "project.list": { implemented: true, handler: "PhrenTreeProvider.ts:projects section" },
53
+ "project.manage": { implemented: true, handler: "extension.ts:phren.manageProject" },
54
+ "project.summary": { implemented: true, handler: "PhrenTreeProvider.ts:project detail view" },
55
+ "export.project": { implemented: false, reason: "Export/import not exposed in VS Code" },
56
+ "import.project": { implemented: false, reason: "Export/import not exposed in VS Code" },
57
+ // Profile / Machine
58
+ "profile.switch": { implemented: true, handler: "extension.ts:phren.switchProfile" },
59
+ "profile.list": { implemented: true, handler: "PhrenTreeProvider.ts:manage section (profiles dir)" },
60
+ },
61
+ };
@@ -0,0 +1,61 @@
1
+ export const webUiManifest = {
2
+ surface: "web-ui",
3
+ version: "1.31.1",
4
+ actions: {
5
+ // Finding management
6
+ "finding.add": { implemented: false, reason: "Web UI is read-only for findings (review queue only)" },
7
+ "finding.remove": { implemented: false, reason: "Web UI is read-only for findings" },
8
+ "finding.list": { implemented: true, handler: "memory-ui-server.ts:/api/project-content" },
9
+ "finding.filter_by_date": { implemented: false, reason: "No date filter in web UI API" },
10
+ "finding.pin": { implemented: false, reason: "No pin action in web UI" },
11
+ // Task management
12
+ "task.add": { implemented: false, reason: "No task creation in web UI" },
13
+ "task.complete": { implemented: false, reason: "No task completion in web UI" },
14
+ "task.remove": { implemented: false, reason: "No task deletion in web UI" },
15
+ "task.update": { implemented: false, reason: "No task update in web UI" },
16
+ "task.list": { implemented: true, handler: "memory-ui-server.ts:/api/tasks" },
17
+ "task.pin": { implemented: false, reason: "No task pinning in web UI" },
18
+ "task.github_link": { implemented: false, reason: "No GitHub link in web UI" },
19
+ // Hook management
20
+ "hook.list": { implemented: true, handler: "memory-ui-server.ts:/api/hooks" },
21
+ "hook.toggle": { implemented: true, handler: "memory-ui-server.ts:/api/hook-toggle" },
22
+ "hook.toggle_per_project": { implemented: false, reason: "Per-project hook toggle not exposed in web UI" },
23
+ "hook.custom_crud": { implemented: false, reason: "Custom hooks CRUD not exposed in web UI" },
24
+ "hook.errors": { implemented: false, reason: "Hook errors not exposed in web UI" },
25
+ // Search
26
+ "search.fts": { implemented: true, handler: "memory-ui-server.ts:/api/search" },
27
+ "search.fragment": { implemented: false, reason: "No fragment search in web UI" },
28
+ "search.related_docs": { implemented: false, reason: "No related docs in web UI" },
29
+ "search.history": { implemented: false, reason: "No search history in web UI" },
30
+ // Graph
31
+ "graph.read": { implemented: true, handler: "memory-ui-server.ts:/api/graph" },
32
+ "graph.visualize": { implemented: true, handler: "memory-ui-page.ts:graph tab (Canvas2D + Barnes-Hut engine)" },
33
+ "graph.link_findings": { implemented: false, reason: "No link findings action in web UI" },
34
+ // Config
35
+ "config.proactivity": { implemented: false, reason: "Config is CLI-only" },
36
+ "config.task_mode": { implemented: true, handler: "memory-ui-server.ts:/api/settings (workflow policy)" },
37
+ "config.retention": { implemented: false, reason: "Config is CLI-only" },
38
+ "config.workflow": { implemented: true, handler: "memory-ui-server.ts:/api/settings (workflow policy)" },
39
+ "config.index": { implemented: false, reason: "Config is CLI-only" },
40
+ // Health / Sync / Session
41
+ "health.check": { implemented: true, handler: "memory-ui-server.ts:/api/runtime-health" },
42
+ "health.doctor_fix": { implemented: false, reason: "Doctor --fix is CLI-only" },
43
+ "health.sync": { implemented: true, handler: "memory-ui-server.ts:/api/sync" },
44
+ "session.start": { implemented: false, reason: "Session lifecycle is not web UI driven" },
45
+ "session.end": { implemented: false, reason: "Session lifecycle is not web UI driven" },
46
+ // Skill management
47
+ "skill.list": { implemented: true, handler: "memory-ui-server.ts:/api/skills" },
48
+ "skill.read": { implemented: true, handler: "memory-ui-server.ts:/api/skill-content" },
49
+ "skill.enable": { implemented: true, handler: "memory-ui-server.ts:/api/skill-toggle" },
50
+ "skill.write": { implemented: true, handler: "memory-ui-server.ts:/api/skill-save" },
51
+ // Project management
52
+ "project.list": { implemented: true, handler: "memory-ui-server.ts:/api/projects" },
53
+ "project.manage": { implemented: false, reason: "No archive/unarchive in web UI" },
54
+ "project.summary": { implemented: true, handler: "memory-ui-server.ts:/api/project-content" },
55
+ "export.project": { implemented: false, reason: "Export/import not exposed in web UI" },
56
+ "import.project": { implemented: false, reason: "Export/import not exposed in web UI" },
57
+ // Profile / Machine
58
+ "profile.switch": { implemented: false, reason: "No profile switching in web UI" },
59
+ "profile.list": { implemented: false, reason: "No profile listing in web UI" },
60
+ },
61
+ };
@@ -0,0 +1,302 @@
1
+ import * as fs from "fs";
2
+ import { runtimeFile, getPhrenPath } from "./shared.js";
3
+ import { recordFeedback, flushEntryScores, getWorkflowPolicy, } from "./shared-governance.js";
4
+ import { upsertCanonical } from "./shared-content.js";
5
+ import { errorMessage } from "./utils.js";
6
+ import { addFinding as addFindingCore } from "./core-finding.js";
7
+ import { runDoctor } from "./link.js";
8
+ import { startWebUi } from "./memory-ui.js";
9
+ import { startShell } from "./shell.js";
10
+ import { runPhrenUpdate } from "./update.js";
11
+ import { readRuntimeHealth } from "./data-access.js";
12
+ import { runSearch, runFragmentSearch, parseFragmentSearchArgs, runRelatedDocs, parseRelatedDocsArgs } from "./cli-search.js";
13
+ import { resolveRuntimeProfile } from "./runtime-profile.js";
14
+ export async function handleSearch(opts, profile) {
15
+ const result = await runSearch(opts, getPhrenPath(), profile);
16
+ if (result.lines.length > 0) {
17
+ console.log(result.lines.join("\n"));
18
+ }
19
+ if (result.exitCode !== 0)
20
+ process.exit(result.exitCode);
21
+ }
22
+ export async function handleFragmentSearch(args, profile) {
23
+ const opts = parseFragmentSearchArgs(args);
24
+ if (!opts)
25
+ return;
26
+ const result = await runFragmentSearch(opts.query, getPhrenPath(), profile, opts);
27
+ if (result.lines.length > 0) {
28
+ console.log(result.lines.join("\n"));
29
+ }
30
+ if (result.exitCode !== 0)
31
+ process.exit(result.exitCode);
32
+ }
33
+ export async function handleRelatedDocs(args, profile) {
34
+ const opts = parseRelatedDocsArgs(args);
35
+ if (!opts)
36
+ return;
37
+ const result = await runRelatedDocs(opts.entity, getPhrenPath(), profile, opts);
38
+ if (result.lines.length > 0) {
39
+ console.log(result.lines.join("\n"));
40
+ }
41
+ if (result.exitCode !== 0)
42
+ process.exit(result.exitCode);
43
+ }
44
+ export async function handleAddFinding(project, learning) {
45
+ if (!project || !learning) {
46
+ console.error('Usage: phren add-finding <project> "<insight>"');
47
+ process.exit(1);
48
+ }
49
+ try {
50
+ const result = addFindingCore(getPhrenPath(), project, learning);
51
+ if (!result.ok) {
52
+ console.error(result.message);
53
+ process.exit(1);
54
+ }
55
+ console.log(result.message);
56
+ }
57
+ catch (err) {
58
+ console.error(err instanceof Error ? err.message : String(err));
59
+ process.exit(1);
60
+ }
61
+ }
62
+ export async function handlePinCanonical(project, memory) {
63
+ if (!project || !memory) {
64
+ console.error('Usage: phren pin <project> "<memory>"');
65
+ process.exit(1);
66
+ }
67
+ const result = upsertCanonical(getPhrenPath(), project, memory);
68
+ console.log(result.ok ? result.data : result.error);
69
+ }
70
+ export async function handleDoctor(args) {
71
+ const profile = resolveRuntimeProfile(getPhrenPath());
72
+ const fix = args.includes("--fix");
73
+ const checkData = args.includes("--check-data");
74
+ const agentsOnly = args.includes("--agents");
75
+ const parityCheck = args.includes("--parity");
76
+ if (parityCheck) {
77
+ const { ALL_MANIFESTS, ACTION_KEYS } = await import("./capabilities/index.js");
78
+ const gaps = [];
79
+ for (const key of ACTION_KEYS) {
80
+ for (const manifest of ALL_MANIFESTS) {
81
+ const entry = manifest.actions[key];
82
+ if (!entry.implemented) {
83
+ gaps.push({ action: key, surface: manifest.surface, reason: entry.reason || "unknown" });
84
+ }
85
+ }
86
+ }
87
+ const byAction = new Map();
88
+ for (const gap of gaps) {
89
+ const arr = byAction.get(gap.action) || [];
90
+ arr.push({ surface: gap.surface, reason: gap.reason });
91
+ byAction.set(gap.action, arr);
92
+ }
93
+ const total = ACTION_KEYS.length;
94
+ const implemented = new Map();
95
+ for (const manifest of ALL_MANIFESTS) {
96
+ let count = 0;
97
+ for (const key of ACTION_KEYS) {
98
+ if (manifest.actions[key].implemented)
99
+ count++;
100
+ }
101
+ implemented.set(manifest.surface, count);
102
+ }
103
+ console.log(`phren doctor --parity: ${total} actions across ${ALL_MANIFESTS.length} surfaces\n`);
104
+ for (const manifest of ALL_MANIFESTS) {
105
+ const count = implemented.get(manifest.surface) || 0;
106
+ console.log(` ${manifest.surface}: ${count}/${total} implemented (${Math.round(100 * count / total)}%)`);
107
+ }
108
+ if (byAction.size > 0) {
109
+ console.log(`\nGaps (${gaps.length} total):`);
110
+ for (const [action, entries] of byAction) {
111
+ const surfaces = entries.map((e) => e.surface).join(", ");
112
+ console.log(` ${action}: missing in ${surfaces}`);
113
+ }
114
+ }
115
+ else {
116
+ console.log("\nNo gaps — full parity across all surfaces.");
117
+ }
118
+ process.exit(0);
119
+ }
120
+ const result = await runDoctor(getPhrenPath(), fix, checkData);
121
+ if (agentsOnly) {
122
+ const agentChecks = result.checks.filter((check) => check.name.includes("cursor") || check.name.includes("copilot") || check.name.includes("codex") || check.name.includes("windsurf"));
123
+ console.log(`phren doctor --agents: ${agentChecks.every((check) => check.ok) ? "all configured" : "some not configured"}`);
124
+ for (const check of agentChecks) {
125
+ console.log(`- ${check.ok ? "ok" : "not configured"} ${check.name}: ${check.detail}`);
126
+ }
127
+ if (agentChecks.length === 0) {
128
+ console.log("No agent integrations detected. Run `phren init` to configure.");
129
+ }
130
+ process.exit(agentChecks.every((check) => check.ok) ? 0 : 1);
131
+ }
132
+ console.log(`phren doctor: ${result.ok ? "ok" : "issues found"}`);
133
+ if (result.machine)
134
+ console.log(`machine: ${result.machine}`);
135
+ if (result.profile)
136
+ console.log(`profile: ${result.profile}`);
137
+ console.log(`tasks: ${getWorkflowPolicy(getPhrenPath()).taskMode} mode`);
138
+ const renderCheckState = (check) => {
139
+ if (check.name === "git-remote" &&
140
+ check.ok &&
141
+ /no remote configured|local-only/i.test(check.detail)) {
142
+ return "info";
143
+ }
144
+ return check.ok ? "ok" : "fail";
145
+ };
146
+ for (const check of result.checks) {
147
+ console.log(`- ${renderCheckState(check)} ${check.name}: ${check.detail}`);
148
+ }
149
+ try {
150
+ const missFile = runtimeFile(getPhrenPath(), "search-misses.jsonl");
151
+ if (fs.existsSync(missFile)) {
152
+ const lines = fs.readFileSync(missFile, "utf8").split("\n").filter(Boolean);
153
+ if (lines.length > 0) {
154
+ const tokenCounts = new Map();
155
+ for (const line of lines) {
156
+ try {
157
+ const entry = JSON.parse(line);
158
+ const tokens = entry.query.toLowerCase().split(/\s+/).filter((token) => token.length > 2);
159
+ for (const token of tokens) {
160
+ tokenCounts.set(token, (tokenCounts.get(token) ?? 0) + 1);
161
+ }
162
+ }
163
+ catch (err) {
164
+ if ((process.env.PHREN_DEBUG || process.env.PHREN_DEBUG))
165
+ process.stderr.write(`[phren] doctor searchMissParse: ${errorMessage(err)}\n`);
166
+ }
167
+ }
168
+ const topMisses = [...tokenCounts.entries()]
169
+ .sort((a, b) => b[1] - a[1])
170
+ .slice(0, 10);
171
+ if (topMisses.length > 0) {
172
+ console.log(`\nSearch miss patterns (${lines.length} zero-result queries):`);
173
+ for (const [token, count] of topMisses) {
174
+ console.log(` ${token}: ${count} miss(es)`);
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+ catch (err) {
181
+ if ((process.env.PHREN_DEBUG || process.env.PHREN_DEBUG))
182
+ process.stderr.write(`[phren] doctor searchMissAnalysis: ${errorMessage(err)}\n`);
183
+ }
184
+ try {
185
+ const { checkOllamaAvailable, checkModelAvailable, getOllamaUrl, getEmbeddingModel } = await import("./shared-ollama.js");
186
+ const { getEmbeddingCache, formatEmbeddingCoverage } = await import("./shared-embedding-cache.js");
187
+ const { listIndexedDocumentPaths } = await import("./shared-index.js");
188
+ const ollamaUrl = getOllamaUrl();
189
+ if (!ollamaUrl) {
190
+ console.log("- ok semantic-search: disabled (optional; enable for fuzzy/paraphrase-heavy retrieval)");
191
+ }
192
+ else {
193
+ const available = await checkOllamaAvailable();
194
+ if (!available) {
195
+ console.log(`- warn semantic-search: Ollama not running at ${ollamaUrl} (start Ollama or set PHREN_OLLAMA_URL=off to disable)`);
196
+ }
197
+ else {
198
+ const model = getEmbeddingModel();
199
+ const modelReady = await checkModelAvailable();
200
+ if (!modelReady) {
201
+ console.log(`- warn semantic-search: model ${model} not pulled (run: ollama pull ${model})`);
202
+ }
203
+ else {
204
+ const phrenPath = getPhrenPath();
205
+ const cache = getEmbeddingCache(phrenPath);
206
+ await cache.load().catch(() => { });
207
+ const allPaths = listIndexedDocumentPaths(phrenPath, profile || undefined);
208
+ const coverage = cache.coverage(allPaths);
209
+ console.log(`- ok semantic-search: ${model} ready, ${formatEmbeddingCoverage(coverage)}`);
210
+ }
211
+ }
212
+ }
213
+ }
214
+ catch (err) {
215
+ if ((process.env.PHREN_DEBUG || process.env.PHREN_DEBUG))
216
+ process.stderr.write(`[phren] doctor ollamaStatus: ${errorMessage(err)}\n`);
217
+ }
218
+ process.exit(result.ok ? 0 : 1);
219
+ }
220
+ export async function handleStatus() {
221
+ const phrenPath = getPhrenPath();
222
+ const profile = resolveRuntimeProfile(phrenPath);
223
+ const runtime = readRuntimeHealth(phrenPath);
224
+ console.log("phren status");
225
+ console.log(`last auto-save: ${runtime.lastAutoSave?.status || "n/a"}${runtime.lastAutoSave?.at ? ` @ ${runtime.lastAutoSave.at}` : ""}`);
226
+ console.log(`last pull: ${runtime.lastSync?.lastPullStatus || "n/a"}${runtime.lastSync?.lastPullAt ? ` @ ${runtime.lastSync.lastPullAt}` : ""}`);
227
+ console.log(`last push: ${runtime.lastSync?.lastPushStatus || "n/a"}${runtime.lastSync?.lastPushAt ? ` @ ${runtime.lastSync.lastPushAt}` : ""}`);
228
+ console.log(`unsynced commits: ${runtime.lastSync?.unsyncedCommits ?? 0}`);
229
+ if (runtime.lastSync?.lastPushDetail)
230
+ console.log(`push detail: ${runtime.lastSync.lastPushDetail}`);
231
+ try {
232
+ const { getOllamaUrl, checkOllamaAvailable, checkModelAvailable, getEmbeddingModel } = await import("./shared-ollama.js");
233
+ const { getEmbeddingCache, formatEmbeddingCoverage } = await import("./shared-embedding-cache.js");
234
+ const { listIndexedDocumentPaths } = await import("./shared-index.js");
235
+ const ollamaUrl = getOllamaUrl();
236
+ if (!ollamaUrl) {
237
+ console.log("semantic-search: disabled (optional)");
238
+ return;
239
+ }
240
+ const available = await checkOllamaAvailable();
241
+ if (!available) {
242
+ console.log(`semantic-search: offline (${ollamaUrl})`);
243
+ return;
244
+ }
245
+ const model = getEmbeddingModel();
246
+ const modelReady = await checkModelAvailable();
247
+ if (!modelReady) {
248
+ console.log(`semantic-search: model missing (${model})`);
249
+ return;
250
+ }
251
+ const cache = getEmbeddingCache(phrenPath);
252
+ await cache.load().catch(() => { });
253
+ const coverage = cache.coverage(listIndexedDocumentPaths(phrenPath, profile || undefined));
254
+ console.log(`semantic-search: ${model} ready, ${formatEmbeddingCoverage(coverage)}`);
255
+ }
256
+ catch (err) {
257
+ if ((process.env.PHREN_DEBUG || process.env.PHREN_DEBUG))
258
+ process.stderr.write(`[phren] handleStatus semanticSearch: ${errorMessage(err)}\n`);
259
+ }
260
+ }
261
+ export async function handleQualityFeedback(args) {
262
+ const key = args.find((arg) => arg.startsWith("--key="))?.slice("--key=".length);
263
+ const feedback = args.find((arg) => arg.startsWith("--type="))?.slice("--type=".length);
264
+ if (!key || !feedback || !["helpful", "reprompt", "regression"].includes(feedback)) {
265
+ console.error("Usage: phren quality-feedback --key=<entry-key> --type=helpful|reprompt|regression");
266
+ process.exit(1);
267
+ }
268
+ recordFeedback(getPhrenPath(), key, feedback);
269
+ flushEntryScores(getPhrenPath());
270
+ console.log(`Recorded feedback: ${feedback} for ${key}`);
271
+ }
272
+ export async function handleMemoryUi(args) {
273
+ const portArg = args.find((arg) => arg.startsWith("--port="));
274
+ const noOpen = args.includes("--no-open");
275
+ const port = portArg ? Number.parseInt(portArg.slice("--port=".length), 10) : 3499;
276
+ const safePort = Number.isNaN(port) ? 3499 : port;
277
+ await startWebUi(getPhrenPath(), safePort, resolveRuntimeProfile(getPhrenPath()), {
278
+ autoOpen: !noOpen,
279
+ allowPortFallback: !portArg,
280
+ });
281
+ }
282
+ export async function handleShell(args, profile) {
283
+ if (args.includes("--help") || args.includes("-h")) {
284
+ console.log("Usage: phren shell");
285
+ console.log("Interactive shell with views for Projects, Task, Findings, Review Queue, Skills, Hooks, Machines/Profiles, and Health.");
286
+ return;
287
+ }
288
+ await startShell(getPhrenPath(), profile);
289
+ }
290
+ export async function handleUpdate(args) {
291
+ if (args.includes("--help") || args.includes("-h")) {
292
+ console.log("Usage: phren update [--refresh-starter]");
293
+ console.log("Updates phren to the latest version (local git clone when available, otherwise npm global package).");
294
+ console.log("Pass --refresh-starter to refresh global starter assets in the same flow.");
295
+ return;
296
+ }
297
+ const result = await runPhrenUpdate({ refreshStarter: args.includes("--refresh-starter") });
298
+ console.log(result.message);
299
+ if (!result.ok) {
300
+ process.exitCode = 1;
301
+ }
302
+ }