cascivo 0.6.0 → 0.6.2

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.
@@ -19,21 +19,40 @@ function buildContract(input) {
19
19
  }
20
20
  const contentNames = /* @__PURE__ */ new Set();
21
21
  for (const c of input.context.components) if (c.intent?.content) contentNames.add(c.name);
22
- const components = /* @__PURE__ */ new Map();
22
+ const byName = /* @__PURE__ */ new Map();
23
23
  for (const entry of input.registry.components) {
24
24
  const meta = entry.meta;
25
25
  if (!meta?.name) continue;
26
- const props = (meta.props ?? []).map((p) => ({
27
- name: p.name,
28
- type: p.type ?? "unknown",
29
- required: p.required === true
30
- }));
31
- const requiredProps = props.filter((p) => p.required).map((p) => p.name);
32
- components.set(meta.name, {
33
- props,
26
+ const list = byName.get(meta.name);
27
+ if (list) list.push(meta);
28
+ else byName.set(meta.name, [meta]);
29
+ }
30
+ const components = /* @__PURE__ */ new Map();
31
+ for (const [name, metas] of byName) {
32
+ const props = /* @__PURE__ */ new Map();
33
+ for (const meta of metas) for (const p of meta.props ?? []) {
34
+ const required = (props.get(p.name)?.required ?? true) && p.required === true;
35
+ props.set(p.name, {
36
+ name: p.name,
37
+ type: p.type ?? "unknown",
38
+ required
39
+ });
40
+ }
41
+ if (metas.length > 1) {
42
+ for (const [propName, info] of props) if (!metas.every((m) => (m.props ?? []).some((p) => p.name === propName))) props.set(propName, {
43
+ ...info,
44
+ required: false
45
+ });
46
+ }
47
+ const all = [...props.values()];
48
+ const requiredProps = all.filter((p) => p.required && p.name !== "children").map((p) => p.name);
49
+ components.set(name, {
50
+ props: all,
34
51
  requiredProps,
35
52
  hasRequiredProps: requiredProps.length > 0,
36
- hasContent: contentNames.has(meta.name)
53
+ requiresChildren: all.some((p) => p.name === "children" && p.required),
54
+ hasContent: contentNames.has(name),
55
+ entryCount: metas.length
37
56
  });
38
57
  }
39
58
  return {
@@ -96,6 +115,42 @@ function classify(value, contract) {
96
115
  };
97
116
  }
98
117
  /**
118
+ * Character ranges covered by a JSX `style={{ … }}` object.
119
+ *
120
+ * The inline-style scan used to run over every `prop: 'value'` pair in a `.tsx` file, so a
121
+ * plain data object was audited as if it were CSS: a `DataTable` column's
122
+ * `width: '3rem'` was reported as a hardcoded value that should be `--cascivo-space-12`.
123
+ * A spacing token is not the right unit for a table column, and the object was never a
124
+ * style in the first place — the rule was matching the literal, not the context.
125
+ */
126
+ function styleObjectRanges(source) {
127
+ const ranges = [];
128
+ for (const m of source.matchAll(/style\s*=\s*\{/g)) {
129
+ let depth = 0;
130
+ let quote = "";
131
+ for (let i = m.index + m[0].length - 1; i < source.length; i++) {
132
+ const ch = source[i];
133
+ if (quote) {
134
+ if (ch === quote) quote = "";
135
+ continue;
136
+ }
137
+ if (ch === "\"" || ch === "'" || ch === "`") {
138
+ quote = ch;
139
+ continue;
140
+ }
141
+ if (ch === "{") depth++;
142
+ else if (ch === "}") {
143
+ depth--;
144
+ if (depth === 0) {
145
+ ranges.push([m.index, i]);
146
+ break;
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return ranges;
152
+ }
153
+ /**
99
154
  * Detect literal color/size values in CSS declarations and TSX inline styles
100
155
  * that exactly match a known cascade token. Heuristic, line-based — no full
101
156
  * CSS/JS parse. Values with no catalog match are NOT flagged (arbitrary brand
@@ -104,6 +159,14 @@ function classify(value, contract) {
104
159
  function findCssLiteralViolations(source, filename, contract) {
105
160
  const findings = [];
106
161
  const lines = source.split("\n");
162
+ const styleRanges = styleObjectRanges(source);
163
+ const lineStarts = [];
164
+ let offset = 0;
165
+ for (const line of lines) {
166
+ lineStarts.push(offset);
167
+ offset += line.length + 1;
168
+ }
169
+ const inStyleObject = (absolute) => styleRanges.some(([start, end]) => absolute >= start && absolute <= end);
107
170
  const cssDecl = /(^|[;{\s])([a-z-]+)\s*:\s*([^;}{]+?)\s*(?=[;}]|$)/gi;
108
171
  const inlineDecl = /([A-Za-z][A-Za-z]*)\s*:\s*(['"])([^'"]+)\2/g;
109
172
  for (let i = 0; i < lines.length; i++) {
@@ -133,6 +196,7 @@ function findCssLiteralViolations(source, filename, contract) {
133
196
  if (m[1] === void 0 || m[3] === void 0) continue;
134
197
  const prop = INLINE_PROP_MAP[m[1]];
135
198
  if (!prop) continue;
199
+ if (!inStyleObject((lineStarts[i] ?? 0) + (m.index ?? 0))) continue;
136
200
  const rawValue = m[3].trim();
137
201
  if (!isLiteralValue(rawValue)) continue;
138
202
  const key = `${prop}|${rawValue}`;
@@ -232,17 +296,37 @@ function isPassthrough(prop) {
232
296
  if (/^on[A-Z]/.test(prop)) return true;
233
297
  return false;
234
298
  }
235
- /** Names imported from @cascivo/react in this source. */
299
+ /**
300
+ * Local JSX names bound to a cascade component, mapped to the contract name they refer to.
301
+ *
302
+ * Two rules, both learned from false positives on correct code:
303
+ *
304
+ * 1. **Track the LOCAL binding, not the imported name.** `import { Link as CascadeLink }`
305
+ * used to register `Link`, so the scan then matched the *router's* `<Link to=…>` and
306
+ * reported `to` as an unknown prop. For a router-based app that collateral is close to
307
+ * guaranteed.
308
+ * 2. **Never audit a name this file also imports from somewhere else.** A bare-name clash
309
+ * (`Link` from `@tanstack/react-router`) must not be audited against cascivo's contract
310
+ * even when nothing is aliased.
311
+ */
236
312
  function importedCascadeComponents(source) {
237
- const names = /* @__PURE__ */ new Set();
238
- for (const m of source.matchAll(/import\s*\{([^}]*)\}\s*from\s*['"]@cascivo\/react['"]/g)) {
239
- const group = m[1];
240
- if (group === void 0) continue;
313
+ const names = /* @__PURE__ */ new Map();
314
+ const foreign = /* @__PURE__ */ new Set();
315
+ for (const m of source.matchAll(/import\s*(?:type\s*)?\{([^}]*)\}\s*from\s*['"]([^'"]+)['"]/g)) {
316
+ const [, group, specifier] = m;
317
+ if (group === void 0 || specifier === void 0) continue;
318
+ const isCascade = specifier === "@cascivo/react";
241
319
  for (const raw of group.split(",")) {
242
- const name = raw.trim().split(/\s+as\s+/)[0]?.trim();
243
- if (name) names.add(name);
320
+ const parts = raw.trim().split(/\s+as\s+/);
321
+ const imported = parts[0]?.trim().replace(/^type\s+/, "");
322
+ const local = (parts[1] ?? parts[0])?.trim();
323
+ if (!imported || !local) continue;
324
+ if (isCascade) names.set(local, imported);
325
+ else foreign.add(local);
244
326
  }
245
327
  }
328
+ for (const m of source.matchAll(/import\s+(\w+)\s*(?:,\s*\{[^}]*\})?\s*from\s*['"]([^'"]+)['"]/g)) if (m[2] !== "@cascivo/react" && m[1]) foreign.add(m[1]);
329
+ for (const local of foreign) names.delete(local);
246
330
  return names;
247
331
  }
248
332
  function findOpeningTags(source, comp) {
@@ -276,11 +360,13 @@ function findOpeningTags(source, comp) {
276
360
  attrs += ch;
277
361
  }
278
362
  if (!closed) continue;
279
- const cleanAttrs = attrs.replace(/\/$/, "");
363
+ const selfClosing = /\/\s*$/.test(attrs);
364
+ const cleanAttrs = attrs.replace(/\/\s*$/, "");
280
365
  tags.push({
281
366
  attrs: cleanAttrs,
282
367
  index: start,
283
- hasSpread: /\{\s*\.\.\./.test(cleanAttrs)
368
+ hasSpread: /\{\s*\.\.\./.test(cleanAttrs),
369
+ selfClosing
284
370
  });
285
371
  }
286
372
  return tags;
@@ -343,8 +429,8 @@ function lineOf(source, index) {
343
429
  function findJsxPropViolations(source, filename, contract) {
344
430
  const findings = [];
345
431
  const tracked = importedCascadeComponents(source);
346
- for (const comp of tracked) {
347
- const info = contract.components.get(comp);
432
+ for (const [comp, contractName] of tracked) {
433
+ const info = contract.components.get(contractName);
348
434
  if (!info) continue;
349
435
  const known = new Set(info.props.map((p) => p.name));
350
436
  for (const tag of findOpeningTags(source, comp)) {
@@ -395,8 +481,8 @@ function looksLikeProse(text) {
395
481
  function findRawStringViolations(source, filename, contract) {
396
482
  const findings = [];
397
483
  const tracked = importedCascadeComponents(source);
398
- for (const comp of tracked) {
399
- if (!contract.components.get(comp)?.hasContent) continue;
484
+ for (const [comp, contractName] of tracked) {
485
+ if (!contract.components.get(contractName)?.hasContent) continue;
400
486
  for (const tag of findOpeningTags(source, comp)) {
401
487
  const openEnd = source.indexOf(">", tag.index);
402
488
  if (openEnd === -1) continue;
@@ -427,9 +513,9 @@ function findRawStringViolations(source, filename, contract) {
427
513
  function findRequiredPropViolations(source, filename, contract) {
428
514
  const findings = [];
429
515
  const tracked = importedCascadeComponents(source);
430
- for (const comp of tracked) {
431
- const info = contract.components.get(comp);
432
- if (!info?.hasRequiredProps) continue;
516
+ for (const [comp, contractName] of tracked) {
517
+ const info = contract.components.get(contractName);
518
+ if (!info) continue;
433
519
  for (const tag of findOpeningTags(source, comp)) {
434
520
  if (tag.hasSpread) continue;
435
521
  const present = new Set(extractAttrNames(tag.attrs));
@@ -446,6 +532,15 @@ function findRequiredPropViolations(source, filename, contract) {
446
532
  message: `<${comp}> requires "${req}"`
447
533
  });
448
534
  }
535
+ if (info.requiresChildren && tag.selfClosing && !present.has("children")) findings.push({
536
+ file: filename,
537
+ line,
538
+ component: comp,
539
+ prop: "children",
540
+ level: "error",
541
+ rule: "missing-prop",
542
+ message: `<${comp} /> is self-closing but requires children`
543
+ });
449
544
  }
450
545
  }
451
546
  return findings;
@@ -959,4 +1054,4 @@ async function audit(args, _config) {
959
1054
  //#endregion
960
1055
  export { audit };
961
1056
 
962
- //# sourceMappingURL=audit-CX-ifnQT.mjs.map
1057
+ //# sourceMappingURL=audit-Cn6HJkuo.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-Cn6HJkuo.mjs","names":["MESSAGE"],"sources":["../src/utils/contract-pure.ts","../src/audit-ai/css-literals.ts","../src/audit-ai/jsx-props.ts","../src/audit-ai/raw-strings.ts","../src/audit-ai/required-props.ts","../src/utils/css-layers.ts","../src/audit-ai/unlayered.ts","../src/audit-ai/vendor-css.ts","../src/audit-ai/suppress.ts","../src/utils/contract.ts","../src/commands/audit.ts"],"sourcesContent":["export interface PropInfo {\n name: string\n type: string\n required: boolean\n}\n\nexport interface ComponentInfo {\n props: PropInfo[]\n /** True if any prop has required: true */\n hasRequiredProps: boolean\n /**\n * Props that have required: true, EXCLUDING `children`. A component's children arrive as\n * JSX element content, not as an attribute, and the audit's prop scan only ever sees the\n * opening tag — so a required `children` reported every correct usage as missing. It is\n * checked separately, via the self-closing flag.\n */\n requiredProps: string[]\n /** True when the component's manifest marks `children` required. */\n requiresChildren: boolean\n /** True if the component declares user-facing chrome text (intent.content) */\n hasContent: boolean\n /**\n * Number of distinct registry entries that share this display name. More than one means\n * the name is ambiguous (`AppShell` is both the npm component and the copy-paste\n * `layout/app-shell`, with different prop surfaces) and the props below are the UNION —\n * see `buildContract`.\n */\n entryCount: number\n}\n\nexport interface Contract {\n /** Map from normalized color/size value → token names */\n tokensByValue: Map<string, string[]>\n /** Map from component name (PascalCase) → component info */\n components: Map<string, ComponentInfo>\n}\n\ninterface TokenEntry {\n name: string\n resolvedDefault: string | null\n}\n\ninterface CatalogFile {\n tokens: TokenEntry[]\n}\n\ninterface RegistryPropMeta {\n name: string\n type?: string\n required?: boolean\n}\n\ninterface RegistryComponentMeta {\n name: string\n props?: RegistryPropMeta[]\n}\n\ninterface RegistryEntry {\n meta?: RegistryComponentMeta\n}\n\ninterface RegistryFile {\n components: RegistryEntry[]\n}\n\ninterface ContextComponentEntry {\n name: string\n intent?: { content?: unknown }\n}\n\ninterface ContextFile {\n components: ContextComponentEntry[]\n}\n\nexport interface BuildContractInput {\n catalog: CatalogFile\n registry: RegistryFile\n context: ContextFile\n}\n\n/** Normalize a color/size value for catalog comparison: lowercase, strip spaces. */\nexport function normalizeValue(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, '')\n}\n\n/** Pure builder — assemble a Contract from already-parsed JSON. Testable without fs. */\nexport function buildContract(input: BuildContractInput): Contract {\n const tokensByValue = new Map<string, string[]>()\n for (const token of input.catalog.tokens) {\n if (token.resolvedDefault == null) continue\n const key = normalizeValue(token.resolvedDefault)\n const list = tokensByValue.get(key)\n if (list) list.push(token.name)\n else tokensByValue.set(key, [token.name])\n }\n\n const contentNames = new Set<string>()\n for (const c of input.context.components) {\n if (c.intent?.content) contentNames.add(c.name)\n }\n\n // Several registry entries share a display name — `AppShell` is both the npm component\n // (props: header/nav/children/…) and the copy-paste `layout/app-shell` (props:\n // header/sideNav/aside/persistKey/…), and `Calendar` is both the component and the chart.\n // Keying a Map by name meant the last one won, so every adopter of `@cascivo/react`'s\n // AppShell was audited against a component they don't have: `nav` came back as an\n // \"unknown prop\" and `sideNav` was the only recognised slot.\n //\n // A JSX name alone cannot tell the entries apart, so the contract merges them: props are\n // the UNION (no false `unknown-prop`), and `required` only survives when EVERY entry with\n // that name requires it (no false `missing-prop`).\n const byName = new Map<string, RegistryComponentMeta[]>()\n for (const entry of input.registry.components) {\n const meta = entry.meta\n if (!meta?.name) continue\n const list = byName.get(meta.name)\n if (list) list.push(meta)\n else byName.set(meta.name, [meta])\n }\n\n const components = new Map<string, ComponentInfo>()\n for (const [name, metas] of byName) {\n const props = new Map<string, PropInfo>()\n for (const meta of metas) {\n for (const p of meta.props ?? []) {\n const existing = props.get(p.name)\n // Required only if required in every entry that declares the prop.\n const required = (existing?.required ?? true) && p.required === true\n props.set(p.name, { name: p.name, type: p.type ?? 'unknown', required })\n }\n }\n // A prop absent from one of the entries can't be required overall.\n if (metas.length > 1) {\n for (const [propName, info] of props) {\n const inEvery = metas.every((m) => (m.props ?? []).some((p) => p.name === propName))\n if (!inEvery) props.set(propName, { ...info, required: false })\n }\n }\n const all = [...props.values()]\n // `children` is element content, not an attribute — tracked separately.\n const requiredProps = all.filter((p) => p.required && p.name !== 'children').map((p) => p.name)\n components.set(name, {\n props: all,\n requiredProps,\n hasRequiredProps: requiredProps.length > 0,\n requiresChildren: all.some((p) => p.name === 'children' && p.required),\n hasContent: contentNames.has(name),\n entryCount: metas.length,\n })\n }\n\n return { tokensByValue, components }\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport { normalizeValue } from '../utils/contract-pure.js'\n\nexport interface LiteralFinding {\n file: string\n line: number\n property: string\n value: string\n level: 'error' | 'warn' | 'info'\n rule: 'hardcoded-value'\n /** only when exactly one catalog match */\n suggestedToken?: string\n /** when multiple catalog matches → info */\n allMatches?: string[]\n}\n\n/** Visual CSS properties whose literal values should be tokens. */\nconst VISUAL_PROPS = new Set([\n 'color',\n 'background',\n 'background-color',\n 'border-color',\n 'box-shadow',\n 'border-radius',\n 'font-size',\n 'gap',\n 'padding',\n 'margin',\n 'width',\n 'height',\n])\n\n/** Inline-style camelCase → kebab-case for the props we care about. */\nconst INLINE_PROP_MAP: Record<string, string> = {\n color: 'color',\n background: 'background',\n backgroundColor: 'background-color',\n borderColor: 'border-color',\n boxShadow: 'box-shadow',\n borderRadius: 'border-radius',\n fontSize: 'font-size',\n gap: 'gap',\n padding: 'padding',\n margin: 'margin',\n width: 'width',\n height: 'height',\n}\n\n/** A literal value worth checking: hex, oklch/rgb/hsl(a), or px/rem number. */\nfunction isLiteralValue(value: string): boolean {\n const v = value.trim()\n if (v.includes('var(')) return false\n if (/^#[0-9a-fA-F]{3,8}$/.test(v)) return true\n if (/^(oklch|oklab|rgb|rgba|hsl|hsla)\\(/i.test(v)) return true\n if (/^-?\\d*\\.?\\d+(px|rem)$/.test(v)) return true\n return false\n}\n\nfunction classify(\n value: string,\n contract: Contract,\n): Pick<LiteralFinding, 'level' | 'suggestedToken' | 'allMatches'> | null {\n const matches = contract.tokensByValue.get(normalizeValue(value))\n if (!matches || matches.length === 0) return null\n const first = matches[0]\n if (matches.length === 1 && first) return { level: 'error', suggestedToken: first }\n return { level: 'info', allMatches: matches }\n}\n\n/**\n * Character ranges covered by a JSX `style={{ … }}` object.\n *\n * The inline-style scan used to run over every `prop: 'value'` pair in a `.tsx` file, so a\n * plain data object was audited as if it were CSS: a `DataTable` column's\n * `width: '3rem'` was reported as a hardcoded value that should be `--cascivo-space-12`.\n * A spacing token is not the right unit for a table column, and the object was never a\n * style in the first place — the rule was matching the literal, not the context.\n */\nfunction styleObjectRanges(source: string): Array<[number, number]> {\n const ranges: Array<[number, number]> = []\n const re = /style\\s*=\\s*\\{/g\n for (const m of source.matchAll(re)) {\n let depth = 0\n let quote = ''\n for (let i = m.index! + m[0].length - 1; i < source.length; i++) {\n const ch = source[i]\n if (quote) {\n if (ch === quote) quote = ''\n continue\n }\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n quote = ch\n continue\n }\n if (ch === '{') depth++\n else if (ch === '}') {\n depth--\n if (depth === 0) {\n ranges.push([m.index!, i])\n break\n }\n }\n }\n }\n return ranges\n}\n\n/**\n * Detect literal color/size values in CSS declarations and TSX inline styles\n * that exactly match a known cascade token. Heuristic, line-based — no full\n * CSS/JS parse. Values with no catalog match are NOT flagged (arbitrary brand\n * values are allowed).\n */\nexport function findCssLiteralViolations(\n source: string,\n filename: string,\n contract: Contract,\n): LiteralFinding[] {\n const findings: LiteralFinding[] = []\n const lines = source.split('\\n')\n const styleRanges = styleObjectRanges(source)\n // Absolute offset of the start of each line, so a match can be tested against the ranges.\n const lineStarts: number[] = []\n let offset = 0\n for (const line of lines) {\n lineStarts.push(offset)\n offset += line.length + 1\n }\n const inStyleObject = (absolute: number): boolean =>\n styleRanges.some(([start, end]) => absolute >= start && absolute <= end)\n\n // CSS declaration: `property: value;` (also matches the kebab props inside style=\"...\")\n const cssDecl = /(^|[;{\\s])([a-z-]+)\\s*:\\s*([^;}{]+?)\\s*(?=[;}]|$)/gi\n // Inline JSX style object: `color: '#fff'` or `color: \"#fff\"`\n const inlineDecl = /([A-Za-z][A-Za-z]*)\\s*:\\s*(['\"])([^'\"]+)\\2/g\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (line === undefined) continue\n const seen = new Set<string>()\n\n for (const m of line.matchAll(cssDecl)) {\n if (m[2] === undefined || m[3] === undefined) continue\n const prop = m[2].toLowerCase()\n const rawValue = m[3].trim()\n if (!VISUAL_PROPS.has(prop)) continue\n if (!isLiteralValue(rawValue)) continue\n const cls = classify(rawValue, contract)\n if (!cls) continue\n const key = `${prop}|${rawValue}`\n seen.add(key)\n findings.push({\n file: filename,\n line: i + 1,\n property: prop,\n value: rawValue,\n rule: 'hardcoded-value',\n ...cls,\n })\n }\n\n for (const m of line.matchAll(inlineDecl)) {\n if (m[1] === undefined || m[3] === undefined) continue\n const prop = INLINE_PROP_MAP[m[1]]\n if (!prop) continue\n // Only inside an actual `style={{ … }}`; a data object that happens to have a\n // `width` key is not CSS.\n if (!inStyleObject((lineStarts[i] ?? 0) + (m.index ?? 0))) continue\n const rawValue = m[3].trim()\n if (!isLiteralValue(rawValue)) continue\n const key = `${prop}|${rawValue}`\n if (seen.has(key)) continue\n const cls = classify(rawValue, contract)\n if (!cls) continue\n // Inline TSX `style={{…}}` overrides are a sanctioned fast-prototyping escape\n // hatch — surface a gentle `warn` (not a loop-blocking `error`) so an agent can\n // finish. `.css`-file literals stay `error`: there the fix is mechanical (`--fix`).\n const inlineCls = cls.level === 'error' ? { ...cls, level: 'warn' as const } : cls\n findings.push({\n file: filename,\n line: i + 1,\n property: prop,\n value: rawValue,\n rule: 'hardcoded-value',\n ...inlineCls,\n })\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\n\nexport interface PropFinding {\n file: string\n line: number\n component: string\n prop: string\n level: 'error' | 'info'\n rule: 'unknown-prop' | 'spread-suppressed'\n message: string\n}\n\n/** Props always allowed on any cascade component (DOM passthrough / React intrinsics). */\nexport const PASSTHROUGH = new Set(['className', 'style', 'id', 'ref', 'key', 'children'])\n\n/**\n * Standard HTML/React DOM attributes. Every cascade component extends an\n * `HTMLAttributes` interface and spreads `{...props}` onto its element (verified\n * in button.tsx, card.tsx, …), so these are valid at runtime even though the\n * hand-written `*.meta.ts` prop lists (the audit contract) don't enumerate them.\n * Without this set, a legitimate `type`/`name`/`title`/`tabIndex` on a Button is\n * a non-suppressible `unknown-prop` error — the audit-loop deadlock.\n */\nexport const HTML_PASSTHROUGH = new Set([\n 'type',\n 'name',\n 'value',\n 'defaultValue',\n 'checked',\n 'defaultChecked',\n 'placeholder',\n 'title',\n 'role',\n 'tabIndex',\n 'form',\n 'href',\n 'target',\n 'rel',\n 'download',\n 'src',\n 'alt',\n 'width',\n 'height',\n 'loading',\n 'autoComplete',\n 'autoFocus',\n 'required',\n 'readOnly',\n 'min',\n 'max',\n 'step',\n 'rows',\n 'cols',\n 'wrap',\n 'maxLength',\n 'minLength',\n 'pattern',\n 'multiple',\n 'accept',\n 'size',\n 'dir',\n 'lang',\n 'hidden',\n 'draggable',\n 'spellCheck',\n 'contentEditable',\n 'inputMode',\n 'enterKeyHint',\n 'htmlFor',\n 'slot',\n 'disabled',\n 'open',\n])\n\nfunction isPassthrough(prop: string): boolean {\n if (PASSTHROUGH.has(prop)) return true\n if (HTML_PASSTHROUGH.has(prop)) return true\n if (prop.startsWith('data-')) return true\n if (prop.startsWith('aria-')) return true\n if (/^on[A-Z]/.test(prop)) return true\n return false\n}\n\n/**\n * Local JSX names bound to a cascade component, mapped to the contract name they refer to.\n *\n * Two rules, both learned from false positives on correct code:\n *\n * 1. **Track the LOCAL binding, not the imported name.** `import { Link as CascadeLink }`\n * used to register `Link`, so the scan then matched the *router's* `<Link to=…>` and\n * reported `to` as an unknown prop. For a router-based app that collateral is close to\n * guaranteed.\n * 2. **Never audit a name this file also imports from somewhere else.** A bare-name clash\n * (`Link` from `@tanstack/react-router`) must not be audited against cascivo's contract\n * even when nothing is aliased.\n */\nexport function importedCascadeComponents(source: string): Map<string, string> {\n const names = new Map<string, string>()\n const foreign = new Set<string>()\n\n const importRe = /import\\s*(?:type\\s*)?\\{([^}]*)\\}\\s*from\\s*['\"]([^'\"]+)['\"]/g\n for (const m of source.matchAll(importRe)) {\n const [, group, specifier] = m\n if (group === undefined || specifier === undefined) continue\n const isCascade = specifier === '@cascivo/react'\n for (const raw of group.split(',')) {\n const parts = raw.trim().split(/\\s+as\\s+/)\n const imported = parts[0]?.trim().replace(/^type\\s+/, '')\n const local = (parts[1] ?? parts[0])?.trim()\n if (!imported || !local) continue\n if (isCascade) names.set(local, imported)\n else foreign.add(local)\n }\n }\n // A default import (`import Link from 'next/link'`) also shadows the name.\n for (const m of source.matchAll(\n /import\\s+(\\w+)\\s*(?:,\\s*\\{[^}]*\\})?\\s*from\\s*['\"]([^'\"]+)['\"]/g,\n )) {\n if (m[2] !== '@cascivo/react' && m[1]) foreign.add(m[1])\n }\n\n for (const local of foreign) names.delete(local)\n return names\n}\n\n/** Find each opening tag for `comp`, returning its attribute substring + start index. */\nexport interface OpeningTag {\n attrs: string\n index: number\n hasSpread: boolean\n /** `<Foo />` — the one shape that genuinely cannot have children. */\n selfClosing: boolean\n}\n\nexport function findOpeningTags(source: string, comp: string): OpeningTag[] {\n const tags: OpeningTag[] = []\n const re = new RegExp(`<${comp}(?=[\\\\s/>])`, 'g')\n for (const m of source.matchAll(re)) {\n const start = m.index ?? 0\n // Walk forward to the matching '>' that closes the opening tag, respecting\n // nested braces (JSX expressions) and quoted strings.\n let i = start + m[0].length\n let depth = 0\n let quote = ''\n let attrs = ''\n let closed = false\n for (; i < source.length; i++) {\n const ch = source[i]\n if (quote) {\n if (ch === quote) quote = ''\n attrs += ch\n continue\n }\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n quote = ch\n attrs += ch\n continue\n }\n if (ch === '{') depth++\n else if (ch === '}') depth--\n else if (ch === '>' && depth === 0) {\n closed = true\n break\n }\n attrs += ch\n }\n if (!closed) continue\n const selfClosing = /\\/\\s*$/.test(attrs)\n const cleanAttrs = attrs.replace(/\\/\\s*$/, '')\n tags.push({\n attrs: cleanAttrs,\n index: start,\n hasSpread: /\\{\\s*\\.\\.\\./.test(cleanAttrs),\n selfClosing,\n })\n }\n return tags\n}\n\n/** Extract top-level attribute names from an opening-tag attribute string. */\nexport function extractAttrNames(attrs: string): string[] {\n const names: string[] = []\n let depth = 0\n let quote = ''\n let token = ''\n const flush = () => {\n const name = token.trim().split('=')[0]?.trim()\n if (name && /^[A-Za-z]/.test(name)) names.push(name)\n token = ''\n }\n for (let i = 0; i < attrs.length; i++) {\n const ch = attrs[i]\n if (ch === undefined) continue\n if (quote) {\n if (ch === quote) quote = ''\n continue\n }\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n quote = ch\n continue\n }\n if (ch === '{') {\n depth++\n continue\n }\n if (ch === '}') {\n depth--\n continue\n }\n if (depth > 0) continue\n if (ch === '=') {\n flush()\n // skip the value: handled by quote/brace state on next chars; reset token\n token = ''\n continue\n }\n if (/\\s/.test(ch)) {\n if (token.trim()) flush()\n continue\n }\n token += ch\n }\n if (token.trim()) flush()\n return names\n}\n\nexport function lineOf(source: string, index: number): number {\n let line = 1\n for (let i = 0; i < index && i < source.length; i++) {\n if (source[i] === '\\n') line++\n }\n return line\n}\n\n/**\n * Check JSX usages of imported cascade components for unknown props.\n * Heuristic — regex/brace-aware scan, not a full AST. Elements using a spread\n * (`{...rest}`) are reported as info and skipped (props can't be statically known).\n */\nexport function findJsxPropViolations(\n source: string,\n filename: string,\n contract: Contract,\n): PropFinding[] {\n const findings: PropFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const [comp, contractName] of tracked) {\n const info = contract.components.get(contractName)\n if (!info) continue\n const known = new Set(info.props.map((p) => p.name))\n\n for (const tag of findOpeningTags(source, comp)) {\n const line = lineOf(source, tag.index)\n if (tag.hasSpread) {\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: '...',\n level: 'info',\n rule: 'spread-suppressed',\n message: `<${comp}> uses a spread — prop checks skipped`,\n })\n continue\n }\n for (const name of extractAttrNames(tag.attrs)) {\n if (isPassthrough(name)) continue\n if (known.has(name)) continue\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: name,\n level: 'error',\n rule: 'unknown-prop',\n message:\n `<${comp}> has unknown prop \"${name}\". ` +\n 'style/className pass through on every component (see the override ladder in ' +\n 'docs/AI-RULES.md); for an intentional one-off add `/* cascivo-audit: allow unknown-prop */`.',\n })\n }\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport { findOpeningTags, importedCascadeComponents, lineOf } from './jsx-props.js'\n\nexport interface RawStringFinding {\n file: string\n line: number\n component: string\n text: string\n level: 'warn'\n rule: 'raw-string'\n message: string\n}\n\n/** Looks like English prose worth flagging: ≥2 whitespace-separated words, letters/spaces only. */\nfunction looksLikeProse(text: string): boolean {\n const trimmed = text.trim()\n if (!/^[A-Za-z][A-Za-z\\s]*$/.test(trimmed)) return false\n return trimmed.split(/\\s+/).length >= 2\n}\n\n/**\n * Conservative raw-string check: for cascade components that own user-facing\n * chrome text (intent.content), warn when a literal multi-word English child\n * appears, suggesting the labels prop / i18n. Never errors. Only inspects the\n * immediate text directly after the opening tag (no nested element traversal).\n */\nexport function findRawStringViolations(\n source: string,\n filename: string,\n contract: Contract,\n): RawStringFinding[] {\n const findings: RawStringFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const [comp, contractName] of tracked) {\n const info = contract.components.get(contractName)\n if (!info?.hasContent) continue\n\n for (const tag of findOpeningTags(source, comp)) {\n // Locate the end of this opening tag in the source.\n const openEnd = source.indexOf('>', tag.index)\n if (openEnd === -1) continue\n if (source[openEnd - 1] === '/') continue // self-closing, no children\n\n // Grab text up to the next tag/expression boundary.\n const after = source.slice(openEnd + 1)\n const stop = after.search(/[<{]/)\n const child = (stop === -1 ? after : after.slice(0, stop)).trim()\n if (!child || !looksLikeProse(child)) continue\n\n findings.push({\n file: filename,\n line: lineOf(source, openEnd),\n component: comp,\n text: child,\n level: 'warn',\n rule: 'raw-string',\n message: `<${comp}> raw text \"${child}\" — use the labels prop / i18n`,\n })\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport {\n extractAttrNames,\n findOpeningTags,\n importedCascadeComponents,\n lineOf,\n} from './jsx-props.js'\n\nexport interface RequiredPropFinding {\n file: string\n line: number\n component: string\n prop: string\n level: 'error'\n rule: 'missing-prop'\n message: string\n}\n\n/**\n * Flag cascade elements that omit a prop the component marks required.\n * Elements using a spread are skipped (the prop may arrive via the spread).\n */\nexport function findRequiredPropViolations(\n source: string,\n filename: string,\n contract: Contract,\n): RequiredPropFinding[] {\n const findings: RequiredPropFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const [comp, contractName] of tracked) {\n const info = contract.components.get(contractName)\n if (!info) continue\n\n for (const tag of findOpeningTags(source, comp)) {\n if (tag.hasSpread) continue\n const present = new Set(extractAttrNames(tag.attrs))\n const line = lineOf(source, tag.index)\n for (const req of info.requiredProps) {\n if (present.has(req)) continue\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: req,\n level: 'error',\n rule: 'missing-prop',\n message: `<${comp}> requires \"${req}\"`,\n })\n }\n // `children` is element content, not an attribute. The scan only ever sees the\n // opening tag, so treating it like a prop reported EVERY correct usage as missing —\n // `<AppShell>{children}</AppShell>` and `<Field label=\"…\"><Input/></Field>` both.\n // A self-closing tag is the one shape that genuinely has no children.\n if (info.requiresChildren && tag.selfClosing && !present.has('children')) {\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: 'children',\n level: 'error',\n rule: 'missing-prop',\n message: `<${comp} /> is self-closing but requires children`,\n })\n }\n }\n }\n\n return findings\n}\n","/**\n * Zero-dependency scanner for **unlayered style rules** in a CSS source.\n *\n * cascivo ships everything inside `@layer` blocks. Unlayered author CSS beats\n * every layered rule regardless of specificity (CSS cascade-layer semantics), so\n * a single unlayered style rule silently overrides the whole design system. This\n * scanner finds top-level style rules that live outside any `@layer` block.\n *\n * It is line-based and brace-tracking, not a full CSS parse — good enough because\n * we only need to know, for each `{`, whether an `@layer` block is an ancestor.\n *\n * Transparent to layering: `@media`, `@container`, `@supports`, `@scope` — a rule\n * inside these is layered iff the group is inside a layer. Ignored entirely:\n * `@keyframes`/`@font-face`/`@property`/`@page`/etc. (their inner blocks are not\n * style rules we govern). `@import`/`@charset`/`@layer;` statements are not blocks.\n */\n\nexport interface UnlayeredRule {\n /** 1-indexed line of the rule's selector. */\n line: number\n /** The selector text (trimmed, truncated) for the report. */\n selector: string\n}\n\n/** Replace comment bodies and string contents with spaces, preserving newlines. */\nfunction blankCommentsAndStrings(source: string): string {\n let out = ''\n let i = 0\n const n = source.length\n while (i < n) {\n const c = source[i]!\n const next = source[i + 1]\n if (c === '/' && next === '*') {\n out += ' '\n i += 2\n while (i < n && !(source[i] === '*' && source[i + 1] === '/')) {\n out += source[i] === '\\n' ? '\\n' : ' '\n i++\n }\n out += ' '\n i += 2\n } else if (c === '\"' || c === \"'\") {\n const quote = c\n out += ' '\n i++\n while (i < n && source[i] !== quote) {\n if (source[i] === '\\\\') {\n out += ' '\n i += 2\n continue\n }\n out += source[i] === '\\n' ? '\\n' : ' '\n i++\n }\n out += ' '\n i++\n } else {\n out += c\n i++\n }\n }\n return out\n}\n\ntype FrameKind = 'layer' | 'group' | 'style' | 'other'\n\n/**\n * Accessibility / user-preference media features whose overrides MUST win over\n * everything — including a consumer's `cascivo.override` layer — so they are\n * legitimately placed unlayered (top-level). A `@media (forced-colors: active)`\n * block outside `@layer` is the sanctioned cascade idiom, not a hotfix leak.\n */\nconst A11Y_GUARANTEE_RE =\n /@media[^{]*\\b(forced-colors|prefers-contrast|prefers-reduced-motion|prefers-reduced-transparency|inverted-colors)\\b/\n\nfunction classifyPrelude(prelude: string): FrameKind {\n const p = prelude.trim().toLowerCase()\n if (p.startsWith('@layer')) return 'layer'\n // A11y-guarantee media queries are an exempt (non-flagging) context.\n if (A11Y_GUARANTEE_RE.test(p)) return 'other'\n if (\n p.startsWith('@media') ||\n p.startsWith('@container') ||\n p.startsWith('@supports') ||\n p.startsWith('@scope')\n ) {\n return 'group'\n }\n if (p.startsWith('@')) return 'other'\n return 'style'\n}\n\n/**\n * Return every top-level style rule that is NOT inside an `@layer` block. Only the\n * outermost unlayered rule is reported (nested rules inside it are implied).\n */\nexport function findUnlayeredRules(source: string): UnlayeredRule[] {\n const clean = blankCommentsAndStrings(source)\n const rules: UnlayeredRule[] = []\n const stack: FrameKind[] = []\n\n let preludeStart = 0\n const lineStarts: number[] = [0]\n for (let i = 0; i < clean.length; i++) {\n if (clean[i] === '\\n') lineStarts.push(i + 1)\n }\n const lineOf = (idx: number): number => {\n // binary search over lineStarts\n let lo = 0\n let hi = lineStarts.length - 1\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1\n if (lineStarts[mid]! <= idx) lo = mid\n else hi = mid - 1\n }\n return lo + 1\n }\n\n const hasAncestor = (kind: FrameKind): boolean => stack.includes(kind)\n\n for (let i = 0; i < clean.length; i++) {\n const c = clean[i]\n if (c === '{') {\n const prelude = clean.slice(preludeStart, i)\n const kind = classifyPrelude(prelude)\n if (\n kind === 'style' &&\n !hasAncestor('layer') &&\n !hasAncestor('other') &&\n !hasAncestor('style')\n ) {\n const trimmed = prelude.trim().replace(/\\s+/g, ' ')\n const startIdx = preludeStart + (prelude.length - prelude.trimStart().length)\n rules.push({\n line: lineOf(startIdx),\n selector: trimmed.length > 60 ? `${trimmed.slice(0, 57)}…` : trimmed,\n })\n }\n stack.push(kind)\n preludeStart = i + 1\n } else if (c === '}') {\n stack.pop()\n preludeStart = i + 1\n } else if (c === ';') {\n // A statement terminator (@import, `@layer a, b;`, or a declaration inside a\n // block). Reset the prelude window so the next `{` sees a clean selector.\n preludeStart = i + 1\n }\n }\n\n return rules\n}\n","import { findUnlayeredRules } from '../utils/css-layers.js'\n\nexport interface UnlayeredFinding {\n file: string\n line: number\n selector: string\n level: 'warn'\n rule: 'unlayered-css'\n message: string\n}\n\nconst MESSAGE =\n 'Unlayered CSS beats every cascivo layer regardless of specificity. ' +\n 'For a one-off override use `@layer cascivo.override { … }`; for app styles declare ' +\n 'an app layer (e.g. cascivo.example) in your order statement. See docs/CSS-LAYERS-PITFALL.md.'\n\n/**\n * Warn on top-level style rules that live outside any `@layer` block. This is the\n * consumer-facing half of the zero-unlayered guard: it teaches the fix rather than\n * failing the build, because `docs/USING-WITH-TAILWIND.md` blesses deliberate\n * unlayered CSS as a valid interop escape hatch. Accessibility-guarantee media\n * queries (`forced-colors`, `prefers-contrast`, …) are exempt — see css-layers.ts.\n */\nexport function findUnlayeredViolations(source: string, filename: string): UnlayeredFinding[] {\n return findUnlayeredRules(source).map((rule) => ({\n file: filename,\n line: rule.line,\n selector: rule.selector,\n level: 'warn',\n rule: 'unlayered-css',\n message: MESSAGE,\n }))\n}\n","import { lineOf } from './jsx-props.js'\n\nexport interface VendorCssFinding {\n file: string\n line: number\n specifier: string\n level: 'warn'\n rule: 'vendor-css-import'\n message: string\n}\n\n// `import '<spec>'` or `import x from '<spec>'` where <spec> ends in .css\n// (optionally with a ?query / #hash). Captures the specifier.\nconst CSS_IMPORT_RE = /import\\s+(?:[^'\"]*?\\bfrom\\s+)?(['\"])([^'\"]+\\.css(?:[?#][^'\"]*)?)\\1/g\n\n/** A bare specifier resolves into node_modules (not a relative or absolute path). */\nfunction isBareSpecifier(spec: string): boolean {\n return !spec.startsWith('.') && !spec.startsWith('/')\n}\n\nconst MESSAGE =\n 'CSS imported from a package through JS/TS cannot be wrapped in an @layer, so if this ' +\n 'package ships unlayered global CSS it beats every cascivo layer. Route it through a CSS ' +\n 'file (`@import url(\"<pkg>/styles.css\") layer(vendor);`) or add @cascivo/vite-plugin ' +\n '(`cascivoLayers({ imports: { \"<pkg>/styles.css\": \"vendor\" } })`). See docs/THIRD-PARTY-CSS.md.'\n\n/**\n * Warn on bare (node_modules) `*.css` imports in JS/TS. Relative imports (the\n * consumer's own CSS modules) and cascivo's own already-layered `@cascivo/*`\n * stylesheets are exempt. Level `warn` — teaches the layer(vendor) recipe.\n */\nexport function findVendorCssImports(source: string, filename: string): VendorCssFinding[] {\n const findings: VendorCssFinding[] = []\n for (const m of source.matchAll(CSS_IMPORT_RE)) {\n const spec = m[2]\n if (spec === undefined) continue\n if (!isBareSpecifier(spec)) continue\n // cascivo's own stylesheets ship the layer statement + fully-layered rules.\n if (spec.startsWith('@cascivo/')) continue\n findings.push({\n file: filename,\n line: lineOf(source, m.index ?? 0),\n specifier: spec,\n level: 'warn',\n rule: 'vendor-css-import',\n message: MESSAGE,\n })\n }\n return findings\n}\n","/**\n * Inline suppression directives for `cascivo audit --ai`.\n *\n * A comment `cascivo-audit: allow <rule-id>[, <rule-id>…]` (or `allow all`) on the\n * same line as, or the line immediately preceding, a finding downgrades that\n * finding: it is marked `suppressed` so it no longer counts toward the error/warn\n * exit gate, while still being printed so it stays visible. This is the guaranteed\n * loop-breaker for an AI agent — the one escape hatch that no rule can override.\n */\n\n/** Rule ids a directive may name (the user-facing error/warn rules). */\nexport const AUDIT_RULES = new Set<string>([\n 'unknown-prop',\n 'hardcoded-value',\n 'missing-prop',\n 'raw-string',\n 'unlayered-css',\n 'vendor-css-import',\n])\n\nexport interface DirectiveFinding {\n file: string\n line: number\n level: 'warn'\n rule: 'audit-directive'\n message: string\n}\n\ninterface Directive {\n line: number\n rules: 'all' | Set<string>\n}\n\nconst DIRECTIVE_RE = /cascivo-audit:\\s*allow\\s+([^\\n]+)/i\n\n/**\n * Scan a source file for suppression directives. Returns the parsed directives\n * plus `warn`-level findings for any unknown rule id (so typos surface rather\n * than silently failing to suppress).\n */\nexport function parseDirectives(\n source: string,\n file: string,\n): { directives: Directive[]; findings: DirectiveFinding[] } {\n const directives: Directive[] = []\n const findings: DirectiveFinding[] = []\n const lines = source.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const m = lines[i]?.match(DIRECTIVE_RE)\n if (!m || m[1] === undefined) continue\n // Strip trailing comment terminators (`*/`, `-->`) and whitespace.\n const raw = m[1]\n .replace(/\\*\\/.*$/, '')\n .replace(/-->.*$/, '')\n .trim()\n const ids = raw.split(/[\\s,]+/).filter(Boolean)\n const line = i + 1\n if (ids.includes('all')) {\n directives.push({ line, rules: 'all' })\n continue\n }\n const valid = new Set<string>()\n const unknown: string[] = []\n for (const id of ids) {\n if (AUDIT_RULES.has(id)) valid.add(id)\n else unknown.push(id)\n }\n if (valid.size > 0) directives.push({ line, rules: valid })\n if (unknown.length > 0) {\n findings.push({\n file,\n line,\n level: 'warn',\n rule: 'audit-directive',\n message:\n `unknown audit rule id${unknown.length > 1 ? 's' : ''} in directive: ${unknown.join(', ')}. ` +\n `valid ids: ${[...AUDIT_RULES].join(', ')}.`,\n })\n }\n }\n return { directives, findings }\n}\n\n/**\n * Mark findings covered by a directive as `suppressed`. A directive on line L\n * applies to findings on line L (inline comment) or line L+1 (comment above the\n * code). Level is left unchanged; callers exclude `suppressed` findings from the\n * exit gate.\n */\nexport function applySuppressions<T extends { line: number; rule: string }>(\n findings: T[],\n directives: Directive[],\n): Array<T & { suppressed?: boolean }> {\n if (directives.length === 0) return findings\n return findings.map((f) => {\n const covered = directives.some(\n (d) =>\n (d.line === f.line || d.line === f.line - 1) && (d.rules === 'all' || d.rules.has(f.rule)),\n )\n return covered ? { ...f, suppressed: true } : f\n })\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport type { BuildContractInput, ComponentInfo, Contract, PropInfo } from './contract-pure.js'\nexport { buildContract, normalizeValue } from './contract-pure.js'\nimport type { Contract } from './contract-pure.js'\nimport { buildContract } from './contract-pure.js'\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\n\n/** Walk up from a start directory looking for the apps/site/public dir. */\nfunction findDocsPublic(startDir: string): string | null {\n let dir = startDir\n for (let i = 0; i < 10; i++) {\n const candidate = join(dir, 'apps', 'site', 'public')\n if (existsSync(candidate)) return candidate\n dir = join(dir, '..')\n }\n return null\n}\n\n/** Walk up from a start directory looking for registry.json at the repo root. */\nfunction findRegistry(startDir: string): string | null {\n let dir = startDir\n for (let i = 0; i < 10; i++) {\n const candidate = join(dir, 'registry.json')\n if (existsSync(candidate)) return candidate\n dir = join(dir, '..')\n }\n return null\n}\n\nconst CONTRACT_URL = 'https://cascivo.com/audit-contract.json'\n\n/**\n * Download the contract, caching it by version so a second run is offline-fast. Returns\n * null on any failure — the audit must never hard-depend on the network.\n */\nasync function fetchContract(report: (source: string) => void): Promise<Contract | null> {\n try {\n const response = await fetch(CONTRACT_URL, { signal: AbortSignal.timeout(5000) })\n if (!response.ok) return null\n const bundled = (await response.json()) as BundledContract\n try {\n const target = cachePath(bundled.version)\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, JSON.stringify(bundled))\n } catch {\n // A read-only cache dir is not a reason to fail the audit.\n }\n report(`network: ${CONTRACT_URL}`)\n return fromBundled(bundled)\n } catch {\n return null\n }\n}\n\n/** The reduced contract shipped inside this package (scripts/registry/audit-contract.ts). */\ninterface BundledContract {\n version: string\n tokens: { name: string; resolvedDefault: string | null }[]\n components: { name: string; props: { name: string; type: string; required: boolean }[] }[]\n content: string[]\n}\n\n/** Adapt the bundled shape to `buildContract`'s three-artifact input. */\nfunction fromBundled(bundled: BundledContract): Contract {\n return buildContract({\n catalog: { tokens: bundled.tokens },\n registry: { components: bundled.components.map((c) => ({ meta: c })) },\n context: { components: bundled.content.map((name) => ({ name, intent: { content: true } })) },\n })\n}\n\n/** Where the network fallback caches a downloaded contract. */\nfunction cachePath(version: string): string {\n const base = process.env['XDG_CACHE_HOME'] ?? join(process.env['HOME'] ?? tmpdir(), '.cache')\n return join(base, 'cascivo', `audit-contract-${version}.json`)\n}\n\n/**\n * Load the cascade contract. Resolution order, first hit wins:\n *\n * 1. an explicit path (`--contract <file>` / `options.contractPath`)\n * 2. the dev-monorepo artifacts (`apps/site/public/…` + `registry.json`)\n * 3. the contract bundled in this package ← what makes `audit` work in a real project\n * 4. `https://cascivo.com/audit-contract.json`, cached under `~/.cache/cascivo/`\n *\n * (3) is why this exists: the walk-up in (2) only ever finds anything inside this monorepo,\n * so `cascivo audit --ai` died with \"token catalog not found\" in every consumer project —\n * a documented, working feature that nobody outside this repo could run. (4) is best-effort\n * and never required: `audit` works offline.\n */\nexport async function loadContract(options?: {\n catalogPath?: string\n contextPath?: string\n registryPath?: string\n /** Explicit contract file — either the bundled shape or a docs-public directory. */\n contractPath?: string\n /** Report which tier answered (used by `--verbose`). */\n onResolve?: (source: string) => void\n}): Promise<Contract> {\n const report = options?.onResolve ?? (() => {})\n\n // 1. Explicit path.\n if (options?.contractPath) {\n if (!existsSync(options.contractPath)) {\n throw new Error(`contract file not found: ${options.contractPath}`)\n }\n report(`explicit: ${options.contractPath}`)\n return fromBundled(JSON.parse(readFileSync(options.contractPath, 'utf8')) as BundledContract)\n }\n\n // 2. Dev monorepo — unchanged, so in-repo behavior and its tests are untouched.\n const docsPublic = findDocsPublic(HERE) ?? findDocsPublic(process.cwd())\n const catalogPath =\n options?.catalogPath ?? (docsPublic ? join(docsPublic, 'tokens.catalog.json') : null)\n const contextPath = options?.contextPath ?? (docsPublic ? join(docsPublic, 'context.json') : null)\n const registryPath = options?.registryPath ?? findRegistry(HERE) ?? findRegistry(process.cwd())\n const haveMonorepo =\n catalogPath &&\n existsSync(catalogPath) &&\n registryPath &&\n existsSync(registryPath) &&\n contextPath &&\n existsSync(contextPath)\n\n if (!haveMonorepo) {\n // 3. Bundled contract.\n const bundled = join(HERE, 'generated', 'audit-contract.json')\n const bundledDist = join(HERE, '..', 'generated', 'audit-contract.json')\n for (const candidate of [bundled, bundledDist]) {\n if (existsSync(candidate)) {\n report(`bundled: ${candidate}`)\n return fromBundled(JSON.parse(readFileSync(candidate, 'utf8')) as BundledContract)\n }\n }\n\n // 4. Network, with a local cache. Best-effort: a failure falls through to the error below.\n const fetched = await fetchContract(report)\n if (fetched) return fetched\n\n throw new Error(\n 'cascivo contract unavailable. Pass --contract <path> to a downloaded ' +\n 'audit-contract.json, or run inside the cascivo monorepo. ' +\n '(The CLI normally ships one; this build appears to be missing it.)',\n )\n }\n report('monorepo artifacts')\n\n const catalog = JSON.parse(readFileSync(catalogPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['catalog']\n const registry = JSON.parse(readFileSync(registryPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['registry']\n const context = JSON.parse(readFileSync(contextPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['context']\n\n return buildContract({ catalog, registry, context })\n}\n","import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'\nimport { extname, join } from 'node:path'\nimport type { LiteralFinding } from '../audit-ai/css-literals.js'\nimport { findCssLiteralViolations } from '../audit-ai/css-literals.js'\nimport type { PropFinding } from '../audit-ai/jsx-props.js'\nimport { findJsxPropViolations } from '../audit-ai/jsx-props.js'\nimport type { RawStringFinding } from '../audit-ai/raw-strings.js'\nimport { findRawStringViolations } from '../audit-ai/raw-strings.js'\nimport type { RequiredPropFinding } from '../audit-ai/required-props.js'\nimport { findRequiredPropViolations } from '../audit-ai/required-props.js'\nimport type { UnlayeredFinding } from '../audit-ai/unlayered.js'\nimport { findUnlayeredViolations } from '../audit-ai/unlayered.js'\nimport type { VendorCssFinding } from '../audit-ai/vendor-css.js'\nimport { findVendorCssImports } from '../audit-ai/vendor-css.js'\nimport type { DirectiveFinding } from '../audit-ai/suppress.js'\nimport { applySuppressions, parseDirectives } from '../audit-ai/suppress.js'\nimport type { CascadeConfig } from '../utils/config.js'\nimport type { Contract } from '../utils/contract.js'\nimport { loadContract } from '../utils/contract.js'\n\nexport type Finding =\n | LiteralFinding\n | PropFinding\n | RequiredPropFinding\n | RawStringFinding\n | UnlayeredFinding\n | VendorCssFinding\n | DirectiveFinding\n\n/** A finding after suppression directives have been applied. */\nexport type AuditedFinding = Finding & { suppressed?: boolean }\n\nconst SKIP_DIRS = new Set(['node_modules', 'dist', '.git', 'build', '.next', 'coverage'])\n\nfunction collectFiles(paths: string[]): string[] {\n const out: string[] = []\n const walk = (p: string) => {\n if (!existsSync(p)) return\n const s = statSync(p)\n if (s.isDirectory()) {\n const base = p.split('/').pop() ?? ''\n if (SKIP_DIRS.has(base)) return\n for (const entry of readdirSync(p)) walk(join(p, entry))\n return\n }\n const ext = extname(p)\n if (ext === '.css' || ext === '.tsx' || ext === '.ts') out.push(p)\n }\n for (const p of paths) walk(p)\n return out\n}\n\nfunction findingsFor(file: string, source: string, contract: Contract): Finding[] {\n const ext = extname(file)\n const findings: Finding[] = []\n if (ext === '.css') {\n findings.push(...findCssLiteralViolations(source, file, contract))\n findings.push(...findUnlayeredViolations(source, file))\n } else if (ext === '.tsx' || ext === '.ts') {\n findings.push(...findCssLiteralViolations(source, file, contract))\n findings.push(...findJsxPropViolations(source, file, contract))\n findings.push(...findRequiredPropViolations(source, file, contract))\n findings.push(...findRawStringViolations(source, file, contract))\n findings.push(...findVendorCssImports(source, file))\n }\n return findings\n}\n\nfunction detail(f: Finding): string {\n switch (f.rule) {\n case 'hardcoded-value':\n if (f.suggestedToken) return `${f.value} → var(${f.suggestedToken})`\n return `${f.value} → ${f.allMatches?.join(' | ') ?? '(ambiguous)'}`\n case 'unknown-prop':\n return `<${f.component} ${f.prop}>`\n case 'spread-suppressed':\n return `<${f.component} {...}> (props not checked)`\n case 'missing-prop':\n return `<${f.component}> requires \"${f.prop}\"`\n case 'raw-string':\n return `\"${f.text}\" → use labels prop / i18n`\n case 'unlayered-css':\n return `${f.selector} { … } → wrap in @layer`\n case 'vendor-css-import':\n return `import '${f.specifier}' → @import url(…) layer(vendor)`\n case 'audit-directive':\n return f.message\n }\n}\n\nfunction levelLabel(level: Finding['level']): string {\n return level === 'warn' ? 'warn' : level\n}\n\nfunction renderFindings(findings: AuditedFinding[]): void {\n if (findings.length === 0) {\n console.log('cascade audit --ai: no findings.')\n return\n }\n const rows = findings.map((f) => ({\n loc: `${f.file}:${f.line}`,\n level: f.suppressed ? 'suppressed' : levelLabel(f.level),\n rule: f.rule,\n detail: detail(f),\n }))\n const locW = Math.max(...rows.map((r) => r.loc.length), 8)\n const lvlW = Math.max(...rows.map((r) => r.level.length), 5)\n const ruleW = Math.max(...rows.map((r) => r.rule.length), 4)\n for (const r of rows) {\n console.log(\n `${r.loc.padEnd(locW)} ${r.level.padEnd(lvlW)} ${r.rule.padEnd(ruleW)} ${r.detail}`,\n )\n }\n console.log('---')\n const active = findings.filter((f) => !f.suppressed)\n const errors = active.filter((f) => f.level === 'error').length\n const warnings = active.filter((f) => f.level === 'warn').length\n const infos = active.filter((f) => f.level === 'info').length\n const suppressed = findings.filter((f) => f.suppressed).length\n const parts = [\n `${errors} error${errors === 1 ? '' : 's'}`,\n `${warnings} warning${warnings === 1 ? '' : 's'}`,\n ]\n if (infos) parts.push(`${infos} info`)\n if (suppressed) parts.push(`${suppressed} suppressed`)\n console.log(parts.join(', '))\n}\n\nfunction escapeRe(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Pure literal→token rewrite. Only rewrites simple `property: #hex;` style\n * declarations where exactly one token matches. Returns the new source and how\n * many findings were resolved (verified by re-running the checker).\n */\nexport function fixCssLiterals(\n source: string,\n file: string,\n contract: Contract,\n): { source: string; fixed: number } {\n const fixable = findCssLiteralViolations(source, file, contract).filter(\n (f) => f.level === 'error' && f.suggestedToken && /^#[0-9a-fA-F]{3,8}$/.test(f.value),\n )\n let next = source\n for (const f of fixable) {\n // Only rewrite a full-value declaration: `prop: #hex;` (or end of block).\n const re = new RegExp(`(${escapeRe(f.property)}\\\\s*:\\\\s*)${escapeRe(f.value)}(\\\\s*[;}])`, 'gi')\n next = next.replace(re, `$1var(${f.suggestedToken})$2`)\n }\n if (next === source) return { source, fixed: 0 }\n const remaining = findCssLiteralViolations(next, file, contract).filter(\n (f) => f.level === 'error' && f.suggestedToken,\n ).length\n return { source: next, fixed: fixable.length - remaining }\n}\n\n/** Apply {@link fixCssLiterals} to each .css file on disk. */\nfunction applyFixes(files: string[], contract: Contract): number {\n let fixed = 0\n for (const file of files) {\n if (extname(file) !== '.css') continue\n const { source, fixed: n } = fixCssLiterals(readFileSync(file, 'utf8'), file, contract)\n if (n > 0) {\n writeFileSync(file, source)\n fixed += n\n }\n }\n return fixed\n}\n\nexport async function audit(args: string[], _config: CascadeConfig): Promise<void> {\n if (!args.includes('--ai')) {\n console.log('cascivo audit: use --ai to audit AI-generated code against the cascivo contract')\n console.log(' --ai [paths…] audit files against the cascivo contract')\n console.log(' --fix rewrite hardcoded values to tokens where unambiguous')\n console.log(' --json machine-readable findings')\n console.log(' --level <level> minimum level to report (error|warning|info)')\n console.log(' --contract <path> use this audit-contract.json instead of the bundled one')\n console.log(' --verbose report which contract source was used')\n return\n }\n\n const jsonOutput = args.includes('--json')\n const fixMode = args.includes('--fix')\n const verbose = args.includes('--verbose')\n const levelIdx = args.indexOf('--level')\n const minLevel = levelIdx >= 0 ? (args[levelIdx + 1] ?? 'error') : 'error'\n const contractIdx = args.indexOf('--contract')\n const contractPath = contractIdx >= 0 ? args[contractIdx + 1] : undefined\n\n const paths = args.filter((a, i) => {\n if (a.startsWith('--')) return false\n if (levelIdx >= 0 && i === levelIdx + 1) return false\n if (contractIdx >= 0 && i === contractIdx + 1) return false\n return true\n })\n\n let contract: Contract\n try {\n contract = await loadContract({\n ...(contractPath ? { contractPath } : {}),\n ...(verbose ? { onResolve: (source: string) => console.error(`contract ← ${source}`) } : {}),\n })\n } catch (e) {\n console.error(`Contract unavailable: ${e instanceof Error ? e.message : String(e)}`)\n process.exitCode = 2\n return\n }\n\n const files = collectFiles(paths.length ? paths : [process.cwd()])\n\n if (fixMode) {\n const n = applyFixes(files, contract)\n console.log(`cascade audit --ai --fix: rewrote ${n} literal${n === 1 ? '' : 's'} to tokens.`)\n }\n\n const allFindings: AuditedFinding[] = []\n for (const file of files) {\n const source = readFileSync(file, 'utf8')\n const { directives, findings: directiveFindings } = parseDirectives(source, file)\n allFindings.push(...applySuppressions(findingsFor(file, source, contract), directives))\n allFindings.push(...directiveFindings)\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(allFindings, null, 2))\n } else {\n renderFindings(allFindings)\n }\n\n // Suppressed findings never fail the run — that is the escape hatch's whole point.\n const active = allFindings.filter((f) => !f.suppressed)\n const hasErrors = active.some((f) => f.level === 'error')\n if (minLevel === 'error' && hasErrors) process.exitCode = 1\n if (minLevel === 'warn' && active.some((f) => f.level !== 'info')) process.exitCode = 1\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.12.0",
2
+ "version": "0.13.1",
3
3
  "tokens": [
4
4
  { "name": "--cascivo-gray-0", "resolvedDefault": "oklch(1 0 0)" },
5
5
  { "name": "--cascivo-gray-50", "resolvedDefault": "oklch(0.985 0.002 264)" },
@@ -291,6 +291,8 @@
291
291
  { "name": "--cascivo-shell-header-block-size", "resolvedDefault": "3rem" },
292
292
  { "name": "--cascivo-shell-panel-inline-size", "resolvedDefault": "20rem" },
293
293
  { "name": "--cascivo-shell-aside-inline-size", "resolvedDefault": "18rem" },
294
+ { "name": "--cascivo-link-color", "resolvedDefault": "oklch(0.52 0.2 250)" },
295
+ { "name": "--cascivo-search-width", "resolvedDefault": "100%" },
294
296
  { "name": "--cascivo-screen-sm", "resolvedDefault": "30rem" },
295
297
  { "name": "--cascivo-screen-md", "resolvedDefault": "40rem" },
296
298
  { "name": "--cascivo-screen-lg", "resolvedDefault": "64rem" },
@@ -358,6 +360,7 @@
358
360
  "name": "--cascivo-focus-ring",
359
361
  "resolvedDefault": "0 0 0 var(--cascivo-ring-width) var(--cascivo-ring-color)"
360
362
  },
363
+ { "name": "--cascivo-chart-fill-opacity-overlap", "resolvedDefault": "0.125" },
361
364
  { "name": "--cascivo-color-primary-content", "resolvedDefault": "oklch(0.985 0 0)" },
362
365
  { "name": "--cascivo-color-accent-content", "resolvedDefault": "oklch(1 0 0)" },
363
366
  { "name": "--cascivo-color-destructive-content", "resolvedDefault": "oklch(1 0 0)" },
@@ -940,6 +943,7 @@
940
943
  {
941
944
  "name": "Filter",
942
945
  "props": [
946
+ { "name": "ariaLabel", "type": "string", "required": false },
943
947
  { "name": "aria-label", "type": "string", "required": false },
944
948
  { "name": "options", "type": "FilterOption[]", "required": true },
945
949
  { "name": "value", "type": "string[]", "required": false },
@@ -1003,7 +1007,7 @@
1003
1007
  {
1004
1008
  "name": "IconButton",
1005
1009
  "props": [
1006
- { "name": "label", "type": "string", "required": true },
1010
+ { "name": "label", "type": "string", "required": false },
1007
1011
  { "name": "ariaLabel", "type": "string", "required": false },
1008
1012
  { "name": "icon", "type": "React.ReactNode", "required": false },
1009
1013
  { "name": "variant", "type": "'ghost' | 'outline' | 'filled'", "required": false },
@@ -1113,7 +1117,8 @@
1113
1117
  { "name": "variant", "type": "'standalone' | 'inline'", "required": false },
1114
1118
  { "name": "size", "type": "'sm' | 'md' | 'lg'", "required": false },
1115
1119
  { "name": "external", "type": "boolean", "required": false },
1116
- { "name": "href", "type": "string", "required": false }
1120
+ { "name": "href", "type": "string", "required": false },
1121
+ { "name": "asChild", "type": "boolean", "required": false }
1117
1122
  ]
1118
1123
  },
1119
1124
  {
@@ -1173,6 +1178,7 @@
1173
1178
  { "name": "title", "type": "string", "required": false },
1174
1179
  { "name": "description", "type": "string", "required": false },
1175
1180
  { "name": "size", "type": "'sm' | 'md' | 'lg'", "required": false },
1181
+ { "name": "footer", "type": "ReactNode", "required": false },
1176
1182
  { "name": "draggable", "type": "boolean", "required": false }
1177
1183
  ]
1178
1184
  },
@@ -1321,6 +1327,7 @@
1321
1327
  {
1322
1328
  "name": "Progress",
1323
1329
  "props": [
1330
+ { "name": "ariaLabel", "type": "string", "required": false },
1324
1331
  { "name": "aria-label", "type": "string", "required": false },
1325
1332
  { "name": "aria-describedby", "type": "string", "required": false },
1326
1333
  { "name": "value", "type": "number", "required": false },
@@ -1553,7 +1560,7 @@
1553
1560
  "props": [
1554
1561
  { "name": "groups", "type": "SideNavGroup[]", "required": false },
1555
1562
  { "name": "showCollapseToggle", "type": "boolean", "required": false },
1556
- { "name": "items", "type": "SideNavItem[]", "required": true },
1563
+ { "name": "items", "type": "SideNavItem[]", "required": false },
1557
1564
  { "name": "collapsed", "type": "boolean", "required": false },
1558
1565
  { "name": "defaultCollapsed", "type": "boolean", "required": false },
1559
1566
  { "name": "onCollapsedChange", "type": "(collapsed: boolean) => void", "required": false },
@@ -1613,6 +1620,7 @@
1613
1620
  {
1614
1621
  "name": "Stat",
1615
1622
  "props": [
1623
+ { "name": "card", "type": "boolean", "required": false },
1616
1624
  { "name": "label", "type": "string", "required": true },
1617
1625
  { "name": "value", "type": "string | number", "required": true },
1618
1626
  { "name": "delta", "type": "string", "required": false },
@@ -1645,6 +1653,7 @@
1645
1653
  {
1646
1654
  "name": "StructuredList",
1647
1655
  "props": [
1656
+ { "name": "ariaLabel", "type": "string", "required": false },
1648
1657
  { "name": "aria-label", "type": "string", "required": false },
1649
1658
  {
1650
1659
  "name": "items",
@@ -2110,6 +2119,9 @@
2110
2119
  { "name": "mode", "type": "'grouped' | 'stacked' | 'percent'", "required": false },
2111
2120
  { "name": "width", "type": "number", "required": false },
2112
2121
  { "name": "height", "type": "number", "required": false },
2122
+ { "name": "valueAxisTicks", "type": "number", "required": false },
2123
+ { "name": "categoryAxisTicks", "type": "number", "required": false },
2124
+ { "name": "categoryLabelEvery", "type": "number", "required": false },
2113
2125
  { "name": "xTicks", "type": "number", "required": false },
2114
2126
  { "name": "yTicks", "type": "number", "required": false },
2115
2127
  { "name": "xLabelEvery", "type": "number", "required": false },
@@ -2326,6 +2338,11 @@
2326
2338
  { "name": "height", "type": "number", "required": false },
2327
2339
  { "name": "xTicks", "type": "number", "required": false },
2328
2340
  { "name": "yTicks", "type": "number", "required": false },
2341
+ {
2342
+ "name": "format",
2343
+ "type": "(value: number | string | Date) => string",
2344
+ "required": false
2345
+ },
2329
2346
  { "name": "legend", "type": "boolean", "required": false },
2330
2347
  { "name": "tooltip", "type": "boolean", "required": false },
2331
2348
  {
@@ -2762,6 +2779,7 @@
2762
2779
  "props": [
2763
2780
  { "name": "id", "type": "string", "required": true },
2764
2781
  { "name": "position", "type": "{ x: number; y: number }", "required": false },
2782
+ { "name": "defaultPosition", "type": "XYPosition", "required": false },
2765
2783
  { "name": "onPositionChange", "type": "(position: XYPosition) => void", "required": false },
2766
2784
  { "name": "zoom", "type": "number", "required": false },
2767
2785
  { "name": "selected", "type": "boolean", "required": false },
package/dist/index.mjs CHANGED
@@ -2543,7 +2543,7 @@ async function run(args) {
2543
2543
  break;
2544
2544
  }
2545
2545
  case "audit": {
2546
- const { audit } = await import("./audit-CX-ifnQT.mjs");
2546
+ const { audit } = await import("./audit-Cn6HJkuo.mjs");
2547
2547
  await audit(rest, await loadConfig());
2548
2548
  break;
2549
2549
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cascivo",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "private": false,
5
5
  "description": "CLI — npx cascivo init / add / list / update",
6
6
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"file":"audit-CX-ifnQT.mjs","names":["MESSAGE"],"sources":["../src/utils/contract-pure.ts","../src/audit-ai/css-literals.ts","../src/audit-ai/jsx-props.ts","../src/audit-ai/raw-strings.ts","../src/audit-ai/required-props.ts","../src/utils/css-layers.ts","../src/audit-ai/unlayered.ts","../src/audit-ai/vendor-css.ts","../src/audit-ai/suppress.ts","../src/utils/contract.ts","../src/commands/audit.ts"],"sourcesContent":["export interface PropInfo {\n name: string\n type: string\n required: boolean\n}\n\nexport interface ComponentInfo {\n props: PropInfo[]\n /** True if any prop has required: true */\n hasRequiredProps: boolean\n /** Props that have required: true */\n requiredProps: string[]\n /** True if the component declares user-facing chrome text (intent.content) */\n hasContent: boolean\n}\n\nexport interface Contract {\n /** Map from normalized color/size value → token names */\n tokensByValue: Map<string, string[]>\n /** Map from component name (PascalCase) → component info */\n components: Map<string, ComponentInfo>\n}\n\ninterface TokenEntry {\n name: string\n resolvedDefault: string | null\n}\n\ninterface CatalogFile {\n tokens: TokenEntry[]\n}\n\ninterface RegistryPropMeta {\n name: string\n type?: string\n required?: boolean\n}\n\ninterface RegistryComponentMeta {\n name: string\n props?: RegistryPropMeta[]\n}\n\ninterface RegistryEntry {\n meta?: RegistryComponentMeta\n}\n\ninterface RegistryFile {\n components: RegistryEntry[]\n}\n\ninterface ContextComponentEntry {\n name: string\n intent?: { content?: unknown }\n}\n\ninterface ContextFile {\n components: ContextComponentEntry[]\n}\n\nexport interface BuildContractInput {\n catalog: CatalogFile\n registry: RegistryFile\n context: ContextFile\n}\n\n/** Normalize a color/size value for catalog comparison: lowercase, strip spaces. */\nexport function normalizeValue(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, '')\n}\n\n/** Pure builder — assemble a Contract from already-parsed JSON. Testable without fs. */\nexport function buildContract(input: BuildContractInput): Contract {\n const tokensByValue = new Map<string, string[]>()\n for (const token of input.catalog.tokens) {\n if (token.resolvedDefault == null) continue\n const key = normalizeValue(token.resolvedDefault)\n const list = tokensByValue.get(key)\n if (list) list.push(token.name)\n else tokensByValue.set(key, [token.name])\n }\n\n const contentNames = new Set<string>()\n for (const c of input.context.components) {\n if (c.intent?.content) contentNames.add(c.name)\n }\n\n const components = new Map<string, ComponentInfo>()\n for (const entry of input.registry.components) {\n const meta = entry.meta\n if (!meta?.name) continue\n const props: PropInfo[] = (meta.props ?? []).map((p) => ({\n name: p.name,\n type: p.type ?? 'unknown',\n required: p.required === true,\n }))\n const requiredProps = props.filter((p) => p.required).map((p) => p.name)\n components.set(meta.name, {\n props,\n requiredProps,\n hasRequiredProps: requiredProps.length > 0,\n hasContent: contentNames.has(meta.name),\n })\n }\n\n return { tokensByValue, components }\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport { normalizeValue } from '../utils/contract-pure.js'\n\nexport interface LiteralFinding {\n file: string\n line: number\n property: string\n value: string\n level: 'error' | 'warn' | 'info'\n rule: 'hardcoded-value'\n /** only when exactly one catalog match */\n suggestedToken?: string\n /** when multiple catalog matches → info */\n allMatches?: string[]\n}\n\n/** Visual CSS properties whose literal values should be tokens. */\nconst VISUAL_PROPS = new Set([\n 'color',\n 'background',\n 'background-color',\n 'border-color',\n 'box-shadow',\n 'border-radius',\n 'font-size',\n 'gap',\n 'padding',\n 'margin',\n 'width',\n 'height',\n])\n\n/** Inline-style camelCase → kebab-case for the props we care about. */\nconst INLINE_PROP_MAP: Record<string, string> = {\n color: 'color',\n background: 'background',\n backgroundColor: 'background-color',\n borderColor: 'border-color',\n boxShadow: 'box-shadow',\n borderRadius: 'border-radius',\n fontSize: 'font-size',\n gap: 'gap',\n padding: 'padding',\n margin: 'margin',\n width: 'width',\n height: 'height',\n}\n\n/** A literal value worth checking: hex, oklch/rgb/hsl(a), or px/rem number. */\nfunction isLiteralValue(value: string): boolean {\n const v = value.trim()\n if (v.includes('var(')) return false\n if (/^#[0-9a-fA-F]{3,8}$/.test(v)) return true\n if (/^(oklch|oklab|rgb|rgba|hsl|hsla)\\(/i.test(v)) return true\n if (/^-?\\d*\\.?\\d+(px|rem)$/.test(v)) return true\n return false\n}\n\nfunction classify(\n value: string,\n contract: Contract,\n): Pick<LiteralFinding, 'level' | 'suggestedToken' | 'allMatches'> | null {\n const matches = contract.tokensByValue.get(normalizeValue(value))\n if (!matches || matches.length === 0) return null\n const first = matches[0]\n if (matches.length === 1 && first) return { level: 'error', suggestedToken: first }\n return { level: 'info', allMatches: matches }\n}\n\n/**\n * Detect literal color/size values in CSS declarations and TSX inline styles\n * that exactly match a known cascade token. Heuristic, line-based — no full\n * CSS/JS parse. Values with no catalog match are NOT flagged (arbitrary brand\n * values are allowed).\n */\nexport function findCssLiteralViolations(\n source: string,\n filename: string,\n contract: Contract,\n): LiteralFinding[] {\n const findings: LiteralFinding[] = []\n const lines = source.split('\\n')\n\n // CSS declaration: `property: value;` (also matches the kebab props inside style=\"...\")\n const cssDecl = /(^|[;{\\s])([a-z-]+)\\s*:\\s*([^;}{]+?)\\s*(?=[;}]|$)/gi\n // Inline JSX style object: `color: '#fff'` or `color: \"#fff\"`\n const inlineDecl = /([A-Za-z][A-Za-z]*)\\s*:\\s*(['\"])([^'\"]+)\\2/g\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]\n if (line === undefined) continue\n const seen = new Set<string>()\n\n for (const m of line.matchAll(cssDecl)) {\n if (m[2] === undefined || m[3] === undefined) continue\n const prop = m[2].toLowerCase()\n const rawValue = m[3].trim()\n if (!VISUAL_PROPS.has(prop)) continue\n if (!isLiteralValue(rawValue)) continue\n const cls = classify(rawValue, contract)\n if (!cls) continue\n const key = `${prop}|${rawValue}`\n seen.add(key)\n findings.push({\n file: filename,\n line: i + 1,\n property: prop,\n value: rawValue,\n rule: 'hardcoded-value',\n ...cls,\n })\n }\n\n for (const m of line.matchAll(inlineDecl)) {\n if (m[1] === undefined || m[3] === undefined) continue\n const prop = INLINE_PROP_MAP[m[1]]\n if (!prop) continue\n const rawValue = m[3].trim()\n if (!isLiteralValue(rawValue)) continue\n const key = `${prop}|${rawValue}`\n if (seen.has(key)) continue\n const cls = classify(rawValue, contract)\n if (!cls) continue\n // Inline TSX `style={{…}}` overrides are a sanctioned fast-prototyping escape\n // hatch — surface a gentle `warn` (not a loop-blocking `error`) so an agent can\n // finish. `.css`-file literals stay `error`: there the fix is mechanical (`--fix`).\n const inlineCls = cls.level === 'error' ? { ...cls, level: 'warn' as const } : cls\n findings.push({\n file: filename,\n line: i + 1,\n property: prop,\n value: rawValue,\n rule: 'hardcoded-value',\n ...inlineCls,\n })\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\n\nexport interface PropFinding {\n file: string\n line: number\n component: string\n prop: string\n level: 'error' | 'info'\n rule: 'unknown-prop' | 'spread-suppressed'\n message: string\n}\n\n/** Props always allowed on any cascade component (DOM passthrough / React intrinsics). */\nconst PASSTHROUGH = new Set(['className', 'style', 'id', 'ref', 'key', 'children'])\n\n/**\n * Standard HTML/React DOM attributes. Every cascade component extends an\n * `HTMLAttributes` interface and spreads `{...props}` onto its element (verified\n * in button.tsx, card.tsx, …), so these are valid at runtime even though the\n * hand-written `*.meta.ts` prop lists (the audit contract) don't enumerate them.\n * Without this set, a legitimate `type`/`name`/`title`/`tabIndex` on a Button is\n * a non-suppressible `unknown-prop` error — the audit-loop deadlock.\n */\nconst HTML_PASSTHROUGH = new Set([\n 'type',\n 'name',\n 'value',\n 'defaultValue',\n 'checked',\n 'defaultChecked',\n 'placeholder',\n 'title',\n 'role',\n 'tabIndex',\n 'form',\n 'href',\n 'target',\n 'rel',\n 'download',\n 'src',\n 'alt',\n 'width',\n 'height',\n 'loading',\n 'autoComplete',\n 'autoFocus',\n 'required',\n 'readOnly',\n 'min',\n 'max',\n 'step',\n 'rows',\n 'cols',\n 'wrap',\n 'maxLength',\n 'minLength',\n 'pattern',\n 'multiple',\n 'accept',\n 'size',\n 'dir',\n 'lang',\n 'hidden',\n 'draggable',\n 'spellCheck',\n 'contentEditable',\n 'inputMode',\n 'enterKeyHint',\n 'htmlFor',\n 'slot',\n 'disabled',\n 'open',\n])\n\nfunction isPassthrough(prop: string): boolean {\n if (PASSTHROUGH.has(prop)) return true\n if (HTML_PASSTHROUGH.has(prop)) return true\n if (prop.startsWith('data-')) return true\n if (prop.startsWith('aria-')) return true\n if (/^on[A-Z]/.test(prop)) return true\n return false\n}\n\n/** Names imported from @cascivo/react in this source. */\nexport function importedCascadeComponents(source: string): Set<string> {\n const names = new Set<string>()\n const importRe = /import\\s*\\{([^}]*)\\}\\s*from\\s*['\"]@cascivo\\/react['\"]/g\n for (const m of source.matchAll(importRe)) {\n const group = m[1]\n if (group === undefined) continue\n for (const raw of group.split(',')) {\n const name = raw\n .trim()\n .split(/\\s+as\\s+/)[0]\n ?.trim()\n if (name) names.add(name)\n }\n }\n return names\n}\n\n/** Find each opening tag for `comp`, returning its attribute substring + start index. */\nexport interface OpeningTag {\n attrs: string\n index: number\n hasSpread: boolean\n}\n\nexport function findOpeningTags(source: string, comp: string): OpeningTag[] {\n const tags: OpeningTag[] = []\n const re = new RegExp(`<${comp}(?=[\\\\s/>])`, 'g')\n for (const m of source.matchAll(re)) {\n const start = m.index ?? 0\n // Walk forward to the matching '>' that closes the opening tag, respecting\n // nested braces (JSX expressions) and quoted strings.\n let i = start + m[0].length\n let depth = 0\n let quote = ''\n let attrs = ''\n let closed = false\n for (; i < source.length; i++) {\n const ch = source[i]\n if (quote) {\n if (ch === quote) quote = ''\n attrs += ch\n continue\n }\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n quote = ch\n attrs += ch\n continue\n }\n if (ch === '{') depth++\n else if (ch === '}') depth--\n else if (ch === '>' && depth === 0) {\n closed = true\n break\n }\n attrs += ch\n }\n if (!closed) continue\n const cleanAttrs = attrs.replace(/\\/$/, '')\n tags.push({ attrs: cleanAttrs, index: start, hasSpread: /\\{\\s*\\.\\.\\./.test(cleanAttrs) })\n }\n return tags\n}\n\n/** Extract top-level attribute names from an opening-tag attribute string. */\nexport function extractAttrNames(attrs: string): string[] {\n const names: string[] = []\n let depth = 0\n let quote = ''\n let token = ''\n const flush = () => {\n const name = token.trim().split('=')[0]?.trim()\n if (name && /^[A-Za-z]/.test(name)) names.push(name)\n token = ''\n }\n for (let i = 0; i < attrs.length; i++) {\n const ch = attrs[i]\n if (ch === undefined) continue\n if (quote) {\n if (ch === quote) quote = ''\n continue\n }\n if (ch === '\"' || ch === \"'\" || ch === '`') {\n quote = ch\n continue\n }\n if (ch === '{') {\n depth++\n continue\n }\n if (ch === '}') {\n depth--\n continue\n }\n if (depth > 0) continue\n if (ch === '=') {\n flush()\n // skip the value: handled by quote/brace state on next chars; reset token\n token = ''\n continue\n }\n if (/\\s/.test(ch)) {\n if (token.trim()) flush()\n continue\n }\n token += ch\n }\n if (token.trim()) flush()\n return names\n}\n\nexport function lineOf(source: string, index: number): number {\n let line = 1\n for (let i = 0; i < index && i < source.length; i++) {\n if (source[i] === '\\n') line++\n }\n return line\n}\n\n/**\n * Check JSX usages of imported cascade components for unknown props.\n * Heuristic — regex/brace-aware scan, not a full AST. Elements using a spread\n * (`{...rest}`) are reported as info and skipped (props can't be statically known).\n */\nexport function findJsxPropViolations(\n source: string,\n filename: string,\n contract: Contract,\n): PropFinding[] {\n const findings: PropFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const comp of tracked) {\n const info = contract.components.get(comp)\n if (!info) continue\n const known = new Set(info.props.map((p) => p.name))\n\n for (const tag of findOpeningTags(source, comp)) {\n const line = lineOf(source, tag.index)\n if (tag.hasSpread) {\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: '...',\n level: 'info',\n rule: 'spread-suppressed',\n message: `<${comp}> uses a spread — prop checks skipped`,\n })\n continue\n }\n for (const name of extractAttrNames(tag.attrs)) {\n if (isPassthrough(name)) continue\n if (known.has(name)) continue\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: name,\n level: 'error',\n rule: 'unknown-prop',\n message:\n `<${comp}> has unknown prop \"${name}\". ` +\n 'style/className pass through on every component (see the override ladder in ' +\n 'docs/AI-RULES.md); for an intentional one-off add `/* cascivo-audit: allow unknown-prop */`.',\n })\n }\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport { findOpeningTags, importedCascadeComponents, lineOf } from './jsx-props.js'\n\nexport interface RawStringFinding {\n file: string\n line: number\n component: string\n text: string\n level: 'warn'\n rule: 'raw-string'\n message: string\n}\n\n/** Looks like English prose worth flagging: ≥2 whitespace-separated words, letters/spaces only. */\nfunction looksLikeProse(text: string): boolean {\n const trimmed = text.trim()\n if (!/^[A-Za-z][A-Za-z\\s]*$/.test(trimmed)) return false\n return trimmed.split(/\\s+/).length >= 2\n}\n\n/**\n * Conservative raw-string check: for cascade components that own user-facing\n * chrome text (intent.content), warn when a literal multi-word English child\n * appears, suggesting the labels prop / i18n. Never errors. Only inspects the\n * immediate text directly after the opening tag (no nested element traversal).\n */\nexport function findRawStringViolations(\n source: string,\n filename: string,\n contract: Contract,\n): RawStringFinding[] {\n const findings: RawStringFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const comp of tracked) {\n const info = contract.components.get(comp)\n if (!info?.hasContent) continue\n\n for (const tag of findOpeningTags(source, comp)) {\n // Locate the end of this opening tag in the source.\n const openEnd = source.indexOf('>', tag.index)\n if (openEnd === -1) continue\n if (source[openEnd - 1] === '/') continue // self-closing, no children\n\n // Grab text up to the next tag/expression boundary.\n const after = source.slice(openEnd + 1)\n const stop = after.search(/[<{]/)\n const child = (stop === -1 ? after : after.slice(0, stop)).trim()\n if (!child || !looksLikeProse(child)) continue\n\n findings.push({\n file: filename,\n line: lineOf(source, openEnd),\n component: comp,\n text: child,\n level: 'warn',\n rule: 'raw-string',\n message: `<${comp}> raw text \"${child}\" — use the labels prop / i18n`,\n })\n }\n }\n\n return findings\n}\n","import type { Contract } from '../utils/contract-pure.js'\nimport {\n extractAttrNames,\n findOpeningTags,\n importedCascadeComponents,\n lineOf,\n} from './jsx-props.js'\n\nexport interface RequiredPropFinding {\n file: string\n line: number\n component: string\n prop: string\n level: 'error'\n rule: 'missing-prop'\n message: string\n}\n\n/**\n * Flag cascade elements that omit a prop the component marks required.\n * Elements using a spread are skipped (the prop may arrive via the spread).\n */\nexport function findRequiredPropViolations(\n source: string,\n filename: string,\n contract: Contract,\n): RequiredPropFinding[] {\n const findings: RequiredPropFinding[] = []\n const tracked = importedCascadeComponents(source)\n\n for (const comp of tracked) {\n const info = contract.components.get(comp)\n if (!info?.hasRequiredProps) continue\n\n for (const tag of findOpeningTags(source, comp)) {\n if (tag.hasSpread) continue\n const present = new Set(extractAttrNames(tag.attrs))\n const line = lineOf(source, tag.index)\n for (const req of info.requiredProps) {\n if (present.has(req)) continue\n findings.push({\n file: filename,\n line,\n component: comp,\n prop: req,\n level: 'error',\n rule: 'missing-prop',\n message: `<${comp}> requires \"${req}\"`,\n })\n }\n }\n }\n\n return findings\n}\n","/**\n * Zero-dependency scanner for **unlayered style rules** in a CSS source.\n *\n * cascivo ships everything inside `@layer` blocks. Unlayered author CSS beats\n * every layered rule regardless of specificity (CSS cascade-layer semantics), so\n * a single unlayered style rule silently overrides the whole design system. This\n * scanner finds top-level style rules that live outside any `@layer` block.\n *\n * It is line-based and brace-tracking, not a full CSS parse — good enough because\n * we only need to know, for each `{`, whether an `@layer` block is an ancestor.\n *\n * Transparent to layering: `@media`, `@container`, `@supports`, `@scope` — a rule\n * inside these is layered iff the group is inside a layer. Ignored entirely:\n * `@keyframes`/`@font-face`/`@property`/`@page`/etc. (their inner blocks are not\n * style rules we govern). `@import`/`@charset`/`@layer;` statements are not blocks.\n */\n\nexport interface UnlayeredRule {\n /** 1-indexed line of the rule's selector. */\n line: number\n /** The selector text (trimmed, truncated) for the report. */\n selector: string\n}\n\n/** Replace comment bodies and string contents with spaces, preserving newlines. */\nfunction blankCommentsAndStrings(source: string): string {\n let out = ''\n let i = 0\n const n = source.length\n while (i < n) {\n const c = source[i]!\n const next = source[i + 1]\n if (c === '/' && next === '*') {\n out += ' '\n i += 2\n while (i < n && !(source[i] === '*' && source[i + 1] === '/')) {\n out += source[i] === '\\n' ? '\\n' : ' '\n i++\n }\n out += ' '\n i += 2\n } else if (c === '\"' || c === \"'\") {\n const quote = c\n out += ' '\n i++\n while (i < n && source[i] !== quote) {\n if (source[i] === '\\\\') {\n out += ' '\n i += 2\n continue\n }\n out += source[i] === '\\n' ? '\\n' : ' '\n i++\n }\n out += ' '\n i++\n } else {\n out += c\n i++\n }\n }\n return out\n}\n\ntype FrameKind = 'layer' | 'group' | 'style' | 'other'\n\n/**\n * Accessibility / user-preference media features whose overrides MUST win over\n * everything — including a consumer's `cascivo.override` layer — so they are\n * legitimately placed unlayered (top-level). A `@media (forced-colors: active)`\n * block outside `@layer` is the sanctioned cascade idiom, not a hotfix leak.\n */\nconst A11Y_GUARANTEE_RE =\n /@media[^{]*\\b(forced-colors|prefers-contrast|prefers-reduced-motion|prefers-reduced-transparency|inverted-colors)\\b/\n\nfunction classifyPrelude(prelude: string): FrameKind {\n const p = prelude.trim().toLowerCase()\n if (p.startsWith('@layer')) return 'layer'\n // A11y-guarantee media queries are an exempt (non-flagging) context.\n if (A11Y_GUARANTEE_RE.test(p)) return 'other'\n if (\n p.startsWith('@media') ||\n p.startsWith('@container') ||\n p.startsWith('@supports') ||\n p.startsWith('@scope')\n ) {\n return 'group'\n }\n if (p.startsWith('@')) return 'other'\n return 'style'\n}\n\n/**\n * Return every top-level style rule that is NOT inside an `@layer` block. Only the\n * outermost unlayered rule is reported (nested rules inside it are implied).\n */\nexport function findUnlayeredRules(source: string): UnlayeredRule[] {\n const clean = blankCommentsAndStrings(source)\n const rules: UnlayeredRule[] = []\n const stack: FrameKind[] = []\n\n let preludeStart = 0\n const lineStarts: number[] = [0]\n for (let i = 0; i < clean.length; i++) {\n if (clean[i] === '\\n') lineStarts.push(i + 1)\n }\n const lineOf = (idx: number): number => {\n // binary search over lineStarts\n let lo = 0\n let hi = lineStarts.length - 1\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1\n if (lineStarts[mid]! <= idx) lo = mid\n else hi = mid - 1\n }\n return lo + 1\n }\n\n const hasAncestor = (kind: FrameKind): boolean => stack.includes(kind)\n\n for (let i = 0; i < clean.length; i++) {\n const c = clean[i]\n if (c === '{') {\n const prelude = clean.slice(preludeStart, i)\n const kind = classifyPrelude(prelude)\n if (\n kind === 'style' &&\n !hasAncestor('layer') &&\n !hasAncestor('other') &&\n !hasAncestor('style')\n ) {\n const trimmed = prelude.trim().replace(/\\s+/g, ' ')\n const startIdx = preludeStart + (prelude.length - prelude.trimStart().length)\n rules.push({\n line: lineOf(startIdx),\n selector: trimmed.length > 60 ? `${trimmed.slice(0, 57)}…` : trimmed,\n })\n }\n stack.push(kind)\n preludeStart = i + 1\n } else if (c === '}') {\n stack.pop()\n preludeStart = i + 1\n } else if (c === ';') {\n // A statement terminator (@import, `@layer a, b;`, or a declaration inside a\n // block). Reset the prelude window so the next `{` sees a clean selector.\n preludeStart = i + 1\n }\n }\n\n return rules\n}\n","import { findUnlayeredRules } from '../utils/css-layers.js'\n\nexport interface UnlayeredFinding {\n file: string\n line: number\n selector: string\n level: 'warn'\n rule: 'unlayered-css'\n message: string\n}\n\nconst MESSAGE =\n 'Unlayered CSS beats every cascivo layer regardless of specificity. ' +\n 'For a one-off override use `@layer cascivo.override { … }`; for app styles declare ' +\n 'an app layer (e.g. cascivo.example) in your order statement. See docs/CSS-LAYERS-PITFALL.md.'\n\n/**\n * Warn on top-level style rules that live outside any `@layer` block. This is the\n * consumer-facing half of the zero-unlayered guard: it teaches the fix rather than\n * failing the build, because `docs/USING-WITH-TAILWIND.md` blesses deliberate\n * unlayered CSS as a valid interop escape hatch. Accessibility-guarantee media\n * queries (`forced-colors`, `prefers-contrast`, …) are exempt — see css-layers.ts.\n */\nexport function findUnlayeredViolations(source: string, filename: string): UnlayeredFinding[] {\n return findUnlayeredRules(source).map((rule) => ({\n file: filename,\n line: rule.line,\n selector: rule.selector,\n level: 'warn',\n rule: 'unlayered-css',\n message: MESSAGE,\n }))\n}\n","import { lineOf } from './jsx-props.js'\n\nexport interface VendorCssFinding {\n file: string\n line: number\n specifier: string\n level: 'warn'\n rule: 'vendor-css-import'\n message: string\n}\n\n// `import '<spec>'` or `import x from '<spec>'` where <spec> ends in .css\n// (optionally with a ?query / #hash). Captures the specifier.\nconst CSS_IMPORT_RE = /import\\s+(?:[^'\"]*?\\bfrom\\s+)?(['\"])([^'\"]+\\.css(?:[?#][^'\"]*)?)\\1/g\n\n/** A bare specifier resolves into node_modules (not a relative or absolute path). */\nfunction isBareSpecifier(spec: string): boolean {\n return !spec.startsWith('.') && !spec.startsWith('/')\n}\n\nconst MESSAGE =\n 'CSS imported from a package through JS/TS cannot be wrapped in an @layer, so if this ' +\n 'package ships unlayered global CSS it beats every cascivo layer. Route it through a CSS ' +\n 'file (`@import url(\"<pkg>/styles.css\") layer(vendor);`) or add @cascivo/vite-plugin ' +\n '(`cascivoLayers({ imports: { \"<pkg>/styles.css\": \"vendor\" } })`). See docs/THIRD-PARTY-CSS.md.'\n\n/**\n * Warn on bare (node_modules) `*.css` imports in JS/TS. Relative imports (the\n * consumer's own CSS modules) and cascivo's own already-layered `@cascivo/*`\n * stylesheets are exempt. Level `warn` — teaches the layer(vendor) recipe.\n */\nexport function findVendorCssImports(source: string, filename: string): VendorCssFinding[] {\n const findings: VendorCssFinding[] = []\n for (const m of source.matchAll(CSS_IMPORT_RE)) {\n const spec = m[2]\n if (spec === undefined) continue\n if (!isBareSpecifier(spec)) continue\n // cascivo's own stylesheets ship the layer statement + fully-layered rules.\n if (spec.startsWith('@cascivo/')) continue\n findings.push({\n file: filename,\n line: lineOf(source, m.index ?? 0),\n specifier: spec,\n level: 'warn',\n rule: 'vendor-css-import',\n message: MESSAGE,\n })\n }\n return findings\n}\n","/**\n * Inline suppression directives for `cascivo audit --ai`.\n *\n * A comment `cascivo-audit: allow <rule-id>[, <rule-id>…]` (or `allow all`) on the\n * same line as, or the line immediately preceding, a finding downgrades that\n * finding: it is marked `suppressed` so it no longer counts toward the error/warn\n * exit gate, while still being printed so it stays visible. This is the guaranteed\n * loop-breaker for an AI agent — the one escape hatch that no rule can override.\n */\n\n/** Rule ids a directive may name (the user-facing error/warn rules). */\nexport const AUDIT_RULES = new Set<string>([\n 'unknown-prop',\n 'hardcoded-value',\n 'missing-prop',\n 'raw-string',\n 'unlayered-css',\n 'vendor-css-import',\n])\n\nexport interface DirectiveFinding {\n file: string\n line: number\n level: 'warn'\n rule: 'audit-directive'\n message: string\n}\n\ninterface Directive {\n line: number\n rules: 'all' | Set<string>\n}\n\nconst DIRECTIVE_RE = /cascivo-audit:\\s*allow\\s+([^\\n]+)/i\n\n/**\n * Scan a source file for suppression directives. Returns the parsed directives\n * plus `warn`-level findings for any unknown rule id (so typos surface rather\n * than silently failing to suppress).\n */\nexport function parseDirectives(\n source: string,\n file: string,\n): { directives: Directive[]; findings: DirectiveFinding[] } {\n const directives: Directive[] = []\n const findings: DirectiveFinding[] = []\n const lines = source.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const m = lines[i]?.match(DIRECTIVE_RE)\n if (!m || m[1] === undefined) continue\n // Strip trailing comment terminators (`*/`, `-->`) and whitespace.\n const raw = m[1]\n .replace(/\\*\\/.*$/, '')\n .replace(/-->.*$/, '')\n .trim()\n const ids = raw.split(/[\\s,]+/).filter(Boolean)\n const line = i + 1\n if (ids.includes('all')) {\n directives.push({ line, rules: 'all' })\n continue\n }\n const valid = new Set<string>()\n const unknown: string[] = []\n for (const id of ids) {\n if (AUDIT_RULES.has(id)) valid.add(id)\n else unknown.push(id)\n }\n if (valid.size > 0) directives.push({ line, rules: valid })\n if (unknown.length > 0) {\n findings.push({\n file,\n line,\n level: 'warn',\n rule: 'audit-directive',\n message:\n `unknown audit rule id${unknown.length > 1 ? 's' : ''} in directive: ${unknown.join(', ')}. ` +\n `valid ids: ${[...AUDIT_RULES].join(', ')}.`,\n })\n }\n }\n return { directives, findings }\n}\n\n/**\n * Mark findings covered by a directive as `suppressed`. A directive on line L\n * applies to findings on line L (inline comment) or line L+1 (comment above the\n * code). Level is left unchanged; callers exclude `suppressed` findings from the\n * exit gate.\n */\nexport function applySuppressions<T extends { line: number; rule: string }>(\n findings: T[],\n directives: Directive[],\n): Array<T & { suppressed?: boolean }> {\n if (directives.length === 0) return findings\n return findings.map((f) => {\n const covered = directives.some(\n (d) =>\n (d.line === f.line || d.line === f.line - 1) && (d.rules === 'all' || d.rules.has(f.rule)),\n )\n return covered ? { ...f, suppressed: true } : f\n })\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport type { BuildContractInput, ComponentInfo, Contract, PropInfo } from './contract-pure.js'\nexport { buildContract, normalizeValue } from './contract-pure.js'\nimport type { Contract } from './contract-pure.js'\nimport { buildContract } from './contract-pure.js'\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\n\n/** Walk up from a start directory looking for the apps/site/public dir. */\nfunction findDocsPublic(startDir: string): string | null {\n let dir = startDir\n for (let i = 0; i < 10; i++) {\n const candidate = join(dir, 'apps', 'site', 'public')\n if (existsSync(candidate)) return candidate\n dir = join(dir, '..')\n }\n return null\n}\n\n/** Walk up from a start directory looking for registry.json at the repo root. */\nfunction findRegistry(startDir: string): string | null {\n let dir = startDir\n for (let i = 0; i < 10; i++) {\n const candidate = join(dir, 'registry.json')\n if (existsSync(candidate)) return candidate\n dir = join(dir, '..')\n }\n return null\n}\n\nconst CONTRACT_URL = 'https://cascivo.com/audit-contract.json'\n\n/**\n * Download the contract, caching it by version so a second run is offline-fast. Returns\n * null on any failure — the audit must never hard-depend on the network.\n */\nasync function fetchContract(report: (source: string) => void): Promise<Contract | null> {\n try {\n const response = await fetch(CONTRACT_URL, { signal: AbortSignal.timeout(5000) })\n if (!response.ok) return null\n const bundled = (await response.json()) as BundledContract\n try {\n const target = cachePath(bundled.version)\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, JSON.stringify(bundled))\n } catch {\n // A read-only cache dir is not a reason to fail the audit.\n }\n report(`network: ${CONTRACT_URL}`)\n return fromBundled(bundled)\n } catch {\n return null\n }\n}\n\n/** The reduced contract shipped inside this package (scripts/registry/audit-contract.ts). */\ninterface BundledContract {\n version: string\n tokens: { name: string; resolvedDefault: string | null }[]\n components: { name: string; props: { name: string; type: string; required: boolean }[] }[]\n content: string[]\n}\n\n/** Adapt the bundled shape to `buildContract`'s three-artifact input. */\nfunction fromBundled(bundled: BundledContract): Contract {\n return buildContract({\n catalog: { tokens: bundled.tokens },\n registry: { components: bundled.components.map((c) => ({ meta: c })) },\n context: { components: bundled.content.map((name) => ({ name, intent: { content: true } })) },\n })\n}\n\n/** Where the network fallback caches a downloaded contract. */\nfunction cachePath(version: string): string {\n const base = process.env['XDG_CACHE_HOME'] ?? join(process.env['HOME'] ?? tmpdir(), '.cache')\n return join(base, 'cascivo', `audit-contract-${version}.json`)\n}\n\n/**\n * Load the cascade contract. Resolution order, first hit wins:\n *\n * 1. an explicit path (`--contract <file>` / `options.contractPath`)\n * 2. the dev-monorepo artifacts (`apps/site/public/…` + `registry.json`)\n * 3. the contract bundled in this package ← what makes `audit` work in a real project\n * 4. `https://cascivo.com/audit-contract.json`, cached under `~/.cache/cascivo/`\n *\n * (3) is why this exists: the walk-up in (2) only ever finds anything inside this monorepo,\n * so `cascivo audit --ai` died with \"token catalog not found\" in every consumer project —\n * a documented, working feature that nobody outside this repo could run. (4) is best-effort\n * and never required: `audit` works offline.\n */\nexport async function loadContract(options?: {\n catalogPath?: string\n contextPath?: string\n registryPath?: string\n /** Explicit contract file — either the bundled shape or a docs-public directory. */\n contractPath?: string\n /** Report which tier answered (used by `--verbose`). */\n onResolve?: (source: string) => void\n}): Promise<Contract> {\n const report = options?.onResolve ?? (() => {})\n\n // 1. Explicit path.\n if (options?.contractPath) {\n if (!existsSync(options.contractPath)) {\n throw new Error(`contract file not found: ${options.contractPath}`)\n }\n report(`explicit: ${options.contractPath}`)\n return fromBundled(JSON.parse(readFileSync(options.contractPath, 'utf8')) as BundledContract)\n }\n\n // 2. Dev monorepo — unchanged, so in-repo behavior and its tests are untouched.\n const docsPublic = findDocsPublic(HERE) ?? findDocsPublic(process.cwd())\n const catalogPath =\n options?.catalogPath ?? (docsPublic ? join(docsPublic, 'tokens.catalog.json') : null)\n const contextPath = options?.contextPath ?? (docsPublic ? join(docsPublic, 'context.json') : null)\n const registryPath = options?.registryPath ?? findRegistry(HERE) ?? findRegistry(process.cwd())\n const haveMonorepo =\n catalogPath &&\n existsSync(catalogPath) &&\n registryPath &&\n existsSync(registryPath) &&\n contextPath &&\n existsSync(contextPath)\n\n if (!haveMonorepo) {\n // 3. Bundled contract.\n const bundled = join(HERE, 'generated', 'audit-contract.json')\n const bundledDist = join(HERE, '..', 'generated', 'audit-contract.json')\n for (const candidate of [bundled, bundledDist]) {\n if (existsSync(candidate)) {\n report(`bundled: ${candidate}`)\n return fromBundled(JSON.parse(readFileSync(candidate, 'utf8')) as BundledContract)\n }\n }\n\n // 4. Network, with a local cache. Best-effort: a failure falls through to the error below.\n const fetched = await fetchContract(report)\n if (fetched) return fetched\n\n throw new Error(\n 'cascivo contract unavailable. Pass --contract <path> to a downloaded ' +\n 'audit-contract.json, or run inside the cascivo monorepo. ' +\n '(The CLI normally ships one; this build appears to be missing it.)',\n )\n }\n report('monorepo artifacts')\n\n const catalog = JSON.parse(readFileSync(catalogPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['catalog']\n const registry = JSON.parse(readFileSync(registryPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['registry']\n const context = JSON.parse(readFileSync(contextPath, 'utf8')) as Parameters<\n typeof buildContract\n >[0]['context']\n\n return buildContract({ catalog, registry, context })\n}\n","import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'\nimport { extname, join } from 'node:path'\nimport type { LiteralFinding } from '../audit-ai/css-literals.js'\nimport { findCssLiteralViolations } from '../audit-ai/css-literals.js'\nimport type { PropFinding } from '../audit-ai/jsx-props.js'\nimport { findJsxPropViolations } from '../audit-ai/jsx-props.js'\nimport type { RawStringFinding } from '../audit-ai/raw-strings.js'\nimport { findRawStringViolations } from '../audit-ai/raw-strings.js'\nimport type { RequiredPropFinding } from '../audit-ai/required-props.js'\nimport { findRequiredPropViolations } from '../audit-ai/required-props.js'\nimport type { UnlayeredFinding } from '../audit-ai/unlayered.js'\nimport { findUnlayeredViolations } from '../audit-ai/unlayered.js'\nimport type { VendorCssFinding } from '../audit-ai/vendor-css.js'\nimport { findVendorCssImports } from '../audit-ai/vendor-css.js'\nimport type { DirectiveFinding } from '../audit-ai/suppress.js'\nimport { applySuppressions, parseDirectives } from '../audit-ai/suppress.js'\nimport type { CascadeConfig } from '../utils/config.js'\nimport type { Contract } from '../utils/contract.js'\nimport { loadContract } from '../utils/contract.js'\n\nexport type Finding =\n | LiteralFinding\n | PropFinding\n | RequiredPropFinding\n | RawStringFinding\n | UnlayeredFinding\n | VendorCssFinding\n | DirectiveFinding\n\n/** A finding after suppression directives have been applied. */\nexport type AuditedFinding = Finding & { suppressed?: boolean }\n\nconst SKIP_DIRS = new Set(['node_modules', 'dist', '.git', 'build', '.next', 'coverage'])\n\nfunction collectFiles(paths: string[]): string[] {\n const out: string[] = []\n const walk = (p: string) => {\n if (!existsSync(p)) return\n const s = statSync(p)\n if (s.isDirectory()) {\n const base = p.split('/').pop() ?? ''\n if (SKIP_DIRS.has(base)) return\n for (const entry of readdirSync(p)) walk(join(p, entry))\n return\n }\n const ext = extname(p)\n if (ext === '.css' || ext === '.tsx' || ext === '.ts') out.push(p)\n }\n for (const p of paths) walk(p)\n return out\n}\n\nfunction findingsFor(file: string, source: string, contract: Contract): Finding[] {\n const ext = extname(file)\n const findings: Finding[] = []\n if (ext === '.css') {\n findings.push(...findCssLiteralViolations(source, file, contract))\n findings.push(...findUnlayeredViolations(source, file))\n } else if (ext === '.tsx' || ext === '.ts') {\n findings.push(...findCssLiteralViolations(source, file, contract))\n findings.push(...findJsxPropViolations(source, file, contract))\n findings.push(...findRequiredPropViolations(source, file, contract))\n findings.push(...findRawStringViolations(source, file, contract))\n findings.push(...findVendorCssImports(source, file))\n }\n return findings\n}\n\nfunction detail(f: Finding): string {\n switch (f.rule) {\n case 'hardcoded-value':\n if (f.suggestedToken) return `${f.value} → var(${f.suggestedToken})`\n return `${f.value} → ${f.allMatches?.join(' | ') ?? '(ambiguous)'}`\n case 'unknown-prop':\n return `<${f.component} ${f.prop}>`\n case 'spread-suppressed':\n return `<${f.component} {...}> (props not checked)`\n case 'missing-prop':\n return `<${f.component}> requires \"${f.prop}\"`\n case 'raw-string':\n return `\"${f.text}\" → use labels prop / i18n`\n case 'unlayered-css':\n return `${f.selector} { … } → wrap in @layer`\n case 'vendor-css-import':\n return `import '${f.specifier}' → @import url(…) layer(vendor)`\n case 'audit-directive':\n return f.message\n }\n}\n\nfunction levelLabel(level: Finding['level']): string {\n return level === 'warn' ? 'warn' : level\n}\n\nfunction renderFindings(findings: AuditedFinding[]): void {\n if (findings.length === 0) {\n console.log('cascade audit --ai: no findings.')\n return\n }\n const rows = findings.map((f) => ({\n loc: `${f.file}:${f.line}`,\n level: f.suppressed ? 'suppressed' : levelLabel(f.level),\n rule: f.rule,\n detail: detail(f),\n }))\n const locW = Math.max(...rows.map((r) => r.loc.length), 8)\n const lvlW = Math.max(...rows.map((r) => r.level.length), 5)\n const ruleW = Math.max(...rows.map((r) => r.rule.length), 4)\n for (const r of rows) {\n console.log(\n `${r.loc.padEnd(locW)} ${r.level.padEnd(lvlW)} ${r.rule.padEnd(ruleW)} ${r.detail}`,\n )\n }\n console.log('---')\n const active = findings.filter((f) => !f.suppressed)\n const errors = active.filter((f) => f.level === 'error').length\n const warnings = active.filter((f) => f.level === 'warn').length\n const infos = active.filter((f) => f.level === 'info').length\n const suppressed = findings.filter((f) => f.suppressed).length\n const parts = [\n `${errors} error${errors === 1 ? '' : 's'}`,\n `${warnings} warning${warnings === 1 ? '' : 's'}`,\n ]\n if (infos) parts.push(`${infos} info`)\n if (suppressed) parts.push(`${suppressed} suppressed`)\n console.log(parts.join(', '))\n}\n\nfunction escapeRe(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Pure literal→token rewrite. Only rewrites simple `property: #hex;` style\n * declarations where exactly one token matches. Returns the new source and how\n * many findings were resolved (verified by re-running the checker).\n */\nexport function fixCssLiterals(\n source: string,\n file: string,\n contract: Contract,\n): { source: string; fixed: number } {\n const fixable = findCssLiteralViolations(source, file, contract).filter(\n (f) => f.level === 'error' && f.suggestedToken && /^#[0-9a-fA-F]{3,8}$/.test(f.value),\n )\n let next = source\n for (const f of fixable) {\n // Only rewrite a full-value declaration: `prop: #hex;` (or end of block).\n const re = new RegExp(`(${escapeRe(f.property)}\\\\s*:\\\\s*)${escapeRe(f.value)}(\\\\s*[;}])`, 'gi')\n next = next.replace(re, `$1var(${f.suggestedToken})$2`)\n }\n if (next === source) return { source, fixed: 0 }\n const remaining = findCssLiteralViolations(next, file, contract).filter(\n (f) => f.level === 'error' && f.suggestedToken,\n ).length\n return { source: next, fixed: fixable.length - remaining }\n}\n\n/** Apply {@link fixCssLiterals} to each .css file on disk. */\nfunction applyFixes(files: string[], contract: Contract): number {\n let fixed = 0\n for (const file of files) {\n if (extname(file) !== '.css') continue\n const { source, fixed: n } = fixCssLiterals(readFileSync(file, 'utf8'), file, contract)\n if (n > 0) {\n writeFileSync(file, source)\n fixed += n\n }\n }\n return fixed\n}\n\nexport async function audit(args: string[], _config: CascadeConfig): Promise<void> {\n if (!args.includes('--ai')) {\n console.log('cascivo audit: use --ai to audit AI-generated code against the cascivo contract')\n console.log(' --ai [paths…] audit files against the cascivo contract')\n console.log(' --fix rewrite hardcoded values to tokens where unambiguous')\n console.log(' --json machine-readable findings')\n console.log(' --level <level> minimum level to report (error|warning|info)')\n console.log(' --contract <path> use this audit-contract.json instead of the bundled one')\n console.log(' --verbose report which contract source was used')\n return\n }\n\n const jsonOutput = args.includes('--json')\n const fixMode = args.includes('--fix')\n const verbose = args.includes('--verbose')\n const levelIdx = args.indexOf('--level')\n const minLevel = levelIdx >= 0 ? (args[levelIdx + 1] ?? 'error') : 'error'\n const contractIdx = args.indexOf('--contract')\n const contractPath = contractIdx >= 0 ? args[contractIdx + 1] : undefined\n\n const paths = args.filter((a, i) => {\n if (a.startsWith('--')) return false\n if (levelIdx >= 0 && i === levelIdx + 1) return false\n if (contractIdx >= 0 && i === contractIdx + 1) return false\n return true\n })\n\n let contract: Contract\n try {\n contract = await loadContract({\n ...(contractPath ? { contractPath } : {}),\n ...(verbose ? { onResolve: (source: string) => console.error(`contract ← ${source}`) } : {}),\n })\n } catch (e) {\n console.error(`Contract unavailable: ${e instanceof Error ? e.message : String(e)}`)\n process.exitCode = 2\n return\n }\n\n const files = collectFiles(paths.length ? paths : [process.cwd()])\n\n if (fixMode) {\n const n = applyFixes(files, contract)\n console.log(`cascade audit --ai --fix: rewrote ${n} literal${n === 1 ? '' : 's'} to tokens.`)\n }\n\n const allFindings: AuditedFinding[] = []\n for (const file of files) {\n const source = readFileSync(file, 'utf8')\n const { directives, findings: directiveFindings } = parseDirectives(source, file)\n allFindings.push(...applySuppressions(findingsFor(file, source, contract), directives))\n allFindings.push(...directiveFindings)\n }\n\n if (jsonOutput) {\n console.log(JSON.stringify(allFindings, null, 2))\n } else {\n renderFindings(allFindings)\n }\n\n // Suppressed findings never fail the run — that is the escape hatch's whole point.\n const active = allFindings.filter((f) => !f.suppressed)\n const hasErrors = active.some((f) => f.level === 'error')\n if (minLevel === 'error' && hasErrors) process.exitCode = 1\n if (minLevel === 'warn' && active.some((f) => f.level !== 'info')) process.exitCode = 1\n}\n"],"mappings":"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"}