@nurix/etna 0.19.11 → 0.19.12

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 (486) hide show
  1. package/data/harness-index.json +1 -1
  2. package/data/harnesses/code/harness.json +1 -1
  3. package/data/harnesses/code/rules/frontend.md +5 -5
  4. package/data/harnesses/code/skills/design/SKILL.md +70 -50
  5. package/data/harnesses/code/skills/design/components/charts.md +76 -0
  6. package/data/harnesses/code/skills/design/components/collections.md +132 -0
  7. package/data/harnesses/code/skills/design/components/feedback.md +47 -0
  8. package/data/harnesses/code/skills/design/components/hooks.md +35 -0
  9. package/data/harnesses/code/skills/design/components/index.md +143 -0
  10. package/data/harnesses/code/skills/design/components/inputs.md +327 -0
  11. package/data/harnesses/code/skills/design/components/layout.md +52 -0
  12. package/data/harnesses/code/skills/design/components/media.md +66 -0
  13. package/data/harnesses/code/skills/design/components/motion.md +82 -0
  14. package/data/harnesses/code/skills/design/components/navigation.md +29 -0
  15. package/data/harnesses/code/skills/design/components/overlays.md +72 -0
  16. package/data/harnesses/code/skills/design/components/setup.md +40 -0
  17. package/data/harnesses/code/skills/design/components/typography.md +46 -0
  18. package/data/harnesses/code/skills/design/components/utils.md +37 -0
  19. package/data/harnesses/code/skills/design/data/blueprints/browse.md +38 -0
  20. package/data/harnesses/code/skills/design/data/blueprints/creation-flow.md +38 -0
  21. package/data/harnesses/code/skills/design/data/blueprints/dashboard.md +38 -0
  22. package/data/harnesses/code/skills/design/data/blueprints/grid.md +38 -0
  23. package/data/harnesses/code/skills/design/data/blueprints/queue.md +38 -0
  24. package/data/harnesses/code/skills/design/data/blueprints/record-detail.md +38 -0
  25. package/data/harnesses/code/skills/design/data/blueprints/settings.md +38 -0
  26. package/data/harnesses/code/skills/design/data/chart-styling/Readme.md +33 -0
  27. package/data/harnesses/code/skills/design/data/chart-styling/carbon-accessible-alert-semantic.md +19 -0
  28. package/data/harnesses/code/skills/design/data/chart-styling/carbon-monochrome-sequential-trend.md +19 -0
  29. package/data/harnesses/code/skills/design/data/chart-styling/datadog-classic-six-aligned.md +19 -0
  30. package/data/harnesses/code/skills/design/data/chart-styling/datawrapper-tiered-gray-hierarchy.md +19 -0
  31. package/data/harnesses/code/skills/design/data/chart-styling/econ-red-rule-horizontal.md +19 -0
  32. package/data/harnesses/code/skills/design/data/chart-styling/financial-diverging-threshold-overlay.md +19 -0
  33. package/data/harnesses/code/skills/design/data/chart-styling/ft-vocabulary-ranked-muted.md +19 -0
  34. package/data/harnesses/code/skills/design/data/chart-styling/grafana-dark-threshold-bands.md +19 -0
  35. package/data/harnesses/code/skills/design/data/chart-styling/material-rounded-explicit-label.md +19 -0
  36. package/data/harnesses/code/skills/design/data/chart-styling/nyt-ghost-grid-direct-label.md +19 -0
  37. package/data/harnesses/code/skills/design/data/chart-styling/plot-currentcolor-inherit.md +19 -0
  38. package/data/harnesses/code/skills/design/data/chart-styling/saas-gradient-glow-area.md +19 -0
  39. package/data/harnesses/code/skills/design/data/chart-styling/shadcn-composable-css-vars.md +19 -0
  40. package/data/harnesses/code/skills/design/data/charts/census.csv +58 -0
  41. package/data/harnesses/code/skills/design/data/checklists/browse.md +21 -0
  42. package/data/harnesses/code/skills/design/data/checklists/creation-flow.md +20 -0
  43. package/data/harnesses/code/skills/design/data/checklists/dashboard.md +21 -0
  44. package/data/harnesses/code/skills/design/data/checklists/grid.md +21 -0
  45. package/data/harnesses/code/skills/design/data/checklists/queue.md +21 -0
  46. package/data/harnesses/code/skills/design/data/checklists/record-detail.md +21 -0
  47. package/data/harnesses/code/skills/design/data/checklists/settings.md +21 -0
  48. package/data/harnesses/code/skills/design/data/chrome/board-column.md +68 -0
  49. package/data/harnesses/code/skills/design/data/chrome/data-table.md +63 -0
  50. package/data/harnesses/code/skills/design/data/chrome/side-panel.md +60 -0
  51. package/data/harnesses/code/skills/design/data/chrome/sidebar.md +78 -0
  52. package/data/harnesses/code/skills/design/data/chrome/stat-cards.md +62 -0
  53. package/data/harnesses/code/skills/design/data/chrome/topbar.md +65 -0
  54. package/data/harnesses/code/skills/design/data/color/accent-presets.md +90 -0
  55. package/data/harnesses/code/skills/design/data/color/aesop-earth-mute.md +91 -0
  56. package/data/harnesses/code/skills/design/data/color/arc-peach-play.md +90 -0
  57. package/data/harnesses/code/skills/design/data/color/attio-hunter-teal.md +90 -0
  58. package/data/harnesses/code/skills/design/data/color/carbon-cyan-signal.md +90 -0
  59. package/data/harnesses/code/skills/design/data/color/clay-parchment.md +90 -0
  60. package/data/harnesses/code/skills/design/data/color/duolingo-feather.md +90 -0
  61. package/data/harnesses/code/skills/design/data/color/geist-mono-signal.md +90 -0
  62. package/data/harnesses/code/skills/design/data/color/linear-graphite-violet.md +90 -0
  63. package/data/harnesses/code/skills/design/data/color/mercury-onyx-cobalt.md +90 -0
  64. package/data/harnesses/code/skills/design/data/color/notion-paper-ink.md +90 -0
  65. package/data/harnesses/code/skills/design/data/color/radix-slate-iris.md +90 -0
  66. package/data/harnesses/code/skills/design/data/color/raycast-void-spectrum.md +90 -0
  67. package/data/harnesses/code/skills/design/data/color/spectrum-celery-fuchsia.md +90 -0
  68. package/data/harnesses/code/skills/design/data/color/stripe-blurple-ruby.md +90 -0
  69. package/data/harnesses/code/skills/design/data/color/superhuman-cod-picton.md +89 -0
  70. package/data/harnesses/code/skills/design/data/corpora/operations-review/companies.csv +15 -0
  71. package/data/harnesses/code/skills/design/data/corpora/operations-review/corpus.md +87 -0
  72. package/data/harnesses/code/skills/design/data/corpora/operations-review/people.csv +25 -0
  73. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/companies.csv +15 -0
  74. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/corpus.md +83 -0
  75. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/people.csv +25 -0
  76. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/companies.csv +15 -0
  77. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/corpus.md +89 -0
  78. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/people.csv +25 -0
  79. package/data/harnesses/code/skills/design/data/elevation/ant-design-directional-shadow.md +19 -0
  80. package/data/harnesses/code/skills/design/data/elevation/apple-liquid-glass-material.md +18 -0
  81. package/data/harnesses/code/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +20 -0
  82. package/data/harnesses/code/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +20 -0
  83. package/data/harnesses/code/skills/design/data/elevation/github-primer-sparing-shadow.md +19 -0
  84. package/data/harnesses/code/skills/design/data/elevation/ibm-carbon-layer-and-border.md +19 -0
  85. package/data/harnesses/code/skills/design/data/elevation/linear-dark-surface-ladder.md +17 -0
  86. package/data/harnesses/code/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +19 -0
  87. package/data/harnesses/code/skills/design/data/elevation/material-3-tonal-elevation.md +21 -0
  88. package/data/harnesses/code/skills/design/data/elevation/neobrutalist-hard-offset.md +19 -0
  89. package/data/harnesses/code/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +18 -0
  90. package/data/harnesses/code/skills/design/data/elevation/notion-warm-minimal-hairline.md +17 -0
  91. package/data/harnesses/code/skills/design/data/elevation/polaris-elevation-inset-bevel.md +21 -0
  92. package/data/harnesses/code/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +19 -0
  93. package/data/harnesses/code/skills/design/data/elevation/shadcn-neutral-derived-radius.md +19 -0
  94. package/data/harnesses/code/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +18 -0
  95. package/data/harnesses/code/skills/design/data/elevation/tailwind-default-utility-scale.md +19 -0
  96. package/data/harnesses/code/skills/design/data/elevation/vercel-geist-shadow-as-border.md +20 -0
  97. package/data/harnesses/code/skills/design/data/gradients/amber-attention-fill.md +16 -0
  98. package/data/harnesses/code/skills/design/data/gradients/cloud-shadow-wash.md +16 -0
  99. package/data/harnesses/code/skills/design/data/gradients/confident-lavender-wash.md +16 -0
  100. package/data/harnesses/code/skills/design/data/gradients/ember-ship-flare.md +18 -0
  101. package/data/harnesses/code/skills/design/data/gradients/full-metal-wash.md +16 -0
  102. package/data/harnesses/code/skills/design/data/gradients/indigo-ruby-cta-band.md +18 -0
  103. package/data/harnesses/code/skills/design/data/gradients/linear-graphite-wash.md +18 -0
  104. package/data/harnesses/code/skills/design/data/gradients/marble-quartz-wash.md +16 -0
  105. package/data/harnesses/code/skills/design/data/gradients/midnight-aurora-panel.md +16 -0
  106. package/data/harnesses/code/skills/design/data/gradients/neutral-volume-fill.md +16 -0
  107. package/data/harnesses/code/skills/design/data/gradients/revenue-uptrend-fill.md +16 -0
  108. package/data/harnesses/code/skills/design/data/gradients/risk-decline-fill.md +16 -0
  109. package/data/harnesses/code/skills/design/data/gradients/signal-blue-develop.md +18 -0
  110. package/data/harnesses/code/skills/design/data/gradients/slate-mist-wash.md +16 -0
  111. package/data/harnesses/code/skills/design/data/gradients/stripe-atmosphere-mesh.md +18 -0
  112. package/data/harnesses/code/skills/design/data/gradients/teal-signal-accent.md +16 -0
  113. package/data/harnesses/code/skills/design/data/gradients/violet-magenta-promo.md +16 -0
  114. package/data/harnesses/code/skills/design/data/iconography.md +199 -0
  115. package/data/harnesses/code/skills/design/data/motion/accordion-expand.md +18 -0
  116. package/data/harnesses/code/skills/design/data/motion/destructive-hold-confirm.md +18 -0
  117. package/data/harnesses/code/skills/design/data/motion/drag-dismiss-momentum.md +18 -0
  118. package/data/harnesses/code/skills/design/data/motion/empty-state-arrive.md +18 -0
  119. package/data/harnesses/code/skills/design/data/motion/hover-lift.md +18 -0
  120. package/data/harnesses/code/skills/design/data/motion/modal-center-arrive.md +18 -0
  121. package/data/harnesses/code/skills/design/data/motion/number-ticker-roll.md +18 -0
  122. package/data/harnesses/code/skills/design/data/motion/onboarding-bounce.md +18 -0
  123. package/data/harnesses/code/skills/design/data/motion/panel-slide.md +18 -0
  124. package/data/harnesses/code/skills/design/data/motion/press-feedback.md +18 -0
  125. package/data/harnesses/code/skills/design/data/motion/progress-linear-loop.md +18 -0
  126. package/data/harnesses/code/skills/design/data/motion/route-crossfade.md +18 -0
  127. package/data/harnesses/code/skills/design/data/motion/rubber-band-overscroll.md +18 -0
  128. package/data/harnesses/code/skills/design/data/motion/skeleton-shimmer.md +18 -0
  129. package/data/harnesses/code/skills/design/data/motion/stagger-arrive.md +18 -0
  130. package/data/harnesses/code/skills/design/data/motion/toast-enter-stack.md +18 -0
  131. package/data/harnesses/code/skills/design/data/motion/tooltip-chain-instant.md +18 -0
  132. package/data/harnesses/code/skills/design/data/motion/trigger-anchored-reveal.md +18 -0
  133. package/data/harnesses/code/skills/design/data/tells.csv +34 -0
  134. package/data/harnesses/code/skills/design/data/typography/anton-work-sans.md +17 -0
  135. package/data/harnesses/code/skills/design/data/typography/archivo-black-archivo.md +17 -0
  136. package/data/harnesses/code/skills/design/data/typography/bitter-karla.md +17 -0
  137. package/data/harnesses/code/skills/design/data/typography/dm-serif-dm-sans.md +17 -0
  138. package/data/harnesses/code/skills/design/data/typography/fraunces-inter.md +17 -0
  139. package/data/harnesses/code/skills/design/data/typography/geist-geist-mono.md +17 -0
  140. package/data/harnesses/code/skills/design/data/typography/hubot-sans-mona-sans.md +17 -0
  141. package/data/harnesses/code/skills/design/data/typography/ibm-plex-sans-operator-single-family.md +17 -0
  142. package/data/harnesses/code/skills/design/data/typography/instrument-serif-instrument-sans.md +17 -0
  143. package/data/harnesses/code/skills/design/data/typography/inter-operator-single-family.md +17 -0
  144. package/data/harnesses/code/skills/design/data/typography/libre-baskerville-libre-franklin.md +17 -0
  145. package/data/harnesses/code/skills/design/data/typography/newsreader-inter.md +17 -0
  146. package/data/harnesses/code/skills/design/data/typography/playfair-display-source-sans.md +17 -0
  147. package/data/harnesses/code/skills/design/data/typography/public-sans-operator-single-family.md +17 -0
  148. package/data/harnesses/code/skills/design/data/typography/sohne-inter-fintech.md +17 -0
  149. package/data/harnesses/code/skills/design/data/typography/source-serif-source-sans.md +17 -0
  150. package/data/harnesses/code/skills/design/data/typography/space-grotesk-work-sans-space-mono.md +17 -0
  151. package/data/harnesses/code/skills/design/data/typography/spectral-manrope.md +17 -0
  152. package/data/harnesses/code/skills/design/data/voices/bright-collaborator.md +29 -0
  153. package/data/harnesses/code/skills/design/data/voices/direct-operator.md +29 -0
  154. package/data/harnesses/code/skills/design/data/voices/earnest-helper.md +29 -0
  155. package/data/harnesses/code/skills/design/data/voices/editorial-composed.md +29 -0
  156. package/data/harnesses/code/skills/design/data/voices/quiet-concierge.md +29 -0
  157. package/data/harnesses/code/skills/design/data/voices/warm-guide.md +29 -0
  158. package/data/harnesses/code/skills/design/design-md/SCHEMA.md +179 -0
  159. package/data/harnesses/code/skills/design/design-md/index.csv +67 -0
  160. package/data/harnesses/code/skills/design/design-md/library/airbnb.md +207 -0
  161. package/data/harnesses/code/skills/design/design-md/library/airtable.md +205 -0
  162. package/data/harnesses/code/skills/design/design-md/library/anthropic-claude.md +203 -0
  163. package/data/harnesses/code/skills/design/design-md/library/apple.md +206 -0
  164. package/data/harnesses/code/skills/design/design-md/library/binance.md +210 -0
  165. package/data/harnesses/code/skills/design/design-md/library/bmw.md +210 -0
  166. package/data/harnesses/code/skills/design/design-md/library/cal.md +209 -0
  167. package/data/harnesses/code/skills/design/design-md/library/clay.md +204 -0
  168. package/data/harnesses/code/skills/design/design-md/library/clickhouse.md +205 -0
  169. package/data/harnesses/code/skills/design/design-md/library/cohere.md +205 -0
  170. package/data/harnesses/code/skills/design/design-md/library/coinbase.md +198 -0
  171. package/data/harnesses/code/skills/design/design-md/library/composio.md +198 -0
  172. package/data/harnesses/code/skills/design/design-md/library/cursor.md +197 -0
  173. package/data/harnesses/code/skills/design/design-md/library/elevenlabs.md +199 -0
  174. package/data/harnesses/code/skills/design/design-md/library/expo.md +200 -0
  175. package/data/harnesses/code/skills/design/design-md/library/figma.md +199 -0
  176. package/data/harnesses/code/skills/design/design-md/library/framer.md +202 -0
  177. package/data/harnesses/code/skills/design/design-md/library/hashicorp.md +205 -0
  178. package/data/harnesses/code/skills/design/design-md/library/ibm.md +205 -0
  179. package/data/harnesses/code/skills/design/design-md/library/intercom.md +204 -0
  180. package/data/harnesses/code/skills/design/design-md/library/kraken.md +200 -0
  181. package/data/harnesses/code/skills/design/design-md/library/linear-app.md +198 -0
  182. package/data/harnesses/code/skills/design/design-md/library/lovable.md +199 -0
  183. package/data/harnesses/code/skills/design/design-md/library/meta.md +204 -0
  184. package/data/harnesses/code/skills/design/design-md/library/minimax.md +204 -0
  185. package/data/harnesses/code/skills/design/design-md/library/mintlify.md +210 -0
  186. package/data/harnesses/code/skills/design/design-md/library/miro.md +209 -0
  187. package/data/harnesses/code/skills/design/design-md/library/mistral-ai.md +201 -0
  188. package/data/harnesses/code/skills/design/design-md/library/mongodb.md +201 -0
  189. package/data/harnesses/code/skills/design/design-md/library/notion.md +204 -0
  190. package/data/harnesses/code/skills/design/design-md/library/nvidia.md +215 -0
  191. package/data/harnesses/code/skills/design/design-md/library/ollama.md +213 -0
  192. package/data/harnesses/code/skills/design/design-md/library/opencode-ai.md +216 -0
  193. package/data/harnesses/code/skills/design/design-md/library/posthog.md +218 -0
  194. package/data/harnesses/code/skills/design/design-md/library/raycast.md +214 -0
  195. package/data/harnesses/code/skills/design/design-md/library/replicate.md +202 -0
  196. package/data/harnesses/code/skills/design/design-md/library/resend.md +203 -0
  197. package/data/harnesses/code/skills/design/design-md/library/revolut.md +203 -0
  198. package/data/harnesses/code/skills/design/design-md/library/runwayml.md +203 -0
  199. package/data/harnesses/code/skills/design/design-md/library/sanity.md +200 -0
  200. package/data/harnesses/code/skills/design/design-md/library/sentry.md +201 -0
  201. package/data/harnesses/code/skills/design/design-md/library/shopify.md +202 -0
  202. package/data/harnesses/code/skills/design/design-md/library/slack.md +202 -0
  203. package/data/harnesses/code/skills/design/design-md/library/spacex.md +206 -0
  204. package/data/harnesses/code/skills/design/design-md/library/spotify.md +206 -0
  205. package/data/harnesses/code/skills/design/design-md/library/stripe.md +196 -0
  206. package/data/harnesses/code/skills/design/design-md/library/supabase.md +196 -0
  207. package/data/harnesses/code/skills/design/design-md/library/superhuman.md +194 -0
  208. package/data/harnesses/code/skills/design/design-md/library/tesla.md +198 -0
  209. package/data/harnesses/code/skills/design/design-md/library/theverge.md +199 -0
  210. package/data/harnesses/code/skills/design/design-md/library/together-ai.md +193 -0
  211. package/data/harnesses/code/skills/design/design-md/library/uber.md +195 -0
  212. package/data/harnesses/code/skills/design/design-md/library/vercel.md +195 -0
  213. package/data/harnesses/code/skills/design/design-md/library/voltagent.md +197 -0
  214. package/data/harnesses/code/skills/design/design-md/library/warp.md +196 -0
  215. package/data/harnesses/code/skills/design/design-md/library/webflow.md +197 -0
  216. package/data/harnesses/code/skills/design/design-md/library/wired.md +197 -0
  217. package/data/harnesses/code/skills/design/design-md/library/wise.md +198 -0
  218. package/data/harnesses/code/skills/design/design-md/library/x-ai.md +199 -0
  219. package/data/harnesses/code/skills/design/design-md/library/zapier.md +198 -0
  220. package/data/harnesses/code/skills/design/design-md/nurix.md +214 -0
  221. package/data/harnesses/code/skills/design/design-md/variants/editorial-luxury.md +184 -0
  222. package/data/harnesses/code/skills/design/design-md/variants/expressive-saas.md +216 -0
  223. package/data/harnesses/code/skills/design/design-md/variants/quiet-premium.md +211 -0
  224. package/data/harnesses/code/skills/design/design-md/variants/terse-dense-operator.md +212 -0
  225. package/data/harnesses/code/skills/design/design-md/variants/warm-approachable.md +216 -0
  226. package/data/harnesses/code/skills/design/references/compose.md +23 -0
  227. package/data/harnesses/code/skills/design/references/content.md +28 -0
  228. package/data/harnesses/code/skills/design/references/emission.md +21 -0
  229. package/data/harnesses/code/skills/design/references/existing-apps.md +27 -0
  230. package/data/harnesses/code/skills/design/references/intake.md +36 -0
  231. package/data/harnesses/code/skills/design/references/object-pass.md +24 -0
  232. package/data/harnesses/code/skills/design/references/ship-gate.md +29 -0
  233. package/data/harnesses/code/skills/design/references/ux-patterns/Readme.md +195 -0
  234. package/data/harnesses/code/skills/design/references/ux-patterns/ai-layer.md +49 -0
  235. package/data/harnesses/code/skills/design/references/ux-patterns/attributes-lifecycle.md +43 -0
  236. package/data/harnesses/code/skills/design/references/ux-patterns/container-choice.md +44 -0
  237. package/data/harnesses/code/skills/design/references/ux-patterns/creation-paths.md +46 -0
  238. package/data/harnesses/code/skills/design/references/ux-patterns/dashboards.md +42 -0
  239. package/data/harnesses/code/skills/design/references/ux-patterns/modes.md +42 -0
  240. package/data/harnesses/code/skills/design/references/ux-patterns/object-model.md +46 -0
  241. package/data/harnesses/code/skills/design/references/ux-patterns/page-archetype.md +48 -0
  242. package/data/harnesses/code/skills/design/references/ux-patterns/promotion-demotion.md +37 -0
  243. package/data/harnesses/code/skills/design/references/ux-patterns/settings.md +42 -0
  244. package/data/harnesses/code/skills/design/references/ux-patterns/standard-pages.md +46 -0
  245. package/data/harnesses/code/skills/design/references/ux-patterns/state-matrix.md +41 -0
  246. package/data/harnesses/code/skills/design/references/ux-patterns/table-mechanics.md +48 -0
  247. package/data/harnesses/code/skills/design/references/ux-patterns/verbs.md +45 -0
  248. package/data/harnesses/code/skills/design/references/ux-patterns/viewer-context.md +40 -0
  249. package/data/harnesses/code/skills/design/scripts/README-validator.md +27 -0
  250. package/data/harnesses/code/skills/design/scripts/select-chart.mjs +596 -0
  251. package/data/harnesses/code/skills/design/scripts/validate-design-md.mjs +1198 -0
  252. package/package.json +1 -1
  253. package/data/harnesses/code/skills/design/data/catalog/rules.csv +0 -137
  254. package/data/harnesses/code/skills/design/data/combinations/Readme.md +0 -33
  255. package/data/harnesses/code/skills/design/data/combinations/accent-presets.md +0 -113
  256. package/data/harnesses/code/skills/design/data/combinations/charts.csv +0 -33
  257. package/data/harnesses/code/skills/design/data/combinations/fonts-known.json +0 -448
  258. package/data/harnesses/code/skills/design/data/combinations/icons.csv +0 -157
  259. package/data/harnesses/code/skills/design/data/combinations/landing.csv +0 -38
  260. package/data/harnesses/code/skills/design/data/combinations/lucide-names.json +0 -2001
  261. package/data/harnesses/code/skills/design/data/combinations/manifest.json +0 -330
  262. package/data/harnesses/code/skills/design/data/combinations/motion.csv +0 -10
  263. package/data/harnesses/code/skills/design/data/combinations/palettes.csv +0 -92
  264. package/data/harnesses/code/skills/design/data/combinations/product-router.csv +0 -80
  265. package/data/harnesses/code/skills/design/data/combinations/styles.csv +0 -67
  266. package/data/harnesses/code/skills/design/data/combinations/typography.csv +0 -64
  267. package/data/harnesses/code/skills/design/data/design-md/SCHEMA.md +0 -106
  268. package/data/harnesses/code/skills/design/data/design-md/library/airbnb.md +0 -154
  269. package/data/harnesses/code/skills/design/data/design-md/library/airtable.md +0 -151
  270. package/data/harnesses/code/skills/design/data/design-md/library/anthropic-claude.md +0 -139
  271. package/data/harnesses/code/skills/design/data/design-md/library/apple.md +0 -139
  272. package/data/harnesses/code/skills/design/data/design-md/library/binance.md +0 -140
  273. package/data/harnesses/code/skills/design/data/design-md/library/bmw.md +0 -140
  274. package/data/harnesses/code/skills/design/data/design-md/library/cal.md +0 -140
  275. package/data/harnesses/code/skills/design/data/design-md/library/clay.md +0 -139
  276. package/data/harnesses/code/skills/design/data/design-md/library/clickhouse.md +0 -139
  277. package/data/harnesses/code/skills/design/data/design-md/library/cohere.md +0 -147
  278. package/data/harnesses/code/skills/design/data/design-md/library/coinbase.md +0 -156
  279. package/data/harnesses/code/skills/design/data/design-md/library/composio.md +0 -138
  280. package/data/harnesses/code/skills/design/data/design-md/library/cursor.md +0 -138
  281. package/data/harnesses/code/skills/design/data/design-md/library/elevenlabs.md +0 -137
  282. package/data/harnesses/code/skills/design/data/design-md/library/expo.md +0 -148
  283. package/data/harnesses/code/skills/design/data/design-md/library/figma.md +0 -141
  284. package/data/harnesses/code/skills/design/data/design-md/library/framer.md +0 -156
  285. package/data/harnesses/code/skills/design/data/design-md/library/hashicorp.md +0 -140
  286. package/data/harnesses/code/skills/design/data/design-md/library/ibm.md +0 -153
  287. package/data/harnesses/code/skills/design/data/design-md/library/intercom.md +0 -158
  288. package/data/harnesses/code/skills/design/data/design-md/library/kraken.md +0 -156
  289. package/data/harnesses/code/skills/design/data/design-md/library/linear-app.md +0 -122
  290. package/data/harnesses/code/skills/design/data/design-md/library/lovable.md +0 -140
  291. package/data/harnesses/code/skills/design/data/design-md/library/meta.md +0 -139
  292. package/data/harnesses/code/skills/design/data/design-md/library/minimax.md +0 -139
  293. package/data/harnesses/code/skills/design/data/design-md/library/mintlify.md +0 -139
  294. package/data/harnesses/code/skills/design/data/design-md/library/miro.md +0 -153
  295. package/data/harnesses/code/skills/design/data/design-md/library/mistral-ai.md +0 -140
  296. package/data/harnesses/code/skills/design/data/design-md/library/mongodb.md +0 -155
  297. package/data/harnesses/code/skills/design/data/design-md/library/notion.md +0 -140
  298. package/data/harnesses/code/skills/design/data/design-md/library/nvidia.md +0 -141
  299. package/data/harnesses/code/skills/design/data/design-md/library/ollama.md +0 -145
  300. package/data/harnesses/code/skills/design/data/design-md/library/opencode-ai.md +0 -142
  301. package/data/harnesses/code/skills/design/data/design-md/library/posthog.md +0 -152
  302. package/data/harnesses/code/skills/design/data/design-md/library/raycast.md +0 -137
  303. package/data/harnesses/code/skills/design/data/design-md/library/replicate.md +0 -140
  304. package/data/harnesses/code/skills/design/data/design-md/library/resend.md +0 -170
  305. package/data/harnesses/code/skills/design/data/design-md/library/revolut.md +0 -145
  306. package/data/harnesses/code/skills/design/data/design-md/library/runwayml.md +0 -137
  307. package/data/harnesses/code/skills/design/data/design-md/library/sanity.md +0 -168
  308. package/data/harnesses/code/skills/design/data/design-md/library/sentry.md +0 -163
  309. package/data/harnesses/code/skills/design/data/design-md/library/shopify.md +0 -147
  310. package/data/harnesses/code/skills/design/data/design-md/library/slack.md +0 -158
  311. package/data/harnesses/code/skills/design/data/design-md/library/spacex.md +0 -171
  312. package/data/harnesses/code/skills/design/data/design-md/library/spotify.md +0 -166
  313. package/data/harnesses/code/skills/design/data/design-md/library/stripe.md +0 -160
  314. package/data/harnesses/code/skills/design/data/design-md/library/supabase.md +0 -173
  315. package/data/harnesses/code/skills/design/data/design-md/library/superhuman.md +0 -145
  316. package/data/harnesses/code/skills/design/data/design-md/library/tesla.md +0 -153
  317. package/data/harnesses/code/skills/design/data/design-md/library/theverge.md +0 -167
  318. package/data/harnesses/code/skills/design/data/design-md/library/together-ai.md +0 -140
  319. package/data/harnesses/code/skills/design/data/design-md/library/uber.md +0 -140
  320. package/data/harnesses/code/skills/design/data/design-md/library/vercel.md +0 -140
  321. package/data/harnesses/code/skills/design/data/design-md/library/voltagent.md +0 -130
  322. package/data/harnesses/code/skills/design/data/design-md/library/warp.md +0 -140
  323. package/data/harnesses/code/skills/design/data/design-md/library/webflow.md +0 -140
  324. package/data/harnesses/code/skills/design/data/design-md/library/wired.md +0 -139
  325. package/data/harnesses/code/skills/design/data/design-md/library/wise.md +0 -137
  326. package/data/harnesses/code/skills/design/data/design-md/library/x-ai.md +0 -138
  327. package/data/harnesses/code/skills/design/data/design-md/library/zapier.md +0 -158
  328. package/data/harnesses/code/skills/design/data/design-md/nurix.md +0 -138
  329. package/data/harnesses/code/skills/design/data/design-tokens/SCHEMA.md +0 -695
  330. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.resolver.json +0 -20
  331. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.tokens.json +0 -1272
  332. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.resolver.json +0 -20
  333. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.tokens.json +0 -1268
  334. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.resolver.json +0 -20
  335. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.tokens.json +0 -1273
  336. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.resolver.json +0 -20
  337. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.tokens.json +0 -1262
  338. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.resolver.json +0 -20
  339. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.tokens.json +0 -1257
  340. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.resolver.json +0 -20
  341. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.tokens.json +0 -1270
  342. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.resolver.json +0 -20
  343. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.tokens.json +0 -1270
  344. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.resolver.json +0 -20
  345. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.tokens.json +0 -1261
  346. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.resolver.json +0 -20
  347. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.tokens.json +0 -1268
  348. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.resolver.json +0 -20
  349. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.tokens.json +0 -1281
  350. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.resolver.json +0 -20
  351. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.tokens.json +0 -1262
  352. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.resolver.json +0 -20
  353. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.tokens.json +0 -1271
  354. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.resolver.json +0 -20
  355. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.tokens.json +0 -1276
  356. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.resolver.json +0 -20
  357. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.tokens.json +0 -1293
  358. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.resolver.json +0 -20
  359. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.tokens.json +0 -1270
  360. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.resolver.json +0 -20
  361. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.tokens.json +0 -1276
  362. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.resolver.json +0 -20
  363. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.tokens.json +0 -1267
  364. package/data/harnesses/code/skills/design/data/design-tokens/goldens.json +0 -251
  365. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.resolver.json +0 -20
  366. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.tokens.json +0 -1273
  367. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.resolver.json +0 -20
  368. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.tokens.json +0 -1286
  369. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.resolver.json +0 -20
  370. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.tokens.json +0 -1290
  371. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.resolver.json +0 -20
  372. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.tokens.json +0 -1270
  373. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.resolver.json +0 -23
  374. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.dark.json +0 -599
  375. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.json +0 -1272
  376. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.resolver.json +0 -20
  377. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.tokens.json +0 -1267
  378. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.resolver.json +0 -20
  379. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.tokens.json +0 -1289
  380. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.resolver.json +0 -20
  381. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.tokens.json +0 -1258
  382. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.resolver.json +0 -20
  383. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.tokens.json +0 -1284
  384. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.resolver.json +0 -20
  385. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.tokens.json +0 -1291
  386. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.resolver.json +0 -20
  387. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.tokens.json +0 -1263
  388. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.resolver.json +0 -20
  389. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.tokens.json +0 -1270
  390. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.resolver.json +0 -20
  391. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.tokens.json +0 -1261
  392. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.resolver.json +0 -20
  393. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.tokens.json +0 -1209
  394. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.resolver.json +0 -20
  395. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.tokens.json +0 -1265
  396. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.resolver.json +0 -20
  397. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.tokens.json +0 -1253
  398. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.resolver.json +0 -20
  399. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.tokens.json +0 -1268
  400. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.resolver.json +0 -20
  401. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.tokens.json +0 -1261
  402. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.resolver.json +0 -20
  403. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.tokens.json +0 -1263
  404. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.resolver.json +0 -20
  405. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.tokens.json +0 -1266
  406. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.resolver.json +0 -23
  407. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.dark.json +0 -623
  408. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.json +0 -1276
  409. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.resolver.json +0 -20
  410. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.tokens.json +0 -1264
  411. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.resolver.json +0 -20
  412. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.tokens.json +0 -1268
  413. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.resolver.json +0 -20
  414. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.tokens.json +0 -1270
  415. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.resolver.json +0 -20
  416. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.tokens.json +0 -1288
  417. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.resolver.json +0 -20
  418. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.tokens.json +0 -1272
  419. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.resolver.json +0 -20
  420. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.tokens.json +0 -1265
  421. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.resolver.json +0 -20
  422. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.tokens.json +0 -1287
  423. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.resolver.json +0 -20
  424. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.tokens.json +0 -1286
  425. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.resolver.json +0 -20
  426. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.tokens.json +0 -1285
  427. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.resolver.json +0 -20
  428. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.tokens.json +0 -1287
  429. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.resolver.json +0 -20
  430. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.tokens.json +0 -1278
  431. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.resolver.json +0 -20
  432. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.tokens.json +0 -1269
  433. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.resolver.json +0 -20
  434. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.tokens.json +0 -1285
  435. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.resolver.json +0 -20
  436. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.tokens.json +0 -1303
  437. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.resolver.json +0 -20
  438. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.tokens.json +0 -1274
  439. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.resolver.json +0 -20
  440. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.tokens.json +0 -1296
  441. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.resolver.json +0 -23
  442. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.dark.json +0 -612
  443. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.json +0 -1282
  444. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.resolver.json +0 -20
  445. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.tokens.json +0 -1287
  446. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.resolver.json +0 -20
  447. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.tokens.json +0 -1268
  448. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.resolver.json +0 -20
  449. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.tokens.json +0 -1276
  450. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.resolver.json +0 -20
  451. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.tokens.json +0 -1273
  452. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.resolver.json +0 -20
  453. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.tokens.json +0 -1296
  454. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.resolver.json +0 -20
  455. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.tokens.json +0 -1286
  456. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/command-center.tsx +0 -249
  457. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/create-edit.tsx +0 -249
  458. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/dashboard.tsx +0 -225
  459. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/entity-detail.tsx +0 -249
  460. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/list-detail.tsx +0 -224
  461. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/log-stream.tsx +0 -249
  462. package/data/harnesses/code/skills/design/data/operator-pack/fixtures.md +0 -88
  463. package/data/harnesses/code/skills/design/data/operator-pack/surface-catalog.md +0 -132
  464. package/data/harnesses/code/skills/design/data/operator-pack/trust-rubric.md +0 -76
  465. package/data/harnesses/code/skills/design/references/create.md +0 -173
  466. package/data/harnesses/code/skills/design/references/diagnosis.md +0 -108
  467. package/data/harnesses/code/skills/design/references/hard-rules.md +0 -177
  468. package/data/harnesses/code/skills/design/references/improve.md +0 -116
  469. package/data/harnesses/code/skills/design/references/interaction.md +0 -77
  470. package/data/harnesses/code/skills/design/references/introspect.md +0 -100
  471. package/data/harnesses/code/skills/design/references/lifecycle.md +0 -73
  472. package/data/harnesses/code/skills/design/references/personality.md +0 -575
  473. package/data/harnesses/code/skills/design/references/structure.md +0 -159
  474. package/data/harnesses/code/skills/design/scripts/convert-design-md.mjs +0 -1312
  475. package/data/harnesses/code/skills/design/scripts/derive-personality.mjs +0 -1498
  476. package/data/harnesses/code/skills/design/scripts/generate-fixtures.mjs +0 -551
  477. package/data/harnesses/code/skills/design/scripts/lib/checks.mjs +0 -1092
  478. package/data/harnesses/code/skills/design/scripts/lib/golden.mjs +0 -26
  479. package/data/harnesses/code/skills/design/scripts/lib/vocabulary.mjs +0 -65
  480. package/data/harnesses/code/skills/design/scripts/phase-gate.mjs +0 -538
  481. package/data/harnesses/code/skills/design/scripts/preship-sweep.mjs +0 -312
  482. package/data/harnesses/code/skills/design/scripts/render-rung.mjs +0 -890
  483. package/data/harnesses/code/skills/design/scripts/scaffold.mjs +0 -769
  484. package/data/harnesses/code/skills/design/scripts/self-integrity.mjs +0 -675
  485. package/data/harnesses/code/skills/design/scripts/snapshot-goldens.mjs +0 -164
  486. package/data/harnesses/code/skills/design/scripts/validate-combinations.mjs +0 -439
@@ -1,26 +0,0 @@
1
- // skills/design/scripts/lib/golden.mjs — golden-CSS comparison primitives: comment stripping + sha256 hashing for the byte-match regression oracle.
2
-
3
- import { createHash } from "node:crypto";
4
-
5
- // Remove every /* ... */ comment block (CSS has no other comment syntax; an unterminated comment strips to EOF) — no whitespace normalization, byte-exact otherwise.
6
- export function stripCssComments(css) {
7
- let out = "";
8
- let i = 0;
9
- while (i < css.length) {
10
- const open = css.indexOf("/*", i);
11
- if (open === -1) {
12
- out += css.slice(i);
13
- break;
14
- }
15
- out += css.slice(i, open);
16
- const close = css.indexOf("*/", open + 2);
17
- if (close === -1) break; // unterminated comment: strip to EOF
18
- i = close + 2;
19
- }
20
- return out;
21
- }
22
-
23
- // sha256 hex digest of stripCssComments(css) — the golden fingerprint of one emitted CSS file.
24
- export function goldenHash(css) {
25
- return createHash("sha256").update(stripCssComments(css), "utf8").digest("hex");
26
- }
@@ -1,65 +0,0 @@
1
- // skills/design/scripts/lib/vocabulary.mjs — single-source shared runtime vocabulary for the design skill's scripts: the delight-budget enum + file-header stamps, the surface-archetype budget defaults, the motion-moment class names, and the theme attribute convention. scaffold.mjs writes these strings; phase-gate.mjs reads them at the surfaces gate; the preship sweep and emission read them in later steps. One module so the stamp text, the enum, and the theme names never drift between the writer and its readers.
2
-
3
- // The two delight-budget values a surface can carry (references/structure.md, the delight budget).
4
- export const BUDGETS = ['baseline', 'brand-forward'];
5
-
6
- // The verbatim file-header comment scaffold.mjs writes at the top of each surface route file, keyed by budget.
7
- export const BUDGET_STAMPS = {
8
- baseline: '// Surface: baseline',
9
- 'brand-forward': '// Surface: brand-forward (delight-allowing)',
10
- };
11
-
12
- // The stamp comment for a budget, or null when it is not one of BUDGETS.
13
- export function stampFor(budget) {
14
- return Object.prototype.hasOwnProperty.call(BUDGET_STAMPS, budget) ? BUDGET_STAMPS[budget] : null;
15
- }
16
-
17
- // Matches any `// Surface:` header line, well-formed or not — gates count these to catch a malformed
18
- // or duplicated stamp against the well-formed matches below.
19
- export const BUDGET_STAMP_LOOSE_RE = /\/\/ Surface:.*/g;
20
-
21
- // Every well-formed budget stamp in a source blob, in order, as budget values ('baseline' | 'brand-forward').
22
- // Gates count occurrences (exactly one per route file) and read the stamped budget from this.
23
- export function findBudgetStamps(source) {
24
- const re = /\/\/ Surface: (brand-forward \(delight-allowing\)|baseline)(?=\s|$)/g;
25
- const found = [];
26
- let m;
27
- while ((m = re.exec(String(source))) !== null) {
28
- found.push(m[1].startsWith('brand-forward') ? 'brand-forward' : 'baseline');
29
- }
30
- return found;
31
- }
32
-
33
- // Surface archetypes whose delight budget defaults to `baseline` — a `brand-forward` stamp on one of
34
- // these needs a recorded reason in the surface map (references/structure.md, the delight budget).
35
- export const BASELINE_DEFAULT_ARCHETYPES = ['list-detail', 'log-stream', 'command-center'];
36
-
37
- // Surface archetypes that are `brand-forward` *candidates* — granted when the look's delight is
38
- // expressive or the brief asks for presence, else baseline; no recorded reason needed either way.
39
- export const BRAND_FORWARD_CANDIDATE_ARCHETYPES = ['dashboard', 'entity-detail', 'create-edit'];
40
-
41
- // True when a `brand-forward` stamp on this archetype requires a recorded reason in the surface map.
42
- export function requiresBudgetReason(archetype, budget) {
43
- return budget === 'brand-forward' && BASELINE_DEFAULT_ARCHETYPES.includes(String(archetype));
44
- }
45
-
46
- // Motion-moment CSS classes (references/structure.md the delight budget; data/combinations/motion.csv).
47
- // scaffold consumes them where the archetype calls: table rows ride motion-lift (hover feedback,
48
- // budget-free); card grids ride motion-stagger on brand-forward surfaces only — baseline-stamped
49
- // surfaces skip arrival cascades (mot-08). The render rung audits rendered stagger containers.
50
- export const MOTION_LIFT_CLASS = 'motion-lift';
51
- export const MOTION_STAGGER_CLASS = 'motion-stagger';
52
- // The derived custom property the stagger cascade reads; cap the staggered children at STAGGER_CHILD_CAP.
53
- export const STAGGER_DELAY_VAR = '--stagger-delay';
54
- export const STAGGER_CHILD_CAP = 8;
55
-
56
- // The theme runtime attribute: its name and the two legal rendered values. look.theme `both` boots
57
- // light with a working toggle, so the emitted default is always one of these two.
58
- export const THEME_ATTR = 'data-theme';
59
- export const THEME_VALUES = ['light', 'dark'];
60
-
61
- // Resolve a look.theme (light | dark | both) to the emitted default data-theme value (both → light);
62
- // anything unrecognized falls back to light.
63
- export function resolveThemeDefault(theme) {
64
- return theme === 'dark' ? 'dark' : 'light';
65
- }
@@ -1,538 +0,0 @@
1
- // skills/design/scripts/phase-gate.mjs — create-phase precondition gates (D21/D23): validate the named phase's exit preconditions, printing the exact fix on failure; every gate also fires the machine-check engine (lib/checks.mjs — per-file catalog + manifest drift) over the project's whole UI tree and exits non-zero on either failure.
2
- import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
3
- import { join, dirname, resolve, relative } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { spawnSync } from 'node:child_process';
6
- import { runChecks, formatFindings, walkUiFiles } from './lib/checks.mjs';
7
- import { findBudgetStamps, BUDGET_STAMP_LOOSE_RE, requiresBudgetReason } from './lib/vocabulary.mjs';
8
-
9
- const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
10
- const PHASES = ['intake', 'structure', 'scaffold', 'tokens', 'fixtures', 'surfaces'];
11
- const ARCHETYPES = new Set(['list-detail', 'dashboard', 'entity-detail', 'create-edit', 'log-stream', 'command-center']);
12
- const PROVENANCE = new Set(['project', 'extracted', 'library', 'default']);
13
- const STATE_SYNONYMS = { loading: ['loading', 'skeleton'], empty: ['empty'], error: ['error'], partial: ['partial', 'degraded', 'stale'] };
14
- // The intake look block's enums (references/create.md, the look block). theme carries `both`; the emitted
15
- // data-theme value the attribute cascade uses is light|dark (both boots light) — that pair lives in vocabulary.mjs.
16
- const LOOK_THEMES = new Set(['light', 'dark', 'both']);
17
- const DELIGHT_LEVELS = new Set(['baseline', 'expressive']);
18
- const RESOLUTION_MODES = new Set(['confirmed', 'recorded']);
19
- // The resolution spine's legal shapes: project | library:<slug> | seed:<style-row>+<palette-row> | default.
20
- const RESOLUTION_RE = /^(project|default|library:.+|seed:.+\+.+)$/i;
21
-
22
- const useColor = process.stdout.isTTY;
23
- // Wrap a string in green/red when writing to a TTY, plain otherwise.
24
- const green = (s) => (useColor ? `\x1b[32m${s}\x1b[0m` : s);
25
- const red = (s) => (useColor ? `\x1b[31m${s}\x1b[0m` : s);
26
-
27
- // Read a UTF-8 file, returning '' when it is absent.
28
- function readText(path) {
29
- try { return readFileSync(path, 'utf8'); } catch { return ''; }
30
- }
31
-
32
- // Sentinel a gate throws (via fail) to abort its remaining precondition checks without exiting the process.
33
- class GateFailure extends Error {}
34
-
35
- // Report a passing gate as one green line (the process exit code is decided in main, after the source sweep).
36
- function pass(phase, msg) {
37
- console.log(`${green(`PASS phase-gate[${phase}]`)} ${msg}`);
38
- }
39
-
40
- // Report a failing gate with the problem and the exact fix, then abort the gate.
41
- function fail(phase, problem, fixLines) {
42
- console.error(`${red(`FAIL phase-gate[${phase}]`)} ${problem}`);
43
- console.error('');
44
- console.error(' Fix:');
45
- for (const line of fixLines) {
46
- if (line == null || line === '') continue;
47
- for (const sub of String(line).split('\n')) console.error(` ${sub}`);
48
- }
49
- throw new GateFailure(problem);
50
- }
51
-
52
- // Lowercase-kebab a display name for route-dir / fixture-module matching.
53
- function kebab(s) {
54
- return String(s).trim().toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
55
- }
56
-
57
- // Return the first non-parameter path segment of a route (/tickets/:id -> tickets).
58
- function firstStaticSegment(route) {
59
- for (const p of String(route).split('/').filter(Boolean)) {
60
- if (!p.startsWith(':')) return kebab(p);
61
- }
62
- return null;
63
- }
64
-
65
- // Return the last non-parameter path segment of a route (/tickets/new -> new).
66
- function lastStaticSegment(route) {
67
- const parts = String(route).split('/').filter(Boolean).filter((p) => !p.startsWith(':'));
68
- return parts.length ? kebab(parts[parts.length - 1]) : null;
69
- }
70
-
71
- // Parse a JSON file into an object, or null when it is absent or malformed.
72
- function readJson(path) {
73
- try {
74
- const parsed = JSON.parse(readFileSync(path, 'utf8'));
75
- return parsed && typeof parsed === 'object' ? parsed : null;
76
- } catch { return null; }
77
- }
78
-
79
- // Collect every token file the resolver references (set values plus all modifier-context overlays).
80
- function resolverNamedFiles(resolver) {
81
- const named = [];
82
- for (const set of Array.isArray(resolver.sets) ? resolver.sets : []) {
83
- if (set && Array.isArray(set.values)) named.push(...set.values.filter((f) => typeof f === 'string'));
84
- }
85
- for (const mod of Array.isArray(resolver.modifiers) ? resolver.modifiers : []) {
86
- const contexts = mod && mod.contexts && typeof mod.contexts === 'object' ? mod.contexts : {};
87
- for (const files of Object.values(contexts)) {
88
- if (Array.isArray(files)) named.push(...files.filter((f) => typeof f === 'string'));
89
- }
90
- }
91
- return named;
92
- }
93
-
94
- // Split a `[a, b, c]` inline list into trimmed members.
95
- function parseBracketList(s) {
96
- const m = String(s).match(/\[([^\]]*)\]/);
97
- if (!m) return [];
98
- return m[1].split(',').map((x) => x.trim()).filter(Boolean);
99
- }
100
-
101
- // Store one `key: value` pair onto a list-item object, parsing `states` into an array.
102
- function applyKV(obj, s) {
103
- const idx = s.indexOf(':');
104
- if (idx < 0) return;
105
- const key = s.slice(0, idx).trim();
106
- const value = s.slice(idx + 1).trim();
107
- if (key === 'states') obj.states = parseBracketList(value);
108
- else obj[key] = value;
109
- }
110
-
111
- // Parse the fenced ```yaml structure block into entities, surfaces, and temporal facts.
112
- function parseStructureBlock(md) {
113
- const m = md.match(/```yaml structure\r?\n([\s\S]*?)```/);
114
- if (!m) return null;
115
- const result = { unitOfWork: null, coreLoop: null, entities: [], temporal: null, surfaces: [] };
116
- let section = null;
117
- let itemIndent = -1;
118
- let current = null;
119
- for (const raw of m[1].split(/\r?\n/)) {
120
- if (!raw.trim() || raw.trim().startsWith('#')) continue;
121
- const indent = raw.length - raw.trimStart().length;
122
- const line = raw.trim();
123
- if (indent === 0) {
124
- current = null;
125
- itemIndent = -1;
126
- if (line.startsWith('unit-of-work:')) { result.unitOfWork = line.slice(line.indexOf(':') + 1).trim(); section = null; }
127
- else if (line.startsWith('core-loop:')) { result.coreLoop = line.slice(line.indexOf(':') + 1).trim(); section = null; }
128
- else if (line === 'entities:') section = 'entities';
129
- else if (line === 'surfaces:') section = 'surfaces';
130
- else if (line === 'temporal:') { section = 'temporal'; result.temporal = {}; }
131
- else section = null;
132
- continue;
133
- }
134
- if (section === 'entities' || section === 'surfaces') {
135
- const list = section === 'entities' ? result.entities : result.surfaces;
136
- if (line.startsWith('- ')) {
137
- if (itemIndent === -1) itemIndent = indent;
138
- if (indent === itemIndent) {
139
- current = {};
140
- list.push(current);
141
- const rest = line.slice(2).trim();
142
- if (rest && rest.includes(':')) applyKV(current, rest);
143
- }
144
- } else if (current && itemIndent !== -1 && indent > itemIndent) {
145
- applyKV(current, line);
146
- }
147
- } else if (section === 'temporal') {
148
- const idx = line.indexOf(':');
149
- if (idx > 0) result.temporal[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
150
- }
151
- }
152
- return result;
153
- }
154
-
155
- // Read and parse the structure map, or fail the gate with the structure-phase fix.
156
- function requireMap(phase, project) {
157
- const p = join(project, 'docs/design/structure.md');
158
- if (!existsSync(p)) {
159
- fail(phase, `No entity/surface map at ${p} — this phase reads it.`, [
160
- 'Complete the structure phase first: derive docs/design/structure.md with a fenced ```yaml structure block (references/structure.md).',
161
- ]);
162
- }
163
- const blk = parseStructureBlock(readText(p));
164
- if (!blk) {
165
- fail(phase, `${p} has no parseable "yaml structure" fenced block.`, [
166
- 'The block must open exactly with the fence info-string `yaml structure` and carry entities[], temporal, and surfaces[].',
167
- ]);
168
- }
169
- return blk;
170
- }
171
-
172
- // Collect all .ts/.tsx source under a route directory into one lowercased blob.
173
- function routeSource(dir) {
174
- return routeSourceRaw(dir).toLowerCase();
175
- }
176
-
177
- // Collect all .ts/.tsx source under a route directory, case preserved (the budget stamp is case-sensitive).
178
- function routeSourceRaw(dir) {
179
- let out = '';
180
- const stack = [dir];
181
- while (stack.length) {
182
- const cur = stack.pop();
183
- let entries;
184
- try { entries = readdirSync(cur, { withFileTypes: true }); } catch { continue; }
185
- for (const ent of entries) {
186
- const full = join(cur, ent.name);
187
- if (ent.isDirectory()) stack.push(full);
188
- else if (/\.(tsx|ts)$/.test(ent.name)) out += `\n${readText(full)}`;
189
- }
190
- }
191
- return out;
192
- }
193
-
194
- // Return the candidate route-dir slugs for a surface (name-kebab, route segments, archetype).
195
- function routeDirCandidates(s) {
196
- const out = [];
197
- if (s.name) out.push(kebab(s.name));
198
- if (s.route) { const f = firstStaticSegment(s.route); if (f) out.push(f); const l = lastStaticSegment(s.route); if (l) out.push(l); }
199
- if (s.archetype) out.push(s.archetype);
200
- return [...new Set(out.filter(Boolean))];
201
- }
202
-
203
- // Resolve a surface's route directory to the first existing candidate, or null.
204
- function resolveRouteDir(s, routesDir) {
205
- for (const c of routeDirCandidates(s)) {
206
- const d = join(routesDir, c);
207
- if (existsSync(d) && statSync(d).isDirectory()) return d;
208
- }
209
- return null;
210
- }
211
-
212
- // List the declared states whose branch is absent from a route's shell source.
213
- function missingStates(dir, states) {
214
- const text = routeSource(dir);
215
- return states.filter((st) => {
216
- const words = STATE_SYNONYMS[st] || [st.toLowerCase()];
217
- return !words.some((w) => text.includes(w));
218
- });
219
- }
220
-
221
- // Validate the load-bearing five-step globals.css import order (Cascade Contract 2).
222
- function checkImportOrder(rawCss) {
223
- const css = rawCss.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^[ \t]*\/\/.*$/gm, '');
224
- const marks = [
225
- ['@import "./personality.css"', css.indexOf('@import "./personality.css"')],
226
- ['@import "tailwindcss"', css.indexOf('@import "tailwindcss"')],
227
- ['@import "@nurix/components/styles.css"', css.indexOf('@import "@nurix/components/styles.css"')],
228
- ['@theme inline', css.search(/^\s*@theme\s+inline\b/m)],
229
- ];
230
- const absent = marks.filter(([, i]) => i < 0).map(([n]) => n);
231
- if (absent.length) {
232
- return { problem: `globals.css is missing: ${absent.join(', ')}.`, fix: [
233
- 'Emit the five-step cascade order (references/personality.md §4, Cascade Contract 2):',
234
- '@import "./personality.css"; -> @import "tailwindcss"; -> @import "@nurix/components/styles.css"; -> @theme inline { ... }',
235
- ] };
236
- }
237
- const [p, t, l, th] = marks.map(([, i]) => i);
238
- if (!(p < t && t < l && l < th)) {
239
- return { problem: 'globals.css import order is wrong — personality -> tailwindcss -> library -> @theme is load-bearing.', fix: [
240
- 'Reorder so the consumer @theme inline comes AFTER the @nurix/components/styles.css import, or the library radius scale and token defaults win.',
241
- ] };
242
- }
243
- return null;
244
- }
245
-
246
- // Validate the payload's mandatory look block (references/create.md, the look block): presence, the theme /
247
- // delight / resolution-mode enums, 2–3 named anchor strings, the resolution shape, and — when the
248
- // resolution was authorized autonomously (resolution-mode: recorded) — that the artifact root
249
- // $description carries a resolution record naming the runner-up. Fails the gate with the exact fix.
250
- function validateLookBlock(payload, tokens) {
251
- const look = payload.look;
252
- if (!look || typeof look !== 'object' || Array.isArray(look)) {
253
- fail('intake', 'payload carries no look block (payload.look).', [
254
- 'Add the mandatory look block to the artifact payload (references/create.md, the look block):',
255
- 'look: { theme: light|dark|both, anchors: ["Product A", "Product B"], delight: baseline|expressive,',
256
- ' resolution: project | library:<slug> | seed:<style>+<palette> | default, resolution-mode: confirmed|recorded }.',
257
- ]);
258
- }
259
- if (!LOOK_THEMES.has(look.theme)) {
260
- fail('intake', `look.theme is "${look.theme ?? '(missing)'}"; must be light | dark | both.`, [
261
- 'Set look.theme from the brief; it is binding when stated, default light (references/create.md, the look block).',
262
- ]);
263
- }
264
- if (!DELIGHT_LEVELS.has(look.delight)) {
265
- fail('intake', `look.delight is "${look.delight ?? '(missing)'}"; must be baseline | expressive.`, [
266
- 'Set look.delight — the global delight ceiling per-surface budgets refine (references/create.md the look block, references/structure.md the delight budget).',
267
- ]);
268
- }
269
- const mode = look['resolution-mode'];
270
- if (!RESOLUTION_MODES.has(mode)) {
271
- fail('intake', `look.resolution-mode is "${mode ?? '(missing)'}"; must be confirmed | recorded.`, [
272
- 'Set look.resolution-mode: confirmed when a confirmer authorized the pick, recorded when it was resolved autonomously (references/create.md, Resolution).',
273
- ]);
274
- }
275
- const anchors = look.anchors;
276
- if (!Array.isArray(anchors) || anchors.length < 2 || anchors.length > 3 || !anchors.every((a) => typeof a === 'string' && a.trim())) {
277
- fail('intake', `look.anchors must be 2–3 non-empty named strings; got ${JSON.stringify(anchors ?? null)}.`, [
278
- 'Name two or three real products (["Linear", "Stripe Dashboard"]); adjectives are not anchors —',
279
- 'convert an adjective to a named product by asking (interactive) or inferring-and-recording (autonomous) via the design-md resemblance lookup (references/create.md, the look block).',
280
- ]);
281
- }
282
- if (typeof look.resolution !== 'string' || !RESOLUTION_RE.test(look.resolution.trim())) {
283
- fail('intake', `look.resolution is "${look.resolution ?? '(missing)'}"; must match project | library:<slug> | seed:<style>+<palette> | default.`, [
284
- 'Set look.resolution to the resolved source from the precedence spine (references/create.md, Resolution).',
285
- ]);
286
- }
287
- if (mode === 'recorded') {
288
- const desc = tokens.$description;
289
- if (typeof desc !== 'string' || !desc.trim() || !/runner-up/i.test(desc)) {
290
- fail('intake', 'resolution-mode is recorded but the artifact root $description carries no resolution record naming the runner-up.', [
291
- 'Write the resolution record into the artifact root $description — winner, runner-up, and the deciding evidence, e.g.:',
292
- 'resolution: library:stripe (recorded; runner-up palettes.csv#3; brief phrase "Stripe-dashboard territory" matched product + fintech traits).',
293
- 'A recorded (autonomous) resolution is legitimate only once it is auditable (references/create.md, Resolution).',
294
- ]);
295
- }
296
- }
297
- }
298
-
299
- // intake gate: a structurally sound design-tokens artifact sits at project root — both files parse, the dark
300
- // file agrees with the resolver, the payload carries a legal schema/provenance/product, and the mandatory
301
- // look block is present and well-formed. Light checks only; deep validation (coverage, aliases, parse-back)
302
- // is derive-personality.mjs --check at the tokens gate.
303
- function gateIntake(project) {
304
- const tokensPath = join(project, 'design.tokens.json');
305
- const resolverPath = join(project, 'design.resolver.json');
306
- const absent = [tokensPath, resolverPath].filter((p) => !existsSync(p)).map((p) => relative(project, p));
307
- if (absent.length) {
308
- fail('intake', `Missing token-artifact file(s) at project root: ${absent.join(', ')}.`, [
309
- 'Write the design-tokens artifact against skills/design/data/design-tokens/SCHEMA.md:',
310
- 'design.tokens.json (base/light set + the $extensions["com.nurix.design"] payload) and design.resolver.json,',
311
- 'plus design.tokens.dark.json only when the look has dark values.',
312
- 'Resolve the look artifact-first: the project artifact wins, else a confirmed library entry, else the Nurix default.',
313
- ]);
314
- }
315
- const tokens = readJson(tokensPath);
316
- if (!tokens) fail('intake', 'design.tokens.json does not parse as JSON.', ['Fix the JSON before anything deeper runs (data/design-tokens/SCHEMA.md).']);
317
- const resolver = readJson(resolverPath);
318
- if (!resolver) fail('intake', 'design.resolver.json does not parse as JSON.', ['Fix the JSON (data/design-tokens/SCHEMA.md — the resolver section).']);
319
- const namesDark = resolverNamedFiles(resolver).includes('design.tokens.dark.json');
320
- const hasDark = existsSync(join(project, 'design.tokens.dark.json'));
321
- if (namesDark && !hasDark) {
322
- fail('intake', 'design.resolver.json names design.tokens.dark.json but the file is absent.', [
323
- 'Ship the dark modifier set beside the base file, or drop the dark context from the resolver —',
324
- 'the dark file exists exactly when the resolver names it (data/design-tokens/SCHEMA.md).',
325
- ]);
326
- }
327
- if (!namesDark && hasDark) {
328
- fail('intake', 'design.tokens.dark.json is present but the resolver names no dark context.', [
329
- 'Add "dark": ["design.tokens.dark.json"] to the theme modifier contexts, or remove the dark file —',
330
- 'the dark file exists exactly when the resolver names it (data/design-tokens/SCHEMA.md).',
331
- ]);
332
- }
333
- const payload = tokens.$extensions && tokens.$extensions['com.nurix.design'];
334
- if (!payload || typeof payload !== 'object') {
335
- fail('intake', 'design.tokens.json carries no root $extensions["com.nurix.design"] payload.', [
336
- 'Add the file-level payload (schema, dtcg, product, provenance, sourced, lever-manifest, …) per data/design-tokens/SCHEMA.md.',
337
- ]);
338
- }
339
- if (payload.schema !== 'design-tokens/v2') fail('intake', `payload schema is "${payload.schema || '(missing)'}", expected design-tokens/v2.`, ['Set schema: "design-tokens/v2" in the payload (data/design-tokens/SCHEMA.md).']);
340
- if (!PROVENANCE.has(payload.provenance)) fail('intake', `payload provenance is "${payload.provenance || '(missing)'}"; must be one of project|extracted|library|default.`, ['Set provenance to one of: project | extracted | library | default (data/design-tokens/SCHEMA.md).']);
341
- if (typeof payload.product !== 'string' || !payload.product.trim()) fail('intake', 'payload product is missing or empty.', ['Set product to the product name; slugified it becomes the data-style value (data/design-tokens/SCHEMA.md).']);
342
- validateLookBlock(payload, tokens);
343
- pass('intake', `design.tokens.json + design.resolver.json present and parsing; payload schema design-tokens/v2, provenance "${payload.provenance}"${namesDark ? ', dark set named and present' : ', light-only'}; look block valid (theme ${payload.look.theme}, delight ${payload.look.delight}, ${Array.isArray(payload.look.anchors) ? payload.look.anchors.length : 0} anchors, resolution-mode ${payload.look['resolution-mode']}).`);
344
- }
345
-
346
- // structure gate: the map parses, is populated, has a temporal block, and every surface archetype is one of the six.
347
- function gateStructure(project) {
348
- const blk = requireMap('structure', project);
349
- if (!blk.entities.length) fail('structure', 'The structure map has no entities — the object pass was skipped.', ['Populate entities[] from the domain nouns (references/structure.md -> object pass); a small brief earns a small pass, never a skipped one.']);
350
- if (!blk.surfaces.length) fail('structure', 'The structure map has no surfaces.', ['Assign each surface an archetype from the closed six under surfaces[].']);
351
- if (!blk.temporal || !Object.keys(blk.temporal).length) fail('structure', 'The structure map has no temporal block.', ['Add the temporal probe (intermediate-states, read-model-lag, deletion, failure-paths) — model facts, not later polish.']);
352
- const bad = blk.surfaces.filter((s) => !ARCHETYPES.has(s.archetype));
353
- if (bad.length) {
354
- fail('structure', `${bad.length} surface(s) carry an archetype outside the closed six: ${bad.map((s) => `${s.name || '(unnamed)'}="${s.archetype || '(none)'}"`).join(', ')}.`, [
355
- `Every surface's archetype must be one of: ${[...ARCHETYPES].join(', ')}.`,
356
- ]);
357
- }
358
- pass('structure', `${blk.surfaces.length} surface(s), all archetypes valid; ${blk.entities.length} entit(ies) and a temporal block present.`);
359
- }
360
-
361
- // scaffold gate: the shell, per-surface route dirs + state-shells, router wiring, and globals.css import order are in place.
362
- function gateScaffold(project) {
363
- const blk = requireMap('scaffold', project);
364
- const shellFiles = ['index.html', 'src/main.tsx', 'src/App.tsx'];
365
- const missing = shellFiles.filter((f) => !existsSync(join(project, f)));
366
- if (missing.length) {
367
- fail('scaffold', `Missing shell file(s): ${missing.join(', ')}.`, [
368
- `Run scaffold.mjs docs/design/structure.md --out ${project} to emit index.html, src/main.tsx, src/App.tsx, route wiring, and state-shells.`,
369
- ]);
370
- }
371
- const indexHtml = readText(join(project, 'index.html'));
372
- if (!/<html[^>]*\bdata-style=/.test(indexHtml)) {
373
- fail('scaffold', 'index.html <html> is missing the data-style attribute.', [
374
- 'Emit <html data-style="..." data-density="..." data-verbosity="..." data-feedback="..." data-theme="light"> (references/personality.md §5).',
375
- ]);
376
- }
377
- const routesDir = join(project, 'src/routes');
378
- const app = readText(join(project, 'src/App.tsx'));
379
- const noRoute = [];
380
- const noWire = [];
381
- const noShell = [];
382
- for (const s of blk.surfaces) {
383
- const dir = resolveRouteDir(s, routesDir);
384
- const name = s.name || s.route || '(unnamed)';
385
- if (!dir) { noRoute.push(`${name} (expected src/routes/${routeDirCandidates(s).join(' or /')})`); continue; }
386
- const seg = s.route ? firstStaticSegment(s.route) : null;
387
- if (seg && !app.toLowerCase().includes(seg)) noWire.push(`${name} (route "${s.route}" not referenced in src/App.tsx)`);
388
- const states = (s.states && s.states.length) ? s.states : ['loading', 'empty', 'error', 'partial'];
389
- const miss = missingStates(dir, states);
390
- if (miss.length) noShell.push(`${name} (no ${miss.join(', ')} shell)`);
391
- }
392
- if (noRoute.length) fail('scaffold', `No route directory for surface(s): ${noRoute.join('; ')}.`, ['scaffold.mjs owns route/nav wiring — emit src/routes/<surface>/ per surface from the map.']);
393
- if (noWire.length) fail('scaffold', `Route(s) not wired into the router: ${noWire.join('; ')}.`, ['Every surface route must be registered in src/App.tsx (react-router-dom) — routes and nav derive from the map, never decorated on.']);
394
- if (noShell.length) fail('scaffold', `Missing state-shell stubs: ${noShell.join('; ')}.`, ['Each surface needs its loading / empty / error / degraded shells wired (references/create.md -> scaffold).']);
395
- const globals = join(project, 'src/styles/globals.css');
396
- if (!existsSync(globals)) fail('scaffold', 'Missing src/styles/globals.css (Tailwind glue with the five-step import order).', ['Emit src/styles/globals.css with the Cascade Contract 2 import order (references/personality.md §4).']);
397
- const orderErr = checkImportOrder(readText(globals));
398
- if (orderErr) fail('scaffold', orderErr.problem, orderErr.fix);
399
- pass('scaffold', `Shell, ${blk.surfaces.length} wired route dir(s) with state-shells, and globals.css import order all in place.`);
400
- }
401
-
402
- // tokens gate: the design-tokens artifact clears the coverage gate (derive-personality.mjs <project> --check) and both CSS files are emitted with the cascade order intact.
403
- function gateTokens(project) {
404
- const tokensPath = join(project, 'design.tokens.json');
405
- if (!existsSync(tokensPath)) fail('tokens', `No design.tokens.json at ${tokensPath}.`, ['Resolve and materialize the design-tokens artifact first (intake phase; data/design-tokens/SCHEMA.md).']);
406
- const derive = join(SCRIPT_DIR, 'derive-personality.mjs');
407
- if (!existsSync(derive)) fail('tokens', `Coverage-gate sibling not found: ${derive}.`, ['derive-personality.mjs must sit beside phase-gate.mjs in the scripts/ directory.']);
408
- const res = spawnSync(process.execPath, [derive, project, '--check'], { encoding: 'utf8' });
409
- if (res.status !== 0) {
410
- const detail = `${res.stdout || ''}${res.stderr || ''}`.trim();
411
- fail('tokens', `The token-artifact coverage gate failed (derive-personality.mjs --check exited ${res.status == null ? '(spawn error)' : res.status}).`, [
412
- 'Assign or hint every named token path below, then re-run this gate:',
413
- detail,
414
- ]);
415
- }
416
- const files = ['src/styles/personality.css', 'src/styles/globals.css'];
417
- const miss = files.filter((f) => !existsSync(join(project, f)));
418
- if (miss.length) {
419
- fail('tokens', `Coverage gate passed but emitted CSS is missing: ${miss.join(', ')}.`, [
420
- `Run derive-personality.mjs ${project} --emit ${project} to write src/styles/personality.css and src/styles/globals.css.`,
421
- ]);
422
- }
423
- const orderErr = checkImportOrder(readText(join(project, 'src/styles/globals.css')));
424
- if (orderErr) fail('tokens', orderErr.problem, orderErr.fix);
425
- pass('tokens', 'Coverage gate green; personality.css + globals.css emitted with the cascade order intact.');
426
- }
427
-
428
- // fixtures gate: src/fixtures/ carries one seeded module per map entity.
429
- function gateFixtures(project) {
430
- const blk = requireMap('fixtures', project);
431
- const fdir = join(project, 'src/fixtures');
432
- if (!existsSync(fdir)) {
433
- fail('fixtures', 'No src/fixtures/ directory.', [
434
- `Run generate-fixtures.mjs docs/design/structure.md --seed <n> --out ${join(project, 'src/fixtures/')} to write one seeded module per entity.`,
435
- ]);
436
- }
437
- const bases = readdirSync(fdir).filter((f) => /\.(ts|tsx)$/.test(f)).map((f) => f.replace(/\.(ts|tsx)$/, '').toLowerCase());
438
- const missing = [];
439
- for (const e of blk.entities) {
440
- if (!e.name) continue;
441
- const base = e.name.toLowerCase();
442
- const k = kebab(e.name);
443
- const cands = new Set([base, k, `${base}s`, `${k}s`]);
444
- if (/y$/.test(base)) { cands.add(`${base.slice(0, -1)}ies`); cands.add(`${k.slice(0, -1)}ies`); }
445
- if (!bases.some((n) => cands.has(n))) missing.push(e.name);
446
- }
447
- if (missing.length) {
448
- fail('fixtures', `No seeded fixture module for entity/ies: ${missing.join(', ')}.`, [
449
- 'Each map entity needs a seeded module in src/fixtures/ (fixture-before-surface). Re-run generate-fixtures.mjs.',
450
- ]);
451
- }
452
- pass('fixtures', `Seeded fixture module present for all ${blk.entities.length} entit(ies).`);
453
- }
454
-
455
- // surfaces gate: every surface's route dir exists, its shell contains every declared state branch, and
456
- // it carries exactly one well-formed budget stamp — with a recorded budget-reason in the map when a
457
- // brand-forward stamp overrides a baseline-default archetype (references/structure.md, the delight budget). The
458
- // budget-gated vocabulary sweeps (display step typ-20, wash col-16) land with the rule catalog in a
459
- // later step; the stamp is parsed here via lib/vocabulary.mjs so those sweeps reuse the same reader.
460
- function gateSurfaces(project) {
461
- const blk = requireMap('surfaces', project);
462
- const routesDir = join(project, 'src/routes');
463
- const problems = [];
464
- for (const s of blk.surfaces) {
465
- const name = s.name || s.route || '(unnamed)';
466
- const dir = resolveRouteDir(s, routesDir);
467
- if (!dir) { problems.push(`${name}: no route dir under src/routes/ (expected ${routeDirCandidates(s).join(' or ')})`); continue; }
468
- const states = (s.states && s.states.length) ? s.states : ['loading', 'empty', 'error'];
469
- const miss = missingStates(dir, states);
470
- if (miss.length) problems.push(`${name}: shell missing state branch(es) ${miss.join(', ')}`);
471
- const src = routeSourceRaw(dir);
472
- const looseCount = (src.match(BUDGET_STAMP_LOOSE_RE) || []).length;
473
- const stamps = findBudgetStamps(src);
474
- if (looseCount === 0) {
475
- problems.push(`${name}: no budget stamp at the top of the route file`);
476
- } else if (stamps.length !== 1 || looseCount !== 1) {
477
- problems.push(`${name}: expected exactly one well-formed budget stamp, found ${looseCount} "// Surface:" line(s) (${stamps.length} well-formed)`);
478
- } else if (requiresBudgetReason(s.archetype, stamps[0]) && !(typeof s['budget-reason'] === 'string' && s['budget-reason'].trim())) {
479
- problems.push(`${name}: brand-forward stamp on a ${s.archetype} surface (archetype defaults baseline) with no budget-reason in the surface map`);
480
- }
481
- }
482
- if (problems.length) {
483
- fail('surfaces', `${problems.length} surface(s) not fully composed. Handle these before finalizing:`, [
484
- ...problems.map((p) => `- ${p}`),
485
- 'Fill every declared lifecycle state into its pre-created shell (references/create.md -> surfaces); states are composed with the surface, not bolted on.',
486
- 'Every surface route file carries exactly one stamp — "// Surface: baseline" or "// Surface: brand-forward (delight-allowing)"; scaffold.mjs writes it from the map budget, so re-classify by editing the surface budget in docs/design/structure.md and re-running scaffold.mjs.',
487
- 'A brand-forward stamp on a baseline-default archetype (list-detail / log-stream / command-center) needs a recorded budget-reason on that surface entry (references/structure.md, the delight budget).',
488
- ]);
489
- }
490
- pass('surfaces', `All ${blk.surfaces.length} surface(s) have a route dir, every declared state branch, and exactly one legal budget stamp.`);
491
- }
492
-
493
- const GATES = { intake: gateIntake, structure: gateStructure, scaffold: gateScaffold, tokens: gateTokens, fixtures: gateFixtures, surfaces: gateSurfaces };
494
-
495
- // Fire the check engine over the project's whole UI tree (plus design.tokens.json manifest drift); print findings fix-or-classify style, return the violation count.
496
- function sourceSweep(project) {
497
- const files = walkUiFiles(join(project, 'src'));
498
- console.log('');
499
- if (!files.length) {
500
- console.log('source sweep: no src/**/*.{tsx,ts,css,html} files to scan.');
501
- return 0;
502
- }
503
- const manifest = join(project, 'design.tokens.json');
504
- const findings = runChecks(files, { manifestPath: existsSync(manifest) ? manifest : null })
505
- .map((f) => ({ ...f, file: relative(project, f.file) || f.file }));
506
- if (!findings.length) {
507
- console.log(green(`source sweep: clean — ${files.length} file(s), no catalog or manifest-drift violations.`));
508
- return 0;
509
- }
510
- console.log(formatFindings(findings, { color: useColor, label: 'source sweep' }));
511
- return findings.length;
512
- }
513
-
514
- // Parse argv, resolve the project dir, dispatch to the named phase gate, then fire the whole-tree source sweep.
515
- function main() {
516
- const args = process.argv.slice(2);
517
- const phase = args[0];
518
- let project = process.cwd();
519
- for (let i = 1; i < args.length; i++) {
520
- if (args[i] === '--project') project = resolve(args[++i] || '.');
521
- else if (args[i].startsWith('--project=')) project = resolve(args[i].slice('--project='.length));
522
- }
523
- if (!phase || !PHASES.includes(phase)) {
524
- console.error(`usage: phase-gate.mjs <${PHASES.join('|')}> [--project <dir>]`);
525
- process.exit(2);
526
- }
527
- let gateFailed = false;
528
- try {
529
- GATES[phase](project);
530
- } catch (e) {
531
- if (!(e instanceof GateFailure)) throw e;
532
- gateFailed = true;
533
- }
534
- const sweepCount = sourceSweep(project);
535
- process.exit(gateFailed || sweepCount > 0 ? 1 : 0);
536
- }
537
-
538
- main();