@momentiq/dark-factory-cli 3.0.2 → 3.1.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 (52) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +3 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/mode.d.ts.map +1 -1
  5. package/dist/commands/mode.js +120 -22
  6. package/dist/commands/mode.js.map +1 -1
  7. package/dist/commands/skills.d.ts.map +1 -1
  8. package/dist/commands/skills.js +11 -1
  9. package/dist/commands/skills.js.map +1 -1
  10. package/dist/commands/verify.d.ts.map +1 -1
  11. package/dist/commands/verify.js +113 -8
  12. package/dist/commands/verify.js.map +1 -1
  13. package/dist/mcp/tools/skills-install.d.ts.map +1 -1
  14. package/dist/mcp/tools/skills-install.js +8 -3
  15. package/dist/mcp/tools/skills-install.js.map +1 -1
  16. package/dist/mode/critic-registration.d.ts +30 -10
  17. package/dist/mode/critic-registration.d.ts.map +1 -1
  18. package/dist/mode/critic-registration.js +31 -10
  19. package/dist/mode/critic-registration.js.map +1 -1
  20. package/dist/mode/guard.d.ts.map +1 -1
  21. package/dist/mode/guard.js +30 -2
  22. package/dist/mode/guard.js.map +1 -1
  23. package/dist/mode/init.d.ts +8 -4
  24. package/dist/mode/init.d.ts.map +1 -1
  25. package/dist/mode/init.js +148 -12
  26. package/dist/mode/init.js.map +1 -1
  27. package/dist/mode/preview-capture.d.ts +3 -0
  28. package/dist/mode/preview-capture.d.ts.map +1 -0
  29. package/dist/mode/preview-capture.js +137 -0
  30. package/dist/mode/preview-capture.js.map +1 -0
  31. package/dist/mode/preview.d.ts +227 -0
  32. package/dist/mode/preview.d.ts.map +1 -0
  33. package/dist/mode/preview.js +802 -0
  34. package/dist/mode/preview.js.map +1 -0
  35. package/dist/onboard/seeders/design-md.d.ts.map +1 -1
  36. package/dist/onboard/seeders/design-md.js +512 -17
  37. package/dist/onboard/seeders/design-md.js.map +1 -1
  38. package/dist/skills/install.d.ts +25 -5
  39. package/dist/skills/install.d.ts.map +1 -1
  40. package/dist/skills/install.js +34 -17
  41. package/dist/skills/install.js.map +1 -1
  42. package/dist/skills/known-skills.d.ts +2 -0
  43. package/dist/skills/known-skills.d.ts.map +1 -0
  44. package/dist/skills/known-skills.js +25 -0
  45. package/dist/skills/known-skills.js.map +1 -0
  46. package/package.json +2 -2
  47. package/skills/designer-build/SKILL.md.tmpl +14 -0
  48. package/skills/designer-handoff/SKILL.md.tmpl +28 -1
  49. package/skills/verify/producer/README.md +29 -4
  50. package/skills/verify/producer/playwright-route.sh +10 -0
  51. package/skills/verify/producer/surface-declaration.ts +373 -0
  52. package/skills/verify/producer/ui-route.producer.spec.ts +44 -11
package/dist/mode/init.js CHANGED
@@ -4,8 +4,10 @@
4
4
  // Design constraints:
5
5
  // - APPEND, never re-serialize the consumer's file: hand-maintained comments
6
6
  // and formatting survive. The appended block is generated YAML.
7
- // - Deterministic scope proposal: only directories that actually exist are
8
- // proposed (the engineer reviews the init PR — this is a seed, not policy).
7
+ // - Deterministic scope proposal: directories that actually exist are proposed
8
+ // (the engineer reviews the init PR — this is a seed, not policy), plus two
9
+ // always-on seeds independent of layout — `**/*.css` (a minimal editable
10
+ // surface) and `.darkfactory/**` (the mode's own workflow artifacts).
9
11
  // - Idempotent: an existing `modes.<name>` entry short-circuits to "exists".
10
12
  // - Fail closed: the candidate file content must round-trip through the
11
13
  // canonical parser (@momentiq/dark-factory-schemas) before it is written.
@@ -23,6 +25,14 @@ const DEFAULT_PROTECTED_PATHS = [
23
25
  "package.json",
24
26
  "package-lock.json",
25
27
  ];
28
+ // Non-monorepo frontend roots (Next/Vite/CRA/Remix): the app lives in a named
29
+ // top-level dir rather than at the repo root or under `apps/*`. Each root is
30
+ // probed for the same conventional subdirs, mirrored one level deep — so a
31
+ // designer on a `web/`-rooted repo gets real component scopes, not css-only (#354).
32
+ // Exported so `df mode preview` resolves the SAME frontend workspace this init
33
+ // step detects, instead of assuming the repo root is the frontend (#377/#379).
34
+ export const FRONTEND_ROOT_DIRS = ["web", "frontend", "client"];
35
+ const FRONTEND_ROOT_SUBDIRS = ["components", "app", "pages", "src", "lib", "styles"];
26
36
  const ROOT_SCOPE_DIR_CANDIDATES = [
27
37
  "src/components",
28
38
  "src/app",
@@ -33,6 +43,7 @@ const ROOT_SCOPE_DIR_CANDIDATES = [
33
43
  "pages",
34
44
  "styles",
35
45
  "public",
46
+ ...FRONTEND_ROOT_DIRS.flatMap((root) => FRONTEND_ROOT_SUBDIRS.map((sub) => `${root}/${sub}`)),
36
47
  ];
37
48
  const APP_SCOPE_SUBDIR_CANDIDATES = ["src/components", "src/app", "src/pages", "public"];
38
49
  function isDir(path) {
@@ -44,10 +55,13 @@ function isDir(path) {
44
55
  }
45
56
  }
46
57
  /**
47
- * Propose write scopes from directories that exist. Monorepo `apps/<name>`
48
- * workspaces are scanned one level deep. Styling files are always in scope —
49
- * a designer mode with no reachable surface still gets `**\/*.css` so the
50
- * engineer sees an editable (if minimal) seed to correct in the init PR.
58
+ * Propose write scopes from directories that exist. Root-level frontend roots
59
+ * (`web/`, `frontend/`, `client/`) and the Next `src/` conventions are probed,
60
+ * plus monorepo `apps/<name>` workspaces one level deep. Two always-on seeds
61
+ * are appended regardless of layout: `**\/*.css` (a designer with no reachable
62
+ * component surface still gets a minimal editable seed to correct in the init
63
+ * PR) and `.darkfactory/**` (the mode's own workflow — `designer-brief` and
64
+ * `df objectives derive --apply` — writes there, so its outputs stay in scope).
51
65
  */
52
66
  export function detectWriteScopes(repoRoot) {
53
67
  const scopes = [];
@@ -55,6 +69,17 @@ export function detectWriteScopes(repoRoot) {
55
69
  if (isDir(join(repoRoot, candidate)))
56
70
  scopes.push(`${candidate}/**`);
57
71
  }
72
+ // Bare top-level `src/` fallback (#354): repos that keep the whole frontend
73
+ // under a single `src/` (no Next `src/<area>` split) match none of the
74
+ // `src/<subdir>` candidates above and would otherwise fall through to
75
+ // css-only. Propose the broad `src/**` only when `src/` exists AND no
76
+ // more-specific `src/<subdir>` scope already matched, so the seed never lists
77
+ // `src/**` beside a scope it already contains. (The web/frontend/client roots
78
+ // need no such guard — their subdirs are siblings, not nested under a broader
79
+ // candidate.)
80
+ if (isDir(join(repoRoot, "src")) && !scopes.some((s) => s.startsWith("src/"))) {
81
+ scopes.push("src/**");
82
+ }
58
83
  const appsRoot = join(repoRoot, "apps");
59
84
  if (isDir(appsRoot)) {
60
85
  for (const entry of readdirSync(appsRoot).sort()) {
@@ -65,24 +90,135 @@ export function detectWriteScopes(repoRoot) {
65
90
  }
66
91
  }
67
92
  }
68
- scopes.push("**/*.css");
93
+ // Always-on seeds, independent of repo layout: `**\/*.css` (a designer with no
94
+ // reachable component surface still gets a minimal editable seed) and
95
+ // `.darkfactory/**` — the mode's OWN workflow writes there (`designer-brief`
96
+ // → .darkfactory/briefs/…, `df objectives derive --apply` →
97
+ // .darkfactory/objectives.yaml), so seeding it keeps those outputs in scope
98
+ // and the mode doesn't fail its own `mode-scope-critic` gate (#361).
99
+ scopes.push("**/*.css", ".darkfactory/**");
69
100
  return scopes;
70
101
  }
71
- function detectDevServer(repoRoot) {
102
+ // Best-effort default preview URL. The seed is reviewed in the init PR; the
103
+ // engineer corrects the port if the detected server binds elsewhere.
104
+ const DEFAULT_DEV_URL = "http://localhost:3000";
105
+ // GNU make reads the first of these that exists (GNUmakefile → makefile →
106
+ // Makefile); we mirror that precedence.
107
+ const MAKEFILE_NAMES = ["GNUmakefile", "makefile", "Makefile"];
108
+ // foreman/honcho read `Procfile.dev` for development when present, else `Procfile`.
109
+ const PROCFILE_NAMES = ["Procfile.dev", "Procfile"];
110
+ // Docker Compose v2 file precedence — the highest-precedence file that exists
111
+ // is authoritative; the rest are ignored by the tool, so we don't read them.
112
+ const COMPOSE_FILE_NAMES = [
113
+ "compose.yaml",
114
+ "compose.yml",
115
+ "docker-compose.yaml",
116
+ "docker-compose.yml",
117
+ ];
118
+ // Service names that plausibly ARE the dev server, in priority order.
119
+ const COMPOSE_DEV_SERVICE_NAMES = ["dev", "web", "app", "frontend", "client"];
120
+ function detectPackageDevServer(repoRoot) {
72
121
  const pkgPath = join(repoRoot, "package.json");
73
122
  if (!existsSync(pkgPath))
74
123
  return undefined;
75
124
  try {
76
125
  const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
77
- if (pkg.scripts?.["dev"]) {
78
- return { command: "npm run dev", url: "http://localhost:3000" };
79
- }
126
+ if (pkg.scripts?.["dev"])
127
+ return { command: "npm run dev", url: DEFAULT_DEV_URL };
80
128
  }
81
129
  catch {
82
- // Malformed package.json → no dev-server proposal; init still succeeds.
130
+ // Malformed package.json → no proposal from this source; init still succeeds.
131
+ }
132
+ return undefined;
133
+ }
134
+ function detectMakefileDevServer(repoRoot) {
135
+ for (const name of MAKEFILE_NAMES) {
136
+ const filePath = join(repoRoot, name);
137
+ if (!existsSync(filePath))
138
+ continue;
139
+ let content;
140
+ try {
141
+ content = readFileSync(filePath, "utf8");
142
+ }
143
+ catch {
144
+ continue;
145
+ }
146
+ for (const line of content.split("\n")) {
147
+ // A `dev` target is defined at column 0 as `dev:` / `dev: prereqs` /
148
+ // `dev::` (double-colon rule). Inspect the TARGET's own colon only: a
149
+ // `dev :=` / `dev ::=` / `dev :::=` variable assignment has `=`
150
+ // immediately after the colon run, while a real target does not. Keying
151
+ // on the target colon (not a `:=` substring anywhere on the line) keeps a
152
+ // valid target with a target-specific variable (`dev: FOO := bar`)
153
+ // correctly detected.
154
+ if (/^dev[ \t]*:{1,2}(?![:=])/.test(line)) {
155
+ return { command: "make dev", url: DEFAULT_DEV_URL };
156
+ }
157
+ }
158
+ }
159
+ return undefined;
160
+ }
161
+ function detectProcfileDevServer(repoRoot) {
162
+ for (const name of PROCFILE_NAMES) {
163
+ const filePath = join(repoRoot, name);
164
+ if (!existsSync(filePath))
165
+ continue;
166
+ let content;
167
+ try {
168
+ content = readFileSync(filePath, "utf8");
169
+ }
170
+ catch {
171
+ continue;
172
+ }
173
+ // Procfile lines are `<process>: <command>`; the `web` process is the HTTP
174
+ // server a designer previews. Propose its command verbatim.
175
+ const match = content.match(/^web:\s*(.+)$/m);
176
+ const command = (match?.[1] ?? "").trim();
177
+ if (command)
178
+ return { command, url: DEFAULT_DEV_URL };
179
+ }
180
+ return undefined;
181
+ }
182
+ function detectComposeDevServer(repoRoot) {
183
+ for (const name of COMPOSE_FILE_NAMES) {
184
+ const filePath = join(repoRoot, name);
185
+ if (!existsSync(filePath))
186
+ continue;
187
+ // The highest-precedence compose file that exists is authoritative; Compose
188
+ // ignores the lower-precedence files, so we don't fall through to them.
189
+ try {
190
+ const doc = parseYaml(readFileSync(filePath, "utf8"));
191
+ const services = doc?.services;
192
+ if (services && typeof services === "object") {
193
+ for (const svc of COMPOSE_DEV_SERVICE_NAMES) {
194
+ if (Object.prototype.hasOwnProperty.call(services, svc)) {
195
+ return { command: `docker compose up ${svc}`, url: DEFAULT_DEV_URL };
196
+ }
197
+ }
198
+ }
199
+ }
200
+ catch {
201
+ // Malformed compose file → no proposal; init still succeeds.
202
+ }
203
+ return undefined;
83
204
  }
84
205
  return undefined;
85
206
  }
207
+ /**
208
+ * Propose a dev-server command for the mode's mandatory visual loop. Priority:
209
+ * an explicit npm `dev` script first, then the container-first / make / Procfile
210
+ * layouts that repos without a `scripts.dev` use — so a designer on a
211
+ * make-driven or compose-driven repo gets a real preview command instead of
212
+ * nothing (#357; the component-isolation preview harness is a separate PR).
213
+ * Only a source whose file/target actually exists yields a proposal; undefined
214
+ * when none match.
215
+ */
216
+ function detectDevServer(repoRoot) {
217
+ return (detectPackageDevServer(repoRoot) ??
218
+ detectMakefileDevServer(repoRoot) ??
219
+ detectProcfileDevServer(repoRoot) ??
220
+ detectComposeDevServer(repoRoot));
221
+ }
86
222
  export function buildDefaultModeEntry(repoRoot, modeName) {
87
223
  const writeScopes = detectWriteScopes(repoRoot);
88
224
  const devServer = detectDevServer(repoRoot);
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/mode/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/mode/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type CaptureDeps } from "./preview.js";
2
+ export declare const defaultCaptureDeps: CaptureDeps;
3
+ //# sourceMappingURL=preview-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-capture.d.ts","sourceRoot":"","sources":["../../src/mode/preview-capture.ts"],"names":[],"mappings":"AAmBA,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AA2BzE,eAAO,MAAM,kBAAkB,EAAE,WAoEhC,CAAC"}
@@ -0,0 +1,137 @@
1
+ // Default `CaptureDeps` for `df mode preview` — the real Vite-server + Playwright
2
+ // wiring. Kept in its own file (never imported by tests, which inject fakes) so
3
+ // the pure harness/detection core in `preview.ts` stays browser- and
4
+ // bundler-free.
5
+ //
6
+ // RESOLUTION CONTEXT (load-bearing). Vite and Playwright are NOT dependencies of
7
+ // this CLI — like the `ui-visual` route, they are resolved from the CONSUMER's
8
+ // repo. A bare `import("vite")` would resolve against the CLI's own node_modules
9
+ // (wrong copy, or absent). So we resolve every consumer module against the
10
+ // resolved FRONTEND WORKSPACE (`workspaceDir` — often a `web/` subdir, where the
11
+ // frontend's node_modules actually live, NOT necessarily the repo root) and
12
+ // dynamic-import the resolved path. When a module or the browser is missing, we
13
+ // THROW — `runPreview` catches it and degrades with an actionable message (never
14
+ // a crash, never fabricated evidence).
15
+ import { createRequire } from "node:module";
16
+ import { join } from "node:path";
17
+ import { pathToFileURL } from "node:url";
18
+ import { BrowserUnavailableError } from "./preview.js";
19
+ /** Dynamic-import a module resolved from `baseDir` (the frontend workspace), NOT
20
+ * the CLI's own node_modules. Throws (with the module name) when not installed. */
21
+ async function importFrom(mod, baseDir) {
22
+ // The anchor file need not exist — node uses its dirname as the resolution base.
23
+ const req = createRequire(join(baseDir, "package.json"));
24
+ let resolved;
25
+ try {
26
+ resolved = req.resolve(mod);
27
+ }
28
+ catch {
29
+ throw new Error(`cannot resolve "${mod}" from ${baseDir} — is it installed here?`);
30
+ }
31
+ return (await import(pathToFileURL(resolved).href));
32
+ }
33
+ /** CJS/ESM interop: a CJS module imported via dynamic `import()` exposes its
34
+ * `module.exports` under `.default`; a real ESM module exposes named exports
35
+ * directly. Vite's and Playwright's resolved (CJS) builds land on `.default`,
36
+ * so read the member from whichever object actually has it. */
37
+ function member(mod, name) {
38
+ const direct = mod[name];
39
+ if (direct !== undefined)
40
+ return direct;
41
+ const def = mod["default"];
42
+ return def?.[name];
43
+ }
44
+ export const defaultCaptureDeps = {
45
+ async startServer({ workspaceDir, harnessDir, port, alias }) {
46
+ // Vite transforms the component's TSX/JSX (+ CSS, path aliases) on the fly —
47
+ // the "detected framework's isolated render" the harness relies on. Resolve
48
+ // vite + the react plugin from the frontend workspace (they live in its
49
+ // node_modules — `web/node_modules`, not necessarily the repo root's).
50
+ const viteMod = await importFrom("vite", workspaceDir);
51
+ const createServer = member(viteMod, "createServer");
52
+ if (typeof createServer !== "function") {
53
+ throw new Error("resolved `vite` but it exposes no createServer() — unexpected build shape");
54
+ }
55
+ const reactPluginMod = await importFrom("@vitejs/plugin-react", workspaceDir);
56
+ const reactPlugin = (typeof reactPluginMod["default"] === "function" ? reactPluginMod["default"] : reactPluginMod);
57
+ // root = harnessDir (inside workspaceDir), so its index.html is served at "/",
58
+ // bare `react` imports resolve up into the workspace's node_modules, and
59
+ // `fs.allow` lets the entry import the component under the workspace. The
60
+ // injected `resolve.alias` (from the workspace tsconfig `paths`) is what makes
61
+ // real components' `@/…` imports resolve (#377) — omit the key entirely when
62
+ // empty so Vite's defaults are untouched.
63
+ const server = await createServer({
64
+ root: harnessDir,
65
+ configFile: false,
66
+ logLevel: "silent",
67
+ plugins: [reactPlugin()],
68
+ ...(alias.length > 0 ? { resolve: { alias } } : {}),
69
+ server: {
70
+ port,
71
+ strictPort: false,
72
+ host: "127.0.0.1",
73
+ fs: { allow: [workspaceDir, harnessDir] },
74
+ },
75
+ });
76
+ await server.listen();
77
+ const url = server.resolvedUrls?.local?.[0] ?? `http://127.0.0.1:${port}/`;
78
+ return {
79
+ url,
80
+ close: async () => {
81
+ await server.close();
82
+ },
83
+ };
84
+ },
85
+ async capture({ url, workspaceDir }) {
86
+ // Resolve Playwright from the SAME frontend workspace as the server — accept
87
+ // either `playwright` or `@playwright/test` (the ui-visual route uses the
88
+ // latter). Resolution + launch failures are a genuinely-unavailable browser →
89
+ // BrowserUnavailableError (soft-degrade). Anything AFTER launch (navigation,
90
+ // the render, the screenshot) is a REAL failure and propagates as a plain
91
+ // Error so runPreview surfaces it loudly.
92
+ const browser = await launchBrowser(workspaceDir);
93
+ try {
94
+ const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
95
+ await page.goto(url, { waitUntil: "networkidle", timeout: 30_000 });
96
+ // Structural render floor — the harness wraps the component in <main>.
97
+ await page.locator("main").first().waitFor({ state: "visible", timeout: 15_000 });
98
+ const aria = await page.locator("body").ariaSnapshot();
99
+ const png = await page.screenshot({ fullPage: true });
100
+ return { aria, png };
101
+ }
102
+ finally {
103
+ await browser.close();
104
+ }
105
+ },
106
+ };
107
+ /** Resolve + launch Chromium from the consumer repo. Every failure here is a
108
+ * browser-unavailable condition (not installed / no binary / missing system
109
+ * deps), so normalize it to `BrowserUnavailableError` — the ONLY capture failure
110
+ * runPreview soft-degrades. */
111
+ async function launchBrowser(baseDir) {
112
+ let pwMod;
113
+ try {
114
+ pwMod = await importFrom("playwright", baseDir);
115
+ }
116
+ catch {
117
+ try {
118
+ pwMod = await importFrom("@playwright/test", baseDir);
119
+ }
120
+ catch (err) {
121
+ throw new BrowserUnavailableError(`Playwright is not installed in ${baseDir} (${err instanceof Error ? err.message : String(err)}). ` +
122
+ `Install with \`npm i -D playwright\`.`);
123
+ }
124
+ }
125
+ const chromium = member(pwMod, "chromium");
126
+ if (!chromium || typeof chromium.launch !== "function") {
127
+ throw new BrowserUnavailableError("resolved Playwright but it exposes no chromium.launch() — unexpected shape");
128
+ }
129
+ try {
130
+ return await chromium.launch();
131
+ }
132
+ catch (err) {
133
+ // A launch failure is a missing/unusable browser binary or system deps.
134
+ throw new BrowserUnavailableError(err instanceof Error ? err.message : String(err));
135
+ }
136
+ }
137
+ //# sourceMappingURL=preview-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-capture.js","sourceRoot":"","sources":["../../src/mode/preview-capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,227 @@
1
+ export interface FrontendWorkspace {
2
+ /** Absolute dir whose package.json declares react — the module/config base
3
+ * (deps read, vite/plugin-react resolution, harness dir, fs.allow, aliases). */
4
+ workspaceDir: string;
5
+ /** Label relative to the invocation cwd, for the operator note ("web" or "."). */
6
+ relLabel: string;
7
+ }
8
+ /**
9
+ * Resolve the frontend workspace for a repo rooted at `cwd`. Mirrors
10
+ * `df mode init`'s detection (same FRONTEND_ROOT_DIRS): the first of
11
+ * `web/`,`frontend/`,`client/` whose package.json declares react wins; else the
12
+ * repo root itself when ITS package.json declares react. Returns `null` when no
13
+ * react is found anywhere — the caller degrades with the existing no-react
14
+ * blocker (which keeps the honest "install react" message + exit code). PURE.
15
+ */
16
+ export declare function resolveFrontendWorkspace(cwd: string): FrontendWorkspace | null;
17
+ /** A Vite/rollup alias entry. The regex `find` form maps a `/*` glob prefix
18
+ * correctly (e.g. `{ find: /^@\//, replacement: "<ws>/src/" }`). */
19
+ export interface AliasEntry {
20
+ find: string | RegExp;
21
+ replacement: string;
22
+ }
23
+ /**
24
+ * Strip line (`//`) and block comments from JSONC, STRING-AWARE: a naive
25
+ * stripper corrupts a value like `"./src/*"` (which contains a literal
26
+ * slash-star) by treating it as the start of a block comment. Tracks string
27
+ * state (and escapes) so only real comments are removed. PURE.
28
+ */
29
+ export declare function stripJsonComments(text: string): string;
30
+ /** Tolerant JSONC parse: strip comments (string-aware) + trailing commas, then
31
+ * JSON.parse. Returns `null` on any failure (caller proceeds with no alias). */
32
+ export declare function parseJsonc(text: string): unknown;
33
+ /**
34
+ * Convert tsconfig `compilerOptions.paths` (+ `baseUrl`) into Vite alias entries.
35
+ * `paths` targets resolve relative to `baseUrl` (default `.` = tsconfigDir).
36
+ * Only the FIRST target is used (Vite alias has no fallback array). PURE.
37
+ *
38
+ * A single `classifyGlob` is applied to BOTH the key and the target, and an entry
39
+ * is emitted ONLY when the two AGREE — so mis-shapen mappings can't leak through
40
+ * on either side:
41
+ * - both `exact` → exact alias (`^<key>$` → resolved target).
42
+ * - both `prefix` → prefix alias (`^<keyPrefix>/` → `<resolvedTargetPrefix>/`).
43
+ * The find RE-ADDS the boundary `/` so it anchors on a path separator: `"@/*"`
44
+ * → `^@/`, which never matches `@scope/pkg` (a bare `^@` WOULD shadow every
45
+ * scoped npm package — the bug this guards).
46
+ * - ANY other combination — either side `unsupported`, or a KIND MISMATCH like a
47
+ * `prefix` key with an `exact` target (`"@/*": ["./src/index.ts"]`, invalid
48
+ * TS) — is SKIPPED: the key is returned in `unsupported`, no alias, no throw.
49
+ *
50
+ * The common shadcn/Next shapes (`"@/*": ["./src/*"]`, `["./*"]`, exact keys) are
51
+ * unaffected; monorepo mid-glob mappings (a `@pkg` key mapped to a
52
+ * `packages`-style target with an inner wildcard) skip.
53
+ */
54
+ export declare function tsconfigPathsToAlias(input: {
55
+ paths?: Record<string, string[]> | undefined;
56
+ baseUrl?: string | undefined;
57
+ tsconfigDir: string;
58
+ }): {
59
+ alias: AliasEntry[];
60
+ unsupported: string[];
61
+ };
62
+ /** One file the harness writes into its temp dir. */
63
+ export interface HarnessFile {
64
+ /** Path relative to the harness dir (e.g. "index.html", ENTRY_BASENAME). */
65
+ path: string;
66
+ contents: string;
67
+ }
68
+ export declare const ENTRY_BASENAME = "df-preview-entry.tsx";
69
+ export declare const INDEX_HTML_BASENAME = "index.html";
70
+ export interface GenerateHarnessInput {
71
+ /** Absolute path to the component file being previewed. */
72
+ componentAbsPath: string;
73
+ /** Absolute path to the (temp) harness dir the files are written into. The
74
+ * entry imports the component by a path relative to here. */
75
+ harnessDir: string;
76
+ /** Human component name (from the filename) — used in the title + wrapper. */
77
+ componentName: string;
78
+ /** Named export to mount. When omitted the harness imports the DEFAULT export. */
79
+ exportName?: string;
80
+ /** React major (18/19 → `createRoot`; <18 → `ReactDOM.render`). */
81
+ reactMajor: number;
82
+ }
83
+ /**
84
+ * Generate the minimal isolated-render harness for a React component: an entry
85
+ * that mounts JUST that component (placeholder/default props) inside a `<main>`
86
+ * landmark, plus an `index.html`. The `<main>` wrapper guarantees the same
87
+ * structural render floor the `ui-visual` producer asserts (`getByRole("main")`),
88
+ * regardless of what the component itself renders. PURE — returns file contents;
89
+ * the caller writes them.
90
+ */
91
+ export declare function generateHarness(input: GenerateHarnessInput): HarnessFile[];
92
+ export type PreviewBlockerCode = "not-a-component-file" | "no-react" | "no-vite" | "server-component" | "no-export";
93
+ export interface DetectInput {
94
+ /** Repo root (consumer cwd). */
95
+ cwd: string;
96
+ /** Absolute path to the component file. */
97
+ componentAbsPath: string;
98
+ /** The component file's source. */
99
+ source: string;
100
+ /** Parsed consumer package.json (deps ∪ devDeps ∪ peerDeps merged), or null. */
101
+ packageDeps: Record<string, string> | null;
102
+ }
103
+ export interface DetectResult {
104
+ /** `vite-harness` = renderable via the generated harness; `unsupported` = a
105
+ * blocker prevents an honest render (see `blocker`). */
106
+ engine: "vite-harness" | "unsupported";
107
+ componentName: string;
108
+ reactMajor: number;
109
+ /** Resolved export to mount (undefined = default export). */
110
+ exportName?: string;
111
+ /** An isolation tool is present — reported (v1 still renders via the generated
112
+ * harness; native story capture is deferred, see the PR body). */
113
+ storybook: boolean;
114
+ ladle: boolean;
115
+ /** Non-fatal advisories surfaced to the operator. */
116
+ warnings: string[];
117
+ /** Non-null when the component genuinely cannot be rendered — `runPreview`
118
+ * degrades (exit 2) with this message rather than a wrong render. */
119
+ blocker?: {
120
+ code: PreviewBlockerCode;
121
+ message: string;
122
+ };
123
+ }
124
+ /** Best-effort PascalCase component name from a filename (`user-card.tsx` →
125
+ * `UserCard`, `Button.tsx` → `Button`). */
126
+ export declare function componentNameFromPath(componentAbsPath: string): string;
127
+ /**
128
+ * Resolve which export the harness should mount. Preference order:
129
+ * 1. `export default` present → default import (undefined exportName).
130
+ * 2. a named export matching the PascalCase filename.
131
+ * 3. the first `export function|const <PascalCaseName>`.
132
+ * Returns `{ kind: "none" }` when no export is found (a blocker).
133
+ */
134
+ export declare function resolveExport(source: string, componentName: string): {
135
+ kind: "default";
136
+ } | {
137
+ kind: "named";
138
+ name: string;
139
+ } | {
140
+ kind: "none";
141
+ };
142
+ /**
143
+ * Decide whether the component can be rendered via the generated Vite harness,
144
+ * and gather advisories. PURE — no fs, no network.
145
+ */
146
+ export declare function detectStrategy(input: DetectInput): DetectResult;
147
+ /** Injected boundary so the Vite-server + Playwright wiring is never imported by
148
+ * tests. The default implementation lives in `preview-capture.ts`. */
149
+ export interface CaptureDeps {
150
+ /** Start an isolated dev server rooted at the harness dir; resolve to its base
151
+ * URL + a close(). `workspaceDir` is the resolved FRONTEND workspace (where
152
+ * react/vite/node_modules + the tsconfig aliases live), NOT the invocation cwd
153
+ * — vite/plugin-react resolve from it and `fs.allow` is scoped to it. `alias`
154
+ * is the tsconfig `paths` map as Vite `resolve.alias` entries (may be empty).
155
+ * Throws when the transform tool (Vite) is unavailable. */
156
+ startServer(input: {
157
+ workspaceDir: string;
158
+ harnessDir: string;
159
+ port: number;
160
+ alias: AliasEntry[];
161
+ }): Promise<{
162
+ url: string;
163
+ close: () => Promise<void>;
164
+ }>;
165
+ /** Drive a browser: navigate, wait for the `main` landmark, return the ARIA
166
+ * snapshot + a full-page PNG. `workspaceDir` is threaded so the browser is
167
+ * resolved from the SAME frontend workspace as the server (not `process.cwd()`
168
+ * and not necessarily the repo root). Throws a `BrowserUnavailableError` when
169
+ * the browser genuinely can't launch; any OTHER throw is treated as a real
170
+ * render/transform failure (surfaced loudly). */
171
+ capture(input: {
172
+ url: string;
173
+ workspaceDir: string;
174
+ }): Promise<{
175
+ aria: string;
176
+ png: Buffer;
177
+ }>;
178
+ }
179
+ /** Thrown by a `CaptureDeps.capture` when the browser cannot be resolved/launched
180
+ * (Playwright not installed, Chromium binary absent, missing system deps). This
181
+ * is the ONLY capture failure that degrades softly (exit 2, "reached the capture
182
+ * step") — a Vite transform error, a component runtime exception, missing props,
183
+ * or an `fs.allow`-blocked import is a REAL failure and surfaces loudly (exit 1). */
184
+ export declare class BrowserUnavailableError extends Error {
185
+ constructor(message: string);
186
+ }
187
+ /** Secondary heuristic (belt-and-suspenders alongside `BrowserUnavailableError`):
188
+ * recognize a genuine missing-browser / launch / install failure from its message
189
+ * so a raw Playwright error is still classified as degrade-soft, while a render or
190
+ * transform error is NOT. Kept deliberately narrow. */
191
+ export declare function isBrowserUnavailable(err: unknown): boolean;
192
+ export interface RunPreviewOptions {
193
+ /** Component path as given by the operator (relative to cwd or absolute). */
194
+ componentPath: string;
195
+ cwd: string;
196
+ /** Local port for the isolated harness server (default 5199). */
197
+ port?: number;
198
+ /** Override the evidence slug (default: sanitized component filename). */
199
+ slug?: string;
200
+ }
201
+ export type PreviewStatus = "captured" | "degraded" | "error";
202
+ export interface RunPreviewResult {
203
+ status: PreviewStatus;
204
+ /** 0 captured · 2 degraded (tool/browser/unsupported) · 1 hard usage error. */
205
+ exitCode: 0 | 1 | 2;
206
+ slug: string;
207
+ message: string;
208
+ warnings: string[];
209
+ /** Absolute evidence dir when `captured`. */
210
+ evidenceDir?: string;
211
+ }
212
+ /**
213
+ * A safe evidence slug is a SINGLE path segment: filesystem-safe chars only, and
214
+ * never `.` / `..` / anything with a separator. The slug is interpolated into the
215
+ * evidence path (`agent-reviews/quality-gates/ui/<sha>/<slug>/…`), so an operator
216
+ * `--slug ../../..` would otherwise traverse OUT of the evidence tree and clobber
217
+ * arbitrary files. The auto-derived slug is already safe (`sanitizeSlug`); this
218
+ * fail-closes an explicit `--slug`. Exported for the traversal regression test.
219
+ */
220
+ export declare function isSafeSlug(slug: string): boolean;
221
+ /**
222
+ * Render one component in isolation and write `ui-visual`-shaped evidence.
223
+ * Never throws for an expected failure — returns a `degraded`/`error` result
224
+ * with an actionable message and the right exit code.
225
+ */
226
+ export declare function runPreview(opts: RunPreviewOptions, deps: CaptureDeps): Promise<RunPreviewResult>;
227
+ //# sourceMappingURL=preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../src/mode/preview.ts"],"names":[],"mappings":"AAkDA,MAAM,WAAW,iBAAiB;IAChC;qFACiF;IACjF,YAAY,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAO9E;AAWD;qEACqE;AACrE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsDtD;AAED;iFACiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUhD;AAsCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG;IAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAqCjD;AAuFD,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,cAAc,yBAAyB,CAAC;AACrD,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,2DAA2D;IAC3D,gBAAgB,EAAE,MAAM,CAAC;IACzB;kEAC8D;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;CACpB;AASD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,WAAW,EAAE,CAmE1E;AAQD,MAAM,MAAM,kBAAkB,GAC1B,sBAAsB,GACtB,UAAU,GACV,SAAS,GACT,kBAAkB,GAClB,WAAW,CAAC;AAEhB,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,gBAAgB,EAAE,MAAM,CAAC;IACzB,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,YAAY;IAC3B;6DACyD;IACzD,MAAM,EAAE,cAAc,GAAG,aAAa,CAAC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;uEACmE;IACnE,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,qDAAqD;IACrD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;0EACsE;IACtE,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,kBAAkB,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAWD;4CAC4C;AAC5C,wBAAgB,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAuB1E;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAiF/D;AAID;uEACuE;AACvE,MAAM,WAAW,WAAW;IAC1B;;;;;gEAK4D;IAC5D,WAAW,CAAC,KAAK,EAAE;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,UAAU,EAAE,CAAC;KACrB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC,CAAC;IACzD;;;;;sDAKkD;IAClD,OAAO,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/F;AAED;;;;sFAIsF;AACtF,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED;;;wDAGwD;AACxD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAW1D;AAED,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,aAAa,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAYD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIhD;AA0BD;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,gBAAgB,CAAC,CAmL3B"}