@nurix/etna 0.19.11 → 0.19.13

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 (494) hide show
  1. package/README.md +6 -4
  2. package/data/harness-index.json +1 -1
  3. package/data/harnesses/code/agents/maintenance.md +1 -1
  4. package/data/harnesses/code/harness.json +1 -1
  5. package/data/harnesses/code/rules/frontend.md +5 -5
  6. package/data/harnesses/code/skills/design/SKILL.md +70 -50
  7. package/data/harnesses/code/skills/design/components/charts.md +76 -0
  8. package/data/harnesses/code/skills/design/components/collections.md +132 -0
  9. package/data/harnesses/code/skills/design/components/feedback.md +47 -0
  10. package/data/harnesses/code/skills/design/components/hooks.md +35 -0
  11. package/data/harnesses/code/skills/design/components/index.md +143 -0
  12. package/data/harnesses/code/skills/design/components/inputs.md +327 -0
  13. package/data/harnesses/code/skills/design/components/layout.md +52 -0
  14. package/data/harnesses/code/skills/design/components/media.md +66 -0
  15. package/data/harnesses/code/skills/design/components/motion.md +82 -0
  16. package/data/harnesses/code/skills/design/components/navigation.md +29 -0
  17. package/data/harnesses/code/skills/design/components/overlays.md +72 -0
  18. package/data/harnesses/code/skills/design/components/setup.md +40 -0
  19. package/data/harnesses/code/skills/design/components/typography.md +46 -0
  20. package/data/harnesses/code/skills/design/components/utils.md +37 -0
  21. package/data/harnesses/code/skills/design/data/blueprints/browse.md +38 -0
  22. package/data/harnesses/code/skills/design/data/blueprints/creation-flow.md +38 -0
  23. package/data/harnesses/code/skills/design/data/blueprints/dashboard.md +38 -0
  24. package/data/harnesses/code/skills/design/data/blueprints/grid.md +38 -0
  25. package/data/harnesses/code/skills/design/data/blueprints/queue.md +38 -0
  26. package/data/harnesses/code/skills/design/data/blueprints/record-detail.md +38 -0
  27. package/data/harnesses/code/skills/design/data/blueprints/settings.md +38 -0
  28. package/data/harnesses/code/skills/design/data/chart-styling/Readme.md +33 -0
  29. package/data/harnesses/code/skills/design/data/chart-styling/carbon-accessible-alert-semantic.md +19 -0
  30. package/data/harnesses/code/skills/design/data/chart-styling/carbon-monochrome-sequential-trend.md +19 -0
  31. package/data/harnesses/code/skills/design/data/chart-styling/datadog-classic-six-aligned.md +19 -0
  32. package/data/harnesses/code/skills/design/data/chart-styling/datawrapper-tiered-gray-hierarchy.md +19 -0
  33. package/data/harnesses/code/skills/design/data/chart-styling/econ-red-rule-horizontal.md +19 -0
  34. package/data/harnesses/code/skills/design/data/chart-styling/financial-diverging-threshold-overlay.md +19 -0
  35. package/data/harnesses/code/skills/design/data/chart-styling/ft-vocabulary-ranked-muted.md +19 -0
  36. package/data/harnesses/code/skills/design/data/chart-styling/grafana-dark-threshold-bands.md +19 -0
  37. package/data/harnesses/code/skills/design/data/chart-styling/material-rounded-explicit-label.md +19 -0
  38. package/data/harnesses/code/skills/design/data/chart-styling/nyt-ghost-grid-direct-label.md +19 -0
  39. package/data/harnesses/code/skills/design/data/chart-styling/plot-currentcolor-inherit.md +19 -0
  40. package/data/harnesses/code/skills/design/data/chart-styling/saas-gradient-glow-area.md +19 -0
  41. package/data/harnesses/code/skills/design/data/chart-styling/shadcn-composable-css-vars.md +19 -0
  42. package/data/harnesses/code/skills/design/data/charts/census.csv +58 -0
  43. package/data/harnesses/code/skills/design/data/checklists/browse.md +21 -0
  44. package/data/harnesses/code/skills/design/data/checklists/creation-flow.md +20 -0
  45. package/data/harnesses/code/skills/design/data/checklists/dashboard.md +21 -0
  46. package/data/harnesses/code/skills/design/data/checklists/grid.md +21 -0
  47. package/data/harnesses/code/skills/design/data/checklists/queue.md +21 -0
  48. package/data/harnesses/code/skills/design/data/checklists/record-detail.md +21 -0
  49. package/data/harnesses/code/skills/design/data/checklists/settings.md +21 -0
  50. package/data/harnesses/code/skills/design/data/chrome/board-column.md +68 -0
  51. package/data/harnesses/code/skills/design/data/chrome/data-table.md +63 -0
  52. package/data/harnesses/code/skills/design/data/chrome/side-panel.md +60 -0
  53. package/data/harnesses/code/skills/design/data/chrome/sidebar.md +78 -0
  54. package/data/harnesses/code/skills/design/data/chrome/stat-cards.md +62 -0
  55. package/data/harnesses/code/skills/design/data/chrome/topbar.md +65 -0
  56. package/data/harnesses/code/skills/design/data/color/accent-presets.md +90 -0
  57. package/data/harnesses/code/skills/design/data/color/aesop-earth-mute.md +91 -0
  58. package/data/harnesses/code/skills/design/data/color/arc-peach-play.md +90 -0
  59. package/data/harnesses/code/skills/design/data/color/attio-hunter-teal.md +90 -0
  60. package/data/harnesses/code/skills/design/data/color/carbon-cyan-signal.md +90 -0
  61. package/data/harnesses/code/skills/design/data/color/clay-parchment.md +90 -0
  62. package/data/harnesses/code/skills/design/data/color/duolingo-feather.md +90 -0
  63. package/data/harnesses/code/skills/design/data/color/geist-mono-signal.md +90 -0
  64. package/data/harnesses/code/skills/design/data/color/linear-graphite-violet.md +90 -0
  65. package/data/harnesses/code/skills/design/data/color/mercury-onyx-cobalt.md +90 -0
  66. package/data/harnesses/code/skills/design/data/color/notion-paper-ink.md +90 -0
  67. package/data/harnesses/code/skills/design/data/color/radix-slate-iris.md +90 -0
  68. package/data/harnesses/code/skills/design/data/color/raycast-void-spectrum.md +90 -0
  69. package/data/harnesses/code/skills/design/data/color/spectrum-celery-fuchsia.md +90 -0
  70. package/data/harnesses/code/skills/design/data/color/stripe-blurple-ruby.md +90 -0
  71. package/data/harnesses/code/skills/design/data/color/superhuman-cod-picton.md +89 -0
  72. package/data/harnesses/code/skills/design/data/corpora/operations-review/companies.csv +15 -0
  73. package/data/harnesses/code/skills/design/data/corpora/operations-review/corpus.md +87 -0
  74. package/data/harnesses/code/skills/design/data/corpora/operations-review/people.csv +25 -0
  75. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/companies.csv +15 -0
  76. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/corpus.md +83 -0
  77. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/people.csv +25 -0
  78. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/companies.csv +15 -0
  79. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/corpus.md +89 -0
  80. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/people.csv +25 -0
  81. package/data/harnesses/code/skills/design/data/elevation/ant-design-directional-shadow.md +19 -0
  82. package/data/harnesses/code/skills/design/data/elevation/apple-liquid-glass-material.md +18 -0
  83. package/data/harnesses/code/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +20 -0
  84. package/data/harnesses/code/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +20 -0
  85. package/data/harnesses/code/skills/design/data/elevation/github-primer-sparing-shadow.md +19 -0
  86. package/data/harnesses/code/skills/design/data/elevation/ibm-carbon-layer-and-border.md +19 -0
  87. package/data/harnesses/code/skills/design/data/elevation/linear-dark-surface-ladder.md +17 -0
  88. package/data/harnesses/code/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +19 -0
  89. package/data/harnesses/code/skills/design/data/elevation/material-3-tonal-elevation.md +21 -0
  90. package/data/harnesses/code/skills/design/data/elevation/neobrutalist-hard-offset.md +19 -0
  91. package/data/harnesses/code/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +18 -0
  92. package/data/harnesses/code/skills/design/data/elevation/notion-warm-minimal-hairline.md +17 -0
  93. package/data/harnesses/code/skills/design/data/elevation/polaris-elevation-inset-bevel.md +21 -0
  94. package/data/harnesses/code/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +19 -0
  95. package/data/harnesses/code/skills/design/data/elevation/shadcn-neutral-derived-radius.md +19 -0
  96. package/data/harnesses/code/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +18 -0
  97. package/data/harnesses/code/skills/design/data/elevation/tailwind-default-utility-scale.md +19 -0
  98. package/data/harnesses/code/skills/design/data/elevation/vercel-geist-shadow-as-border.md +20 -0
  99. package/data/harnesses/code/skills/design/data/gradients/amber-attention-fill.md +16 -0
  100. package/data/harnesses/code/skills/design/data/gradients/cloud-shadow-wash.md +16 -0
  101. package/data/harnesses/code/skills/design/data/gradients/confident-lavender-wash.md +16 -0
  102. package/data/harnesses/code/skills/design/data/gradients/ember-ship-flare.md +18 -0
  103. package/data/harnesses/code/skills/design/data/gradients/full-metal-wash.md +16 -0
  104. package/data/harnesses/code/skills/design/data/gradients/indigo-ruby-cta-band.md +18 -0
  105. package/data/harnesses/code/skills/design/data/gradients/linear-graphite-wash.md +18 -0
  106. package/data/harnesses/code/skills/design/data/gradients/marble-quartz-wash.md +16 -0
  107. package/data/harnesses/code/skills/design/data/gradients/midnight-aurora-panel.md +16 -0
  108. package/data/harnesses/code/skills/design/data/gradients/neutral-volume-fill.md +16 -0
  109. package/data/harnesses/code/skills/design/data/gradients/revenue-uptrend-fill.md +16 -0
  110. package/data/harnesses/code/skills/design/data/gradients/risk-decline-fill.md +16 -0
  111. package/data/harnesses/code/skills/design/data/gradients/signal-blue-develop.md +18 -0
  112. package/data/harnesses/code/skills/design/data/gradients/slate-mist-wash.md +16 -0
  113. package/data/harnesses/code/skills/design/data/gradients/stripe-atmosphere-mesh.md +18 -0
  114. package/data/harnesses/code/skills/design/data/gradients/teal-signal-accent.md +16 -0
  115. package/data/harnesses/code/skills/design/data/gradients/violet-magenta-promo.md +16 -0
  116. package/data/harnesses/code/skills/design/data/iconography.md +199 -0
  117. package/data/harnesses/code/skills/design/data/motion/accordion-expand.md +18 -0
  118. package/data/harnesses/code/skills/design/data/motion/destructive-hold-confirm.md +18 -0
  119. package/data/harnesses/code/skills/design/data/motion/drag-dismiss-momentum.md +18 -0
  120. package/data/harnesses/code/skills/design/data/motion/empty-state-arrive.md +18 -0
  121. package/data/harnesses/code/skills/design/data/motion/hover-lift.md +18 -0
  122. package/data/harnesses/code/skills/design/data/motion/modal-center-arrive.md +18 -0
  123. package/data/harnesses/code/skills/design/data/motion/number-ticker-roll.md +18 -0
  124. package/data/harnesses/code/skills/design/data/motion/onboarding-bounce.md +18 -0
  125. package/data/harnesses/code/skills/design/data/motion/panel-slide.md +18 -0
  126. package/data/harnesses/code/skills/design/data/motion/press-feedback.md +18 -0
  127. package/data/harnesses/code/skills/design/data/motion/progress-linear-loop.md +18 -0
  128. package/data/harnesses/code/skills/design/data/motion/route-crossfade.md +18 -0
  129. package/data/harnesses/code/skills/design/data/motion/rubber-band-overscroll.md +18 -0
  130. package/data/harnesses/code/skills/design/data/motion/skeleton-shimmer.md +18 -0
  131. package/data/harnesses/code/skills/design/data/motion/stagger-arrive.md +18 -0
  132. package/data/harnesses/code/skills/design/data/motion/toast-enter-stack.md +18 -0
  133. package/data/harnesses/code/skills/design/data/motion/tooltip-chain-instant.md +18 -0
  134. package/data/harnesses/code/skills/design/data/motion/trigger-anchored-reveal.md +18 -0
  135. package/data/harnesses/code/skills/design/data/tells.csv +34 -0
  136. package/data/harnesses/code/skills/design/data/typography/anton-work-sans.md +17 -0
  137. package/data/harnesses/code/skills/design/data/typography/archivo-black-archivo.md +17 -0
  138. package/data/harnesses/code/skills/design/data/typography/bitter-karla.md +17 -0
  139. package/data/harnesses/code/skills/design/data/typography/dm-serif-dm-sans.md +17 -0
  140. package/data/harnesses/code/skills/design/data/typography/fraunces-inter.md +17 -0
  141. package/data/harnesses/code/skills/design/data/typography/geist-geist-mono.md +17 -0
  142. package/data/harnesses/code/skills/design/data/typography/hubot-sans-mona-sans.md +17 -0
  143. package/data/harnesses/code/skills/design/data/typography/ibm-plex-sans-operator-single-family.md +17 -0
  144. package/data/harnesses/code/skills/design/data/typography/instrument-serif-instrument-sans.md +17 -0
  145. package/data/harnesses/code/skills/design/data/typography/inter-operator-single-family.md +17 -0
  146. package/data/harnesses/code/skills/design/data/typography/libre-baskerville-libre-franklin.md +17 -0
  147. package/data/harnesses/code/skills/design/data/typography/newsreader-inter.md +17 -0
  148. package/data/harnesses/code/skills/design/data/typography/playfair-display-source-sans.md +17 -0
  149. package/data/harnesses/code/skills/design/data/typography/public-sans-operator-single-family.md +17 -0
  150. package/data/harnesses/code/skills/design/data/typography/sohne-inter-fintech.md +17 -0
  151. package/data/harnesses/code/skills/design/data/typography/source-serif-source-sans.md +17 -0
  152. package/data/harnesses/code/skills/design/data/typography/space-grotesk-work-sans-space-mono.md +17 -0
  153. package/data/harnesses/code/skills/design/data/typography/spectral-manrope.md +17 -0
  154. package/data/harnesses/code/skills/design/data/voices/bright-collaborator.md +29 -0
  155. package/data/harnesses/code/skills/design/data/voices/direct-operator.md +29 -0
  156. package/data/harnesses/code/skills/design/data/voices/earnest-helper.md +29 -0
  157. package/data/harnesses/code/skills/design/data/voices/editorial-composed.md +29 -0
  158. package/data/harnesses/code/skills/design/data/voices/quiet-concierge.md +29 -0
  159. package/data/harnesses/code/skills/design/data/voices/warm-guide.md +29 -0
  160. package/data/harnesses/code/skills/design/design-md/SCHEMA.md +179 -0
  161. package/data/harnesses/code/skills/design/design-md/index.csv +67 -0
  162. package/data/harnesses/code/skills/design/design-md/library/airbnb.md +207 -0
  163. package/data/harnesses/code/skills/design/design-md/library/airtable.md +205 -0
  164. package/data/harnesses/code/skills/design/design-md/library/anthropic-claude.md +203 -0
  165. package/data/harnesses/code/skills/design/design-md/library/apple.md +206 -0
  166. package/data/harnesses/code/skills/design/design-md/library/binance.md +210 -0
  167. package/data/harnesses/code/skills/design/design-md/library/bmw.md +210 -0
  168. package/data/harnesses/code/skills/design/design-md/library/cal.md +209 -0
  169. package/data/harnesses/code/skills/design/design-md/library/clay.md +204 -0
  170. package/data/harnesses/code/skills/design/design-md/library/clickhouse.md +205 -0
  171. package/data/harnesses/code/skills/design/design-md/library/cohere.md +205 -0
  172. package/data/harnesses/code/skills/design/design-md/library/coinbase.md +198 -0
  173. package/data/harnesses/code/skills/design/design-md/library/composio.md +198 -0
  174. package/data/harnesses/code/skills/design/design-md/library/cursor.md +197 -0
  175. package/data/harnesses/code/skills/design/design-md/library/elevenlabs.md +199 -0
  176. package/data/harnesses/code/skills/design/design-md/library/expo.md +200 -0
  177. package/data/harnesses/code/skills/design/design-md/library/figma.md +199 -0
  178. package/data/harnesses/code/skills/design/design-md/library/framer.md +202 -0
  179. package/data/harnesses/code/skills/design/design-md/library/hashicorp.md +205 -0
  180. package/data/harnesses/code/skills/design/design-md/library/ibm.md +205 -0
  181. package/data/harnesses/code/skills/design/design-md/library/intercom.md +204 -0
  182. package/data/harnesses/code/skills/design/design-md/library/kraken.md +200 -0
  183. package/data/harnesses/code/skills/design/design-md/library/linear-app.md +198 -0
  184. package/data/harnesses/code/skills/design/design-md/library/lovable.md +199 -0
  185. package/data/harnesses/code/skills/design/design-md/library/meta.md +204 -0
  186. package/data/harnesses/code/skills/design/design-md/library/minimax.md +204 -0
  187. package/data/harnesses/code/skills/design/design-md/library/mintlify.md +210 -0
  188. package/data/harnesses/code/skills/design/design-md/library/miro.md +209 -0
  189. package/data/harnesses/code/skills/design/design-md/library/mistral-ai.md +201 -0
  190. package/data/harnesses/code/skills/design/design-md/library/mongodb.md +201 -0
  191. package/data/harnesses/code/skills/design/design-md/library/notion.md +204 -0
  192. package/data/harnesses/code/skills/design/design-md/library/nvidia.md +215 -0
  193. package/data/harnesses/code/skills/design/design-md/library/ollama.md +213 -0
  194. package/data/harnesses/code/skills/design/design-md/library/opencode-ai.md +216 -0
  195. package/data/harnesses/code/skills/design/design-md/library/posthog.md +218 -0
  196. package/data/harnesses/code/skills/design/design-md/library/raycast.md +214 -0
  197. package/data/harnesses/code/skills/design/design-md/library/replicate.md +202 -0
  198. package/data/harnesses/code/skills/design/design-md/library/resend.md +203 -0
  199. package/data/harnesses/code/skills/design/design-md/library/revolut.md +203 -0
  200. package/data/harnesses/code/skills/design/design-md/library/runwayml.md +203 -0
  201. package/data/harnesses/code/skills/design/design-md/library/sanity.md +200 -0
  202. package/data/harnesses/code/skills/design/design-md/library/sentry.md +201 -0
  203. package/data/harnesses/code/skills/design/design-md/library/shopify.md +202 -0
  204. package/data/harnesses/code/skills/design/design-md/library/slack.md +202 -0
  205. package/data/harnesses/code/skills/design/design-md/library/spacex.md +206 -0
  206. package/data/harnesses/code/skills/design/design-md/library/spotify.md +206 -0
  207. package/data/harnesses/code/skills/design/design-md/library/stripe.md +196 -0
  208. package/data/harnesses/code/skills/design/design-md/library/supabase.md +196 -0
  209. package/data/harnesses/code/skills/design/design-md/library/superhuman.md +194 -0
  210. package/data/harnesses/code/skills/design/design-md/library/tesla.md +198 -0
  211. package/data/harnesses/code/skills/design/design-md/library/theverge.md +199 -0
  212. package/data/harnesses/code/skills/design/design-md/library/together-ai.md +193 -0
  213. package/data/harnesses/code/skills/design/design-md/library/uber.md +195 -0
  214. package/data/harnesses/code/skills/design/design-md/library/vercel.md +195 -0
  215. package/data/harnesses/code/skills/design/design-md/library/voltagent.md +197 -0
  216. package/data/harnesses/code/skills/design/design-md/library/warp.md +196 -0
  217. package/data/harnesses/code/skills/design/design-md/library/webflow.md +197 -0
  218. package/data/harnesses/code/skills/design/design-md/library/wired.md +197 -0
  219. package/data/harnesses/code/skills/design/design-md/library/wise.md +198 -0
  220. package/data/harnesses/code/skills/design/design-md/library/x-ai.md +199 -0
  221. package/data/harnesses/code/skills/design/design-md/library/zapier.md +198 -0
  222. package/data/harnesses/code/skills/design/design-md/nurix.md +214 -0
  223. package/data/harnesses/code/skills/design/design-md/variants/editorial-luxury.md +184 -0
  224. package/data/harnesses/code/skills/design/design-md/variants/expressive-saas.md +216 -0
  225. package/data/harnesses/code/skills/design/design-md/variants/quiet-premium.md +211 -0
  226. package/data/harnesses/code/skills/design/design-md/variants/terse-dense-operator.md +212 -0
  227. package/data/harnesses/code/skills/design/design-md/variants/warm-approachable.md +216 -0
  228. package/data/harnesses/code/skills/design/references/compose.md +23 -0
  229. package/data/harnesses/code/skills/design/references/content.md +28 -0
  230. package/data/harnesses/code/skills/design/references/emission.md +21 -0
  231. package/data/harnesses/code/skills/design/references/existing-apps.md +27 -0
  232. package/data/harnesses/code/skills/design/references/intake.md +36 -0
  233. package/data/harnesses/code/skills/design/references/object-pass.md +24 -0
  234. package/data/harnesses/code/skills/design/references/ship-gate.md +29 -0
  235. package/data/harnesses/code/skills/design/references/ux-patterns/Readme.md +195 -0
  236. package/data/harnesses/code/skills/design/references/ux-patterns/ai-layer.md +49 -0
  237. package/data/harnesses/code/skills/design/references/ux-patterns/attributes-lifecycle.md +43 -0
  238. package/data/harnesses/code/skills/design/references/ux-patterns/container-choice.md +44 -0
  239. package/data/harnesses/code/skills/design/references/ux-patterns/creation-paths.md +46 -0
  240. package/data/harnesses/code/skills/design/references/ux-patterns/dashboards.md +42 -0
  241. package/data/harnesses/code/skills/design/references/ux-patterns/modes.md +42 -0
  242. package/data/harnesses/code/skills/design/references/ux-patterns/object-model.md +46 -0
  243. package/data/harnesses/code/skills/design/references/ux-patterns/page-archetype.md +48 -0
  244. package/data/harnesses/code/skills/design/references/ux-patterns/promotion-demotion.md +37 -0
  245. package/data/harnesses/code/skills/design/references/ux-patterns/settings.md +42 -0
  246. package/data/harnesses/code/skills/design/references/ux-patterns/standard-pages.md +46 -0
  247. package/data/harnesses/code/skills/design/references/ux-patterns/state-matrix.md +41 -0
  248. package/data/harnesses/code/skills/design/references/ux-patterns/table-mechanics.md +48 -0
  249. package/data/harnesses/code/skills/design/references/ux-patterns/verbs.md +45 -0
  250. package/data/harnesses/code/skills/design/references/ux-patterns/viewer-context.md +40 -0
  251. package/data/harnesses/code/skills/design/scripts/README-validator.md +27 -0
  252. package/data/harnesses/code/skills/design/scripts/select-chart.mjs +596 -0
  253. package/data/harnesses/code/skills/design/scripts/validate-design-md.mjs +1198 -0
  254. package/data/harnesses/discussion/agents/discussion-baseline.md +1 -1
  255. package/data/harnesses/discussion/harness.json +1 -1
  256. package/data/harnesses/etna/agents/maintenance.md +1 -1
  257. package/data/harnesses/etna/harness.json +1 -1
  258. package/data/harnesses/hr/CLAUDE.md +1 -1
  259. package/data/harnesses/hr/harness.json +1 -1
  260. package/package.json +1 -1
  261. package/data/harnesses/code/skills/design/data/catalog/rules.csv +0 -137
  262. package/data/harnesses/code/skills/design/data/combinations/Readme.md +0 -33
  263. package/data/harnesses/code/skills/design/data/combinations/accent-presets.md +0 -113
  264. package/data/harnesses/code/skills/design/data/combinations/charts.csv +0 -33
  265. package/data/harnesses/code/skills/design/data/combinations/fonts-known.json +0 -448
  266. package/data/harnesses/code/skills/design/data/combinations/icons.csv +0 -157
  267. package/data/harnesses/code/skills/design/data/combinations/landing.csv +0 -38
  268. package/data/harnesses/code/skills/design/data/combinations/lucide-names.json +0 -2001
  269. package/data/harnesses/code/skills/design/data/combinations/manifest.json +0 -330
  270. package/data/harnesses/code/skills/design/data/combinations/motion.csv +0 -10
  271. package/data/harnesses/code/skills/design/data/combinations/palettes.csv +0 -92
  272. package/data/harnesses/code/skills/design/data/combinations/product-router.csv +0 -80
  273. package/data/harnesses/code/skills/design/data/combinations/styles.csv +0 -67
  274. package/data/harnesses/code/skills/design/data/combinations/typography.csv +0 -64
  275. package/data/harnesses/code/skills/design/data/design-md/SCHEMA.md +0 -106
  276. package/data/harnesses/code/skills/design/data/design-md/library/airbnb.md +0 -154
  277. package/data/harnesses/code/skills/design/data/design-md/library/airtable.md +0 -151
  278. package/data/harnesses/code/skills/design/data/design-md/library/anthropic-claude.md +0 -139
  279. package/data/harnesses/code/skills/design/data/design-md/library/apple.md +0 -139
  280. package/data/harnesses/code/skills/design/data/design-md/library/binance.md +0 -140
  281. package/data/harnesses/code/skills/design/data/design-md/library/bmw.md +0 -140
  282. package/data/harnesses/code/skills/design/data/design-md/library/cal.md +0 -140
  283. package/data/harnesses/code/skills/design/data/design-md/library/clay.md +0 -139
  284. package/data/harnesses/code/skills/design/data/design-md/library/clickhouse.md +0 -139
  285. package/data/harnesses/code/skills/design/data/design-md/library/cohere.md +0 -147
  286. package/data/harnesses/code/skills/design/data/design-md/library/coinbase.md +0 -156
  287. package/data/harnesses/code/skills/design/data/design-md/library/composio.md +0 -138
  288. package/data/harnesses/code/skills/design/data/design-md/library/cursor.md +0 -138
  289. package/data/harnesses/code/skills/design/data/design-md/library/elevenlabs.md +0 -137
  290. package/data/harnesses/code/skills/design/data/design-md/library/expo.md +0 -148
  291. package/data/harnesses/code/skills/design/data/design-md/library/figma.md +0 -141
  292. package/data/harnesses/code/skills/design/data/design-md/library/framer.md +0 -156
  293. package/data/harnesses/code/skills/design/data/design-md/library/hashicorp.md +0 -140
  294. package/data/harnesses/code/skills/design/data/design-md/library/ibm.md +0 -153
  295. package/data/harnesses/code/skills/design/data/design-md/library/intercom.md +0 -158
  296. package/data/harnesses/code/skills/design/data/design-md/library/kraken.md +0 -156
  297. package/data/harnesses/code/skills/design/data/design-md/library/linear-app.md +0 -122
  298. package/data/harnesses/code/skills/design/data/design-md/library/lovable.md +0 -140
  299. package/data/harnesses/code/skills/design/data/design-md/library/meta.md +0 -139
  300. package/data/harnesses/code/skills/design/data/design-md/library/minimax.md +0 -139
  301. package/data/harnesses/code/skills/design/data/design-md/library/mintlify.md +0 -139
  302. package/data/harnesses/code/skills/design/data/design-md/library/miro.md +0 -153
  303. package/data/harnesses/code/skills/design/data/design-md/library/mistral-ai.md +0 -140
  304. package/data/harnesses/code/skills/design/data/design-md/library/mongodb.md +0 -155
  305. package/data/harnesses/code/skills/design/data/design-md/library/notion.md +0 -140
  306. package/data/harnesses/code/skills/design/data/design-md/library/nvidia.md +0 -141
  307. package/data/harnesses/code/skills/design/data/design-md/library/ollama.md +0 -145
  308. package/data/harnesses/code/skills/design/data/design-md/library/opencode-ai.md +0 -142
  309. package/data/harnesses/code/skills/design/data/design-md/library/posthog.md +0 -152
  310. package/data/harnesses/code/skills/design/data/design-md/library/raycast.md +0 -137
  311. package/data/harnesses/code/skills/design/data/design-md/library/replicate.md +0 -140
  312. package/data/harnesses/code/skills/design/data/design-md/library/resend.md +0 -170
  313. package/data/harnesses/code/skills/design/data/design-md/library/revolut.md +0 -145
  314. package/data/harnesses/code/skills/design/data/design-md/library/runwayml.md +0 -137
  315. package/data/harnesses/code/skills/design/data/design-md/library/sanity.md +0 -168
  316. package/data/harnesses/code/skills/design/data/design-md/library/sentry.md +0 -163
  317. package/data/harnesses/code/skills/design/data/design-md/library/shopify.md +0 -147
  318. package/data/harnesses/code/skills/design/data/design-md/library/slack.md +0 -158
  319. package/data/harnesses/code/skills/design/data/design-md/library/spacex.md +0 -171
  320. package/data/harnesses/code/skills/design/data/design-md/library/spotify.md +0 -166
  321. package/data/harnesses/code/skills/design/data/design-md/library/stripe.md +0 -160
  322. package/data/harnesses/code/skills/design/data/design-md/library/supabase.md +0 -173
  323. package/data/harnesses/code/skills/design/data/design-md/library/superhuman.md +0 -145
  324. package/data/harnesses/code/skills/design/data/design-md/library/tesla.md +0 -153
  325. package/data/harnesses/code/skills/design/data/design-md/library/theverge.md +0 -167
  326. package/data/harnesses/code/skills/design/data/design-md/library/together-ai.md +0 -140
  327. package/data/harnesses/code/skills/design/data/design-md/library/uber.md +0 -140
  328. package/data/harnesses/code/skills/design/data/design-md/library/vercel.md +0 -140
  329. package/data/harnesses/code/skills/design/data/design-md/library/voltagent.md +0 -130
  330. package/data/harnesses/code/skills/design/data/design-md/library/warp.md +0 -140
  331. package/data/harnesses/code/skills/design/data/design-md/library/webflow.md +0 -140
  332. package/data/harnesses/code/skills/design/data/design-md/library/wired.md +0 -139
  333. package/data/harnesses/code/skills/design/data/design-md/library/wise.md +0 -137
  334. package/data/harnesses/code/skills/design/data/design-md/library/x-ai.md +0 -138
  335. package/data/harnesses/code/skills/design/data/design-md/library/zapier.md +0 -158
  336. package/data/harnesses/code/skills/design/data/design-md/nurix.md +0 -138
  337. package/data/harnesses/code/skills/design/data/design-tokens/SCHEMA.md +0 -695
  338. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.resolver.json +0 -20
  339. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.tokens.json +0 -1272
  340. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.resolver.json +0 -20
  341. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.tokens.json +0 -1268
  342. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.resolver.json +0 -20
  343. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.tokens.json +0 -1273
  344. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.resolver.json +0 -20
  345. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.tokens.json +0 -1262
  346. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.resolver.json +0 -20
  347. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.tokens.json +0 -1257
  348. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.resolver.json +0 -20
  349. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.tokens.json +0 -1270
  350. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.resolver.json +0 -20
  351. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.tokens.json +0 -1270
  352. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.resolver.json +0 -20
  353. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.tokens.json +0 -1261
  354. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.resolver.json +0 -20
  355. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.tokens.json +0 -1268
  356. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.resolver.json +0 -20
  357. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.tokens.json +0 -1281
  358. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.resolver.json +0 -20
  359. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.tokens.json +0 -1262
  360. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.resolver.json +0 -20
  361. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.tokens.json +0 -1271
  362. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.resolver.json +0 -20
  363. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.tokens.json +0 -1276
  364. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.resolver.json +0 -20
  365. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.tokens.json +0 -1293
  366. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.resolver.json +0 -20
  367. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.tokens.json +0 -1270
  368. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.resolver.json +0 -20
  369. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.tokens.json +0 -1276
  370. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.resolver.json +0 -20
  371. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.tokens.json +0 -1267
  372. package/data/harnesses/code/skills/design/data/design-tokens/goldens.json +0 -251
  373. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.resolver.json +0 -20
  374. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.tokens.json +0 -1273
  375. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.resolver.json +0 -20
  376. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.tokens.json +0 -1286
  377. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.resolver.json +0 -20
  378. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.tokens.json +0 -1290
  379. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.resolver.json +0 -20
  380. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.tokens.json +0 -1270
  381. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.resolver.json +0 -23
  382. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.dark.json +0 -599
  383. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.json +0 -1272
  384. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.resolver.json +0 -20
  385. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.tokens.json +0 -1267
  386. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.resolver.json +0 -20
  387. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.tokens.json +0 -1289
  388. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.resolver.json +0 -20
  389. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.tokens.json +0 -1258
  390. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.resolver.json +0 -20
  391. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.tokens.json +0 -1284
  392. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.resolver.json +0 -20
  393. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.tokens.json +0 -1291
  394. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.resolver.json +0 -20
  395. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.tokens.json +0 -1263
  396. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.resolver.json +0 -20
  397. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.tokens.json +0 -1270
  398. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.resolver.json +0 -20
  399. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.tokens.json +0 -1261
  400. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.resolver.json +0 -20
  401. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.tokens.json +0 -1209
  402. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.resolver.json +0 -20
  403. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.tokens.json +0 -1265
  404. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.resolver.json +0 -20
  405. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.tokens.json +0 -1253
  406. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.resolver.json +0 -20
  407. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.tokens.json +0 -1268
  408. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.resolver.json +0 -20
  409. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.tokens.json +0 -1261
  410. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.resolver.json +0 -20
  411. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.tokens.json +0 -1263
  412. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.resolver.json +0 -20
  413. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.tokens.json +0 -1266
  414. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.resolver.json +0 -23
  415. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.dark.json +0 -623
  416. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.json +0 -1276
  417. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.resolver.json +0 -20
  418. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.tokens.json +0 -1264
  419. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.resolver.json +0 -20
  420. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.tokens.json +0 -1268
  421. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.resolver.json +0 -20
  422. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.tokens.json +0 -1270
  423. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.resolver.json +0 -20
  424. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.tokens.json +0 -1288
  425. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.resolver.json +0 -20
  426. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.tokens.json +0 -1272
  427. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.resolver.json +0 -20
  428. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.tokens.json +0 -1265
  429. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.resolver.json +0 -20
  430. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.tokens.json +0 -1287
  431. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.resolver.json +0 -20
  432. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.tokens.json +0 -1286
  433. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.resolver.json +0 -20
  434. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.tokens.json +0 -1285
  435. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.resolver.json +0 -20
  436. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.tokens.json +0 -1287
  437. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.resolver.json +0 -20
  438. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.tokens.json +0 -1278
  439. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.resolver.json +0 -20
  440. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.tokens.json +0 -1269
  441. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.resolver.json +0 -20
  442. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.tokens.json +0 -1285
  443. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.resolver.json +0 -20
  444. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.tokens.json +0 -1303
  445. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.resolver.json +0 -20
  446. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.tokens.json +0 -1274
  447. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.resolver.json +0 -20
  448. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.tokens.json +0 -1296
  449. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.resolver.json +0 -23
  450. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.dark.json +0 -612
  451. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.json +0 -1282
  452. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.resolver.json +0 -20
  453. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.tokens.json +0 -1287
  454. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.resolver.json +0 -20
  455. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.tokens.json +0 -1268
  456. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.resolver.json +0 -20
  457. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.tokens.json +0 -1276
  458. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.resolver.json +0 -20
  459. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.tokens.json +0 -1273
  460. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.resolver.json +0 -20
  461. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.tokens.json +0 -1296
  462. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.resolver.json +0 -20
  463. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.tokens.json +0 -1286
  464. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/command-center.tsx +0 -249
  465. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/create-edit.tsx +0 -249
  466. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/dashboard.tsx +0 -225
  467. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/entity-detail.tsx +0 -249
  468. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/list-detail.tsx +0 -224
  469. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/log-stream.tsx +0 -249
  470. package/data/harnesses/code/skills/design/data/operator-pack/fixtures.md +0 -88
  471. package/data/harnesses/code/skills/design/data/operator-pack/surface-catalog.md +0 -132
  472. package/data/harnesses/code/skills/design/data/operator-pack/trust-rubric.md +0 -76
  473. package/data/harnesses/code/skills/design/references/create.md +0 -173
  474. package/data/harnesses/code/skills/design/references/diagnosis.md +0 -108
  475. package/data/harnesses/code/skills/design/references/hard-rules.md +0 -177
  476. package/data/harnesses/code/skills/design/references/improve.md +0 -116
  477. package/data/harnesses/code/skills/design/references/interaction.md +0 -77
  478. package/data/harnesses/code/skills/design/references/introspect.md +0 -100
  479. package/data/harnesses/code/skills/design/references/lifecycle.md +0 -73
  480. package/data/harnesses/code/skills/design/references/personality.md +0 -575
  481. package/data/harnesses/code/skills/design/references/structure.md +0 -159
  482. package/data/harnesses/code/skills/design/scripts/convert-design-md.mjs +0 -1312
  483. package/data/harnesses/code/skills/design/scripts/derive-personality.mjs +0 -1498
  484. package/data/harnesses/code/skills/design/scripts/generate-fixtures.mjs +0 -551
  485. package/data/harnesses/code/skills/design/scripts/lib/checks.mjs +0 -1092
  486. package/data/harnesses/code/skills/design/scripts/lib/golden.mjs +0 -26
  487. package/data/harnesses/code/skills/design/scripts/lib/vocabulary.mjs +0 -65
  488. package/data/harnesses/code/skills/design/scripts/phase-gate.mjs +0 -538
  489. package/data/harnesses/code/skills/design/scripts/preship-sweep.mjs +0 -312
  490. package/data/harnesses/code/skills/design/scripts/render-rung.mjs +0 -890
  491. package/data/harnesses/code/skills/design/scripts/scaffold.mjs +0 -769
  492. package/data/harnesses/code/skills/design/scripts/self-integrity.mjs +0 -675
  493. package/data/harnesses/code/skills/design/scripts/snapshot-goldens.mjs +0 -164
  494. 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); });