@phren/cli 0.0.28 → 0.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mcp/dist/capabilities/cli.js +2 -5
- package/mcp/dist/capabilities/mcp.js +5 -8
- package/mcp/dist/capabilities/types.js +2 -5
- package/mcp/dist/capabilities/vscode.js +2 -5
- package/mcp/dist/capabilities/web-ui.js +2 -5
- package/mcp/dist/{cli-actions.js → cli/actions.js} +25 -21
- package/mcp/dist/{cli.js → cli/cli.js} +13 -13
- package/mcp/dist/{cli-config.js → cli/config.js} +12 -12
- package/mcp/dist/{cli-extract.js → cli/extract.js} +8 -8
- package/mcp/dist/{cli-govern.js → cli/govern.js} +28 -17
- package/mcp/dist/{cli-graph.js → cli/graph.js} +10 -9
- package/mcp/dist/{cli-hooks-citations.js → cli/hooks-citations.js} +2 -2
- package/mcp/dist/{cli-hooks-context.js → cli/hooks-context.js} +23 -23
- package/mcp/dist/{cli-hooks-globs.js → cli/hooks-globs.js} +4 -4
- package/mcp/dist/{cli-hooks-output.js → cli/hooks-output.js} +9 -10
- package/mcp/dist/{cli-hooks-session.js → cli/hooks-session.js} +58 -117
- package/mcp/dist/{cli-hooks.js → cli/hooks.js} +27 -26
- package/mcp/dist/{cli-namespaces.js → cli/namespaces.js} +25 -24
- package/mcp/dist/{cli-ops.js → cli/ops.js} +9 -9
- package/mcp/dist/{cli-search.js → cli/search.js} +12 -11
- package/mcp/dist/cli-hooks-git.js +243 -0
- package/mcp/dist/cli-hooks-prompt.js +323 -0
- package/mcp/dist/cli-hooks-session-handlers.js +337 -0
- package/mcp/dist/cli-hooks-stop.js +519 -0
- package/mcp/dist/{content-archive.js → content/archive.js} +16 -29
- package/mcp/dist/{content-citation.js → content/citation.js} +5 -5
- package/mcp/dist/{content-dedup.js → content/dedup.js} +9 -12
- package/mcp/dist/{content-learning.js → content/learning.js} +41 -20
- package/mcp/dist/{content-validate.js → content/validate.js} +5 -5
- package/mcp/dist/{core-finding.js → core/finding.js} +4 -4
- package/mcp/dist/{core-project.js → core/project.js} +4 -4
- package/mcp/dist/{core-search.js → core/search.js} +2 -2
- package/mcp/dist/{data-access.js → data/access.js} +142 -15
- package/mcp/dist/{data-tasks.js → data/tasks.js} +7 -5
- package/mcp/dist/embedding.js +9 -14
- package/mcp/dist/entrypoint.js +11 -11
- package/mcp/dist/{finding-context.js → finding/context.js} +2 -2
- package/mcp/dist/{finding-impact.js → finding/impact.js} +3 -3
- package/mcp/dist/{finding-journal.js → finding/journal.js} +4 -4
- package/mcp/dist/{finding-lifecycle.js → finding/lifecycle.js} +13 -7
- package/mcp/dist/governance/audit.js +30 -0
- package/mcp/dist/{governance-locks.js → governance/locks.js} +14 -9
- package/mcp/dist/{governance-policy.js → governance/policy.js} +23 -12
- package/mcp/dist/{governance-rbac.js → governance/rbac.js} +4 -4
- package/mcp/dist/{governance-scores.js → governance/scores.js} +10 -11
- package/mcp/dist/hooks.js +53 -37
- package/mcp/dist/index-query.js +4 -1
- package/mcp/dist/index.js +54 -30
- package/mcp/dist/{init-config.js → init/config.js} +6 -6
- package/mcp/dist/{init.js → init/init.js} +80 -69
- package/mcp/dist/{init-preferences.js → init/preferences.js} +3 -3
- package/mcp/dist/{init-setup.js → init/setup.js} +17 -19
- package/mcp/dist/{init-shared.js → init/shared.js} +4 -4
- package/mcp/dist/init-bootstrap.js +21 -0
- package/mcp/dist/init-detect.js +38 -0
- package/mcp/dist/init-env.js +114 -0
- package/mcp/dist/init-fresh.js +234 -0
- package/mcp/dist/init-hooks.js +26 -0
- package/mcp/dist/init-mcp.js +65 -0
- package/mcp/dist/init-modes.js +135 -0
- package/mcp/dist/init-npm.js +37 -0
- package/mcp/dist/init-project-local.js +99 -0
- package/mcp/dist/init-semantic.js +48 -0
- package/mcp/dist/init-types.js +1 -0
- package/mcp/dist/init-uninstall.js +504 -0
- package/mcp/dist/init-update.js +96 -0
- package/mcp/dist/init-walkthrough.js +524 -0
- package/mcp/dist/{link-checksums.js → link/checksums.js} +5 -5
- package/mcp/dist/{link-context.js → link/context.js} +4 -4
- package/mcp/dist/{link-doctor.js → link/doctor.js} +20 -22
- package/mcp/dist/{link.js → link/link.js} +26 -31
- package/mcp/dist/{link-skills.js → link/skills.js} +10 -10
- package/mcp/dist/logger.js +11 -3
- package/mcp/dist/package-metadata.js +1 -1
- package/mcp/dist/phren-art.js +4 -126
- package/mcp/dist/phren-paths.js +30 -12
- package/mcp/dist/proactivity.js +3 -3
- package/mcp/dist/profile-store.js +5 -6
- package/mcp/dist/project-config.js +2 -2
- package/mcp/dist/project-topics.js +17 -47
- package/mcp/dist/provider-adapters.js +1 -1
- package/mcp/dist/query-correlation.js +1 -1
- package/mcp/dist/runtime-profile.js +1 -1
- package/mcp/dist/{session-checkpoints.js → session/checkpoints.js} +3 -3
- package/mcp/dist/{session-utils.js → session/utils.js} +1 -1
- package/mcp/dist/{shared-content.js → shared/content.js} +7 -7
- package/mcp/dist/{shared-data-utils.js → shared/data-utils.js} +28 -3
- package/mcp/dist/{shared-embedding-cache.js → shared/embedding-cache.js} +3 -3
- package/mcp/dist/{shared-fragment-graph.js → shared/fragment-graph.js} +19 -42
- package/mcp/dist/shared/governance.js +4 -0
- package/mcp/dist/{shared-index.js → shared/index.js} +105 -132
- package/mcp/dist/{shared-ollama.js → shared/ollama.js} +25 -7
- package/mcp/dist/shared/process.js +24 -0
- package/mcp/dist/{shared-retrieval.js → shared/retrieval.js} +22 -24
- package/mcp/dist/{shared-search-fallback.js → shared/search-fallback.js} +18 -20
- package/mcp/dist/{shared-sqljs.js → shared/sqljs.js} +3 -3
- package/mcp/dist/{shared-vector-index.js → shared/vector-index.js} +3 -3
- package/mcp/dist/shared.js +6 -60
- package/mcp/dist/{shell-entry.js → shell/entry.js} +6 -6
- package/mcp/dist/{shell-input.js → shell/input.js} +13 -13
- package/mcp/dist/{shell-palette.js → shell/palette.js} +3 -3
- package/mcp/dist/{shell-render.js → shell/render.js} +2 -2
- package/mcp/dist/{shell.js → shell/shell.js} +11 -11
- package/mcp/dist/{shell-state-store.js → shell/state-store.js} +5 -5
- package/mcp/dist/{shell-view-list.js → shell/view-list.js} +1 -1
- package/mcp/dist/{shell-view.js → shell/view.js} +13 -13
- package/mcp/dist/{skill-files.js → skill/files.js} +9 -9
- package/mcp/dist/{skill-registry.js → skill/registry.js} +5 -5
- package/mcp/dist/{skill-state.js → skill/state.js} +1 -4
- package/mcp/dist/startup-embedding.js +2 -2
- package/mcp/dist/status.js +15 -14
- package/mcp/dist/{tasks-github.js → task/github.js} +3 -2
- package/mcp/dist/{task-hygiene.js → task/hygiene.js} +4 -4
- package/mcp/dist/{task-lifecycle.js → task/lifecycle.js} +8 -13
- package/mcp/dist/telemetry.js +3 -4
- package/mcp/dist/tool-registry.js +29 -17
- package/mcp/dist/tools/config.js +530 -0
- package/mcp/dist/{mcp-data.js → tools/data.js} +8 -10
- package/mcp/dist/{mcp-extract-facts.js → tools/extract-facts.js} +6 -6
- package/mcp/dist/{mcp-extract.js → tools/extract.js} +6 -6
- package/mcp/dist/tools/finding.js +584 -0
- package/mcp/dist/{mcp-graph.js → tools/graph.js} +11 -14
- package/mcp/dist/{mcp-hooks.js → tools/hooks.js} +6 -6
- package/mcp/dist/{mcp-memory.js → tools/memory.js} +5 -5
- package/mcp/dist/tools/ops.js +468 -0
- package/mcp/dist/tools/search.js +672 -0
- package/mcp/dist/{mcp-session.js → tools/session.js} +51 -25
- package/mcp/dist/{mcp-skills.js → tools/skills.js} +42 -35
- package/mcp/dist/{mcp-tasks.js → tools/tasks.js} +155 -282
- package/mcp/dist/{memory-ui-data.js → ui/data.js} +31 -17
- package/mcp/dist/{memory-ui.js → ui/memory-ui.js} +3 -3
- package/mcp/dist/{memory-ui-page.js → ui/page.js} +5 -7
- package/mcp/dist/ui/server.js +1024 -0
- package/mcp/dist/update.js +2 -2
- package/mcp/dist/utils.js +63 -19
- package/package.json +2 -2
- package/scripts/preuninstall.mjs +31 -0
- package/starter/global/CLAUDE.md +3 -2
- package/mcp/dist/governance-audit.js +0 -22
- package/mcp/dist/mcp-config.js +0 -551
- package/mcp/dist/mcp-finding.js +0 -594
- package/mcp/dist/mcp-ops.js +0 -363
- package/mcp/dist/mcp-search.js +0 -668
- package/mcp/dist/memory-ui-server.js +0 -1411
- package/mcp/dist/shared-governance.js +0 -4
- /package/mcp/dist/{content-metadata.js → content/metadata.js} +0 -0
- /package/mcp/dist/{shared-stemmer.js → shared/stemmer.js} +0 -0
- /package/mcp/dist/{shell-types.js → shell/types.js} +0 -0
- /package/mcp/dist/{mcp-types.js → tools/types.js} +0 -0
- /package/mcp/dist/{memory-ui-assets.js → ui/assets.js} +0 -0
- /package/mcp/dist/{memory-ui-graph.js → ui/graph.js} +0 -0
- /package/mcp/dist/{memory-ui-scripts.js → ui/scripts.js} +0 -0
- /package/mcp/dist/{memory-ui-styles.js → ui/styles.js} +0 -0
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import { buildHookContext, handleGuardSkip, debugLog, appendAuditLog, runtimeFile, sessionMarker, EXEC_TIMEOUT_MS, getPhrenPath, getProjectDirs, findProjectNameCaseInsensitive, homePath, updateRuntimeHealth, withFileLock, getWorkflowPolicy, appendReviewQueue, recordFeedback, getQualityMultiplier, detectProject, isProjectHookEnabled, readProjectConfig, getProjectSourcePath, detectProjectDir, ensureLocalGitRepo, isProjectTracked, repairPreexistingInstall, getProactivityLevelForTask, getProactivityLevelForFindings, hasExplicitFindingSignal, shouldAutoCaptureFindingsForLevel, FINDING_SENSITIVITY_CONFIG, isFeatureEnabled, errorMessage, bootstrapPhrenDotEnv, finalizeTaskSession, appendFindingJournal, runDoctor, resolveRuntimeProfile, } from "./
|
|
2
|
-
import { sessionMetricsFile, qualityMarkers, } from "
|
|
3
|
-
import { autoMergeConflicts, mergeTask, mergeFindings, } from "
|
|
4
|
-
import { runGit } from "
|
|
5
|
-
import { readInstallPreferences } from "
|
|
1
|
+
import { buildHookContext, handleGuardSkip, debugLog, appendAuditLog, runtimeFile, sessionMarker, EXEC_TIMEOUT_MS, getPhrenPath, getProjectDirs, findProjectNameCaseInsensitive, homePath, updateRuntimeHealth, withFileLock, getWorkflowPolicy, appendReviewQueue, recordFeedback, getQualityMultiplier, detectProject, isProjectHookEnabled, readProjectConfig, getProjectSourcePath, detectProjectDir, ensureLocalGitRepo, isProjectTracked, repairPreexistingInstall, getProactivityLevelForTask, getProactivityLevelForFindings, hasExplicitFindingSignal, shouldAutoCaptureFindingsForLevel, FINDING_SENSITIVITY_CONFIG, isFeatureEnabled, errorMessage, bootstrapPhrenDotEnv, finalizeTaskSession, appendFindingJournal, runDoctor, resolveRuntimeProfile, buildSyncStatus, } from "./hooks-context.js";
|
|
2
|
+
import { sessionMetricsFile, qualityMarkers, } from "../shared.js";
|
|
3
|
+
import { autoMergeConflicts, mergeTask, mergeFindings, } from "../shared/content.js";
|
|
4
|
+
import { runGit } from "../utils.js";
|
|
5
|
+
import { readInstallPreferences } from "../init/preferences.js";
|
|
6
6
|
import * as fs from "fs";
|
|
7
7
|
import * as path from "path";
|
|
8
8
|
import * as os from "os";
|
|
9
|
-
import { execFileSync
|
|
9
|
+
import { execFileSync } from "child_process";
|
|
10
|
+
import { spawnDetachedChild } from "../shared/process.js";
|
|
10
11
|
import { fileURLToPath } from "url";
|
|
11
|
-
import { isTaskFileName, TASKS_FILENAME } from "
|
|
12
|
-
import { buildIndex, queryRows, } from "
|
|
13
|
-
import { filterTaskByPriority } from "
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export { buildHookContext,
|
|
12
|
+
import { isTaskFileName, TASKS_FILENAME } from "../data/tasks.js";
|
|
13
|
+
import { buildIndex, queryRows, } from "../shared/index.js";
|
|
14
|
+
import { filterTaskByPriority } from "../shared/retrieval.js";
|
|
15
|
+
import { logger } from "../logger.js";
|
|
16
|
+
const SYNC_LOCK_STALE_MS = 10 * 60 * 1000; // 10 minutes
|
|
17
|
+
const MAINTENANCE_LOCK_STALE_MS = 2 * 60 * 60 * 1000; // 2 hours
|
|
18
|
+
export { buildHookContext, handleGuardSkip } from "./hooks-context.js";
|
|
18
19
|
/** Read JSON from stdin if it's not a TTY. Returns null if stdin is a TTY or parsing fails. */
|
|
19
20
|
function readStdinJson() {
|
|
20
21
|
if (process.stdin.isTTY)
|
|
@@ -23,8 +24,7 @@ function readStdinJson() {
|
|
|
23
24
|
return JSON.parse(fs.readFileSync(0, "utf-8"));
|
|
24
25
|
}
|
|
25
26
|
catch (err) {
|
|
26
|
-
|
|
27
|
-
process.stderr.write(`[phren] readStdinJson: ${errorMessage(err)}\n`);
|
|
27
|
+
logger.debug("hooks-session", `readStdinJson: ${errorMessage(err)}`);
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -230,13 +230,17 @@ export function trackSessionMetrics(phrenPathLocal, sessionId, selected) {
|
|
|
230
230
|
}
|
|
231
231
|
// ── Background maintenance ───────────────────────────────────────────────────
|
|
232
232
|
export function resolveSubprocessArgs(command) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
233
|
+
// Prefer the entry script that started this process
|
|
234
|
+
const entry = process.argv[1];
|
|
235
|
+
if (entry && fs.existsSync(entry) && /index\.(ts|js)$/.test(entry))
|
|
236
|
+
return [entry, command];
|
|
237
|
+
// Fallback: look for index.js next to this file or one level up (for subdirectory builds)
|
|
238
|
+
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
239
|
+
for (const dir of [thisDir, path.dirname(thisDir)]) {
|
|
240
|
+
const candidate = path.join(dir, "index.js");
|
|
241
|
+
if (fs.existsSync(candidate))
|
|
242
|
+
return [candidate, command];
|
|
243
|
+
}
|
|
240
244
|
return null;
|
|
241
245
|
}
|
|
242
246
|
function scheduleBackgroundSync(phrenPathLocal) {
|
|
@@ -248,7 +252,7 @@ function scheduleBackgroundSync(phrenPathLocal) {
|
|
|
248
252
|
try {
|
|
249
253
|
if (fs.existsSync(lockPath)) {
|
|
250
254
|
const ageMs = Date.now() - fs.statSync(lockPath).mtimeMs;
|
|
251
|
-
if (ageMs <=
|
|
255
|
+
if (ageMs <= SYNC_LOCK_STALE_MS)
|
|
252
256
|
return false;
|
|
253
257
|
fs.unlinkSync(lockPath);
|
|
254
258
|
}
|
|
@@ -261,16 +265,7 @@ function scheduleBackgroundSync(phrenPathLocal) {
|
|
|
261
265
|
fs.writeFileSync(lockPath, JSON.stringify({ startedAt: new Date().toISOString(), pid: process.pid }) + "\n", { flag: "wx" });
|
|
262
266
|
const logFd = fs.openSync(logPath, "a");
|
|
263
267
|
fs.writeSync(logFd, `[${new Date().toISOString()}] spawn ${process.execPath} ${spawnArgs.join(" ")}\n`);
|
|
264
|
-
const child =
|
|
265
|
-
cwd: process.cwd(),
|
|
266
|
-
detached: true,
|
|
267
|
-
stdio: ["ignore", logFd, logFd],
|
|
268
|
-
env: {
|
|
269
|
-
...process.env,
|
|
270
|
-
PHREN_PATH: phrenPathLocal,
|
|
271
|
-
PHREN_PROFILE: getRuntimeProfile(),
|
|
272
|
-
},
|
|
273
|
-
});
|
|
268
|
+
const child = spawnDetachedChild(spawnArgs, { phrenPath: phrenPathLocal, logFd });
|
|
274
269
|
child.unref();
|
|
275
270
|
fs.closeSync(logFd);
|
|
276
271
|
return true;
|
|
@@ -293,7 +288,7 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
|
|
|
293
288
|
if (fs.existsSync(markers.lock)) {
|
|
294
289
|
try {
|
|
295
290
|
const ageMs = Date.now() - fs.statSync(markers.lock).mtimeMs;
|
|
296
|
-
if (ageMs <=
|
|
291
|
+
if (ageMs <= MAINTENANCE_LOCK_STALE_MS)
|
|
297
292
|
return false;
|
|
298
293
|
fs.unlinkSync(markers.lock);
|
|
299
294
|
}
|
|
@@ -319,8 +314,7 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
|
|
|
319
314
|
}
|
|
320
315
|
catch (err) {
|
|
321
316
|
// Another process already claimed the lock
|
|
322
|
-
|
|
323
|
-
process.stderr.write(`[phren] backgroundMaintenance lockClaim: ${errorMessage(err)}\n`);
|
|
317
|
+
logger.debug("hooks-session", `backgroundMaintenance lockClaim: ${errorMessage(err)}`);
|
|
324
318
|
return false;
|
|
325
319
|
}
|
|
326
320
|
try {
|
|
@@ -336,40 +330,28 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
|
|
|
336
330
|
const logPath = path.join(logDir, "background-maintenance.log");
|
|
337
331
|
const logFd = fs.openSync(logPath, "a");
|
|
338
332
|
fs.writeSync(logFd, `[${new Date().toISOString()}] spawn ${process.execPath} ${spawnArgs.join(" ")}\n`);
|
|
339
|
-
const child =
|
|
340
|
-
cwd: process.cwd(),
|
|
341
|
-
detached: true,
|
|
342
|
-
stdio: ["ignore", logFd, logFd],
|
|
343
|
-
env: {
|
|
344
|
-
...process.env,
|
|
345
|
-
PHREN_PATH: phrenPathLocal,
|
|
346
|
-
PHREN_PROFILE: getRuntimeProfile(),
|
|
347
|
-
},
|
|
348
|
-
});
|
|
333
|
+
const child = spawnDetachedChild(spawnArgs, { phrenPath: phrenPathLocal, logFd });
|
|
349
334
|
child.on("exit", (code, signal) => {
|
|
350
335
|
const msg = `[${new Date().toISOString()}] exit code=${code ?? "null"} signal=${signal ?? "none"}\n`;
|
|
351
336
|
try {
|
|
352
337
|
fs.appendFileSync(logPath, msg);
|
|
353
338
|
}
|
|
354
339
|
catch (err) {
|
|
355
|
-
|
|
356
|
-
process.stderr.write(`[phren] backgroundMaintenance exitLog: ${errorMessage(err)}\n`);
|
|
340
|
+
logger.debug("hooks-session", `backgroundMaintenance exitLog: ${errorMessage(err)}`);
|
|
357
341
|
}
|
|
358
342
|
if (code === 0) {
|
|
359
343
|
try {
|
|
360
344
|
fs.writeFileSync(markers.done, new Date().toISOString() + "\n");
|
|
361
345
|
}
|
|
362
346
|
catch (err) {
|
|
363
|
-
|
|
364
|
-
process.stderr.write(`[phren] backgroundMaintenance doneMarker: ${errorMessage(err)}\n`);
|
|
347
|
+
logger.debug("hooks-session", `backgroundMaintenance doneMarker: ${errorMessage(err)}`);
|
|
365
348
|
}
|
|
366
349
|
}
|
|
367
350
|
try {
|
|
368
351
|
fs.unlinkSync(markers.lock);
|
|
369
352
|
}
|
|
370
353
|
catch (err) {
|
|
371
|
-
|
|
372
|
-
process.stderr.write(`[phren] backgroundMaintenance unlockOnExit: ${errorMessage(err)}\n`);
|
|
354
|
+
logger.debug("hooks-session", `backgroundMaintenance unlockOnExit: ${errorMessage(err)}`);
|
|
373
355
|
}
|
|
374
356
|
});
|
|
375
357
|
child.on("error", (spawnErr) => {
|
|
@@ -378,15 +360,13 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
|
|
|
378
360
|
fs.appendFileSync(logPath, msg);
|
|
379
361
|
}
|
|
380
362
|
catch (err) {
|
|
381
|
-
|
|
382
|
-
process.stderr.write(`[phren] backgroundMaintenance errorLog: ${errorMessage(err)}\n`);
|
|
363
|
+
logger.debug("hooks-session", `backgroundMaintenance errorLog: ${errorMessage(err)}`);
|
|
383
364
|
}
|
|
384
365
|
try {
|
|
385
366
|
fs.unlinkSync(markers.lock);
|
|
386
367
|
}
|
|
387
368
|
catch (err) {
|
|
388
|
-
|
|
389
|
-
process.stderr.write(`[phren] backgroundMaintenance unlockOnError: ${errorMessage(err)}\n`);
|
|
369
|
+
logger.debug("hooks-session", `backgroundMaintenance unlockOnError: ${errorMessage(err)}`);
|
|
390
370
|
}
|
|
391
371
|
});
|
|
392
372
|
fs.closeSync(logFd);
|
|
@@ -401,15 +381,13 @@ function scheduleBackgroundMaintenance(phrenPathLocal, project) {
|
|
|
401
381
|
fs.appendFileSync(path.join(logDir, "background-maintenance.log"), `[${new Date().toISOString()}] spawn failed: ${errMsg}\n`);
|
|
402
382
|
}
|
|
403
383
|
catch (err) {
|
|
404
|
-
|
|
405
|
-
process.stderr.write(`[phren] backgroundMaintenance logSpawnFailure: ${errorMessage(err)}\n`);
|
|
384
|
+
logger.debug("hooks-session", `backgroundMaintenance logSpawnFailure: ${errorMessage(err)}`);
|
|
406
385
|
}
|
|
407
386
|
try {
|
|
408
387
|
fs.unlinkSync(markers.lock);
|
|
409
388
|
}
|
|
410
389
|
catch (err) {
|
|
411
|
-
|
|
412
|
-
process.stderr.write(`[phren] backgroundMaintenance unlockOnFailure: ${errorMessage(err)}\n`);
|
|
390
|
+
logger.debug("hooks-session", `backgroundMaintenance unlockOnFailure: ${errorMessage(err)}`);
|
|
413
391
|
}
|
|
414
392
|
return false;
|
|
415
393
|
}
|
|
@@ -608,12 +586,11 @@ export async function handleHookSessionStart() {
|
|
|
608
586
|
const maintenanceScheduled = scheduleBackgroundMaintenance(phrenPath);
|
|
609
587
|
const unsyncedCommits = hasRemote ? await countUnsyncedCommits(phrenPath) : 0;
|
|
610
588
|
try {
|
|
611
|
-
const { trackSession } = await import("
|
|
589
|
+
const { trackSession } = await import("../telemetry.js");
|
|
612
590
|
trackSession(phrenPath);
|
|
613
591
|
}
|
|
614
592
|
catch (err) {
|
|
615
|
-
|
|
616
|
-
process.stderr.write(`[phren] hookSessionStart trackSession: ${errorMessage(err)}\n`);
|
|
593
|
+
logger.debug("hooks-session", `hookSessionStart trackSession: ${errorMessage(err)}`);
|
|
617
594
|
}
|
|
618
595
|
updateRuntimeHealth(phrenPath, {
|
|
619
596
|
lastSessionStartAt: startedAt,
|
|
@@ -779,8 +756,7 @@ export async function handleHookStop() {
|
|
|
779
756
|
}
|
|
780
757
|
}
|
|
781
758
|
catch (err) {
|
|
782
|
-
|
|
783
|
-
process.stderr.write(`[phren] hookStop transcriptParse: ${errorMessage(err)}\n`);
|
|
759
|
+
logger.debug("hooks-session", `hookStop transcriptParse: ${errorMessage(err)}`);
|
|
784
760
|
}
|
|
785
761
|
}
|
|
786
762
|
captureInput = assistantTexts.join("\n");
|
|
@@ -804,8 +780,7 @@ export async function handleHookStop() {
|
|
|
804
780
|
}
|
|
805
781
|
}
|
|
806
782
|
catch (err) {
|
|
807
|
-
|
|
808
|
-
process.stderr.write(`[phren] hookStop sessionCapCheck: ${errorMessage(err)}\n`);
|
|
783
|
+
logger.debug("hooks-session", `hookStop sessionCapCheck: ${errorMessage(err)}`);
|
|
809
784
|
}
|
|
810
785
|
}
|
|
811
786
|
if (!capReached) {
|
|
@@ -1026,12 +1001,7 @@ export async function handleBackgroundSync() {
|
|
|
1026
1001
|
const unsyncedCommits = await countUnsyncedCommits(phrenPathLocal);
|
|
1027
1002
|
updateRuntimeHealth(phrenPathLocal, {
|
|
1028
1003
|
lastAutoSave: { at: now, status: "saved-local", detail: "background sync skipped; no remote configured" },
|
|
1029
|
-
lastSync: {
|
|
1030
|
-
lastPushAt: now,
|
|
1031
|
-
lastPushStatus: "saved-local",
|
|
1032
|
-
lastPushDetail: "background sync skipped; no remote configured",
|
|
1033
|
-
unsyncedCommits,
|
|
1034
|
-
},
|
|
1004
|
+
lastSync: buildSyncStatus({ now, pushStatus: "saved-local", pushDetail: "background sync skipped; no remote configured", unsyncedCommits }),
|
|
1035
1005
|
});
|
|
1036
1006
|
appendAuditLog(phrenPathLocal, "background_sync", "status=saved-local detail=no_remote");
|
|
1037
1007
|
return;
|
|
@@ -1040,12 +1010,7 @@ export async function handleBackgroundSync() {
|
|
|
1040
1010
|
if (push.ok) {
|
|
1041
1011
|
updateRuntimeHealth(phrenPathLocal, {
|
|
1042
1012
|
lastAutoSave: { at: now, status: "saved-pushed", detail: "commit pushed by background sync" },
|
|
1043
|
-
lastSync: {
|
|
1044
|
-
lastPushAt: now,
|
|
1045
|
-
lastPushStatus: "saved-pushed",
|
|
1046
|
-
lastPushDetail: "commit pushed by background sync",
|
|
1047
|
-
unsyncedCommits: 0,
|
|
1048
|
-
},
|
|
1013
|
+
lastSync: buildSyncStatus({ now, pushStatus: "saved-pushed", pushDetail: "commit pushed by background sync", unsyncedCommits: 0 }),
|
|
1049
1014
|
});
|
|
1050
1015
|
appendAuditLog(phrenPathLocal, "background_sync", "status=saved-pushed");
|
|
1051
1016
|
return;
|
|
@@ -1054,34 +1019,18 @@ export async function handleBackgroundSync() {
|
|
|
1054
1019
|
if (recovered.ok) {
|
|
1055
1020
|
updateRuntimeHealth(phrenPathLocal, {
|
|
1056
1021
|
lastAutoSave: { at: now, status: "saved-pushed", detail: recovered.detail },
|
|
1057
|
-
lastSync: {
|
|
1058
|
-
lastPullAt: now,
|
|
1059
|
-
lastPullStatus: recovered.pullStatus,
|
|
1060
|
-
lastPullDetail: recovered.pullDetail,
|
|
1061
|
-
lastSuccessfulPullAt: now,
|
|
1062
|
-
lastPushAt: now,
|
|
1063
|
-
lastPushStatus: "saved-pushed",
|
|
1064
|
-
lastPushDetail: recovered.detail,
|
|
1065
|
-
unsyncedCommits: 0,
|
|
1066
|
-
},
|
|
1022
|
+
lastSync: buildSyncStatus({ now, pushStatus: "saved-pushed", pushDetail: recovered.detail, pullAt: now, pullStatus: recovered.pullStatus, pullDetail: recovered.pullDetail, successfulPullAt: now, unsyncedCommits: 0 }),
|
|
1067
1023
|
});
|
|
1068
1024
|
appendAuditLog(phrenPathLocal, "background_sync", `status=saved-pushed detail=${JSON.stringify(recovered.detail)}`);
|
|
1069
1025
|
return;
|
|
1070
1026
|
}
|
|
1071
1027
|
const unsyncedCommits = await countUnsyncedCommits(phrenPathLocal);
|
|
1028
|
+
const failDetail = recovered.detail || push.error || "background sync push failed";
|
|
1072
1029
|
updateRuntimeHealth(phrenPathLocal, {
|
|
1073
|
-
lastAutoSave: { at: now, status: "saved-local", detail:
|
|
1074
|
-
lastSync: {
|
|
1075
|
-
lastPullAt: now,
|
|
1076
|
-
lastPullStatus: recovered.pullStatus,
|
|
1077
|
-
lastPullDetail: recovered.pullDetail,
|
|
1078
|
-
lastPushAt: now,
|
|
1079
|
-
lastPushStatus: "saved-local",
|
|
1080
|
-
lastPushDetail: recovered.detail || push.error || "background sync push failed",
|
|
1081
|
-
unsyncedCommits,
|
|
1082
|
-
},
|
|
1030
|
+
lastAutoSave: { at: now, status: "saved-local", detail: failDetail },
|
|
1031
|
+
lastSync: buildSyncStatus({ now, pushStatus: "saved-local", pushDetail: failDetail, pullAt: now, pullStatus: recovered.pullStatus, pullDetail: recovered.pullDetail, unsyncedCommits }),
|
|
1083
1032
|
});
|
|
1084
|
-
appendAuditLog(phrenPathLocal, "background_sync", `status=saved-local detail=${JSON.stringify(
|
|
1033
|
+
appendAuditLog(phrenPathLocal, "background_sync", `status=saved-local detail=${JSON.stringify(failDetail)}`);
|
|
1085
1034
|
}
|
|
1086
1035
|
finally {
|
|
1087
1036
|
try {
|
|
@@ -1098,7 +1047,7 @@ function scheduleWeeklyGovernance() {
|
|
|
1098
1047
|
if (daysSince >= 7) {
|
|
1099
1048
|
const spawnArgs = resolveSubprocessArgs("background-maintenance");
|
|
1100
1049
|
if (spawnArgs) {
|
|
1101
|
-
const child =
|
|
1050
|
+
const child = spawnDetachedChild(spawnArgs, { phrenPath: getPhrenPath() });
|
|
1102
1051
|
child.unref();
|
|
1103
1052
|
fs.writeFileSync(lastGovPath, Date.now().toString());
|
|
1104
1053
|
debugLog("hook_stop: scheduled weekly governance run");
|
|
@@ -1225,8 +1174,7 @@ export async function handleHookTool() {
|
|
|
1225
1174
|
raw = fs.readFileSync(0, "utf-8");
|
|
1226
1175
|
}
|
|
1227
1176
|
catch (err) {
|
|
1228
|
-
|
|
1229
|
-
process.stderr.write(`[phren] hookTool stdinRead: ${errorMessage(err)}\n`);
|
|
1177
|
+
logger.debug("hooks-session", `hookTool stdinRead: ${errorMessage(err)}`);
|
|
1230
1178
|
process.exit(0);
|
|
1231
1179
|
}
|
|
1232
1180
|
}
|
|
@@ -1235,8 +1183,7 @@ export async function handleHookTool() {
|
|
|
1235
1183
|
data = JSON.parse(raw);
|
|
1236
1184
|
}
|
|
1237
1185
|
catch (err) {
|
|
1238
|
-
|
|
1239
|
-
process.stderr.write(`[phren] hookTool stdinParse: ${errorMessage(err)}\n`);
|
|
1186
|
+
logger.debug("hooks-session", `hookTool stdinParse: ${errorMessage(err)}`);
|
|
1240
1187
|
process.exit(0);
|
|
1241
1188
|
}
|
|
1242
1189
|
const toolName = String(data.tool_name ?? data.tool ?? "");
|
|
@@ -1287,8 +1234,7 @@ export async function handleHookTool() {
|
|
|
1287
1234
|
fs.appendFileSync(logFile, JSON.stringify(entry) + "\n");
|
|
1288
1235
|
}
|
|
1289
1236
|
catch (err) {
|
|
1290
|
-
|
|
1291
|
-
process.stderr.write(`[phren] hookTool toolLog: ${errorMessage(err)}\n`);
|
|
1237
|
+
logger.debug("hooks-session", `hookTool toolLog: ${errorMessage(err)}`);
|
|
1292
1238
|
}
|
|
1293
1239
|
const cooldownFile = runtimeFile(ctx.phrenPath, "hook-tool-cooldown");
|
|
1294
1240
|
try {
|
|
@@ -1301,8 +1247,7 @@ export async function handleHookTool() {
|
|
|
1301
1247
|
}
|
|
1302
1248
|
}
|
|
1303
1249
|
catch (err) {
|
|
1304
|
-
|
|
1305
|
-
process.stderr.write(`[phren] hookTool cooldownStat: ${errorMessage(err)}\n`);
|
|
1250
|
+
logger.debug("hooks-session", `hookTool cooldownStat: ${errorMessage(err)}`);
|
|
1306
1251
|
}
|
|
1307
1252
|
if (activeProject && sessionId) {
|
|
1308
1253
|
try {
|
|
@@ -1318,8 +1263,7 @@ export async function handleHookTool() {
|
|
|
1318
1263
|
}
|
|
1319
1264
|
}
|
|
1320
1265
|
catch (err) {
|
|
1321
|
-
|
|
1322
|
-
process.stderr.write(`[phren] hookTool sessionCapCheck: ${errorMessage(err)}\n`);
|
|
1266
|
+
logger.debug("hooks-session", `hookTool sessionCapCheck: ${errorMessage(err)}`);
|
|
1323
1267
|
}
|
|
1324
1268
|
}
|
|
1325
1269
|
const findingsLevelForTool = getProactivityLevelForFindings(ctx.phrenPath);
|
|
@@ -1335,8 +1279,7 @@ export async function handleHookTool() {
|
|
|
1335
1279
|
fs.writeFileSync(cooldownFile, Date.now().toString());
|
|
1336
1280
|
}
|
|
1337
1281
|
catch (err) {
|
|
1338
|
-
|
|
1339
|
-
process.stderr.write(`[phren] hookTool cooldownWrite: ${errorMessage(err)}\n`);
|
|
1282
|
+
logger.debug("hooks-session", `hookTool cooldownWrite: ${errorMessage(err)}`);
|
|
1340
1283
|
}
|
|
1341
1284
|
if (sessionId) {
|
|
1342
1285
|
try {
|
|
@@ -1346,15 +1289,13 @@ export async function handleHookTool() {
|
|
|
1346
1289
|
count = Number.parseInt(fs.readFileSync(capFile, "utf8").trim(), 10) || 0;
|
|
1347
1290
|
}
|
|
1348
1291
|
catch (err) {
|
|
1349
|
-
|
|
1350
|
-
process.stderr.write(`[phren] hookTool capFileRead: ${errorMessage(err)}\n`);
|
|
1292
|
+
logger.debug("hooks-session", `hookTool capFileRead: ${errorMessage(err)}`);
|
|
1351
1293
|
}
|
|
1352
1294
|
count += candidates.length;
|
|
1353
1295
|
fs.writeFileSync(capFile, count.toString());
|
|
1354
1296
|
}
|
|
1355
1297
|
catch (err) {
|
|
1356
|
-
|
|
1357
|
-
process.stderr.write(`[phren] hookTool capFileWrite: ${errorMessage(err)}\n`);
|
|
1298
|
+
logger.debug("hooks-session", `hookTool capFileWrite: ${errorMessage(err)}`);
|
|
1358
1299
|
}
|
|
1359
1300
|
}
|
|
1360
1301
|
}
|
|
@@ -4,38 +4,39 @@
|
|
|
4
4
|
// cli-hooks-session.ts — session lifecycle hooks, metrics, background maintenance
|
|
5
5
|
// cli-hooks-output.ts — hook output formatting
|
|
6
6
|
// cli-hooks-globs.ts — project glob matching
|
|
7
|
-
import { debugLog, sessionMarker, sessionsDir, getPhrenPath, } from "
|
|
8
|
-
import { mergeConfig, } from "
|
|
9
|
-
import { buildIndex, detectProject, } from "
|
|
10
|
-
import { isProjectHookEnabled } from "
|
|
11
|
-
import { checkConsolidationNeeded, } from "
|
|
12
|
-
import { buildRobustFtsQuery, extractKeywordEntries, isFeatureEnabled, clampInt, errorMessage, loadSynonymMap, learnSynonym, STOP_WORDS, } from "
|
|
13
|
-
import { getHooksEnabledPreference } from "
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
7
|
+
import { debugLog, sessionMarker, sessionsDir, getPhrenPath, } from "../shared.js";
|
|
8
|
+
import { mergeConfig, } from "../shared/governance.js";
|
|
9
|
+
import { buildIndex, detectProject, } from "../shared/index.js";
|
|
10
|
+
import { isProjectHookEnabled } from "../project-config.js";
|
|
11
|
+
import { checkConsolidationNeeded, } from "../shared/content.js";
|
|
12
|
+
import { buildRobustFtsQuery, extractKeywordEntries, isFeatureEnabled, clampInt, errorMessage, loadSynonymMap, learnSynonym, STOP_WORDS, } from "../utils.js";
|
|
13
|
+
import { getHooksEnabledPreference } from "../init/init.js";
|
|
14
|
+
import { logger } from "../logger.js";
|
|
15
|
+
import { isToolHookEnabled } from "../hooks.js";
|
|
16
|
+
import { handleExtractMemories } from "./extract.js";
|
|
17
|
+
import { appendAuditLog } from "../shared.js";
|
|
18
|
+
import { updateRuntimeHealth } from "../shared/governance.js";
|
|
19
|
+
import { getProactivityLevelForTask, getProactivityLevelForFindings } from "../proactivity.js";
|
|
20
|
+
import { FINDING_SENSITIVITY_CONFIG } from "./config.js";
|
|
20
21
|
import * as fs from "fs";
|
|
21
22
|
// ── Re-exports from focused modules ─────────────────────────────────────────
|
|
22
23
|
// Citations
|
|
23
|
-
export { parseCitations, validateCitation, annotateStale, clearCitationValidCache, } from "./
|
|
24
|
+
export { parseCitations, validateCitation, annotateStale, clearCitationValidCache, } from "./hooks-citations.js";
|
|
24
25
|
// Globs
|
|
25
|
-
export { getProjectGlobBoost, clearProjectGlobCache, } from "./
|
|
26
|
+
export { getProjectGlobBoost, clearProjectGlobCache, } from "./hooks-globs.js";
|
|
26
27
|
// Retrieval
|
|
27
|
-
export { detectTaskIntent, filterTaskByPriority, searchDocuments, applyTrustFilter, rankResults, selectSnippets, } from "
|
|
28
|
+
export { detectTaskIntent, filterTaskByPriority, searchDocuments, applyTrustFilter, rankResults, selectSnippets, } from "../shared/retrieval.js";
|
|
28
29
|
// Output
|
|
29
|
-
export { buildHookOutput, } from "./
|
|
30
|
+
export { buildHookOutput, } from "./hooks-output.js";
|
|
30
31
|
// Session
|
|
31
|
-
export { handleHookSessionStart, handleHookStop, handleBackgroundSync, handleHookContext, handleHookTool, trackSessionMetrics, filterConversationInsightsForProactivity, extractToolFindings, filterToolFindingsForProactivity, resolveSubprocessArgs, } from "./
|
|
32
|
+
export { handleHookSessionStart, handleHookStop, handleBackgroundSync, handleHookContext, handleHookTool, trackSessionMetrics, filterConversationInsightsForProactivity, extractToolFindings, filterToolFindingsForProactivity, resolveSubprocessArgs, } from "./hooks-session.js";
|
|
32
33
|
// ── Imports for the orchestrator ─────────────────────────────────────────────
|
|
33
|
-
import { searchDocumentsAsync, applyTrustFilter, rankResults, selectSnippets, detectTaskIntent, } from "
|
|
34
|
-
import { buildHookOutput } from "./
|
|
35
|
-
import { getGitContext, trackSessionMetrics, } from "./
|
|
36
|
-
import { approximateTokens } from "
|
|
37
|
-
import { resolveRuntimeProfile } from "
|
|
38
|
-
import { handleTaskPromptLifecycle } from "
|
|
34
|
+
import { searchDocumentsAsync, applyTrustFilter, rankResults, selectSnippets, detectTaskIntent, } from "../shared/retrieval.js";
|
|
35
|
+
import { buildHookOutput } from "./hooks-output.js";
|
|
36
|
+
import { getGitContext, trackSessionMetrics, } from "./hooks-session.js";
|
|
37
|
+
import { approximateTokens } from "../shared/retrieval.js";
|
|
38
|
+
import { resolveRuntimeProfile } from "../runtime-profile.js";
|
|
39
|
+
import { handleTaskPromptLifecycle } from "../task/lifecycle.js";
|
|
39
40
|
function synonymTermKnown(term, map) {
|
|
40
41
|
if (Object.prototype.hasOwnProperty.call(map, term))
|
|
41
42
|
return true;
|
|
@@ -126,7 +127,7 @@ export async function handleHookPrompt() {
|
|
|
126
127
|
}
|
|
127
128
|
catch (err) {
|
|
128
129
|
if (process.env.PHREN_DEBUG)
|
|
129
|
-
|
|
130
|
+
logger.debug("cli-hooks", `hookPrompt stdinRead: ${errorMessage(err)}`);
|
|
130
131
|
process.exit(0);
|
|
131
132
|
}
|
|
132
133
|
const input = parseHookInput(raw);
|
|
@@ -362,7 +363,7 @@ export async function handleHookPrompt() {
|
|
|
362
363
|
}
|
|
363
364
|
catch (err) {
|
|
364
365
|
if (process.env.PHREN_DEBUG)
|
|
365
|
-
|
|
366
|
+
logger.debug("cli-hooks", `hookPrompt noticeFileWrite: ${errorMessage(err)}`);
|
|
366
367
|
}
|
|
367
368
|
}
|
|
368
369
|
}
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import { execFileSync } from "child_process";
|
|
4
|
-
import { expandHomePath, findArchivedProjectNameCaseInsensitive, findProjectNameCaseInsensitive, getPhrenPath, getProjectDirs, homePath, hookConfigPath, normalizeProjectNameForCreate, readRootManifest, } from "
|
|
5
|
-
import { isValidProjectName, errorMessage } from "
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
4
|
+
import { expandHomePath, findArchivedProjectNameCaseInsensitive, findProjectNameCaseInsensitive, getPhrenPath, getProjectDirs, homePath, hookConfigPath, normalizeProjectNameForCreate, readRootManifest, } from "../shared.js";
|
|
5
|
+
import { isValidProjectName, errorMessage } from "../utils.js";
|
|
6
|
+
import { logger } from "../logger.js";
|
|
7
|
+
import { readInstallPreferences, writeInstallPreferences } from "../init/preferences.js";
|
|
8
|
+
import { buildSkillManifest, findLocalSkill, findSkill, getAllSkills } from "../skill/registry.js";
|
|
9
|
+
import { detectSkillCollisions } from "../link/skills.js";
|
|
10
|
+
import { setSkillEnabledAndSync, syncSkillLinksForScope } from "../skill/files.js";
|
|
11
|
+
import { findProjectDir } from "../project-locator.js";
|
|
12
|
+
import { TASK_FILE_ALIASES, addTask, completeTask, updateTask, reorderTask, pinTask, removeTask, workNextTask, tidyDoneTasks, linkTaskIssue, promoteTask, resolveTaskItem } from "../data/tasks.js";
|
|
13
|
+
import { buildTaskIssueBody, createGithubIssueForTask, parseGithubIssueUrl, resolveProjectGithubRepo } from "../task/github.js";
|
|
14
|
+
import { PROJECT_HOOK_EVENTS, PROJECT_OWNERSHIP_MODES, isProjectHookEnabled, parseProjectOwnershipMode, readProjectConfig, writeProjectConfig, writeProjectHookConfig, } from "../project-config.js";
|
|
15
|
+
import { addFinding, removeFinding } from "../core/finding.js";
|
|
16
|
+
import { supersedeFinding, retractFinding, resolveFindingContradiction } from "../finding/lifecycle.js";
|
|
17
|
+
import { readCustomHooks, getHookTarget, HOOK_EVENT_VALUES, validateCustomHookCommand } from "../hooks.js";
|
|
18
|
+
import { runtimeFile } from "../shared.js";
|
|
18
19
|
const HOOK_TOOLS = ["claude", "copilot", "cursor", "codex"];
|
|
19
20
|
function printSkillsUsage() {
|
|
20
21
|
console.log("Usage:");
|
|
@@ -78,7 +79,7 @@ function openInEditor(filePath) {
|
|
|
78
79
|
}
|
|
79
80
|
catch (err) {
|
|
80
81
|
if ((process.env.PHREN_DEBUG))
|
|
81
|
-
|
|
82
|
+
logger.debug("cli-namespaces", `openInEditor: ${errorMessage(err)}`);
|
|
82
83
|
console.error(`Editor "${editor}" failed. Set $EDITOR to your preferred editor.`);
|
|
83
84
|
process.exit(1);
|
|
84
85
|
}
|
|
@@ -147,7 +148,7 @@ export function handleSkillsNamespace(args, profile) {
|
|
|
147
148
|
}
|
|
148
149
|
catch (err) {
|
|
149
150
|
if ((process.env.PHREN_DEBUG))
|
|
150
|
-
|
|
151
|
+
logger.debug("cli-namespaces", `skill add symlinkFailed: ${errorMessage(err)}`);
|
|
151
152
|
fs.copyFileSync(source, dest);
|
|
152
153
|
console.log(`Copied skill ${fileName} into ${project}.`);
|
|
153
154
|
}
|
|
@@ -457,7 +458,7 @@ export function handleDetectSkills(args, profile) {
|
|
|
457
458
|
}
|
|
458
459
|
catch (err) {
|
|
459
460
|
if ((process.env.PHREN_DEBUG))
|
|
460
|
-
|
|
461
|
+
logger.debug("cli-namespaces", `skillList lstat: ${errorMessage(err)}`);
|
|
461
462
|
}
|
|
462
463
|
const name = entry.replace(/\.md$/, "");
|
|
463
464
|
if (trackedSkills.has(name))
|
|
@@ -666,7 +667,7 @@ export async function handleProjectsNamespace(args, profile) {
|
|
|
666
667
|
console.error(`Project "${name}" not found.`);
|
|
667
668
|
process.exit(1);
|
|
668
669
|
}
|
|
669
|
-
const { readFindings, readTasks, resolveTaskFilePath
|
|
670
|
+
const { readFindings, readTasks, resolveTaskFilePath } = await import("../data/access.js");
|
|
670
671
|
const exported = { project: name, exportedAt: new Date().toISOString(), version: 1 };
|
|
671
672
|
const summaryPath = path.join(projectDir, "summary.md");
|
|
672
673
|
if (fs.existsSync(summaryPath))
|
|
@@ -721,7 +722,7 @@ export async function handleProjectsNamespace(args, profile) {
|
|
|
721
722
|
console.error("Invalid import payload: missing project field.");
|
|
722
723
|
process.exit(1);
|
|
723
724
|
}
|
|
724
|
-
const { TASKS_FILENAME } = await import("
|
|
725
|
+
const { TASKS_FILENAME } = await import("../data/access.js");
|
|
725
726
|
const phrenPath = getPhrenPath();
|
|
726
727
|
const projectName = normalizeProjectNameForCreate(String(decoded.project));
|
|
727
728
|
if (!isValidProjectName(projectName)) {
|
|
@@ -874,7 +875,7 @@ function handleProjectsList(profile) {
|
|
|
874
875
|
}
|
|
875
876
|
catch (err) {
|
|
876
877
|
if ((process.env.PHREN_DEBUG))
|
|
877
|
-
|
|
878
|
+
logger.debug("cli-namespaces", `projects list readdir: ${errorMessage(err)}`);
|
|
878
879
|
dirFiles = new Set();
|
|
879
880
|
}
|
|
880
881
|
const tags = [];
|
|
@@ -917,7 +918,7 @@ async function handleProjectsRemove(name, profile) {
|
|
|
917
918
|
}
|
|
918
919
|
catch (err) {
|
|
919
920
|
if ((process.env.PHREN_DEBUG))
|
|
920
|
-
|
|
921
|
+
logger.debug("cli-namespaces", `projects remove countFiles: ${errorMessage(err)}`);
|
|
921
922
|
}
|
|
922
923
|
const readline = await import("readline");
|
|
923
924
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -956,7 +957,7 @@ export async function handleTaskNamespace(args) {
|
|
|
956
957
|
}
|
|
957
958
|
if (subcommand === "list") {
|
|
958
959
|
// Delegate to the cross-project task view (same as `phren tasks`)
|
|
959
|
-
const { handleTaskView } = await import("./
|
|
960
|
+
const { handleTaskView } = await import("./ops.js");
|
|
960
961
|
return handleTaskView(args[1] || "default");
|
|
961
962
|
}
|
|
962
963
|
if (subcommand === "add") {
|
|
@@ -1321,7 +1322,7 @@ export async function handleFindingNamespace(args) {
|
|
|
1321
1322
|
console.error("Usage: phren finding list <project>");
|
|
1322
1323
|
process.exit(1);
|
|
1323
1324
|
}
|
|
1324
|
-
const { readFindings } = await import("
|
|
1325
|
+
const { readFindings } = await import("../data/access.js");
|
|
1325
1326
|
const result = readFindings(getPhrenPath(), project);
|
|
1326
1327
|
if (!result.ok) {
|
|
1327
1328
|
console.error(result.error);
|
|
@@ -1441,7 +1442,7 @@ export async function handleFindingNamespace(args) {
|
|
|
1441
1442
|
const project = args[1];
|
|
1442
1443
|
const phrenPath = getPhrenPath();
|
|
1443
1444
|
const RESERVED_DIRS = new Set(["global", ".runtime", ".sessions", ".config"]);
|
|
1444
|
-
const { readFindings } = await import("
|
|
1445
|
+
const { readFindings } = await import("../data/access.js");
|
|
1445
1446
|
const projects = project
|
|
1446
1447
|
? [project]
|
|
1447
1448
|
: fs.readdirSync(phrenPath, { withFileTypes: true })
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import { execFileSync } from "child_process";
|
|
4
|
-
import { EXEC_TIMEOUT_MS, findProjectNameCaseInsensitive, getPhrenPath, normalizeProjectNameForCreate, } from "
|
|
5
|
-
import { isValidProjectName, errorMessage } from "
|
|
6
|
-
import { readTasksAcrossProjects, TASKS_FILENAME } from "
|
|
7
|
-
import { applyGravity } from "
|
|
8
|
-
import { buildIndex, queryRows } from "
|
|
9
|
-
import { resolveSubprocessArgs } from "./
|
|
10
|
-
import { listAllSessions, getSessionArtifacts } from "
|
|
4
|
+
import { EXEC_TIMEOUT_MS, findProjectNameCaseInsensitive, getPhrenPath, normalizeProjectNameForCreate, } from "../shared.js";
|
|
5
|
+
import { isValidProjectName, errorMessage } from "../utils.js";
|
|
6
|
+
import { readTasksAcrossProjects, TASKS_FILENAME } from "../data/access.js";
|
|
7
|
+
import { applyGravity } from "../data/tasks.js";
|
|
8
|
+
import { buildIndex, queryRows } from "../shared/index.js";
|
|
9
|
+
import { resolveSubprocessArgs } from "./hooks.js";
|
|
10
|
+
import { listAllSessions, getSessionArtifacts } from "../tools/session.js";
|
|
11
11
|
export function handleTaskView(profile) {
|
|
12
12
|
const docs = readTasksAcrossProjects(getPhrenPath(), profile);
|
|
13
13
|
if (!docs.length) {
|
|
@@ -100,8 +100,8 @@ export function handleSessionsView(args) {
|
|
|
100
100
|
console.log(`\n${sessions.length} session(s). Use \`phren sessions <id>\` to drill into one.`);
|
|
101
101
|
}
|
|
102
102
|
export async function handleQuickstart() {
|
|
103
|
-
const { runInit } = await import("
|
|
104
|
-
const { runLink } = await import("
|
|
103
|
+
const { runInit } = await import("../init/init.js");
|
|
104
|
+
const { runLink } = await import("../link/link.js");
|
|
105
105
|
const dirBasename = path.basename(process.cwd());
|
|
106
106
|
const readline = await import("readline");
|
|
107
107
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|