@monoes/monomindcli 2.14.1 → 2.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/.claude/helpers/control-start.cjs +10 -13
  2. package/.claude/skills/monodesign/scripts/context.mjs +4 -4
  3. package/.claude/skills/monodesign/scripts/critique-storage.mjs +1 -1
  4. package/.claude/skills/monodesign/scripts/detect-csp.mjs +1 -6
  5. package/.claude/skills/monodesign/scripts/detector/browser/injected/index.mjs +16 -18
  6. package/.claude/skills/monodesign/scripts/detector/cli/main.mjs +3 -3
  7. package/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +67 -47
  8. package/.claude/skills/monodesign/scripts/detector/engines/regex/detect-text.mjs +6 -6
  9. package/.claude/skills/monodesign/scripts/detector/engines/static-html/css-cascade.mjs +6 -5
  10. package/.claude/skills/monodesign/scripts/detector/engines/static-html/detect-html.mjs +6 -6
  11. package/.claude/skills/monodesign/scripts/detector/fix/index.mjs +3 -3
  12. package/.claude/skills/monodesign/scripts/detector/node/file-system.mjs +1 -1
  13. package/.claude/skills/monodesign/scripts/detector/registry/antipatterns.mjs +1 -1
  14. package/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +24 -25
  15. package/.claude/skills/monodesign/scripts/detector/shared/color.mjs +2 -2
  16. package/.claude/skills/monodesign/scripts/detector/shared/constants.mjs +1 -1
  17. package/.claude/skills/monodesign/scripts/detector/shared/inline-ignores.mjs +2 -2
  18. package/.claude/skills/monodesign/scripts/hook-admin.mjs +6 -6
  19. package/.claude/skills/monodesign/scripts/hook-before-edit.mjs +4 -4
  20. package/.claude/skills/monodesign/scripts/hook-lib.mjs +20 -11
  21. package/.claude/skills/monodesign/scripts/hook.mjs +1 -1
  22. package/.claude/skills/monodesign/scripts/lib/design-parser.mjs +9 -42
  23. package/.claude/skills/monodesign/scripts/lib/is-generated.mjs +1 -1
  24. package/.claude/skills/monodesign/scripts/lib/monodesign-config.mjs +5 -5
  25. package/.claude/skills/monodesign/scripts/lib/monodesign-paths.mjs +1 -1
  26. package/.claude/skills/monodesign/scripts/live/event-validation.mjs +13 -13
  27. package/.claude/skills/monodesign/scripts/live/manual-apply.mjs +4 -4
  28. package/.claude/skills/monodesign/scripts/live/manual-edits-buffer.mjs +1 -1
  29. package/.claude/skills/monodesign/scripts/live/session-store.mjs +5 -5
  30. package/.claude/skills/monodesign/scripts/live/svelte-component.mjs +13 -13
  31. package/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +4 -4
  32. package/.claude/skills/monodesign/scripts/live/ui-core.mjs +1 -1
  33. package/.claude/skills/monodesign/scripts/live-accept.mjs +24 -24
  34. package/.claude/skills/monodesign/scripts/live-browser-dom.js +8 -7
  35. package/.claude/skills/monodesign/scripts/live-browser-session.js +8 -7
  36. package/.claude/skills/monodesign/scripts/live-browser.js +405 -432
  37. package/.claude/skills/monodesign/scripts/live-commit-manual-edits.mjs +6 -6
  38. package/.claude/skills/monodesign/scripts/live-copy-edit-agent.mjs +2 -2
  39. package/.claude/skills/monodesign/scripts/live-discard-manual-edits.mjs +1 -1
  40. package/.claude/skills/monodesign/scripts/live-inject.mjs +7 -7
  41. package/.claude/skills/monodesign/scripts/live-insert.mjs +11 -11
  42. package/.claude/skills/monodesign/scripts/live-manual-edit-evidence.mjs +4 -4
  43. package/.claude/skills/monodesign/scripts/live-poll.mjs +5 -5
  44. package/.claude/skills/monodesign/scripts/live-server.mjs +10 -10
  45. package/.claude/skills/monodesign/scripts/live-wrap.mjs +31 -41
  46. package/.claude/skills/monodesign/scripts/live.mjs +5 -5
  47. package/.claude/skills/monodesign/scripts/palette.mjs +3 -1
  48. package/.claude/skills/monodesign/scripts/pin.mjs +1 -1
  49. package/dist/src/commands/doc-filters.d.ts.map +1 -1
  50. package/dist/src/commands/doc-filters.js +6 -0
  51. package/dist/src/commands/doc-filters.js.map +1 -1
  52. package/dist/src/commands/doc-library.d.ts +2 -1
  53. package/dist/src/commands/doc-library.d.ts.map +1 -1
  54. package/dist/src/commands/doc-library.js +66 -2
  55. package/dist/src/commands/doc-library.js.map +1 -1
  56. package/dist/src/commands/doc.d.ts.map +1 -1
  57. package/dist/src/commands/doc.js +2 -0
  58. package/dist/src/commands/doc.js.map +1 -1
  59. package/dist/src/commands/org.d.ts.map +1 -1
  60. package/dist/src/commands/org.js +42 -4
  61. package/dist/src/commands/org.js.map +1 -1
  62. package/dist/src/commands/ui.d.ts.map +1 -1
  63. package/dist/src/commands/ui.js +60 -0
  64. package/dist/src/commands/ui.js.map +1 -1
  65. package/dist/src/knowledge/capture-envelope.d.ts +5 -0
  66. package/dist/src/knowledge/capture-envelope.d.ts.map +1 -1
  67. package/dist/src/knowledge/capture-envelope.js +2 -0
  68. package/dist/src/knowledge/capture-envelope.js.map +1 -1
  69. package/dist/src/knowledge/document-chunking.d.ts +42 -0
  70. package/dist/src/knowledge/document-chunking.d.ts.map +1 -0
  71. package/dist/src/knowledge/document-chunking.js +288 -0
  72. package/dist/src/knowledge/document-chunking.js.map +1 -0
  73. package/dist/src/knowledge/document-index.d.ts +124 -0
  74. package/dist/src/knowledge/document-index.d.ts.map +1 -0
  75. package/dist/src/knowledge/document-index.js +314 -0
  76. package/dist/src/knowledge/document-index.js.map +1 -0
  77. package/dist/src/knowledge/document-ingest.d.ts +23 -0
  78. package/dist/src/knowledge/document-ingest.d.ts.map +1 -0
  79. package/dist/src/knowledge/document-ingest.js +368 -0
  80. package/dist/src/knowledge/document-ingest.js.map +1 -0
  81. package/dist/src/knowledge/document-pipeline.d.ts +26 -208
  82. package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
  83. package/dist/src/knowledge/document-pipeline.js +25 -1104
  84. package/dist/src/knowledge/document-pipeline.js.map +1 -1
  85. package/dist/src/knowledge/document-search.d.ts +27 -0
  86. package/dist/src/knowledge/document-search.d.ts.map +1 -0
  87. package/dist/src/knowledge/document-search.js +138 -0
  88. package/dist/src/knowledge/document-search.js.map +1 -0
  89. package/dist/src/knowledge/document-store.d.ts +28 -0
  90. package/dist/src/knowledge/document-store.d.ts.map +1 -0
  91. package/dist/src/knowledge/document-store.js +61 -0
  92. package/dist/src/knowledge/document-store.js.map +1 -0
  93. package/dist/src/knowledge/document-types.d.ts +103 -0
  94. package/dist/src/knowledge/document-types.d.ts.map +1 -0
  95. package/dist/src/knowledge/document-types.js +12 -0
  96. package/dist/src/knowledge/document-types.js.map +1 -0
  97. package/dist/src/knowledge/highlights.d.ts +168 -0
  98. package/dist/src/knowledge/highlights.d.ts.map +1 -0
  99. package/dist/src/knowledge/highlights.js +311 -0
  100. package/dist/src/knowledge/highlights.js.map +1 -0
  101. package/dist/src/knowledge/lookup.d.ts +80 -0
  102. package/dist/src/knowledge/lookup.d.ts.map +1 -0
  103. package/dist/src/knowledge/lookup.js +156 -0
  104. package/dist/src/knowledge/lookup.js.map +1 -0
  105. package/dist/src/knowledge/okf-bundle.d.ts +19 -0
  106. package/dist/src/knowledge/okf-bundle.d.ts.map +1 -0
  107. package/dist/src/knowledge/okf-bundle.js +106 -0
  108. package/dist/src/knowledge/okf-bundle.js.map +1 -0
  109. package/dist/src/knowledge/profile-store.d.ts +134 -0
  110. package/dist/src/knowledge/profile-store.d.ts.map +1 -0
  111. package/dist/src/knowledge/profile-store.js +237 -0
  112. package/dist/src/knowledge/profile-store.js.map +1 -0
  113. package/dist/src/orgrt/agent-runner.d.ts +4 -0
  114. package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
  115. package/dist/src/orgrt/agent-runner.js +22 -0
  116. package/dist/src/orgrt/agent-runner.js.map +1 -1
  117. package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
  118. package/dist/src/orgrt/antigravity-runner.js +2 -1
  119. package/dist/src/orgrt/antigravity-runner.js.map +1 -1
  120. package/dist/src/orgrt/authority-mask.d.ts +32 -0
  121. package/dist/src/orgrt/authority-mask.d.ts.map +1 -0
  122. package/dist/src/orgrt/authority-mask.js +135 -0
  123. package/dist/src/orgrt/authority-mask.js.map +1 -0
  124. package/dist/src/orgrt/codex-runner.d.ts.map +1 -1
  125. package/dist/src/orgrt/codex-runner.js +2 -1
  126. package/dist/src/orgrt/codex-runner.js.map +1 -1
  127. package/dist/src/orgrt/copilot-runner.d.ts.map +1 -1
  128. package/dist/src/orgrt/copilot-runner.js +2 -1
  129. package/dist/src/orgrt/copilot-runner.js.map +1 -1
  130. package/dist/src/orgrt/crush-runner.d.ts.map +1 -1
  131. package/dist/src/orgrt/crush-runner.js +6 -1
  132. package/dist/src/orgrt/crush-runner.js.map +1 -1
  133. package/dist/src/orgrt/daemon.d.ts +4 -0
  134. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  135. package/dist/src/orgrt/daemon.js +13 -2
  136. package/dist/src/orgrt/daemon.js.map +1 -1
  137. package/dist/src/orgrt/decisions.d.ts +9 -0
  138. package/dist/src/orgrt/decisions.d.ts.map +1 -1
  139. package/dist/src/orgrt/decisions.js +32 -5
  140. package/dist/src/orgrt/decisions.js.map +1 -1
  141. package/dist/src/orgrt/file-roots.d.ts +2 -1
  142. package/dist/src/orgrt/file-roots.d.ts.map +1 -1
  143. package/dist/src/orgrt/file-roots.js +7 -3
  144. package/dist/src/orgrt/file-roots.js.map +1 -1
  145. package/dist/src/orgrt/grok-runner.d.ts.map +1 -1
  146. package/dist/src/orgrt/grok-runner.js +2 -1
  147. package/dist/src/orgrt/grok-runner.js.map +1 -1
  148. package/dist/src/orgrt/hermes-runner.d.ts.map +1 -1
  149. package/dist/src/orgrt/hermes-runner.js +2 -1
  150. package/dist/src/orgrt/hermes-runner.js.map +1 -1
  151. package/dist/src/orgrt/inbox.d.ts.map +1 -1
  152. package/dist/src/orgrt/inbox.js +70 -4
  153. package/dist/src/orgrt/inbox.js.map +1 -1
  154. package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
  155. package/dist/src/orgrt/kimicode-runner.js +2 -1
  156. package/dist/src/orgrt/kimicode-runner.js.map +1 -1
  157. package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
  158. package/dist/src/orgrt/opencode-runner.js +3 -2
  159. package/dist/src/orgrt/opencode-runner.js.map +1 -1
  160. package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -1
  161. package/dist/src/orgrt/pi-rpc-runner.js +3 -2
  162. package/dist/src/orgrt/pi-rpc-runner.js.map +1 -1
  163. package/dist/src/orgrt/pi-runner.d.ts.map +1 -1
  164. package/dist/src/orgrt/pi-runner.js +2 -1
  165. package/dist/src/orgrt/pi-runner.js.map +1 -1
  166. package/dist/src/orgrt/policy.d.ts.map +1 -1
  167. package/dist/src/orgrt/policy.js +3 -0
  168. package/dist/src/orgrt/policy.js.map +1 -1
  169. package/dist/src/orgrt/qwen-rpc-runner.d.ts.map +1 -1
  170. package/dist/src/orgrt/qwen-rpc-runner.js +3 -2
  171. package/dist/src/orgrt/qwen-rpc-runner.js.map +1 -1
  172. package/dist/src/orgrt/qwen-runner.d.ts.map +1 -1
  173. package/dist/src/orgrt/qwen-runner.js +2 -1
  174. package/dist/src/orgrt/qwen-runner.js.map +1 -1
  175. package/dist/src/orgrt/role-sandbox.d.ts +21 -0
  176. package/dist/src/orgrt/role-sandbox.d.ts.map +1 -1
  177. package/dist/src/orgrt/role-sandbox.js +31 -6
  178. package/dist/src/orgrt/role-sandbox.js.map +1 -1
  179. package/dist/src/orgrt/session.d.ts.map +1 -1
  180. package/dist/src/orgrt/session.js +21 -2
  181. package/dist/src/orgrt/session.js.map +1 -1
  182. package/dist/src/orgrt/task-dag.d.ts +3 -0
  183. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  184. package/dist/src/orgrt/task-dag.js +1 -0
  185. package/dist/src/orgrt/task-dag.js.map +1 -1
  186. package/dist/src/orgrt/types.d.ts +5 -0
  187. package/dist/src/orgrt/types.d.ts.map +1 -1
  188. package/dist/src/orgrt/types.js +23 -1
  189. package/dist/src/orgrt/types.js.map +1 -1
  190. package/dist/src/ui/dashboard.html +28 -848
  191. package/dist/src/ui/human-auth.mjs +103 -0
  192. package/dist/src/ui/org-hil.mjs +86 -37
  193. package/dist/src/ui/org-runtime.mjs +21 -13
  194. package/dist/src/ui/routes-org.mjs +49 -445
  195. package/dist/src/ui/server.mjs +103 -4
  196. package/dist/tsconfig.tsbuildinfo +1 -1
  197. package/package.json +6 -6
@@ -82,7 +82,7 @@ function checkColors(opts) {
82
82
  if (hasDirectText && textColor && !isEmojiOnly) {
83
83
  // Run background-dependent checks against either a solid bg or, if the
84
84
  // ancestor is a gradient, against every gradient stop (use the worst case).
85
- const bgs = effectiveBg ? [effectiveBg] : (effectiveBgStops && effectiveBgStops.length ? effectiveBgStops : null);
85
+ const bgs = effectiveBg ? [effectiveBg] : (effectiveBgStops?.length ? effectiveBgStops : null);
86
86
  if (bgs) {
87
87
  // Gray on colored background — flag if every stop is chromatic
88
88
  const textLum = relativeLuminance(textColor);
@@ -263,7 +263,6 @@ function isAccentColor(cssColor) {
263
263
  if (!cssColor) return false;
264
264
  const s = String(cssColor).trim();
265
265
  // rgb / rgba — direct channel-distance check.
266
- const rgbM = /rgba?\(\s*(\d+)\s*,?\s+|\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(s.replace(/rgba?\(\s*/, 'rgb(').replace(/,/g, ', '));
267
266
  const rgbStrict = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(s);
268
267
  if (rgbStrict) {
269
268
  const r = +rgbStrict[1], g = +rgbStrict[2], b = +rgbStrict[3];
@@ -308,7 +307,7 @@ function isAccentColor(cssColor) {
308
307
  // uppercase eyebrow OR the modern accent-colored bold eyebrow.
309
308
  function checkHeroEyebrow(opts) {
310
309
  const {
311
- headingTag, headingText, headingFontSize,
310
+ headingTag, headingText,
312
311
  siblingTag, siblingText, siblingTextTransform,
313
312
  siblingFontSize, siblingLetterSpacing,
314
313
  siblingFontWeight, siblingColor,
@@ -779,7 +778,7 @@ function parseRadiusToPx(value, widthPx) {
779
778
  return num;
780
779
  }
781
780
 
782
- function resolveBorderRadiusPx(el, style, widthPx, win) {
781
+ function resolveBorderRadiusPx(_el, style, widthPx, _win) {
783
782
  const fromComputed = parseRadiusToPx(style.borderRadius, widthPx);
784
783
  if (fromComputed !== null) return fromComputed;
785
784
  return 0;
@@ -822,7 +821,7 @@ function checkElementColorsDOM(el) {
822
821
  effectiveBg,
823
822
  effectiveBgStops: effectiveBg ? null : resolveGradientStops(el),
824
823
  fontSize: parseFloat(style.fontSize) || 16,
825
- fontWeight: parseInt(style.fontWeight) || 400,
824
+ fontWeight: parseInt(style.fontWeight, 10) || 400,
826
825
  hasDirectText,
827
826
  isEmojiOnly: isEmojiOnlyText(directText),
828
827
  bgClip: style.webkitBackgroundClip || style.backgroundClip || '',
@@ -930,7 +929,7 @@ function buildCustomPropMap(document) {
930
929
  if (!style) continue;
931
930
  for (let i = 0; i < style.length; i++) {
932
931
  const prop = style[i];
933
- if (!prop || !prop.startsWith('--')) continue;
932
+ if (!prop?.startsWith('--')) continue;
934
933
  const val = style.getPropertyValue(prop).trim();
935
934
  if (val) map.set(prop, val);
936
935
  }
@@ -972,7 +971,7 @@ function oklchToRgb(L, C, H) {
972
971
  const bLin = -0.0041960863 * lc - 0.7034186147 * mc + 1.7076147010 * sc;
973
972
  const enc = (x) => {
974
973
  const c = Math.max(0, Math.min(1, x));
975
- return c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
974
+ return c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;
976
975
  };
977
976
  return {
978
977
  r: Math.round(enc(rLin) * 255),
@@ -1274,7 +1273,7 @@ function resolveFontSizePx(el, win) {
1274
1273
  const v = chain[i];
1275
1274
  if (!v || v === 'inherit') continue;
1276
1275
  const num = parseFloat(v);
1277
- if (isNaN(num)) continue;
1276
+ if (Number.isNaN(num)) continue;
1278
1277
  if (v.endsWith('px')) px = num;
1279
1278
  else if (v.endsWith('rem')) px = num * 16;
1280
1279
  else if (v.endsWith('em')) px = num * px;
@@ -1289,7 +1288,7 @@ function resolveFontSizePx(el, win) {
1289
1288
  function resolveLengthPx(value, fontSizePx) {
1290
1289
  if (!value || value === 'normal' || value === 'auto' || value === 'inherit') return null;
1291
1290
  const num = parseFloat(value);
1292
- if (isNaN(num)) return null;
1291
+ if (Number.isNaN(num)) return null;
1293
1292
  if (value.endsWith('px')) return num;
1294
1293
  if (value.endsWith('rem')) return num * 16;
1295
1294
  if (value.endsWith('em')) return num * fontSizePx;
@@ -1405,7 +1404,7 @@ function checkQuality(opts) {
1405
1404
  // font-size — bigger text demands proportionally more padding.
1406
1405
  // vertical: max(4px, fontSize × 0.3)
1407
1406
  // horizontal: max(8px, fontSize × 0.5)
1408
- const isInlineCode = tag === 'code' && !(el.closest && el.closest('pre'));
1407
+ const isInlineCode = tag === 'code' && !el.closest?.('pre');
1409
1408
  if (!isInlineCode && rect && hasDirectText && textLen > 20 && rect.width > 100 && rect.height > 30) {
1410
1409
  const borders = {
1411
1410
  top: parseFloat(style.borderTopWidth) || 0,
@@ -1521,7 +1520,7 @@ function checkQuality(opts) {
1521
1520
  const CHILD_INSULATE_THRESHOLD = 4;
1522
1521
  const childrenInsulate = { top: false, right: false, bottom: false, left: false };
1523
1522
  for (const child of el.children) {
1524
- let childStyle = getComputedStyleFor(win, child);
1523
+ const childStyle = getComputedStyleFor(win, child);
1525
1524
  if (!childStyle) continue;
1526
1525
  const childPad = {
1527
1526
  top: resolveLengthPx(childStyle.paddingTop, fontSize) ?? 0,
@@ -1653,7 +1652,7 @@ function checkQuality(opts) {
1653
1652
  // Only flag actual body content, not UI labels (buttons, tabs, badges, captions, footer text, etc.)
1654
1653
  if (hasDirectText && textLen > 20 && fontSize < 12) {
1655
1654
  const skipTags = ['sub', 'sup', 'code', 'kbd', 'samp', 'var', 'caption', 'figcaption'];
1656
- const inUIContext = el.closest && el.closest('button, a, label, summary, pre, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"], nav, footer, [aria-hidden="true"], [class*="badge" i], [class*="caption" i], [class*="chip" i], [class*="code" i], [class*="console" i], [class*="diff" i], [class*="label" i], [class*="meta" i], [class*="mock" i], [class*="pill" i], [class*="preview" i], [class*="tag" i], [class*="terminal" i], [class*="writes" i]');
1655
+ const inUIContext = el.closest?.('button, a, label, summary, pre, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"], nav, footer, [aria-hidden="true"], [class*="badge" i], [class*="caption" i], [class*="chip" i], [class*="code" i], [class*="console" i], [class*="diff" i], [class*="label" i], [class*="meta" i], [class*="mock" i], [class*="pill" i], [class*="preview" i], [class*="tag" i], [class*="terminal" i], [class*="writes" i]');
1657
1656
  const isUppercase = style.textTransform === 'uppercase';
1658
1657
  if (!skipTags.includes(tag) && !inUIContext && !isUppercase) {
1659
1658
  findings.push({ id: 'tiny-text', snippet: `${fontSize}px body text` });
@@ -1718,7 +1717,7 @@ function checkPageQualityFromDoc(doc) {
1718
1717
  let prevLevel = 0;
1719
1718
  let prevText = '';
1720
1719
  for (const h of headings) {
1721
- const level = parseInt(h.tagName[1]);
1720
+ const level = parseInt(h.tagName[1], 10);
1722
1721
  const text = (h.textContent || '').trim().replace(/\s+/g, ' ').slice(0, 60);
1723
1722
  if (prevLevel > 0 && level > prevLevel + 1) {
1724
1723
  findings.push({
@@ -1766,7 +1765,7 @@ function checkElementBorders(tag, style, overrides, resolvedRadius) {
1766
1765
  if (widths[s] === 0 && overrides && overrides[s]) {
1767
1766
  widths[s] = overrides[s].width;
1768
1767
  colors[s] = overrides[s].color;
1769
- } else if (colors[s] && colors[s].startsWith('var(') && overrides && overrides[s]) {
1768
+ } else if (colors[s]?.startsWith('var(') && overrides?.[s]) {
1770
1769
  // Longhand case: jsdom kept the width but left the color as the
1771
1770
  // literal `var(...)` string. Substitute the resolved color.
1772
1771
  colors[s] = overrides[s].color;
@@ -1827,7 +1826,7 @@ function checkElementColors(el, style, tag, window, customPropMap, hasAnchorInhe
1827
1826
  effectiveBg,
1828
1827
  effectiveBgStops: effectiveBg ? null : resolveGradientStops(el, window),
1829
1828
  fontSize: parseFloat(style.fontSize) || 16,
1830
- fontWeight: parseInt(style.fontWeight) || 400,
1829
+ fontWeight: parseInt(style.fontWeight, 10) || 400,
1831
1830
  hasDirectText,
1832
1831
  isEmojiOnly: isEmojiOnlyText(directText),
1833
1832
  bgClip: style.webkitBackgroundClip || style.backgroundClip || '',
@@ -1954,7 +1953,7 @@ function checkTypography() {
1954
1953
  let totalTextElements = 0;
1955
1954
  for (const el of document.querySelectorAll('p, h1, h2, h3, h4, h5, h6, li, td, th, dd, blockquote, figcaption, a, button, label, span')) {
1956
1955
  // Skip monodesign's own elements
1957
- if (el.closest && el.closest('.monodesign-overlay, .monodesign-label, .monodesign-banner, .monodesign-tooltip')) continue;
1956
+ if (el.closest?.('.monodesign-overlay, .monodesign-label, .monodesign-banner, .monodesign-tooltip')) continue;
1958
1957
  // Only count elements that actually have visible direct text
1959
1958
  const hasText = [...el.childNodes].some(n => n.nodeType === 3 && n.textContent.trim().length > 0);
1960
1959
  if (!hasText) continue;
@@ -1995,7 +1994,7 @@ function checkTypography() {
1995
1994
  const sorted = [...sizes].sort((a, b) => a - b);
1996
1995
  const ratio = sorted[sorted.length - 1] / sorted[0];
1997
1996
  if (ratio < 2.0) {
1998
- findings.push({ type: 'flat-type-hierarchy', detail: `Sizes: ${sorted.map(s => s + 'px').join(', ')} (ratio ${ratio.toFixed(1)}:1)` });
1997
+ findings.push({ type: 'flat-type-hierarchy', detail: `Sizes: ${sorted.map(s => `${s}px`).join(', ')} (ratio ${ratio.toFixed(1)}:1)` });
1999
1998
  }
2000
1999
  }
2001
2000
 
@@ -2114,7 +2113,7 @@ function checkPageTypography(doc, win) {
2114
2113
  const sorted = [...sizes].sort((a, b) => a - b);
2115
2114
  const ratio = sorted[sorted.length - 1] / sorted[0];
2116
2115
  if (ratio < 2.0) {
2117
- findings.push({ id: 'flat-type-hierarchy', snippet: `Sizes: ${sorted.map(s => s + 'px').join(', ')} (ratio ${ratio.toFixed(1)}:1)` });
2116
+ findings.push({ id: 'flat-type-hierarchy', snippet: `Sizes: ${sorted.map(s => `${s}px`).join(', ')} (ratio ${ratio.toFixed(1)}:1)` });
2118
2117
  }
2119
2118
  }
2120
2119
 
@@ -2246,7 +2245,7 @@ function checkCreamPalette(doc, win) {
2246
2245
  // 2. Tailwind class fallback — for the static path, where utility classes
2247
2246
  // never resolve to computed CSS.
2248
2247
  for (const el of [body, html]) {
2249
- const tok = creamFromClassList(el && el.getAttribute ? el.getAttribute('class') : '');
2248
+ const tok = creamFromClassList(el?.getAttribute ? el.getAttribute('class') : '');
2250
2249
  if (tok) {
2251
2250
  findings.push({ id: 'cream-palette', snippet: `cream/beige page background (Tailwind ${tok})` });
2252
2251
  break;
@@ -2282,7 +2281,7 @@ function checkOversizedH1({ tag, fontSize, headingText, rect = null, viewportWid
2282
2281
  return [];
2283
2282
  }
2284
2283
 
2285
- function checkElementOversizedH1(el, style, tag, window) {
2284
+ function checkElementOversizedH1(el, _style, tag, window) {
2286
2285
  if (tag !== 'h1') return [];
2287
2286
  const fontSize = resolveFontSizePx(el, window);
2288
2287
  const headingText = (el.textContent || '').trim().replace(/\s+/g, ' ');
@@ -2366,7 +2365,7 @@ function borderColorsFromStyle(style) {
2366
2365
  ];
2367
2366
  }
2368
2367
 
2369
- function checkElementGptBorderShadow(el, style) {
2368
+ function checkElementGptBorderShadow(_el, style) {
2370
2369
  return checkGptThinBorderWideShadow({ borderWidths: borderWidthsFromStyle(style), borderColors: borderColorsFromStyle(style), boxShadow: style.boxShadow || '' });
2371
2370
  }
2372
2371
 
@@ -2516,7 +2515,7 @@ function checkClippedOverflow(el, style, getStyle) {
2516
2515
  return [];
2517
2516
  }
2518
2517
 
2519
- function checkElementClippedOverflow(el, style, tag, window) {
2518
+ function checkElementClippedOverflow(el, style, _tag, window) {
2520
2519
  return checkClippedOverflow(el, style, (n) => window.getComputedStyle(n));
2521
2520
  }
2522
2521
 
@@ -2862,7 +2861,7 @@ function checkElementImageDimensions(el, style) {
2862
2861
  const parts = [el.getAttribute?.('style') || el.attribs?.style || ''];
2863
2862
  const ar = style && (style.aspectRatio || style['aspect-ratio']);
2864
2863
  if (ar && ar !== 'auto') parts.push(`aspect-ratio:${ar}`);
2865
- const h = style && style.height;
2864
+ const h = style?.height;
2866
2865
  if (h && h !== 'auto' && h !== '') parts.push(`height:${h}`);
2867
2866
  return checkImageDimensions({ hasWidthAttr, hasHeightAttr, style: parts.join(';') });
2868
2867
  }
@@ -2922,7 +2921,7 @@ function checkElementSmallTouchTarget(el, style, tag) {
2922
2921
  // (button-like). jsdom returns '' for the default inline display, so key
2923
2922
  // off "not blockish" rather than "== inline".
2924
2923
  const isBlockish = /^(block|flex|grid|inline-block|inline-flex|table)/.test(style.display || '');
2925
- const inProse = !!(el.closest && el.closest(PROSE_ANCESTOR_SELECTOR));
2924
+ const inProse = !!el.closest?.(PROSE_ANCESTOR_SELECTOR);
2926
2925
  const isInlineLinkInProse = tag === 'a' && !isBlockish && inProse;
2927
2926
  return checkSmallTouchTarget({ tag, role, href, inputType, widthPx, heightPx, isInlineLinkInProse });
2928
2927
  }
@@ -2936,7 +2935,7 @@ function checkElementSmallTouchTargetDOM(el) {
2936
2935
  const inputType = el.getAttribute('type') || '';
2937
2936
  const style = getComputedStyle(el);
2938
2937
  const isBlockish = /^(block|flex|grid|inline-block|inline-flex|table)/.test(style.display || '');
2939
- const inProse = !!(el.closest && el.closest(PROSE_ANCESTOR_SELECTOR));
2938
+ const inProse = !!el.closest?.(PROSE_ANCESTOR_SELECTOR);
2940
2939
  const isInlineLinkInProse = tag === 'a' && !isBlockish && inProse;
2941
2940
  return checkSmallTouchTarget({ tag, role, href, inputType, widthPx: rect.width, heightPx: rect.height, isInlineLinkInProse });
2942
2941
  }
@@ -72,7 +72,7 @@ function contrastRatio(c1, c2) {
72
72
  }
73
73
 
74
74
  function parseGradientColors(bgImage) {
75
- if (!bgImage || !bgImage.includes('gradient')) return [];
75
+ if (!bgImage?.includes('gradient')) return [];
76
76
  const colors = [];
77
77
  for (const m of bgImage.matchAll(/rgba?\([^)]+\)/g)) {
78
78
  const c = parseRgb(m[0]);
@@ -109,7 +109,7 @@ function getHue(c) {
109
109
 
110
110
  function colorToHex(c) {
111
111
  if (!c) return '?';
112
- return '#' + [c.r, c.g, c.b].map(v => v.toString(16).padStart(2, '0')).join('');
112
+ return `#${[c.r, c.g, c.b].map(v => v.toString(16).padStart(2, '0')).join('')}`;
113
113
  }
114
114
 
115
115
  export {
@@ -53,7 +53,7 @@ function isBrandFontOnOwnDomain(font) {
53
53
  const allowed = BRAND_FONT_DOMAINS[font];
54
54
  if (!allowed) return false;
55
55
  const host = location.hostname.toLowerCase();
56
- return allowed.some(suffix => host === suffix || host.endsWith('.' + suffix));
56
+ return allowed.some(suffix => host === suffix || host.endsWith(`.${suffix}`));
57
57
  }
58
58
 
59
59
  const GENERIC_FONTS = new Set([
@@ -117,10 +117,10 @@ function setMatches(set, rule) {
117
117
  }
118
118
 
119
119
  function isInlineIgnored(finding, directives) {
120
- const rule = normalizeRule(finding && finding.antipattern);
120
+ const rule = normalizeRule(finding?.antipattern);
121
121
  if (!rule) return false;
122
122
  if (setMatches(directives.file, rule)) return true;
123
- const line = Number(finding && finding.line) || 0;
123
+ const line = Number(finding?.line) || 0;
124
124
  if (line > 0) {
125
125
  if (setMatches(directives.line.get(line), rule)) return true;
126
126
  if (setMatches(directives.nextLine.get(line), rule)) return true;
@@ -184,7 +184,7 @@ function writeHookConfig(cwd, hookConfig, opts = {}) {
184
184
  // (consent, quiet, auditLog) survive an Monodesign hooks edit.
185
185
  const next = { ...existing, hook: { ...existingHook, ...hookConfig } };
186
186
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
187
- fs.writeFileSync(filePath, JSON.stringify(next, null, 2) + '\n');
187
+ fs.writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`);
188
188
  return filePath;
189
189
  }
190
190
 
@@ -202,14 +202,14 @@ function writeDetectorConfig(cwd, detectorConfig, opts = {}) {
202
202
  if (Object.keys(nextHook).length > 0) next.hook = nextHook;
203
203
  else delete next.hook;
204
204
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
205
- fs.writeFileSync(filePath, JSON.stringify(next, null, 2) + '\n');
205
+ fs.writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`);
206
206
  return filePath;
207
207
  }
208
208
 
209
209
  function mergeHookConfig(existing) {
210
210
  const base = existing && typeof existing === 'object' ? existing : {};
211
211
  return {
212
- enabled: base.enabled === false ? false : true,
212
+ enabled: base.enabled !== false,
213
213
  limits: {
214
214
  maxFindings: Number.isFinite(base?.limits?.maxFindings) ? base.limits.maxFindings : DEFAULT_CONFIG.limits.maxFindings,
215
215
  maxChars: Number.isFinite(base?.limits?.maxChars) ? base.limits.maxChars : DEFAULT_CONFIG.limits.maxChars,
@@ -234,7 +234,7 @@ function mergeDetectorConfig(existing, seed = null) {
234
234
  if (base.designSystem && typeof base.designSystem === 'object' && !Array.isArray(base.designSystem)) {
235
235
  out.designSystem = {
236
236
  ...(out.designSystem || {}),
237
- enabled: base.designSystem.enabled === false ? false : true,
237
+ enabled: base.designSystem.enabled !== false,
238
238
  };
239
239
  }
240
240
  if (Array.isArray(base.ignoreRules)) {
@@ -644,7 +644,7 @@ function reset(cwd) {
644
644
  if (Object.keys(rest).length === 0) {
645
645
  fs.unlinkSync(filePath);
646
646
  } else {
647
- fs.writeFileSync(filePath, JSON.stringify(rest, null, 2) + '\n');
647
+ fs.writeFileSync(filePath, `${JSON.stringify(rest, null, 2)}\n`);
648
648
  }
649
649
  removed.push(path.relative(cwd, filePath).split(path.sep).join('/') || filePath);
650
650
  } catch { /* ignore */ }
@@ -684,7 +684,7 @@ function main() {
684
684
  case 'ignore-value': out = addIgnoreValue(cwd, rest); break;
685
685
  case 'reset': out = reset(cwd); break;
686
686
  }
687
- process.stdout.write(out + '\n');
687
+ process.stdout.write(`${out}\n`);
688
688
  } catch (err) {
689
689
  process.stderr.write(`Error: ${err.message || err}\n`);
690
690
  process.exit(1);
@@ -17,11 +17,11 @@ import path from 'node:path';
17
17
  import {
18
18
  ALLOWED_EXTS,
19
19
  EDIT_COUNT_THRESHOLD,
20
- GENERATED_PATH,
21
20
  SENSITIVE_PATH,
22
21
  appendDesignSystemNote,
23
22
  designSystemOptions,
24
23
  filterFindings,
24
+ isGeneratedPath,
25
25
  isNativePlatform,
26
26
  loadDetector,
27
27
  matchConfiguredExtension,
@@ -162,7 +162,7 @@ function replaceOnce(original, oldString, newString) {
162
162
 
163
163
  function readExistingProjectFile(filePath, cwd) {
164
164
  if (!isInsideProject(filePath, cwd)) return null;
165
- if (SENSITIVE_PATH.test(filePath) || GENERATED_PATH.test(filePath)) return null;
165
+ if (SENSITIVE_PATH.test(filePath) || isGeneratedPath(filePath, cwd)) return null;
166
166
  try {
167
167
  const stat = fs.statSync(filePath);
168
168
  if (!stat.isFile() || stat.size > 1024 * 1024) return null;
@@ -233,7 +233,7 @@ function shellCopiedFileContent(command, cwd) {
233
233
  if (!source) return '';
234
234
  const sourcePath = path.isAbsolute(source) ? source : path.resolve(cwd, source);
235
235
  if (!isInsideProject(sourcePath, cwd)) return '';
236
- if (SENSITIVE_PATH.test(sourcePath) || GENERATED_PATH.test(sourcePath)) return '';
236
+ if (SENSITIVE_PATH.test(sourcePath) || isGeneratedPath(sourcePath, cwd)) return '';
237
237
  try {
238
238
  const stat = fs.statSync(sourcePath);
239
239
  if (!stat.isFile() || stat.size > 1024 * 1024) return '';
@@ -416,7 +416,7 @@ async function main() {
416
416
  if (!filePath) return allow({ ...audit, skipped: 'no-file-path', durationMs: Date.now() - started });
417
417
  if (!isInsideProject(filePath, cwd)) return allow({ ...audit, skipped: 'outside-project', durationMs: Date.now() - started });
418
418
  if (SENSITIVE_PATH.test(filePath)) return allow({ ...audit, skipped: 'sensitive', durationMs: Date.now() - started });
419
- if (GENERATED_PATH.test(filePath)) return allow({ ...audit, skipped: 'generated', durationMs: Date.now() - started });
419
+ if (isGeneratedPath(filePath, cwd)) return allow({ ...audit, skipped: 'generated', durationMs: Date.now() - started });
420
420
 
421
421
  // Config is read before the extension gate so `detector.extensions` entries
422
422
  // (e.g. `.blade.php` template files, issue #316) can widen it.
@@ -73,6 +73,15 @@ export const SENSITIVE_PATH = new RegExp([
73
73
  // Hard-skip regex for generated, lock, minified, and build-output paths.
74
74
  export const GENERATED_PATH = /(?:\.generated\.[a-z]+$|\.d\.ts$|\.min\.[a-z]+$|[/\\]node_modules[/\\]|[/\\](?:dist|build|out|\.next|\.cache|coverage)[/\\]|[/\\]?[^/\\]+\.lock(?:\.json)?$)/i;
75
75
 
76
+ // GENERATED_PATH checked against the path inside the project, so a project
77
+ // that lives under e.g. ~/.cache/ or /srv/build/ is still scanned. Paths
78
+ // outside the project root fall back to the absolute path.
79
+ export function isGeneratedPath(filePath, projectRoot) {
80
+ const rel = path.relative(path.resolve(projectRoot), path.resolve(filePath));
81
+ const inside = rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
82
+ return GENERATED_PATH.test(inside ? path.sep + rel : filePath);
83
+ }
84
+
76
85
  export const TRUTHY = /^(1|true|yes|on)$/i;
77
86
 
78
87
  export const DEFAULT_CONFIG = Object.freeze({
@@ -184,7 +193,7 @@ export function resolveCacheCwd(primaryFile, sessionCwd) {
184
193
  export function resolveProjectPlatform(cwd) {
185
194
  try {
186
195
  const ctx = loadContext(cwd);
187
- return extractPlatform(ctx && ctx.product);
196
+ return extractPlatform(ctx?.product);
188
197
  } catch {
189
198
  return null;
190
199
  }
@@ -239,7 +248,7 @@ function applyDetectorConfigSource(config, raw) {
239
248
  if (raw.designSystem && typeof raw.designSystem === 'object' && !Array.isArray(raw.designSystem)) {
240
249
  config.designSystem = {
241
250
  ...config.designSystem,
242
- enabled: raw.designSystem.enabled === false ? false : true,
251
+ enabled: raw.designSystem.enabled !== false,
243
252
  };
244
253
  }
245
254
  if (Array.isArray(raw.ignoreRules)) {
@@ -302,10 +311,10 @@ export function matchConfiguredExtension(filePath, extensions) {
302
311
 
303
312
  function applyConfigSource(config, raw) {
304
313
  if (!raw || typeof raw !== 'object') return config;
305
- if (Object.prototype.hasOwnProperty.call(raw, 'enabled')) {
306
- config.enabled = raw.enabled === false ? false : true;
314
+ if (Object.hasOwn(raw, 'enabled')) {
315
+ config.enabled = raw.enabled !== false;
307
316
  }
308
- if (Object.prototype.hasOwnProperty.call(raw, 'quiet')) {
317
+ if (Object.hasOwn(raw, 'quiet')) {
309
318
  config.quiet = raw.quiet === true;
310
319
  }
311
320
  if (typeof raw.auditLog === 'string' && raw.auditLog.trim()) {
@@ -399,7 +408,7 @@ function splitColorArgs(body) {
399
408
  if (text.includes(',')) {
400
409
  const parts = text.split(',').map((part) => part.trim()).filter(Boolean);
401
410
  const last = parts[parts.length - 1];
402
- if (last && last.includes('/')) {
411
+ if (last?.includes('/')) {
403
412
  const split = last.split('/').map((part) => part.trim()).filter(Boolean);
404
413
  return [...parts.slice(0, -1), ...split];
405
414
  }
@@ -944,7 +953,7 @@ function clampGroupedToBudget(header, lines, footer, maxChars) {
944
953
  footer,
945
954
  ].join('\n');
946
955
 
947
- let working = lines.slice();
956
+ const working = lines.slice();
948
957
  let omitted = false;
949
958
  let assembled = assemble(working, omitted);
950
959
  while (assembled.length > maxChars && working.length > 1) {
@@ -967,7 +976,7 @@ function clampToBudget(header, lines, more, footer, maxChars) {
967
976
  return blocks.join('\n');
968
977
  };
969
978
 
970
- let working = lines.slice();
979
+ const working = lines.slice();
971
980
  let moreText = more;
972
981
  let assembled = assemble(working, moreText);
973
982
  while (assembled.length > maxChars && working.length > 1) {
@@ -1351,7 +1360,7 @@ export function writeAuditLog(env, entry, cwd = process.cwd()) {
1351
1360
  expanded = path.resolve(baseCwd, target);
1352
1361
  }
1353
1362
  fs.mkdirSync(path.dirname(expanded), { recursive: true });
1354
- const line = JSON.stringify({ ts: new Date().toISOString(), ...entry }) + '\n';
1363
+ const line = `${JSON.stringify({ ts: new Date().toISOString(), ...entry })}\n`;
1355
1364
  fs.appendFileSync(expanded, line);
1356
1365
  return true;
1357
1366
  } catch {
@@ -1573,7 +1582,7 @@ export async function runHook({ stdinJson, env = {}, cwd = process.cwd(), now =
1573
1582
  lastSkip = 'sensitive';
1574
1583
  continue;
1575
1584
  }
1576
- if (GENERATED_PATH.test(filePath)) {
1585
+ if (isGeneratedPath(filePath, projectCwd)) {
1577
1586
  lastSkip = 'generated';
1578
1587
  continue;
1579
1588
  }
@@ -1756,7 +1765,7 @@ export async function runHook({ stdinJson, env = {}, cwd = process.cwd(), now =
1756
1765
  return {
1757
1766
  exitCode: 0,
1758
1767
  stdout: '',
1759
- audit: { ...audit, error: String(err && err.message ? err.message : err) },
1768
+ audit: { ...audit, error: String(err?.message ? err.message : err) },
1760
1769
  };
1761
1770
  }
1762
1771
  }
@@ -51,7 +51,7 @@ main().catch((err) => {
51
51
  writeAuditLog(process.env, {
52
52
  ts: new Date().toISOString(),
53
53
  event: 'PostToolUse',
54
- error: String(err && err.message ? err.message : err),
54
+ error: String(err?.message ? err.message : err),
55
55
  });
56
56
  } catch { /* swallow */ }
57
57
  if (process.env.MONODESIGN_HOOK_DEBUG) {
@@ -130,9 +130,6 @@ function parseScalar(raw) {
130
130
 
131
131
  const HEX_RE = /#[0-9a-fA-F]{3,8}\b/g;
132
132
  const OKLCH_RE = /oklch\([^)]+\)/gi;
133
- const RGBA_RE = /rgba?\([^)]+\)/gi;
134
- const BOX_SHADOW_RE = /(?:box-shadow:\s*)?((?:-?\d[\w\d\s\-.,/()#%]*)+)/;
135
- const NAMED_RULE_RE = /\*\*(The [^*]+?Rule)\.\*\*\s*(.+)/;
136
133
 
137
134
  // ---------- Section splitting ----------
138
135
 
@@ -246,7 +243,7 @@ function collectBullets(lines) {
246
243
  }
247
244
  // continuation of a bullet (indented line)
248
245
  if (current && raw.match(/^\s{2,}\S/)) {
249
- current += ' ' + raw.trim();
246
+ current += ` ${raw.trim()}`;
250
247
  continue;
251
248
  }
252
249
  // blank line ends a bullet
@@ -415,7 +412,7 @@ function parseColorBullet(bullet) {
415
412
 
416
413
  // Case 1 (Monodesign): **Name** (value-with-maybe-nested-parens): description
417
414
  const bold = text.match(/^\*\*(.+?)\*\*\s*(.*)$/);
418
- if (bold && bold[2].startsWith('(')) {
415
+ if (bold?.[2].startsWith('(')) {
419
416
  const value = extractParenGroup(bold[2]);
420
417
  if (value !== null) {
421
418
  const after = bold[2].slice(value.length + 2).trimStart();
@@ -485,36 +482,6 @@ function detectFormat(v) {
485
482
  return 'unknown';
486
483
  }
487
484
 
488
- function scanInlineColors(lines) {
489
- const out = [];
490
- for (const line of lines) {
491
- if (!/^\s*[-*]\s/.test(line)) continue;
492
- const trimmed = line.replace(/^\s*[-*]\s+/, '');
493
- const color = parseColorBullet(trimmed);
494
- if (color) out.push(color);
495
- }
496
- return out;
497
- }
498
-
499
- function parseStitchInlineGroups(lines) {
500
- // Stitch writes: `* **Primary (`#00478d` to `#005eb8`):** Use for "..."`
501
- // Each bullet IS its own role. Group them under the spoken role name.
502
- const out = [];
503
- for (const line of lines) {
504
- if (!/^\s*[-*]\s/.test(line)) continue;
505
- const trimmed = line.replace(/^\s*[-*]\s+/, '').trim();
506
- const m = trimmed.match(
507
- /^\*\*([A-Z][a-zA-Z]+)\s*\(([^)]+)\):\*\*\s*(.*)$/
508
- );
509
- if (m) {
510
- const role = m[1];
511
- const color = buildColor(role, m[2], m[3]);
512
- out.push({ role, colors: [color] });
513
- }
514
- }
515
- return out;
516
- }
517
-
518
485
  function extractTypography(section) {
519
486
  if (!section) return null;
520
487
  const text = section.lines.join('\n');
@@ -611,7 +578,7 @@ function extractElevation(section) {
611
578
  const shadows = [];
612
579
  const seen = new Set();
613
580
  const dedupe = (entry) => {
614
- const key = (entry.name || '') + '::' + entry.value;
581
+ const key = `${entry.name || ''}::${entry.value}`;
615
582
  if (seen.has(key)) return;
616
583
  seen.add(key);
617
584
  shadows.push(entry);
@@ -660,7 +627,7 @@ function extractInlineShadows(text) {
660
627
  .trim();
661
628
  if (stripped) {
662
629
  name =
663
- stripped.charAt(0).toUpperCase() + stripped.slice(1) + ' shadow';
630
+ `${stripped.charAt(0).toUpperCase() + stripped.slice(1)} shadow`;
664
631
  }
665
632
  }
666
633
  out.push({
@@ -830,11 +797,11 @@ export function parseDesignMd(md) {
830
797
  schemaVersion: 2,
831
798
  title,
832
799
  frontmatter,
833
- overview: extractOverview(sections['Overview']),
834
- colors: extractColors(sections['Colors']),
835
- typography: extractTypography(sections['Typography']),
836
- elevation: extractElevation(sections['Elevation']),
837
- components: extractComponents(sections['Components']),
800
+ overview: extractOverview(sections.Overview),
801
+ colors: extractColors(sections.Colors),
802
+ typography: extractTypography(sections.Typography),
803
+ elevation: extractElevation(sections.Elevation),
804
+ components: extractComponents(sections.Components),
838
805
  dosDonts: extractDosDonts(sections["Do's and Don'ts"]),
839
806
  };
840
807
  }
@@ -46,7 +46,7 @@ function isGitIgnored(absPath, cwd) {
46
46
  stdio: 'ignore',
47
47
  });
48
48
  return true; // exit 0 = ignored
49
- } catch (err) {
49
+ } catch {
50
50
  // Exit code 1 = not ignored. Exit code 128 = not a git repo or other error.
51
51
  // In both cases, treat as "not known to be ignored."
52
52
  return false;
@@ -36,11 +36,11 @@ function safeReadJson(filePath) {
36
36
  }
37
37
 
38
38
  function hookSection(raw) {
39
- return raw && raw.hook && typeof raw.hook === 'object' && !Array.isArray(raw.hook) ? raw.hook : null;
39
+ return raw?.hook && typeof raw.hook === 'object' && !Array.isArray(raw.hook) ? raw.hook : null;
40
40
  }
41
41
 
42
42
  function detectorSection(raw) {
43
- return raw && raw.detector && typeof raw.detector === 'object' && !Array.isArray(raw.detector) ? raw.detector : null;
43
+ return raw?.detector && typeof raw.detector === 'object' && !Array.isArray(raw.detector) ? raw.detector : null;
44
44
  }
45
45
 
46
46
  const DETECTOR_CONFIG_KEYS = new Set(['ignoreRules', 'ignoreFiles', 'ignoreValues', 'designSystem']);
@@ -74,7 +74,7 @@ function applyDetectionConfigSource(config, raw) {
74
74
  if (raw.designSystem && typeof raw.designSystem === 'object' && !Array.isArray(raw.designSystem)) {
75
75
  config.designSystem = {
76
76
  ...config.designSystem,
77
- enabled: raw.designSystem.enabled === false ? false : true,
77
+ enabled: raw.designSystem.enabled !== false,
78
78
  };
79
79
  }
80
80
  if (Array.isArray(raw.ignoreRules)) {
@@ -153,7 +153,7 @@ function normalizeDetectionConfigForWrite(config) {
153
153
  out.ignoreValues = normalizeIgnoreValueEntries(config?.ignoreValues || []);
154
154
  if (config?.designSystem && typeof config.designSystem === 'object' && !Array.isArray(config.designSystem)) {
155
155
  out.designSystem = {
156
- enabled: config.designSystem.enabled === false ? false : true,
156
+ enabled: config.designSystem.enabled !== false,
157
157
  };
158
158
  }
159
159
  return out;
@@ -242,7 +242,7 @@ function splitColorArgs(body) {
242
242
  if (text.includes(',')) {
243
243
  const parts = text.split(',').map((part) => part.trim()).filter(Boolean);
244
244
  const last = parts[parts.length - 1];
245
- if (last && last.includes('/')) {
245
+ if (last?.includes('/')) {
246
246
  const split = last.split('/').map((part) => part.trim()).filter(Boolean);
247
247
  return [...parts.slice(0, -1), ...split];
248
248
  }
@@ -43,7 +43,7 @@ export function getLegacyLiveConfigPath(scriptsDir) {
43
43
  }
44
44
 
45
45
  export function resolveLiveConfigPath({ cwd = process.cwd(), scriptsDir, env = process.env, targetPath } = {}) {
46
- if (env.MONODESIGN_LIVE_CONFIG && env.MONODESIGN_LIVE_CONFIG.trim()) {
46
+ if (env.MONODESIGN_LIVE_CONFIG?.trim()) {
47
47
  const configured = env.MONODESIGN_LIVE_CONFIG.trim();
48
48
  return path.isAbsolute(configured) ? configured : path.resolve(cwd, configured);
49
49
  }