@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,675 +0,0 @@
1
- // skills/design/scripts/self-integrity.mjs — the design skill's own CI check: anchor parity (rule ids and the doctrine-floor f-ids), catalog invariants, stated-count and fixture-pair validation (pairs exercised through lib/checks.mjs), the token-era net — token file-tree + goldens parity, per-artifact --check validity, and (behind --goldens) golden emission hash match — plus combination-data validation (validate-combinations.mjs); --fixture <rule-id> runs a single pair
2
- import { readFileSync, existsSync, readdirSync, mkdtempSync, rmSync } from "node:fs";
3
- import { join, dirname, resolve } from "node:path";
4
- import { tmpdir } from "node:os";
5
- import { spawn } from "node:child_process";
6
- import { fileURLToPath } from "node:url";
7
- import { runChecks } from "./lib/checks.mjs";
8
- import { goldenHash } from "./lib/golden.mjs";
9
- import { validateCombinations } from "./validate-combinations.mjs";
10
-
11
- const SCRIPTS_DIR = dirname(fileURLToPath(import.meta.url));
12
- const SKILL_ROOT = join(SCRIPTS_DIR, "..");
13
-
14
- const CATALOG_CSV = join(SKILL_ROOT, "data/catalog/rules.csv");
15
- const FIXTURES_DIR = join(SKILL_ROOT, "data/catalog/fixtures");
16
- const HARD_RULES_MD = join(SKILL_ROOT, "references/hard-rules.md");
17
- const TOKENS_DIR = join(SKILL_ROOT, "data/design-tokens");
18
- const COMBINATIONS_DIR = join(SKILL_ROOT, "data/combinations");
19
- const GOLDENS_JSON = join(TOKENS_DIR, "goldens.json");
20
- const DERIVE_PERSONALITY = join(SCRIPTS_DIR, "derive-personality.mjs");
21
- const SPAWN_LIMIT = 8;
22
-
23
- const CSV_HEADER = ["id", "dimension", "statement", "numbers", "grade", "fire_points", "detector", "scope_note", "provenance", "fixture_pair"];
24
- const VALID_DIMENSIONS = new Set(["P1", "P2", "P3", "P4", "P5", "P6", "P7", "S1", "S2", "S3", "S4", "B1", "B2", "B3", "B4", "B5"]);
25
- const ANCHOR_PREFIXES = "typ|col|spc|dep|int|mot|sta|cod|proc|inst|trust";
26
- const ANCHOR_TOKEN = new RegExp("`(" + ANCHOR_PREFIXES + ")-(\\d{2})`", "g");
27
- const ANCHOR_ID = "(?:" + ANCHOR_PREFIXES + ")-\\d{2}";
28
-
29
- const PINNED = { rows: 136, source: 70, render: 12, archetypes: 6, primitives: 27, colorTokens: 36, semanticTokens: 19, substrateTokens: 17, rampSteps: 7, elevation: 4 };
30
-
31
- // The doctrine floor's canonical ids (f01-f12) — enumerated once in hard-rules.md's Doctrine floor
32
- // section; every in-skill floor citation must name one of these (05-rule-amendments.md, the mapping).
33
- const FLOOR_IDS = Array.from({ length: 12 }, (_, i) => "f" + String(i + 1).padStart(2, "0"));
34
-
35
- // Read a UTF-8 file, returning null when it does not exist.
36
- function readSafe(path) {
37
- return existsSync(path) ? readFileSync(path, "utf8") : null;
38
- }
39
-
40
- // Parse RFC4180-style CSV text into an array of field arrays (quotes + doubled-quote escapes honored).
41
- function parseCsv(text) {
42
- const rows = [];
43
- let field = "";
44
- let record = [];
45
- let inQuotes = false;
46
- for (let i = 0; i < text.length; i++) {
47
- const ch = text[i];
48
- if (inQuotes) {
49
- if (ch === '"') {
50
- if (text[i + 1] === '"') { field += '"'; i++; }
51
- else inQuotes = false;
52
- } else field += ch;
53
- } else if (ch === '"') inQuotes = true;
54
- else if (ch === ",") { record.push(field); field = ""; }
55
- else if (ch === "\n") { record.push(field); rows.push(record); record = []; field = ""; }
56
- else if (ch === "\r") { /* skip */ }
57
- else field += ch;
58
- }
59
- if (field.length > 0 || record.length > 0) { record.push(field); rows.push(record); }
60
- return rows;
61
- }
62
-
63
- // Split a rule id into its {prefix, num} parts, or null when it is not a well-formed anchor id.
64
- function splitId(id) {
65
- const m = /^([a-z]+)-(\d{2})$/.exec(id);
66
- return m ? { prefix: m[1], num: parseInt(m[2], 10) } : null;
67
- }
68
-
69
- // Strip leading whitespace and a single markdown list marker from a line.
70
- function stripListMarker(line) {
71
- return line.replace(/^\s*/, "").replace(/^[-*+]\s+/, "");
72
- }
73
-
74
- // Load and index the rule catalog into typed row objects plus derived counts.
75
- function loadCatalog() {
76
- const text = readSafe(CATALOG_CSV);
77
- if (text === null) throw new Error("rules.csv not found at " + CATALOG_CSV);
78
- const raw = parseCsv(text).filter((r) => r.length > 1 || (r.length === 1 && r[0].trim() !== ""));
79
- const header = raw[0];
80
- const dataRows = raw.slice(1).map((cells) => {
81
- const obj = {};
82
- CSV_HEADER.forEach((k, idx) => { obj[k] = cells[idx] !== undefined ? cells[idx] : ""; });
83
- obj._cells = cells;
84
- return obj;
85
- });
86
- return { header, rows: dataRows };
87
- }
88
-
89
- // ── Check 1: rules.csv is well-formed ──────────────────────────────────────────
90
- function checkCsvWellFormed(catalog) {
91
- const errors = [];
92
- const { header, rows } = catalog;
93
-
94
- if (header.length !== CSV_HEADER.length || CSV_HEADER.some((h, i) => header[i] !== h))
95
- errors.push(`header mismatch: expected [${CSV_HEADER.join(",")}] got [${header.join(",")}]`);
96
-
97
- const seen = new Map();
98
- const byPrefix = new Map();
99
- for (const row of rows) {
100
- if (row._cells.length !== CSV_HEADER.length)
101
- errors.push(`${row.id || "?"}: has ${row._cells.length} columns, expected ${CSV_HEADER.length}`);
102
-
103
- const parts = splitId(row.id);
104
- if (!parts) { errors.push(`malformed id "${row.id}" (want <prefix>-NN)`); }
105
- else {
106
- if (seen.has(row.id)) errors.push(`duplicate id ${row.id}`);
107
- seen.set(row.id, true);
108
- if (!byPrefix.has(parts.prefix)) byPrefix.set(parts.prefix, []);
109
- byPrefix.get(parts.prefix).push(parts.num);
110
- }
111
-
112
- if (!VALID_DIMENSIONS.has(row.dimension))
113
- errors.push(`${row.id}: invalid dimension "${row.dimension}"`);
114
-
115
- // grade/detector/fixture_pair invariants
116
- if (row.detector === "source" && row.fixture_pair !== "yes")
117
- errors.push(`${row.id}: detector=source must have fixture_pair=yes (got "${row.fixture_pair}")`);
118
- if (row.grade === "judged" && !(row.detector === "none" || row.detector === "render"))
119
- errors.push(`${row.id}: grade=judged must have detector none|render (got "${row.detector}")`);
120
- if (row.grade === "procedure" && row.detector !== "procedure")
121
- errors.push(`${row.id}: grade=procedure must have detector=procedure (got "${row.detector}")`);
122
- if (!["machine", "judged", "procedure"].includes(row.grade))
123
- errors.push(`${row.id}: invalid grade "${row.grade}"`);
124
- if (!["source", "render", "procedure", "none"].includes(row.detector))
125
- errors.push(`${row.id}: invalid detector "${row.detector}"`);
126
- if (!["yes", "na"].includes(row.fixture_pair))
127
- errors.push(`${row.id}: invalid fixture_pair "${row.fixture_pair}"`);
128
- }
129
-
130
- // Contiguous numbering per prefix: 1..N with no gaps, no duplicates.
131
- for (const [prefix, nums] of byPrefix) {
132
- const sorted = [...nums].sort((a, b) => a - b);
133
- for (let i = 0; i < sorted.length; i++) {
134
- if (sorted[i] !== i + 1) {
135
- errors.push(`${prefix}-* numbering not contiguous: expected ${i + 1} at position ${i}, got ${sorted[i]} (full: ${sorted.join(",")})`);
136
- break;
137
- }
138
- }
139
- }
140
-
141
- return { name: "rules.csv well-formed", pass: errors.length === 0, detail: errors.length ? `${errors.length} issue(s)` : `${rows.length} rows, ${byPrefix.size} prefixes`, errors };
142
- }
143
-
144
- // ── Check 2: anchor parity between rules.csv and hard-rules.md ──────────────────
145
- function checkAnchorParity(catalog) {
146
- const errors = [];
147
- const md = readSafe(HARD_RULES_MD);
148
- if (md === null) return { name: "anchor parity (prose<->catalog)", pass: false, detail: "hard-rules.md missing", errors: ["hard-rules.md not found at " + HARD_RULES_MD] };
149
-
150
- const lines = md.split("\n");
151
- const defCounts = new Map(); // id -> { main, judged }
152
- const rangeCovered = new Set();
153
- const allBacktickIds = new Set();
154
- const judgedHeader = /^##\s+judged dimensions/i;
155
- let inJudged = false;
156
-
157
- const bump = (id, section) => {
158
- if (!defCounts.has(id)) defCounts.set(id, { main: 0, judged: 0 });
159
- defCounts.get(id)[section]++;
160
- };
161
-
162
- for (const line of lines) {
163
- if (judgedHeader.test(line.trim())) inJudged = true;
164
-
165
- let m;
166
- ANCHOR_TOKEN.lastIndex = 0;
167
- while ((m = ANCHOR_TOKEN.exec(line)) !== null) allBacktickIds.add(`${m[1]}-${m[2]}`);
168
-
169
- const body = stripListMarker(line);
170
- const rangeMatch = new RegExp("^`(" + ANCHOR_ID + ")`\\s*[\\u2013\\u2014-]\\s*`(" + ANCHOR_ID + ")`").exec(body);
171
- const defMatch = new RegExp("^`(" + ANCHOR_ID + ")`").exec(body);
172
-
173
- if (rangeMatch) {
174
- const a = splitId(rangeMatch[1]);
175
- const b = splitId(rangeMatch[2]);
176
- if (a && b && a.prefix === b.prefix) for (let n = a.num; n <= b.num; n++) rangeCovered.add(`${a.prefix}-${String(n).padStart(2, "0")}`);
177
- }
178
- if (defMatch) bump(defMatch[1], inJudged ? "judged" : "main");
179
- }
180
-
181
- const csvIds = new Set(catalog.rows.map((r) => r.id));
182
- const proseCovered = new Set([...rangeCovered, ...defCounts.keys()]);
183
-
184
- // No prose anchor without a csv row.
185
- for (const id of allBacktickIds)
186
- if (!csvIds.has(id)) errors.push(`prose anchor ${id} has no rules.csv row`);
187
-
188
- for (const row of catalog.rows) {
189
- const c = defCounts.get(row.id) || { main: 0, judged: 0 };
190
- const total = c.main + c.judged;
191
- const isInstTrust = row.id.startsWith("inst-") || row.id.startsWith("trust-");
192
-
193
- if (row.grade === "machine" || row.grade === "procedure") {
194
- if (c.main === 1 && c.judged === 0) { /* ok */ }
195
- else if (total === 0) errors.push(`${row.grade} rule ${row.id} has no backticked definition line in hard-rules.md`);
196
- else if (total > 1) errors.push(`${row.id} defined ${total} times (want exactly 1)`);
197
- else if (c.judged > 0) errors.push(`${row.grade} rule ${row.id} is defined inside the Judged dimensions section`);
198
- } else if (row.grade === "judged" && isInstTrust) {
199
- if (!rangeCovered.has(row.id) && total === 0)
200
- errors.push(`judged range rule ${row.id} not covered by a range pointer line`);
201
- } else if (row.grade === "judged") {
202
- if (c.judged === 1 && c.main === 0) { /* ok */ }
203
- else if (total === 0) errors.push(`judged rule ${row.id} missing from the Judged dimensions index`);
204
- else if (c.main > 0) errors.push(`judged rule ${row.id} defined outside the Judged dimensions section`);
205
- else if (c.judged > 1) errors.push(`judged rule ${row.id} indexed ${c.judged} times (want exactly 1)`);
206
- }
207
-
208
- if (!proseCovered.has(row.id)) errors.push(`rules.csv row ${row.id} has no prose coverage`);
209
- }
210
-
211
- // The two collapsed range pointers must be present and complete.
212
- for (let n = 1; n <= 11; n++) if (!rangeCovered.has(`inst-${String(n).padStart(2, "0")}`)) errors.push(`inst-${String(n).padStart(2, "0")} not covered by the inst range pointer`);
213
- for (let n = 1; n <= 4; n++) if (!rangeCovered.has(`trust-0${n}`)) errors.push(`trust-0${n} not covered by the trust range pointer`);
214
-
215
- const defTotal = [...defCounts.keys()].length;
216
- return { name: "anchor parity (prose<->catalog)", pass: errors.length === 0, detail: errors.length ? `${errors.length} parity break(s)` : `${defTotal} definitions, ${rangeCovered.size} range-covered, all ${catalog.rows.length} rows covered`, errors };
217
- }
218
-
219
- // ── Check 3: every fixture_pair=yes rule ships a flag + pass fixture ────────────
220
- function checkFixturePresence(catalog) {
221
- const errors = [];
222
- const files = existsSync(FIXTURES_DIR) ? readdirSync(FIXTURES_DIR) : null;
223
- if (files === null) {
224
- const needed = catalog.rows.filter((r) => r.fixture_pair === "yes");
225
- return { name: "fixture-pair presence", pass: false, detail: `fixtures dir missing; ${needed.length} pairs needed`, errors: ["data/catalog/fixtures/ does not exist"] };
226
- }
227
- const present = new Set(files);
228
- const hasKind = (id, kind) => [...present].some((f) => f.startsWith(`${id}.${kind}.`));
229
- let ok = 0;
230
- for (const row of catalog.rows) {
231
- if (row.fixture_pair !== "yes") continue;
232
- const hasFlag = hasKind(row.id, "flag");
233
- const hasPass = hasKind(row.id, "pass");
234
- if (!hasFlag) errors.push(`${row.id}: missing ${row.id}.flag.*`);
235
- if (!hasPass) errors.push(`${row.id}: missing ${row.id}.pass.*`);
236
- if (hasFlag && hasPass) ok++;
237
- }
238
- const total = catalog.rows.filter((r) => r.fixture_pair === "yes").length;
239
- return { name: "fixture-pair presence", pass: errors.length === 0, detail: `${ok}/${total} pairs present`, errors };
240
- }
241
-
242
- // Run the check engine (lib/checks.mjs) on one fixture file and return the set of anchor ids it reports.
243
- function runEngine(file) {
244
- // Scan the leading comment block for a `// detector-args:` directive (the mandatory file-path
245
- // comment occupies line 1, so the directive cannot be line 0). Relative paths in it (e.g. a
246
- // --manifest sibling) resolve against FIXTURES_DIR, matching each fixture's documented verify command.
247
- let extra = [];
248
- for (const line of (readSafe(file) || "").split("\n")) {
249
- const t = line.trim();
250
- if (t !== "" && !t.startsWith("//")) break;
251
- const argMatch = /^\/\/\s*detector-args:\s*(.+)$/.exec(t);
252
- if (argMatch) { extra = argMatch[1].trim().split(/\s+/); break; }
253
- }
254
- let manifestPath = null;
255
- const extraFiles = [];
256
- for (let i = 0; i < extra.length; i++) {
257
- const a = extra[i];
258
- if (a === "--manifest") manifestPath = resolve(FIXTURES_DIR, extra[++i] || "");
259
- else if (a.startsWith("--manifest=")) manifestPath = resolve(FIXTURES_DIR, a.slice("--manifest=".length));
260
- else if (!a.startsWith("--")) extraFiles.push(resolve(FIXTURES_DIR, a));
261
- }
262
- try {
263
- const findings = runChecks([file, ...extraFiles], { manifestPath });
264
- return { ids: new Set(findings.map((f) => f.rule)) };
265
- } catch (e) {
266
- return { ids: new Set(), error: String(e) };
267
- }
268
- }
269
-
270
- // ── Check 4: contrastive validity — flag fires the rule, pass does not ──────────
271
- function checkContrastiveValidity(catalog, onlyId = null) {
272
- const errors = [];
273
- if (!existsSync(FIXTURES_DIR)) return { name: "contrastive fixture validity", pass: false, detail: "fixtures dir missing", errors: ["data/catalog/fixtures/ does not exist"] };
274
- const files = readdirSync(FIXTURES_DIR);
275
- const findFile = (id, kind) => files.find((f) => f.startsWith(`${id}.${kind}.`));
276
- let checked = 0;
277
- for (const row of catalog.rows) {
278
- if (row.fixture_pair !== "yes") continue;
279
- if (onlyId && row.id !== onlyId) continue;
280
- const flag = findFile(row.id, "flag");
281
- const pass = findFile(row.id, "pass");
282
- if (!flag || !pass) continue; // absence is check 3's job
283
- checked++;
284
- const flagRes = runEngine(join(FIXTURES_DIR, flag));
285
- if (flagRes.error) { errors.push(`${row.id}: check engine threw on flag (${flagRes.error})`); continue; }
286
- if (!flagRes.ids.has(row.id)) errors.push(`${row.id}: flag fixture did not report ${row.id} (reported: ${[...flagRes.ids].join(",") || "none"})`);
287
- const passRes = runEngine(join(FIXTURES_DIR, pass));
288
- if (passRes.error) { errors.push(`${row.id}: check engine threw on pass (${passRes.error})`); continue; }
289
- if (passRes.ids.has(row.id)) errors.push(`${row.id}: pass fixture wrongly reported ${row.id}`);
290
- }
291
- return { name: "contrastive fixture validity", pass: errors.length === 0, detail: `${checked} pair(s) exercised`, errors };
292
- }
293
-
294
- // Recursively collect prose/data files (.md/.csv/.tsx/.json) under a dir for the floor-citation scan.
295
- function walkTextFiles(dir, acc = []) {
296
- if (!existsSync(dir)) return acc;
297
- for (const ent of readdirSync(dir, { withFileTypes: true })) {
298
- if (ent.name.startsWith(".") || ent.name === "node_modules") continue;
299
- const full = join(dir, ent.name);
300
- if (ent.isDirectory()) walkTextFiles(full, acc);
301
- else if (/\.(md|csv|tsx|json)$/.test(ent.name)) acc.push(full);
302
- }
303
- return acc;
304
- }
305
-
306
- // ── Check 2b: doctrine-floor anchor parity (f-ids) ─────────────────────────────
307
- // Same mechanism as rule-id parity: hard-rules.md's Doctrine floor section is the canonical
308
- // enumeration (exactly f01-f12, once each); every f-id cited anywhere in the skill's prose/data
309
- // names an enumerated id, and the retired "floor P<n>" numbering is gone.
310
- function checkFloorParity() {
311
- const errors = [];
312
- const md = readSafe(HARD_RULES_MD);
313
- if (md === null) return { name: "floor parity (f-ids)", pass: false, detail: "hard-rules.md missing", errors: ["hard-rules.md not found at " + HARD_RULES_MD] };
314
-
315
- const section = /^##\s+Doctrine floor\s*$([\s\S]*?)(?=^##\s)/m.exec(md);
316
- const enumerated = new Map();
317
- if (!section) errors.push('hard-rules.md has no "## Doctrine floor" section (the canonical f01-f12 enumeration)');
318
- else {
319
- for (const m of section[1].matchAll(/`(f\d{2})`/g)) enumerated.set(m[1], (enumerated.get(m[1]) || 0) + 1);
320
- for (const id of FLOOR_IDS) {
321
- const n = enumerated.get(id) || 0;
322
- if (n === 0) errors.push(`doctrine floor enumeration is missing ${id}`);
323
- else if (n > 1) errors.push(`${id} enumerated ${n} times (want exactly 1)`);
324
- }
325
- for (const id of enumerated.keys()) if (!FLOOR_IDS.includes(id)) errors.push(`enumeration carries unknown floor id ${id} (legal: f01-f12)`);
326
- }
327
-
328
- const targets = [join(SKILL_ROOT, "SKILL.md"), ...walkTextFiles(join(SKILL_ROOT, "references")), ...walkTextFiles(join(SKILL_ROOT, "data"))];
329
- let cited = 0;
330
- for (const file of targets) {
331
- const text = readSafe(file);
332
- if (text === null) continue;
333
- const rel = file.replace(SKILL_ROOT + "/", "");
334
- text.split("\n").forEach((line, i) => {
335
- for (const m of line.matchAll(/(?:\bfloor\s+|[(`/]\s?)(f\d{2})\b/g)) {
336
- cited++;
337
- if (!FLOOR_IDS.includes(m[1])) errors.push(`${rel}:${i + 1}: cites unknown floor id ${m[1]} (legal: f01-f12)`);
338
- }
339
- const stale = /\bfloor\s+P\d+\b/.exec(line);
340
- if (stale) errors.push(`${rel}:${i + 1}: retired P-numbered floor citation "${stale[0]}" — rename to its f-id (05-rule-amendments.md mapping)`);
341
- });
342
- }
343
- return { name: "floor parity (f-ids)", pass: errors.length === 0, detail: errors.length ? `${errors.length} parity break(s)` : `${enumerated.size} enumerated, ${cited} citation(s) checked`, errors };
344
- }
345
-
346
- const NUMBER_WORDS = { one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7, eight: 8, nine: 9, ten: 10, eleven: 11, twelve: 12, thirteen: 13, fourteen: 14, fifteen: 15, sixteen: 16, seventeen: 17, eighteen: 18, nineteen: 19, twenty: 20, "twenty-six": 26 };
347
-
348
- // Resolve a numeric token (digits or an English number word) to a number, or NaN.
349
- function toNumber(tok) {
350
- if (/^\d+$/.test(tok)) return parseInt(tok, 10);
351
- return NUMBER_WORDS[tok.toLowerCase()] ?? NaN;
352
- }
353
-
354
- // ── Check 5: stated counts in prose match the ground truth ─────────────────────
355
- function checkStatedCounts(catalog, ground) {
356
- const errors = [];
357
- // Ground truth drift guard: derived counts (CSV rows; the token surface counted off the Nurix
358
- // default artifact) must match the pinned numbers.
359
- if (ground.rows !== PINNED.rows) errors.push(`derived row count ${ground.rows} != pinned ${PINNED.rows}`);
360
- if (ground.source !== PINNED.source) errors.push(`derived source count ${ground.source} != pinned ${PINNED.source}`);
361
- if (ground.render !== PINNED.render) errors.push(`derived machine-render count ${ground.render} != pinned ${PINNED.render}`);
362
- if (ground.primitives !== null && ground.primitives !== PINNED.primitives) errors.push(`derived primitive count ${ground.primitives} != pinned ${PINNED.primitives}`);
363
- if (ground.colorTokens !== null && ground.colorTokens !== PINNED.colorTokens) errors.push(`derived color-token count ${ground.colorTokens} != pinned ${PINNED.colorTokens}`);
364
- if (ground.rampSteps !== null && ground.rampSteps !== PINNED.rampSteps) errors.push(`derived ramp-step count ${ground.rampSteps} != pinned ${PINNED.rampSteps}`);
365
- if (ground.elevation !== null && ground.elevation !== PINNED.elevation) errors.push(`derived elevation count ${ground.elevation} != pinned ${PINNED.elevation}`);
366
-
367
- const gtMap = {
368
- rules: ground.rows, rule: ground.rows, rows: ground.rows, row: ground.rows,
369
- source: ground.source, render: ground.render,
370
- archetypes: PINNED.archetypes, archetype: PINNED.archetypes,
371
- primitives: PINNED.primitives, primitive: PINNED.primitives,
372
- "color-tokens": PINNED.colorTokens, "color tokens": PINNED.colorTokens, colortokens: PINNED.colorTokens,
373
- "semantic-tokens": PINNED.semanticTokens, "substrate-tokens": PINNED.substrateTokens,
374
- "ramp-steps": PINNED.rampSteps, rampsteps: PINNED.rampSteps, elevation: PINNED.elevation,
375
- };
376
-
377
- const targets = [join(SKILL_ROOT, "SKILL.md"), ...(existsSync(join(SKILL_ROOT, "references")) ? readdirSync(join(SKILL_ROOT, "references")).filter((f) => f.endsWith(".md")).map((f) => join(SKILL_ROOT, "references", f)) : [])];
378
- let commentClaims = 0;
379
- let bareClaims = 0;
380
- for (const file of targets) {
381
- const text = readSafe(file);
382
- if (text === null) continue;
383
- const rel = file.replace(SKILL_ROOT + "/", "");
384
- const linesArr = text.split("\n");
385
- linesArr.forEach((line, i) => {
386
- // (a) machine-readable HTML comment claims: <!-- count:<name>=<n> -->
387
- const cmt = /<!--\s*count:([a-z0-9 _-]+)=(\d+)\s*-->/gi;
388
- let cm;
389
- while ((cm = cmt.exec(line)) !== null) {
390
- commentClaims++;
391
- const name = cm[1].trim().toLowerCase().replace(/\s+/g, "-");
392
- const val = parseInt(cm[2], 10);
393
- const expected = gtMap[name] ?? gtMap[name.replace(/-/g, " ")];
394
- if (expected === undefined) errors.push(`${rel}:${i + 1}: count comment names unknown quantity "${cm[1].trim()}"`);
395
- else if (expected !== val) errors.push(`${rel}:${i + 1}: count:${cm[1].trim()}=${val} but ground truth is ${expected}`);
396
- }
397
- // (b) bare claims of the exact named forms. Require adjacency (number immediately
398
- // before the noun) so qualified subset phrases ("24 static primitives", "one layout
399
- // primitive") are not misread as grand-total claims.
400
- const bare = /\b(\d+|[a-z]+)\s+(rules?|archetypes?|primitives?)\b/gi;
401
- let bm;
402
- while ((bm = bare.exec(line)) !== null) {
403
- const n = toNumber(bm[1]);
404
- if (Number.isNaN(n)) continue;
405
- const key = bm[2].toLowerCase();
406
- const expected = gtMap[key];
407
- if (expected === undefined) continue;
408
- bareClaims++;
409
- if (n !== expected) errors.push(`${rel}:${i + 1}: bare claim "${bm[0].trim()}" (=${n}) contradicts ground truth ${expected}`);
410
- }
411
- });
412
- }
413
- return { name: "stated-count integrity", pass: errors.length === 0, detail: `${commentClaims} comment + ${bareClaims} bare claim(s) checked`, errors };
414
- }
415
-
416
- // ── Check 6: every brief-pinned path exists ────────────────────────────────────
417
- function checkFileTree() {
418
- const errors = [];
419
- const files = [
420
- "SKILL.md",
421
- "references/hard-rules.md", "references/create.md", "references/improve.md", "references/introspect.md",
422
- "references/diagnosis.md", "references/structure.md", "references/personality.md", "references/interaction.md", "references/lifecycle.md",
423
- "data/catalog/rules.csv",
424
- "data/catalog/fixtures/cod-02.manifest.tokens.json",
425
- "data/design-md/SCHEMA.md", "data/design-md/nurix.md",
426
- "data/operator-pack/surface-catalog.md", "data/operator-pack/fixtures.md", "data/operator-pack/trust-rubric.md",
427
- "data/operator-pack/exemplars/list-detail.tsx", "data/operator-pack/exemplars/dashboard.tsx",
428
- "data/operator-pack/exemplars/entity-detail.tsx", "data/operator-pack/exemplars/create-edit.tsx",
429
- "data/operator-pack/exemplars/log-stream.tsx", "data/operator-pack/exemplars/command-center.tsx",
430
- "scripts/lib/checks.mjs", "scripts/phase-gate.mjs", "scripts/preship-sweep.mjs", "scripts/render-rung.mjs",
431
- "scripts/scaffold.mjs", "scripts/derive-personality.mjs", "scripts/generate-fixtures.mjs",
432
- "scripts/self-integrity.mjs",
433
- ];
434
- for (const rel of files) if (!existsSync(join(SKILL_ROOT, rel))) errors.push(`missing ${rel}`);
435
-
436
- const dirs = ["data/catalog/fixtures", "data/design-md/library"];
437
- for (const rel of dirs) {
438
- const abs = join(SKILL_ROOT, rel);
439
- if (!existsSync(abs)) errors.push(`missing dir ${rel}/`);
440
- else if (readdirSync(abs).length === 0) errors.push(`empty dir ${rel}/`);
441
- }
442
- const found = files.length - errors.filter((e) => e.startsWith("missing ")).length;
443
- return { name: "file-tree presence", pass: errors.length === 0, detail: `${found}/${files.length} files present`, errors };
444
- }
445
-
446
- // Every artifact directory under data/design-tokens/ (a directory holding design.tokens.json), sorted by slug.
447
- function listArtifactSlugs() {
448
- if (!existsSync(TOKENS_DIR)) return [];
449
- return readdirSync(TOKENS_DIR, { withFileTypes: true })
450
- .filter((d) => d.isDirectory() && existsSync(join(TOKENS_DIR, d.name, "design.tokens.json")))
451
- .map((d) => d.name)
452
- .sort();
453
- }
454
-
455
- // Parse goldens.json into its entry slugs (every key except "_meta"), or null when absent/unparseable.
456
- function readGoldenSlugs() {
457
- const text = readSafe(GOLDENS_JSON);
458
- if (text === null) return null;
459
- try { return Object.keys(JSON.parse(text)).filter((k) => k !== "_meta").sort(); }
460
- catch { return null; }
461
- }
462
-
463
- // Run an async worker over items with at most `limit` in flight; results keep item order.
464
- async function runPool(items, limit, worker) {
465
- const results = new Array(items.length);
466
- let next = 0;
467
- const lane = async () => {
468
- while (next < items.length) {
469
- const i = next++;
470
- results[i] = await worker(items[i], i);
471
- }
472
- };
473
- await Promise.all(Array.from({ length: Math.min(limit, items.length) || 1 }, lane));
474
- return results;
475
- }
476
-
477
- // Spawn `node <args>` and resolve with { status, stdout, stderr } (never rejects; a spawn error surfaces as status -1).
478
- function execNode(args) {
479
- return new Promise((resolveExec) => {
480
- const child = spawn(process.execPath, args, { stdio: ["ignore", "pipe", "pipe"] });
481
- let stdout = "";
482
- let stderr = "";
483
- child.stdout.on("data", (d) => { stdout += d; });
484
- child.stderr.on("data", (d) => { stderr += d; });
485
- child.on("error", (e) => resolveExec({ status: -1, stdout, stderr: stderr + String(e) }));
486
- child.on("close", (status) => resolveExec({ status, stdout, stderr }));
487
- });
488
- }
489
-
490
- // First non-empty line of a child process's output, for one-line error reporting.
491
- function firstLine(text) {
492
- return (text || "").split("\n").find((l) => l.trim() !== "") || "(no output)";
493
- }
494
-
495
- // ── Check 7: token-era file tree + goldens<->artifact parity ───────────────────
496
- function checkTokenFileTree() {
497
- const errors = [];
498
- const pins = [
499
- "data/design-tokens/SCHEMA.md",
500
- "data/design-tokens/goldens.json",
501
- "scripts/convert-design-md.mjs",
502
- "scripts/snapshot-goldens.mjs",
503
- "scripts/lib/golden.mjs",
504
- ];
505
- for (const rel of pins) if (!existsSync(join(SKILL_ROOT, rel))) errors.push(`missing ${rel}`);
506
- const pinsFound = pins.length - errors.length;
507
-
508
- const diskSlugs = listArtifactSlugs();
509
- const goldenSlugs = readGoldenSlugs();
510
- if (goldenSlugs === null) {
511
- errors.push("goldens.json missing or does not parse as JSON");
512
- } else {
513
- const goldenSet = new Set(goldenSlugs);
514
- for (const slug of goldenSlugs) {
515
- if (!existsSync(join(TOKENS_DIR, slug, "design.tokens.json")))
516
- errors.push(`goldens.json entry "${slug}" has no data/design-tokens/${slug}/design.tokens.json on disk`);
517
- else if (!existsSync(join(TOKENS_DIR, slug, "design.resolver.json")))
518
- errors.push(`goldens.json entry "${slug}": data/design-tokens/${slug}/ is missing design.resolver.json`);
519
- }
520
- for (const slug of diskSlugs) {
521
- if (!goldenSet.has(slug)) errors.push(`artifact dir data/design-tokens/${slug}/ has no goldens.json entry`);
522
- else if (!existsSync(join(TOKENS_DIR, slug, "design.resolver.json")) && !errors.some((e) => e.includes(`"${slug}"`)))
523
- errors.push(`artifact dir data/design-tokens/${slug}/ is missing design.resolver.json`);
524
- }
525
- }
526
- const goldenCount = goldenSlugs === null ? 0 : goldenSlugs.length;
527
- return { name: "token file-tree + goldens parity", pass: errors.length === 0, detail: errors.length ? `${errors.length} issue(s)` : `${pinsFound}/${pins.length} pins, goldens<->artifacts ${goldenCount}<->${diskSlugs.length}`, errors };
528
- }
529
-
530
- // ── Check 8: every design-tokens artifact passes derive-personality --check ────
531
- async function checkArtifactValidity() {
532
- const slugs = listArtifactSlugs();
533
- if (slugs.length === 0) return { name: "artifact validity (--check)", pass: false, detail: "no artifact dirs found", errors: [`no design.tokens.json dirs under ${TOKENS_DIR}`] };
534
- const runs = await runPool(slugs, SPAWN_LIMIT, (slug) => execNode([DERIVE_PERSONALITY, join(TOKENS_DIR, slug), "--check"]));
535
- const errors = [];
536
- runs.forEach((res, i) => {
537
- if (res.status !== 0) errors.push(`${slugs[i]}: --check exited ${res.status}: ${firstLine(res.stderr || res.stdout)}`);
538
- });
539
- return { name: "artifact validity (--check)", pass: errors.length === 0, detail: `${slugs.length - errors.length}/${slugs.length} artifacts pass --check`, errors };
540
- }
541
-
542
- // ── Check 9: emitted CSS hashes match goldens.json (slow; gated behind --goldens) ──
543
- async function checkGoldenMatch(enabled) {
544
- if (!enabled) return { name: "golden emission match", pass: true, skip: true, detail: "skipped (slow) — run with --goldens to verify emitted hashes against goldens.json", errors: [] };
545
- const goldenSlugs = readGoldenSlugs();
546
- if (goldenSlugs === null) return { name: "golden emission match", pass: false, detail: "goldens.json missing/unparseable", errors: ["goldens.json missing or does not parse as JSON"] };
547
- const goldens = JSON.parse(readSafe(GOLDENS_JSON));
548
- const emitRoot = mkdtempSync(join(tmpdir(), "design-self-integrity-"));
549
- let matched = 0;
550
- const errors = [];
551
- try {
552
- // Each worker returns its slug's error list; flattening after the pool keeps report order deterministic.
553
- const perSlug = await runPool(goldenSlugs, SPAWN_LIMIT, async (slug) => {
554
- const slugErrors = [];
555
- const outdir = join(emitRoot, slug);
556
- const res = await execNode([DERIVE_PERSONALITY, join(TOKENS_DIR, slug), "--emit", outdir, "--provisional"]);
557
- if (res.status !== 0) {
558
- slugErrors.push(`${slug}: --emit exited ${res.status}: ${firstLine(res.stderr || res.stdout)}`);
559
- return slugErrors;
560
- }
561
- for (const [key, fileName] of [["personality", "personality.css"], ["globals", "globals.css"]]) {
562
- const css = readSafe(join(outdir, "src/styles", fileName));
563
- if (css === null) { slugErrors.push(`${slug}: emit produced no src/styles/${fileName}`); continue; }
564
- const actual = goldenHash(css);
565
- const expected = goldens[slug] && goldens[slug][key];
566
- if (actual === expected) matched++;
567
- else slugErrors.push(`${slug}: ${fileName} hash ${actual} != golden ${expected ?? "(missing key)"}`);
568
- }
569
- return slugErrors;
570
- });
571
- for (const slugErrors of perSlug) errors.push(...slugErrors);
572
- } finally {
573
- rmSync(emitRoot, { recursive: true, force: true });
574
- }
575
- return { name: "golden emission match", pass: errors.length === 0, detail: `${matched}/${goldenSlugs.length * 2} hashes match goldens.json`, errors };
576
- }
577
-
578
- // Derive the ground-truth counts: rule counts from the catalog itself; the token-surface counts
579
- // (primitives, color roles, ramp steps, elevation levels) from the Nurix default artifact, the
580
- // schema's worked example. null when the artifact is unreadable (check 8 reports that separately).
581
- function deriveGround(catalog) {
582
- const ground = {
583
- rows: catalog.rows.length,
584
- source: catalog.rows.filter((r) => r.detector === "source").length,
585
- render: catalog.rows.filter((r) => r.detector === "render" && r.grade === "machine").length,
586
- primitives: null, colorTokens: null, rampSteps: null, elevation: null,
587
- };
588
- try {
589
- const nurix = JSON.parse(readFileSync(join(TOKENS_DIR, "nurix", "design.tokens.json"), "utf8"));
590
- const count = (group) => Object.keys(group || {}).filter((k) => !k.startsWith("$")).length;
591
- ground.primitives = count(nurix.primitive);
592
- ground.colorTokens = count(nurix.color);
593
- ground.rampSteps = count(nurix.typography && nurix.typography.ramp);
594
- ground.elevation = count(nurix.elevation);
595
- } catch { /* artifact validity is check 8's job */ }
596
- return ground;
597
- }
598
-
599
- // Run one rule's contrastive fixture pair through the check engine and exit 0/1 on its result.
600
- function runSingleFixture(catalog, ruleId) {
601
- const row = catalog.rows.find((r) => r.id === ruleId);
602
- if (!row) { console.error(`--fixture: no rules.csv row with id "${ruleId}"`); process.exit(2); }
603
- if (row.fixture_pair !== "yes") { console.error(`--fixture: ${ruleId} has fixture_pair=${row.fixture_pair}; no contrastive pair to run`); process.exit(2); }
604
- const r = checkContrastiveValidity(catalog, ruleId);
605
- if (r.errors.length === 0 && r.detail.startsWith("0 ")) {
606
- console.error(`--fixture: ${ruleId}.flag.* / ${ruleId}.pass.* not found in data/catalog/fixtures/`);
607
- process.exit(2);
608
- }
609
- if (r.pass) { console.log(`PASS fixture pair ${ruleId} — flag reports ${ruleId}, pass reports zero.`); process.exit(0); }
610
- console.error(`FAIL fixture pair ${ruleId}`);
611
- for (const e of r.errors) console.error(` - ${e}`);
612
- process.exit(1);
613
- }
614
-
615
- // Run every check, print the summary table, and exit non-zero on any failure.
616
- async function main() {
617
- const args = process.argv.slice(2);
618
- let fixtureId = null;
619
- let runGoldens = false;
620
- for (let i = 0; i < args.length; i++) {
621
- if (args[i] === "--fixture") fixtureId = args[++i] || null;
622
- else if (args[i].startsWith("--fixture=")) fixtureId = args[i].slice("--fixture=".length);
623
- else if (args[i] === "--goldens") runGoldens = true;
624
- }
625
-
626
- const results = [];
627
- let catalog = null;
628
- try { catalog = loadCatalog(); } catch (e) {
629
- console.error("FATAL: " + e.message);
630
- process.exit(2);
631
- }
632
-
633
- if (fixtureId) runSingleFixture(catalog, fixtureId);
634
-
635
- const ground = deriveGround(catalog);
636
-
637
- const runners = [
638
- () => checkCsvWellFormed(catalog),
639
- () => checkAnchorParity(catalog),
640
- () => checkFloorParity(),
641
- () => checkFixturePresence(catalog),
642
- () => checkContrastiveValidity(catalog),
643
- () => checkStatedCounts(catalog, ground),
644
- () => checkFileTree(),
645
- () => checkTokenFileTree(),
646
- () => checkArtifactValidity(),
647
- () => checkGoldenMatch(runGoldens),
648
- () => validateCombinations(COMBINATIONS_DIR),
649
- ];
650
- for (const run of runners) {
651
- try { results.push(await run()); }
652
- catch (e) { results.push({ name: run.name || "check", pass: false, detail: "threw", errors: [e.stack || String(e)] }); }
653
- }
654
-
655
- for (const r of results) {
656
- if (r.errors && r.errors.length) {
657
- console.log(`\n[${r.pass ? "PASS" : "FAIL"}] ${r.name}`);
658
- for (const e of r.errors) console.log(` - ${e}`);
659
- }
660
- }
661
-
662
- console.log("\n" + "=".repeat(60));
663
- console.log("self-integrity — design skill");
664
- console.log("=".repeat(60));
665
- const pad = (s, n) => (s + " ".repeat(n)).slice(0, n);
666
- for (const r of results) console.log(`${r.skip ? "SKIP" : r.pass ? "PASS" : "FAIL"} ${pad(r.name, 34)} ${r.detail}`);
667
- console.log("=".repeat(60));
668
-
669
- const failed = results.filter((r) => !r.pass);
670
- if (failed.length) { console.log(`${failed.length} check(s) failed.`); process.exit(1); }
671
- console.log("all checks passed.");
672
- process.exit(0);
673
- }
674
-
675
- main().catch((e) => { console.error("FATAL: " + (e.stack || String(e))); process.exit(2); });