@phren/cli 0.0.50 → 0.0.53
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/README.md +11 -0
- package/mcp/dist/cli/actions.js +17 -2
- package/mcp/dist/cli/cli.js +1 -1
- package/mcp/dist/cli/namespaces.js +77 -12
- package/mcp/dist/cli/ops.js +2 -2
- package/mcp/dist/content/validate.js +17 -0
- package/mcp/dist/data/access.js +26 -0
- package/mcp/dist/data/tasks.js +27 -2
- package/mcp/dist/generated/memory-ui-graph.browser.js +29 -26
- package/mcp/dist/governance/policy.js +3 -1
- package/mcp/dist/memory-ui-graph.runtime.js +29 -26
- package/mcp/dist/phren-core.js +1 -1
- package/mcp/dist/profile-store.js +19 -0
- package/mcp/dist/project-config.js +26 -0
- package/mcp/dist/shared/index.js +2 -2
- package/mcp/dist/shell/view.js +32 -12
- package/mcp/dist/store-registry.js +41 -0
- package/mcp/dist/store-routing.js +2 -2
- package/mcp/dist/task/lifecycle.js +11 -0
- package/mcp/dist/tools/config.js +23 -5
- package/mcp/dist/tools/data.js +25 -14
- package/mcp/dist/tools/extract.js +8 -5
- package/mcp/dist/tools/finding.js +14 -9
- package/mcp/dist/tools/graph.js +12 -3
- package/mcp/dist/tools/hooks.js +15 -2
- package/mcp/dist/tools/search.js +8 -9
- package/mcp/dist/tools/session.js +58 -18
- package/mcp/dist/tools/tasks.js +58 -44
- package/mcp/dist/ui/data.js +62 -21
- package/mcp/dist/ui/server.js +2 -1
- package/package.json +1 -1
package/mcp/dist/ui/data.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as fs from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import { createHash } from "crypto";
|
|
4
4
|
import { getProjectDirs, runtimeDir, runtimeHealthFile, memoryUsageLogFile, homePath, } from "../shared.js";
|
|
5
|
-
import { getNonPrimaryStores } from "../store-registry.js";
|
|
5
|
+
import { getNonPrimaryStores, getStoreProjectDirs } from "../store-registry.js";
|
|
6
6
|
import { errorMessage } from "../utils.js";
|
|
7
7
|
import { readInstallPreferences } from "../init/preferences.js";
|
|
8
8
|
import { readCustomHooks } from "../hooks.js";
|
|
@@ -151,42 +151,76 @@ export function getHooksData(phrenPath, profile) {
|
|
|
151
151
|
return { globalEnabled, tools, customHooks: readCustomHooks(phrenPath), projectOverrides };
|
|
152
152
|
}
|
|
153
153
|
export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
154
|
-
|
|
154
|
+
// Collect projects from primary store and all readable non-primary stores
|
|
155
|
+
const storeProjects = [];
|
|
156
|
+
const primaryProjects = getProjectDirs(phrenPath, profile)
|
|
157
|
+
.map((projectDir) => path.basename(projectDir))
|
|
158
|
+
.filter((project) => project !== "global");
|
|
159
|
+
for (const project of primaryProjects)
|
|
160
|
+
storeProjects.push({ storePath: phrenPath, project });
|
|
161
|
+
// Map store paths to store names
|
|
162
|
+
const storePathToName = new Map();
|
|
163
|
+
storePathToName.set(phrenPath, "primary");
|
|
164
|
+
for (const store of getNonPrimaryStores(phrenPath)) {
|
|
165
|
+
if (!fs.existsSync(store.path))
|
|
166
|
+
continue;
|
|
167
|
+
storePathToName.set(store.path, store.name);
|
|
168
|
+
try {
|
|
169
|
+
const storeProjectDirs = getStoreProjectDirs(store)
|
|
170
|
+
.map((projectDir) => path.basename(projectDir))
|
|
171
|
+
.filter((project) => project !== "global");
|
|
172
|
+
for (const project of storeProjectDirs)
|
|
173
|
+
storeProjects.push({ storePath: store.path, project });
|
|
174
|
+
}
|
|
175
|
+
catch { /* store not accessible — skip */ }
|
|
176
|
+
}
|
|
177
|
+
const projects = storeProjects.map((sp) => sp.project);
|
|
155
178
|
const nodes = [];
|
|
156
179
|
const links = [];
|
|
157
180
|
const projectSet = new Set(projects);
|
|
158
181
|
// Collect all unique topics across projects for the UI
|
|
159
182
|
const topicMetaMap = new Map();
|
|
160
|
-
|
|
183
|
+
// Track which project nodes have already been pushed (same name may appear in multiple stores)
|
|
184
|
+
const addedProjectNodeIds = new Set();
|
|
185
|
+
for (const { storePath, project } of storeProjects) {
|
|
161
186
|
// Load dynamic topics for this project
|
|
162
|
-
const { topics: projectTopics } = readProjectTopics(
|
|
187
|
+
const { topics: projectTopics } = readProjectTopics(storePath, project);
|
|
163
188
|
for (const topic of projectTopics) {
|
|
164
189
|
if (!topicMetaMap.has(topic.slug)) {
|
|
165
190
|
topicMetaMap.set(topic.slug, { slug: topic.slug, label: topic.label });
|
|
166
191
|
}
|
|
167
192
|
}
|
|
168
|
-
const findingsPath = path.join(
|
|
193
|
+
const findingsPath = path.join(storePath, project, "FINDINGS.md");
|
|
194
|
+
const storeName = storePathToName.get(storePath) || "unknown";
|
|
169
195
|
if (!fs.existsSync(findingsPath)) {
|
|
196
|
+
if (!addedProjectNodeIds.has(project)) {
|
|
197
|
+
addedProjectNodeIds.add(project);
|
|
198
|
+
nodes.push({
|
|
199
|
+
id: project,
|
|
200
|
+
label: project,
|
|
201
|
+
fullLabel: project,
|
|
202
|
+
group: "project",
|
|
203
|
+
refCount: 0,
|
|
204
|
+
project,
|
|
205
|
+
store: storeName,
|
|
206
|
+
tagged: false,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (!addedProjectNodeIds.has(project)) {
|
|
212
|
+
addedProjectNodeIds.add(project);
|
|
170
213
|
nodes.push({
|
|
171
214
|
id: project,
|
|
172
215
|
label: project,
|
|
173
216
|
fullLabel: project,
|
|
174
217
|
group: "project",
|
|
175
|
-
refCount:
|
|
218
|
+
refCount: 1,
|
|
176
219
|
project,
|
|
220
|
+
store: storeName,
|
|
177
221
|
tagged: false,
|
|
178
222
|
});
|
|
179
|
-
continue;
|
|
180
223
|
}
|
|
181
|
-
nodes.push({
|
|
182
|
-
id: project,
|
|
183
|
-
label: project,
|
|
184
|
-
fullLabel: project,
|
|
185
|
-
group: "project",
|
|
186
|
-
refCount: 1,
|
|
187
|
-
project,
|
|
188
|
-
tagged: false,
|
|
189
|
-
});
|
|
190
224
|
const content = fs.readFileSync(findingsPath, "utf8");
|
|
191
225
|
const lines = content.split("\n");
|
|
192
226
|
// No cap for focused project; high caps otherwise
|
|
@@ -236,6 +270,7 @@ export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
|
236
270
|
group: `topic:${topic.slug}`,
|
|
237
271
|
refCount: taggedCount,
|
|
238
272
|
project,
|
|
273
|
+
store: storeName,
|
|
239
274
|
tagged: true,
|
|
240
275
|
scoreKey,
|
|
241
276
|
scoreKeys: [scoreKey],
|
|
@@ -270,6 +305,7 @@ export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
|
270
305
|
group: `topic:${topic.slug}`,
|
|
271
306
|
refCount: taggedCount,
|
|
272
307
|
project,
|
|
308
|
+
store: storeName,
|
|
273
309
|
tagged: true,
|
|
274
310
|
scoreKey,
|
|
275
311
|
scoreKeys: [scoreKey],
|
|
@@ -304,6 +340,7 @@ export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
|
304
340
|
group: `topic:${topic.slug}`,
|
|
305
341
|
refCount: untaggedAdded,
|
|
306
342
|
project,
|
|
343
|
+
store: storeName,
|
|
307
344
|
tagged: false,
|
|
308
345
|
scoreKey,
|
|
309
346
|
scoreKeys: [scoreKey],
|
|
@@ -316,10 +353,11 @@ export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
|
316
353
|
}
|
|
317
354
|
// ── Tasks ──────────────────────────────────────────────────────────
|
|
318
355
|
try {
|
|
319
|
-
for (const project of
|
|
320
|
-
const taskResult = readTasks(
|
|
356
|
+
for (const { storePath, project } of storeProjects) {
|
|
357
|
+
const taskResult = readTasks(storePath, project);
|
|
321
358
|
if (!taskResult.ok)
|
|
322
359
|
continue;
|
|
360
|
+
const taskStoreName = storePathToName.get(storePath) || "unknown";
|
|
323
361
|
const doc = taskResult.data;
|
|
324
362
|
let taskCount = 0;
|
|
325
363
|
const MAX_TASKS = 50;
|
|
@@ -337,6 +375,7 @@ export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
|
337
375
|
fullLabel: item.line,
|
|
338
376
|
group,
|
|
339
377
|
project,
|
|
378
|
+
store: taskStoreName,
|
|
340
379
|
tagged: false,
|
|
341
380
|
scoreKey,
|
|
342
381
|
scoreKeys: [scoreKey],
|
|
@@ -443,8 +482,9 @@ export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
|
443
482
|
}
|
|
444
483
|
// ── Reference docs ────────────────────────────────────────────────
|
|
445
484
|
try {
|
|
446
|
-
for (const project of
|
|
447
|
-
const
|
|
485
|
+
for (const { storePath, project } of storeProjects) {
|
|
486
|
+
const refStoreName = storePathToName.get(storePath) || "unknown";
|
|
487
|
+
const refDir = path.join(storePath, project, "reference");
|
|
448
488
|
if (!fs.existsSync(refDir) || !fs.statSync(refDir).isDirectory())
|
|
449
489
|
continue;
|
|
450
490
|
const files = fs.readdirSync(refDir);
|
|
@@ -461,6 +501,7 @@ export async function buildGraph(phrenPath, profile, focusProject, existingDb) {
|
|
|
461
501
|
fullLabel: file,
|
|
462
502
|
group: "reference",
|
|
463
503
|
project,
|
|
504
|
+
store: refStoreName,
|
|
464
505
|
tagged: false,
|
|
465
506
|
scoreKeys: [],
|
|
466
507
|
refDocs: [{ doc: docRef, project }],
|
|
@@ -613,7 +654,7 @@ export function collectProjectsForUI(phrenPath, profile) {
|
|
|
613
654
|
for (const store of teamStores) {
|
|
614
655
|
if (!fs.existsSync(store.path))
|
|
615
656
|
continue;
|
|
616
|
-
const teamProjects =
|
|
657
|
+
const teamProjects = getStoreProjectDirs(store).map((d) => path.basename(d)).filter((p) => p !== "global");
|
|
617
658
|
for (const project of teamProjects) {
|
|
618
659
|
if (seen.has(project))
|
|
619
660
|
continue; // skip if same name exists in primary
|
package/mcp/dist/ui/server.js
CHANGED
|
@@ -543,7 +543,8 @@ function handleGetFindings(res, pathname, ctx) {
|
|
|
543
543
|
const project = decodeURIComponent(pathname.slice("/api/findings/".length));
|
|
544
544
|
if (!project || !isValidProjectName(project))
|
|
545
545
|
return jsonErr(res, "Invalid project name", 400);
|
|
546
|
-
const
|
|
546
|
+
const basePath = resolveProjectBasePath(ctx.phrenPath, project);
|
|
547
|
+
const result = readFindings(basePath, project);
|
|
547
548
|
jsonOk(res, result.ok ? { ok: true, data: { project, findings: result.data } } : { ok: false, error: result.error });
|
|
548
549
|
}
|
|
549
550
|
// ── POST handlers ─────────────────────────────────────────────────────────────
|