@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
@@ -158,11 +158,10 @@ function probePort(p) {
158
158
  // shelling out to `lsof` (Unix-only — unavailable on Windows, which left the
159
159
  // pairing step below permanently broken there: control.json stuck at pid:0
160
160
  // forever, dashboard-token never refreshed after the shared server restarts).
161
- // GET / is an intentionally-open route that embeds the live auth token in a
162
- // <meta name="mm-token"> tag for exactly this same-machine, loopback-trusted
163
- // purpose; re-using it here to authenticate a follow-up GET /api/status call
164
- // gets both the pid and the project `dir` in one portable HTTP round trip —
165
- // no OS-specific process inspection needed on any platform.
161
+ // GET /api/identity names the server's pid, project `dir` and token FILE —
162
+ // never the token itself (the dashboard's pages only embed it for a logged-in
163
+ // browser). The token is read from that file as the same user, in one
164
+ // portable HTTP round trip — no OS-specific process inspection needed.
166
165
  function fetchForeignServerInfo(p) {
167
166
  const http = require('http');
168
167
  const getBody = (reqPath, headers) => new Promise((resolve) => {
@@ -175,16 +174,14 @@ function fetchForeignServerInfo(p) {
175
174
  req.on('timeout', () => { req.destroy(); resolve(null); });
176
175
  });
177
176
  return (async () => {
178
- const home = await getBody('/');
179
- if (!home) return null;
180
- const m = home.body.match(/name="mm-token" content="([^"]*)"/);
181
- const token = m ? m[1] : null;
182
- if (!token) return null;
183
- const status = await getBody('/api/status', { 'x-monomind-token': token });
184
- if (!status) return null;
177
+ const id = await getBody('/api/identity');
178
+ if (!id || id.statusCode !== 200) return null;
185
179
  try {
186
- const parsed = JSON.parse(status.body);
180
+ const parsed = JSON.parse(id.body);
187
181
  if (typeof parsed.pid !== 'number' || typeof parsed.dir !== 'string') return null;
182
+ const tokenFile = typeof parsed.tokenFile === 'string' ? parsed.tokenFile : path.join(parsed.dir, '.monomind', 'dashboard-token');
183
+ const token = fs.readFileSync(tokenFile, 'utf8').trim();
184
+ if (!token) return null;
188
185
  return { pid: parsed.pid, dir: parsed.dir, token };
189
186
  } catch { return null; }
190
187
  })();
@@ -205,7 +205,7 @@ function resolveLocalContextDir(root) {
205
205
 
206
206
  function resolveEnvContextDir(cwd) {
207
207
  const envDir = process.env.MONODESIGN_CONTEXT_DIR;
208
- if (!envDir || !envDir.trim()) return null;
208
+ if (!envDir?.trim()) return null;
209
209
  const trimmed = envDir.trim();
210
210
  return path.isAbsolute(trimmed) ? trimmed : path.resolve(cwd, trimmed);
211
211
  }
@@ -930,7 +930,7 @@ async function cli() {
930
930
  const targetExists = targetProvided ? pathExistsForTarget(process.cwd(), cliOptions.targetPath) : null;
931
931
  const selection = resolveTargetSelection(process.cwd(), cliOptions);
932
932
  if (selection) {
933
- process.stdout.write(buildTargetSelectionDirective(selection) + '\n');
933
+ process.stdout.write(`${buildTargetSelectionDirective(selection)}\n`);
934
934
  process.exit(0);
935
935
  }
936
936
  const ctx = loadContext(process.cwd(), cliOptions);
@@ -952,7 +952,7 @@ async function cli() {
952
952
  parts.push(buildMissingTargetDirective());
953
953
  }
954
954
  if (updateDirective) parts.push(updateDirective);
955
- process.stdout.write(parts.join('\n\n---\n\n') + '\n');
955
+ process.stdout.write(`${parts.join('\n\n---\n\n')}\n`);
956
956
  process.exit(0);
957
957
  }
958
958
  const parts = [`# PRODUCT.md\n\n${ctx.product.trim()}`];
@@ -989,7 +989,7 @@ async function cli() {
989
989
  }
990
990
  }
991
991
  if (updateDirective) parts.push(updateDirective);
992
- process.stdout.write(parts.join('\n\n---\n\n') + '\n');
992
+ process.stdout.write(`${parts.join('\n\n---\n\n')}\n`);
993
993
  }
994
994
 
995
995
  function parseCliOptions(args) {
@@ -381,7 +381,7 @@ function main(argv) {
381
381
  }
382
382
  case 'trend': {
383
383
  const rows = readTrend(args[0], { limit: args[1] ? Number(args[1]) : 5 });
384
- process.stdout.write(JSON.stringify(rows, null, 2) + '\n');
384
+ process.stdout.write(`${JSON.stringify(rows, null, 2)}\n`);
385
385
  return;
386
386
  }
387
387
  case 'recall': {
@@ -71,11 +71,6 @@ const INLINE_HEADER_SIGNALS = [
71
71
  /\bscript-src\b/,
72
72
  /\bconnect-src\b/,
73
73
  ];
74
- const NUXT_ROUTE_RULES_SIGNALS = [
75
- /\brouteRules\b/,
76
- /Content-Security-Policy/i,
77
- /\bscript-src\b/,
78
- ];
79
74
 
80
75
  const MIDDLEWARE_HINT = /headers\.set\(\s*["']Content-Security-Policy["']/i;
81
76
  const META_TAG_HINT = /http-equiv\s*=\s*["']Content-Security-Policy["']/i;
@@ -91,7 +86,7 @@ export function detectCsp(cwd = process.cwd()) {
91
86
  const ext = path.extname(absPath);
92
87
  const base = path.basename(absPath).toLowerCase();
93
88
  const isConfig = (name) =>
94
- new RegExp('(^|/)' + name + '\\.config\\.').test(relPath);
89
+ new RegExp(`(^|/)${name}\\.config\\.`).test(relPath);
95
90
 
96
91
  // === append-arrays candidates ===
97
92
 
@@ -112,7 +112,7 @@ if (IS_BROWSER) {
112
112
  }
113
113
 
114
114
  function showSpotlight(target) {
115
- if (!target || !target.getBoundingClientRect) return;
115
+ if (!target?.getBoundingClientRect) return;
116
116
  // Respect the spotlightBlur setting: if disabled, don't show the backdrop
117
117
  if (window.__MONODESIGN_CONFIG__?.spotlightBlur === false) {
118
118
  spotlightTarget = target;
@@ -258,10 +258,8 @@ if (IS_BROWSER) {
258
258
  }
259
259
  });
260
260
 
261
- const highlight = function(el, findings) {
261
+ const highlight = (el, findings) => {
262
262
  if (el._monodesignOverlay) detachOverlay(el._monodesignOverlay);
263
- const hasSlop = findings.some(f => RULE_CATEGORY[f.type || f.id] === 'slop');
264
-
265
263
  const fixed = isInFixedContext(el);
266
264
  const rect = el.getBoundingClientRect();
267
265
  const outline = document.createElement('div');
@@ -405,7 +403,7 @@ if (IS_BROWSER) {
405
403
  overlays.push(outline);
406
404
  };
407
405
 
408
- const showPageBanner = function(findings) {
406
+ const showPageBanner = (findings) => {
409
407
  if (!findings.length) return;
410
408
  const banner = document.createElement('div');
411
409
  banner.className = 'monodesign-overlay monodesign-banner';
@@ -505,7 +503,7 @@ if (IS_BROWSER) {
505
503
  .filter(c => !c.startsWith('monodesign-') && !isLikelyHashedClass(c))
506
504
  .slice(0, 2);
507
505
  if (classes.length > 0) {
508
- sel += '.' + classes.map(c => CSS.escape(c)).join('.');
506
+ sel += `.${classes.map(c => CSS.escape(c)).join('.')}`;
509
507
  }
510
508
  }
511
509
 
@@ -513,7 +511,7 @@ if (IS_BROWSER) {
513
511
  const parent = el.parentElement;
514
512
  if (parent) {
515
513
  try {
516
- const matching = parent.querySelectorAll(':scope > ' + sel);
514
+ const matching = parent.querySelectorAll(`:scope > ${sel}`);
517
515
  if (matching.length > 1) {
518
516
  const sameType = [...parent.children].filter(c => c.tagName === el.tagName);
519
517
  const idx = sameType.indexOf(el) + 1;
@@ -530,7 +528,7 @@ if (IS_BROWSER) {
530
528
  function generateSelector(el) {
531
529
  if (el === document.body) return 'body';
532
530
  if (el === document.documentElement) return 'html';
533
- if (el.id) return '#' + CSS.escape(el.id);
531
+ if (el.id) return `#${CSS.escape(el.id)}`;
534
532
 
535
533
  const parts = [];
536
534
  let current = el;
@@ -542,7 +540,7 @@ if (IS_BROWSER) {
542
540
 
543
541
  // Anchor on an ancestor's ID and stop walking up
544
542
  if (current.id) {
545
- parts[0] = '#' + CSS.escape(current.id);
543
+ parts[0] = `#${CSS.escape(current.id)}`;
546
544
  break;
547
545
  }
548
546
 
@@ -682,7 +680,7 @@ if (IS_BROWSER) {
682
680
 
683
681
  const textColor = parseRgb(style.color);
684
682
  const fontSize = parseFloat(style.fontSize) || 16;
685
- const fontWeight = parseInt(style.fontWeight) || 400;
683
+ const fontWeight = parseInt(style.fontWeight, 10) || 400;
686
684
  const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700);
687
685
  const threshold = isLargeText ? 3.0 : 4.5;
688
686
  const clip = {
@@ -900,7 +898,7 @@ if (IS_BROWSER) {
900
898
  function sampleDrawablePixel(drawable, sourcePoint) {
901
899
  if (visualContrastRasterCache.has(drawable)) {
902
900
  const cached = visualContrastRasterCache.get(drawable);
903
- if (!cached || !cached.ctx) return { status: 'unresolved', reason: cached?.reason || 'image sample failed' };
901
+ if (!cached?.ctx) return { status: 'unresolved', reason: cached?.reason || 'image sample failed' };
904
902
  try {
905
903
  const x = Math.max(0, Math.min(cached.width - 1, Math.floor(sourcePoint.x * cached.scaleX)));
906
904
  const y = Math.max(0, Math.min(cached.height - 1, Math.floor(sourcePoint.y * cached.scaleY)));
@@ -1035,7 +1033,7 @@ if (IS_BROWSER) {
1035
1033
  const unresolved = [];
1036
1034
 
1037
1035
  for (const node of nodes) {
1038
- if (!node || node.nodeType !== 1) continue;
1036
+ if (node?.nodeType !== 1) continue;
1039
1037
  if (node.closest?.('.monodesign-overlay, .monodesign-label, .monodesign-banner, .monodesign-tooltip')) continue;
1040
1038
  const tag = node.tagName?.toLowerCase();
1041
1039
  if (tag === 'img') {
@@ -1232,7 +1230,7 @@ if (IS_BROWSER) {
1232
1230
  }));
1233
1231
  }
1234
1232
 
1235
- const printSummary = function(allFindings) {
1233
+ const printSummary = (allFindings) => {
1236
1234
  if (allFindings.length === 0) {
1237
1235
  console.log('%c[monodesign] No anti-patterns found.', 'color: #22c55e; font-weight: bold');
1238
1236
  return;
@@ -1559,7 +1557,7 @@ if (IS_BROWSER) {
1559
1557
  try { rules = sheet.cssRules; } catch { continue; }
1560
1558
  if (!rules) continue;
1561
1559
  for (const rule of Array.from(rules)) {
1562
- try { stylesheetCssText += rule.cssText + '\n'; } catch { /* ignore */ }
1560
+ try { stylesheetCssText += `${rule.cssText}\n`; } catch { /* ignore */ }
1563
1561
  }
1564
1562
  }
1565
1563
  const stylesheetFindings = [
@@ -1832,7 +1830,7 @@ if (IS_BROWSER) {
1832
1830
  }
1833
1831
 
1834
1832
  let firstScanDone = false;
1835
- const scan = function(options = {}) {
1833
+ const scan = (options = {}) => {
1836
1834
  clearOverlays();
1837
1835
  const generation = scanGeneration;
1838
1836
  const collected = collectBrowserFindings();
@@ -1849,7 +1847,7 @@ if (IS_BROWSER) {
1849
1847
  return allFindings;
1850
1848
  };
1851
1849
 
1852
- const scanAsync = async function(options = {}) {
1850
+ const scanAsync = async (options = {}) => {
1853
1851
  clearOverlays();
1854
1852
  const generation = scanGeneration;
1855
1853
  if (shouldRunVisualContrast(options)) {
@@ -1861,13 +1859,13 @@ if (IS_BROWSER) {
1861
1859
  return renderBrowserFindings(collectBrowserFindings(), options);
1862
1860
  };
1863
1861
 
1864
- const detect = function(options = {}) {
1862
+ const detect = (options = {}) => {
1865
1863
  lastVisualContrastAnalyses = [];
1866
1864
  const { allFindings } = collectBrowserFindings();
1867
1865
  return options.serialize === false ? allFindings : serializeFindings(allFindings);
1868
1866
  };
1869
1867
 
1870
- const detectAsync = async function(options = {}) {
1868
+ const detectAsync = async (options = {}) => {
1871
1869
  if (shouldRunVisualContrast(options)) {
1872
1870
  const { allFindings } = await collectBrowserFindingsAsync(options);
1873
1871
  return options.serialize === false ? allFindings : serializeFindings(allFindings);
@@ -309,9 +309,9 @@ async function detectCli() {
309
309
  allFindings = filterByScopes(allFindings, scopes);
310
310
 
311
311
  if (allFindings.length > 0) {
312
- if (jsonMode) process.stdout.write(formatFindings(allFindings, true) + '\n');
313
- else if (quietMode) process.stderr.write(formatFindingSummary(allFindings.length) + '\n');
314
- else process.stderr.write(formatFindings(allFindings, false) + '\n');
312
+ if (jsonMode) process.stdout.write(`${formatFindings(allFindings, true)}\n`);
313
+ else if (quietMode) process.stderr.write(`${formatFindingSummary(allFindings.length)}\n`);
314
+ else process.stderr.write(`${formatFindings(allFindings, false)}\n`);
315
315
  process.exit(2);
316
316
  }
317
317
  if (jsonMode) process.stdout.write('[]\n');