From bc1894889e89ee8a53ad7d2a2d72157060170170 Mon Sep 17 00:00:00 2001 From: Paul Bakaus Date: Mon, 18 May 2026 15:15:14 -0700 Subject: [PATCH] Improve critique skill reliability - add provider-specific block compilation and tests - bundle detector scripts for skill critique runs - harden critique orchestration, browser handling, and storage --- .../skills/impeccable/reference/critique.md | 156 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .agents/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .claude/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .cursor/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .gemini/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .github/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .kiro/skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .kiro/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .../skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .pi/skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .pi/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .pi/skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .qoder/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .rovodev/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .trae-cn/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- .trae/skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- .trae/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- package.json | 2 +- .../skills/impeccable/reference/critique.md | 137 +- .../impeccable/scripts/critique-storage.mjs | 23 +- plugin/skills/impeccable/scripts/detect.mjs | 21 + .../detector/browser/injected/index.mjs | 1688 +++++++ .../impeccable/scripts/detector/cli/main.mjs | 232 + .../detector/detect-antipatterns-browser.js | 4030 +++++++++++++++++ .../scripts/detector/detect-antipatterns.mjs | 43 + .../detector/engines/browser/detect-url.mjs | 251 + .../detector/engines/regex/detect-text.mjs | 420 ++ .../engines/static-html/css-cascade.mjs | 954 ++++ .../engines/static-html/detect-html.mjs | 174 + .../engines/visual/screenshot-contrast.mjs | 189 + .../impeccable/scripts/detector/findings.mjs | 12 + .../scripts/detector/node/file-system.mjs | 198 + .../scripts/detector/profile/profiler.mjs | 166 + .../detector/registry/antipatterns.mjs | 278 ++ .../scripts/detector/rules/checks.mjs | 1948 ++++++++ .../scripts/detector/shared/color.mjs | 124 + .../scripts/detector/shared/constants.mjs | 101 + .../scripts/detector/shared/page.mjs | 7 + .../skills/impeccable/scripts/live-server.mjs | 6 +- scripts/lib/transformers/factory.js | 31 +- scripts/lib/transformers/providers.js | 14 + scripts/lib/utils.js | 72 + skill/reference/critique.md | 170 +- skill/scripts/critique-storage.mjs | 23 +- skill/scripts/detect.mjs | 21 + skill/scripts/live-server.mjs | 6 +- tests/critique-storage.test.mjs | 18 +- tests/lib/detector-bundle.test.js | 27 + tests/lib/provider-blocks.test.js | 86 + .../lib/transformers/provider-blocks.test.js | 137 + 285 files changed, 142401 insertions(+), 1251 deletions(-) create mode 100644 .agents/skills/impeccable/scripts/detect.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .agents/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .agents/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .claude/skills/impeccable/scripts/detect.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .claude/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .claude/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .cursor/skills/impeccable/scripts/detect.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .cursor/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .cursor/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .gemini/skills/impeccable/scripts/detect.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .gemini/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .gemini/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .github/skills/impeccable/scripts/detect.mjs create mode 100644 .github/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .github/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .github/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .github/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .github/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .github/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .github/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .github/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .github/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .github/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .github/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .github/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .github/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .github/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .github/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .github/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .github/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .kiro/skills/impeccable/scripts/detect.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .kiro/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .kiro/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .opencode/skills/impeccable/scripts/detect.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .opencode/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .opencode/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .pi/skills/impeccable/scripts/detect.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .pi/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .pi/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .qoder/skills/impeccable/scripts/detect.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .qoder/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .qoder/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detect.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .rovodev/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .rovodev/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detect.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .trae-cn/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .trae-cn/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 .trae/skills/impeccable/scripts/detect.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 .trae/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/findings.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 .trae/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 plugin/skills/impeccable/scripts/detect.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/browser/injected/index.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/cli/main.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/detect-antipatterns-browser.js create mode 100644 plugin/skills/impeccable/scripts/detector/detect-antipatterns.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/findings.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/node/file-system.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/profile/profiler.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/registry/antipatterns.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/rules/checks.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/shared/color.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/shared/constants.mjs create mode 100644 plugin/skills/impeccable/scripts/detector/shared/page.mjs create mode 100644 skill/scripts/detect.mjs create mode 100644 tests/lib/detector-bundle.test.js create mode 100644 tests/lib/provider-blocks.test.js create mode 100644 tests/lib/transformers/provider-blocks.test.js diff --git a/.agents/skills/impeccable/reference/critique.md b/.agents/skills/impeccable/reference/critique.md index 9c33472e7..4e84fcb55 100644 --- a/.agents/skills/impeccable/reference/critique.md +++ b/.agents/skills/impeccable/reference/critique.md @@ -1,109 +1,96 @@ -> **Additional context needed**: what the interface is trying to accomplish. +### Purpose -### Setup: Resolve Target and Load Ignore List +Resolve one stable target, run two independent assessments, synthesize a design critique, persist a snapshot, and ask the user what to improve next. The chat response is the primary deliverable; the snapshot is an archive/backlog for future commands. -Before gathering assessments, do two small bookkeeping steps. They cost almost nothing and they're what makes critique iterative across runs. +### Hard Invariants -1. **Resolve the primary artifact.** The user's phrasing ("the homepage", "the pricing flow") is not stable enough to track across runs. Resolve it to a concrete file path or URL: the same one you'd already need to scan code or open in a browser. Examples: - - "the homepage" → `site/pages/index.astro` (or `http://localhost:3000/` if you're inspecting live) - - "the settings modal" → the primary component file (e.g., `src/components/Settings.tsx`) - - "this page" → the URL or the page's source file - Prefer the source file path over the dev-server URL when both exist; ports drift between runs (`bun dev` vs `bun preview`), file paths don't. +- Assessment A (design review) and Assessment B (detector/browser evidence) are both required. +- Assessment A must finish before detector findings enter the parent synthesis context. Detector output is deterministic, but it still anchors judgment. +- If sub-agents are unavailable, fall back sequentially: finish and record Assessment A first, then run Assessment B, then synthesize. +- A skipped detector is a failed critique run unless `detect.mjs` is missing or crashes after a real attempt. +- Viewable targets require browser inspection when available. +- Any local server started only for critique visualization must run in the background, have a recorded stop method, and be stopped before final reporting unless the user asks to keep it. +- Do not claim a user-visible overlay exists unless script injection succeeded and the detector ran in the page. -2. **Compute the slug.** Run: +### Setup + +1. **Resolve the target** to a concrete file path or URL. Prefer a source path over a dev-server URL when both identify the same surface; ports drift, paths do not. + - "the homepage" -> `site/pages/index.astro` or `index.html` + - "the settings modal" -> the primary component file + - "this page" -> the current URL or source file +2. **Compute the slug**: ```bash node .agents/skills/impeccable/scripts/critique-storage.mjs slug "" ``` - Keep the printed slug. It identifies this target's stream across runs. If the command exits non-zero ("no stable slug for input"), skip persistence for this run and tell the user; the trend won't update but the critique still goes ahead. + Keep it. If the command exits non-zero, skip persistence and trend for this run, but continue the critique. +3. **Read `.impeccable/critique/ignore.md`** if it exists. Drop matching findings silently; it is the only prior-run input critique consumes. -3. **Read the ignore list** at `.impeccable/critique/ignore.md` if it exists. Plain markdown; each non-empty, non-comment line is something the user has marked as "do not re-raise" (deferred tradeoffs, designer-intended deviations, detector false-positives the user accepts). When a finding's text matches a line here (case-insensitive substring against rule name or snippet), **drop it silently**. Do not mention it in the report. This is the ONLY input critique consumes from prior runs; anchoring on prior findings would defeat the point of independent assessment. +### Assessment Orchestration -### Gather Assessments +Delegate Assessment A and Assessment B to separate sub-agents when possible. They must not see each other's output. Do not show findings to the user until synthesis. -Launch two independent assessments. **Neither may see the other's output.** This isolation is what makes the combined score honest. Running both in one head silently anchors them to each other; do not shortcut it for cost, speed, or context-size reasons. +Codex sub-agent gate: +- If `spawn_agent` is exposed and the user explicitly allowed sub-agents, delegation, or parallel agent work, spawn A and B immediately. +- If `spawn_agent` is exposed but the user did not explicitly allow sub-agents, ask exactly once: "Impeccable critique is designed to run two independent sub-agents for an unanchored assessment. May I use sub-agents for this critique?" Then stop until the user answers. +- If allowed, spawn A and B. If declined, run sequentially and report `Assessment independence: degraded (sub-agents declined by user)`. +- If `spawn_agent` is not exposed, do not ask; run sequentially and report `Assessment independence: degraded (spawn_agent unavailable in this session)`. +- If spawning fails after permission, run sequentially and report `Assessment independence: degraded (sub-agent spawn failed: )`. +Prefer `fork_context: false` with self-contained prompts containing cwd, target, live URL, references, product context, and output contract. If using `fork_context: true`, omit `agent_type`, `model`, and `reasoning_effort`. -Delegate each assessment to a separate sub-agent (Claude Code's `Agent` tool, Codex's subagent spawning, etc.). Each returns structured findings as text. Do NOT output findings to the user yet. +If browser automation is available, each assessment creates its own new tab. Never reuse an existing tab, even if it is already at the right URL. -Fall back to sequential in-head work only if the environment genuinely cannot spawn sub-agents. +### Assessment A: Design Review -**Tab isolation**: When browser automation is available, each assessment MUST create its own new tab. Never reuse an existing tab, even if one is already open at the correct URL. This prevents the two assessments from interfering with each other's page state. +Read relevant source files and visually inspect the live page when browser automation is available. Think like a design director. -#### Assessment A: LLM Design Review +Evaluate: +- **AI slop**: Would someone believe "AI made this" immediately? Check all DON'T guidance from the parent Impeccable skill. +- **Holistic design**: hierarchy, IA, emotional fit, discoverability, composition, typography, color, accessibility, states, copy, and edge cases. +- **Cognitive load**: consult [cognitive-load](cognitive-load.md); report checklist failures and decision points with >4 visible options. +- **Emotional journey**: peak-end rule, emotional valleys, reassurance at high-stakes moments. +- **Nielsen heuristics**: consult [heuristics-scoring](heuristics-scoring.md); score all 10 heuristics 0-4. -Read the relevant source files (HTML, CSS, JS/TS) and, if browser automation is available, visually inspect the live page. **Create a new tab** for this; do not reuse existing tabs. After navigation, label the tab by setting the document title: -```javascript -document.title = '[LLM] ' + document.title; -``` -Think like a design director. Evaluate: +Return: AI slop verdict, heuristic scores, cognitive load, emotional journey, 2-3 strengths, 3-5 priority issues, persona red flags, minor observations, and provocative questions. -**AI Slop Detection (CRITICAL)**: Does this look like every other AI-generated interface? Review against ALL **DON'T** guidelines from the parent impeccable skill (already loaded in this context). Check for AI color palette, gradient text, dark glows, glassmorphism, hero metric layouts, identical card grids, generic fonts, and all other tells. **The test**: If someone said "AI made this," would you believe them immediately? +### Assessment B: Detector + Browser Evidence -**Holistic Design Review**: visual hierarchy (eye flow, primary action clarity), information architecture (structure, grouping, cognitive load), emotional resonance (does it match brand and audience?), discoverability (are interactive elements obvious?), composition (balance, whitespace, rhythm), typography (hierarchy, readability, font choices), color (purposeful use, cohesion, accessibility), states & edge cases (empty, loading, error, success), microcopy (clarity, tone, helpfulness). +Run the bundled detector and browser visualization evidence. Assessment B is mandatory and must remain isolated from Assessment A until both are complete. -**Cognitive Load** (consult [cognitive-load](cognitive-load.md)): -- Run the 8-item cognitive load checklist. Report failure count: 0-1 = low (good), 2-3 = moderate, 4+ = critical. -- Count visible options at each decision point. If >4, flag it. -- Check for progressive disclosure: is complexity revealed only when needed? - -**Emotional Journey**: -- What emotion does this interface evoke? Is that intentional? -- **Peak-end rule**: Is the most intense moment positive? Does the experience end well? -- **Emotional valleys**: Check for anxiety spikes at high-stakes moments (payment, delete, commit). Are there design interventions (progress indicators, reassurance copy, undo options)? - -**Nielsen's Heuristics** (consult [heuristics-scoring](heuristics-scoring.md)): -Score each of the 10 heuristics 0-4. This scoring will be presented in the report. - -Return structured findings covering: AI slop verdict, heuristic scores, cognitive load assessment, what's working (2-3 items), priority issues (3-5 with what/why/fix), minor observations, and provocative questions. - -#### Assessment B: Automated Detection - -Run the bundled deterministic detector, which flags 27 specific patterns (AI slop tells + general design quality). - -**CLI scan**: +CLI scan: ```bash -npx impeccable detect --json [--fast] [target] +node .agents/skills/impeccable/scripts/detect.mjs --json [--fast] [target] ``` -- Pass HTML/JSX/TSX/Vue/Svelte files or directories as `[target]` (anything with markup). Do not pass CSS-only files. -- For URLs, skip the CLI scan (it requires Puppeteer). Use browser visualization instead. -- For large directories (200+ scannable files), use `--fast` (regex-only, skips jsdom) -- For 500+ files, narrow scope or ask the user -- Exit code 0 = clean, 2 = findings +- Pass markup files/directories as `[target]`; do not pass CSS-only files. +- For URLs, skip CLI scan and use browser visualization. +- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask. +- Exit code 0 = clean; 2 = findings. +- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review. -**Browser visualization**: **required** when browser automation tools are available AND the target is a viewable page. The `[Human]` overlay tab is the user-facing deliverable; the critique is incomplete without it. Skip only if the target is not a viewable page (CSS-only file, non-browser target). +Browser visualization is required for a viewable target when browser automation is available. Use a localhost dev/static URL for local files; avoid `file://` unless the available browser explicitly supports this workflow. Overlay flow: -The overlay is a **visual aid for the user**. It highlights issues directly in their browser. Do NOT scroll through the page to screenshot overlays. Instead, read the console output to get the results programmatically. +1. Create a fresh tab and navigate. +2. Preflight mutable injection by setting `document.title` and appending a ` + * Re-scan: window.impeccableScan() + */ +(function () { +if (typeof window === 'undefined') return; +// --- cli/engine/shared/constants.mjs --- +// ─── Section 1: Constants ─────────────────────────────────────────────────── + +const SAFE_TAGS = new Set([ + 'blockquote', 'nav', 'a', 'input', 'textarea', 'select', + 'pre', 'code', 'span', 'th', 'td', 'tr', 'li', 'label', + 'button', 'hr', 'html', 'head', 'body', 'script', 'style', + 'link', 'meta', 'title', 'br', 'img', 'svg', 'path', 'circle', + 'rect', 'line', 'polyline', 'polygon', 'g', 'defs', 'use', +]); + +// Per-check safe-tags override for the border (side-tab / border-accent) +// rule. We intentionally re-allow