@phren/cli 0.0.50 → 0.0.52
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/mcp/dist/cli/actions.js +17 -2
- package/mcp/dist/cli/cli.js +1 -1
- package/mcp/dist/cli/namespaces.js +35 -10
- package/mcp/dist/cli/ops.js +2 -2
- package/mcp/dist/content/validate.js +18 -0
- package/mcp/dist/data/access.js +27 -0
- package/mcp/dist/data/tasks.js +27 -2
- package/mcp/dist/generated/memory-ui-graph.browser.js +21 -21
- package/mcp/dist/governance/policy.js +3 -1
- package/mcp/dist/memory-ui-graph.runtime.js +21 -21
- package/mcp/dist/phren-core.js +1 -1
- package/mcp/dist/profile-store.js +20 -0
- package/mcp/dist/project-config.js +26 -0
- package/mcp/dist/shared/index.js +1 -1
- package/mcp/dist/shell/view.js +27 -9
- 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 +17 -7
- 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/session.js +58 -18
- package/mcp/dist/tools/tasks.js +58 -44
- package/mcp/dist/ui/data.js +46 -19
- package/mcp/dist/ui/server.js +2 -1
- package/package.json +1 -1
package/mcp/dist/cli/actions.js
CHANGED
|
@@ -15,6 +15,19 @@ import { runSearch, runFragmentSearch, parseFragmentSearchArgs, runRelatedDocs,
|
|
|
15
15
|
import { resolveRuntimeProfile } from "../runtime-profile.js";
|
|
16
16
|
import { getProjectConsolidationStatus, CONSOLIDATION_ENTRY_THRESHOLD } from "../content/validate.js";
|
|
17
17
|
import { listAllSessions } from "../tools/session.js";
|
|
18
|
+
function resolveProjectStorePath(phrenPath, project) {
|
|
19
|
+
try {
|
|
20
|
+
const { getNonPrimaryStores } = require("../store-registry.js");
|
|
21
|
+
if (fs.existsSync(path.join(phrenPath, project)))
|
|
22
|
+
return phrenPath;
|
|
23
|
+
for (const store of getNonPrimaryStores(phrenPath)) {
|
|
24
|
+
if (fs.existsSync(path.join(store.path, project)))
|
|
25
|
+
return store.path;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch { /* fall through */ }
|
|
29
|
+
return phrenPath;
|
|
30
|
+
}
|
|
18
31
|
async function runAndPrint(fn) {
|
|
19
32
|
const result = await fn();
|
|
20
33
|
if (result.lines.length > 0)
|
|
@@ -69,7 +82,8 @@ export async function handleTruths(project) {
|
|
|
69
82
|
process.exit(1);
|
|
70
83
|
}
|
|
71
84
|
const phrenPath = getPhrenPath();
|
|
72
|
-
const
|
|
85
|
+
const storePath = resolveProjectStorePath(phrenPath, project);
|
|
86
|
+
const truthsPath = path.join(storePath, project, "truths.md");
|
|
73
87
|
if (!fs.existsSync(truthsPath)) {
|
|
74
88
|
console.log(`No truths pinned for "${project}" yet.`);
|
|
75
89
|
console.log(`\nPin one: phren pin ${project} "your truth here"`);
|
|
@@ -375,7 +389,8 @@ export async function handleConsolidationStatus(args) {
|
|
|
375
389
|
? (() => {
|
|
376
390
|
if (!isValidProjectName(project))
|
|
377
391
|
return null;
|
|
378
|
-
const
|
|
392
|
+
const storePath = resolveProjectStorePath(phrenPath, project);
|
|
393
|
+
const dir = path.join(storePath, project);
|
|
379
394
|
return fs.existsSync(dir) ? [dir] : [];
|
|
380
395
|
})()
|
|
381
396
|
: getProjectDirs(phrenPath, profile);
|
package/mcp/dist/cli/cli.js
CHANGED
|
@@ -79,7 +79,7 @@ export async function runCliCommand(command, args) {
|
|
|
79
79
|
case "tasks":
|
|
80
80
|
return handleTaskView(getProfile());
|
|
81
81
|
case "sessions":
|
|
82
|
-
return handleSessionsView(args);
|
|
82
|
+
return await handleSessionsView(args);
|
|
83
83
|
case "task":
|
|
84
84
|
return handleTaskNamespace(args);
|
|
85
85
|
case "finding":
|
|
@@ -4,6 +4,19 @@ import { execFileSync } from "child_process";
|
|
|
4
4
|
import { expandHomePath, findArchivedProjectNameCaseInsensitive, findProjectNameCaseInsensitive, getPhrenPath, getProjectDirs, homePath, hookConfigPath, normalizeProjectNameForCreate, readRootManifest, } from "../shared.js";
|
|
5
5
|
import { isValidProjectName, errorMessage } from "../utils.js";
|
|
6
6
|
import { logger } from "../logger.js";
|
|
7
|
+
function resolveProjectStorePath(phrenPath, project) {
|
|
8
|
+
try {
|
|
9
|
+
const { getNonPrimaryStores } = require("../store-registry.js");
|
|
10
|
+
if (fs.existsSync(path.join(phrenPath, project)))
|
|
11
|
+
return phrenPath;
|
|
12
|
+
for (const store of getNonPrimaryStores(phrenPath)) {
|
|
13
|
+
if (fs.existsSync(path.join(store.path, project)))
|
|
14
|
+
return store.path;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch { /* fall through */ }
|
|
18
|
+
return phrenPath;
|
|
19
|
+
}
|
|
7
20
|
import { readInstallPreferences, writeInstallPreferences } from "../init/preferences.js";
|
|
8
21
|
import { buildSkillManifest, findLocalSkill, findSkill, getAllSkills } from "../skill/registry.js";
|
|
9
22
|
import { detectSkillCollisions } from "../link/skills.js";
|
|
@@ -252,10 +265,17 @@ export function handleHooksNamespace(args) {
|
|
|
252
265
|
const hooksEnabled = prefs.hooksEnabled !== false;
|
|
253
266
|
const toolPrefs = prefs.hookTools && typeof prefs.hookTools === "object" ? prefs.hookTools : {};
|
|
254
267
|
const project = getOptionValue(args.slice(1), "--project");
|
|
255
|
-
if (project &&
|
|
268
|
+
if (project && !isValidProjectName(project)) {
|
|
256
269
|
console.error(`Project "${project}" not found.`);
|
|
257
270
|
process.exit(1);
|
|
258
271
|
}
|
|
272
|
+
if (project) {
|
|
273
|
+
const storePath = resolveProjectStorePath(phrenPath, project);
|
|
274
|
+
if (!fs.existsSync(path.join(storePath, project))) {
|
|
275
|
+
console.error(`Project "${project}" not found.`);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
259
279
|
const rows = HOOK_TOOLS.map((tool) => ({
|
|
260
280
|
tool,
|
|
261
281
|
hookType: "lifecycle",
|
|
@@ -663,7 +683,8 @@ export async function handleProjectsNamespace(args, profile) {
|
|
|
663
683
|
process.exit(1);
|
|
664
684
|
}
|
|
665
685
|
const phrenPath = getPhrenPath();
|
|
666
|
-
const
|
|
686
|
+
const storePath = resolveProjectStorePath(phrenPath, name);
|
|
687
|
+
const projectDir = path.join(storePath, name);
|
|
667
688
|
if (!fs.existsSync(projectDir)) {
|
|
668
689
|
console.error(`Project "${name}" not found.`);
|
|
669
690
|
process.exit(1);
|
|
@@ -673,16 +694,16 @@ export async function handleProjectsNamespace(args, profile) {
|
|
|
673
694
|
const summaryPath = path.join(projectDir, "summary.md");
|
|
674
695
|
if (fs.existsSync(summaryPath))
|
|
675
696
|
exported.summary = fs.readFileSync(summaryPath, "utf8");
|
|
676
|
-
const learningsResult = readFindings(
|
|
697
|
+
const learningsResult = readFindings(storePath, name);
|
|
677
698
|
if (learningsResult.ok)
|
|
678
699
|
exported.learnings = learningsResult.data;
|
|
679
700
|
const findingsPath = path.join(projectDir, "FINDINGS.md");
|
|
680
701
|
if (fs.existsSync(findingsPath))
|
|
681
702
|
exported.findingsRaw = fs.readFileSync(findingsPath, "utf8");
|
|
682
|
-
const taskResult = readTasks(
|
|
703
|
+
const taskResult = readTasks(storePath, name);
|
|
683
704
|
if (taskResult.ok) {
|
|
684
705
|
exported.task = taskResult.data.items;
|
|
685
|
-
const taskRawPath = resolveTaskFilePath(
|
|
706
|
+
const taskRawPath = resolveTaskFilePath(storePath, name);
|
|
686
707
|
if (taskRawPath && fs.existsSync(taskRawPath))
|
|
687
708
|
exported.taskRaw = fs.readFileSync(taskRawPath, "utf8");
|
|
688
709
|
}
|
|
@@ -799,8 +820,9 @@ export async function handleProjectsNamespace(args, profile) {
|
|
|
799
820
|
const phrenPath = getPhrenPath();
|
|
800
821
|
if (subcommand === "archive") {
|
|
801
822
|
const activeProject = findProjectNameCaseInsensitive(phrenPath, name);
|
|
802
|
-
const
|
|
803
|
-
const
|
|
823
|
+
const storePath = resolveProjectStorePath(phrenPath, activeProject ?? name);
|
|
824
|
+
const projectDir = activeProject ? path.join(storePath, activeProject) : path.join(storePath, name);
|
|
825
|
+
const archiveDir = path.join(storePath, `${activeProject ?? name}.archived`);
|
|
804
826
|
if (!fs.existsSync(projectDir)) {
|
|
805
827
|
console.error(`Project "${name}" not found.`);
|
|
806
828
|
process.exit(1);
|
|
@@ -826,8 +848,9 @@ export async function handleProjectsNamespace(args, profile) {
|
|
|
826
848
|
process.exit(1);
|
|
827
849
|
}
|
|
828
850
|
const archivedProject = findArchivedProjectNameCaseInsensitive(phrenPath, name);
|
|
829
|
-
const
|
|
830
|
-
const
|
|
851
|
+
const storePath = resolveProjectStorePath(phrenPath, archivedProject ?? name);
|
|
852
|
+
const projectDir = path.join(storePath, archivedProject ?? name);
|
|
853
|
+
const archiveDir = path.join(storePath, `${archivedProject ?? name}.archived`);
|
|
831
854
|
if (!fs.existsSync(archiveDir)) {
|
|
832
855
|
const available = fs.readdirSync(phrenPath)
|
|
833
856
|
.filter((e) => e.endsWith(".archived"))
|
|
@@ -1323,8 +1346,10 @@ export async function handleFindingNamespace(args) {
|
|
|
1323
1346
|
console.error("Usage: phren finding list <project>");
|
|
1324
1347
|
process.exit(1);
|
|
1325
1348
|
}
|
|
1349
|
+
const phrenPath = getPhrenPath();
|
|
1326
1350
|
const { readFindings } = await import("../data/access.js");
|
|
1327
|
-
const
|
|
1351
|
+
const storePath = resolveProjectStorePath(phrenPath, project);
|
|
1352
|
+
const result = readFindings(storePath, project);
|
|
1328
1353
|
if (!result.ok) {
|
|
1329
1354
|
console.error(result.error);
|
|
1330
1355
|
process.exit(1);
|
package/mcp/dist/cli/ops.js
CHANGED
|
@@ -49,7 +49,7 @@ export function handleTaskView(profile) {
|
|
|
49
49
|
}
|
|
50
50
|
console.log(`\n${totalActive} active, ${totalQueue} queued across ${docs.length} project(s).`);
|
|
51
51
|
}
|
|
52
|
-
export function handleSessionsView(args) {
|
|
52
|
+
export async function handleSessionsView(args) {
|
|
53
53
|
const phrenPath = getPhrenPath();
|
|
54
54
|
const sessionId = args[0];
|
|
55
55
|
if (sessionId) {
|
|
@@ -60,7 +60,7 @@ export function handleSessionsView(args) {
|
|
|
60
60
|
console.error(`Session "${sessionId}" not found.`);
|
|
61
61
|
process.exit(1);
|
|
62
62
|
}
|
|
63
|
-
const artifacts = getSessionArtifacts(phrenPath, session.sessionId);
|
|
63
|
+
const artifacts = await getSessionArtifacts(phrenPath, session.sessionId);
|
|
64
64
|
console.log(`Session: ${session.sessionId.slice(0, 8)}`);
|
|
65
65
|
console.log(`Project: ${session.project ?? "—"}`);
|
|
66
66
|
console.log(`Started: ${session.startedAt.slice(0, 16).replace("T", " ")}`);
|
|
@@ -74,6 +74,24 @@ export function checkConsolidationNeeded(phrenPath, profile) {
|
|
|
74
74
|
results.push(status);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
+
// Include projects from team stores
|
|
78
|
+
try {
|
|
79
|
+
const storeRegistry = require("../store-registry.js");
|
|
80
|
+
const { getNonPrimaryStores } = storeRegistry;
|
|
81
|
+
for (const store of getNonPrimaryStores(phrenPath)) {
|
|
82
|
+
if (!fs.existsSync(store.path))
|
|
83
|
+
continue;
|
|
84
|
+
for (const dir of getProjectDirs(store.path)) {
|
|
85
|
+
const status = getProjectConsolidationStatus(dir);
|
|
86
|
+
if (status && status.recommended) {
|
|
87
|
+
results.push(status);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// store-registry not available or error loading, continue with primary only
|
|
94
|
+
}
|
|
77
95
|
return results;
|
|
78
96
|
}
|
|
79
97
|
/**
|
package/mcp/dist/data/access.js
CHANGED
|
@@ -559,6 +559,7 @@ export function readReviewQueueAcrossProjects(phrenPath, profile) {
|
|
|
559
559
|
Conflicts: 2,
|
|
560
560
|
};
|
|
561
561
|
const items = [];
|
|
562
|
+
const seen = new Set(projects);
|
|
562
563
|
for (const project of projects) {
|
|
563
564
|
const result = readReviewQueue(phrenPath, project);
|
|
564
565
|
if (!result.ok)
|
|
@@ -567,6 +568,32 @@ export function readReviewQueueAcrossProjects(phrenPath, profile) {
|
|
|
567
568
|
items.push({ project, ...item });
|
|
568
569
|
}
|
|
569
570
|
}
|
|
571
|
+
// Include projects from team stores
|
|
572
|
+
try {
|
|
573
|
+
const storeRegistry = require("../store-registry.js");
|
|
574
|
+
const { getNonPrimaryStores } = storeRegistry;
|
|
575
|
+
for (const store of getNonPrimaryStores(phrenPath)) {
|
|
576
|
+
if (!fs.existsSync(store.path))
|
|
577
|
+
continue;
|
|
578
|
+
const storeDirs = getProjectDirs(store.path)
|
|
579
|
+
.map((d) => path.basename(d))
|
|
580
|
+
.filter((p) => p !== "global");
|
|
581
|
+
for (const storeProject of storeDirs) {
|
|
582
|
+
if (seen.has(storeProject))
|
|
583
|
+
continue;
|
|
584
|
+
seen.add(storeProject);
|
|
585
|
+
const result = readReviewQueue(store.path, storeProject);
|
|
586
|
+
if (!result.ok)
|
|
587
|
+
continue;
|
|
588
|
+
for (const item of result.data) {
|
|
589
|
+
items.push({ project: storeProject, ...item });
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
catch {
|
|
595
|
+
// store-registry not available or error loading, continue with primary only
|
|
596
|
+
}
|
|
570
597
|
items.sort((a, b) => {
|
|
571
598
|
const aDate = a.date === "unknown" ? "" : a.date;
|
|
572
599
|
const bDate = b.date === "unknown" ? "" : b.date;
|
package/mcp/dist/data/tasks.js
CHANGED
|
@@ -352,9 +352,11 @@ export function readTasks(phrenPath, project) {
|
|
|
352
352
|
return phrenOk(parseTaskContent(project, taskPath, content));
|
|
353
353
|
}
|
|
354
354
|
export function readTasksAcrossProjects(phrenPath, profile) {
|
|
355
|
-
const projects = getProjectDirs(phrenPath, profile).map((dir) => path.basename(dir)).sort();
|
|
356
355
|
const result = [];
|
|
357
|
-
|
|
356
|
+
const seen = new Set();
|
|
357
|
+
// Primary store projects (with profile filtering)
|
|
358
|
+
const primaryProjects = getProjectDirs(phrenPath, profile).map((dir) => path.basename(dir)).sort();
|
|
359
|
+
for (const project of primaryProjects) {
|
|
358
360
|
const file = canonicalTaskFilePath(phrenPath, project);
|
|
359
361
|
if (!file || !fs.existsSync(file))
|
|
360
362
|
continue;
|
|
@@ -362,7 +364,30 @@ export function readTasksAcrossProjects(phrenPath, profile) {
|
|
|
362
364
|
if (!parsed.ok)
|
|
363
365
|
continue;
|
|
364
366
|
result.push(parsed.data);
|
|
367
|
+
seen.add(project);
|
|
365
368
|
}
|
|
369
|
+
// Non-primary store projects (no profile — team stores don't have profiles)
|
|
370
|
+
try {
|
|
371
|
+
const { getNonPrimaryStores } = require("../store-registry.js");
|
|
372
|
+
for (const store of getNonPrimaryStores(phrenPath)) {
|
|
373
|
+
if (!fs.existsSync(store.path))
|
|
374
|
+
continue;
|
|
375
|
+
const storeProjects = getProjectDirs(store.path).map((dir) => path.basename(dir));
|
|
376
|
+
for (const project of storeProjects) {
|
|
377
|
+
if (seen.has(project))
|
|
378
|
+
continue;
|
|
379
|
+
seen.add(project);
|
|
380
|
+
const file = canonicalTaskFilePath(store.path, project);
|
|
381
|
+
if (!file || !fs.existsSync(file))
|
|
382
|
+
continue;
|
|
383
|
+
const parsed = readTasks(store.path, project);
|
|
384
|
+
if (!parsed.ok)
|
|
385
|
+
continue;
|
|
386
|
+
result.push(parsed.data);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
catch { /* store-registry not available — primary only */ }
|
|
366
391
|
return result;
|
|
367
392
|
}
|
|
368
393
|
export function resolveTaskItem(phrenPath, project, match) {
|