@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
@@ -0,0 +1,596 @@
1
+ // skills/design/scripts/select-chart.mjs - B1 chart-selection engine: eliminate, rank, refuse
2
+ //
3
+ // One graph question per call. The model authors the data-signature JSON (the judgment
4
+ // half); this script computes elimination, scoring, ranking, and refusal (the mechanical
5
+ // half) over the chart-leaf census at ../data/charts/census.csv. Deterministic: same
6
+ // signature in, same output out. No network, stdlib only.
7
+ //
8
+ // OUTPUT CONTRACT (docs/features/design-skill/07-evaluation-integrity.md §B1 — exact):
9
+ // {
10
+ // "admissible": ["chart-id"],
11
+ // "eliminated": [{ "id": "chart-id", "reasonCode": "elimination-code" }],
12
+ // "ranking": [{ "id": "chart-id", "score": 0, "reasonCodes": ["reason-code"] }],
13
+ // "recommendation": "chart-id-or-null",
14
+ // "refusal": "refusal-code-or-null"
15
+ // }
16
+ //
17
+ // INPUT SIGNATURE (fixed schema; the fuzzy question->schema derivation is the caller's job):
18
+ // {
19
+ // question: string (audit only — no rule reads it),
20
+ // questions: [string] — optional; >1 entries signals a compound question (refusal),
21
+ // structure: "flat|tree|edges|matrix|geo|interval|grid|scalar|text" (default flat;
22
+ // scalar is derived when dimensions are empty and a measure exists),
23
+ // granularity: "raw-observations|pre-aggregated" (default pre-aggregated),
24
+ // rows: number — dataset row count (drives the overplotting regime),
25
+ // measures: [{ id, kind, unit, sign: "positive|signed|fraction", integer, isId, ambiguous }],
26
+ // dimensions: [{ id, kind: "nominal|ordinal|temporal|geo", ordered, cardinality,
27
+ // spacing: "regular|irregular", ambiguous }],
28
+ // target: { value, source } — optional explicit target,
29
+ // semantics: { targetExists, partsFormWhole, orderedProgression, temporalSubject,
30
+ // negativeValues, wholeUnits, uncertainty, mixedUnits },
31
+ // task: { primary, secondary: [<=2] } — optional; derived from schema defaults
32
+ // when absent (explicit caller cues always win over the defaults),
33
+ // ambiguities: [{ field, alternatives }] — optional; non-empty signals refusal,
34
+ // constraints: { viewport: "mobile|tablet|desktop|wide" (default desktop),
35
+ // interactionAllowed, colorVisionSafe, guardOverrides }
36
+ // }
37
+ //
38
+ // REFUSAL CONTRACT — four codes (graph-selection research 02 §7), checked in this order:
39
+ // 1. "unmappable-structure" (R-UNMAPPABLE) structure fits no signature: free prose,
40
+ // a lone non-numeric fact, or an empty signature (no fields at all).
41
+ // 2. "compound-question" (R-COMPOUND) input.questions carries >1 disjoint graph
42
+ // questions; decomposition is the invoker's job — the engine never charts two at once.
43
+ // 3. "ambiguous-schema" (R-AMBIGUOUS) the schema derives two ways that land in
44
+ // different families (any field marked ambiguous, or input.ambiguities non-empty).
45
+ // 4. "no-quantitative-measure" (R-NO-MEASURE) no measure and no countable structure —
46
+ // a bare entity list is a table row-set, not a chart; the engine refuses rather than
47
+ // inventing a count.
48
+ //
49
+ // FIXED OPEN PARAMETERS (the research left these open; fixed here, per 01 §B1):
50
+ // * Scoring constants (research §5 M-table, rescaled to reduce clamp saturation at 100
51
+ // while preserving every ordering relationship: M1 dominant, |M3 match| > |M2|,
52
+ // over-cap ~ -M3): BASE 50, clamp [0,100];
53
+ // M1 native fit: family anchor +20, native +16, fallback (table family) +6
54
+ // M2 encoding: position/length +8, angle/area/color-only -8, else 0
55
+ // M3 primary-task match +12 / mismatch -8 (leaves with no native task: 0)
56
+ // M4 secondary-task match +4 each (<=2)
57
+ // M5 cardinality: comfortable +4, near cap -4, over cap -12 (+ facet escape code)
58
+ // M6 dataset size: rows>=10000 binned +8 / point -8; rows>=1000 hexbin +4
59
+ // M7 decorative/low-precision -8 (pictogram, gauge, streamgraph, radar)
60
+ // M8 flag synergy +6 (temporalSubject->line family; partsFormWhole->part-to-whole
61
+ // family; targetExists->target-native leaves; uncertainty->error-bands)
62
+ // Threshold constants (research §6, fixed by decision inside the evidenced bands):
63
+ // K1 pie slices 6 · K2 bar categories 12 · K3 line series 6 · K4 stacked totals 10
64
+ // K5 overplot 1000 offered / 10000 mandatory · K6 facet panels 20 · K7 grouped
65
+ // series 4 · K8 waffle 10x10 · K9 SPLOM vars 8 · K10 network nodes 300.
66
+ // Hard elimination sits at 2x the comfort cap ("cardinality-exceeded"); between
67
+ // comfort and 2x the leaf is demoted, never killed (T-H: membership is decided only
68
+ // in elimination, so only 2x-destructive overflow counts as an expressiveness kill).
69
+ // * Task facets (research open question 3): primary + <=2 secondary facets are accepted
70
+ // on explicit input.task; schema-default derivation supplies a primary only. Rationale:
71
+ // one question can carry compound facets ("compare regions over time"), but the engine
72
+ // never invents a secondary the caller didn't assert.
73
+ // * Ambiguity handling (research open question 4): R-AMBIGUOUS stays a refusal variant,
74
+ // not a third response type — two response types keep the invoker contract simple
75
+ // (the research's own recommendation, adopted).
76
+ // * Guard overrides (research open question 5): guard variants (dual axes, truncated
77
+ // bar axes, broken axes, 3D) are census-level exclusions — they are design variants,
78
+ // not chart leaves, so there is nothing in the 57-leaf universe to resurrect.
79
+ // constraints.guardOverrides is accepted for forward compatibility and is currently a
80
+ // no-op on this closed output contract; overrides remain a rendering-layer concern
81
+ // recorded by the caller (per the ruling: overridable by explicit flag, logged).
82
+ // * The research's "conditional section" (options that unlock if a flag flips) folds
83
+ // into `eliminated` with flag-gate reason codes ("parts-form-whole-not-asserted",
84
+ // "target-not-asserted", ...) because the ratified 07 §B1 contract is closed — the
85
+ // unlock flag is recoverable from the reason code.
86
+ //
87
+ // CENSUS FLAG SEMANTICS (requires_flags / excludes_flags, |-separated):
88
+ // Flags fall into three classes; requires_flags evaluates per class:
89
+ // ordering class {temporal, ordered-progression} — OR (any one satisfies)
90
+ // structure class {tree, edges, matrix, geo, interval, scalar, grid} — OR
91
+ // semantic class (everything else) — AND (each required)
92
+ // excludes_flags: any listed flag present in the derived input flags eliminates the leaf.
93
+ // Elimination emits one reasonCode per leaf, first match in this fixed precedence:
94
+ // structure-incompatible -> excluded-flag codes -> missing-required-flag codes
95
+ // ("ordered-x-required" for the ordering class, "structure-required" for the structure
96
+ // class, "<flag>-not-asserted"/"-required" for semantic flags) -> signature-mismatch
97
+ // -> cardinality-exceeded -> viewport-too-small.
98
+
99
+ import fs from 'node:fs';
100
+ import path from 'node:path';
101
+ import process from 'node:process';
102
+ import { fileURLToPath } from 'node:url';
103
+
104
+ const VIEWPORT_ORDER = ['mobile', 'tablet', 'desktop', 'wide'];
105
+ const ORDER_FLAGS = new Set(['temporal', 'ordered-progression']);
106
+ const STRUCTURE_FLAGS = new Set(['tree', 'edges', 'matrix', 'geo', 'interval', 'scalar', 'grid']);
107
+ const REFUSING_STRUCTURES = new Set(['text', 'prose', 'text-weights', 'none', 'unknown']);
108
+
109
+ const EXCLUDE_REASON_BY_FLAG = {
110
+ temporal: 'temporal-series-incompatible',
111
+ 'negative-values': 'negative-values-incompatible',
112
+ 'irregular-temporal': 'irregular-temporal-incompatible',
113
+ 'mixed-units': 'mixed-units-incompatible',
114
+ 'no-color-encoding': 'color-encoding-inaccessible',
115
+ };
116
+
117
+ const REQUIRE_REASON_BY_FLAG = {
118
+ 'parts-form-whole': 'parts-form-whole-not-asserted',
119
+ 'target-exists': 'target-not-asserted',
120
+ 'negative-values': 'negative-values-not-asserted',
121
+ 'raw-observations': 'raw-observations-required',
122
+ 'whole-units': 'whole-units-required',
123
+ uncertainty: 'uncertainty-not-asserted',
124
+ };
125
+
126
+ // EL-4: a non-flat structure admits only these leaves (plus any leaf that requires it).
127
+ const STRUCTURE_COMPAT = {
128
+ tree: ['treemap', 'sunburst', 'tree-diagram', 'table', 'table-hybrid'],
129
+ edges: ['sankey', 'chord', 'network-graph', 'table', 'table-hybrid'],
130
+ matrix: ['heatmap', 'chord', 'table', 'table-hybrid'],
131
+ geo: ['choropleth', 'symbol-map', 'flow-map', 'point-map', 'table', 'table-hybrid'],
132
+ interval: ['gantt', 'event-timeline', 'table', 'table-hybrid'],
133
+ scalar: ['kpi-card', 'gauge', 'progress-bar', 'bullet', 'table', 'table-hybrid'],
134
+ grid: ['heatmap', 'table', 'table-hybrid'],
135
+ };
136
+
137
+ // M1 tiers: the settled core mappings (research 00 §C-1) anchor each family.
138
+ const FAMILY_ANCHORS = new Set([
139
+ 'bar', 'line-basic', 'pie', 'histogram', 'scatter', 'ordered-bar', 'sankey',
140
+ 'network-graph', 'choropleth', 'event-timeline', 'kpi-card', 'heatmap', 'candlestick',
141
+ ]);
142
+ const FALLBACK_LEAVES = new Set(['table', 'table-hybrid']);
143
+
144
+ // M2: position/length reads most accurately; angle/area/color-only reads worst.
145
+ const POSITION_LEAVES = new Set([
146
+ 'bar', 'grouped-bar', 'stacked-bar', 'diverging-bar', 'lollipop', 'dot-plot', 'dumbbell',
147
+ 'line-basic', 'line-multi', 'line-with-target', 'slope', 'bump', 'sparkline', 'ordered-bar',
148
+ 'pareto', 'waterfall', 'scatter', 'histogram', 'box-plot', 'strip-plot', 'bullet',
149
+ 'progress-bar', 'gantt', 'candlestick', 'error-bands',
150
+ ]);
151
+ const LOW_PRECISION_LEAVES = new Set([
152
+ 'pie', 'waffle', 'treemap', 'sunburst', 'marimekko', 'funnel', 'streamgraph', 'bubble',
153
+ 'radar', 'pictogram', 'gauge', 'chord', 'heatmap', 'calendar-heatmap', 'choropleth',
154
+ 'symbol-map',
155
+ ]);
156
+
157
+ // M7: decorative/low-precision forms named by the research.
158
+ const DECORATIVE_LEAVES = new Set(['pictogram', 'gauge', 'streamgraph', 'radar']);
159
+
160
+ // M3/M4 native-task table (research §5, Amar-10 + trend/compare/overview).
161
+ const NATIVE_TASKS = {
162
+ correlate: ['scatter', 'hexbin', 'splom', 'parallel-coordinates', 'bubble'],
163
+ trend: ['line-basic', 'line-multi', 'line-with-target', 'area', 'sparkline'],
164
+ distribution: ['histogram', 'density', 'box-plot', 'violin', 'strip-plot'],
165
+ 'retrieve-value': ['table', 'table-hybrid', 'kpi-card'],
166
+ filter: ['table', 'table-hybrid'],
167
+ extremum: ['bar', 'ordered-bar', 'pareto'],
168
+ sort: ['ordered-bar', 'pareto', 'bar'],
169
+ compare: ['bar', 'grouped-bar', 'dot-plot', 'slope'],
170
+ cluster: ['scatter', 'heatmap'],
171
+ anomalies: ['scatter', 'box-plot'],
172
+ range: ['dumbbell', 'box-plot', 'gantt'],
173
+ derive: ['table', 'waterfall'],
174
+ overview: ['bar', 'line-basic', 'heatmap'],
175
+ };
176
+ const NATIVE_TASKS_BY_LEAF = (() => {
177
+ const byLeaf = new Map();
178
+ for (const [task, leaves] of Object.entries(NATIVE_TASKS)) {
179
+ for (const leaf of leaves) {
180
+ if (!byLeaf.has(leaf)) byLeaf.set(leaf, new Set());
181
+ byLeaf.get(leaf).add(task);
182
+ }
183
+ }
184
+ return byLeaf;
185
+ })();
186
+
187
+ // M5 cardinality rules per leaf: comfort cap (K constants), hard kill at 2x comfort
188
+ // unless the census constraint is itself hard (slope's 2-3 x positions).
189
+ const CARDINALITY_RULES = {
190
+ pie: { kind: 'categories', comfort: 6 }, // K1
191
+ waffle: { kind: 'categories', comfort: 6 }, // mirrors K1
192
+ bar: { kind: 'categories', comfort: 12, demoteOnly: true }, // K2
193
+ 'ordered-bar': { kind: 'categories', comfort: 12, demoteOnly: true },
194
+ lollipop: { kind: 'categories', comfort: 12, demoteOnly: true },
195
+ 'dot-plot': { kind: 'categories', comfort: 12, demoteOnly: true },
196
+ 'grouped-bar': { kind: 'series', comfort: 4 }, // K7
197
+ 'stacked-bar': { kind: 'series', comfort: 10 }, // K4
198
+ 'line-multi': { kind: 'series', comfort: 6 }, // K3
199
+ bump: { kind: 'series', comfort: 6 },
200
+ slope: { kind: 'x-positions', comfort: 3, hard: 3 },
201
+ radar: { kind: 'categories', comfort: 3 },
202
+ 'network-graph': { kind: 'nodes', comfort: 150, hard: 300 }, // K10
203
+ };
204
+
205
+ // M6 dataset-size regimes (K5).
206
+ const BINNED_LEAVES = new Set(['hexbin', 'histogram', 'density', 'box-plot', 'heatmap', 'calendar-heatmap']);
207
+ const POINT_LEAVES = new Set(['scatter', 'strip-plot', 'bubble']);
208
+ const OVERPLOT_OFFERED = 1000;
209
+ const OVERPLOT_MANDATORY = 10000;
210
+
211
+ // M8 synergy targets beyond the family-level ones.
212
+ const TARGET_NATIVE_LEAVES = new Set(['progress-bar', 'bullet', 'gauge', 'line-with-target']);
213
+
214
+ const SCORE = {
215
+ base: 50,
216
+ m1Anchor: 20,
217
+ m1Native: 16,
218
+ m1Fallback: 6,
219
+ m2Position: 8,
220
+ m2LowPrecision: -8,
221
+ m3Match: 12,
222
+ m3Mismatch: -8,
223
+ m4Secondary: 4,
224
+ m5Comfortable: 4,
225
+ m5NearCap: -4,
226
+ m5OverCap: -12,
227
+ m6Binned: 8,
228
+ m6Overplot: -8,
229
+ m6HexbinOffered: 4,
230
+ m7Decorative: -8,
231
+ m8Synergy: 6,
232
+ };
233
+
234
+ // Parses one CSV line honoring double-quoted fields.
235
+ function parseCsvLine(line) {
236
+ const cells = [];
237
+ let cell = '';
238
+ let inQuotes = false;
239
+ for (let i = 0; i < line.length; i += 1) {
240
+ const ch = line[i];
241
+ if (inQuotes) {
242
+ if (ch === '"' && line[i + 1] === '"') { cell += '"'; i += 1; }
243
+ else if (ch === '"') inQuotes = false;
244
+ else cell += ch;
245
+ } else if (ch === '"') inQuotes = true;
246
+ else if (ch === ',') { cells.push(cell); cell = ''; }
247
+ else cell += ch;
248
+ }
249
+ cells.push(cell);
250
+ return cells;
251
+ }
252
+
253
+ export function parseCensusCsv(text) {
254
+ const lines = text.split(/\r?\n/).filter((line) => line.trim() !== '');
255
+ const header = parseCsvLine(lines[0]).map((h) => h.trim());
256
+ const expected = ['id', 'family', 'min_measures', 'max_measures', 'min_dims', 'max_dims', 'requires_flags', 'excludes_flags', 'viewport_min', 'notes'];
257
+ if (header.join(',') !== expected.join(',')) {
258
+ throw new Error(`census header mismatch: expected "${expected.join(',')}" got "${header.join(',')}"`);
259
+ }
260
+ return lines.slice(1).map((line, index) => {
261
+ const cells = parseCsvLine(line);
262
+ const row = {};
263
+ header.forEach((key, i) => { row[key] = (cells[i] ?? '').trim(); });
264
+ return {
265
+ id: row.id,
266
+ family: row.family,
267
+ minMeasures: Number(row.min_measures),
268
+ maxMeasures: Number(row.max_measures),
269
+ minDims: Number(row.min_dims),
270
+ maxDims: Number(row.max_dims),
271
+ requiresFlags: row.requires_flags === '' ? [] : row.requires_flags.split('|').map((f) => f.trim()),
272
+ excludesFlags: row.excludes_flags === '' ? [] : row.excludes_flags.split('|').map((f) => f.trim()),
273
+ viewportMin: row.viewport_min === '' ? 'mobile' : row.viewport_min,
274
+ notes: row.notes,
275
+ order: index,
276
+ };
277
+ });
278
+ }
279
+
280
+ export function loadDefaultCensus() {
281
+ const censusPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'data', 'charts', 'census.csv');
282
+ return parseCensusCsv(fs.readFileSync(censusPath, 'utf8'));
283
+ }
284
+
285
+ // Normalizes loose dimension-kind aliases onto the N/O/Q/T backbone.
286
+ function dimensionKind(dim) {
287
+ const kind = dim.kind || 'nominal';
288
+ if (kind === 'categorical') return 'nominal';
289
+ return kind;
290
+ }
291
+
292
+ function effectiveMeasures(input) {
293
+ return (input.measures || []).filter((m) => m.isId !== true);
294
+ }
295
+
296
+ // Derives the auditable flag set the census rows are gated on.
297
+ function deriveFlags(input) {
298
+ const dims = input.dimensions || [];
299
+ const measures = effectiveMeasures(input);
300
+ const semantics = input.semantics || {};
301
+ const constraints = input.constraints || {};
302
+ const structure = deriveStructure(input);
303
+ const flags = new Set();
304
+
305
+ if (dims.some((d) => dimensionKind(d) === 'temporal')) flags.add('temporal');
306
+ if (semantics.orderedProgression === true || dims.some((d) => d.ordered === true && dimensionKind(d) !== 'temporal')) {
307
+ flags.add('ordered-progression');
308
+ }
309
+ if (semantics.partsFormWhole === true) flags.add('parts-form-whole');
310
+ if (semantics.targetExists === true || input.target != null) flags.add('target-exists');
311
+ if (semantics.negativeValues === true || measures.some((m) => m.sign === 'signed')) flags.add('negative-values');
312
+ if ((input.granularity || 'pre-aggregated') === 'raw-observations') flags.add('raw-observations');
313
+ if (semantics.wholeUnits === true
314
+ || (measures.length > 0 && measures.every((m) => m.kind === 'count' || m.unit === 'count' || m.integer === true))) {
315
+ flags.add('whole-units');
316
+ }
317
+ if (dims.some((d) => dimensionKind(d) === 'temporal' && d.spacing === 'irregular')) flags.add('irregular-temporal');
318
+ if (semantics.uncertainty === true || semantics.uncertaintyExists === true) flags.add('uncertainty');
319
+ if (semantics.mixedUnits === true
320
+ || (measures.length > 1 && new Set(measures.map((m) => m.unit ?? m.kind ?? '')).size > 1)) {
321
+ flags.add('mixed-units');
322
+ }
323
+ const accessibility = constraints.accessibility;
324
+ if (constraints.colorVisionSafe === true
325
+ || accessibility === 'color-independent'
326
+ || (Array.isArray(accessibility) && accessibility.includes('color-independent'))) {
327
+ flags.add('no-color-encoding');
328
+ }
329
+ if (STRUCTURE_FLAGS.has(structure)) flags.add(structure);
330
+ return { flags, structure };
331
+ }
332
+
333
+ function deriveStructure(input) {
334
+ if (input.structure) return input.structure;
335
+ const dims = input.dimensions || [];
336
+ const measures = effectiveMeasures(input);
337
+ if (dims.length === 0 && measures.length > 0) return 'scalar';
338
+ return 'flat';
339
+ }
340
+
341
+ // Refusal check — fires instead of a ranking; order is part of the contract (header).
342
+ function deriveRefusal(input, structure) {
343
+ const dims = input.dimensions || [];
344
+ const measures = effectiveMeasures(input);
345
+ const allFields = [...(input.measures || []), ...dims];
346
+ if (REFUSING_STRUCTURES.has(structure)) return 'unmappable-structure';
347
+ if (structure === 'flat' && measures.length === 0 && dims.length === 0 && input.target == null) {
348
+ return 'unmappable-structure';
349
+ }
350
+ if (Array.isArray(input.questions) && input.questions.length > 1) return 'compound-question';
351
+ if ((Array.isArray(input.ambiguities) && input.ambiguities.length > 0)
352
+ || allFields.some((f) => f.ambiguous === true)) {
353
+ return 'ambiguous-schema';
354
+ }
355
+ if (measures.length === 0 && structure === 'flat'
356
+ && !dims.some((d) => ['temporal', 'geo'].includes(dimensionKind(d)))) {
357
+ return 'no-quantitative-measure';
358
+ }
359
+ return null;
360
+ }
361
+
362
+ // Schema-default task derivation (the engine's half of the two-stage derivation;
363
+ // explicit query-cue extraction is the caller's half and arrives as input.task).
364
+ function deriveTask(input, flags) {
365
+ if (input.task && input.task.primary) {
366
+ return {
367
+ primary: input.task.primary,
368
+ secondary: (input.task.secondary || []).slice(0, 2),
369
+ };
370
+ }
371
+ const dims = input.dimensions || [];
372
+ const measures = effectiveMeasures(input);
373
+ const catDims = dims.filter((d) => ['nominal', 'ordinal'].includes(dimensionKind(d)));
374
+ let primary;
375
+ if (dims.length === 0) primary = flags.has('target-exists') ? 'compare' : 'retrieve-value';
376
+ else if (measures.length >= 2 && flags.has('raw-observations')) primary = 'correlate';
377
+ else if (flags.has('temporal') && measures.length >= 1) primary = 'trend';
378
+ else if (measures.length === 1 && flags.has('raw-observations') && catDims.length <= 1) primary = 'distribution';
379
+ else if (measures.length >= 2) primary = 'correlate';
380
+ else if (catDims.length >= 1 && measures.length >= 1) primary = 'compare';
381
+ else primary = 'overview';
382
+ return { primary, secondary: [] };
383
+ }
384
+
385
+ // Resolves the cardinality the leaf's M5 rule inspects.
386
+ function cardinalityFor(rule, input) {
387
+ const dims = input.dimensions || [];
388
+ const catDims = dims.filter((d) => ['nominal', 'ordinal'].includes(dimensionKind(d)));
389
+ const orderedDims = dims.filter((d) => dimensionKind(d) === 'temporal' || d.ordered === true);
390
+ const cards = (list) => list.map((d) => d.cardinality).filter((c) => Number.isFinite(c));
391
+ switch (rule.kind) {
392
+ case 'categories': {
393
+ const c = cards(catDims.length > 0 ? catDims : dims);
394
+ return c.length > 0 ? c[0] : undefined;
395
+ }
396
+ case 'series': {
397
+ const nonOrdered = dims.filter((d) => !(dimensionKind(d) === 'temporal' || d.ordered === true));
398
+ if (orderedDims.length > 0 && nonOrdered.length > 0) {
399
+ const c = cards(nonOrdered);
400
+ return c.length > 0 ? Math.max(...c) : undefined;
401
+ }
402
+ const c = cards(catDims);
403
+ return c.length >= 2 ? Math.min(...c) : c[0];
404
+ }
405
+ case 'x-positions': {
406
+ const c = cards(orderedDims);
407
+ return c.length > 0 ? c[0] : undefined;
408
+ }
409
+ case 'nodes': {
410
+ const c = cards(dims);
411
+ return c.length > 0 ? Math.max(...c) : undefined;
412
+ }
413
+ default:
414
+ return undefined;
415
+ }
416
+ }
417
+
418
+ // Elimination — one reasonCode per leaf, fixed precedence (see header).
419
+ function eliminationReason(leaf, input, flags, structure, viewport) {
420
+ const measures = effectiveMeasures(input);
421
+ const dims = input.dimensions || [];
422
+
423
+ if (structure !== 'flat' && STRUCTURE_COMPAT[structure]
424
+ && !STRUCTURE_COMPAT[structure].includes(leaf.id)
425
+ && !leaf.requiresFlags.includes(structure)) {
426
+ return 'structure-incompatible';
427
+ }
428
+
429
+ for (const flag of leaf.excludesFlags) {
430
+ if (flags.has(flag)) return EXCLUDE_REASON_BY_FLAG[flag] || `${flag}-incompatible`;
431
+ }
432
+
433
+ const orderingRequired = leaf.requiresFlags.filter((f) => ORDER_FLAGS.has(f));
434
+ if (orderingRequired.length > 0 && !orderingRequired.some((f) => flags.has(f))) {
435
+ return 'ordered-x-required';
436
+ }
437
+ const structureRequired = leaf.requiresFlags.filter((f) => STRUCTURE_FLAGS.has(f));
438
+ if (structureRequired.length > 0 && !structureRequired.some((f) => flags.has(f))) {
439
+ return 'structure-required';
440
+ }
441
+ for (const flag of leaf.requiresFlags) {
442
+ if (ORDER_FLAGS.has(flag) || STRUCTURE_FLAGS.has(flag)) continue;
443
+ if (!flags.has(flag)) return REQUIRE_REASON_BY_FLAG[flag] || `${flag}-not-asserted`;
444
+ }
445
+
446
+ if (measures.length < leaf.minMeasures || measures.length > leaf.maxMeasures
447
+ || dims.length < leaf.minDims || dims.length > leaf.maxDims) {
448
+ return 'signature-mismatch';
449
+ }
450
+
451
+ const rule = CARDINALITY_RULES[leaf.id];
452
+ if (rule && !rule.demoteOnly) {
453
+ const card = cardinalityFor(rule, input);
454
+ const hard = rule.hard ?? rule.comfort * 2;
455
+ if (card !== undefined && card > hard) return 'cardinality-exceeded';
456
+ }
457
+
458
+ if (VIEWPORT_ORDER.indexOf(viewport) < VIEWPORT_ORDER.indexOf(leaf.viewportMin)) {
459
+ return 'viewport-too-small';
460
+ }
461
+ return null;
462
+ }
463
+
464
+ // Scoring — additive over the fixed M-table; every weight is a constant (header).
465
+ function scoreLeaf(leaf, input, flags, task) {
466
+ let score = SCORE.base;
467
+ const reasonCodes = [];
468
+
469
+ if (FAMILY_ANCHORS.has(leaf.id)) { score += SCORE.m1Anchor; reasonCodes.push('m1-native-anchor'); }
470
+ else if (FALLBACK_LEAVES.has(leaf.id)) { score += SCORE.m1Fallback; reasonCodes.push('m1-fallback'); }
471
+ else { score += SCORE.m1Native; reasonCodes.push('m1-native-fit'); }
472
+
473
+ if (POSITION_LEAVES.has(leaf.id)) { score += SCORE.m2Position; reasonCodes.push('m2-position-encoding'); }
474
+ else if (LOW_PRECISION_LEAVES.has(leaf.id)) { score += SCORE.m2LowPrecision; reasonCodes.push('m2-low-precision-encoding'); }
475
+
476
+ const nativeTasks = NATIVE_TASKS_BY_LEAF.get(leaf.id);
477
+ if (nativeTasks && task.primary) {
478
+ if (nativeTasks.has(task.primary)) { score += SCORE.m3Match; reasonCodes.push(`m3-task-match:${task.primary}`); }
479
+ else { score += SCORE.m3Mismatch; reasonCodes.push('m3-task-mismatch'); }
480
+ for (const secondary of task.secondary) {
481
+ if (nativeTasks.has(secondary)) { score += SCORE.m4Secondary; reasonCodes.push(`m4-secondary-task-match:${secondary}`); }
482
+ }
483
+ }
484
+
485
+ const rule = CARDINALITY_RULES[leaf.id];
486
+ if (rule) {
487
+ const card = cardinalityFor(rule, input);
488
+ if (card !== undefined) {
489
+ if (card <= rule.comfort) { score += SCORE.m5Comfortable; reasonCodes.push('m5-cardinality-comfortable'); }
490
+ else if (card <= (rule.hard ?? rule.comfort * 2)) { score += SCORE.m5NearCap; reasonCodes.push('m5-cardinality-near-cap'); }
491
+ else { score += SCORE.m5OverCap; reasonCodes.push('m5-cardinality-over-cap', 'op-facet-suggested'); }
492
+ }
493
+ }
494
+
495
+ const rows = Number.isFinite(input.rows) ? input.rows : undefined;
496
+ if (rows !== undefined) {
497
+ if (rows >= OVERPLOT_MANDATORY) {
498
+ if (BINNED_LEAVES.has(leaf.id)) { score += SCORE.m6Binned; reasonCodes.push('m6-binned-boost'); }
499
+ if (POINT_LEAVES.has(leaf.id)) { score += SCORE.m6Overplot; reasonCodes.push('m6-overplot-penalty'); }
500
+ } else if (rows >= OVERPLOT_OFFERED && leaf.id === 'hexbin') {
501
+ score += SCORE.m6HexbinOffered;
502
+ reasonCodes.push('m6-binned-boost');
503
+ }
504
+ }
505
+
506
+ if (DECORATIVE_LEAVES.has(leaf.id)) { score += SCORE.m7Decorative; reasonCodes.push('m7-decorative-penalty'); }
507
+
508
+ const semantics = input.semantics || {};
509
+ if (semantics.temporalSubject === true && leaf.family === 'line') {
510
+ score += SCORE.m8Synergy; reasonCodes.push('m8-flag-synergy:temporal-subject');
511
+ }
512
+ if (flags.has('parts-form-whole') && leaf.family === 'part-to-whole') {
513
+ score += SCORE.m8Synergy; reasonCodes.push('m8-flag-synergy:parts-form-whole');
514
+ }
515
+ if (flags.has('target-exists') && TARGET_NATIVE_LEAVES.has(leaf.id)) {
516
+ score += SCORE.m8Synergy; reasonCodes.push('m8-flag-synergy:target-exists');
517
+ }
518
+ if (flags.has('uncertainty') && leaf.id === 'error-bands') {
519
+ score += SCORE.m8Synergy; reasonCodes.push('m8-flag-synergy:uncertainty');
520
+ }
521
+
522
+ return { score: Math.max(0, Math.min(100, score)), reasonCodes };
523
+ }
524
+
525
+ // The B1 decision function — one engine, two callers (CLI here, contract runner imports).
526
+ export function selectChart(input, censusRows) {
527
+ if (input == null || typeof input !== 'object' || Array.isArray(input)) {
528
+ throw new Error('selectChart: input must be a data-signature object');
529
+ }
530
+ const census = censusRows ?? loadDefaultCensus();
531
+ const { flags, structure } = deriveFlags(input);
532
+
533
+ const refusal = deriveRefusal(input, structure);
534
+ if (refusal !== null) {
535
+ return { admissible: [], eliminated: [], ranking: [], recommendation: null, refusal };
536
+ }
537
+
538
+ const viewport = (input.constraints && input.constraints.viewport) || 'desktop';
539
+ const task = deriveTask(input, flags);
540
+
541
+ const admissibleLeaves = [];
542
+ const eliminated = [];
543
+ for (const leaf of census) {
544
+ const reasonCode = eliminationReason(leaf, input, flags, structure, viewport);
545
+ if (reasonCode !== null) eliminated.push({ id: leaf.id, reasonCode });
546
+ else admissibleLeaves.push(leaf);
547
+ }
548
+
549
+ const ranking = admissibleLeaves
550
+ .map((leaf) => ({ leaf, ...scoreLeaf(leaf, input, flags, task) }))
551
+ .sort((a, b) => (b.score - a.score) || (a.leaf.order - b.leaf.order))
552
+ .map((entry) => ({ id: entry.leaf.id, score: entry.score, reasonCodes: entry.reasonCodes }));
553
+
554
+ return {
555
+ admissible: admissibleLeaves.map((leaf) => leaf.id),
556
+ eliminated,
557
+ ranking,
558
+ recommendation: ranking.length > 0 ? ranking[0].id : null,
559
+ refusal: null,
560
+ };
561
+ }
562
+
563
+ // Reads the whole of stdin (used when no input path is given).
564
+ function readStdin() {
565
+ return fs.readFileSync(0, 'utf8');
566
+ }
567
+
568
+ function main() {
569
+ const inputPath = process.argv[2];
570
+ let raw;
571
+ try {
572
+ raw = inputPath ? fs.readFileSync(inputPath, 'utf8') : readStdin();
573
+ } catch (error) {
574
+ console.error(`select-chart: cannot read input: ${error.message}`);
575
+ process.exit(1);
576
+ }
577
+ let input;
578
+ try {
579
+ input = JSON.parse(raw);
580
+ } catch (error) {
581
+ console.error(`select-chart: input is not valid JSON: ${error.message}`);
582
+ process.exit(1);
583
+ }
584
+ let output;
585
+ try {
586
+ output = selectChart(input);
587
+ } catch (error) {
588
+ console.error(`select-chart: ${error.message}`);
589
+ process.exit(1);
590
+ }
591
+ process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
592
+ }
593
+
594
+ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
595
+ main();
596
+ }