openwolf-enhanced 1.9.3
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/CHANGELOG.md +386 -0
- package/LICENSE +663 -0
- package/NOTICE +48 -0
- package/README.md +283 -0
- package/dist/bin/openwolf.js +10 -0
- package/dist/bin/openwolf.js.map +1 -0
- package/dist/dashboard/assets/AISuggestions-DHXOgHMM.js +9 -0
- package/dist/dashboard/assets/ActivityTimeline-BXLwacZV.js +1 -0
- package/dist/dashboard/assets/AnatomyBrowser-CUyC8M2I.js +1 -0
- package/dist/dashboard/assets/BugLog-Bxvy1sPW.js +1 -0
- package/dist/dashboard/assets/CerebrumViewer-DCySVmzA.js +1 -0
- package/dist/dashboard/assets/CronStatus-BA4fmQX3.js +1 -0
- package/dist/dashboard/assets/DesignQC-BhNEKryS.js +1 -0
- package/dist/dashboard/assets/MemoryViewer-0y9lsDUO.js +1 -0
- package/dist/dashboard/assets/ProjectOverview-CC51rVRe.js +1 -0
- package/dist/dashboard/assets/StatusBadge-4NJI_F2G.js +1 -0
- package/dist/dashboard/assets/TokenUsage-7pCxlnCX.js +55 -0
- package/dist/dashboard/assets/index-4O5rk-qB.css +2 -0
- package/dist/dashboard/assets/index-jfgWxxsn.js +13 -0
- package/dist/dashboard/assets/utils-BqE_aDxV.js +1 -0
- package/dist/dashboard/index.html +16 -0
- package/dist/hooks/post-read.js +85 -0
- package/dist/hooks/post-write.js +520 -0
- package/dist/hooks/pre-read.js +107 -0
- package/dist/hooks/pre-write.js +120 -0
- package/dist/hooks/session-start.js +76 -0
- package/dist/hooks/shared.js +0 -0
- package/dist/hooks/stop.js +219 -0
- package/dist/src/buglog/bug-matcher.js +3 -0
- package/dist/src/buglog/bug-matcher.js.map +1 -0
- package/dist/src/buglog/bug-tracker.js +89 -0
- package/dist/src/buglog/bug-tracker.js.map +1 -0
- package/dist/src/cli/bug-cmd.js +31 -0
- package/dist/src/cli/bug-cmd.js.map +1 -0
- package/dist/src/cli/cron-cmd.js +107 -0
- package/dist/src/cli/cron-cmd.js.map +1 -0
- package/dist/src/cli/daemon-cmd.js +180 -0
- package/dist/src/cli/daemon-cmd.js.map +1 -0
- package/dist/src/cli/dashboard.js +88 -0
- package/dist/src/cli/dashboard.js.map +1 -0
- package/dist/src/cli/designqc-cmd.js +31 -0
- package/dist/src/cli/designqc-cmd.js.map +1 -0
- package/dist/src/cli/doctor-cmd.js +94 -0
- package/dist/src/cli/doctor-cmd.js.map +1 -0
- package/dist/src/cli/index.js +158 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/init.js +493 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/registry.js +93 -0
- package/dist/src/cli/registry.js.map +1 -0
- package/dist/src/cli/scan.js +39 -0
- package/dist/src/cli/scan.js.map +1 -0
- package/dist/src/cli/status.js +98 -0
- package/dist/src/cli/status.js.map +1 -0
- package/dist/src/cli/update.js +435 -0
- package/dist/src/cli/update.js.map +1 -0
- package/dist/src/daemon/cron-engine.js +321 -0
- package/dist/src/daemon/cron-engine.js.map +1 -0
- package/dist/src/daemon/file-watcher.js +64 -0
- package/dist/src/daemon/file-watcher.js.map +1 -0
- package/dist/src/daemon/health.js +23 -0
- package/dist/src/daemon/health.js.map +1 -0
- package/dist/src/daemon/wolf-daemon.js +440 -0
- package/dist/src/daemon/wolf-daemon.js.map +1 -0
- package/dist/src/designqc/designqc-capture.js +278 -0
- package/dist/src/designqc/designqc-capture.js.map +1 -0
- package/dist/src/designqc/designqc-engine.js +159 -0
- package/dist/src/designqc/designqc-engine.js.map +1 -0
- package/dist/src/designqc/designqc-types.js +5 -0
- package/dist/src/designqc/designqc-types.js.map +1 -0
- package/dist/src/hooks/post-read.js +86 -0
- package/dist/src/hooks/post-read.js.map +1 -0
- package/dist/src/hooks/post-write.js +521 -0
- package/dist/src/hooks/post-write.js.map +1 -0
- package/dist/src/hooks/pre-read.js +108 -0
- package/dist/src/hooks/pre-read.js.map +1 -0
- package/dist/src/hooks/pre-write.js +121 -0
- package/dist/src/hooks/pre-write.js.map +1 -0
- package/dist/src/hooks/session-start.js +77 -0
- package/dist/src/hooks/session-start.js.map +1 -0
- package/dist/src/hooks/shared.js +0 -0
- package/dist/src/hooks/shared.js.map +1 -0
- package/dist/src/hooks/stop.js +220 -0
- package/dist/src/hooks/stop.js.map +1 -0
- package/dist/src/scanner/anatomy-scanner.js +278 -0
- package/dist/src/scanner/anatomy-scanner.js.map +1 -0
- package/dist/src/scanner/description-extractor.js +1007 -0
- package/dist/src/scanner/description-extractor.js.map +1 -0
- package/dist/src/scanner/project-root.js +52 -0
- package/dist/src/scanner/project-root.js.map +1 -0
- package/dist/src/tracker/token-estimator.js +20 -0
- package/dist/src/tracker/token-estimator.js.map +1 -0
- package/dist/src/tracker/token-ledger.js +55 -0
- package/dist/src/tracker/token-ledger.js.map +1 -0
- package/dist/src/tracker/waste-detector.js +101 -0
- package/dist/src/tracker/waste-detector.js.map +1 -0
- package/dist/src/utils/dashboard-auth.js +50 -0
- package/dist/src/utils/dashboard-auth.js.map +1 -0
- package/dist/src/utils/fs-safe.js +135 -0
- package/dist/src/utils/fs-safe.js.map +1 -0
- package/dist/src/utils/hooks-deploy.js +70 -0
- package/dist/src/utils/hooks-deploy.js.map +1 -0
- package/dist/src/utils/logger.js +48 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/maintenance.js +385 -0
- package/dist/src/utils/maintenance.js.map +1 -0
- package/dist/src/utils/paths.js +23 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/platform.js +14 -0
- package/dist/src/utils/platform.js.map +1 -0
- package/dist/src/utils/seed.js +61 -0
- package/dist/src/utils/seed.js.map +1 -0
- package/package.json +82 -0
- package/src/templates/OPENWOLF.md +147 -0
- package/src/templates/STATUS.md +48 -0
- package/src/templates/anatomy.md +5 -0
- package/src/templates/buglog.json +4 -0
- package/src/templates/cerebrum.md +22 -0
- package/src/templates/claude-md-snippet.md +5 -0
- package/src/templates/claude-rules-openwolf.md +17 -0
- package/src/templates/config.json +83 -0
- package/src/templates/cron-manifest.json +97 -0
- package/src/templates/cron-state.json +7 -0
- package/src/templates/identity.md +9 -0
- package/src/templates/memory.md +4 -0
- package/src/templates/reframe-frameworks.md +597 -0
- package/src/templates/token-ledger.json +21 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { findProjectRoot } from "../scanner/project-root.js";
|
|
4
|
+
import { readJSON, writeJSON } from "../utils/fs-safe.js";
|
|
5
|
+
import { readDashboardToken } from "../utils/dashboard-auth.js";
|
|
6
|
+
import { Logger } from "../utils/logger.js";
|
|
7
|
+
import { CronEngine } from "../daemon/cron-engine.js";
|
|
8
|
+
export function cronList() {
|
|
9
|
+
const projectRoot = findProjectRoot();
|
|
10
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
11
|
+
if (!fs.existsSync(wolfDir)) {
|
|
12
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const manifest = readJSON(path.join(wolfDir, "cron-manifest.json"), {
|
|
16
|
+
version: 1,
|
|
17
|
+
tasks: [],
|
|
18
|
+
});
|
|
19
|
+
const state = readJSON(path.join(wolfDir, "cron-state.json"), {
|
|
20
|
+
engine_status: "unknown",
|
|
21
|
+
execution_log: [],
|
|
22
|
+
dead_letter_queue: [],
|
|
23
|
+
});
|
|
24
|
+
console.log("Cron Tasks");
|
|
25
|
+
console.log("==========\n");
|
|
26
|
+
if (manifest.tasks.length === 0) {
|
|
27
|
+
console.log(" No tasks configured.");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
for (const task of manifest.tasks) {
|
|
31
|
+
const status = task.enabled ? "enabled" : "disabled";
|
|
32
|
+
const lastRun = state.execution_log
|
|
33
|
+
.filter((e) => e.task_id === task.id)
|
|
34
|
+
.sort((a, b) => b.timestamp.localeCompare(a.timestamp))[0];
|
|
35
|
+
const lastRunStr = lastRun ? `${lastRun.status} at ${lastRun.timestamp}` : "never";
|
|
36
|
+
const isDead = state.dead_letter_queue.some((d) => d.task_id === task.id);
|
|
37
|
+
console.log(` ${task.name} (${task.id})`);
|
|
38
|
+
console.log(` Schedule: ${task.schedule}`);
|
|
39
|
+
console.log(` Status: ${status}${isDead ? " [DEAD-LETTERED]" : ""}`);
|
|
40
|
+
console.log(` Last run: ${lastRunStr}`);
|
|
41
|
+
console.log(` ${task.description}`);
|
|
42
|
+
console.log("");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function cronRun(id) {
|
|
46
|
+
const projectRoot = findProjectRoot();
|
|
47
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
48
|
+
if (!fs.existsSync(wolfDir)) {
|
|
49
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const config = readJSON(path.join(wolfDir, "config.json"), {
|
|
53
|
+
openwolf: { dashboard: { port: 18791 } },
|
|
54
|
+
});
|
|
55
|
+
const port = config.openwolf.dashboard.port;
|
|
56
|
+
// Try calling the daemon's HTTP endpoint first
|
|
57
|
+
try {
|
|
58
|
+
const res = await fetch(`http://127.0.0.1:${port}/api/cron/run/${encodeURIComponent(id)}`, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: { "Content-Type": "application/json", "X-OpenWolf-Token": readDashboardToken(wolfDir) },
|
|
61
|
+
});
|
|
62
|
+
const body = await res.json();
|
|
63
|
+
if (res.ok) {
|
|
64
|
+
console.log(`Task ${id} triggered via daemon.`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.log(`Daemon returned error: ${body.error ?? res.statusText}`);
|
|
68
|
+
console.log("Falling back to direct execution...");
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
console.log("Daemon not reachable. Running task directly...");
|
|
72
|
+
}
|
|
73
|
+
// Fallback: run the task directly via CronEngine
|
|
74
|
+
const logger = new Logger(path.join(wolfDir, "daemon.log"), "info");
|
|
75
|
+
const engine = new CronEngine(wolfDir, projectRoot, logger, () => { });
|
|
76
|
+
try {
|
|
77
|
+
await engine.runTask(id);
|
|
78
|
+
console.log(`Task ${id} executed successfully.`);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
console.error(`Task ${id} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export function cronRetry(id) {
|
|
86
|
+
const projectRoot = findProjectRoot();
|
|
87
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
88
|
+
if (!fs.existsSync(wolfDir)) {
|
|
89
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const statePath = path.join(wolfDir, "cron-state.json");
|
|
93
|
+
const state = readJSON(statePath, {
|
|
94
|
+
engine_status: "unknown",
|
|
95
|
+
execution_log: [],
|
|
96
|
+
dead_letter_queue: [],
|
|
97
|
+
});
|
|
98
|
+
const idx = state.dead_letter_queue.findIndex((d) => d.task_id === id);
|
|
99
|
+
if (idx === -1) {
|
|
100
|
+
console.log(`Task ${id} not found in dead letter queue.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
state.dead_letter_queue.splice(idx, 1);
|
|
104
|
+
writeJSON(statePath, state);
|
|
105
|
+
console.log(`Removed ${id} from dead letter queue. It will retry on next schedule.`);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=cron-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-cmd.js","sourceRoot":"","sources":["../../../src/cli/cron-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { findProjectRoot } from "../scanner/project-root.js";
|
|
6
|
+
import { readJSON } from "../utils/fs-safe.js";
|
|
7
|
+
import { isWindows } from "../utils/platform.js";
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
function getDashboardPort() {
|
|
11
|
+
const projectRoot = findProjectRoot();
|
|
12
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
13
|
+
const config = readJSON(path.join(wolfDir, "config.json"), { openwolf: { dashboard: { port: 18791 } } });
|
|
14
|
+
return config.openwolf.dashboard.port;
|
|
15
|
+
}
|
|
16
|
+
// On Windows the pm2 shim is pm2.cmd; execFileSync needs the exact name (no shell).
|
|
17
|
+
const PM2 = isWindows() ? "pm2.cmd" : "pm2";
|
|
18
|
+
function getPm2Name() {
|
|
19
|
+
const projectRoot = findProjectRoot();
|
|
20
|
+
// Sanitize so the project folder name can't inject pm2/shell args or spaces.
|
|
21
|
+
const safe = path.basename(projectRoot).replace(/[^A-Za-z0-9_.-]/g, "-");
|
|
22
|
+
return `openwolf-${safe}`;
|
|
23
|
+
}
|
|
24
|
+
function hasPm2() {
|
|
25
|
+
try {
|
|
26
|
+
execFileSync(isWindows() ? "where" : "which", ["pm2"], { stdio: "ignore" });
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function findPidOnPort(port) {
|
|
34
|
+
try {
|
|
35
|
+
if (isWindows()) {
|
|
36
|
+
const output = execFileSync("netstat", ["-ano", "-p", "tcp"], { encoding: "utf-8" });
|
|
37
|
+
for (const line of output.split("\n")) {
|
|
38
|
+
if (line.includes(`:${port}`) && line.includes("LISTENING")) {
|
|
39
|
+
const parts = line.trim().split(/\s+/);
|
|
40
|
+
const pid = parseInt(parts[parts.length - 1], 10);
|
|
41
|
+
if (pid > 0)
|
|
42
|
+
return pid;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const output = execFileSync("lsof", ["-ti", `:${port}`], { encoding: "utf-8" });
|
|
48
|
+
const pid = parseInt(output.trim(), 10);
|
|
49
|
+
if (pid > 0)
|
|
50
|
+
return pid;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch { }
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function killPid(pid) {
|
|
57
|
+
try {
|
|
58
|
+
if (isWindows()) {
|
|
59
|
+
execFileSync("taskkill", ["/PID", String(pid), "/F"], { stdio: "ignore" });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
process.kill(pid, "SIGTERM");
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function daemonStart() {
|
|
71
|
+
const projectRoot = findProjectRoot();
|
|
72
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
73
|
+
if (!fs.existsSync(wolfDir)) {
|
|
74
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (!hasPm2()) {
|
|
78
|
+
console.log("pm2 not found. Install with: pnpm add -g pm2");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const name = getPm2Name();
|
|
82
|
+
// Resolve daemon script relative to openwolf's install dir, not the target project
|
|
83
|
+
const daemonScript = path.resolve(__dirname, "..", "daemon", "wolf-daemon.js");
|
|
84
|
+
try {
|
|
85
|
+
execFileSync(PM2, ["start", daemonScript, "--name", name, "--cwd", projectRoot, "--", "--env", `OPENWOLF_PROJECT_ROOT=${projectRoot}`], {
|
|
86
|
+
stdio: "inherit",
|
|
87
|
+
env: { ...process.env, OPENWOLF_PROJECT_ROOT: projectRoot },
|
|
88
|
+
});
|
|
89
|
+
execFileSync(PM2, ["save"], { stdio: "ignore" });
|
|
90
|
+
console.log(`\n ✓ Daemon started: ${name}`);
|
|
91
|
+
if (isWindows()) {
|
|
92
|
+
console.log(" Tip: Run 'pm2-windows-startup' for boot persistence.");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
console.error("Failed to start daemon.");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function daemonStop() {
|
|
100
|
+
const projectRoot = findProjectRoot();
|
|
101
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
102
|
+
if (!fs.existsSync(wolfDir)) {
|
|
103
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// First try PM2
|
|
107
|
+
if (hasPm2()) {
|
|
108
|
+
const name = getPm2Name();
|
|
109
|
+
try {
|
|
110
|
+
execFileSync(PM2, ["stop", name], { stdio: "ignore" });
|
|
111
|
+
console.log(` ✓ Daemon stopped (PM2): ${name}`);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// PM2 process not found — fall through to port-based stop
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Fall back to killing whatever is listening on the dashboard port
|
|
119
|
+
const port = getDashboardPort();
|
|
120
|
+
const pid = findPidOnPort(port);
|
|
121
|
+
if (pid) {
|
|
122
|
+
if (killPid(pid)) {
|
|
123
|
+
console.log(` ✓ Daemon stopped (PID ${pid} on port ${port})`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
console.error(` Failed to kill process ${pid} on port ${port}.`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
console.log(` No daemon running on port ${port}.`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export function daemonRestart() {
|
|
134
|
+
const projectRoot = findProjectRoot();
|
|
135
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
136
|
+
if (!fs.existsSync(wolfDir)) {
|
|
137
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// First try PM2
|
|
141
|
+
if (hasPm2()) {
|
|
142
|
+
const name = getPm2Name();
|
|
143
|
+
try {
|
|
144
|
+
execFileSync(PM2, ["restart", name], { stdio: "ignore" });
|
|
145
|
+
console.log(` ✓ Daemon restarted (PM2): ${name}`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// PM2 process not found — fall through
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Fall back: stop then start via dashboard command flow
|
|
153
|
+
const port = getDashboardPort();
|
|
154
|
+
const pid = findPidOnPort(port);
|
|
155
|
+
if (pid) {
|
|
156
|
+
killPid(pid);
|
|
157
|
+
console.log(` Stopped old daemon (PID ${pid}).`);
|
|
158
|
+
}
|
|
159
|
+
console.log(" Use 'openwolf dashboard' to start a new daemon.");
|
|
160
|
+
}
|
|
161
|
+
export function daemonLogs() {
|
|
162
|
+
const projectRoot = findProjectRoot();
|
|
163
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
164
|
+
if (!fs.existsSync(wolfDir)) {
|
|
165
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (!hasPm2()) {
|
|
169
|
+
console.log("pm2 not found.");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const name = getPm2Name();
|
|
173
|
+
try {
|
|
174
|
+
execFileSync(PM2, ["logs", name, "--lines", "50", "--nostream"], { stdio: "inherit" });
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
console.error("Failed to get daemon logs.");
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=daemon-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-cmd.js","sourceRoot":"","sources":["../../../src/cli/daemon-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,SAAS,gBAAgB;IACvB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,CACrB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EACjC,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAC7C,CAAC;IACF,OAAO,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;AACxC,CAAC;AAED,oFAAoF;AACpF,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AAE5C,SAAS,UAAU;IACjB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,6EAA6E;IAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACzE,OAAO,YAAY,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,MAAM;IACb,IAAI,CAAC;QACH,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,IAAI,CAAC;QACH,IAAI,SAAS,EAAE,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACrF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAClD,IAAI,GAAG,GAAG,CAAC;wBAAE,OAAO,GAAG,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YAChF,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;YACxC,IAAI,GAAG,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC;QAC1B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,OAAO,CAAC,GAAW;IAC1B,IAAI,CAAC;QACH,IAAI,SAAS,EAAE,EAAE,CAAC;YAChB,YAAY,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,mFAAmF;IACnF,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAE/E,IAAI,CAAC;QACH,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,yBAAyB,WAAW,EAAE,CAAC,EAAE;YACtI,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,qBAAqB,EAAE,WAAW,EAAE;SAC5D,CAAC,CAAC;QACH,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;QAC7C,IAAI,SAAS,EAAE,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,gBAAgB;IAChB,IAAI,MAAM,EAAE,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;YACjD,OAAO;QACT,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;QAC5D,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,2BAA2B,GAAG,YAAY,IAAI,GAAG,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,4BAA4B,GAAG,YAAY,IAAI,GAAG,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,GAAG,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,gBAAgB;IAChB,IAAI,MAAM,EAAE,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,YAAY,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,EAAE,CAAC,CAAC;YACnD,OAAO;QACT,CAAC;QAAC,MAAM,CAAC;YACP,uCAAuC;QACzC,CAAC;IACH,CAAC;IAED,wDAAwD;IACxD,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,6BAA6B,GAAG,IAAI,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEhD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as net from "node:net";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { fork } from "node:child_process";
|
|
6
|
+
import { findProjectRoot } from "../scanner/project-root.js";
|
|
7
|
+
import { readJSON } from "../utils/fs-safe.js";
|
|
8
|
+
import { ensureDashboardToken } from "../utils/dashboard-auth.js";
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
function isPortOpen(port) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
const socket = new net.Socket();
|
|
14
|
+
socket.setTimeout(1000);
|
|
15
|
+
socket.once("connect", () => {
|
|
16
|
+
socket.destroy();
|
|
17
|
+
resolve(true);
|
|
18
|
+
});
|
|
19
|
+
socket.once("timeout", () => {
|
|
20
|
+
socket.destroy();
|
|
21
|
+
resolve(false);
|
|
22
|
+
});
|
|
23
|
+
socket.once("error", () => {
|
|
24
|
+
socket.destroy();
|
|
25
|
+
resolve(false);
|
|
26
|
+
});
|
|
27
|
+
socket.connect(port, "127.0.0.1");
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export async function dashboardCommand() {
|
|
31
|
+
const projectRoot = findProjectRoot();
|
|
32
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
33
|
+
if (!fs.existsSync(wolfDir)) {
|
|
34
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const config = readJSON(path.join(wolfDir, "config.json"), {
|
|
38
|
+
openwolf: { dashboard: { port: 18791 } },
|
|
39
|
+
});
|
|
40
|
+
const port = config.openwolf.dashboard.port;
|
|
41
|
+
// The dashboard requires a token; pass it via the URL so the SPA can pick it up.
|
|
42
|
+
const token = ensureDashboardToken(wolfDir);
|
|
43
|
+
const baseUrl = `http://localhost:${port}`;
|
|
44
|
+
const url = `${baseUrl}/?token=${token}`;
|
|
45
|
+
// Check if daemon is already running on that port
|
|
46
|
+
const running = await isPortOpen(port);
|
|
47
|
+
if (!running) {
|
|
48
|
+
console.log(" Daemon not running. Starting dashboard server...");
|
|
49
|
+
// Find the daemon script
|
|
50
|
+
const daemonScript = path.resolve(__dirname, "..", "daemon", "wolf-daemon.js");
|
|
51
|
+
if (!fs.existsSync(daemonScript)) {
|
|
52
|
+
console.error(` Daemon script not found at: ${daemonScript}`);
|
|
53
|
+
console.log(" Run 'pnpm build' in the openwolf directory first.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Fork the daemon as a child process, passing project root explicitly
|
|
57
|
+
const child = fork(daemonScript, [], {
|
|
58
|
+
cwd: projectRoot,
|
|
59
|
+
env: { ...process.env, OPENWOLF_PROJECT_ROOT: projectRoot },
|
|
60
|
+
detached: true,
|
|
61
|
+
stdio: "ignore",
|
|
62
|
+
});
|
|
63
|
+
child.unref();
|
|
64
|
+
// Wait for the port to open (up to 5 seconds)
|
|
65
|
+
let ready = false;
|
|
66
|
+
for (let i = 0; i < 25; i++) {
|
|
67
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
68
|
+
if (await isPortOpen(port)) {
|
|
69
|
+
ready = true;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!ready) {
|
|
74
|
+
console.log(` Server didn't start in time. Try manually: node "${daemonScript}"`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
console.log(` ✓ Dashboard server running on port ${port}`);
|
|
78
|
+
}
|
|
79
|
+
console.log(` Opening ${baseUrl}...`);
|
|
80
|
+
try {
|
|
81
|
+
const { default: open } = await import("open");
|
|
82
|
+
await open(url);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
console.log(` Could not open browser. Visit: ${url}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../../src/cli/dashboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import { findProjectRoot } from "../scanner/project-root.js";
|
|
3
|
+
import { readJSON } from "../utils/fs-safe.js";
|
|
4
|
+
import { DesignQCEngine } from "../designqc/designqc-engine.js";
|
|
5
|
+
import { DEFAULT_VIEWPORTS } from "../designqc/designqc-types.js";
|
|
6
|
+
export async function designqcCommand(target, opts) {
|
|
7
|
+
const projectRoot = findProjectRoot();
|
|
8
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
9
|
+
const config = readJSON(path.join(wolfDir, "config.json"), {});
|
|
10
|
+
const dc = config.openwolf?.designqc ?? {};
|
|
11
|
+
let viewports = dc.viewports || DEFAULT_VIEWPORTS;
|
|
12
|
+
if (opts?.desktopOnly) {
|
|
13
|
+
viewports = viewports.filter((v) => v.name === "desktop");
|
|
14
|
+
if (viewports.length === 0)
|
|
15
|
+
viewports = [DEFAULT_VIEWPORTS[0]];
|
|
16
|
+
}
|
|
17
|
+
const options = {
|
|
18
|
+
targetFile: target,
|
|
19
|
+
devServerUrl: opts?.url,
|
|
20
|
+
routes: opts?.routes,
|
|
21
|
+
viewports,
|
|
22
|
+
maxScreenshots: dc.max_screenshots || 16,
|
|
23
|
+
chromePath: dc.chrome_path ?? undefined,
|
|
24
|
+
quality: Number(opts?.quality) || 70,
|
|
25
|
+
maxWidth: Number(opts?.maxWidth) || 1200,
|
|
26
|
+
};
|
|
27
|
+
console.log("\n OpenWolf Design QC — Screenshot Capture\n");
|
|
28
|
+
const engine = new DesignQCEngine(wolfDir, projectRoot, options);
|
|
29
|
+
await engine.capture();
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=designqc-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"designqc-cmd.js","sourceRoot":"","sources":["../../../src/cli/designqc-cmd.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAoBlE,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAe,EACf,IAAsB;IAEtB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAa,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3E,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,QAAQ,IAAI,EAAE,CAAC;IAE3C,IAAI,SAAS,GAAG,EAAE,CAAC,SAAS,IAAI,iBAAiB,CAAC;IAClD,IAAI,IAAI,EAAE,WAAW,EAAE,CAAC;QACtB,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAC1D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,OAAO,GAAoB;QAC/B,UAAU,EAAE,MAAM;QAClB,YAAY,EAAE,IAAI,EAAE,GAAG;QACvB,MAAM,EAAE,IAAI,EAAE,MAAM;QACpB,SAAS;QACT,cAAc,EAAE,EAAE,CAAC,eAAe,IAAI,EAAE;QACxC,UAAU,EAAE,EAAE,CAAC,WAAW,IAAI,SAAS;QACvC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE;QACpC,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI;KACzC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IACjE,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { findProjectRoot } from "../scanner/project-root.js";
|
|
4
|
+
import { readRegistry, getRegistryPath } from "./registry.js";
|
|
5
|
+
import { getRetention, footprint, humanBytes, compactLedger, consolidateMemory, dedupeAndCapBuglog, pruneBackups, cleanTmp, rotateDaemonLog, dirSize, } from "../utils/maintenance.js";
|
|
6
|
+
// `openwolf doctor` — daemon-independent .wolf/ health report + compaction.
|
|
7
|
+
export async function doctorCommand(opts) {
|
|
8
|
+
const projectRoot = findProjectRoot();
|
|
9
|
+
const wolfDir = path.join(projectRoot, ".wolf");
|
|
10
|
+
if (!fs.existsSync(wolfDir)) {
|
|
11
|
+
console.log("OpenWolf not initialized. Run: openwolf init");
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const ret = getRetention(wolfDir);
|
|
15
|
+
const dry = !!opts.dryRun;
|
|
16
|
+
console.log("OpenWolf Doctor");
|
|
17
|
+
console.log("===============\n");
|
|
18
|
+
// --- Footprint report ---
|
|
19
|
+
const before = footprint(wolfDir, ret);
|
|
20
|
+
console.log(`.wolf/ footprint: ${humanBytes(before.total)}`);
|
|
21
|
+
for (const it of before.items.slice(0, 8)) {
|
|
22
|
+
console.log(` ${humanBytes(it.bytes).padStart(9)} ${it.name}`);
|
|
23
|
+
}
|
|
24
|
+
if (before.warnings.length) {
|
|
25
|
+
console.log("\nWarnings:");
|
|
26
|
+
for (const w of before.warnings)
|
|
27
|
+
console.log(` ⚠ ${w}`);
|
|
28
|
+
}
|
|
29
|
+
// --- Cross-project registry health: dead entries + dashboard-port collisions ---
|
|
30
|
+
try {
|
|
31
|
+
const projects = readRegistry().projects || [];
|
|
32
|
+
const dead = projects.filter((p) => !fs.existsSync(p.root));
|
|
33
|
+
const portMap = new Map();
|
|
34
|
+
for (const p of projects) {
|
|
35
|
+
if (!fs.existsSync(p.root))
|
|
36
|
+
continue;
|
|
37
|
+
try {
|
|
38
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(p.root, ".wolf", "config.json"), "utf-8"));
|
|
39
|
+
const port = cfg?.openwolf?.dashboard?.port;
|
|
40
|
+
if (typeof port === "number")
|
|
41
|
+
portMap.set(port, [...(portMap.get(port) || []), p.name]);
|
|
42
|
+
}
|
|
43
|
+
catch { /* config missing/unreadable */ }
|
|
44
|
+
}
|
|
45
|
+
const collisions = [...portMap.entries()].filter(([, names]) => names.length > 1);
|
|
46
|
+
if (dead.length || collisions.length) {
|
|
47
|
+
console.log("\nRegistry health:");
|
|
48
|
+
for (const d of dead) {
|
|
49
|
+
console.log(` ⚠ dead entry: ${d.name} → ${d.root} (path gone). Remove it from ${getRegistryPath()}.`);
|
|
50
|
+
}
|
|
51
|
+
for (const [port, names] of collisions) {
|
|
52
|
+
console.log(` ⚠ port ${port} shared by ${names.join(", ")} — their daemons will collide. Give each a unique dashboard.port in .wolf/config.json.`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (projects.length > 1) {
|
|
56
|
+
console.log(`\nRegistry health: ${projects.length} projects — unique ports, no dead entries ✓`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch { /* registry not readable — skip */ }
|
|
60
|
+
if (dry) {
|
|
61
|
+
console.log("\n(dry run — no changes written. Run without --dry-run to compact.)");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// --- Compaction pass ---
|
|
65
|
+
console.log("\nCompacting…");
|
|
66
|
+
const totalBefore = before.total;
|
|
67
|
+
const results = [
|
|
68
|
+
compactLedger(wolfDir, ret),
|
|
69
|
+
consolidateMemory(wolfDir, ret.memory_consolidate_after_days),
|
|
70
|
+
dedupeAndCapBuglog(wolfDir, ret.buglog_max_entries),
|
|
71
|
+
pruneBackups(wolfDir, ret.backups_keep),
|
|
72
|
+
rotateDaemonLog(wolfDir, ret.daemon_log_max_bytes),
|
|
73
|
+
cleanTmp(wolfDir),
|
|
74
|
+
];
|
|
75
|
+
let anyChange = false;
|
|
76
|
+
for (const r of results) {
|
|
77
|
+
console.log(` ${r.changed ? "✓" : "·"} ${r.detail}`);
|
|
78
|
+
if (r.changed)
|
|
79
|
+
anyChange = true;
|
|
80
|
+
}
|
|
81
|
+
const totalAfter = dirSize(wolfDir);
|
|
82
|
+
const freed = totalBefore - totalAfter;
|
|
83
|
+
console.log("");
|
|
84
|
+
if (anyChange && freed > 0) {
|
|
85
|
+
console.log(`Done. .wolf/ ${humanBytes(totalBefore)} → ${humanBytes(totalAfter)} (freed ${humanBytes(freed)}).`);
|
|
86
|
+
}
|
|
87
|
+
else if (anyChange) {
|
|
88
|
+
console.log(`Done. .wolf/ now ${humanBytes(totalAfter)}.`);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.log("Everything already within limits — nothing to compact.");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=doctor-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-cmd.js","sourceRoot":"","sources":["../../../src/cli/doctor-cmd.ts"],"names":[],"mappings":"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"}
|