@agimon-ai/doompi-style-system 0.0.1-alpha.100

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/apiContracts.cjs +118 -0
  4. package/dist/apiContracts.cjs.map +1 -0
  5. package/dist/apiContracts.d.mts +52 -0
  6. package/dist/apiContracts.d.mts.map +1 -0
  7. package/dist/apiContracts.mjs +113 -0
  8. package/dist/apiContracts.mjs.map +1 -0
  9. package/dist/cli.cjs +242 -0
  10. package/dist/cli.cjs.map +1 -0
  11. package/dist/cli.d.mts +4 -0
  12. package/dist/cli.d.mts.map +1 -0
  13. package/dist/cli.mjs +239 -0
  14. package/dist/cli.mjs.map +1 -0
  15. package/dist/designCheck-7P9r9ijq.mjs +475 -0
  16. package/dist/designCheck-7P9r9ijq.mjs.map +1 -0
  17. package/dist/designCheck-zx4PsRvE.cjs +495 -0
  18. package/dist/designCheck-zx4PsRvE.cjs.map +1 -0
  19. package/dist/extensions/pi.cjs +94 -0
  20. package/dist/extensions/pi.cjs.map +1 -0
  21. package/dist/extensions/pi.d.mts +5 -0
  22. package/dist/extensions/pi.d.mts.map +1 -0
  23. package/dist/extensions/pi.mjs +87 -0
  24. package/dist/extensions/pi.mjs.map +1 -0
  25. package/dist/extensions/server.cjs +136 -0
  26. package/dist/extensions/server.cjs.map +1 -0
  27. package/dist/extensions/server.d.mts +5 -0
  28. package/dist/extensions/server.d.mts.map +1 -0
  29. package/dist/extensions/server.mjs +131 -0
  30. package/dist/extensions/server.mjs.map +1 -0
  31. package/dist/extensions/web.mjs +942 -0
  32. package/dist/extensions/web.mjs.map +1 -0
  33. package/dist/index.cjs +8 -0
  34. package/dist/index.d.mts +171 -0
  35. package/dist/index.d.mts.map +1 -0
  36. package/dist/index.mjs +3 -0
  37. package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
  38. package/dist/storyPreview-D-hGhlig.cjs +371 -0
  39. package/dist/storyPreview-D-hGhlig.cjs.map +1 -0
  40. package/dist/storyPreview-Dhejqhos.mjs +357 -0
  41. package/dist/storyPreview-Dhejqhos.mjs.map +1 -0
  42. package/package.json +132 -0
  43. package/skills/design-workflow/SKILL.md +84 -0
@@ -0,0 +1,475 @@
1
+ import { n as extractStoryExports } from "./storyPreview-Dhejqhos.mjs";
2
+ import { createHash } from "node:crypto";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ //#region src/services/designCheck/index.ts
6
+ const STORY_FILE_PATTERN = /\.stories\.(?:js|jsx|ts|tsx)$/u;
7
+ const STORY_EXPORT_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;
8
+ const SOURCE_FILE_PATTERN = /\.(?:css|less|sass|scss|js|jsx|md|ts|tsx)$/u;
9
+ const CODE_FILE_PATTERN = /\.(?:js|jsx|ts|tsx)$/u;
10
+ const MAX_FILES = 256;
11
+ const MAX_FILE_BYTES = 524288;
12
+ const MAX_TOTAL_BYTES = 8388608;
13
+ const DEFAULT_MANAGED_TOKEN_PREFIXES = [
14
+ "--doom-",
15
+ "--ds-",
16
+ "--color-",
17
+ "--spacing-",
18
+ "--font-",
19
+ "--radius-",
20
+ "--shadow-"
21
+ ];
22
+ const DEFAULT_COLOR_NAMES = "red orange amber yellow lime green emerald teal cyan sky blue indigo violet purple fuchsia pink rose slate gray zinc neutral stone".split(" ");
23
+ function isContained(root, candidate) {
24
+ const relative = path.relative(root, candidate);
25
+ return relative === "" || !relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative);
26
+ }
27
+ function relativePath(root, candidate) {
28
+ const relative = path.relative(root, candidate).split(path.sep).join("/");
29
+ return relative === "" ? "." : relative;
30
+ }
31
+ async function canonicalPath(root, input, field) {
32
+ if (typeof input !== "string" || input.trim() === "") throw new Error(`${field} is required`);
33
+ const candidate = path.resolve(root, input);
34
+ const canonical = await fs.promises.realpath(candidate);
35
+ if (!isContained(root, canonical)) throw new Error(`${field} must remain inside the workspace root`);
36
+ return canonical;
37
+ }
38
+ async function collectFiles(root, inputPath, files, counters) {
39
+ if (files.length >= MAX_FILES) throw new Error("The design check reached its file limit. Narrow sourceRoots.");
40
+ const stat = await fs.promises.lstat(inputPath);
41
+ if (stat.isSymbolicLink()) throw new Error(`Symlinked design input is not allowed: ${relativePath(root, inputPath)}`);
42
+ if (stat.isDirectory()) {
43
+ const entries = (await fs.promises.readdir(inputPath, { withFileTypes: true })).sort((left, right) => left.name.localeCompare(right.name));
44
+ for (const entry of entries) {
45
+ if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist" || entry.name === ".tmp") continue;
46
+ await collectFiles(root, path.join(inputPath, entry.name), files, counters);
47
+ }
48
+ return;
49
+ }
50
+ if (!stat.isFile() || !SOURCE_FILE_PATTERN.test(inputPath)) return;
51
+ if (stat.size > MAX_FILE_BYTES) throw new Error(`Design input is too large: ${relativePath(root, inputPath)}`);
52
+ counters.bytes += stat.size;
53
+ if (counters.bytes > MAX_TOTAL_BYTES) throw new Error("The design check reached its byte limit. Narrow sourceRoots.");
54
+ const content = await fs.promises.readFile(inputPath, "utf8");
55
+ files.push({
56
+ absolutePath: inputPath,
57
+ relativePath: relativePath(root, inputPath),
58
+ content,
59
+ bytes: stat.size
60
+ });
61
+ }
62
+ function lineAt(source, index) {
63
+ return source.slice(0, index).split("\n").length;
64
+ }
65
+ function addFinding(findings, finding) {
66
+ if (findings.some((existing) => existing.kind === finding.kind && existing.code === finding.code && existing.filePath === finding.filePath && existing.line === finding.line && existing.value === finding.value)) return;
67
+ findings.push(finding);
68
+ }
69
+ function extractClassValues(source) {
70
+ const values = [];
71
+ for (const match of source.matchAll(/\bclassName\s*=\s*(?:"([^"]*)"|'([^']*)'|\{\s*([`'"])([\s\S]*?)\3\s*\})/gu)) {
72
+ const value = match[1] ?? match[2] ?? match[4] ?? "";
73
+ values.push({
74
+ value,
75
+ index: match.index ?? 0,
76
+ dynamic: (match[4] ?? "").includes("${")
77
+ });
78
+ }
79
+ for (const match of source.matchAll(/\bclassName\s*=\s*\{([\s\S]*?)\}/gu)) {
80
+ const body = match[1]?.trim() ?? "";
81
+ if (body !== "" && !/^(['"`])[\s\S]*\1$/u.test(body)) values.push({
82
+ value: body,
83
+ index: match.index ?? 0,
84
+ dynamic: true
85
+ });
86
+ }
87
+ for (const match of source.matchAll(/\b(?:cn|clsx|cva|tv)\s*\(([\s\S]*?)\)/gu)) {
88
+ const body = match[1] ?? "";
89
+ const start = (match.index ?? 0) + match[0].indexOf(body);
90
+ const stringless = body.replace(/'[^'\n]*'|"[^"\n]*"/gu, "").replace(/[\s,]/gu, "");
91
+ if (body.includes("${") || stringless !== "") values.push({
92
+ value: body,
93
+ index: start,
94
+ dynamic: true
95
+ });
96
+ for (const part of body.matchAll(/(['"])([^'"\n]*)\1/gu)) values.push({
97
+ value: part[2] ?? "",
98
+ index: start + (part.index ?? 0),
99
+ dynamic: false
100
+ });
101
+ }
102
+ return values;
103
+ }
104
+ function isMarker(value) {
105
+ return /^(?:group|peer|dark|light|container|prose)(?:[-:/].*)?$/u.test(value);
106
+ }
107
+ function policyViolation(value) {
108
+ const base = value.split("/")[0] ?? value;
109
+ if (new RegExp(`^(?:bg|text|border|from|to|via|ring|decoration|divide|outline|shadow)-(?:${DEFAULT_COLOR_NAMES.join("|")})-(?:50|[1-9]00)$`, "u").test(base)) return "raw-theme-color";
110
+ if (/^(?:text|rounded|tracking|leading)-\[[^\]]+\]$/u.test(value)) return "arbitrary-style-value";
111
+ if (/^(?:bg|text|border|from|to|via|ring)-\[(?:#|rgb|hsl)/u.test(value)) return "raw-theme-color";
112
+ }
113
+ function tokenReferences(source) {
114
+ return [...source.matchAll(/var\(\s*(--[A-Za-z0-9_-]+)/gu)].map((match) => ({
115
+ name: match[1],
116
+ index: match.index ?? 0
117
+ }));
118
+ }
119
+ function declaredTokens(files) {
120
+ const result = /* @__PURE__ */ new Set();
121
+ for (const file of files) for (const match of stripComments(file.content).matchAll(/(--[A-Za-z0-9_-]+)\s*:/gu)) result.add(match[1]);
122
+ return result;
123
+ }
124
+ function stripComments(source) {
125
+ let output = "";
126
+ let quote;
127
+ let escaped = false;
128
+ for (let index = 0; index < source.length; index += 1) {
129
+ const character = source[index];
130
+ const next = source[index + 1];
131
+ if (quote !== void 0) {
132
+ output += character;
133
+ if (escaped) escaped = false;
134
+ else if (character === "\\") escaped = true;
135
+ else if (character === quote) quote = void 0;
136
+ continue;
137
+ }
138
+ if (character === "\"" || character === "'" || character === "`") {
139
+ quote = character;
140
+ output += character;
141
+ } else if (character === "/" && next === "/") {
142
+ output += " ";
143
+ index += 2;
144
+ while (index < source.length && source[index] !== "\n") {
145
+ output += " ";
146
+ index += 1;
147
+ }
148
+ if (index < source.length) output += "\n";
149
+ } else if (character === "/" && next === "*") {
150
+ output += " ";
151
+ index += 2;
152
+ while (index < source.length && !(source[index - 1] === "*" && source[index] === "/")) {
153
+ output += source[index] === "\n" ? "\n" : " ";
154
+ index += 1;
155
+ }
156
+ } else output += character;
157
+ }
158
+ return output;
159
+ }
160
+ function remoteSpecifier(specifier) {
161
+ return /^(?:https?:|data:|file:|\/\/)/iu.test(specifier);
162
+ }
163
+ async function importExists(root, file, specifier, unresolved, violations, index) {
164
+ if (remoteSpecifier(specifier)) {
165
+ addFinding(violations, {
166
+ kind: "policy-violation",
167
+ code: "remote-import",
168
+ message: "Remote and non-workspace imports are not allowed during a read-only design check.",
169
+ filePath: file.relativePath,
170
+ line: lineAt(file.content, index),
171
+ value: specifier
172
+ });
173
+ return;
174
+ }
175
+ if (!specifier.startsWith(".") && !path.isAbsolute(specifier)) return;
176
+ if (path.isAbsolute(specifier)) {
177
+ addFinding(violations, {
178
+ kind: "policy-violation",
179
+ code: "absolute-import",
180
+ message: "Absolute imports are not admitted by the workspace design check.",
181
+ filePath: file.relativePath,
182
+ line: lineAt(file.content, index),
183
+ value: specifier
184
+ });
185
+ return;
186
+ }
187
+ const cleanSpecifier = specifier.split(/[?#]/u)[0];
188
+ const candidate = path.resolve(path.dirname(file.absolutePath), cleanSpecifier);
189
+ if (!isContained(root, candidate)) {
190
+ addFinding(violations, {
191
+ kind: "policy-violation",
192
+ code: "import-traversal",
193
+ message: "A relative import escapes the admitted workspace.",
194
+ filePath: file.relativePath,
195
+ line: lineAt(file.content, index),
196
+ value: specifier
197
+ });
198
+ return;
199
+ }
200
+ const candidates = [
201
+ candidate,
202
+ ...[
203
+ ".js",
204
+ ".jsx",
205
+ ".ts",
206
+ ".tsx",
207
+ ".css",
208
+ ".scss",
209
+ ".sass",
210
+ ".less"
211
+ ].map((extension) => `${candidate}${extension}`),
212
+ ...[
213
+ "index.js",
214
+ "index.jsx",
215
+ "index.ts",
216
+ "index.tsx",
217
+ "index.css"
218
+ ].map((name) => path.join(candidate, name))
219
+ ];
220
+ for (const possible of candidates) try {
221
+ const canonical = await fs.promises.realpath(possible);
222
+ if (!isContained(root, canonical)) {
223
+ addFinding(violations, {
224
+ kind: "policy-violation",
225
+ code: "import-symlink-escape",
226
+ message: "A relative import resolves through a symlink outside the admitted workspace.",
227
+ filePath: file.relativePath,
228
+ line: lineAt(file.content, index),
229
+ value: specifier
230
+ });
231
+ return;
232
+ }
233
+ if ((await fs.promises.stat(canonical)).isFile()) return;
234
+ } catch {}
235
+ addFinding(unresolved, {
236
+ kind: "unresolved",
237
+ code: "missing-import",
238
+ message: "A relative import could not be resolved within the admitted workspace.",
239
+ filePath: file.relativePath,
240
+ line: lineAt(file.content, index),
241
+ value: specifier
242
+ });
243
+ }
244
+ async function inspectSource(root, file, unresolved, violations) {
245
+ const source = stripComments(file.content);
246
+ if (/\.(?:css|less|sass|scss)$/u.test(file.relativePath)) {
247
+ for (const match of source.matchAll(/@(plugin|config)\b/gu)) addFinding(violations, {
248
+ kind: "policy-violation",
249
+ code: "executable-style-directive",
250
+ message: `The @${match[1]} directive is executable configuration and is not run by a read-only check.`,
251
+ filePath: file.relativePath,
252
+ line: lineAt(file.content, match.index ?? 0),
253
+ value: `@${match[1]}`
254
+ });
255
+ for (const match of source.matchAll(/@(?:import|use|forward)\s+(?:url\(\s*)?['"]?([^'")\s]+)['"]?\s*\)?/gu)) await importExists(root, file, match[1], unresolved, violations, match.index ?? 0);
256
+ }
257
+ if (!CODE_FILE_PATTERN.test(file.relativePath)) return;
258
+ for (const pattern of [
259
+ /\bimport\s+(?:[^'"]*?\sfrom\s*)?['"]([^'"]+)['"]/gu,
260
+ /\bexport\s+(?:[^'"]*?\sfrom\s*)?['"]([^'"]+)['"]/gu,
261
+ /\b(?:require|import)\s*\(\s*['"]([^'"]+)['"]/gu
262
+ ]) for (const match of source.matchAll(pattern)) await importExists(root, file, match[1], unresolved, violations, match.index ?? 0);
263
+ }
264
+ function parseTarget(value) {
265
+ if (typeof value !== "object" || value === null) throw new Error("The design target must be a JSON object.");
266
+ const candidate = value;
267
+ const stringField = (name) => {
268
+ const field = candidate[name];
269
+ if (typeof field !== "string" || field.trim() === "") throw new Error(`The design target field '${name}' is required.`);
270
+ return field;
271
+ };
272
+ const stringList = (name) => {
273
+ const field = candidate[name];
274
+ if (field === void 0) return void 0;
275
+ if (!Array.isArray(field) || field.some((item) => typeof item !== "string" || item.trim() === "")) throw new Error(`The design target field '${name}' must be a list of non-empty strings.`);
276
+ return field;
277
+ };
278
+ if (candidate.version !== 1) throw new Error("The design target version must be 1.");
279
+ const storyExport = stringField("storyExport");
280
+ if (!STORY_EXPORT_PATTERN.test(storyExport)) throw new Error("The design target storyExport must be an exact JavaScript named export.");
281
+ return {
282
+ version: 1,
283
+ appPath: stringField("appPath"),
284
+ storyPath: stringField("storyPath"),
285
+ storyExport,
286
+ sourceRoots: stringList("sourceRoots"),
287
+ styleFiles: stringList("styleFiles"),
288
+ principleDocuments: stringList("principleDocuments"),
289
+ managedTokens: stringList("managedTokens"),
290
+ managedTokenPrefixes: stringList("managedTokenPrefixes")
291
+ };
292
+ }
293
+ async function readDesignTarget(filePath) {
294
+ return parseTarget(JSON.parse(await fs.promises.readFile(filePath, "utf8")));
295
+ }
296
+ async function checkDesignTarget(target, workspaceRoot) {
297
+ const root = await fs.promises.realpath(workspaceRoot);
298
+ if (!STORY_EXPORT_PATTERN.test(target.storyExport)) throw new Error("The design target storyExport must be an exact JavaScript named export.");
299
+ const storyPath = await canonicalPath(root, target.storyPath, "storyPath");
300
+ if (!STORY_FILE_PATTERN.test(storyPath)) throw new Error("storyPath must name a .stories.js, .stories.jsx, .stories.ts, or .stories.tsx file");
301
+ const appPath = await canonicalPath(root, target.appPath, "appPath");
302
+ const inputs = /* @__PURE__ */ new Map();
303
+ const counters = { bytes: 0 };
304
+ const coverageFindings = [];
305
+ const addInput = async (input, field) => {
306
+ const candidate = await canonicalPath(root, input, field);
307
+ const files = [];
308
+ await collectFiles(root, candidate, files, counters);
309
+ if (files.length === 0) addFinding(coverageFindings, {
310
+ kind: "unresolved",
311
+ code: "input-not-covered",
312
+ message: `No supported source files were found for ${field} input '${relativePath(root, candidate)}'.`,
313
+ filePath: relativePath(root, candidate)
314
+ });
315
+ else if (field === "sourceRoots" && !files.some((file) => CODE_FILE_PATTERN.test(file.relativePath))) addFinding(coverageFindings, {
316
+ kind: "unresolved",
317
+ code: "source-root-no-code",
318
+ message: `The source root '${relativePath(root, candidate)}' contains no statically inspectable component source files.`,
319
+ filePath: relativePath(root, candidate)
320
+ });
321
+ for (const file of files) inputs.set(file.absolutePath, file);
322
+ };
323
+ await addInput(target.storyPath, "storyPath");
324
+ for (const input of target.sourceRoots ?? []) await addInput(input, "sourceRoots");
325
+ for (const input of target.styleFiles ?? []) await addInput(input, "styleFiles");
326
+ for (const input of target.principleDocuments ?? []) await addInput(input, "principleDocuments");
327
+ const files = [...inputs.values()].sort((left, right) => left.relativePath.localeCompare(right.relativePath));
328
+ const violations = [];
329
+ const unresolved = [...coverageFindings];
330
+ const recognized = [];
331
+ const story = files.find((file) => file.absolutePath === storyPath);
332
+ if (story === void 0) throw new Error("The story file was not included in the design inputs.");
333
+ if (!extractStoryExports(story.content).some((entry) => entry.exportName === target.storyExport)) addFinding(violations, {
334
+ kind: "policy-violation",
335
+ code: "story-export-missing",
336
+ message: `Story export '${target.storyExport}' was not found in ${story.relativePath}.`,
337
+ filePath: story.relativePath,
338
+ value: target.storyExport
339
+ });
340
+ for (const file of files) await inspectSource(root, file, unresolved, violations);
341
+ if (!files.some((file) => /\.(?:css|less|sass|scss)$/u.test(file.relativePath))) addFinding(unresolved, {
342
+ kind: "unresolved",
343
+ code: "style-context-not-declared",
344
+ message: "No CSS or token stylesheet was included, so style and token coverage is incomplete."
345
+ });
346
+ for (const file of files) {
347
+ if (!CODE_FILE_PATTERN.test(file.relativePath)) continue;
348
+ for (const classValue of extractClassValues(stripComments(file.content))) {
349
+ if (classValue.dynamic) {
350
+ addFinding(unresolved, {
351
+ kind: "unresolved",
352
+ code: "dynamic-class-expression",
353
+ message: "The class expression is dynamic and was not evaluated.",
354
+ filePath: file.relativePath,
355
+ line: lineAt(file.content, classValue.index),
356
+ value: classValue.value
357
+ });
358
+ continue;
359
+ }
360
+ for (const value of classValue.value.split(/\s+/u).filter(Boolean)) {
361
+ recognized.push({
362
+ value,
363
+ filePath: file.relativePath,
364
+ line: lineAt(file.content, classValue.index)
365
+ });
366
+ const code = policyViolation(value);
367
+ if (code !== void 0) addFinding(violations, {
368
+ kind: "policy-violation",
369
+ code,
370
+ message: `${value} is not an approved semantic design token or scale value.`,
371
+ filePath: file.relativePath,
372
+ line: lineAt(file.content, classValue.index),
373
+ value
374
+ });
375
+ else if (isMarker(value)) {}
376
+ }
377
+ }
378
+ }
379
+ const availableTokens = declaredTokens(files.filter((file) => /\.(?:css|less|sass|scss)$/u.test(file.relativePath)));
380
+ const configuredTokens = target.managedTokens === void 0 ? void 0 : new Set(target.managedTokens);
381
+ const prefixes = target.managedTokenPrefixes ?? DEFAULT_MANAGED_TOKEN_PREFIXES;
382
+ let tokenValidation = "not-configured";
383
+ for (const file of files) for (const reference of tokenReferences(stripComments(file.content))) {
384
+ if (!(configuredTokens?.has(reference.name) || prefixes.some((prefix) => reference.name.startsWith(prefix)))) continue;
385
+ tokenValidation = configuredTokens === void 0 ? "prefixes-only" : "declared-contract";
386
+ if (availableTokens.has(reference.name) || configuredTokens?.has(reference.name)) continue;
387
+ if (configuredTokens !== void 0) addFinding(violations, {
388
+ kind: "unsupported-token",
389
+ code: "managed-token-missing",
390
+ message: `Managed design token '${reference.name}' is not declared by the admitted CSS inputs.`,
391
+ filePath: file.relativePath,
392
+ line: lineAt(file.content, reference.index),
393
+ value: reference.name
394
+ });
395
+ else addFinding(unresolved, {
396
+ kind: "unresolved",
397
+ code: "token-contract-missing",
398
+ message: `The managed token '${reference.name}' could not be verified without an explicit token contract.`,
399
+ filePath: file.relativePath,
400
+ line: lineAt(file.content, reference.index),
401
+ value: reference.name
402
+ });
403
+ }
404
+ if (target.sourceRoots === void 0 || target.sourceRoots.length === 0) addFinding(unresolved, {
405
+ kind: "unresolved",
406
+ code: "source-roots-not-declared",
407
+ message: "No component source roots were declared, so the check is story-local."
408
+ });
409
+ const fingerprints = files.map((file) => ({
410
+ path: file.relativePath,
411
+ sha256: createHash("sha256").update(file.content).digest("hex"),
412
+ bytes: file.bytes
413
+ }));
414
+ return {
415
+ version: 1,
416
+ status: violations.length > 0 ? "not-ready" : unresolved.length > 0 ? "incomplete" : "ready",
417
+ target: {
418
+ ...target,
419
+ appPath: relativePath(root, appPath),
420
+ storyPath: relativePath(root, storyPath)
421
+ },
422
+ fingerprints,
423
+ violations,
424
+ recognized,
425
+ unresolved,
426
+ coverage: {
427
+ filesChecked: files.length,
428
+ bytesChecked: counters.bytes,
429
+ limits: {
430
+ maxFiles: MAX_FILES,
431
+ maxFileBytes: MAX_FILE_BYTES,
432
+ maxTotalBytes: MAX_TOTAL_BYTES
433
+ },
434
+ classValidation: "static-extraction-only",
435
+ tokenValidation
436
+ }
437
+ };
438
+ }
439
+ async function verifyDesignReport(reportPath, workspaceRoot) {
440
+ const report = JSON.parse(await fs.promises.readFile(reportPath, "utf8"));
441
+ if (report.version !== 1 || !Array.isArray(report.fingerprints) || report.target === void 0) throw new Error("The readiness report is not version 1.");
442
+ const root = await fs.promises.realpath(workspaceRoot);
443
+ const stalePaths = [];
444
+ for (const fingerprint of report.fingerprints) try {
445
+ const absolute = await canonicalPath(root, fingerprint.path, "fingerprint path");
446
+ const content = await fs.promises.readFile(absolute);
447
+ if (createHash("sha256").update(content).digest("hex") !== fingerprint.sha256) stalePaths.push(fingerprint.path);
448
+ } catch {
449
+ stalePaths.push(fingerprint.path);
450
+ }
451
+ try {
452
+ const fresh = await checkDesignTarget(report.target, root);
453
+ const evidence = (value) => JSON.stringify({
454
+ status: value.status,
455
+ target: value.target,
456
+ fingerprints: value.fingerprints,
457
+ violations: value.violations,
458
+ recognized: value.recognized,
459
+ unresolved: value.unresolved,
460
+ coverage: value.coverage
461
+ });
462
+ if (evidence(fresh) !== evidence(report)) stalePaths.push("[check]");
463
+ } catch {
464
+ stalePaths.push("[check]");
465
+ }
466
+ return {
467
+ current: stalePaths.length === 0,
468
+ stalePaths: [...new Set(stalePaths)],
469
+ report
470
+ };
471
+ }
472
+ //#endregion
473
+ export { readDesignTarget as n, verifyDesignReport as r, checkDesignTarget as t };
474
+
475
+ //# sourceMappingURL=designCheck-7P9r9ijq.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"designCheck-7P9r9ijq.mjs","names":[],"sources":["../src/services/designCheck/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { extractStoryExports } from '../storyPreview';\n\nconst STORY_FILE_PATTERN = /\\.stories\\.(?:js|jsx|ts|tsx)$/u;\nconst STORY_EXPORT_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;\nconst SOURCE_FILE_PATTERN = /\\.(?:css|less|sass|scss|js|jsx|md|ts|tsx)$/u;\nconst CODE_FILE_PATTERN = /\\.(?:js|jsx|ts|tsx)$/u;\nconst MAX_FILES = 256;\nconst MAX_FILE_BYTES = 512 * 1024;\nconst MAX_TOTAL_BYTES = 8 * 1024 * 1024;\nconst DEFAULT_MANAGED_TOKEN_PREFIXES = [\n '--doom-',\n '--ds-',\n '--color-',\n '--spacing-',\n '--font-',\n '--radius-',\n '--shadow-',\n];\nconst DEFAULT_COLOR_NAMES =\n 'red orange amber yellow lime green emerald teal cyan sky blue indigo violet purple fuchsia pink rose slate gray zinc neutral stone'.split(\n ' ',\n );\n\nexport interface DesignTargetManifest {\n version: 1;\n appPath: string;\n storyPath: string;\n storyExport: string;\n sourceRoots?: readonly string[];\n styleFiles?: readonly string[];\n principleDocuments?: readonly string[];\n managedTokens?: readonly string[];\n managedTokenPrefixes?: readonly string[];\n}\n\nexport interface DesignFinding {\n kind: 'policy-violation' | 'unsupported-token' | 'unresolved';\n code: string;\n message: string;\n filePath?: string;\n line?: number;\n value?: string;\n}\n\nexport interface DesignFingerprint {\n path: string;\n sha256: string;\n bytes: number;\n}\n\nexport interface DesignCheckReport {\n version: 1;\n status: 'ready' | 'not-ready' | 'incomplete';\n target: DesignTargetManifest;\n fingerprints: readonly DesignFingerprint[];\n violations: readonly DesignFinding[];\n recognized: readonly { value: string; filePath: string; line: number }[];\n unresolved: readonly DesignFinding[];\n coverage: {\n filesChecked: number;\n bytesChecked: number;\n limits: { maxFiles: number; maxFileBytes: number; maxTotalBytes: number };\n classValidation: 'static-extraction-only';\n tokenValidation: 'declared-contract' | 'prefixes-only' | 'not-configured';\n };\n}\n\nexport interface DesignVerificationResult {\n current: boolean;\n stalePaths: readonly string[];\n report: DesignCheckReport;\n}\n\ninterface ReadFile {\n absolutePath: string;\n relativePath: string;\n content: string;\n bytes: number;\n}\n\nfunction isContained(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));\n}\n\nfunction relativePath(root: string, candidate: string): string {\n const relative = path.relative(root, candidate).split(path.sep).join('/');\n return relative === '' ? '.' : relative;\n}\n\nasync function canonicalPath(root: string, input: string, field: string): Promise<string> {\n if (typeof input !== 'string' || input.trim() === '') throw new Error(`${field} is required`);\n const candidate = path.resolve(root, input);\n const canonical = await fs.promises.realpath(candidate);\n if (!isContained(root, canonical)) throw new Error(`${field} must remain inside the workspace root`);\n return canonical;\n}\n\nasync function collectFiles(\n root: string,\n inputPath: string,\n files: ReadFile[],\n counters: { bytes: number },\n): Promise<void> {\n if (files.length >= MAX_FILES) throw new Error('The design check reached its file limit. Narrow sourceRoots.');\n const stat = await fs.promises.lstat(inputPath);\n if (stat.isSymbolicLink()) throw new Error(`Symlinked design input is not allowed: ${relativePath(root, inputPath)}`);\n if (stat.isDirectory()) {\n const entries = (await fs.promises.readdir(inputPath, { withFileTypes: true })).sort((left, right) =>\n left.name.localeCompare(right.name),\n );\n for (const entry of entries) {\n if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === 'dist' || entry.name === '.tmp')\n continue;\n await collectFiles(root, path.join(inputPath, entry.name), files, counters);\n }\n return;\n }\n if (!stat.isFile() || !SOURCE_FILE_PATTERN.test(inputPath)) return;\n if (stat.size > MAX_FILE_BYTES) throw new Error(`Design input is too large: ${relativePath(root, inputPath)}`);\n counters.bytes += stat.size;\n if (counters.bytes > MAX_TOTAL_BYTES) throw new Error('The design check reached its byte limit. Narrow sourceRoots.');\n const content = await fs.promises.readFile(inputPath, 'utf8');\n files.push({ absolutePath: inputPath, relativePath: relativePath(root, inputPath), content, bytes: stat.size });\n}\n\nfunction lineAt(source: string, index: number): number {\n return source.slice(0, index).split('\\n').length;\n}\n\nfunction addFinding(findings: DesignFinding[], finding: DesignFinding): void {\n if (\n findings.some(\n (existing) =>\n existing.kind === finding.kind &&\n existing.code === finding.code &&\n existing.filePath === finding.filePath &&\n existing.line === finding.line &&\n existing.value === finding.value,\n )\n )\n return;\n findings.push(finding);\n}\n\nfunction extractClassValues(source: string): Array<{ value: string; index: number; dynamic: boolean }> {\n const values: Array<{ value: string; index: number; dynamic: boolean }> = [];\n const attribute = /\\bclassName\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|\\{\\s*([`'\"])([\\s\\S]*?)\\3\\s*\\})/gu;\n for (const match of source.matchAll(attribute)) {\n const value = match[1] ?? match[2] ?? match[4] ?? '';\n values.push({ value, index: match.index ?? 0, dynamic: (match[4] ?? '').includes('${') });\n }\n const dynamicAttribute = /\\bclassName\\s*=\\s*\\{([\\s\\S]*?)\\}/gu;\n for (const match of source.matchAll(dynamicAttribute)) {\n const body = match[1]?.trim() ?? '';\n if (body !== '' && !/^(['\"`])[\\s\\S]*\\1$/u.test(body)) {\n values.push({ value: body, index: match.index ?? 0, dynamic: true });\n }\n }\n const helper = /\\b(?:cn|clsx|cva|tv)\\s*\\(([\\s\\S]*?)\\)/gu;\n for (const match of source.matchAll(helper)) {\n const body = match[1] ?? '';\n const start = (match.index ?? 0) + match[0].indexOf(body);\n const stringless = body.replace(/'[^'\\n]*'|\"[^\"\\n]*\"/gu, '').replace(/[\\s,]/gu, '');\n if (body.includes('${') || stringless !== '') values.push({ value: body, index: start, dynamic: true });\n const literal = /(['\"])([^'\"\\n]*)\\1/gu;\n for (const part of body.matchAll(literal))\n values.push({ value: part[2] ?? '', index: start + (part.index ?? 0), dynamic: false });\n }\n return values;\n}\n\nfunction isMarker(value: string): boolean {\n return /^(?:group|peer|dark|light|container|prose)(?:[-:/].*)?$/u.test(value);\n}\n\nfunction policyViolation(value: string): string | undefined {\n const base = value.split('/')[0] ?? value;\n const colorPattern = new RegExp(\n `^(?:bg|text|border|from|to|via|ring|decoration|divide|outline|shadow)-(?:${DEFAULT_COLOR_NAMES.join('|')})-(?:50|[1-9]00)$`,\n 'u',\n );\n if (colorPattern.test(base)) return 'raw-theme-color';\n if (/^(?:text|rounded|tracking|leading)-\\[[^\\]]+\\]$/u.test(value)) return 'arbitrary-style-value';\n if (/^(?:bg|text|border|from|to|via|ring)-\\[(?:#|rgb|hsl)/u.test(value)) return 'raw-theme-color';\n return undefined;\n}\n\nfunction tokenReferences(source: string): Array<{ name: string; index: number }> {\n return [...source.matchAll(/var\\(\\s*(--[A-Za-z0-9_-]+)/gu)].map((match) => ({\n name: match[1]!,\n index: match.index ?? 0,\n }));\n}\n\nfunction declaredTokens(files: readonly ReadFile[]): Set<string> {\n const result = new Set<string>();\n for (const file of files) {\n for (const match of stripComments(file.content).matchAll(/(--[A-Za-z0-9_-]+)\\s*:/gu)) result.add(match[1]!);\n }\n return result;\n}\n\nfunction stripComments(source: string): string {\n let output = '';\n let quote: \"'\" | '\"' | '`' | undefined;\n let escaped = false;\n for (let index = 0; index < source.length; index += 1) {\n const character = source[index];\n const next = source[index + 1];\n if (quote !== undefined) {\n output += character;\n if (escaped) escaped = false;\n else if (character === '\\\\') escaped = true;\n else if (character === quote) quote = undefined;\n continue;\n }\n if (character === '\"' || character === \"'\" || character === '`') {\n quote = character;\n output += character;\n } else if (character === '/' && next === '/') {\n output += ' ';\n index += 2;\n while (index < source.length && source[index] !== '\\n') {\n output += ' ';\n index += 1;\n }\n if (index < source.length) output += '\\n';\n } else if (character === '/' && next === '*') {\n output += ' ';\n index += 2;\n while (index < source.length && !(source[index - 1] === '*' && source[index] === '/')) {\n output += source[index] === '\\n' ? '\\n' : ' ';\n index += 1;\n }\n } else output += character;\n }\n return output;\n}\n\nfunction remoteSpecifier(specifier: string): boolean {\n return /^(?:https?:|data:|file:|\\/\\/)/iu.test(specifier);\n}\n\nasync function importExists(\n root: string,\n file: ReadFile,\n specifier: string,\n unresolved: DesignFinding[],\n violations: DesignFinding[],\n index: number,\n): Promise<void> {\n if (remoteSpecifier(specifier)) {\n addFinding(violations, {\n kind: 'policy-violation',\n code: 'remote-import',\n message: 'Remote and non-workspace imports are not allowed during a read-only design check.',\n filePath: file.relativePath,\n line: lineAt(file.content, index),\n value: specifier,\n });\n return;\n }\n if (!specifier.startsWith('.') && !path.isAbsolute(specifier)) return;\n if (path.isAbsolute(specifier)) {\n addFinding(violations, {\n kind: 'policy-violation',\n code: 'absolute-import',\n message: 'Absolute imports are not admitted by the workspace design check.',\n filePath: file.relativePath,\n line: lineAt(file.content, index),\n value: specifier,\n });\n return;\n }\n const cleanSpecifier = specifier.split(/[?#]/u)[0]!;\n const candidate = path.resolve(path.dirname(file.absolutePath), cleanSpecifier);\n if (!isContained(root, candidate)) {\n addFinding(violations, {\n kind: 'policy-violation',\n code: 'import-traversal',\n message: 'A relative import escapes the admitted workspace.',\n filePath: file.relativePath,\n line: lineAt(file.content, index),\n value: specifier,\n });\n return;\n }\n const candidates = [\n candidate,\n ...['.js', '.jsx', '.ts', '.tsx', '.css', '.scss', '.sass', '.less'].map((extension) => `${candidate}${extension}`),\n ...['index.js', 'index.jsx', 'index.ts', 'index.tsx', 'index.css'].map((name) => path.join(candidate, name)),\n ];\n for (const possible of candidates) {\n try {\n const canonical = await fs.promises.realpath(possible);\n if (!isContained(root, canonical)) {\n addFinding(violations, {\n kind: 'policy-violation',\n code: 'import-symlink-escape',\n message: 'A relative import resolves through a symlink outside the admitted workspace.',\n filePath: file.relativePath,\n line: lineAt(file.content, index),\n value: specifier,\n });\n return;\n }\n const stat = await fs.promises.stat(canonical);\n if (stat.isFile()) return;\n } catch {\n // Try the next conventional extension or index entry.\n }\n }\n addFinding(unresolved, {\n kind: 'unresolved',\n code: 'missing-import',\n message: 'A relative import could not be resolved within the admitted workspace.',\n filePath: file.relativePath,\n line: lineAt(file.content, index),\n value: specifier,\n });\n}\n\nasync function inspectSource(\n root: string,\n file: ReadFile,\n unresolved: DesignFinding[],\n violations: DesignFinding[],\n): Promise<void> {\n const source = stripComments(file.content);\n if (/\\.(?:css|less|sass|scss)$/u.test(file.relativePath)) {\n const directives = /@(plugin|config)\\b/gu;\n for (const match of source.matchAll(directives)) {\n addFinding(violations, {\n kind: 'policy-violation',\n code: 'executable-style-directive',\n message: `The @${match[1]} directive is executable configuration and is not run by a read-only check.`,\n filePath: file.relativePath,\n line: lineAt(file.content, match.index ?? 0),\n value: `@${match[1]}`,\n });\n }\n const cssImports = /@(?:import|use|forward)\\s+(?:url\\(\\s*)?['\"]?([^'\")\\s]+)['\"]?\\s*\\)?/gu;\n for (const match of source.matchAll(cssImports)) {\n await importExists(root, file, match[1]!, unresolved, violations, match.index ?? 0);\n }\n }\n if (!CODE_FILE_PATTERN.test(file.relativePath)) return;\n const patterns = [\n /\\bimport\\s+(?:[^'\"]*?\\sfrom\\s*)?['\"]([^'\"]+)['\"]/gu,\n /\\bexport\\s+(?:[^'\"]*?\\sfrom\\s*)?['\"]([^'\"]+)['\"]/gu,\n /\\b(?:require|import)\\s*\\(\\s*['\"]([^'\"]+)['\"]/gu,\n ];\n for (const pattern of patterns) {\n for (const match of source.matchAll(pattern)) {\n await importExists(root, file, match[1]!, unresolved, violations, match.index ?? 0);\n }\n }\n}\nfunction parseTarget(value: unknown): DesignTargetManifest {\n if (typeof value !== 'object' || value === null) throw new Error('The design target must be a JSON object.');\n const candidate = value as Record<string, unknown>;\n const stringField = (name: string): string => {\n const field = candidate[name];\n if (typeof field !== 'string' || field.trim() === '')\n throw new Error(`The design target field '${name}' is required.`);\n return field;\n };\n const stringList = (name: string): readonly string[] | undefined => {\n const field = candidate[name];\n if (field === undefined) return undefined;\n if (!Array.isArray(field) || field.some((item) => typeof item !== 'string' || item.trim() === '')) {\n throw new Error(`The design target field '${name}' must be a list of non-empty strings.`);\n }\n return field;\n };\n if (candidate.version !== 1) throw new Error('The design target version must be 1.');\n const storyExport = stringField('storyExport');\n if (!STORY_EXPORT_PATTERN.test(storyExport))\n throw new Error('The design target storyExport must be an exact JavaScript named export.');\n return {\n version: 1,\n appPath: stringField('appPath'),\n storyPath: stringField('storyPath'),\n storyExport,\n sourceRoots: stringList('sourceRoots'),\n styleFiles: stringList('styleFiles'),\n principleDocuments: stringList('principleDocuments'),\n managedTokens: stringList('managedTokens'),\n managedTokenPrefixes: stringList('managedTokenPrefixes'),\n };\n}\n\nexport async function readDesignTarget(filePath: string): Promise<DesignTargetManifest> {\n return parseTarget(JSON.parse(await fs.promises.readFile(filePath, 'utf8')));\n}\n\nexport async function checkDesignTarget(\n target: DesignTargetManifest,\n workspaceRoot: string,\n): Promise<DesignCheckReport> {\n const root = await fs.promises.realpath(workspaceRoot);\n if (!STORY_EXPORT_PATTERN.test(target.storyExport))\n throw new Error('The design target storyExport must be an exact JavaScript named export.');\n const storyPath = await canonicalPath(root, target.storyPath, 'storyPath');\n if (!STORY_FILE_PATTERN.test(storyPath))\n throw new Error('storyPath must name a .stories.js, .stories.jsx, .stories.ts, or .stories.tsx file');\n const appPath = await canonicalPath(root, target.appPath, 'appPath');\n const inputs = new Map<string, ReadFile>();\n const counters = { bytes: 0 };\n const coverageFindings: DesignFinding[] = [];\n const addInput = async (input: string, field: string): Promise<void> => {\n const candidate = await canonicalPath(root, input, field);\n const files: ReadFile[] = [];\n await collectFiles(root, candidate, files, counters);\n if (files.length === 0) {\n addFinding(coverageFindings, {\n kind: 'unresolved',\n code: 'input-not-covered',\n message: `No supported source files were found for ${field} input '${relativePath(root, candidate)}'.`,\n filePath: relativePath(root, candidate),\n });\n } else if (field === 'sourceRoots' && !files.some((file) => CODE_FILE_PATTERN.test(file.relativePath))) {\n addFinding(coverageFindings, {\n kind: 'unresolved',\n code: 'source-root-no-code',\n message: `The source root '${relativePath(root, candidate)}' contains no statically inspectable component source files.`,\n filePath: relativePath(root, candidate),\n });\n }\n for (const file of files) inputs.set(file.absolutePath, file);\n };\n await addInput(target.storyPath, 'storyPath');\n for (const input of target.sourceRoots ?? []) await addInput(input, 'sourceRoots');\n for (const input of target.styleFiles ?? []) await addInput(input, 'styleFiles');\n for (const input of target.principleDocuments ?? []) await addInput(input, 'principleDocuments');\n\n const files = [...inputs.values()].sort((left, right) => left.relativePath.localeCompare(right.relativePath));\n const violations: DesignFinding[] = [];\n const unresolved: DesignFinding[] = [...coverageFindings];\n const recognized: Array<{ value: string; filePath: string; line: number }> = [];\n const story = files.find((file) => file.absolutePath === storyPath);\n if (story === undefined) throw new Error('The story file was not included in the design inputs.');\n if (!extractStoryExports(story.content).some((entry) => entry.exportName === target.storyExport)) {\n addFinding(violations, {\n kind: 'policy-violation',\n code: 'story-export-missing',\n message: `Story export '${target.storyExport}' was not found in ${story.relativePath}.`,\n filePath: story.relativePath,\n value: target.storyExport,\n });\n }\n\n for (const file of files) await inspectSource(root, file, unresolved, violations);\n if (!files.some((file) => /\\.(?:css|less|sass|scss)$/u.test(file.relativePath))) {\n addFinding(unresolved, {\n kind: 'unresolved',\n code: 'style-context-not-declared',\n message: 'No CSS or token stylesheet was included, so style and token coverage is incomplete.',\n });\n }\n\n for (const file of files) {\n if (!CODE_FILE_PATTERN.test(file.relativePath)) continue;\n for (const classValue of extractClassValues(stripComments(file.content))) {\n if (classValue.dynamic) {\n addFinding(unresolved, {\n kind: 'unresolved',\n code: 'dynamic-class-expression',\n message: 'The class expression is dynamic and was not evaluated.',\n filePath: file.relativePath,\n line: lineAt(file.content, classValue.index),\n value: classValue.value,\n });\n continue;\n }\n for (const value of classValue.value.split(/\\s+/u).filter(Boolean)) {\n recognized.push({ value, filePath: file.relativePath, line: lineAt(file.content, classValue.index) });\n const code = policyViolation(value);\n if (code !== undefined) {\n addFinding(violations, {\n kind: 'policy-violation',\n code,\n message: `${value} is not an approved semantic design token or scale value.`,\n filePath: file.relativePath,\n line: lineAt(file.content, classValue.index),\n value,\n });\n } else if (isMarker(value)) {\n // Marker classes are valid CSS selectors even when they emit no utility rule.\n }\n }\n }\n }\n\n const cssInputs = files.filter((file) => /\\.(?:css|less|sass|scss)$/u.test(file.relativePath));\n const availableTokens = declaredTokens(cssInputs);\n const configuredTokens = target.managedTokens === undefined ? undefined : new Set(target.managedTokens);\n const prefixes = target.managedTokenPrefixes ?? DEFAULT_MANAGED_TOKEN_PREFIXES;\n let tokenValidation: DesignCheckReport['coverage']['tokenValidation'] = 'not-configured';\n for (const file of files) {\n for (const reference of tokenReferences(stripComments(file.content))) {\n const managed =\n configuredTokens?.has(reference.name) || prefixes.some((prefix) => reference.name.startsWith(prefix));\n if (!managed) continue;\n tokenValidation = configuredTokens === undefined ? 'prefixes-only' : 'declared-contract';\n if (availableTokens.has(reference.name) || configuredTokens?.has(reference.name)) continue;\n if (configuredTokens !== undefined) {\n addFinding(violations, {\n kind: 'unsupported-token',\n code: 'managed-token-missing',\n message: `Managed design token '${reference.name}' is not declared by the admitted CSS inputs.`,\n filePath: file.relativePath,\n line: lineAt(file.content, reference.index),\n value: reference.name,\n });\n } else {\n addFinding(unresolved, {\n kind: 'unresolved',\n code: 'token-contract-missing',\n message: `The managed token '${reference.name}' could not be verified without an explicit token contract.`,\n filePath: file.relativePath,\n line: lineAt(file.content, reference.index),\n value: reference.name,\n });\n }\n }\n }\n if (target.sourceRoots === undefined || target.sourceRoots.length === 0) {\n addFinding(unresolved, {\n kind: 'unresolved',\n code: 'source-roots-not-declared',\n message: 'No component source roots were declared, so the check is story-local.',\n });\n }\n\n const fingerprints = files.map((file) => ({\n path: file.relativePath,\n sha256: createHash('sha256').update(file.content).digest('hex'),\n bytes: file.bytes,\n }));\n const status = violations.length > 0 ? 'not-ready' : unresolved.length > 0 ? 'incomplete' : 'ready';\n return {\n version: 1,\n status,\n target: { ...target, appPath: relativePath(root, appPath), storyPath: relativePath(root, storyPath) },\n fingerprints,\n violations,\n recognized,\n unresolved,\n coverage: {\n filesChecked: files.length,\n bytesChecked: counters.bytes,\n limits: { maxFiles: MAX_FILES, maxFileBytes: MAX_FILE_BYTES, maxTotalBytes: MAX_TOTAL_BYTES },\n classValidation: 'static-extraction-only',\n tokenValidation,\n },\n };\n}\n\nexport async function verifyDesignReport(reportPath: string, workspaceRoot: string): Promise<DesignVerificationResult> {\n const report = JSON.parse(await fs.promises.readFile(reportPath, 'utf8')) as DesignCheckReport;\n if (report.version !== 1 || !Array.isArray(report.fingerprints) || report.target === undefined) {\n throw new Error('The readiness report is not version 1.');\n }\n const root = await fs.promises.realpath(workspaceRoot);\n const stalePaths: string[] = [];\n for (const fingerprint of report.fingerprints) {\n try {\n const absolute = await canonicalPath(root, fingerprint.path, 'fingerprint path');\n const content = await fs.promises.readFile(absolute);\n const digest = createHash('sha256').update(content).digest('hex');\n if (digest !== fingerprint.sha256) stalePaths.push(fingerprint.path);\n } catch {\n stalePaths.push(fingerprint.path);\n }\n }\n try {\n const fresh = await checkDesignTarget(report.target, root);\n const evidence = (value: DesignCheckReport) =>\n JSON.stringify({\n status: value.status,\n target: value.target,\n fingerprints: value.fingerprints,\n violations: value.violations,\n recognized: value.recognized,\n unresolved: value.unresolved,\n coverage: value.coverage,\n });\n if (evidence(fresh) !== evidence(report)) stalePaths.push('[check]');\n } catch {\n stalePaths.push('[check]');\n }\n return { current: stalePaths.length === 0, stalePaths: [...new Set(stalePaths)], report };\n}\n"],"mappings":"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"}