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.
Files changed (127) hide show
  1. package/CHANGELOG.md +386 -0
  2. package/LICENSE +663 -0
  3. package/NOTICE +48 -0
  4. package/README.md +283 -0
  5. package/dist/bin/openwolf.js +10 -0
  6. package/dist/bin/openwolf.js.map +1 -0
  7. package/dist/dashboard/assets/AISuggestions-DHXOgHMM.js +9 -0
  8. package/dist/dashboard/assets/ActivityTimeline-BXLwacZV.js +1 -0
  9. package/dist/dashboard/assets/AnatomyBrowser-CUyC8M2I.js +1 -0
  10. package/dist/dashboard/assets/BugLog-Bxvy1sPW.js +1 -0
  11. package/dist/dashboard/assets/CerebrumViewer-DCySVmzA.js +1 -0
  12. package/dist/dashboard/assets/CronStatus-BA4fmQX3.js +1 -0
  13. package/dist/dashboard/assets/DesignQC-BhNEKryS.js +1 -0
  14. package/dist/dashboard/assets/MemoryViewer-0y9lsDUO.js +1 -0
  15. package/dist/dashboard/assets/ProjectOverview-CC51rVRe.js +1 -0
  16. package/dist/dashboard/assets/StatusBadge-4NJI_F2G.js +1 -0
  17. package/dist/dashboard/assets/TokenUsage-7pCxlnCX.js +55 -0
  18. package/dist/dashboard/assets/index-4O5rk-qB.css +2 -0
  19. package/dist/dashboard/assets/index-jfgWxxsn.js +13 -0
  20. package/dist/dashboard/assets/utils-BqE_aDxV.js +1 -0
  21. package/dist/dashboard/index.html +16 -0
  22. package/dist/hooks/post-read.js +85 -0
  23. package/dist/hooks/post-write.js +520 -0
  24. package/dist/hooks/pre-read.js +107 -0
  25. package/dist/hooks/pre-write.js +120 -0
  26. package/dist/hooks/session-start.js +76 -0
  27. package/dist/hooks/shared.js +0 -0
  28. package/dist/hooks/stop.js +219 -0
  29. package/dist/src/buglog/bug-matcher.js +3 -0
  30. package/dist/src/buglog/bug-matcher.js.map +1 -0
  31. package/dist/src/buglog/bug-tracker.js +89 -0
  32. package/dist/src/buglog/bug-tracker.js.map +1 -0
  33. package/dist/src/cli/bug-cmd.js +31 -0
  34. package/dist/src/cli/bug-cmd.js.map +1 -0
  35. package/dist/src/cli/cron-cmd.js +107 -0
  36. package/dist/src/cli/cron-cmd.js.map +1 -0
  37. package/dist/src/cli/daemon-cmd.js +180 -0
  38. package/dist/src/cli/daemon-cmd.js.map +1 -0
  39. package/dist/src/cli/dashboard.js +88 -0
  40. package/dist/src/cli/dashboard.js.map +1 -0
  41. package/dist/src/cli/designqc-cmd.js +31 -0
  42. package/dist/src/cli/designqc-cmd.js.map +1 -0
  43. package/dist/src/cli/doctor-cmd.js +94 -0
  44. package/dist/src/cli/doctor-cmd.js.map +1 -0
  45. package/dist/src/cli/index.js +158 -0
  46. package/dist/src/cli/index.js.map +1 -0
  47. package/dist/src/cli/init.js +493 -0
  48. package/dist/src/cli/init.js.map +1 -0
  49. package/dist/src/cli/registry.js +93 -0
  50. package/dist/src/cli/registry.js.map +1 -0
  51. package/dist/src/cli/scan.js +39 -0
  52. package/dist/src/cli/scan.js.map +1 -0
  53. package/dist/src/cli/status.js +98 -0
  54. package/dist/src/cli/status.js.map +1 -0
  55. package/dist/src/cli/update.js +435 -0
  56. package/dist/src/cli/update.js.map +1 -0
  57. package/dist/src/daemon/cron-engine.js +321 -0
  58. package/dist/src/daemon/cron-engine.js.map +1 -0
  59. package/dist/src/daemon/file-watcher.js +64 -0
  60. package/dist/src/daemon/file-watcher.js.map +1 -0
  61. package/dist/src/daemon/health.js +23 -0
  62. package/dist/src/daemon/health.js.map +1 -0
  63. package/dist/src/daemon/wolf-daemon.js +440 -0
  64. package/dist/src/daemon/wolf-daemon.js.map +1 -0
  65. package/dist/src/designqc/designqc-capture.js +278 -0
  66. package/dist/src/designqc/designqc-capture.js.map +1 -0
  67. package/dist/src/designqc/designqc-engine.js +159 -0
  68. package/dist/src/designqc/designqc-engine.js.map +1 -0
  69. package/dist/src/designqc/designqc-types.js +5 -0
  70. package/dist/src/designqc/designqc-types.js.map +1 -0
  71. package/dist/src/hooks/post-read.js +86 -0
  72. package/dist/src/hooks/post-read.js.map +1 -0
  73. package/dist/src/hooks/post-write.js +521 -0
  74. package/dist/src/hooks/post-write.js.map +1 -0
  75. package/dist/src/hooks/pre-read.js +108 -0
  76. package/dist/src/hooks/pre-read.js.map +1 -0
  77. package/dist/src/hooks/pre-write.js +121 -0
  78. package/dist/src/hooks/pre-write.js.map +1 -0
  79. package/dist/src/hooks/session-start.js +77 -0
  80. package/dist/src/hooks/session-start.js.map +1 -0
  81. package/dist/src/hooks/shared.js +0 -0
  82. package/dist/src/hooks/shared.js.map +1 -0
  83. package/dist/src/hooks/stop.js +220 -0
  84. package/dist/src/hooks/stop.js.map +1 -0
  85. package/dist/src/scanner/anatomy-scanner.js +278 -0
  86. package/dist/src/scanner/anatomy-scanner.js.map +1 -0
  87. package/dist/src/scanner/description-extractor.js +1007 -0
  88. package/dist/src/scanner/description-extractor.js.map +1 -0
  89. package/dist/src/scanner/project-root.js +52 -0
  90. package/dist/src/scanner/project-root.js.map +1 -0
  91. package/dist/src/tracker/token-estimator.js +20 -0
  92. package/dist/src/tracker/token-estimator.js.map +1 -0
  93. package/dist/src/tracker/token-ledger.js +55 -0
  94. package/dist/src/tracker/token-ledger.js.map +1 -0
  95. package/dist/src/tracker/waste-detector.js +101 -0
  96. package/dist/src/tracker/waste-detector.js.map +1 -0
  97. package/dist/src/utils/dashboard-auth.js +50 -0
  98. package/dist/src/utils/dashboard-auth.js.map +1 -0
  99. package/dist/src/utils/fs-safe.js +135 -0
  100. package/dist/src/utils/fs-safe.js.map +1 -0
  101. package/dist/src/utils/hooks-deploy.js +70 -0
  102. package/dist/src/utils/hooks-deploy.js.map +1 -0
  103. package/dist/src/utils/logger.js +48 -0
  104. package/dist/src/utils/logger.js.map +1 -0
  105. package/dist/src/utils/maintenance.js +385 -0
  106. package/dist/src/utils/maintenance.js.map +1 -0
  107. package/dist/src/utils/paths.js +23 -0
  108. package/dist/src/utils/paths.js.map +1 -0
  109. package/dist/src/utils/platform.js +14 -0
  110. package/dist/src/utils/platform.js.map +1 -0
  111. package/dist/src/utils/seed.js +61 -0
  112. package/dist/src/utils/seed.js.map +1 -0
  113. package/package.json +82 -0
  114. package/src/templates/OPENWOLF.md +147 -0
  115. package/src/templates/STATUS.md +48 -0
  116. package/src/templates/anatomy.md +5 -0
  117. package/src/templates/buglog.json +4 -0
  118. package/src/templates/cerebrum.md +22 -0
  119. package/src/templates/claude-md-snippet.md +5 -0
  120. package/src/templates/claude-rules-openwolf.md +17 -0
  121. package/src/templates/config.json +83 -0
  122. package/src/templates/cron-manifest.json +97 -0
  123. package/src/templates/cron-state.json +7 -0
  124. package/src/templates/identity.md +9 -0
  125. package/src/templates/memory.md +4 -0
  126. package/src/templates/reframe-frameworks.md +597 -0
  127. package/src/templates/token-ledger.json +21 -0
@@ -0,0 +1,278 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import * as http from "node:http";
4
+ import { execSync, spawn } from "node:child_process";
5
+ export function findChromePath(configPath) {
6
+ if (configPath && fs.existsSync(configPath))
7
+ return configPath;
8
+ if (process.platform === "win32") {
9
+ const candidates = [
10
+ path.join(process.env["PROGRAMFILES"] || "C:\\Program Files", "Google\\Chrome\\Application\\chrome.exe"),
11
+ path.join(process.env["PROGRAMFILES(X86)"] || "C:\\Program Files (x86)", "Google\\Chrome\\Application\\chrome.exe"),
12
+ path.join(process.env["LOCALAPPDATA"] || "", "Google\\Chrome\\Application\\chrome.exe"),
13
+ path.join(process.env["PROGRAMFILES(X86)"] || "C:\\Program Files (x86)", "Microsoft\\Edge\\Application\\msedge.exe"),
14
+ path.join(process.env["PROGRAMFILES"] || "C:\\Program Files", "Microsoft\\Edge\\Application\\msedge.exe"),
15
+ ];
16
+ for (const c of candidates) {
17
+ if (fs.existsSync(c))
18
+ return c;
19
+ }
20
+ try {
21
+ const r = execSync("where chrome", { encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }).trim();
22
+ if (r)
23
+ return r.split("\n")[0].trim();
24
+ }
25
+ catch { }
26
+ try {
27
+ const r = execSync("where msedge", { encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }).trim();
28
+ if (r)
29
+ return r.split("\n")[0].trim();
30
+ }
31
+ catch { }
32
+ }
33
+ else if (process.platform === "darwin") {
34
+ for (const c of [
35
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
36
+ "/Applications/Chromium.app/Contents/MacOS/Chromium",
37
+ ]) {
38
+ if (fs.existsSync(c))
39
+ return c;
40
+ }
41
+ }
42
+ else {
43
+ try {
44
+ return execSync("which google-chrome || which chromium || which chromium-browser", {
45
+ encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"],
46
+ }).trim().split("\n")[0];
47
+ }
48
+ catch { }
49
+ }
50
+ throw new Error("Chrome/Edge not found. Install Chrome or set designqc.chrome_path in .wolf/config.json");
51
+ }
52
+ /**
53
+ * Capture a full page as sectioned viewport-height screenshots.
54
+ * Returns multiple screenshots — one per "fold" of the page.
55
+ * This gives Claude focused views of each section without one massive image.
56
+ */
57
+ export async function captureRouteSectioned(page, url, viewport, outputDir, quality, maxWidth) {
58
+ const scale = maxWidth < viewport.width ? maxWidth / viewport.width : 1;
59
+ const captureWidth = Math.round(viewport.width * scale);
60
+ const captureHeight = Math.round(viewport.height * scale);
61
+ await page.setViewport({ width: captureWidth, height: captureHeight });
62
+ await page.goto(url, { waitUntil: "networkidle2", timeout: 30_000 });
63
+ await new Promise((r) => setTimeout(r, 1500));
64
+ // Get full page height
65
+ const fullHeight = await page.evaluate(() => document.documentElement.scrollHeight);
66
+ const route = new URL(url).pathname;
67
+ const safeName = route.replace(/\//g, "_").replace(/^_/, "") || "root";
68
+ const screenshots = [];
69
+ const sectionHeight = captureHeight;
70
+ const totalSections = Math.ceil(fullHeight / sectionHeight);
71
+ // Cap at 8 sections (~20K tokens) to avoid runaway costs
72
+ const maxSections = Math.min(totalSections, 8);
73
+ for (let i = 0; i < maxSections; i++) {
74
+ const y = i * sectionHeight;
75
+ // Scroll to position
76
+ await page.evaluate((scrollY) => window.scrollTo(0, scrollY), y);
77
+ await new Promise((r) => setTimeout(r, 500));
78
+ const screenshotBuffer = await page.screenshot({
79
+ fullPage: false,
80
+ type: "jpeg",
81
+ quality,
82
+ });
83
+ const sectionLabel = i === 0 ? "top" : i === maxSections - 1 ? "bottom" : `section${i + 1}`;
84
+ const fileName = `${safeName}_${viewport.name}_${sectionLabel}.jpg`;
85
+ const filePath = path.join(outputDir, fileName);
86
+ fs.writeFileSync(filePath, screenshotBuffer);
87
+ screenshots.push({ route, viewport, path: filePath });
88
+ }
89
+ return screenshots;
90
+ }
91
+ export function detectRoutes(projectRoot) {
92
+ const routes = ["/"];
93
+ const dirs = [
94
+ path.join(projectRoot, "pages"),
95
+ path.join(projectRoot, "app"),
96
+ path.join(projectRoot, "src", "pages"),
97
+ path.join(projectRoot, "src", "app"),
98
+ ].filter((d) => fs.existsSync(d));
99
+ for (const dir of dirs) {
100
+ try {
101
+ const files = fs.readdirSync(dir, { recursive: true });
102
+ for (const file of files) {
103
+ const f = String(file).replace(/\\/g, "/");
104
+ if (f.includes("api/") || f.includes("_") || f.includes("layout."))
105
+ continue;
106
+ if (f.endsWith(".tsx") || f.endsWith(".jsx") || f.endsWith(".ts") || f.endsWith(".js")) {
107
+ let route = "/" + f
108
+ .replace(/\.(tsx|jsx|ts|js)$/, "")
109
+ .replace(/\/index$/, "")
110
+ .replace(/\/page$/, "");
111
+ if (route === "/")
112
+ continue;
113
+ routes.push(route);
114
+ }
115
+ }
116
+ }
117
+ catch { }
118
+ }
119
+ return [...new Set(routes)].slice(0, 10);
120
+ }
121
+ export async function probePort(port) {
122
+ return new Promise((resolve) => {
123
+ const req = http.get(`http://localhost:${port}`, () => resolve(true));
124
+ req.on("error", () => resolve(false));
125
+ req.setTimeout(2000, () => { req.destroy(); resolve(false); });
126
+ });
127
+ }
128
+ /**
129
+ * Try to find a running dev server on common ports.
130
+ */
131
+ /**
132
+ * Detect the project's deployed/production URL from common config files
133
+ * (package.json homepage, .env* URL vars, vercel.json aliases). Returns null if none —
134
+ * the caller then falls back to a local dev server (upstream #4, bug 4).
135
+ */
136
+ export function detectDeployedUrl(projectRoot) {
137
+ // 1. package.json "homepage"
138
+ try {
139
+ const pkg = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf-8"));
140
+ if (typeof pkg.homepage === "string" && pkg.homepage.startsWith("http"))
141
+ return pkg.homepage;
142
+ }
143
+ catch { /* ignore */ }
144
+ // 2. Common env files — a production URL variable
145
+ const envFiles = [".env.production", ".env.production.local", ".env.local", ".env"];
146
+ const urlVarNames = [
147
+ "NEXT_PUBLIC_SITE_URL", "NEXT_PUBLIC_URL", "NEXT_PUBLIC_APP_URL",
148
+ "NUXT_PUBLIC_SITE_URL", "VITE_APP_URL", "VITE_APP_BASE_URL",
149
+ "PUBLIC_URL", "APP_URL", "SITE_URL", "BASE_URL",
150
+ ];
151
+ for (const envFile of envFiles) {
152
+ try {
153
+ const content = fs.readFileSync(path.join(projectRoot, envFile), "utf-8");
154
+ for (const varName of urlVarNames) {
155
+ const match = content.match(new RegExp(`^${varName}=["']?([^"'\\s]+)["']?`, "m"));
156
+ if (match && match[1].startsWith("http"))
157
+ return match[1].trim();
158
+ }
159
+ }
160
+ catch { /* ignore */ }
161
+ }
162
+ // 3. vercel.json alias(es)
163
+ try {
164
+ const vercelJson = JSON.parse(fs.readFileSync(path.join(projectRoot, "vercel.json"), "utf-8"));
165
+ const aliases = vercelJson.alias ?? vercelJson.aliases;
166
+ if (Array.isArray(aliases) && aliases.length > 0 && typeof aliases[0] === "string") {
167
+ const alias = aliases[0];
168
+ return alias.startsWith("http") ? alias : `https://${alias}`;
169
+ }
170
+ }
171
+ catch { /* ignore */ }
172
+ return null;
173
+ }
174
+ export async function detectDevServer() {
175
+ const commonPorts = [3000, 3001, 5173, 5174, 4321, 8080, 8000, 4200];
176
+ for (const port of commonPorts) {
177
+ if (await probePort(port)) {
178
+ return { url: `http://localhost:${port}`, port };
179
+ }
180
+ }
181
+ return null;
182
+ }
183
+ /**
184
+ * Detect the dev command from package.json.
185
+ * Returns { command, port } or null.
186
+ */
187
+ export function detectDevCommand(projectRoot) {
188
+ const pkgPath = path.join(projectRoot, "package.json");
189
+ if (!fs.existsSync(pkgPath))
190
+ return null;
191
+ try {
192
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
193
+ const scripts = pkg.scripts || {};
194
+ // Priority order: dev, start, serve
195
+ for (const key of ["dev", "start", "serve"]) {
196
+ if (scripts[key]) {
197
+ // Try to detect port from the script
198
+ const portMatch = scripts[key].match(/-p\s+(\d+)|--port\s+(\d+)|PORT=(\d+)/);
199
+ let port = 3000;
200
+ if (portMatch) {
201
+ port = parseInt(portMatch[1] || portMatch[2] || portMatch[3], 10);
202
+ }
203
+ else if (scripts[key].includes("vite")) {
204
+ port = 5173;
205
+ }
206
+ else if (scripts[key].includes("next")) {
207
+ port = 3000;
208
+ }
209
+ else if (scripts[key].includes("astro")) {
210
+ port = 4321;
211
+ }
212
+ else if (scripts[key].includes("angular") || scripts[key].includes("ng serve")) {
213
+ port = 4200;
214
+ }
215
+ // Determine package manager
216
+ let runner = "npm run";
217
+ if (fs.existsSync(path.join(projectRoot, "pnpm-lock.yaml")))
218
+ runner = "pnpm";
219
+ else if (fs.existsSync(path.join(projectRoot, "yarn.lock")))
220
+ runner = "yarn";
221
+ else if (fs.existsSync(path.join(projectRoot, "bun.lockb")))
222
+ runner = "bun run";
223
+ return { command: `${runner} ${key}`, expectedPort: port };
224
+ }
225
+ }
226
+ }
227
+ catch { }
228
+ return null;
229
+ }
230
+ /**
231
+ * Start the dev server, wait for it to be ready, return the process handle.
232
+ * Caller is responsible for killing the process.
233
+ */
234
+ export async function startDevServer(projectRoot) {
235
+ const devCmd = detectDevCommand(projectRoot);
236
+ if (!devCmd) {
237
+ console.error(" No dev script found in package.json (looked for: dev, start, serve)");
238
+ return null;
239
+ }
240
+ console.log(` Starting dev server: ${devCmd.command}`);
241
+ const proc = spawn(devCmd.command, {
242
+ cwd: projectRoot,
243
+ shell: true,
244
+ stdio: ["ignore", "pipe", "pipe"],
245
+ windowsHide: true,
246
+ });
247
+ // Wait for server to be ready (poll port)
248
+ const port = devCmd.expectedPort;
249
+ const maxWait = 30_000;
250
+ const start = Date.now();
251
+ let ready = false;
252
+ while (Date.now() - start < maxWait) {
253
+ // Check if process died
254
+ if (proc.exitCode !== null) {
255
+ console.error(` Dev server exited with code ${proc.exitCode}`);
256
+ return null;
257
+ }
258
+ if (await probePort(port)) {
259
+ ready = true;
260
+ break;
261
+ }
262
+ await new Promise((r) => setTimeout(r, 1000));
263
+ }
264
+ if (!ready) {
265
+ // Try nearby ports in case the detected port was wrong
266
+ for (const p of [3000, 3001, 5173, 5174, 4321, 8080]) {
267
+ if (p !== port && await probePort(p)) {
268
+ console.log(` Server responded on port ${p} (expected ${port})`);
269
+ return { proc, url: `http://localhost:${p}`, port: p };
270
+ }
271
+ }
272
+ console.error(` Dev server did not respond on port ${port} within ${maxWait / 1000}s`);
273
+ proc.kill();
274
+ return null;
275
+ }
276
+ return { proc, url: `http://localhost:${port}`, port };
277
+ }
278
+ //# sourceMappingURL=designqc-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designqc-capture.js","sourceRoot":"","sources":["../../../src/designqc/designqc-capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ import * as path from "node:path";
2
+ import * as fs from "node:fs";
3
+ import { appendText, writeJSON } from "../utils/fs-safe.js";
4
+ import { findChromePath, captureRouteSectioned, detectRoutes, detectDevServer, detectDeployedUrl, startDevServer, } from "./designqc-capture.js";
5
+ import { DEFAULT_VIEWPORTS } from "./designqc-types.js";
6
+ export class DesignQCEngine {
7
+ wolfDir;
8
+ projectRoot;
9
+ options;
10
+ constructor(wolfDir, projectRoot, options) {
11
+ this.wolfDir = wolfDir;
12
+ this.projectRoot = projectRoot;
13
+ this.options = options;
14
+ }
15
+ async capture() {
16
+ let baseUrl = this.options.devServerUrl;
17
+ let serverProc = null;
18
+ let weStartedServer = false;
19
+ try {
20
+ // 1. Find or start server — try a deployed URL first, then a local dev server (#4, bug 4)
21
+ if (!baseUrl) {
22
+ const deployedUrl = detectDeployedUrl(this.projectRoot);
23
+ if (deployedUrl) {
24
+ baseUrl = deployedUrl;
25
+ console.log(` Detected deployed URL: ${baseUrl}`);
26
+ }
27
+ else {
28
+ console.log(" Checking for running dev server...");
29
+ const existing = await detectDevServer();
30
+ if (existing) {
31
+ baseUrl = existing.url;
32
+ console.log(` Found running server at ${baseUrl}`);
33
+ }
34
+ else {
35
+ console.log(" No running server found. Starting dev server...");
36
+ const started = await startDevServer(this.projectRoot);
37
+ if (!started) {
38
+ console.error(" Could not start dev server. Add a 'homepage' to package.json or use --url to specify the URL.");
39
+ return { screenshots: [], captureDir: "", totalSizeKB: 0, estimatedTokens: 0 };
40
+ }
41
+ baseUrl = started.url;
42
+ serverProc = started.proc;
43
+ weStartedServer = true;
44
+ console.log(` Dev server ready at ${baseUrl}`);
45
+ }
46
+ }
47
+ }
48
+ // 2. Detect routes
49
+ let routes = this.options.routes || [];
50
+ if (routes.length === 0) {
51
+ routes = detectRoutes(this.projectRoot);
52
+ }
53
+ console.log(` Routes: ${routes.join(", ")}`);
54
+ // 3. Prepare output directory
55
+ const captureDir = path.join(this.wolfDir, "designqc-captures");
56
+ if (fs.existsSync(captureDir)) {
57
+ for (const f of fs.readdirSync(captureDir)) {
58
+ fs.unlinkSync(path.join(captureDir, f));
59
+ }
60
+ }
61
+ else {
62
+ fs.mkdirSync(captureDir, { recursive: true });
63
+ }
64
+ // 4. Launch browser
65
+ console.log(" Launching browser...");
66
+ const chromePath = findChromePath(this.options.chromePath);
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ let puppeteer;
69
+ try {
70
+ puppeteer = await import("puppeteer-core");
71
+ }
72
+ catch {
73
+ console.error("puppeteer-core is required for designqc. Install it with: pnpm add puppeteer-core");
74
+ return { screenshots: [], captureDir: "", totalSizeKB: 0, estimatedTokens: 0 };
75
+ }
76
+ const browser = await puppeteer.default.launch({
77
+ executablePath: chromePath,
78
+ headless: true,
79
+ args: ["--no-sandbox", "--disable-setuid-sandbox"],
80
+ });
81
+ const viewports = this.options.viewports || DEFAULT_VIEWPORTS;
82
+ const allScreenshots = [];
83
+ try {
84
+ const page = await browser.newPage();
85
+ for (const route of routes) {
86
+ for (const viewport of viewports) {
87
+ if (allScreenshots.length >= this.options.maxScreenshots)
88
+ break;
89
+ const url = `${baseUrl}${route}`;
90
+ console.log(` Capturing ${route} (${viewport.name}) — full page sections...`);
91
+ try {
92
+ const sections = await captureRouteSectioned(page, url, viewport, captureDir, this.options.quality, this.options.maxWidth);
93
+ // Respect max screenshots limit
94
+ const remaining = this.options.maxScreenshots - allScreenshots.length;
95
+ allScreenshots.push(...sections.slice(0, remaining));
96
+ }
97
+ catch (err) {
98
+ console.error(` Failed to capture ${url}: ${err.message}`);
99
+ }
100
+ }
101
+ if (allScreenshots.length >= this.options.maxScreenshots)
102
+ break;
103
+ }
104
+ await page.close();
105
+ }
106
+ finally {
107
+ await browser.close();
108
+ }
109
+ // 5. Calculate sizes and token estimates
110
+ let totalSizeBytes = 0;
111
+ for (const s of allScreenshots) {
112
+ try {
113
+ totalSizeBytes += fs.statSync(s.path).size;
114
+ }
115
+ catch { }
116
+ }
117
+ const totalSizeKB = Math.round(totalSizeBytes / 1024);
118
+ const estimatedTokens = allScreenshots.length * 2500;
119
+ // 6. Print results
120
+ console.log("");
121
+ console.log(` Captured ${allScreenshots.length} screenshot(s) across ${routes.length} route(s)`);
122
+ console.log(` Total size: ${totalSizeKB}KB`);
123
+ console.log(` Estimated token cost: ~${estimatedTokens} tokens`);
124
+ console.log(` Saved to: ${captureDir}`);
125
+ console.log("");
126
+ console.log(" Screenshots:");
127
+ for (const s of allScreenshots) {
128
+ const sizeKB = Math.round(fs.statSync(s.path).size / 1024);
129
+ console.log(` ${path.basename(s.path)} (${sizeKB}KB)`);
130
+ }
131
+ console.log("");
132
+ console.log(" Ask Claude: \"Read the screenshots in .wolf/designqc-captures/ and evaluate the design\"");
133
+ // 7. Write the report so the dashboard's Design QC panel can show it (#4, bug 4).
134
+ writeJSON(path.join(this.wolfDir, "designqc-report.json"), {
135
+ captured_at: new Date().toISOString(),
136
+ captures: allScreenshots.map((s) => ({
137
+ file: path.basename(s.path),
138
+ viewport: s.viewport.name,
139
+ route: s.route,
140
+ })),
141
+ total_size_kb: totalSizeKB,
142
+ estimated_tokens: estimatedTokens,
143
+ });
144
+ // 8. Log to memory
145
+ const now = new Date();
146
+ const timeStr = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`;
147
+ appendText(path.join(this.wolfDir, "memory.md"), `| ${timeStr} | designqc: captured ${allScreenshots.length} screenshots (${totalSizeKB}KB, ~${estimatedTokens} tok) | ${routes.join(", ")} | ready for eval | ~0 |\n`);
148
+ return { screenshots: allScreenshots, captureDir, totalSizeKB, estimatedTokens };
149
+ }
150
+ finally {
151
+ // 8. Kill dev server if we started it
152
+ if (weStartedServer && serverProc) {
153
+ console.log(" Stopping dev server...");
154
+ serverProc.kill();
155
+ }
156
+ }
157
+ }
158
+ }
159
+ //# sourceMappingURL=designqc-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designqc-engine.js","sourceRoot":"","sources":["../../../src/designqc/designqc-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export const DEFAULT_VIEWPORTS = [
2
+ { name: "desktop", width: 1440, height: 900 },
3
+ { name: "mobile", width: 375, height: 812 },
4
+ ];
5
+ //# sourceMappingURL=designqc-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designqc-types.js","sourceRoot":"","sources":["../../../src/designqc/designqc-types.ts"],"names":[],"mappings":"AA8BA,MAAM,CAAC,MAAM,iBAAiB,GAAe;IAC3C,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IAC7C,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;CAC5C,CAAC"}
@@ -0,0 +1,86 @@
1
+ import * as path from "node:path";
2
+ import { getWolfDir, ensureWolfDir, readJSON, writeJSON, readMarkdown, parseAnatomy, estimateTokens, readStdin, normalizePath, loadIgnore, isSecretFile } from "./shared.js";
3
+ async function main() {
4
+ ensureWolfDir();
5
+ const wolfDir = getWolfDir();
6
+ const hooksDir = path.join(wolfDir, "hooks");
7
+ const sessionFile = path.join(hooksDir, "_session.json");
8
+ const raw = await readStdin();
9
+ let input;
10
+ try {
11
+ input = JSON.parse(raw);
12
+ }
13
+ catch {
14
+ process.exit(0);
15
+ return;
16
+ }
17
+ const filePath = input.tool_input?.file_path ?? input.tool_input?.path ?? "";
18
+ const content = input.tool_output?.content ?? "";
19
+ if (!filePath) {
20
+ process.exit(0);
21
+ return;
22
+ }
23
+ const normalizedFile = normalizePath(filePath);
24
+ // Skip tracking for .wolf/ internal files — consistent with pre-read
25
+ const projectDir = normalizePath(process.env.CLAUDE_PROJECT_DIR || process.cwd());
26
+ const relToProject = normalizedFile.startsWith(projectDir)
27
+ ? normalizedFile.slice(projectDir.length).replace(/^\//, "")
28
+ : "";
29
+ // Don't track reads of files outside the project root (upstream #56). relToProject is ""
30
+ // both when the path is outside projectDir and when it equals the root itself — neither
31
+ // is a trackable project file.
32
+ if (!relToProject) {
33
+ process.exit(0);
34
+ return;
35
+ }
36
+ if (relToProject.startsWith(".wolf/") || relToProject.startsWith(".wolf\\")) {
37
+ process.exit(0);
38
+ return;
39
+ }
40
+ // Skip anything matched by .gitignore / .wolfignore — don't track ignored reads.
41
+ if (loadIgnore(projectDir)(relToProject)) {
42
+ process.exit(0);
43
+ return;
44
+ }
45
+ // Never track secret-bearing files in the ledger (#54).
46
+ if (isSecretFile(normalizedFile)) {
47
+ process.exit(0);
48
+ return;
49
+ }
50
+ const ext = path.extname(filePath).toLowerCase();
51
+ const codeExts = new Set([".ts", ".js", ".tsx", ".jsx", ".py", ".rs", ".go", ".java", ".c", ".cpp", ".css", ".json", ".yaml", ".yml", ".dart"]);
52
+ const proseExts = new Set([".md", ".txt", ".rst"]);
53
+ const type = codeExts.has(ext) ? "code" : proseExts.has(ext) ? "prose" : "mixed";
54
+ let tokens = content ? estimateTokens(content, type) : 0;
55
+ // Fallback: if tool_output had no content, use anatomy token estimate
56
+ if (tokens === 0) {
57
+ const anatomyContent = readMarkdown(path.join(wolfDir, "anatomy.md"));
58
+ const sections = parseAnatomy(anatomyContent);
59
+ for (const [sectionKey, entries] of sections) {
60
+ for (const entry of entries) {
61
+ const entryRelPath = normalizePath(path.join(sectionKey, entry.file));
62
+ if (normalizedFile.endsWith(entryRelPath) || normalizedFile.endsWith("/" + entryRelPath)) {
63
+ tokens = entry.tokens;
64
+ break;
65
+ }
66
+ }
67
+ if (tokens > 0)
68
+ break;
69
+ }
70
+ }
71
+ const session = readJSON(sessionFile, { files_read: {} });
72
+ if (session.files_read[normalizedFile]) {
73
+ session.files_read[normalizedFile].tokens = tokens;
74
+ }
75
+ else {
76
+ session.files_read[normalizedFile] = {
77
+ count: 1,
78
+ tokens,
79
+ first_read: new Date().toISOString(),
80
+ };
81
+ }
82
+ writeJSON(sessionFile, session);
83
+ process.exit(0);
84
+ }
85
+ main().catch(() => process.exit(0));
86
+ //# sourceMappingURL=post-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-read.js","sourceRoot":"","sources":["../../../src/hooks/post-read.ts"],"names":[],"mappings":"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"}