@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.
- package/LICENSE +21 -0
- package/README.md +590 -0
- package/mcp/dist/capabilities/cli.js +61 -0
- package/mcp/dist/capabilities/index.js +15 -0
- package/mcp/dist/capabilities/mcp.js +61 -0
- package/mcp/dist/capabilities/types.js +57 -0
- package/mcp/dist/capabilities/vscode.js +61 -0
- package/mcp/dist/capabilities/web-ui.js +61 -0
- package/mcp/dist/cli-actions.js +302 -0
- package/mcp/dist/cli-config.js +580 -0
- package/mcp/dist/cli-extract.js +305 -0
- package/mcp/dist/cli-govern.js +371 -0
- package/mcp/dist/cli-graph.js +169 -0
- package/mcp/dist/cli-hooks-citations.js +44 -0
- package/mcp/dist/cli-hooks-context.js +56 -0
- package/mcp/dist/cli-hooks-globs.js +83 -0
- package/mcp/dist/cli-hooks-output.js +130 -0
- package/mcp/dist/cli-hooks-retrieval.js +2 -0
- package/mcp/dist/cli-hooks-session.js +1402 -0
- package/mcp/dist/cli-hooks.js +350 -0
- package/mcp/dist/cli-namespaces.js +989 -0
- package/mcp/dist/cli-ops.js +253 -0
- package/mcp/dist/cli-search.js +407 -0
- package/mcp/dist/cli.js +108 -0
- package/mcp/dist/content-archive.js +278 -0
- package/mcp/dist/content-citation.js +391 -0
- package/mcp/dist/content-dedup.js +622 -0
- package/mcp/dist/content-learning.js +472 -0
- package/mcp/dist/content-metadata.js +186 -0
- package/mcp/dist/content-validate.js +462 -0
- package/mcp/dist/core-finding.js +54 -0
- package/mcp/dist/core-project.js +36 -0
- package/mcp/dist/core-search.js +50 -0
- package/mcp/dist/data-access.js +400 -0
- package/mcp/dist/data-tasks.js +821 -0
- package/mcp/dist/embedding.js +344 -0
- package/mcp/dist/entrypoint.js +387 -0
- package/mcp/dist/finding-context.js +172 -0
- package/mcp/dist/finding-impact.js +181 -0
- package/mcp/dist/finding-journal.js +122 -0
- package/mcp/dist/finding-lifecycle.js +259 -0
- package/mcp/dist/governance-audit.js +22 -0
- package/mcp/dist/governance-locks.js +96 -0
- package/mcp/dist/governance-policy.js +648 -0
- package/mcp/dist/governance-scores.js +355 -0
- package/mcp/dist/hooks.js +449 -0
- package/mcp/dist/impact-scoring.js +22 -0
- package/mcp/dist/index-query.js +168 -0
- package/mcp/dist/index.js +205 -0
- package/mcp/dist/init-config.js +336 -0
- package/mcp/dist/init-preferences.js +62 -0
- package/mcp/dist/init-setup.js +1305 -0
- package/mcp/dist/init-shared.js +29 -0
- package/mcp/dist/init.js +1730 -0
- package/mcp/dist/link-checksums.js +62 -0
- package/mcp/dist/link-context.js +257 -0
- package/mcp/dist/link-doctor.js +591 -0
- package/mcp/dist/link-skills.js +212 -0
- package/mcp/dist/link.js +596 -0
- package/mcp/dist/logger.js +15 -0
- package/mcp/dist/machine-identity.js +38 -0
- package/mcp/dist/mcp-config.js +254 -0
- package/mcp/dist/mcp-data.js +315 -0
- package/mcp/dist/mcp-extract-facts.js +78 -0
- package/mcp/dist/mcp-extract.js +133 -0
- package/mcp/dist/mcp-finding.js +557 -0
- package/mcp/dist/mcp-graph.js +339 -0
- package/mcp/dist/mcp-hooks.js +256 -0
- package/mcp/dist/mcp-memory.js +58 -0
- package/mcp/dist/mcp-ops.js +328 -0
- package/mcp/dist/mcp-search.js +628 -0
- package/mcp/dist/mcp-session.js +651 -0
- package/mcp/dist/mcp-skills.js +189 -0
- package/mcp/dist/mcp-tasks.js +551 -0
- package/mcp/dist/mcp-types.js +7 -0
- package/mcp/dist/memory-ui-assets.js +6 -0
- package/mcp/dist/memory-ui-data.js +513 -0
- package/mcp/dist/memory-ui-graph.js +1910 -0
- package/mcp/dist/memory-ui-page.js +353 -0
- package/mcp/dist/memory-ui-scripts.js +1387 -0
- package/mcp/dist/memory-ui-server.js +1218 -0
- package/mcp/dist/memory-ui-styles.js +555 -0
- package/mcp/dist/memory-ui.js +9 -0
- package/mcp/dist/package-metadata.js +13 -0
- package/mcp/dist/phren-art.js +52 -0
- package/mcp/dist/phren-core.js +108 -0
- package/mcp/dist/phren-dotenv.js +67 -0
- package/mcp/dist/phren-paths.js +476 -0
- package/mcp/dist/proactivity.js +172 -0
- package/mcp/dist/profile-store.js +228 -0
- package/mcp/dist/project-config.js +85 -0
- package/mcp/dist/project-locator.js +25 -0
- package/mcp/dist/project-topics.js +1134 -0
- package/mcp/dist/provider-adapters.js +176 -0
- package/mcp/dist/runtime-profile.js +18 -0
- package/mcp/dist/session-checkpoints.js +131 -0
- package/mcp/dist/session-utils.js +68 -0
- package/mcp/dist/shared-content.js +8 -0
- package/mcp/dist/shared-embedding-cache.js +143 -0
- package/mcp/dist/shared-fragment-graph.js +456 -0
- package/mcp/dist/shared-governance.js +4 -0
- package/mcp/dist/shared-index.js +1334 -0
- package/mcp/dist/shared-ollama.js +192 -0
- package/mcp/dist/shared-paths.js +1 -0
- package/mcp/dist/shared-retrieval.js +796 -0
- package/mcp/dist/shared-search-fallback.js +375 -0
- package/mcp/dist/shared-sqljs.js +42 -0
- package/mcp/dist/shared-stemmer.js +171 -0
- package/mcp/dist/shared-vector-index.js +199 -0
- package/mcp/dist/shared.js +114 -0
- package/mcp/dist/shell-entry.js +209 -0
- package/mcp/dist/shell-input.js +943 -0
- package/mcp/dist/shell-palette.js +119 -0
- package/mcp/dist/shell-render.js +252 -0
- package/mcp/dist/shell-state-store.js +81 -0
- package/mcp/dist/shell-types.js +13 -0
- package/mcp/dist/shell-view-list.js +14 -0
- package/mcp/dist/shell-view.js +707 -0
- package/mcp/dist/shell.js +352 -0
- package/mcp/dist/skill-files.js +117 -0
- package/mcp/dist/skill-registry.js +279 -0
- package/mcp/dist/skill-state.js +28 -0
- package/mcp/dist/startup-embedding.js +57 -0
- package/mcp/dist/status.js +323 -0
- package/mcp/dist/synonyms.json +670 -0
- package/mcp/dist/task-hygiene.js +251 -0
- package/mcp/dist/task-lifecycle.js +347 -0
- package/mcp/dist/tasks-github.js +76 -0
- package/mcp/dist/telemetry.js +165 -0
- package/mcp/dist/test-global-setup.js +37 -0
- package/mcp/dist/tool-registry.js +104 -0
- package/mcp/dist/update.js +97 -0
- package/mcp/dist/utils.js +543 -0
- package/package.json +67 -0
- package/skills/README.md +7 -0
- package/skills/consolidate/SKILL.md +152 -0
- package/skills/discover/SKILL.md +175 -0
- package/skills/init/SKILL.md +216 -0
- package/skills/profiles/SKILL.md +121 -0
- package/skills/sync/SKILL.md +261 -0
- package/starter/README.md +74 -0
- package/starter/global/CLAUDE.md +89 -0
- package/starter/global/skills/humanize.md +30 -0
- package/starter/global/skills/pipeline.md +35 -0
- package/starter/global/skills/release.md +35 -0
- package/starter/machines.yaml +8 -0
- package/starter/my-api/.claude/skills/README.md +7 -0
- package/starter/my-api/CLAUDE.md +33 -0
- package/starter/my-api/FINDINGS.md +9 -0
- package/starter/my-api/summary.md +7 -0
- package/starter/my-api/tasks.md +7 -0
- package/starter/my-first-project/.claude/skills/README.md +7 -0
- package/starter/my-first-project/CLAUDE.md +49 -0
- package/starter/my-first-project/FINDINGS.md +24 -0
- package/starter/my-first-project/summary.md +11 -0
- package/starter/my-first-project/tasks.md +25 -0
- package/starter/my-frontend/.claude/skills/README.md +7 -0
- package/starter/my-frontend/CLAUDE.md +33 -0
- package/starter/my-frontend/FINDINGS.md +9 -0
- package/starter/my-frontend/summary.md +7 -0
- package/starter/my-frontend/tasks.md +7 -0
- package/starter/profiles/default.yaml +4 -0
- package/starter/profiles/personal.yaml +4 -0
- package/starter/profiles/work.yaml +4 -0
- package/starter/templates/README.md +7 -0
- package/starter/templates/frontend/CLAUDE.md +23 -0
- package/starter/templates/frontend/FINDINGS.md +7 -0
- package/starter/templates/frontend/reference/README.md +4 -0
- package/starter/templates/frontend/summary.md +7 -0
- package/starter/templates/frontend/tasks.md +11 -0
- package/starter/templates/library/CLAUDE.md +22 -0
- package/starter/templates/library/FINDINGS.md +7 -0
- package/starter/templates/library/reference/README.md +4 -0
- package/starter/templates/library/summary.md +7 -0
- package/starter/templates/library/tasks.md +11 -0
- package/starter/templates/monorepo/CLAUDE.md +21 -0
- package/starter/templates/monorepo/FINDINGS.md +7 -0
- package/starter/templates/monorepo/reference/README.md +4 -0
- package/starter/templates/monorepo/summary.md +7 -0
- package/starter/templates/monorepo/tasks.md +11 -0
- package/starter/templates/python-project/CLAUDE.md +21 -0
- package/starter/templates/python-project/FINDINGS.md +7 -0
- package/starter/templates/python-project/reference/README.md +4 -0
- package/starter/templates/python-project/summary.md +7 -0
- 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
|
+
}
|