@master/css-mcp 2.0.0-rc.76 → 2.0.0-rc.78

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.
@@ -0,0 +1,497 @@
1
+ import { getErrorMessage } from "./result.js";
2
+ import { readFile } from "node:fs/promises";
3
+ import { isAbsolute, relative, resolve } from "node:path";
4
+ import fg from "fast-glob";
5
+ import { existsSync } from "node:fs";
6
+ //#region src/contributor.ts
7
+ const REPORT_VERSION = 1;
8
+ const AUDIENCE = "master-css-repository-contributors";
9
+ const MASTER_REPO_MARKERS = [
10
+ "AGENTS.md",
11
+ ".ai/context/index.md",
12
+ ".ai/context/package-routing.md",
13
+ "packages/mcp/package.json"
14
+ ];
15
+ const PACKAGE_JSON_PATTERNS = [
16
+ "package.json",
17
+ "packages/*/package.json",
18
+ "site/package.json",
19
+ "shared/package.json",
20
+ "benchmarks/package.json",
21
+ "examples/*/package.json"
22
+ ];
23
+ const PACKAGE_JSON_IGNORE = [
24
+ "**/node_modules/**",
25
+ "**/dist/**",
26
+ "**/.next/**",
27
+ "**/.svelte-kit/**",
28
+ "**/.vercel/**",
29
+ "**/.turbo/**",
30
+ "**/.tsbuild/**",
31
+ "**/playwright/.cache/**"
32
+ ];
33
+ const HIGH_RISK_PACKAGES = {
34
+ engine: "CSS output and class generation",
35
+ preset: "default preset and generated manifest output",
36
+ compiler: "CSS-first manifest lowering",
37
+ runtime: "runtime hydration, CSSOM insertion, and DOM observation",
38
+ scanner: "static extraction and generated CSS scanner state",
39
+ source: "source class candidate extraction",
40
+ language: "language tokenization and source positions",
41
+ "language-service": "completion, hover, colors, and semantic token features",
42
+ "language-server": "LSP behavior",
43
+ lint: "framework-neutral class lint policy",
44
+ "eslint-plugin": "ESLint parser support, diagnostics, and autofix ranges"
45
+ };
46
+ const PACKAGE_COMMON_PACKS = {
47
+ schema: [".ai/context/package-boundaries.md"],
48
+ lexer: [".ai/context/package-boundaries.md"],
49
+ source: [".ai/context/package-boundaries.md", ".ai/context/testing.md"],
50
+ engine: [".ai/context/css-output.md", ".ai/context/performance.md"],
51
+ preset: [".ai/context/css-output.md"],
52
+ facade: [".ai/context/package-boundaries.md", ".ai/context/css-output.md"],
53
+ compiler: [".ai/context/css-output.md", ".ai/context/package-boundaries.md"],
54
+ project: [".ai/context/package-boundaries.md"],
55
+ integration: [".ai/context/package-boundaries.md"],
56
+ stylesheet: [".ai/context/css-output.md", ".ai/context/package-boundaries.md"],
57
+ runtime: [".ai/context/css-output.md", ".ai/context/performance.md"],
58
+ server: [".ai/context/css-output.md"],
59
+ scanner: [".ai/context/testing.md", ".ai/context/css-output.md"],
60
+ validator: [".ai/context/testing.md", ".ai/context/css-output.md"],
61
+ diagnostics: [".ai/context/testing.md", ".ai/context/package-boundaries.md"],
62
+ lint: [".ai/context/testing.md", ".ai/context/package-boundaries.md"],
63
+ vite: [".ai/context/package-boundaries.md", ".ai/context/css-output.md"],
64
+ webpack: [".ai/context/package-boundaries.md", ".ai/context/css-output.md"],
65
+ next: [".ai/context/package-boundaries.md", ".ai/context/css-output.md"],
66
+ cli: [".ai/context/testing.md", ".ai/context/package-boundaries.md"]
67
+ };
68
+ function unique(values) {
69
+ return [...new Set(values)];
70
+ }
71
+ function sortStrings(values) {
72
+ return unique(values.filter(Boolean)).sort((a, b) => a.localeCompare(b));
73
+ }
74
+ function isMasterCSSRepository(context) {
75
+ return MASTER_REPO_MARKERS.every((marker) => existsSync(resolve(context.root, marker)));
76
+ }
77
+ function normalizeRepoPath(context, filePath) {
78
+ const withoutPrefix = filePath.replace(/^[ab]\//, "");
79
+ const resolved = isAbsolute(withoutPrefix) ? resolve(withoutPrefix) : resolve(context.root, withoutPrefix);
80
+ context.assertContained(resolved);
81
+ const repoPath = relative(context.root, resolved).split(/[\\/]+/).join("/");
82
+ if (!repoPath || repoPath.startsWith("..")) throw new Error(`Path is outside the repository root: ${filePath}`);
83
+ return repoPath;
84
+ }
85
+ function extractDiffPaths(diff = "") {
86
+ const paths = [];
87
+ const push = (value) => {
88
+ if (!value || value === "/dev/null") return;
89
+ paths.push(value);
90
+ };
91
+ for (const line of diff.split("\n")) {
92
+ const gitMatch = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
93
+ if (gitMatch) {
94
+ push(gitMatch[1]);
95
+ push(gitMatch[2]);
96
+ continue;
97
+ }
98
+ const fileMatch = line.match(/^(?:---|\+\+\+) (?:a\/|b\/)?(.+)$/);
99
+ if (fileMatch) {
100
+ push(fileMatch[1]);
101
+ continue;
102
+ }
103
+ const renameMatch = line.match(/^rename (?:from|to) (.+)$/);
104
+ if (renameMatch) push(renameMatch[1]);
105
+ }
106
+ return paths;
107
+ }
108
+ function normalizeInputPaths(context, input = {}) {
109
+ return sortStrings([...input.paths ?? [], ...extractDiffPaths(input.diff)].map((path) => normalizeRepoPath(context, path)));
110
+ }
111
+ async function readJSON(filePath) {
112
+ try {
113
+ return JSON.parse(await readFile(filePath, "utf8"));
114
+ } catch {
115
+ return null;
116
+ }
117
+ }
118
+ function workspaceKind(path) {
119
+ if (path === ".") return "root";
120
+ if (path === "site") return "site";
121
+ if (path === "shared") return "shared";
122
+ if (path === "benchmarks") return "benchmarks";
123
+ if (path.startsWith("examples/")) return "example";
124
+ return "package";
125
+ }
126
+ function normalizeExports(exportsField) {
127
+ if (!exportsField) return [];
128
+ if (typeof exportsField === "string") return ["."];
129
+ if (Array.isArray(exportsField)) return ["."];
130
+ if (typeof exportsField === "object") return Object.keys(exportsField).sort();
131
+ return [];
132
+ }
133
+ function collectDependencies(pkg) {
134
+ return sortStrings([
135
+ ...Object.keys(pkg.dependencies ?? {}),
136
+ ...Object.keys(pkg.devDependencies ?? {}),
137
+ ...Object.keys(pkg.peerDependencies ?? {}),
138
+ ...Object.keys(pkg.optionalDependencies ?? {})
139
+ ]);
140
+ }
141
+ async function loadWorkspacePackages(context, includeExamples = true) {
142
+ const packageFiles = await fg(PACKAGE_JSON_PATTERNS, {
143
+ cwd: context.root,
144
+ ignore: includeExamples ? PACKAGE_JSON_IGNORE : [...PACKAGE_JSON_IGNORE, "examples/**"],
145
+ onlyFiles: true
146
+ });
147
+ const packages = [];
148
+ for (const filePath of packageFiles.sort((a, b) => a.localeCompare(b))) {
149
+ const pkg = await readJSON(resolve(context.root, filePath));
150
+ if (!pkg) continue;
151
+ const path = filePath === "package.json" ? "." : filePath.replace(/\/package\.json$/, "");
152
+ const aiPath = path === "." ? "AGENTS.md" : `${path}/AI.md`;
153
+ packages.push({
154
+ name: pkg.name || path,
155
+ path,
156
+ private: Boolean(pkg.private),
157
+ kind: workspaceKind(path),
158
+ scripts: Object.keys(pkg.scripts ?? {}).sort(),
159
+ exports: normalizeExports(pkg.exports),
160
+ dependencies: collectDependencies(pkg),
161
+ dependents: [],
162
+ aiNotes: existsSync(resolve(context.root, aiPath)) ? aiPath : null
163
+ });
164
+ }
165
+ const packageNames = new Set(packages.map((pkg) => pkg.name));
166
+ for (const pkg of packages) pkg.dependencies = pkg.dependencies.filter((dependency) => packageNames.has(dependency));
167
+ for (const pkg of packages) for (const dependency of pkg.dependencies) {
168
+ const dependencyPackage = packages.find((candidate) => candidate.name === dependency);
169
+ if (dependencyPackage) dependencyPackage.dependents.push(pkg.name);
170
+ }
171
+ for (const pkg of packages) pkg.dependents = sortStrings(pkg.dependents);
172
+ return packages;
173
+ }
174
+ function routePath(packages, path) {
175
+ const packageMatch = path.match(/^packages\/([^/]+)(?:\/|$)/);
176
+ if (packageMatch) {
177
+ const packagePath = `packages/${packageMatch[1]}`;
178
+ const pkg = packages.find((candidate) => candidate.path === packagePath);
179
+ return {
180
+ name: pkg?.name ?? packagePath,
181
+ path: packagePath,
182
+ kind: pkg?.kind ?? "package",
183
+ packageJSON: `${packagePath}/package.json`,
184
+ aiNotes: pkg?.aiNotes ?? null
185
+ };
186
+ }
187
+ if (path.startsWith("site/")) {
188
+ const pkg = packages.find((candidate) => candidate.path === "site");
189
+ return {
190
+ name: pkg?.name ?? "site",
191
+ path: "site",
192
+ kind: "site",
193
+ packageJSON: "site/package.json",
194
+ aiNotes: pkg?.aiNotes ?? null
195
+ };
196
+ }
197
+ if (path.startsWith("shared/")) return {
198
+ name: packages.find((candidate) => candidate.path === "shared")?.name ?? "shared",
199
+ path: "shared",
200
+ kind: "shared",
201
+ packageJSON: "shared/package.json",
202
+ aiNotes: null
203
+ };
204
+ if (path.startsWith("benchmarks/")) return {
205
+ name: packages.find((candidate) => candidate.path === "benchmarks")?.name ?? "benchmarks",
206
+ path: "benchmarks",
207
+ kind: "benchmarks",
208
+ packageJSON: "benchmarks/package.json",
209
+ aiNotes: null
210
+ };
211
+ const exampleMatch = path.match(/^examples\/([^/]+)(?:\/|$)/);
212
+ if (exampleMatch) {
213
+ const packagePath = `examples/${exampleMatch[1]}`;
214
+ return {
215
+ name: packages.find((candidate) => candidate.path === packagePath)?.name ?? packagePath,
216
+ path: packagePath,
217
+ kind: "example",
218
+ packageJSON: `${packagePath}/package.json`,
219
+ aiNotes: null
220
+ };
221
+ }
222
+ if (path === "AGENTS.md" || path.startsWith(".ai/") || path.startsWith(".github/prompts/")) return {
223
+ name: "agent-docs",
224
+ path: ".ai",
225
+ kind: "agent-docs",
226
+ aiNotes: null
227
+ };
228
+ const rootPackage = packages.find((candidate) => candidate.path === ".");
229
+ return {
230
+ name: rootPackage?.name ?? "repo-root",
231
+ path: ".",
232
+ kind: "repo-root",
233
+ packageJSON: rootPackage ? "package.json" : void 0,
234
+ aiNotes: rootPackage?.aiNotes ?? null
235
+ };
236
+ }
237
+ function routePaths(packages, paths) {
238
+ const routed = /* @__PURE__ */ new Map();
239
+ for (const path of paths) {
240
+ const route = routePath(packages, path);
241
+ const key = route.path;
242
+ const existing = routed.get(key);
243
+ if (existing) existing.matchedPaths.push(path);
244
+ else routed.set(key, {
245
+ ...route,
246
+ matchedPaths: [path]
247
+ });
248
+ }
249
+ return [...routed.values()].map((route) => ({
250
+ ...route,
251
+ matchedPaths: sortStrings(route.matchedPaths)
252
+ }));
253
+ }
254
+ function taskPacks(task = "") {
255
+ const normalized = task.toLowerCase();
256
+ const packs = [];
257
+ if (/\b(review|pr)\b/.test(normalized)) packs.push(".ai/context/review.md");
258
+ if (/\b(test|coverage|fixture|snapshot)\b/.test(normalized)) packs.push(".ai/context/testing.md");
259
+ if (/\b(refactor|rewrite|cleanup|migration|re-architecture)\b/.test(normalized)) packs.push(".ai/context/refactor.md");
260
+ if (/\b(css output|generated css|cascade|layer|selector|at-rule|variable|mode|priority|class)\b/.test(normalized)) packs.push(".ai/context/css-output.md");
261
+ if (/\b(performance|benchmark|slow|hot path|memory|cpu)\b/.test(normalized)) packs.push(".ai/context/performance.md");
262
+ if (/\b(doc|docs|readme|site|guide)\b/.test(normalized)) packs.push(".ai/context/docs.md");
263
+ if (/\b(bug|fix|regression|error|failing|failure)\b/.test(normalized)) packs.push(".ai/context/bugfix.md");
264
+ if (/\b(package|boundary|dependency|export|public api|cycle)\b/.test(normalized)) packs.push(".ai/context/package-boundaries.md");
265
+ return packs;
266
+ }
267
+ function pathPacks(paths) {
268
+ const packs = [];
269
+ if (paths.length) packs.push(".ai/context/package-routing.md");
270
+ if (paths.some((path) => path.includes("/tests/") || path.endsWith(".test.ts") || path.endsWith(".test.js"))) packs.push(".ai/context/testing.md");
271
+ if (paths.some((path) => path.startsWith("site/") || path.endsWith("README.md") || path.endsWith(".mdx"))) packs.push(".ai/context/docs.md");
272
+ if (paths.some((path) => path.endsWith("package.json") || path === "pnpm-workspace.yaml" || path.includes("tsconfig"))) packs.push(".ai/context/package-boundaries.md");
273
+ return packs;
274
+ }
275
+ function packagePacks(routes) {
276
+ const packs = [];
277
+ for (const route of routes) {
278
+ const packageName = route.path.match(/^packages\/([^/]+)$/)?.[1];
279
+ if (packageName) {
280
+ packs.push(...PACKAGE_COMMON_PACKS[packageName] ?? []);
281
+ if (packageName.startsWith("language")) packs.push(".ai/context/testing.md");
282
+ if (packageName.startsWith("eslint-")) packs.push(".ai/context/testing.md");
283
+ }
284
+ if (route.kind === "site") packs.push(".ai/context/docs.md");
285
+ if (route.kind === "shared") packs.push(".ai/context/package-boundaries.md");
286
+ }
287
+ return packs;
288
+ }
289
+ function pushRisk(risks, risk) {
290
+ const existing = risks.find((candidate) => candidate.id === risk.id);
291
+ if (existing) {
292
+ existing.paths = sortStrings([...existing.paths, ...risk.paths]);
293
+ return;
294
+ }
295
+ risks.push({
296
+ ...risk,
297
+ paths: sortStrings(risk.paths)
298
+ });
299
+ }
300
+ function detectRisks(paths, routes) {
301
+ const risks = [];
302
+ for (const route of routes) {
303
+ const packageName = route.path.match(/^packages\/([^/]+)$/)?.[1];
304
+ if (packageName && HIGH_RISK_PACKAGES[packageName]) pushRisk(risks, {
305
+ id: packageName === "engine" || packageName === "preset" || packageName === "compiler" ? "css-output" : packageName,
306
+ severity: packageName === "engine" || packageName === "runtime" || packageName === "compiler" ? "high" : "warning",
307
+ reason: HIGH_RISK_PACKAGES[packageName],
308
+ paths: route.matchedPaths
309
+ });
310
+ }
311
+ if (paths.some((path) => path.endsWith("generated.css") || path.endsWith(".snap") || path.includes("/fixtures/"))) pushRisk(risks, {
312
+ id: "fixtures-or-snapshots",
313
+ severity: "high",
314
+ reason: "Fixture, snapshot, or generated CSS changes must be intentional and covered by tests.",
315
+ paths: paths.filter((path) => path.endsWith("generated.css") || path.endsWith(".snap") || path.includes("/fixtures/"))
316
+ });
317
+ if (paths.some((path) => path.endsWith("package.json") || path === "pnpm-workspace.yaml" || path.includes("/src/index.ts"))) pushRisk(risks, {
318
+ id: "public-api-or-package-boundary",
319
+ severity: "warning",
320
+ reason: "Package exports, scripts, dependencies, or public entrypoints may affect downstream consumers.",
321
+ paths: paths.filter((path) => path.endsWith("package.json") || path === "pnpm-workspace.yaml" || path.includes("/src/index.ts"))
322
+ });
323
+ if (paths.some((path) => path.startsWith("site/") || path.endsWith("README.md") || path.endsWith(".mdx"))) pushRisk(risks, {
324
+ id: "docs",
325
+ severity: "info",
326
+ reason: "Public documentation should be verified against source behavior.",
327
+ paths: paths.filter((path) => path.startsWith("site/") || path.endsWith("README.md") || path.endsWith(".mdx"))
328
+ });
329
+ if (paths.some((path) => path.startsWith(".ai/") || path === "AGENTS.md" || path.startsWith(".github/prompts/"))) pushRisk(risks, {
330
+ id: "agent-instructions",
331
+ severity: "info",
332
+ reason: "AI-facing routing changes should stay consistent with context pack rules.",
333
+ paths: paths.filter((path) => path.startsWith(".ai/") || path === "AGENTS.md" || path.startsWith(".github/prompts/"))
334
+ });
335
+ if (routes.length > 1) pushRisk(risks, {
336
+ id: "multi-package",
337
+ severity: "warning",
338
+ reason: "Multiple ownership areas changed; package-boundary context and broader validation may be needed.",
339
+ paths
340
+ });
341
+ return risks.sort((a, b) => {
342
+ const order = {
343
+ high: 0,
344
+ warning: 1,
345
+ info: 2
346
+ };
347
+ return order[a.severity] - order[b.severity] || a.id.localeCompare(b.id);
348
+ });
349
+ }
350
+ function contextFiles(paths, routes, risks, task) {
351
+ const files = [
352
+ "AGENTS.md",
353
+ ".ai/context/index.md",
354
+ ...pathPacks(paths),
355
+ ...packagePacks(routes),
356
+ ...taskPacks(task),
357
+ ...routes.flatMap((route) => [route.packageJSON, route.aiNotes].filter(Boolean))
358
+ ];
359
+ if (risks.some((risk) => risk.severity === "high" || [
360
+ "public-api-or-package-boundary",
361
+ "multi-package",
362
+ "runtime",
363
+ "scanner",
364
+ "source",
365
+ "language",
366
+ "language-service",
367
+ "language-server",
368
+ "lint",
369
+ "eslint-plugin"
370
+ ].includes(risk.id))) files.push(".ai/context/accuracy-guardrails.md");
371
+ return sortStrings(files);
372
+ }
373
+ function commandReason(command, reason) {
374
+ return {
375
+ command,
376
+ reason
377
+ };
378
+ }
379
+ function validationCommands(packages, routes, risks) {
380
+ const commands = [];
381
+ const packageByPath = new Map(packages.map((pkg) => [pkg.path, pkg]));
382
+ for (const route of routes) {
383
+ const pkg = packageByPath.get(route.path);
384
+ if (!pkg || pkg.kind === "root" || pkg.kind === "example") continue;
385
+ if (pkg.scripts.includes("test")) commands.push(commandReason(`pnpm --filter ${pkg.name} test`, `Run ${pkg.name} focused tests.`));
386
+ if (pkg.scripts.includes("e2e") && risks.some((risk) => risk.id === "runtime" || risk.id === "css-output")) commands.push(commandReason(`pnpm --filter ${pkg.name} e2e`, `Run ${pkg.name} browser/e2e coverage for high-risk behavior.`));
387
+ if (pkg.scripts.includes("lint")) commands.push(commandReason(`pnpm --filter ${pkg.name} lint`, `Package-local lint is required when ${pkg.name} changes.`));
388
+ if (pkg.scripts.includes("type-check") && risks.some((risk) => risk.id === "public-api-or-package-boundary")) commands.push(commandReason(`pnpm --filter ${pkg.name} type-check`, `Check public types and package boundary changes in ${pkg.name}.`));
389
+ if (pkg.scripts.includes("build") && risks.some((risk) => risk.id === "public-api-or-package-boundary")) commands.push(commandReason(`pnpm --filter ${pkg.name} build`, `Build ${pkg.name} after public API or export changes.`));
390
+ if (pkg.kind === "site" && pkg.scripts.includes("prepare-app")) commands.push(commandReason("pnpm --filter site prepare-app", "Refresh generated site metadata for docs changes."));
391
+ }
392
+ if (routes.some((route) => route.kind === "agent-docs")) commands.push(commandReason("pnpm run test:docs-consistency", "Validate AI-facing context pack routing consistency."));
393
+ return unique(commands.map((entry) => JSON.stringify(entry))).map((entry) => JSON.parse(entry));
394
+ }
395
+ function routeStatus(context) {
396
+ const supported = isMasterCSSRepository(context);
397
+ return {
398
+ status: supported ? "loaded" : "limited",
399
+ reason: supported ? "Master CSS repository markers were found." : "Contributor routing is optimized for the Master CSS monorepo; generic workspaces return limited package data."
400
+ };
401
+ }
402
+ async function getPackageGraph(context, input = {}) {
403
+ const support = routeStatus(context);
404
+ const packages = await loadWorkspacePackages(context, input.includeExamples ?? true);
405
+ const filtered = input.packageName ? packages.filter((pkg) => pkg.name === input.packageName || pkg.path === input.packageName) : packages;
406
+ return {
407
+ version: REPORT_VERSION,
408
+ audience: AUDIENCE,
409
+ root: context.root,
410
+ ...support,
411
+ packages: filtered,
412
+ summary: {
413
+ packages: filtered.length,
414
+ workspacePackages: filtered.filter((pkg) => pkg.kind === "package").length,
415
+ examples: filtered.filter((pkg) => pkg.kind === "example").length
416
+ }
417
+ };
418
+ }
419
+ async function buildContributorResult(context, input = {}) {
420
+ const support = routeStatus(context);
421
+ const packages = await loadWorkspacePackages(context);
422
+ const paths = normalizeInputPaths(context, input);
423
+ const routes = routePaths(packages, paths);
424
+ const isLoaded = support.status === "loaded";
425
+ const risks = isLoaded ? detectRisks(paths, routes) : [];
426
+ return {
427
+ version: REPORT_VERSION,
428
+ audience: AUDIENCE,
429
+ root: context.root,
430
+ ...support,
431
+ inputs: {
432
+ task: input.task ?? null,
433
+ paths,
434
+ hasDiff: Boolean(input.diff)
435
+ },
436
+ affectedPackages: routes,
437
+ context: {
438
+ files: isLoaded ? contextFiles(paths, routes, risks, input.task) : [],
439
+ note: isLoaded ? "Read these files as routing inputs; source and nearby tests remain the final authority." : "Contributor context routing is limited outside the Master CSS repository; no Master CSS repo-specific context files are recommended."
440
+ },
441
+ risks,
442
+ validation: { commands: isLoaded ? validationCommands(packages, routes, risks) : [] }
443
+ };
444
+ }
445
+ async function getRepoContext(context, input = {}) {
446
+ try {
447
+ return await buildContributorResult(context, input);
448
+ } catch (error) {
449
+ return {
450
+ version: REPORT_VERSION,
451
+ audience: AUDIENCE,
452
+ root: context.root,
453
+ status: "error",
454
+ error: getErrorMessage(error)
455
+ };
456
+ }
457
+ }
458
+ async function getChangeImpact(context, input = {}) {
459
+ const result = await getRepoContext(context, input);
460
+ if (result.status === "error") return result;
461
+ return {
462
+ version: REPORT_VERSION,
463
+ audience: AUDIENCE,
464
+ root: context.root,
465
+ status: result.status,
466
+ reason: result.reason,
467
+ inputs: result.inputs,
468
+ affectedPackages: result.affectedPackages,
469
+ risks: result.risks,
470
+ summary: {
471
+ riskCount: result.risks.length,
472
+ highRisk: result.risks.filter((risk) => risk.severity === "high").length,
473
+ packageCount: result.affectedPackages.length
474
+ }
475
+ };
476
+ }
477
+ async function getTestRouter(context, input = {}) {
478
+ const result = await getRepoContext(context, input);
479
+ if (result.status === "error") return result;
480
+ return {
481
+ version: REPORT_VERSION,
482
+ audience: AUDIENCE,
483
+ root: context.root,
484
+ status: result.status,
485
+ reason: result.reason,
486
+ inputs: result.inputs,
487
+ affectedPackages: result.affectedPackages,
488
+ validation: result.validation,
489
+ risks: result.risks.map((risk) => ({
490
+ id: risk.id,
491
+ severity: risk.severity,
492
+ reason: risk.reason
493
+ }))
494
+ };
495
+ }
496
+ //#endregion
497
+ export { getChangeImpact, getPackageGraph, getRepoContext, getTestRouter };
@@ -0,0 +1,133 @@
1
+ import MasterCSSMCPContext from "./context.js";
2
+
3
+ //#region src/directives.d.ts
4
+ interface InspectDirectivesOptions {
5
+ content?: string;
6
+ filePath?: string;
7
+ entryPath?: string;
8
+ preserveNativeCSS?: boolean;
9
+ }
10
+ declare function inspectDirectives(context: MasterCSSMCPContext, options: InspectDirectivesOptions): Promise<{
11
+ diagnostics: {
12
+ code: string;
13
+ severity: "warning";
14
+ message: string;
15
+ source: string;
16
+ sourceKind: string;
17
+ filePath: string;
18
+ }[];
19
+ summary: {
20
+ status: string;
21
+ directives: number;
22
+ classNames: number;
23
+ nativeClassNames: number;
24
+ dependencies: number;
25
+ warnings: number;
26
+ cssBytes: number;
27
+ errors?: undefined;
28
+ };
29
+ manifest: {
30
+ settings: import("@master/css-engine").MasterCSSManifestSettings;
31
+ counts: {
32
+ variables: number;
33
+ variableNamespaces: number;
34
+ utilities: number;
35
+ variants: number;
36
+ atRules: number;
37
+ breakpointAtRules: number;
38
+ containerAtRules: number;
39
+ selectors: number;
40
+ animations: number;
41
+ };
42
+ };
43
+ directives: {
44
+ manifestInput: {
45
+ keys: string[];
46
+ counts: {
47
+ settings: number;
48
+ variables: number;
49
+ utilities: number;
50
+ variants: number;
51
+ atRules: number;
52
+ selectors: number;
53
+ animations: number;
54
+ };
55
+ };
56
+ classNames: string[];
57
+ nativeClassNames: string[];
58
+ styleDefinitions: number;
59
+ extractionPolicy: import("@master/css-schema/css-directives").CSSDirectiveExtractionPolicy;
60
+ };
61
+ css: {
62
+ bytes: number;
63
+ nativeBytes: number;
64
+ generatedBytes: number;
65
+ };
66
+ dependencies: string[];
67
+ warnings: string[];
68
+ version: number;
69
+ root: string;
70
+ status: string;
71
+ input: {
72
+ filePath: string;
73
+ name: string;
74
+ mode: string;
75
+ };
76
+ directiveEntries: {
77
+ name: import("@master/css-lexer").CSSDirectiveRangeName;
78
+ range: {
79
+ start: number;
80
+ end: number;
81
+ };
82
+ loc: {
83
+ start: import("vscode-languageserver-textdocument").Position;
84
+ end: import("vscode-languageserver-textdocument").Position;
85
+ };
86
+ prelude: string;
87
+ hasBlock: boolean;
88
+ quotedStrings: number;
89
+ }[];
90
+ } | {
91
+ version: number;
92
+ root: string;
93
+ status: string;
94
+ input: {
95
+ filePath: string;
96
+ mode: string;
97
+ name?: undefined;
98
+ };
99
+ directiveEntries: {
100
+ name: import("@master/css-lexer").CSSDirectiveRangeName;
101
+ range: {
102
+ start: number;
103
+ end: number;
104
+ };
105
+ loc: {
106
+ start: import("vscode-languageserver-textdocument").Position;
107
+ end: import("vscode-languageserver-textdocument").Position;
108
+ };
109
+ prelude: string;
110
+ hasBlock: boolean;
111
+ quotedStrings: number;
112
+ }[];
113
+ diagnostics: {
114
+ code: string;
115
+ severity: "error";
116
+ message: string;
117
+ source: string;
118
+ sourceKind: string;
119
+ filePath: string;
120
+ }[];
121
+ summary: {
122
+ status: string;
123
+ directives: number;
124
+ classNames: number;
125
+ nativeClassNames: number;
126
+ dependencies: number;
127
+ warnings: number;
128
+ errors: number;
129
+ cssBytes: number;
130
+ };
131
+ }>;
132
+ //#endregion
133
+ export { InspectDirectivesOptions, inspectDirectives };