forge-cc 1.0.0 → 1.0.1

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 (142) hide show
  1. package/package.json +3 -2
  2. package/dist/gates/codex-gate.d.ts +0 -51
  3. package/dist/gates/codex-gate.js +0 -121
  4. package/dist/gates/codex-gate.js.map +0 -1
  5. package/dist/gates/prd-gate.d.ts +0 -7
  6. package/dist/gates/prd-gate.js +0 -193
  7. package/dist/gates/prd-gate.js.map +0 -1
  8. package/dist/gates/remediation.d.ts +0 -46
  9. package/dist/gates/remediation.js +0 -423
  10. package/dist/gates/remediation.js.map +0 -1
  11. package/dist/gates/review-gate.d.ts +0 -16
  12. package/dist/gates/review-gate.js +0 -479
  13. package/dist/gates/review-gate.js.map +0 -1
  14. package/dist/gates/runtime-gate.d.ts +0 -5
  15. package/dist/gates/runtime-gate.js +0 -99
  16. package/dist/gates/runtime-gate.js.map +0 -1
  17. package/dist/gates/test-analysis.d.ts +0 -21
  18. package/dist/gates/test-analysis.js +0 -394
  19. package/dist/gates/test-analysis.js.map +0 -1
  20. package/dist/gates/visual-capture.d.ts +0 -24
  21. package/dist/gates/visual-capture.js +0 -144
  22. package/dist/gates/visual-capture.js.map +0 -1
  23. package/dist/gates/visual-gate.d.ts +0 -18
  24. package/dist/gates/visual-gate.js +0 -234
  25. package/dist/gates/visual-gate.js.map +0 -1
  26. package/dist/gates/visual-reviewer.d.ts +0 -11
  27. package/dist/gates/visual-reviewer.js +0 -211
  28. package/dist/gates/visual-reviewer.js.map +0 -1
  29. package/dist/go/auto-chain.d.ts +0 -136
  30. package/dist/go/auto-chain.js +0 -389
  31. package/dist/go/auto-chain.js.map +0 -1
  32. package/dist/go/executor.d.ts +0 -137
  33. package/dist/go/executor.js +0 -447
  34. package/dist/go/executor.js.map +0 -1
  35. package/dist/go/finalize.d.ts +0 -108
  36. package/dist/go/finalize.js +0 -331
  37. package/dist/go/finalize.js.map +0 -1
  38. package/dist/go/linear-sync-cli.d.ts +0 -55
  39. package/dist/go/linear-sync-cli.js +0 -192
  40. package/dist/go/linear-sync-cli.js.map +0 -1
  41. package/dist/go/linear-sync.d.ts +0 -112
  42. package/dist/go/linear-sync.js +0 -375
  43. package/dist/go/linear-sync.js.map +0 -1
  44. package/dist/go/prd-queue.d.ts +0 -43
  45. package/dist/go/prd-queue.js +0 -67
  46. package/dist/go/prd-queue.js.map +0 -1
  47. package/dist/go/prd-selector.d.ts +0 -57
  48. package/dist/go/prd-selector.js +0 -101
  49. package/dist/go/prd-selector.js.map +0 -1
  50. package/dist/go/verify-loop.d.ts +0 -64
  51. package/dist/go/verify-loop.js +0 -327
  52. package/dist/go/verify-loop.js.map +0 -1
  53. package/dist/hooks/pre-commit.d.ts +0 -5
  54. package/dist/hooks/pre-commit.js +0 -75
  55. package/dist/hooks/pre-commit.js.map +0 -1
  56. package/dist/linear/issues.d.ts +0 -22
  57. package/dist/linear/issues.js +0 -51
  58. package/dist/linear/issues.js.map +0 -1
  59. package/dist/linear/milestones.d.ts +0 -11
  60. package/dist/linear/milestones.js +0 -32
  61. package/dist/linear/milestones.js.map +0 -1
  62. package/dist/linear/projects.d.ts +0 -16
  63. package/dist/linear/projects.js +0 -51
  64. package/dist/linear/projects.js.map +0 -1
  65. package/dist/reporter/human.d.ts +0 -7
  66. package/dist/reporter/human.js +0 -93
  67. package/dist/reporter/human.js.map +0 -1
  68. package/dist/reporter/json.d.ts +0 -2
  69. package/dist/reporter/json.js +0 -4
  70. package/dist/reporter/json.js.map +0 -1
  71. package/dist/setup/structural-templates.d.ts +0 -12
  72. package/dist/setup/structural-templates.js +0 -288
  73. package/dist/setup/structural-templates.js.map +0 -1
  74. package/dist/setup/templates.d.ts +0 -17
  75. package/dist/setup/templates.js +0 -109
  76. package/dist/setup/templates.js.map +0 -1
  77. package/dist/setup/test-planner.d.ts +0 -38
  78. package/dist/setup/test-planner.js +0 -91
  79. package/dist/setup/test-planner.js.map +0 -1
  80. package/dist/setup/test-scaffold.d.ts +0 -31
  81. package/dist/setup/test-scaffold.js +0 -209
  82. package/dist/setup/test-scaffold.js.map +0 -1
  83. package/dist/setup/test-templates.d.ts +0 -37
  84. package/dist/setup/test-templates.js +0 -313
  85. package/dist/setup/test-templates.js.map +0 -1
  86. package/dist/spec/generator.d.ts +0 -34
  87. package/dist/spec/generator.js +0 -227
  88. package/dist/spec/generator.js.map +0 -1
  89. package/dist/spec/interview.d.ts +0 -142
  90. package/dist/spec/interview.js +0 -287
  91. package/dist/spec/interview.js.map +0 -1
  92. package/dist/spec/linear-sync.d.ts +0 -48
  93. package/dist/spec/linear-sync.js +0 -125
  94. package/dist/spec/linear-sync.js.map +0 -1
  95. package/dist/spec/scanner.d.ts +0 -79
  96. package/dist/spec/scanner.js +0 -566
  97. package/dist/spec/scanner.js.map +0 -1
  98. package/dist/spec/templates.d.ts +0 -375
  99. package/dist/spec/templates.js +0 -95
  100. package/dist/spec/templates.js.map +0 -1
  101. package/dist/state/prd-status.d.ts +0 -62
  102. package/dist/state/prd-status.js +0 -122
  103. package/dist/state/prd-status.js.map +0 -1
  104. package/dist/state/reader.d.ts +0 -7
  105. package/dist/state/reader.js +0 -43
  106. package/dist/state/reader.js.map +0 -1
  107. package/dist/state/writer.d.ts +0 -21
  108. package/dist/state/writer.js +0 -106
  109. package/dist/state/writer.js.map +0 -1
  110. package/dist/team/consensus.d.ts +0 -28
  111. package/dist/team/consensus.js +0 -130
  112. package/dist/team/consensus.js.map +0 -1
  113. package/dist/team/index.d.ts +0 -4
  114. package/dist/team/index.js +0 -5
  115. package/dist/team/index.js.map +0 -1
  116. package/dist/team/lifecycle.d.ts +0 -37
  117. package/dist/team/lifecycle.js +0 -92
  118. package/dist/team/lifecycle.js.map +0 -1
  119. package/dist/team/reviewer.d.ts +0 -10
  120. package/dist/team/reviewer.js +0 -345
  121. package/dist/team/reviewer.js.map +0 -1
  122. package/dist/team/types.d.ts +0 -269
  123. package/dist/team/types.js +0 -70
  124. package/dist/team/types.js.map +0 -1
  125. package/dist/utils/browser.d.ts +0 -10
  126. package/dist/utils/browser.js +0 -96
  127. package/dist/utils/browser.js.map +0 -1
  128. package/dist/utils/platform.d.ts +0 -29
  129. package/dist/utils/platform.js +0 -90
  130. package/dist/utils/platform.js.map +0 -1
  131. package/dist/worktree/identity.d.ts +0 -9
  132. package/dist/worktree/identity.js +0 -32
  133. package/dist/worktree/identity.js.map +0 -1
  134. package/dist/worktree/parallel.d.ts +0 -87
  135. package/dist/worktree/parallel.js +0 -328
  136. package/dist/worktree/parallel.js.map +0 -1
  137. package/dist/worktree/session.d.ts +0 -67
  138. package/dist/worktree/session.js +0 -194
  139. package/dist/worktree/session.js.map +0 -1
  140. package/dist/worktree/state-merge.d.ts +0 -43
  141. package/dist/worktree/state-merge.js +0 -162
  142. package/dist/worktree/state-merge.js.map +0 -1
@@ -1,394 +0,0 @@
1
- import { readdir, readFile, stat } from "node:fs/promises";
2
- import { join, relative, basename, dirname, extname } from "node:path";
3
- // ---------------------------------------------------------------------------
4
- // Helpers
5
- // ---------------------------------------------------------------------------
6
- /** Recursively collect files under a directory. */
7
- async function collectFiles(dir) {
8
- const results = [];
9
- let entries;
10
- try {
11
- entries = await readdir(dir, { withFileTypes: true });
12
- }
13
- catch {
14
- return results;
15
- }
16
- for (const entry of entries) {
17
- const full = join(dir, entry.name);
18
- if (entry.isDirectory()) {
19
- // Skip common non-source directories
20
- if (entry.name === "node_modules" ||
21
- entry.name === "dist" ||
22
- entry.name === ".git" ||
23
- entry.name === ".next" ||
24
- entry.name === "coverage") {
25
- continue;
26
- }
27
- results.push(...(await collectFiles(full)));
28
- }
29
- else if (entry.isFile()) {
30
- results.push(full);
31
- }
32
- }
33
- return results;
34
- }
35
- /** Check whether a file path is a test file. */
36
- function isTestFile(filePath) {
37
- const base = basename(filePath);
38
- return (base.endsWith(".test.ts") ||
39
- base.endsWith(".test.tsx") ||
40
- base.endsWith(".spec.ts") ||
41
- base.endsWith(".spec.tsx") ||
42
- base.endsWith(".test.js") ||
43
- base.endsWith(".test.jsx") ||
44
- base.endsWith(".spec.js") ||
45
- base.endsWith(".spec.jsx"));
46
- }
47
- /** Check whether a file is a TypeScript/JavaScript source file (not a test, not a declaration). */
48
- function isSourceFile(filePath) {
49
- const base = basename(filePath);
50
- const ext = extname(filePath);
51
- if (![".ts", ".tsx", ".js", ".jsx"].includes(ext))
52
- return false;
53
- if (isTestFile(filePath))
54
- return false;
55
- if (base.endsWith(".d.ts"))
56
- return false;
57
- return true;
58
- }
59
- /** Check whether a directory exists. */
60
- async function dirExists(dirPath) {
61
- try {
62
- const s = await stat(dirPath);
63
- return s.isDirectory();
64
- }
65
- catch {
66
- return false;
67
- }
68
- }
69
- /** Check whether a file exists. */
70
- async function fileExists(filePath) {
71
- try {
72
- const s = await stat(filePath);
73
- return s.isFile();
74
- }
75
- catch {
76
- return false;
77
- }
78
- }
79
- /** Read and parse package.json, returning null on failure. */
80
- async function readPackageJson(projectDir) {
81
- try {
82
- const raw = await readFile(join(projectDir, "package.json"), "utf-8");
83
- return JSON.parse(raw);
84
- }
85
- catch {
86
- return null;
87
- }
88
- }
89
- async function detectTestRunner(projectDir, pkg) {
90
- const patterns = [];
91
- const deps = (pkg?.devDependencies ?? {});
92
- const allDeps = {
93
- ...(pkg?.dependencies ?? {}),
94
- ...deps,
95
- };
96
- // Check for vitest
97
- if ("vitest" in allDeps) {
98
- patterns.push("vitest in dependencies");
99
- }
100
- if (await fileExists(join(projectDir, "vitest.config.ts"))) {
101
- patterns.push("vitest.config.ts found");
102
- }
103
- if (await fileExists(join(projectDir, "vitest.config.js"))) {
104
- patterns.push("vitest.config.js found");
105
- }
106
- // Check for jest
107
- if ("jest" in allDeps) {
108
- patterns.push("jest in dependencies");
109
- }
110
- if ("ts-jest" in allDeps) {
111
- patterns.push("ts-jest in dependencies");
112
- }
113
- if (await fileExists(join(projectDir, "jest.config.ts"))) {
114
- patterns.push("jest.config.ts found");
115
- }
116
- if (await fileExists(join(projectDir, "jest.config.js"))) {
117
- patterns.push("jest.config.js found");
118
- }
119
- // Check for testing-library
120
- for (const dep of Object.keys(allDeps)) {
121
- if (dep.startsWith("@testing-library/")) {
122
- patterns.push(`${dep} in devDeps`);
123
- break;
124
- }
125
- }
126
- // Determine runner
127
- const hasVitest = patterns.some((p) => p.includes("vitest"));
128
- const hasJest = patterns.some((p) => p.includes("jest"));
129
- let runner = "none";
130
- if (hasVitest)
131
- runner = "vitest";
132
- else if (hasJest)
133
- runner = "jest";
134
- return { runner, patterns };
135
- }
136
- async function detectAppFramework(projectDir, pkg) {
137
- const patterns = [];
138
- const deps = {
139
- ...(pkg?.dependencies ?? {}),
140
- ...(pkg?.devDependencies ?? {}),
141
- };
142
- const hasNext = "next" in deps;
143
- const hasReact = "react" in deps;
144
- const hasExpress = "express" in deps;
145
- const hasVite = "vite" in deps;
146
- if (hasNext) {
147
- patterns.push("next in dependencies");
148
- // Detect App Router vs Pages Router
149
- const hasAppDir = await dirExists(join(projectDir, "app")) ||
150
- await dirExists(join(projectDir, "src", "app"));
151
- const hasPagesDir = await dirExists(join(projectDir, "pages")) ||
152
- await dirExists(join(projectDir, "src", "pages"));
153
- if (hasAppDir) {
154
- patterns.push("app/ directory found (App Router)");
155
- return { framework: "nextjs-app", patterns };
156
- }
157
- if (hasPagesDir) {
158
- patterns.push("pages/ directory found (Pages Router)");
159
- return { framework: "nextjs-pages", patterns };
160
- }
161
- // Next.js detected but neither router pattern found — default to app
162
- return { framework: "nextjs-app", patterns };
163
- }
164
- if (hasReact && hasVite) {
165
- patterns.push("react + vite in dependencies");
166
- return { framework: "react-vite", patterns };
167
- }
168
- if (hasExpress) {
169
- patterns.push("express in dependencies");
170
- return { framework: "express", patterns };
171
- }
172
- // Check for TypeScript project
173
- if (await fileExists(join(projectDir, "tsconfig.json"))) {
174
- patterns.push("tsconfig.json found");
175
- return { framework: "plain-ts", patterns };
176
- }
177
- return { framework: "unknown", patterns };
178
- }
179
- // ---------------------------------------------------------------------------
180
- // File Discovery
181
- // ---------------------------------------------------------------------------
182
- /** Locate test directories and co-located test files. */
183
- async function discoverTestFiles(projectDir) {
184
- const testFiles = [];
185
- const allFiles = await collectFiles(projectDir);
186
- for (const f of allFiles) {
187
- if (isTestFile(f)) {
188
- testFiles.push(relative(projectDir, f));
189
- }
190
- }
191
- return testFiles;
192
- }
193
- /** Locate source files, using sourceDir as the primary search root. */
194
- async function discoverSourceFiles(projectDir, sourceDir) {
195
- const sourceFiles = [];
196
- // Scan the source directory
197
- const srcPath = join(projectDir, sourceDir);
198
- if (await dirExists(srcPath)) {
199
- const allFiles = await collectFiles(srcPath);
200
- for (const f of allFiles) {
201
- if (isSourceFile(f)) {
202
- sourceFiles.push(relative(projectDir, f));
203
- }
204
- }
205
- }
206
- // Also scan app/ and pages/ for Next.js projects
207
- for (const extra of ["app", "pages"]) {
208
- const extraPath = join(projectDir, extra);
209
- if (await dirExists(extraPath)) {
210
- const allFiles = await collectFiles(extraPath);
211
- for (const f of allFiles) {
212
- if (isSourceFile(f)) {
213
- const rel = relative(projectDir, f);
214
- if (!sourceFiles.includes(rel)) {
215
- sourceFiles.push(rel);
216
- }
217
- }
218
- }
219
- }
220
- }
221
- return sourceFiles;
222
- }
223
- // ---------------------------------------------------------------------------
224
- // Source-to-Test Mapping
225
- // ---------------------------------------------------------------------------
226
- /**
227
- * Build a mapping from source file to its corresponding test file (if any).
228
- * Tries several naming conventions:
229
- * - Co-located: src/foo/bar.ts -> src/foo/bar.test.ts
230
- * - Mirrored: src/foo/bar.ts -> tests/foo/bar.test.ts
231
- * - __tests__: src/foo/bar.ts -> src/foo/__tests__/bar.test.ts
232
- */
233
- function mapSourceToTests(sourceFiles, testFiles) {
234
- const testSet = new Set(testFiles.map((t) => t.replace(/\\/g, "/")));
235
- const mapping = new Map();
236
- for (const src of sourceFiles) {
237
- const normalized = src.replace(/\\/g, "/");
238
- const dir = dirname(normalized);
239
- const base = basename(normalized);
240
- const nameWithoutExt = base.replace(/\.(ts|tsx|js|jsx)$/, "");
241
- const ext = extname(base);
242
- const testExt = ext === ".tsx" || ext === ".jsx" ? ext : ".ts";
243
- // Candidate patterns
244
- const candidates = [
245
- // Co-located: same directory
246
- `${dir}/${nameWithoutExt}.test${testExt}`,
247
- `${dir}/${nameWithoutExt}.spec${testExt}`,
248
- // __tests__ subdirectory
249
- `${dir}/__tests__/${nameWithoutExt}.test${testExt}`,
250
- `${dir}/__tests__/${nameWithoutExt}.spec${testExt}`,
251
- ];
252
- // Mirrored directory: replace leading source dir with common test dirs
253
- const srcPrefixes = ["src/", "lib/", "app/", "pages/"];
254
- const testPrefixes = ["tests/", "test/", "__tests__/"];
255
- for (const sp of srcPrefixes) {
256
- if (normalized.startsWith(sp)) {
257
- const rest = normalized.slice(sp.length);
258
- const restDir = dirname(rest);
259
- const restBase = basename(rest).replace(/\.(ts|tsx|js|jsx)$/, "");
260
- for (const tp of testPrefixes) {
261
- candidates.push(`${tp}${restDir}/${restBase}.test${testExt}`, `${tp}${restDir}/${restBase}.spec${testExt}`, `${tp}${restBase}.test${testExt}`, `${tp}${restBase}.spec${testExt}`);
262
- }
263
- }
264
- }
265
- let matched = null;
266
- for (const c of candidates) {
267
- // Normalize candidate (handle ./ prefix from dirname of top-level files)
268
- const clean = c.replace(/^\.\//, "");
269
- if (testSet.has(clean)) {
270
- matched = clean;
271
- break;
272
- }
273
- }
274
- mapping.set(normalized, matched);
275
- }
276
- return mapping;
277
- }
278
- function categorizeFile(filePath) {
279
- const normalized = filePath.replace(/\\/g, "/");
280
- const parts = normalized.split("/");
281
- const base = basename(normalized);
282
- const ext = extname(normalized);
283
- // API routes
284
- if (parts.includes("api") ||
285
- parts.includes("routes") ||
286
- normalized.includes("app/api/") ||
287
- normalized.includes("pages/api/")) {
288
- return "api-routes";
289
- }
290
- // Middleware
291
- if (base.startsWith("middleware") ||
292
- parts.includes("middleware")) {
293
- return "middleware";
294
- }
295
- // Models / schemas / entities
296
- if (parts.includes("models") ||
297
- parts.includes("schemas") ||
298
- parts.includes("entities")) {
299
- return "models";
300
- }
301
- // Components: .tsx files or in components/ directory
302
- if (parts.includes("components") || ext === ".tsx") {
303
- return "components";
304
- }
305
- // Utils / lib / helpers
306
- if (parts.includes("utils") ||
307
- parts.includes("lib") ||
308
- parts.includes("helpers")) {
309
- return "utils";
310
- }
311
- return "other";
312
- }
313
- function buildCategories(sourceFiles, mapping) {
314
- const buckets = new Map();
315
- for (const src of sourceFiles) {
316
- const normalized = src.replace(/\\/g, "/");
317
- const cat = categorizeFile(normalized);
318
- if (!buckets.has(cat)) {
319
- buckets.set(cat, { sources: [], tests: [], untested: [] });
320
- }
321
- const bucket = buckets.get(cat);
322
- bucket.sources.push(normalized);
323
- const testFile = mapping.get(normalized);
324
- if (testFile) {
325
- bucket.tests.push(testFile);
326
- }
327
- else {
328
- bucket.untested.push(normalized);
329
- }
330
- }
331
- // Sort categories in a stable order
332
- const order = [
333
- "api-routes",
334
- "components",
335
- "utils",
336
- "middleware",
337
- "models",
338
- "other",
339
- ];
340
- const categories = [];
341
- for (const name of order) {
342
- const bucket = buckets.get(name);
343
- if (bucket && bucket.sources.length > 0) {
344
- categories.push({
345
- name,
346
- sourceFiles: bucket.sources.sort(),
347
- testFiles: bucket.tests.sort(),
348
- untestedFiles: bucket.untested.sort(),
349
- });
350
- }
351
- }
352
- return categories;
353
- }
354
- // ---------------------------------------------------------------------------
355
- // Main
356
- // ---------------------------------------------------------------------------
357
- export async function analyzeTestCoverage(projectDir) {
358
- const pkg = await readPackageJson(projectDir);
359
- // Detect frameworks
360
- const { runner, patterns: runnerPatterns } = await detectTestRunner(projectDir, pkg);
361
- const { framework, patterns: frameworkPatterns } = await detectAppFramework(projectDir, pkg);
362
- const detectedPatterns = [...runnerPatterns, ...frameworkPatterns];
363
- // Discover files
364
- const sourceDir = "src";
365
- const sourceFiles = await discoverSourceFiles(projectDir, sourceDir);
366
- const testFiles = await discoverTestFiles(projectDir);
367
- // Build mapping
368
- const mapping = mapSourceToTests(sourceFiles, testFiles);
369
- // Compute coverage
370
- const untestedFiles = [];
371
- for (const [src, test] of mapping) {
372
- if (!test) {
373
- untestedFiles.push(src);
374
- }
375
- }
376
- const ratio = sourceFiles.length > 0 ? testFiles.length / sourceFiles.length : 0;
377
- // Build categories
378
- const categories = buildCategories(sourceFiles, mapping);
379
- return {
380
- framework: {
381
- testRunner: runner,
382
- appFramework: framework,
383
- detectedPatterns,
384
- },
385
- coverage: {
386
- sourceFiles: sourceFiles.length,
387
- testFiles: testFiles.length,
388
- ratio: Math.round(ratio * 100) / 100,
389
- untestedFiles: untestedFiles.sort(),
390
- },
391
- categories,
392
- };
393
- }
394
- //# sourceMappingURL=test-analysis.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-analysis.js","sourceRoot":"","sources":["../../src/gates/test-analysis.ts"],"names":[],"mappings":"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"}
@@ -1,24 +0,0 @@
1
- import type { Page } from "playwright";
2
- import type { ViewportConfig, VisualCaptureResult } from "../types.js";
3
- /** Default viewports for multi-viewport capture: desktop, tablet, mobile */
4
- export declare const DEFAULT_VIEWPORTS: ViewportConfig[];
5
- /** Options for the visual capture function */
6
- export interface CaptureOptions {
7
- pagePath: string;
8
- screenshotDir: string;
9
- viewports?: ViewportConfig[];
10
- }
11
- /**
12
- * Capture multi-viewport screenshots and extract DOM structure from a Playwright page.
13
- *
14
- * For each viewport in the configuration:
15
- * 1. Resizes the viewport via page.setViewportSize()
16
- * 2. Waits for layout to settle (500ms)
17
- * 3. Takes a full-page screenshot saved as {safeName}_{viewportName}.png
18
- * 4. Extracts the serialized DOM tree via page.evaluate()
19
- *
20
- * @param page - Playwright Page instance (already navigated to the target URL)
21
- * @param options - Capture configuration including page path, screenshot dir, and optional viewports
22
- * @returns VisualCaptureResult with screenshots array, DOM snapshots per viewport, and metadata
23
- */
24
- export declare function captureVisual(page: Page, options: CaptureOptions): Promise<VisualCaptureResult>;
@@ -1,144 +0,0 @@
1
- import { mkdirSync } from "node:fs";
2
- import { join } from "node:path";
3
- /** Default viewports for multi-viewport capture: desktop, tablet, mobile */
4
- export const DEFAULT_VIEWPORTS = [
5
- { name: "desktop", width: 1280, height: 800 },
6
- { name: "tablet", width: 768, height: 1024 },
7
- { name: "mobile", width: 390, height: 844 },
8
- ];
9
- /**
10
- * Sanitize a page path into a safe filename component.
11
- * Replaces slashes with underscores and strips leading underscores.
12
- * Falls back to "index" for root path.
13
- */
14
- function sanitizePageName(pagePath) {
15
- const sanitized = pagePath.replace(/\//g, "_").replace(/^_/, "");
16
- return sanitized || "index";
17
- }
18
- /**
19
- * Extract DOM snapshot from the page via page.evaluate().
20
- * The entire extraction logic runs inside the browser context so it must be
21
- * self-contained -- no references to Node.js modules or TypeScript types.
22
- */
23
- async function extractDOM(page) {
24
- return await page.evaluate(() => {
25
- function walkElement(el, isTopLevel) {
26
- const style = window.getComputedStyle(el);
27
- const visible = style.display !== "none" &&
28
- style.visibility !== "hidden" &&
29
- style.opacity !== "0";
30
- const node = {
31
- tag: el.tagName.toLowerCase(),
32
- visible,
33
- children: [],
34
- };
35
- if (el.id) {
36
- node.id = el.id;
37
- }
38
- if (el.className &&
39
- typeof el.className === "string" &&
40
- el.className.trim()) {
41
- node.className = el.className.trim();
42
- }
43
- // Only capture bounding rect for top-level elements to limit payload size
44
- if (isTopLevel) {
45
- const rect = el.getBoundingClientRect();
46
- node.rect = {
47
- x: Math.round(rect.x),
48
- y: Math.round(rect.y),
49
- width: Math.round(rect.width),
50
- height: Math.round(rect.height),
51
- };
52
- }
53
- const childElements = el.children;
54
- for (let i = 0; i < childElements.length; i++) {
55
- node.children.push(walkElement(childElements[i], false));
56
- }
57
- return node;
58
- }
59
- const body = document.body;
60
- if (!body) {
61
- return { tag: "body", visible: true, children: [] };
62
- }
63
- const snapshot = {
64
- tag: "body",
65
- visible: true,
66
- children: [],
67
- };
68
- if (body.id) {
69
- snapshot.id = body.id;
70
- }
71
- if (body.className &&
72
- typeof body.className === "string" &&
73
- body.className.trim()) {
74
- snapshot.className = body.className.trim();
75
- }
76
- const childElements = body.children;
77
- for (let i = 0; i < childElements.length; i++) {
78
- snapshot.children.push(walkElement(childElements[i], true));
79
- }
80
- return snapshot;
81
- });
82
- }
83
- /**
84
- * Capture multi-viewport screenshots and extract DOM structure from a Playwright page.
85
- *
86
- * For each viewport in the configuration:
87
- * 1. Resizes the viewport via page.setViewportSize()
88
- * 2. Waits for layout to settle (500ms)
89
- * 3. Takes a full-page screenshot saved as {safeName}_{viewportName}.png
90
- * 4. Extracts the serialized DOM tree via page.evaluate()
91
- *
92
- * @param page - Playwright Page instance (already navigated to the target URL)
93
- * @param options - Capture configuration including page path, screenshot dir, and optional viewports
94
- * @returns VisualCaptureResult with screenshots array, DOM snapshots per viewport, and metadata
95
- */
96
- export async function captureVisual(page, options) {
97
- const start = Date.now();
98
- const viewports = options.viewports ?? DEFAULT_VIEWPORTS;
99
- const safeName = sanitizePageName(options.pagePath);
100
- mkdirSync(options.screenshotDir, { recursive: true });
101
- const screenshots = [];
102
- const domSnapshots = {};
103
- for (const viewport of viewports) {
104
- try {
105
- // Resize viewport
106
- await page.setViewportSize({
107
- width: viewport.width,
108
- height: viewport.height,
109
- });
110
- // Wait for layout to settle after resize
111
- await page.waitForTimeout(500);
112
- // Take full-page screenshot
113
- const screenshotPath = join(options.screenshotDir, `${safeName}_${viewport.name}.png`);
114
- try {
115
- await page.screenshot({ path: screenshotPath, fullPage: true });
116
- screenshots.push({
117
- page: options.pagePath,
118
- viewport: viewport.name,
119
- path: screenshotPath,
120
- });
121
- }
122
- catch {
123
- // Screenshot failed for this viewport — skip it but continue
124
- }
125
- // Extract DOM snapshot
126
- const domSnapshot = await extractDOM(page);
127
- domSnapshots[viewport.name] = domSnapshot;
128
- }
129
- catch {
130
- // Viewport resize or other operation failed — skip this viewport entirely
131
- }
132
- }
133
- return {
134
- screenshots,
135
- domSnapshots,
136
- metadata: {
137
- viewports,
138
- pagePath: options.pagePath,
139
- capturedAt: new Date().toISOString(),
140
- durationMs: Date.now() - start,
141
- },
142
- };
143
- }
144
- //# sourceMappingURL=visual-capture.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"visual-capture.js","sourceRoot":"","sources":["../../src/gates/visual-capture.ts"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- import type { VisualResult } from "../types.js";
2
- /**
3
- * Capture and store "before" snapshots for the given pages.
4
- * Snapshots are persisted to disk (.forge/screenshots/before/*.snapshot.json)
5
- * so they survive across separate CLI invocations.
6
- */
7
- export declare function captureBeforeSnapshots(projectDir: string, pages: string[], options?: {
8
- devServerCommand?: string;
9
- devServerPort?: number;
10
- screenshotDir?: string;
11
- }): Promise<void>;
12
- /** Clear all stored "before" snapshots from disk (e.g. between milestones). */
13
- export declare function clearBeforeSnapshots(projectDir: string): void;
14
- export declare function verifyVisual(projectDir: string, pages: string[], options?: {
15
- devServerCommand?: string;
16
- devServerPort?: number;
17
- screenshotDir?: string;
18
- }): Promise<VisualResult>;