basalt-ui 1.33.0 → 1.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/MIGRATING.md +108 -15
  4. package/README.md +3 -0
  5. package/agent/skills/basalt-app/SKILL.md +5 -3
  6. package/configs/oxlint-basalt.json +33 -0
  7. package/configs/oxlint-plugin.js +21 -6
  8. package/configs/oxlint-plugin.test.ts +98 -10
  9. package/configs/oxlint.json +2 -30
  10. package/dist/cli/check-theme.d.ts.map +1 -1
  11. package/dist/cli/check-theme.js +37 -36
  12. package/dist/cli/doctor.d.ts.map +1 -1
  13. package/dist/cli/doctor.js +3 -5
  14. package/dist/cli/guard-hook.d.ts.map +1 -1
  15. package/dist/cli/guard-hook.js +6 -34
  16. package/dist/cli/index.d.ts +29 -61
  17. package/dist/cli/index.d.ts.map +1 -1
  18. package/dist/cli/index.js +63 -19
  19. package/dist/cli/sync.d.ts.map +1 -1
  20. package/dist/cli/sync.js +7 -16
  21. package/dist/common/vx-families.d.ts +7 -0
  22. package/dist/common/vx-families.d.ts.map +1 -0
  23. package/dist/common/vx-families.js +32 -0
  24. package/dist/common/vx-family.d.ts +11 -0
  25. package/dist/common/vx-family.d.ts.map +1 -0
  26. package/dist/common/vx-family.js +12 -0
  27. package/dist/guard/index.d.ts +2 -2
  28. package/dist/guard/index.d.ts.map +1 -1
  29. package/dist/guard/index.js +11 -13
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +0 -2
  33. package/dist/shell/app-mobile-nav.d.ts.map +1 -1
  34. package/dist/shell/app-mobile-nav.js +2 -1
  35. package/dist/shell/app-mobile-nav.module.css +12 -0
  36. package/dist/shell/app-sidebar.d.ts.map +1 -1
  37. package/dist/shell/app-sidebar.js +32 -36
  38. package/dist/shell/app-sidebar.module.css +6 -0
  39. package/dist/shell/index.d.ts +0 -1
  40. package/dist/shell/index.d.ts.map +1 -1
  41. package/dist/shell/index.js +0 -2
  42. package/dist/shell/nav-glyph.d.ts +14 -0
  43. package/dist/shell/nav-glyph.d.ts.map +1 -0
  44. package/dist/shell/nav-glyph.js +21 -0
  45. package/dist/shell/nav-types.d.ts +1 -0
  46. package/dist/shell/nav-types.d.ts.map +1 -1
  47. package/dist/shell/sidebar-search.d.ts.map +1 -1
  48. package/dist/shell/sidebar-search.js +1 -3
  49. package/dist/surfaces.d.ts +2 -2
  50. package/dist/surfaces.js +2 -2
  51. package/dist/tokens/index.d.ts +1 -1
  52. package/dist/tokens/index.d.ts.map +1 -1
  53. package/dist/tokens/index.js +17 -1
  54. package/dist/tokens/size-classes.d.ts +12 -0
  55. package/dist/tokens/size-classes.d.ts.map +1 -1
  56. package/dist/tokens/size-classes.js +11 -5
  57. package/llms.txt +4 -4
  58. package/package.json +1 -1
  59. package/src/cli/check-theme.ts +60 -37
  60. package/src/cli/doctor.ts +3 -5
  61. package/src/cli/guard-hook.ts +8 -35
  62. package/src/cli/index.ts +102 -91
  63. package/src/cli/sync.ts +7 -16
  64. package/src/common/vx-families.ts +36 -0
  65. package/src/common/vx-family.ts +22 -0
  66. package/src/guard/index.ts +22 -25
  67. package/src/index.ts +0 -2
  68. package/src/shell/app-mobile-nav.module.css +12 -0
  69. package/src/shell/app-mobile-nav.tsx +8 -1
  70. package/src/shell/app-sidebar.module.css +6 -0
  71. package/src/shell/app-sidebar.tsx +52 -50
  72. package/src/shell/index.tsx +0 -1
  73. package/src/shell/nav-glyph.tsx +38 -0
  74. package/src/shell/nav-types.ts +1 -0
  75. package/src/shell/sidebar-search.tsx +1 -5
  76. package/src/surfaces.ts +2 -2
  77. package/src/tokens/index.ts +28 -1
  78. package/src/tokens/size-classes.ts +18 -5
  79. package/dist/shell/use-breakpoint.d.ts +0 -10
  80. package/dist/shell/use-breakpoint.d.ts.map +0 -1
  81. package/dist/shell/use-breakpoint.js +0 -11
  82. package/src/shell/use-breakpoint.ts +0 -37
@@ -1,8 +1,7 @@
1
- import { readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
3
  import {
4
4
  checkSource,
5
- DEFAULT_GUARD_CONFIG,
6
5
  guardKindRemedy,
7
6
  TOKENS_ONLY_DISABLED_KINDS,
8
7
  unmatchedExemptPatterns
@@ -10,30 +9,50 @@ import {
10
9
  import { auditAllows } from "./audit-allows.js";
11
10
  import { DEFAULT_ROOTS, resolveRoots } from "./config.js";
12
11
  import {
12
+ basaltPresetEntry,
13
13
  conflictingProfileFlags,
14
+ findRepoRoot,
14
15
  declaredProfile,
15
16
  hasBasaltKey,
17
+ namesShipped,
18
+ noteRelocation,
19
+ OXLINT_FILES,
20
+ packageRoot,
21
+ parseJsonc,
16
22
  readBasaltConfig,
17
- resolveExemptRules,
23
+ readIfExists,
24
+ readSource,
25
+ resolveGuardConfig,
18
26
  resolveProjectDir,
19
27
  scannableFiles,
20
28
  SERIES_MODULE_HINT_RE,
21
29
  waiverHintFor
22
30
  } from "./index.js";
23
- function checkTheme(invocationCwd = process.cwd(), flags = []) {
24
- if (conflictingProfileFlags(flags)) {
25
- console.error(
26
- "basalt-ui check-theme: --tokens-only and --framework are alternatives \u2014 pass one."
27
- );
28
- return 1;
31
+ function oxlintLaneAt(dir) {
32
+ const raw = readIfExists(resolve(dir, ".oxlintrc.json"));
33
+ if (raw === null) return "absent";
34
+ const rc = parseJsonc(raw);
35
+ const ownRules = Object.keys(Object(rc?.["rules"])).some((id) => id.startsWith("basalt/"));
36
+ const plugin = ownRules ? [rc?.["jsPlugins"]].flat().find((e) => namesShipped(e, OXLINT_FILES.plugin)) : void 0;
37
+ const entry = basaltPresetEntry(rc?.["extends"]) ?? plugin;
38
+ return entry !== void 0 && existsSync(resolve(dir, entry)) ? "wired" : "unwired";
39
+ }
40
+ function astLaneNotice(cwd) {
41
+ const root = findRepoRoot(cwd);
42
+ for (let dir = cwd; ; dir = dirname(dir)) {
43
+ const lane = oxlintLaneAt(dir);
44
+ if (lane === "wired") return null;
45
+ if (lane === "unwired" || dir === root || dirname(dir) === dir) break;
29
46
  }
47
+ const preset = readSource(packageRoot(), OXLINT_FILES.guards);
48
+ const count = preset === null ? `every (${OXLINT_FILES.guards} unreadable, so uncounted)` : String(preset.match(/"basalt\/[\w-]+":/g)?.length ?? 0);
49
+ return `\u2139 basalt-ui check-theme: AST lane not enforced \u2014 ${count} basalt/* rule ids unguarded (incl. the promoted control-outside-home, raw-breakpoint): no .oxlintrc.json up to the repo root extends basalt-ui/configs/oxlint.json (or the guards-only oxlint-basalt.json). \`basalt-ui doctor\` names the fix.`;
50
+ }
51
+ function checkTheme(invocationCwd = process.cwd(), flags = []) {
52
+ if (conflictingProfileFlags("check-theme", flags)) return 1;
30
53
  const project = resolveProjectDir(invocationCwd);
31
54
  const cwd = project.dir;
32
- if (project.relocatedFrom !== null) {
33
- console.log(
34
- `basalt-ui check-theme: BASALT_CWD relocated from ${project.relocatedFrom} to ${cwd}.`
35
- );
36
- }
55
+ noteRelocation("check-theme", project);
37
56
  const cfg = readBasaltConfig(cwd);
38
57
  const roots = resolveRoots(cfg);
39
58
  const profile = declaredProfile(cfg, flags);
@@ -42,27 +61,7 @@ function checkTheme(invocationCwd = process.cwd(), flags = []) {
42
61
  `basalt-ui check-theme: tokens-only profile \u2014 ${TOKENS_ONLY_DISABLED_KINDS.size} Mantine-coupled kinds are off; the color and typography kinds still apply. Pass --framework to force the full set.`
43
62
  );
44
63
  }
45
- const guardCfg = {
46
- spacingSteps: cfg.spacingSteps ?? DEFAULT_GUARD_CONFIG.spacingSteps,
47
- rawRadius: cfg.rawRadius ?? DEFAULT_GUARD_CONFIG.rawRadius,
48
- forbiddenAccents: cfg.forbiddenAccents ?? DEFAULT_GUARD_CONFIG.forbiddenAccents,
49
- mantineShadeIndex: cfg.mantineShadeIndex ?? DEFAULT_GUARD_CONFIG.mantineShadeIndex,
50
- rawSurface: cfg.rawSurface ?? DEFAULT_GUARD_CONFIG.rawSurface,
51
- cardWithBorder: cfg.cardWithBorder ?? DEFAULT_GUARD_CONFIG.cardWithBorder,
52
- offSystemSurfaceVar: cfg.offSystemSurfaceVar ?? DEFAULT_GUARD_CONFIG.offSystemSurfaceVar,
53
- rawHtmlLayout: cfg.rawHtmlLayout ?? DEFAULT_GUARD_CONFIG.rawHtmlLayout,
54
- inlineSpacing: cfg.inlineSpacing ?? DEFAULT_GUARD_CONFIG.inlineSpacing,
55
- inlineDisplay: cfg.inlineDisplay ?? DEFAULT_GUARD_CONFIG.inlineDisplay,
56
- rawVisxAxis: cfg.rawVisxAxis ?? DEFAULT_GUARD_CONFIG.rawVisxAxis,
57
- rawMotionValue: cfg.rawMotionValue ?? DEFAULT_GUARD_CONFIG.rawMotionValue,
58
- chartMissingAriaLabel: cfg.chartMissingAriaLabel ?? DEFAULT_GUARD_CONFIG.chartMissingAriaLabel,
59
- rawFormControl: cfg.rawFormControl ?? DEFAULT_GUARD_CONFIG.rawFormControl,
60
- sub16InputFont: cfg.sub16InputFont ?? DEFAULT_GUARD_CONFIG.sub16InputFont,
61
- allowComment: "theme-allow",
62
- exemptRules: resolveExemptRules(cfg),
63
- severity: cfg.severity ?? DEFAULT_GUARD_CONFIG.severity,
64
- ...profile === "tokens-only" ? { profile: "tokens-only" } : {}
65
- };
64
+ const guardCfg = resolveGuardConfig(cfg, profile);
66
65
  const findings = [];
67
66
  const scanned = scannableFiles(cwd, cfg);
68
67
  for (const rel of scanned) {
@@ -91,6 +90,8 @@ function checkTheme(invocationCwd = process.cwd(), flags = []) {
91
90
  `\u26A0 basalt-ui check-theme: "basalt.exemptRules" entry ${unmatched.kind}: "${unmatched.pattern}" ` + (unmatched.reason === "unknown-kind" ? "names no guard kind \u2014 it exempts nothing at all (a typo, or a kind that was renamed)." : "matched none of the scanned files \u2014 it suppresses nothing, and reads as coverage in a config review while enforcing as much as an empty object.")
92
91
  );
93
92
  }
93
+ const notice = profile === "tokens-only" ? null : astLaneNotice(cwd);
94
+ if (notice !== null) console.error(notice);
94
95
  if (findings.length === 0) {
95
96
  console.log("\u2713 Theme guard: no off-palette colors.");
96
97
  return 0;
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AA6BA,MAAM,MAAM,YAAY,GAAG;IACzB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AA8DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,MAAM,CAAC,aAAa,GAAE,MAAsB,EAAE,KAAK,GAAE,MAAM,EAAO,GAAG,MAAM,CAsO1F"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,YAAY,GAAG;IACzB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAA;IACpB,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AA8DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,MAAM,CAAC,aAAa,GAAE,MAAsB,EAAE,KAAK,GAAE,MAAM,EAAO,GAAG,MAAM,CAmO1F"}
@@ -9,6 +9,7 @@ import {
9
9
  findBasaltInstall,
10
10
  findRepoRoot,
11
11
  inspectLefthookGate,
12
+ OXLINT_FILES,
12
13
  parseJsonc,
13
14
  readBasaltConfig,
14
15
  readIfExists,
@@ -49,10 +50,7 @@ function resolveAiMajorSkewReason(cfg) {
49
50
  return { reason: null, presentButInvalid: true };
50
51
  }
51
52
  function doctor(invocationCwd = process.cwd(), flags = []) {
52
- if (conflictingProfileFlags(flags)) {
53
- console.error("basalt-ui doctor: --tokens-only and --framework are alternatives \u2014 pass one.");
54
- return 1;
55
- }
53
+ if (conflictingProfileFlags("doctor", flags)) return 1;
56
54
  const project = resolveProjectDir(invocationCwd);
57
55
  const cwd = project.dir;
58
56
  const cfg = readBasaltConfig(cwd);
@@ -136,7 +134,7 @@ basalt-ui doctor \u2014 ${cwd}
136
134
  );
137
135
  } else {
138
136
  const entry = basaltPresetEntry(parsed["extends"]);
139
- const correct = shippedAssetPath(install, cwd, "configs/oxlint.json");
137
+ const correct = shippedAssetPath(install, cwd, OXLINT_FILES.preset);
140
138
  if (entry === null) {
141
139
  fail(
142
140
  `.oxlintrc.json does NOT extend the shipped preset \u2014 every basalt/* design rule is off and oxlint reports green without them. Add "extends": ["${correct}"], or re-run \`basalt-ui init --merge-lint\` to splice it in.`
@@ -1 +1 @@
1
- {"version":3,"file":"guard-hook.d.ts","sourceRoot":"","sources":["../../src/cli/guard-hook.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwF5E"}
1
+ {"version":3,"file":"guard-hook.d.ts","sourceRoot":"","sources":["../../src/cli/guard-hook.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6D5E"}
@@ -1,8 +1,8 @@
1
1
  import { isAbsolute, relative, resolve } from "node:path";
2
- import { DEFAULT_GUARD_CONFIG } from "../guard/index.js";
3
2
  import { evaluateGuardHook } from "../guard/guard-hook.js";
4
- import { SKIP, declaredProfile, defaultExempt, readBasaltConfig, resolveExemptRules } from "./index.js";
3
+ import { SKIP, declaredProfile, defaultExempt, readBasaltConfig, resolveGuardConfig } from "./index.js";
5
4
  import { DEFAULT_ROOTS } from "./config.js";
5
+ const ALLOW = '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}\n';
6
6
  async function guardHook(cwd = process.cwd()) {
7
7
  let raw;
8
8
  try {
@@ -14,44 +14,18 @@ async function guardHook(cwd = process.cwd()) {
14
14
  raw = Buffer.concat(chunks).toString("utf8");
15
15
  }
16
16
  } catch {
17
- process.stdout.write(
18
- '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}\n'
19
- );
17
+ process.stdout.write(ALLOW);
20
18
  return 0;
21
19
  }
22
20
  let payload;
23
21
  try {
24
22
  payload = JSON.parse(raw);
25
23
  } catch {
26
- process.stdout.write(
27
- '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}\n'
28
- );
24
+ process.stdout.write(ALLOW);
29
25
  return 0;
30
26
  }
31
27
  const cfg = readBasaltConfig(cwd);
32
- const guardCfg = {
33
- spacingSteps: cfg.spacingSteps ?? DEFAULT_GUARD_CONFIG.spacingSteps,
34
- rawRadius: cfg.rawRadius ?? DEFAULT_GUARD_CONFIG.rawRadius,
35
- forbiddenAccents: cfg.forbiddenAccents ?? DEFAULT_GUARD_CONFIG.forbiddenAccents,
36
- mantineShadeIndex: cfg.mantineShadeIndex ?? DEFAULT_GUARD_CONFIG.mantineShadeIndex,
37
- rawSurface: cfg.rawSurface ?? DEFAULT_GUARD_CONFIG.rawSurface,
38
- cardWithBorder: cfg.cardWithBorder ?? DEFAULT_GUARD_CONFIG.cardWithBorder,
39
- offSystemSurfaceVar: cfg.offSystemSurfaceVar ?? DEFAULT_GUARD_CONFIG.offSystemSurfaceVar,
40
- rawHtmlLayout: cfg.rawHtmlLayout ?? DEFAULT_GUARD_CONFIG.rawHtmlLayout,
41
- inlineSpacing: cfg.inlineSpacing ?? DEFAULT_GUARD_CONFIG.inlineSpacing,
42
- inlineDisplay: cfg.inlineDisplay ?? DEFAULT_GUARD_CONFIG.inlineDisplay,
43
- rawVisxAxis: cfg.rawVisxAxis ?? DEFAULT_GUARD_CONFIG.rawVisxAxis,
44
- rawMotionValue: cfg.rawMotionValue ?? DEFAULT_GUARD_CONFIG.rawMotionValue,
45
- chartMissingAriaLabel: cfg.chartMissingAriaLabel ?? DEFAULT_GUARD_CONFIG.chartMissingAriaLabel,
46
- rawFormControl: cfg.rawFormControl ?? DEFAULT_GUARD_CONFIG.rawFormControl,
47
- sub16InputFont: cfg.sub16InputFont ?? DEFAULT_GUARD_CONFIG.sub16InputFont,
48
- allowComment: "theme-allow",
49
- exemptRules: resolveExemptRules(cfg),
50
- severity: cfg.severity ?? DEFAULT_GUARD_CONFIG.severity,
51
- // Same detection check-theme uses: the hook must never block an edit over advice the app
52
- // cannot take ("use @mantine/core's Select") in a repo with no Mantine.
53
- ...declaredProfile(cfg, []) === "tokens-only" ? { profile: "tokens-only" } : {}
54
- };
28
+ const guardCfg = resolveGuardConfig(cfg, declaredProfile(cfg, []));
55
29
  const roots = cfg.roots ?? DEFAULT_ROOTS;
56
30
  const exempt = new Set(cfg.exempt ?? defaultExempt(cfg));
57
31
  const isInScope = (filePath) => {
@@ -76,9 +50,7 @@ async function guardHook(cwd = process.cwd()) {
76
50
  }) + "\n"
77
51
  );
78
52
  } else {
79
- process.stdout.write(
80
- '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}\n'
81
- );
53
+ process.stdout.write(ALLOW);
82
54
  }
83
55
  return 0;
84
56
  }
@@ -7,12 +7,7 @@ import { init } from './init.js';
7
7
  import { sync } from './sync.js';
8
8
  import { fontsCss, normalizeColorFunctions, tokensCss } from './tokens-css.js';
9
9
  import type { BasaltConfig } from './config.js';
10
- /**
11
- * The guard-shaped `exemptRules` — paths only. The reason the object form carries never reaches
12
- * the guard: it is accountability for a human reading a diff and for `--audit-allows`, and giving
13
- * the scan a second shape to understand would only be a way for the two to disagree.
14
- */
15
- export declare function resolveExemptRules(cfg: BasaltConfig): GuardConfig['exemptRules'];
10
+ export declare function resolveGuardConfig(cfg: BasaltConfig, profile: DoctorProfile): GuardConfig;
16
11
  /**
17
12
  * Default scan exemption — a bare consumer's only palette source is its series module (the doctrine
18
13
  * directs every consumer to put raw hex series colors there). Shares `resolveSeriesModulePath` with
@@ -81,23 +76,9 @@ type ProjectResolution = {
81
76
  */
82
77
  export declare function resolveProjectDir(cwd: string): ProjectResolution;
83
78
  /**
84
- * Which shape of consumer a project-scoped command is looking at.
85
- *
86
- * A tokens-only consumer took the `--vx-*` layer and nothing else. Every guard kind whose remedy is
87
- * a Mantine component or the React theme factory is meaningless there — telling a Mantine-free app
88
- * to swap its `<select>` for `@mantine/core`'s `Select` is advice it must not take.
89
- *
90
- * DECLARED, never inferred, when the answer SILENCES something. The two callers want opposite
91
- * failure directions and so do not share a default:
92
- *
93
- * - `check-theme` (`declaredProfile`) turns 17 kinds OFF, so it moves on an explicit signal only —
94
- * `--tokens-only`, or `"basalt": { "profile": "tokens-only" }`. Inferring it from the ABSENCE of
95
- * `@mantine/core` would silence the Mantine half of the guard on any repo that keeps its Mantine
96
- * dependency in a workspace package rather than the one holding the basalt config, which is
97
- * precisely this round's "reports green while enforcing nothing" failure with the guard's own
98
- * hand on the switch.
99
- * - `doctor` no longer infers a profile at all (workspace-wide Mantine detection was deleted along
100
- * with the rest of the multi-repo discovery); it reads the same declaration `check-theme` does.
79
+ * Which shape of consumer a project-scoped command is looking at — DECLARED, never inferred
80
+ * (`--tokens-only`, or `"basalt": { "profile": "tokens-only" }`), because the answer switches the
81
+ * Mantine-remedy guard kinds off. Why that direction: package CLAUDE.md § CLI.
101
82
  */
102
83
  export declare function declaredProfile(cfg: BasaltConfig, flags: readonly string[]): DoctorProfile;
103
84
  /**
@@ -106,7 +87,9 @@ export declare function declaredProfile(cfg: BasaltConfig, flags: readonly strin
106
87
  * vs `--selector-attribute`. Silently preferring one meant a CI step that accumulated both flags
107
88
  * enforced whichever the code happened to test first.
108
89
  */
109
- export declare function conflictingProfileFlags(flags: readonly string[]): boolean;
90
+ export declare function conflictingProfileFlags(command: string, flags: readonly string[]): boolean;
91
+ /** Says so when `BASALT_CWD` moved the command off the directory it was invoked in. */
92
+ export declare function noteRelocation(command: string, project: ProjectResolution): void;
110
93
  /**
111
94
  * The relative paths `check-theme` would actually scan for a given config — the ONE place the walk
112
95
  * + `SKIP` + `exempt` filtering lives, so `doctor`'s "the guard sees zero files" check can never
@@ -114,19 +97,11 @@ export declare function conflictingProfileFlags(flags: readonly string[]): boole
114
97
  */
115
98
  export declare function scannableFiles(cwd: string, cfg: BasaltConfig): string[];
116
99
  /**
117
- * The waiver closer for a file, gated on the profile.
118
- *
119
- * `guardWaiverHint` keys off the file class, and for a `.webmanifest` it leads with
120
- * `basaltAppPlugin` — right for a Mantine app, since a hex in a manifest can never be *right* and
121
- * the plugin removes the hand-copy entirely. A `profile: tokens-only` consumer has definitionally
122
- * opted out of that layer: rollhook's Astro site has no `index.html` for the plugin to transform,
123
- * imports no basalt JavaScript at all, and owns maskable icons the plugin does not emit. Leading
124
- * with the plugin there is advice the consumer cannot take, in the one release that finally gave
125
- * that file class a remedy.
126
- *
127
- * So under tokens-only a manifest is treated as what it is to that consumer — plain JSON, with the
128
- * member as the whole answer — plus one sentence saying which remedy is being withheld and why.
129
- * The remedy text still comes from the guard's own registry; only the class mapping is decided here.
100
+ * The waiver closer for a file, gated on the profile. `guardWaiverHint` leads a `.webmanifest` with
101
+ * `basaltAppPlugin` — right for a Mantine app, advice a `profile: tokens-only` consumer cannot take
102
+ * (rollhook's Astro site has no `index.html` for the plugin and owns its maskable icons). There the
103
+ * manifest is plain JSON — the member is the whole answer, plus one sentence on the withheld remedy.
104
+ * The remedy text still comes from the guard's registry; only the class mapping is decided here.
130
105
  */
131
106
  export declare function waiverHintFor(relPath: string, profile: DoctorProfile): string;
132
107
  /**
@@ -374,16 +349,9 @@ type Classification = 'unchanged' | 'drifted' | 'missing' | 'current';
374
349
  export declare function normalizeForLedger(text: string): string;
375
350
  /**
376
351
  * Write a managed unit to disk (whole file, or marker-spliced region). Returns the unit's hash —
377
- * `sha256(normalizeForLedger(desired))`, NOT the raw bytes.
378
- *
379
- * This is the ledger: the manifest already records "what basalt shipped last sync", one entry per
380
- * dest — a stored NORMALIZED hash makes that same single entry survive both a downstream formatter
381
- * (the consumer's own lefthook oxfmt reformatting the written file/block after this function has
382
- * already returned) and a version bump that changed the template's own words since the recorded
383
- * entry — the argo cross-version case: current is v1.0.0's block, post-oxfmt; desired is v1.0.1's
384
- * (different words, e.g. the CLI bin rename). Recording the raw hash can never reconcile that;
385
- * recording the normalized hash lets `classify()` normalize `state.current` the same way and
386
- * compare directly against it, no separate historical-hash storage required.
352
+ * `sha256(normalizeForLedger(desired))`, NOT the raw bytes: the normalized hash is what lets one
353
+ * manifest entry survive a downstream formatter and a cross-version template change (`classify`'s
354
+ * path 2 is the reader).
387
355
  */
388
356
  export declare function writeUnit(file: ManagedFile, cwd: string, desired: string): string;
389
357
  /**
@@ -396,13 +364,8 @@ export declare function writeUnit(file: ManagedFile, cwd: string, desired: strin
396
364
  * manifest (written before this fix, or by a still-running older CLI) holds the RAW
397
365
  * hash of what was written, not the normalized one; keep matching it directly so an
398
366
  * upgrade never mass-classifies a pristine tree as drifted.
399
- * Residual transitional gap: a manifest written by a pre-1.0.2 CLI holds a raw hash
400
- * of the exact old bytes, so if the on-disk block was ALSO reformatted by a
401
- * downstream formatter AND the template body changed cross-version in the same
402
- * upgrade, none of the three paths above match and it classifies `drifted`, needing
403
- * one `--force`. Once any sync since writes a normalized entry (path 2/3 or a
404
- * healed write), the gap is closed for good for that file. Deliberately not solved
405
- * by keeping a historical per-version ledger — that's a real but bounded tradeoff.
367
+ * (A pre-1.0.2 raw entry whose block was ALSO reformatted across a template change
368
+ * needs one `--force`; bounded, and deliberately not solved with a version ledger.)
406
369
  * 2. `sha256(normalizeForLedger(current)) === manifestHash` — the ledger proper.
407
370
  * `manifestHash` normally holds `sha256(normalizeForLedger(<bytes written at the
408
371
  * last sync>))` (see `writeUnit`); normalizing `current` the same way and comparing
@@ -471,14 +434,19 @@ export declare function rootsNotices(state: RootsState): {
471
434
  export declare function parseJsonc(text: string): Record<string, unknown> | null;
472
435
  /** Outcome of splicing the shipped preset into an `.oxlintrc.json` the consumer already had. */
473
436
  export type MergeLintResult = 'added' | 'already' | 'absent' | 'unreadable' | 'has-comments';
437
+ /** The shipped oxlint files, package-relative — the one spelling every reader of them uses. */
438
+ export declare const OXLINT_FILES: {
439
+ readonly preset: "configs/oxlint.json";
440
+ readonly guards: "configs/oxlint-basalt.json";
441
+ readonly plugin: "configs/oxlint-plugin.js";
442
+ };
443
+ /** Whether an `extends`/`jsPlugins` entry names that shipped basalt-ui file. */
444
+ export declare const namesShipped: (entry: unknown, file: string) => entry is string;
474
445
  /**
475
- * The `extends` entry pointing at the shipped oxlint preset, or null when none does.
476
- *
477
- * Returns the ENTRY rather than a boolean because the string alone proves nothing: a consumer that
478
- * upgraded (or moved to an isolated linker) keeps a perfectly well-shaped
479
- * `./node_modules/basalt-ui/configs/oxlint.json` that resolves to nothing, and oxlint then refuses
480
- * to start with `NotFound` while a check built to prove the framework is ON reports green. The
481
- * caller resolves this against the config's own directory — see `extendsSeam`.
446
+ * The `extends` entry naming a shipped preset (full or guards-only), or null. The ENTRY, not a
447
+ * boolean: a well-shaped `./node_modules/basalt-ui/configs/oxlint.json` can resolve to nothing
448
+ * (an upgrade, an isolated linker), and oxlint then dies `NotFound` while a check built to prove the
449
+ * lane is ON reports green — callers resolve it against the config's own directory.
482
450
  */
483
451
  export declare function basaltPresetEntry(entries: unknown): string | null;
484
452
  export type LefthookGate =
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -22,13 +22,40 @@ import { init } from "./init.js";
22
22
  import { sync } from "./sync.js";
23
23
  import { fontsCss, normalizeColorFunctions, tokensCss } from "./tokens-css.js";
24
24
  import { DEFAULT_ROOT, exemptRulePaths, resolveRoots } from "./config.js";
25
- function resolveExemptRules(cfg) {
26
- if (cfg.exemptRules === void 0) return DEFAULT_GUARD_CONFIG.exemptRules;
27
- const out = {};
28
- for (const [kind, entry] of Object.entries(cfg.exemptRules)) {
29
- out[kind] = exemptRulePaths(entry);
30
- }
31
- return out;
25
+ const GUARD_PASSTHROUGH = {
26
+ spacingSteps: true,
27
+ rawRadius: true,
28
+ forbiddenAccents: true,
29
+ mantineShadeIndex: true,
30
+ rawSurface: true,
31
+ cardWithBorder: true,
32
+ offSystemSurfaceVar: true,
33
+ rawHtmlLayout: true,
34
+ inlineSpacing: true,
35
+ inlineDisplay: true,
36
+ rawVisxAxis: true,
37
+ rawMotionValue: true,
38
+ chartMissingAriaLabel: true,
39
+ rawFormControl: true,
40
+ sub16InputFont: true,
41
+ severity: true
42
+ };
43
+ function resolveGuardConfig(cfg, profile) {
44
+ const exemptRules = {};
45
+ for (const [kind, entry] of Object.entries(cfg.exemptRules ?? {})) {
46
+ exemptRules[kind] = exemptRulePaths(entry);
47
+ }
48
+ const from = cfg;
49
+ const set = Object.keys(GUARD_PASSTHROUGH).filter(
50
+ (k) => (from[k] ?? null) !== null
51
+ );
52
+ return {
53
+ ...DEFAULT_GUARD_CONFIG,
54
+ ...Object.fromEntries(set.map((k) => [k, from[k]])),
55
+ allowComment: "theme-allow",
56
+ exemptRules,
57
+ ...profile === "tokens-only" ? { profile: "tokens-only" } : {}
58
+ };
32
59
  }
33
60
  function resolveSeriesModulePath(cfg) {
34
61
  if (cfg.seriesModulePath !== void 0) return cfg.seriesModulePath;
@@ -154,8 +181,19 @@ function declaredProfile(cfg, flags) {
154
181
  if (flags.includes("--framework")) return "framework";
155
182
  return cfg.profile === "tokens-only" ? "tokens-only" : "framework";
156
183
  }
157
- function conflictingProfileFlags(flags) {
158
- return flags.includes("--tokens-only") && flags.includes("--framework");
184
+ function conflictingProfileFlags(command, flags) {
185
+ const both = flags.includes("--tokens-only") && flags.includes("--framework");
186
+ if (both)
187
+ console.error(
188
+ `basalt-ui ${command}: --tokens-only and --framework are alternatives \u2014 pass one.`
189
+ );
190
+ return both;
191
+ }
192
+ function noteRelocation(command, project) {
193
+ if (project.relocatedFrom === null) return;
194
+ console.log(
195
+ `basalt-ui ${command}: BASALT_CWD relocated from ${project.relocatedFrom} to ${project.dir}.`
196
+ );
159
197
  }
160
198
  function scannableFiles(cwd, cfg) {
161
199
  const exempt = new Set(cfg.exempt ?? defaultExempt(cfg));
@@ -234,7 +272,7 @@ function buildTemplateVars(pkgRoot, cwd, cfg) {
234
272
  ACCENT_HUE: cfg.accentHue ?? "blue",
235
273
  SERIES_MODULE_PATH: resolveSeriesModulePath(cfg),
236
274
  ROOTS_GLOBS: resolveRoots(cfg).map(toRootGlob).join(" "),
237
- OXLINT_PRESET_PATH: shippedAssetPath(install, cwd, "configs/oxlint.json"),
275
+ OXLINT_PRESET_PATH: shippedAssetPath(install, cwd, OXLINT_FILES.preset),
238
276
  LEFTHOOK_PRESET_PATH: shippedAssetPath(install, cwd, "configs/lefthook.yml"),
239
277
  BASALT_BIN: basaltBinCommand(install, cwd)
240
278
  };
@@ -422,7 +460,7 @@ pre-commit:
422
460
  const oxlintrc = {
423
461
  dest: ".oxlintrc.json",
424
462
  mode: "seed",
425
- source: "configs/oxlint.json",
463
+ source: OXLINT_FILES.preset,
426
464
  render: (ctx) => `{
427
465
  "extends": ["${ctx.vars.OXLINT_PRESET_PATH}"]
428
466
  }
@@ -708,12 +746,15 @@ function parseJsonc(text) {
708
746
  return null;
709
747
  }
710
748
  }
749
+ const OXLINT_FILES = {
750
+ preset: "configs/oxlint.json",
751
+ guards: "configs/oxlint-basalt.json",
752
+ plugin: "configs/oxlint-plugin.js"
753
+ };
754
+ const namesShipped = (entry, file) => typeof entry === "string" && entry.endsWith(`basalt-ui/${file}`);
711
755
  function basaltPresetEntry(entries) {
712
- if (!Array.isArray(entries)) return null;
713
- const match = entries.find(
714
- (entry) => typeof entry === "string" && entry.endsWith("basalt-ui/configs/oxlint.json")
715
- );
716
- return match ?? null;
756
+ const presets = [OXLINT_FILES.preset, OXLINT_FILES.guards];
757
+ return [entries].flat().find((e) => presets.some((f) => namesShipped(e, f))) ?? null;
717
758
  }
718
759
  const LEFTHOOK_CONFIG_NAMES = ["lefthook.yml", "lefthook.yaml", ".lefthook.yml", ".lefthook.yaml"];
719
760
  function findLefthookConfig(dir) {
@@ -759,9 +800,9 @@ function mergeOxlintExtends(cwd, presetPath) {
759
800
  if (raw === null) return "absent";
760
801
  const cfg = parseJsonc(raw);
761
802
  if (cfg === null) return "unreadable";
762
- if (basaltPresetEntry(cfg["extends"]) !== null) return "already";
803
+ if ([cfg["extends"]].flat().some((e) => namesShipped(e, OXLINT_FILES.preset))) return "already";
763
804
  if (stripJsonc(raw) !== raw) return "has-comments";
764
- const existing = Array.isArray(cfg["extends"]) ? cfg["extends"].filter((entry) => typeof entry === "string") : [];
805
+ const existing = [cfg["extends"]].flat().filter((e) => typeof e === "string" && !namesShipped(e, OXLINT_FILES.guards));
765
806
  const merged = "extends" in cfg ? {} : { extends: [presetPath] };
766
807
  for (const [key, value] of Object.entries(cfg)) {
767
808
  merged[key] = key === "extends" ? [presetPath, ...existing] : value;
@@ -896,6 +937,7 @@ function run(argv, cwd = process.cwd()) {
896
937
  }
897
938
  export {
898
939
  MANIFEST_PATH,
940
+ OXLINT_FILES,
899
941
  ROOT_PLACEMENT,
900
942
  RULE_NAMES,
901
943
  SERIES_MODULE_HINT_RE,
@@ -920,8 +962,10 @@ export {
920
962
  isStringArray,
921
963
  managedFiles,
922
964
  mergeOxlintExtends,
965
+ namesShipped,
923
966
  normalizeColorFunctions,
924
967
  normalizeForLedger,
968
+ noteRelocation,
925
969
  packageRoot,
926
970
  parseJsonc,
927
971
  patchPackageJson,
@@ -936,7 +980,7 @@ export {
936
980
  relativePosix,
937
981
  renderContext,
938
982
  reportPrune,
939
- resolveExemptRules,
983
+ resolveGuardConfig,
940
984
  resolvePeerFlags,
941
985
  resolvePlacement,
942
986
  resolveProjectDir,
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"AA4CA,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CASjE;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mGAAmG;IACnG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,IAAI,GAAE,WAAgB,EAAE,aAAa,GAAE,MAAsB,GAAG,MAAM,CAyM1F"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"AA8CA,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAGjE;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,mGAAmG;IACnG,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC1B,CAAA;AAED;;;;;;;;;GASG;AACH;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,IAAI,CAAC,IAAI,GAAE,WAAgB,EAAE,aAAa,GAAE,MAAsB,GAAG,MAAM,CAoM1F"}
package/dist/cli/sync.js CHANGED
@@ -13,6 +13,8 @@ import {
13
13
  isStringArray,
14
14
  managedFiles,
15
15
  normalizeForLedger,
16
+ noteRelocation,
17
+ OXLINT_FILES,
16
18
  parseJsonc,
17
19
  placementNotices,
18
20
  pruneRetiredManagedFiles,
@@ -35,14 +37,8 @@ import {
35
37
  writeUnit
36
38
  } from "./index.js";
37
39
  function readOxlintPresetPlugins(pkgRoot) {
38
- const raw = readSource(pkgRoot, "configs/oxlint.json");
39
- if (raw === null) return [];
40
- try {
41
- const plugins = JSON.parse(raw).plugins;
42
- return isStringArray(plugins) ? plugins : [];
43
- } catch {
44
- return [];
45
- }
40
+ const plugins = parseJsonc(readSource(pkgRoot, OXLINT_FILES.preset) ?? "null")?.["plugins"];
41
+ return isStringArray(plugins) ? plugins : [];
46
42
  }
47
43
  function parentInstallAdvice(cwd, parent, verb) {
48
44
  return `This repo's install is at ${relativePosix(cwd, parent)} (${parent}) \u2014 run ${verb} there, or set BASALT_CWD to it.`;
@@ -58,15 +54,10 @@ function findManifestAbove(dir) {
58
54
  }
59
55
  function sync(opts = {}, invocationCwd = process.cwd()) {
60
56
  const syncFlags = opts.flags ?? [];
61
- if (conflictingProfileFlags(syncFlags)) {
62
- console.error("basalt-ui sync: --tokens-only and --framework are alternatives \u2014 pass one.");
63
- return 1;
64
- }
57
+ if (conflictingProfileFlags("sync", syncFlags)) return 1;
65
58
  const project = resolveProjectDir(invocationCwd);
66
59
  const cwd = project.dir;
67
- if (project.relocatedFrom !== null) {
68
- console.log(`basalt-ui sync: BASALT_CWD relocated from ${project.relocatedFrom} to ${cwd}.`);
69
- }
60
+ noteRelocation("sync", project);
70
61
  if (declaredProfile(readBasaltConfig(cwd), syncFlags) === "tokens-only") {
71
62
  console.log(
72
63
  `basalt-ui sync: ${MANIFEST_PATH}: n/a \u2014 a tokens-only consumer has no scaffold to reconcile. The token layer is refreshed by re-running \`basalt-ui tokens:css\`, and \`tokens:css --check\` is its drift gate. Pass --framework to force the full profile.`
@@ -150,7 +141,7 @@ function sync(opts = {}, invocationCwd = process.cwd()) {
150
141
  const oxlintEntry = oxlintrcRaw === null ? null : basaltPresetEntry(parseJsonc(oxlintrcRaw)?.["extends"]);
151
142
  if (oxlintEntry !== null && !existsSync(resolve(cwd, oxlintEntry))) {
152
143
  console.error(
153
- `\u26A0 basalt-ui sync: .oxlintrc.json extends "${oxlintEntry}", which does not exist \u2014 oxlint refuses to start on a missing extends target (\`NotFound\`). Repoint it at "${shippedAssetPath(install, cwd, "configs/oxlint.json")}".`
144
+ `\u26A0 basalt-ui sync: .oxlintrc.json extends "${oxlintEntry}", which does not exist \u2014 oxlint refuses to start on a missing extends target (\`NotFound\`). Repoint it at "${shippedAssetPath(install, cwd, OXLINT_FILES.preset)}".`
154
145
  );
155
146
  }
156
147
  if (opts.check) {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The families every emitted `--vx-*` name lives in (`basaltVxFamilies`) — basalt-owned:
3
+ * `unknown-vx-token` judges every name inside one, and `groupTokens`/`seriesTokens` warn on a
4
+ * consumer ref there.
5
+ */
6
+ export declare const BASALT_VX_FAMILIES: readonly string[];
7
+ //# sourceMappingURL=vx-families.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vx-families.d.ts","sourceRoot":"","sources":["../../src/common/vx-families.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EA4B/C,CAAA"}