quiver-cli 0.7.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/README.md +110 -45
  2. package/bin/quiver-cli.mjs +3 -1
  3. package/dist/cli.js +733 -499
  4. package/package.json +2 -2
  5. package/template/.agents/AGENTS.md +4 -3
  6. package/template/.agents/config.json +7 -0
  7. package/template/.agents/plugins/opencode/rtk.ts +34 -0
  8. package/template/.agents/skills/agent-browser/SKILL.md +1 -0
  9. package/template/.agents/skills/apps/skybridge/SKILL.md +4 -0
  10. package/template/.agents/skills/design/impeccable/SKILL.md +36 -118
  11. package/template/.agents/skills/design/impeccable/reference/adapt.md +1 -0
  12. package/template/.agents/skills/design/impeccable/reference/adapt.native.md +58 -0
  13. package/template/.agents/skills/design/impeccable/reference/android.md +40 -0
  14. package/template/.agents/skills/design/impeccable/reference/animate.md +73 -188
  15. package/template/.agents/skills/design/impeccable/reference/audit.md +12 -9
  16. package/template/.agents/skills/design/impeccable/reference/audit.native.md +139 -0
  17. package/template/.agents/skills/design/impeccable/reference/bolder.md +19 -101
  18. package/template/.agents/skills/design/impeccable/reference/clarify.md +59 -253
  19. package/template/.agents/skills/design/impeccable/reference/colorize.md +51 -222
  20. package/template/.agents/skills/design/impeccable/reference/craft-floor.md +42 -0
  21. package/template/.agents/skills/design/impeccable/reference/craft.md +3 -121
  22. package/template/.agents/skills/design/impeccable/reference/critique.md +44 -23
  23. package/template/.agents/skills/design/impeccable/reference/degraded/asset-producer.md +90 -0
  24. package/template/.agents/skills/design/impeccable/reference/degraded/documenter.md +24 -0
  25. package/template/.agents/skills/design/impeccable/reference/degraded/finish-reviewer.md +37 -0
  26. package/template/.agents/skills/design/impeccable/reference/degraded/manual-edit-applier.md +92 -0
  27. package/template/.agents/skills/design/impeccable/reference/delight.md +47 -279
  28. package/template/.agents/skills/design/impeccable/reference/distill.md +2 -2
  29. package/template/.agents/skills/design/impeccable/reference/doctor.md +53 -0
  30. package/template/.agents/skills/design/impeccable/reference/document.md +60 -73
  31. package/template/.agents/skills/design/impeccable/reference/harden.md +1 -12
  32. package/template/.agents/skills/design/impeccable/reference/hooks.md +20 -5
  33. package/template/.agents/skills/design/impeccable/reference/init.md +72 -119
  34. package/template/.agents/skills/design/impeccable/reference/ios.md +45 -0
  35. package/template/.agents/skills/design/impeccable/reference/layout.md +54 -131
  36. package/template/.agents/skills/design/impeccable/reference/live-setup.md +102 -0
  37. package/template/.agents/skills/design/impeccable/reference/live.md +116 -511
  38. package/template/.agents/skills/design/impeccable/reference/new-work.md +105 -0
  39. package/template/.agents/skills/design/impeccable/reference/{product.md → operate.md} +6 -5
  40. package/template/.agents/skills/design/impeccable/reference/optimize.md +4 -4
  41. package/template/.agents/skills/design/impeccable/reference/overdrive.md +1 -4
  42. package/template/.agents/skills/design/impeccable/reference/polish.md +68 -212
  43. package/template/.agents/skills/design/impeccable/reference/quieter.md +3 -3
  44. package/template/.agents/skills/design/impeccable/reference/routing.md +18 -0
  45. package/template/.agents/skills/design/impeccable/reference/shape.md +38 -144
  46. package/template/.agents/skills/design/impeccable/reference/typeset.md +51 -250
  47. package/template/.agents/skills/design/impeccable/reference/visualize.md +47 -0
  48. package/template/.agents/skills/design/impeccable/scripts/command-metadata.json +1 -1
  49. package/template/.agents/skills/design/impeccable/scripts/concept-seed.mjs +558 -0
  50. package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +119 -10
  51. package/template/.agents/skills/design/impeccable/scripts/context.mjs +534 -45
  52. package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +18 -47
  53. package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +96 -10
  54. package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +174 -26
  55. package/template/.agents/skills/design/impeccable/scripts/detector/design-system.mjs +233 -0
  56. package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +3348 -203
  57. package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +102 -7
  58. package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +297 -97
  59. package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +187 -16
  60. package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +41 -11
  61. package/template/.agents/skills/design/impeccable/scripts/detector/findings.mjs +7 -1
  62. package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +16 -2
  63. package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +207 -38
  64. package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +3082 -173
  65. package/template/.agents/skills/design/impeccable/scripts/detector/shared/constants.mjs +11 -0
  66. package/template/.agents/skills/design/impeccable/scripts/detector/shared/fonts.mjs +30 -0
  67. package/template/.agents/skills/design/impeccable/scripts/doctor.mjs +336 -0
  68. package/template/.agents/skills/design/impeccable/scripts/embed-prompt.mjs +133 -0
  69. package/template/.agents/skills/design/impeccable/scripts/generate-image.mjs +240 -0
  70. package/template/.agents/skills/design/impeccable/scripts/hook-admin.mjs +98 -18
  71. package/template/.agents/skills/design/impeccable/scripts/hook-before-edit.mjs +46 -6
  72. package/template/.agents/skills/design/impeccable/scripts/hook-lib.mjs +518 -50
  73. package/template/.agents/skills/design/impeccable/scripts/hook.mjs +25 -8
  74. package/template/.agents/skills/design/impeccable/scripts/lib/artifact-schema.mjs +93 -0
  75. package/template/.agents/skills/design/impeccable/scripts/lib/composition-catalog.mjs +200 -0
  76. package/template/.agents/skills/design/impeccable/scripts/lib/concept-catalog.mjs +357 -0
  77. package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-config.mjs +27 -7
  78. package/template/.agents/skills/design/impeccable/scripts/lib/impeccable-paths.mjs +17 -8
  79. package/template/.agents/skills/design/impeccable/scripts/lib/provider.mjs +5 -0
  80. package/template/.agents/skills/design/impeccable/scripts/lib/roll-selection.mjs +362 -0
  81. package/template/.agents/skills/design/impeccable/scripts/lib/staleness-deep.mjs +457 -0
  82. package/template/.agents/skills/design/impeccable/scripts/lib/staleness-notice.mjs +169 -0
  83. package/template/.agents/skills/design/impeccable/scripts/lib/staleness.mjs +457 -0
  84. package/template/.agents/skills/design/impeccable/scripts/lib/surface-briefs.mjs +151 -0
  85. package/template/.agents/skills/design/impeccable/scripts/lib/target-slug.mjs +33 -0
  86. package/template/.agents/skills/design/impeccable/scripts/lib/template-extensions.mjs +146 -0
  87. package/template/.agents/skills/design/impeccable/scripts/live/accept-css.mjs +617 -0
  88. package/template/.agents/skills/design/impeccable/scripts/live/accept-verify.mjs +60 -0
  89. package/template/.agents/skills/design/impeccable/scripts/live/browser-script-parts.mjs +7 -1
  90. package/template/.agents/skills/design/impeccable/scripts/live/completion.mjs +10 -1
  91. package/template/.agents/skills/design/impeccable/scripts/live/event-validation.mjs +67 -5
  92. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/astro.mjs +47 -0
  93. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/detect-utils.mjs +73 -0
  94. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/index.mjs +143 -0
  95. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/journal.mjs +197 -0
  96. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nextjs.mjs +49 -0
  97. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/nuxt.mjs +161 -0
  98. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/script-src.mjs +17 -0
  99. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/static-html.mjs +26 -0
  100. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/sveltekit.mjs +71 -0
  101. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tag-strategy.mjs +247 -0
  102. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/tanstack-start.mjs +70 -0
  103. package/template/.agents/skills/design/impeccable/scripts/live/frameworks/vite-generic.mjs +42 -0
  104. package/template/.agents/skills/design/impeccable/scripts/live/generation-preflight.mjs +149 -0
  105. package/template/.agents/skills/design/impeccable/scripts/live/instructions.mjs +142 -0
  106. package/template/.agents/skills/design/impeccable/scripts/live/poll-lanes.mjs +14 -0
  107. package/template/.agents/skills/design/impeccable/scripts/live/roots.mjs +508 -0
  108. package/template/.agents/skills/design/impeccable/scripts/live/session-store.mjs +324 -50
  109. package/template/.agents/skills/design/impeccable/scripts/live/source-lock.mjs +105 -0
  110. package/template/.agents/skills/design/impeccable/scripts/live/source-search.mjs +105 -0
  111. package/template/.agents/skills/design/impeccable/scripts/live/svelte-ast.mjs +961 -0
  112. package/template/.agents/skills/design/impeccable/scripts/live/svelte-component.mjs +588 -72
  113. package/template/.agents/skills/design/impeccable/scripts/live/sveltekit-adapter.mjs +59 -17
  114. package/template/.agents/skills/design/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
  115. package/template/.agents/skills/design/impeccable/scripts/live/vocabulary.mjs +135 -0
  116. package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +210 -68
  117. package/template/.agents/skills/design/impeccable/scripts/live-browser.js +1562 -223
  118. package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +3 -0
  119. package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +33 -1
  120. package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +175 -255
  121. package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +26 -6
  122. package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +6 -1
  123. package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +61 -16
  124. package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +39 -10
  125. package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +573 -47
  126. package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +17 -7
  127. package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +124 -91
  128. package/template/.agents/skills/design/impeccable/scripts/live.mjs +88 -26
  129. package/template/.agents/skills/design/impeccable/scripts/palette.mjs +76 -81
  130. package/template/.agents/skills/design/impeccable/scripts/pin.mjs +18 -11
  131. package/template/.agents/skills/design/impeccable/scripts/serve-question.mjs +932 -0
  132. package/template/.agents/skills/design/impeccable/scripts/surface-brief.mjs +74 -0
  133. package/template/.agents/skills/design/shadcn/SKILL.md +46 -11
  134. package/template/.agents/skills/design/shadcn/cli.md +49 -16
  135. package/template/.agents/skills/design/shadcn/customization.md +14 -7
  136. package/template/.agents/skills/design/shadcn/evals/evals.json +30 -0
  137. package/template/.agents/skills/design/shadcn/mcp.md +27 -16
  138. package/template/.agents/skills/design/shadcn/registry.md +277 -0
  139. package/template/.agents/skills/design/shadcn/rules/chat.md +224 -0
  140. package/template/.agents/skills/design/shadcn/rules/composition.md +20 -2
  141. package/template/.agents/skills/design/shadcn/rules/styling.md +23 -0
  142. package/template/.agents/skills/find-skills/SKILL.md +2 -3
  143. package/template/.agents/skills/hono/SKILL.md +579 -0
  144. package/template/.agents/skills/integrations/langfuse/SKILL.md +10 -6
  145. package/template/.agents/skills/integrations/langfuse/references/ci-cd.md +41 -0
  146. package/template/.agents/skills/integrations/langfuse/references/cli.md +8 -0
  147. package/template/.agents/skills/integrations/langfuse/references/error-analysis.md +15 -27
  148. package/template/.agents/skills/integrations/langfuse/references/instrumentation.md +39 -52
  149. package/template/.agents/skills/integrations/langfuse/references/judge-calibration.md +5 -2
  150. package/template/.agents/skills/integrations/langfuse/references/prompt-engineering.md +35 -0
  151. package/template/.agents/skills/integrations/langfuse/references/prompt-migration.md +41 -196
  152. package/template/.agents/skills/integrations/langfuse/references/skill-feedback.md +3 -0
  153. package/template/.agents/skills/integrations/langfuse/references/trace-evaluator-upgrade.md +76 -0
  154. package/template/.agents/skills/integrations/langfuse/references/user-feedback.md +4 -0
  155. package/template/.agents/skills/integrations/langfuse/references/v4-project-migration.md +73 -0
  156. package/template/.agents/skills/supabase/CHANGELOG.md +71 -0
  157. package/template/.agents/skills/supabase/SKILL.md +145 -0
  158. package/template/.agents/skills/supabase/assets/feedback-issue-template.md +17 -0
  159. package/template/.agents/skills/supabase/references/skill-feedback.md +17 -0
  160. package/template/.agents/skills/supabase-postgres-best-practices/CHANGELOG.md +73 -0
  161. package/template/.agents/skills/supabase-postgres-best-practices/SKILL.md +64 -0
  162. package/template/.agents/skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
  163. package/template/.agents/skills/supabase-postgres-best-practices/references/_sections.md +39 -0
  164. package/template/.agents/skills/supabase-postgres-best-practices/references/_template.md +34 -0
  165. package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
  166. package/template/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
  167. package/template/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
  168. package/template/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
  169. package/template/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
  170. package/template/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
  171. package/template/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
  172. package/template/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
  173. package/template/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
  174. package/template/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
  175. package/template/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
  176. package/template/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
  177. package/template/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
  178. package/template/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
  179. package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
  180. package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
  181. package/template/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
  182. package/template/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
  183. package/template/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
  184. package/template/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
  185. package/template/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
  186. package/template/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
  187. package/template/.agents/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
  188. package/template/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
  189. package/template/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
  190. package/template/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
  191. package/template/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
  192. package/template/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
  193. package/template/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
  194. package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
  195. package/template/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
  196. package/template/.agents/upstreams.json +34 -12
  197. package/template/.agents/skills/design/impeccable/reference/brand.md +0 -108
  198. package/template/.agents/skills/design/impeccable/reference/codex.md +0 -105
  199. package/template/.agents/skills/design/impeccable/reference/interaction-design.md +0 -189
  200. package/template/.agents/skills/integrations/langfuse/references/sdk-upgrade.md +0 -175
@@ -21,24 +21,17 @@ const ANTIPATTERNS = [
21
21
  {
22
22
  id: 'overused-font',
23
23
  category: 'slop',
24
+ scopes: ['type'],
24
25
  name: 'Overused font',
25
26
  description:
26
27
  'Inter, Roboto, Fraunces, Geist, Plus Jakarta Sans, and Space Grotesk are used on so many sites they no longer feel distinctive. Each new wave of AI-generated UIs converges on the same handful of faces. Choose a face that gives your interface personality.',
27
28
  skillSection: 'Typography',
28
29
  skillGuideline: 'overused fonts like Inter',
29
30
  },
30
- {
31
- id: 'single-font',
32
- category: 'slop',
33
- name: 'Single font for everything',
34
- description:
35
- 'Only one font family is used for the entire page. Pair a distinctive display font with a refined body font to create typographic hierarchy.',
36
- skillSection: 'Typography',
37
- skillGuideline: 'only one font family for the entire page',
38
- },
39
31
  {
40
32
  id: 'flat-type-hierarchy',
41
33
  category: 'slop',
34
+ scopes: ['type'],
42
35
  name: 'Flat type hierarchy',
43
36
  description:
44
37
  'Font sizes are too close together — no clear visual hierarchy. Use fewer sizes with more contrast (aim for at least a 1.25 ratio between steps).',
@@ -75,6 +68,7 @@ const ANTIPATTERNS = [
75
68
  {
76
69
  id: 'nested-cards',
77
70
  category: 'slop',
71
+ scopes: ['layout'],
78
72
  name: 'Nested cards',
79
73
  description:
80
74
  'Cards inside cards create visual noise and excessive depth. Flatten the hierarchy — use spacing, typography, and dividers instead of nesting containers.',
@@ -84,6 +78,7 @@ const ANTIPATTERNS = [
84
78
  {
85
79
  id: 'monotonous-spacing',
86
80
  category: 'slop',
81
+ scopes: ['layout'],
87
82
  name: 'Monotonous spacing',
88
83
  description:
89
84
  'The same spacing value used everywhere — no rhythm, no variation. Use tight groupings for related items and generous separations between sections.',
@@ -99,18 +94,73 @@ const ANTIPATTERNS = [
99
94
  skillSection: 'Motion',
100
95
  skillGuideline: 'bounce or elastic easing',
101
96
  },
97
+ {
98
+ id: 'pulsing-dot',
99
+ category: 'slop',
100
+ name: 'Pulsing status dot',
101
+ description:
102
+ 'Small pulsing status dots simulate liveness decoratively. Reserve pulse animation for indicators tied to genuinely live, changing data; a static indicator with clear labeling is honest and calmer.',
103
+ skillSection: 'Motion',
104
+ skillGuideline: 'decorative pulsing status dot',
105
+ },
106
+ {
107
+ id: 'blinking-cursor',
108
+ category: 'slop',
109
+ severity: 'advisory',
110
+ name: 'Decorative blinking cursor',
111
+ description:
112
+ 'A blinking text cursor animated into a hero or landing section simulates typing where no input exists. It borrows the dev-tool aesthetic as decoration. Real editable fields draw their own caret; anywhere else, let the composition hold attention without a fake prompt.',
113
+ skillSection: 'Motion',
114
+ },
115
+ {
116
+ id: 'shape-assembled-illustration',
117
+ category: 'slop',
118
+ severity: 'advisory',
119
+ name: 'Shape-assembled illustration',
120
+ description:
121
+ 'A large inline SVG that builds a pictorial scene from a pile of primitive shapes reads as placeholder clip art, not illustration. Icons, logos, and data graphics are fine at their scale; a hero-sized visual deserves real artwork, a photograph, or a deliberately drawn graphic.',
122
+ skillSection: 'Imagery',
123
+ },
102
124
  {
103
125
  id: 'dark-glow',
104
126
  category: 'slop',
105
- name: 'Dark mode with glowing accents',
127
+ name: 'Glowing shadow accents',
128
+ description:
129
+ 'Colored glow shadows — a zero-offset chromatic halo (box- or text-shadow) on any background, or any colored blurred shadow on a dark background — are the default "cool" look of AI-generated UIs. Use neutral elevation shadows and subtle, purposeful lighting instead.',
130
+ skillSection: 'Color & Contrast',
131
+ skillGuideline: 'dark mode with glowing accents',
132
+ },
133
+ {
134
+ id: 'radial-halo',
135
+ category: 'slop',
136
+ name: 'Radial-gradient background halo',
137
+ description:
138
+ 'A chromatic radial-gradient wash — saturated at the center, fading to transparent — used as a decorative background glow on a dark page. Same tell as glowing shadows, drawn with a gradient instead of a shadow. Ground the surface with a solid or subtly shifted background instead.',
139
+ skillSection: 'Color & Contrast',
140
+ skillGuideline: 'dark mode with glowing accents',
141
+ },
142
+ {
143
+ id: 'radial-spotlight-glow',
144
+ category: 'slop',
145
+ name: 'Decorative radial spotlight glow',
106
146
  description:
107
- 'Dark backgrounds with colored box-shadow glows are the default "cool" look of AI-generated UIs. Use subtle, purposeful lighting instead or skip the dark theme entirely.',
147
+ 'A soft, low-opacity accent-colored radial gradient fading to transparent, dropped behind a hero or section as a "spotlight." It is a reflex AI decoration — the translucent cousin of the saturated radial halo. Let the surface stand on its own, or light the composition with a deliberate material accent rather than a floating colored haze.',
108
148
  skillSection: 'Color & Contrast',
109
149
  skillGuideline: 'dark mode with glowing accents',
110
150
  },
151
+ {
152
+ id: 'marquee',
153
+ category: 'slop',
154
+ name: 'Auto-scrolling marquee',
155
+ description:
156
+ 'Continuously auto-scrolling content demands attention it has not earned and hides half its content at any moment. Reserve motion for content that changes; let readers move at their own pace.',
157
+ skillSection: 'Motion',
158
+ skillGuideline: 'auto-scrolling marquee',
159
+ },
111
160
  {
112
161
  id: 'icon-tile-stack',
113
162
  category: 'slop',
163
+ scopes: ['layout'],
114
164
  name: 'Icon tile stacked above heading',
115
165
  description:
116
166
  'A small rounded-square icon container above a heading is the universal AI feature-card template — every generator outputs this exact shape. Try a side-by-side icon and heading, or let the icon sit in flow without its own container.',
@@ -120,6 +170,7 @@ const ANTIPATTERNS = [
120
170
  {
121
171
  id: 'italic-serif-display',
122
172
  category: 'slop',
173
+ scopes: ['type'],
123
174
  name: 'Italic serif display headline',
124
175
  description:
125
176
  'Oversized italic serif (Fraunces, Recoleta, Playfair, Newsreader-italic) as the primary hero headline reads as taste in isolation but has become the universal AI-startup landing page hero. Set roman, or move to a non-serif display face. Editorial / magazine register may legitimately want this — judge by context.',
@@ -129,6 +180,7 @@ const ANTIPATTERNS = [
129
180
  {
130
181
  id: 'hero-eyebrow-chip',
131
182
  category: 'slop',
183
+ scopes: ['type'],
132
184
  name: 'Hero eyebrow / pill chip',
133
185
  description:
134
186
  'A tiny uppercase letter-spaced label sitting immediately above an oversized hero headline — or the same shape rendered as a pill chip — is now the default AI SaaS hero. Drop the eyebrow, integrate the kicker into the headline, or run it as a navigation breadcrumb instead.',
@@ -136,31 +188,37 @@ const ANTIPATTERNS = [
136
188
  skillGuideline: 'tiny uppercase tracked label above the hero headline',
137
189
  },
138
190
  {
139
- id: 'repeated-section-kickers',
191
+ id: 'kicker-above-heading',
140
192
  category: 'slop',
141
- severity: 'advisory',
142
- name: 'Repeated section kicker labels',
193
+ scopes: ['type'],
194
+ name: 'Kicker / eyebrow label above heading',
143
195
  description:
144
- 'Repeating tiny uppercase tracked labels above section headings turns a brand page into AI editorial scaffolding. Replace them with stronger structure, artifacts, imagery, or a deliberate brand system.',
196
+ 'A tiny tracked uppercase or small-caps label sitting as its own block directly above a heading is banned outright, repeated or not. Generated kickers never earn their place: the heading carries its own weight. Delete the label and let the heading speak; if the words matter, work them into the heading or the body.',
145
197
  skillSection: 'Typography',
146
- skillGuideline: 'repeated eyebrow or kicker labels as section scaffolding',
198
+ skillGuideline: 'kicker or eyebrow labels above headings',
147
199
  },
148
200
  {
149
- id: 'numbered-section-markers',
201
+ id: 'numbered-section-labels',
150
202
  category: 'slop',
203
+ scopes: ['type'],
151
204
  severity: 'advisory',
152
- name: 'Numbered section markers (01 / 02 / 03)',
205
+ name: 'Tiny numbered section labels',
153
206
  description:
154
- 'Numbered display markers as section labels (01, 02, 03) are the AI editorial scaffold one tier deeper than tracked eyebrow chips. If you find yourself reaching for them, choose a different section cadence.',
207
+ 'Small numeric index labels riding next to section headings, repeated section after section, are AI editorial scaffolding a page numbering its own chapters instead of earning structure. Let hierarchy, content, and rhythm carry the sequence.',
155
208
  skillSection: 'Layout & Space',
156
209
  skillGuideline: 'numbered section markers',
157
210
  },
158
211
  {
159
212
  id: 'em-dash-overuse',
160
213
  category: 'slop',
214
+ // Advisory: humans use em-dashes legitimately, so this rule is opt-in noise
215
+ // rather than a failure. It fires only on the AI saturation pattern, not on
216
+ // ordinary prose. Advisory findings are surfaced separately, never counted
217
+ // as failures, and skipped by the design hook unless a project opts in.
218
+ advisory: true,
161
219
  name: 'Em-dash overuse',
162
220
  description:
163
- 'More than two em-dashes (— or --) in body copy is an AI cadence tell. Use commas, colons, periods, or parentheses instead.',
221
+ 'Em-dash saturation in body copy is an AI cadence tell. Advisory only: humans use em-dashes legitimately, so this fires only on saturation — at least 8 em-dashes (— or --) at a density near one per 500 characters of body text never on a long article that uses a few. Prefer commas, colons, periods, or parentheses.',
164
222
  skillSection: 'Copy',
165
223
  skillGuideline: 'no em dashes',
166
224
  },
@@ -185,6 +243,7 @@ const ANTIPATTERNS = [
185
243
  {
186
244
  id: 'oversized-h1',
187
245
  category: 'slop',
246
+ scopes: ['type'],
188
247
  name: 'Oversized hero headline',
189
248
  description:
190
249
  'A full-sentence headline set at display size ends up dominating the viewport, leaving no room for anything else above the fold. A punchy one- or two-word headline at that size is fine — the problem is a long headline blown up too large. Set long headlines smaller, or tighten the copy.',
@@ -194,6 +253,7 @@ const ANTIPATTERNS = [
194
253
  {
195
254
  id: 'extreme-negative-tracking',
196
255
  category: 'slop',
256
+ scopes: ['type'],
197
257
  name: 'Crushed letter spacing',
198
258
  description:
199
259
  'Letter-spacing pulled tighter than the point where characters keep their own shapes costs legibility. Tighten display type optically, not destructively.',
@@ -211,6 +271,49 @@ const ANTIPATTERNS = [
211
271
  },
212
272
 
213
273
  // ── Quality: general design and accessibility issues ──
274
+ {
275
+ id: 'script-error',
276
+ category: 'quality',
277
+ severity: 'error',
278
+ name: 'Uncaught script error on load',
279
+ description:
280
+ 'A script threw an uncaught exception or failed to parse while the page loaded. Broken JavaScript silently kills reveals, interactions, and dynamic content, and can leave most of a page invisible. Fix the error before judging anything else.',
281
+ },
282
+ {
283
+ id: 'content-hidden-at-rest',
284
+ category: 'quality',
285
+ severity: 'error',
286
+ scopes: ['layout'],
287
+ name: 'Content invisible at rest',
288
+ description:
289
+ 'A large share of the page text sits at opacity 0 or visibility hidden even after every reveal handler had a chance to run. This is the failed-reveal signature: the content shipped but never becomes visible. Make content visible by default and let JavaScript enhance its entrance instead of gating its existence.',
290
+ },
291
+ {
292
+ id: 'edge-flush-cards',
293
+ category: 'quality',
294
+ scopes: ['layout'],
295
+ name: 'Cards flush against the scroller edge',
296
+ description:
297
+ 'Cards inside a horizontal scroller or tab panel sit flush against the container edge at rest while keeping a gutter on the other side, so their edges and rounded corners get cut off. Usually the panel is sized wider than its clip box. Keep a consistent inset on both sides.',
298
+ },
299
+ {
300
+ id: 'text-occlusion',
301
+ category: 'quality',
302
+ scopes: ['layout'],
303
+ name: 'Text occluded by an overlapping element',
304
+ description:
305
+ 'Text is painted under an opaque element or a second text run, so part of it cannot be read. A decorative box, a stacked layer, or an inline element with leaked padding lands on the words instead of beside them. Give overlapping layers room, or move the text out from under the layer above it.',
306
+ skillSection: 'Layout & Space',
307
+ },
308
+ {
309
+ id: 'first-viewport-column-overflow',
310
+ category: 'quality',
311
+ scopes: ['layout'],
312
+ name: 'One column stretches the first viewport',
313
+ description:
314
+ 'A multi-column opening section lets one column run far past the fold while its sibling fits in a single viewport, so the short column floats in dead space and the fold falls deep inside one section. Balance the columns, cap the tall one, or let the long content flow below the opening row.',
315
+ skillSection: 'Layout & Space',
316
+ },
214
317
  {
215
318
  id: 'gray-on-color',
216
319
  category: 'quality',
@@ -239,6 +342,7 @@ const ANTIPATTERNS = [
239
342
  {
240
343
  id: 'line-length',
241
344
  category: 'quality',
345
+ scopes: ['type', 'layout'],
242
346
  name: 'Line length too long',
243
347
  description:
244
348
  'Text lines wider than ~80 characters are hard to read. The eye loses its place tracking back to the start of the next line. Add a max-width (65ch to 75ch) to text containers.',
@@ -248,6 +352,7 @@ const ANTIPATTERNS = [
248
352
  {
249
353
  id: 'cramped-padding',
250
354
  category: 'quality',
355
+ scopes: ['layout'],
251
356
  name: 'Cramped padding',
252
357
  description:
253
358
  'Text is too close to the edge of its container. Two shapes: (1) an element with its own text where the padding is too low for the font size, and (2) a wrapper with text-bearing children and near-zero padding against a visible boundary (border, outline, or non-transparent background) — children land flush against the boundary line. Add at least 8px (ideally 12–16px) of padding inside bordered, outlined, or colored containers.',
@@ -257,6 +362,7 @@ const ANTIPATTERNS = [
257
362
  {
258
363
  id: 'body-text-viewport-edge',
259
364
  category: 'quality',
365
+ scopes: ['layout'],
260
366
  name: 'Body text touching viewport edge',
261
367
  description:
262
368
  'Body paragraphs render flush against the left or right viewport edge with no container providing horizontal padding. Wrap content in a container with at least 16px (ideally 24-32px) of horizontal padding, or apply max-width with mx-auto.',
@@ -264,6 +370,7 @@ const ANTIPATTERNS = [
264
370
  {
265
371
  id: 'tight-leading',
266
372
  category: 'quality',
373
+ scopes: ['type'],
267
374
  name: 'Tight line height',
268
375
  description:
269
376
  'Line height below 1.3x the font size makes multi-line text hard to read. Use 1.5 to 1.7 for body text so lines have room to breathe.',
@@ -271,13 +378,24 @@ const ANTIPATTERNS = [
271
378
  {
272
379
  id: 'skipped-heading',
273
380
  category: 'quality',
381
+ scopes: ['type'],
274
382
  name: 'Skipped heading level',
275
383
  description:
276
384
  'Heading levels should not skip (e.g. h1 then h3 with no h2). Screen readers use heading hierarchy for navigation. Skipping levels breaks the document outline.',
277
385
  },
386
+ {
387
+ id: 'heading-rhythm',
388
+ category: 'quality',
389
+ scopes: ['layout', 'type'],
390
+ name: 'Heading crowded against the previous block',
391
+ description:
392
+ 'A heading binds to the content it introduces, so the rendered space above it should exceed the space below it. When headings across a page sit as close or closer to the block above than to their own content, every section reads as if it captions the previous one. Open up the space above each heading.',
393
+ skillSection: 'Layout & Space',
394
+ },
278
395
  {
279
396
  id: 'justified-text',
280
397
  category: 'quality',
398
+ scopes: ['type'],
281
399
  name: 'Justified text',
282
400
  description:
283
401
  'Justified text without hyphenation creates uneven word spacing ("rivers of white"). Use text-align: left for body text, or enable hyphens: auto if you must justify.',
@@ -285,13 +403,23 @@ const ANTIPATTERNS = [
285
403
  {
286
404
  id: 'tiny-text',
287
405
  category: 'quality',
406
+ scopes: ['type'],
288
407
  name: 'Tiny body text',
289
408
  description:
290
409
  'Body text below 12px is hard to read, especially on high-DPI screens. Use at least 14px for body content, 16px is ideal.',
291
410
  },
411
+ {
412
+ id: 'undersized-ui-text',
413
+ category: 'quality',
414
+ scopes: ['type'],
415
+ name: 'Undersized functional text',
416
+ description:
417
+ 'Interactive and content-bearing UI text (links, buttons, nav items, labels, table cells, meta rows, timecodes) below 11px is a legibility failure, not a style choice. WCAG sets no absolute pixel floor, but functional text under 11px is a defensible quality bar: it fails on high-DPI and small viewports and it degrades tap and read targets. The 11px floor holds even inside a footer; only non-interactive legal smallprint gets the softer 10px floor. Being ON the DESIGN.md size ramp does not exempt a value here: adding 8px to the ramp launders the token but not the legibility problem, and that is exactly the escape hatch this rule closes. Exempts sup/sub, visually-hidden (sr-only) text, and code/terminal contexts. Decorative letterspaced micro-labels are still functional and stay in scope.',
418
+ },
292
419
  {
293
420
  id: 'all-caps-body',
294
421
  category: 'quality',
422
+ scopes: ['type'],
295
423
  name: 'All-caps body text',
296
424
  description:
297
425
  'Long passages in uppercase are hard to read. We recognize words by shape (ascenders and descenders), which all-caps removes. Reserve uppercase for short labels and headings.',
@@ -301,6 +429,7 @@ const ANTIPATTERNS = [
301
429
  {
302
430
  id: 'wide-tracking',
303
431
  category: 'quality',
432
+ scopes: ['type'],
304
433
  name: 'Wide letter spacing on body text',
305
434
  description:
306
435
  'Letter spacing above 0.05em on body text disrupts natural character groupings and slows reading. Reserve wide tracking for short uppercase labels only.',
@@ -308,15 +437,24 @@ const ANTIPATTERNS = [
308
437
  {
309
438
  id: 'text-overflow',
310
439
  category: 'quality',
440
+ scopes: ['layout'],
311
441
  name: 'Content overflowing its container',
312
442
  description:
313
443
  'Content renders wider than its container, spilling out or forcing a horizontal scrollbar. Let text wrap, constrain widths, or give the region a deliberate scroll affordance.',
314
444
  skillSection: 'Layout & Space',
315
445
  skillGuideline: 'content wider than its container',
316
446
  },
447
+ {
448
+ id: 'repeated-container-text',
449
+ category: 'quality',
450
+ name: 'Same text repeated inside one container',
451
+ description:
452
+ 'The same literal text rendered three or more times in structurally different spots inside a single card or panel is redundant messaging — usually a status or label wired into every slot of a template. Say it once, in the slot where it matters most.',
453
+ },
317
454
  {
318
455
  id: 'clipped-overflow-container',
319
456
  category: 'quality',
457
+ scopes: ['layout'],
320
458
  name: 'Positioned child clipped by overflow container',
321
459
  description:
322
460
  'A clipping container (overflow hidden or clip) wrapping an absolutely-positioned child cuts off tooltips, menus, and popovers that need to escape. Let the overflow be visible, or move the positioned layer out of the clip.',
@@ -326,6 +464,7 @@ const ANTIPATTERNS = [
326
464
  {
327
465
  id: 'design-system-font',
328
466
  category: 'quality',
467
+ scopes: ['type'],
329
468
  name: 'Font outside DESIGN.md',
330
469
  description:
331
470
  'A font is used that is not declared in DESIGN.md typography. Use the documented type system or update DESIGN.md if this is an intentional brand addition.',
@@ -352,13 +491,23 @@ const ANTIPATTERNS = [
352
491
  skillSection: 'Visual Details',
353
492
  skillGuideline: 'border radius outside the project design system',
354
493
  },
494
+ {
495
+ id: 'design-system-font-size',
496
+ category: 'quality',
497
+ severity: 'advisory',
498
+ scopes: ['type'],
499
+ name: 'Font size outside DESIGN.md',
500
+ description:
501
+ 'A literal font-size is off the type ramp documented in DESIGN.md typography. Use a documented size step or update the design system if the new step is intentional.',
502
+ skillSection: 'Typography',
503
+ skillGuideline: 'font size outside the project design system',
504
+ },
355
505
 
356
- // ── Provider tells: opt-in via --gpt / --gemini (gated off by default) ──
506
+ // ── Common generated-UI tells ───────────────────────────────────────────
357
507
  {
358
508
  id: 'gpt-thin-border-wide-shadow',
359
509
  category: 'slop',
360
510
  severity: 'advisory',
361
- gated: 'gpt',
362
511
  name: 'Hairline border with wide shadow',
363
512
  description:
364
513
  'A hairline border paired with a wide, diffuse shadow is a recurring generated-UI signature. Commit to one — a defined edge or a soft elevation — rather than both at once.',
@@ -369,18 +518,26 @@ const ANTIPATTERNS = [
369
518
  id: 'repeating-stripes-gradient',
370
519
  category: 'slop',
371
520
  severity: 'advisory',
372
- gated: 'gpt',
373
521
  name: 'Repeating-gradient stripes',
374
522
  description:
375
523
  'Repeating-gradient stripes used as surface decoration are a recurring generated-UI signature. Reach for a deliberate texture or leave the surface plain.',
376
524
  skillSection: 'Visual Details',
377
525
  skillGuideline: 'repeating-gradient decorative stripes',
378
526
  },
527
+ {
528
+ id: 'codex-grid-background',
529
+ category: 'slop',
530
+ severity: 'advisory',
531
+ name: 'Decorative grid-line background',
532
+ description:
533
+ 'A decorative grid or line-field background drawn with hairline linear-gradient layers tiled by a fixed pixel cell is a recurring generated-UI signature. Reserve grid overlays for actual canvas, map, blueprint, or measurement surfaces; elsewhere use product structure or a plain surface.',
534
+ skillSection: 'Visual Details',
535
+ skillGuideline: 'two-axis grid-line gradient background',
536
+ },
379
537
  {
380
538
  id: 'theater-slop-phrase',
381
539
  category: 'slop',
382
540
  severity: 'advisory',
383
- gated: 'gpt',
384
541
  name: 'Theater framing copy',
385
542
  description:
386
543
  'Dismissing something as "theater" is a recurring generated-copy tic. Say plainly what the thing does or does not do.',
@@ -391,7 +548,6 @@ const ANTIPATTERNS = [
391
548
  id: 'image-hover-transform',
392
549
  category: 'slop',
393
550
  severity: 'advisory',
394
- gated: 'gemini',
395
551
  name: 'Image hover transform',
396
552
  description:
397
553
  'Scaling or rotating an image on hover is a recurring generated-UI signature. Let imagery sit still, or use a subtler, purposeful interaction.',
@@ -411,6 +567,18 @@ function getAntipattern(id) {
411
567
  return ANTIPATTERNS.find(rule => rule.id === id);
412
568
  }
413
569
 
570
+ // Advisory rules are detected and reported, but never treated as failures:
571
+ // the CLI lists them under a separate "Advisory" section, they do not affect
572
+ // exit codes or the failure count, and the design hook skips them by default.
573
+ // The set is derived from the registry so a rule only needs `advisory: true`.
574
+ const ADVISORY_RULE_IDS = new Set(
575
+ ANTIPATTERNS.filter(rule => rule.advisory === true).map(rule => rule.id),
576
+ );
577
+
578
+ function isAdvisoryRule(id) {
579
+ return ADVISORY_RULE_IDS.has(id);
580
+ }
581
+
414
582
  function getRulesForCategory(category) {
415
583
  return ANTIPATTERNS.filter(rule => rule.category === category);
416
584
  }
@@ -419,30 +587,31 @@ function getRuleEngineSupport(engine) {
419
587
  return RULE_ENGINE_SUPPORT[engine] || new Set();
420
588
  }
421
589
 
422
- // Set of provider tags that gate rules off by default (e.g. 'gpt', 'gemini').
423
- const GATED_PROVIDERS = new Set(
424
- ANTIPATTERNS.map(rule => rule.gated).filter(Boolean),
590
+ // Set of scope tags rules can declare (e.g. 'type', 'layout'). Used by the
591
+ // CLI --scope flag to narrow output to one design domain.
592
+ const RULE_SCOPES = new Set(
593
+ ANTIPATTERNS.flatMap(rule => rule.scopes || []),
425
594
  );
426
595
 
427
- // Drop findings for rules gated behind a provider tag unless that provider
428
- // was explicitly enabled (CLI --gpt / --gemini). Non-gated findings always
429
- // pass through. `findings` carry the rule id on `.antipattern`.
430
- function filterByProviders(findings, providers = []) {
431
- const enabled = new Set(providers || []);
432
- if (!GATED_PROVIDERS.size) return findings;
596
+ // Keep only findings whose rule declares at least one of the requested
597
+ // scopes. An empty scope list means no filtering (default CLI behavior).
598
+ function filterByScopes(findings, scopes = []) {
599
+ if (!scopes || scopes.length === 0) return findings;
600
+ const enabled = new Set(scopes);
433
601
  return findings.filter(f => {
434
602
  const rule = getAntipattern(f.antipattern);
435
- if (!rule || !rule.gated) return true;
436
- return enabled.has(rule.gated);
603
+ return (rule?.scopes || []).some(scope => enabled.has(scope));
437
604
  });
438
605
  }
439
606
 
440
607
  export {
441
608
  ANTIPATTERNS,
609
+ RULE_SCOPES,
442
610
  RULE_ENGINE_SUPPORT,
443
- GATED_PROVIDERS,
611
+ ADVISORY_RULE_IDS,
444
612
  getAntipattern,
445
613
  getRulesForCategory,
446
614
  getRuleEngineSupport,
447
- filterByProviders,
615
+ isAdvisoryRule,
616
+ filterByScopes,
448
617
  };