@nurix/etna 0.19.10 → 0.19.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (491) hide show
  1. package/data/harness-index.json +1 -1
  2. package/data/harnesses/code/harness.json +1 -1
  3. package/data/harnesses/code/rules/frontend.md +5 -5
  4. package/data/harnesses/code/skills/design/SKILL.md +70 -50
  5. package/data/harnesses/code/skills/design/components/charts.md +76 -0
  6. package/data/harnesses/code/skills/design/components/collections.md +132 -0
  7. package/data/harnesses/code/skills/design/components/feedback.md +47 -0
  8. package/data/harnesses/code/skills/design/components/hooks.md +35 -0
  9. package/data/harnesses/code/skills/design/components/index.md +143 -0
  10. package/data/harnesses/code/skills/design/components/inputs.md +327 -0
  11. package/data/harnesses/code/skills/design/components/layout.md +52 -0
  12. package/data/harnesses/code/skills/design/components/media.md +66 -0
  13. package/data/harnesses/code/skills/design/components/motion.md +82 -0
  14. package/data/harnesses/code/skills/design/components/navigation.md +29 -0
  15. package/data/harnesses/code/skills/design/components/overlays.md +72 -0
  16. package/data/harnesses/code/skills/design/components/setup.md +40 -0
  17. package/data/harnesses/code/skills/design/components/typography.md +46 -0
  18. package/data/harnesses/code/skills/design/components/utils.md +37 -0
  19. package/data/harnesses/code/skills/design/data/blueprints/browse.md +38 -0
  20. package/data/harnesses/code/skills/design/data/blueprints/creation-flow.md +38 -0
  21. package/data/harnesses/code/skills/design/data/blueprints/dashboard.md +38 -0
  22. package/data/harnesses/code/skills/design/data/blueprints/grid.md +38 -0
  23. package/data/harnesses/code/skills/design/data/blueprints/queue.md +38 -0
  24. package/data/harnesses/code/skills/design/data/blueprints/record-detail.md +38 -0
  25. package/data/harnesses/code/skills/design/data/blueprints/settings.md +38 -0
  26. package/data/harnesses/code/skills/design/data/chart-styling/Readme.md +33 -0
  27. package/data/harnesses/code/skills/design/data/chart-styling/carbon-accessible-alert-semantic.md +19 -0
  28. package/data/harnesses/code/skills/design/data/chart-styling/carbon-monochrome-sequential-trend.md +19 -0
  29. package/data/harnesses/code/skills/design/data/chart-styling/datadog-classic-six-aligned.md +19 -0
  30. package/data/harnesses/code/skills/design/data/chart-styling/datawrapper-tiered-gray-hierarchy.md +19 -0
  31. package/data/harnesses/code/skills/design/data/chart-styling/econ-red-rule-horizontal.md +19 -0
  32. package/data/harnesses/code/skills/design/data/chart-styling/financial-diverging-threshold-overlay.md +19 -0
  33. package/data/harnesses/code/skills/design/data/chart-styling/ft-vocabulary-ranked-muted.md +19 -0
  34. package/data/harnesses/code/skills/design/data/chart-styling/grafana-dark-threshold-bands.md +19 -0
  35. package/data/harnesses/code/skills/design/data/chart-styling/material-rounded-explicit-label.md +19 -0
  36. package/data/harnesses/code/skills/design/data/chart-styling/nyt-ghost-grid-direct-label.md +19 -0
  37. package/data/harnesses/code/skills/design/data/chart-styling/plot-currentcolor-inherit.md +19 -0
  38. package/data/harnesses/code/skills/design/data/chart-styling/saas-gradient-glow-area.md +19 -0
  39. package/data/harnesses/code/skills/design/data/chart-styling/shadcn-composable-css-vars.md +19 -0
  40. package/data/harnesses/code/skills/design/data/charts/census.csv +58 -0
  41. package/data/harnesses/code/skills/design/data/checklists/browse.md +21 -0
  42. package/data/harnesses/code/skills/design/data/checklists/creation-flow.md +20 -0
  43. package/data/harnesses/code/skills/design/data/checklists/dashboard.md +21 -0
  44. package/data/harnesses/code/skills/design/data/checklists/grid.md +21 -0
  45. package/data/harnesses/code/skills/design/data/checklists/queue.md +21 -0
  46. package/data/harnesses/code/skills/design/data/checklists/record-detail.md +21 -0
  47. package/data/harnesses/code/skills/design/data/checklists/settings.md +21 -0
  48. package/data/harnesses/code/skills/design/data/chrome/board-column.md +68 -0
  49. package/data/harnesses/code/skills/design/data/chrome/data-table.md +63 -0
  50. package/data/harnesses/code/skills/design/data/chrome/side-panel.md +60 -0
  51. package/data/harnesses/code/skills/design/data/chrome/sidebar.md +78 -0
  52. package/data/harnesses/code/skills/design/data/chrome/stat-cards.md +62 -0
  53. package/data/harnesses/code/skills/design/data/chrome/topbar.md +65 -0
  54. package/data/harnesses/code/skills/design/data/color/accent-presets.md +90 -0
  55. package/data/harnesses/code/skills/design/data/color/aesop-earth-mute.md +91 -0
  56. package/data/harnesses/code/skills/design/data/color/arc-peach-play.md +90 -0
  57. package/data/harnesses/code/skills/design/data/color/attio-hunter-teal.md +90 -0
  58. package/data/harnesses/code/skills/design/data/color/carbon-cyan-signal.md +90 -0
  59. package/data/harnesses/code/skills/design/data/color/clay-parchment.md +90 -0
  60. package/data/harnesses/code/skills/design/data/color/duolingo-feather.md +90 -0
  61. package/data/harnesses/code/skills/design/data/color/geist-mono-signal.md +90 -0
  62. package/data/harnesses/code/skills/design/data/color/linear-graphite-violet.md +90 -0
  63. package/data/harnesses/code/skills/design/data/color/mercury-onyx-cobalt.md +90 -0
  64. package/data/harnesses/code/skills/design/data/color/notion-paper-ink.md +90 -0
  65. package/data/harnesses/code/skills/design/data/color/radix-slate-iris.md +90 -0
  66. package/data/harnesses/code/skills/design/data/color/raycast-void-spectrum.md +90 -0
  67. package/data/harnesses/code/skills/design/data/color/spectrum-celery-fuchsia.md +90 -0
  68. package/data/harnesses/code/skills/design/data/color/stripe-blurple-ruby.md +90 -0
  69. package/data/harnesses/code/skills/design/data/color/superhuman-cod-picton.md +89 -0
  70. package/data/harnesses/code/skills/design/data/corpora/operations-review/companies.csv +15 -0
  71. package/data/harnesses/code/skills/design/data/corpora/operations-review/corpus.md +87 -0
  72. package/data/harnesses/code/skills/design/data/corpora/operations-review/people.csv +25 -0
  73. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/companies.csv +15 -0
  74. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/corpus.md +83 -0
  75. package/data/harnesses/code/skills/design/data/corpora/procurement-approvals/people.csv +25 -0
  76. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/companies.csv +15 -0
  77. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/corpus.md +89 -0
  78. package/data/harnesses/code/skills/design/data/corpora/revenue-analytics/people.csv +25 -0
  79. package/data/harnesses/code/skills/design/data/elevation/ant-design-directional-shadow.md +19 -0
  80. package/data/harnesses/code/skills/design/data/elevation/apple-liquid-glass-material.md +18 -0
  81. package/data/harnesses/code/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +20 -0
  82. package/data/harnesses/code/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +20 -0
  83. package/data/harnesses/code/skills/design/data/elevation/github-primer-sparing-shadow.md +19 -0
  84. package/data/harnesses/code/skills/design/data/elevation/ibm-carbon-layer-and-border.md +19 -0
  85. package/data/harnesses/code/skills/design/data/elevation/linear-dark-surface-ladder.md +17 -0
  86. package/data/harnesses/code/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +19 -0
  87. package/data/harnesses/code/skills/design/data/elevation/material-3-tonal-elevation.md +21 -0
  88. package/data/harnesses/code/skills/design/data/elevation/neobrutalist-hard-offset.md +19 -0
  89. package/data/harnesses/code/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +18 -0
  90. package/data/harnesses/code/skills/design/data/elevation/notion-warm-minimal-hairline.md +17 -0
  91. package/data/harnesses/code/skills/design/data/elevation/polaris-elevation-inset-bevel.md +21 -0
  92. package/data/harnesses/code/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +19 -0
  93. package/data/harnesses/code/skills/design/data/elevation/shadcn-neutral-derived-radius.md +19 -0
  94. package/data/harnesses/code/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +18 -0
  95. package/data/harnesses/code/skills/design/data/elevation/tailwind-default-utility-scale.md +19 -0
  96. package/data/harnesses/code/skills/design/data/elevation/vercel-geist-shadow-as-border.md +20 -0
  97. package/data/harnesses/code/skills/design/data/gradients/amber-attention-fill.md +16 -0
  98. package/data/harnesses/code/skills/design/data/gradients/cloud-shadow-wash.md +16 -0
  99. package/data/harnesses/code/skills/design/data/gradients/confident-lavender-wash.md +16 -0
  100. package/data/harnesses/code/skills/design/data/gradients/ember-ship-flare.md +18 -0
  101. package/data/harnesses/code/skills/design/data/gradients/full-metal-wash.md +16 -0
  102. package/data/harnesses/code/skills/design/data/gradients/indigo-ruby-cta-band.md +18 -0
  103. package/data/harnesses/code/skills/design/data/gradients/linear-graphite-wash.md +18 -0
  104. package/data/harnesses/code/skills/design/data/gradients/marble-quartz-wash.md +16 -0
  105. package/data/harnesses/code/skills/design/data/gradients/midnight-aurora-panel.md +16 -0
  106. package/data/harnesses/code/skills/design/data/gradients/neutral-volume-fill.md +16 -0
  107. package/data/harnesses/code/skills/design/data/gradients/revenue-uptrend-fill.md +16 -0
  108. package/data/harnesses/code/skills/design/data/gradients/risk-decline-fill.md +16 -0
  109. package/data/harnesses/code/skills/design/data/gradients/signal-blue-develop.md +18 -0
  110. package/data/harnesses/code/skills/design/data/gradients/slate-mist-wash.md +16 -0
  111. package/data/harnesses/code/skills/design/data/gradients/stripe-atmosphere-mesh.md +18 -0
  112. package/data/harnesses/code/skills/design/data/gradients/teal-signal-accent.md +16 -0
  113. package/data/harnesses/code/skills/design/data/gradients/violet-magenta-promo.md +16 -0
  114. package/data/harnesses/code/skills/design/data/iconography.md +199 -0
  115. package/data/harnesses/code/skills/design/data/motion/accordion-expand.md +18 -0
  116. package/data/harnesses/code/skills/design/data/motion/destructive-hold-confirm.md +18 -0
  117. package/data/harnesses/code/skills/design/data/motion/drag-dismiss-momentum.md +18 -0
  118. package/data/harnesses/code/skills/design/data/motion/empty-state-arrive.md +18 -0
  119. package/data/harnesses/code/skills/design/data/motion/hover-lift.md +18 -0
  120. package/data/harnesses/code/skills/design/data/motion/modal-center-arrive.md +18 -0
  121. package/data/harnesses/code/skills/design/data/motion/number-ticker-roll.md +18 -0
  122. package/data/harnesses/code/skills/design/data/motion/onboarding-bounce.md +18 -0
  123. package/data/harnesses/code/skills/design/data/motion/panel-slide.md +18 -0
  124. package/data/harnesses/code/skills/design/data/motion/press-feedback.md +18 -0
  125. package/data/harnesses/code/skills/design/data/motion/progress-linear-loop.md +18 -0
  126. package/data/harnesses/code/skills/design/data/motion/route-crossfade.md +18 -0
  127. package/data/harnesses/code/skills/design/data/motion/rubber-band-overscroll.md +18 -0
  128. package/data/harnesses/code/skills/design/data/motion/skeleton-shimmer.md +18 -0
  129. package/data/harnesses/code/skills/design/data/motion/stagger-arrive.md +18 -0
  130. package/data/harnesses/code/skills/design/data/motion/toast-enter-stack.md +18 -0
  131. package/data/harnesses/code/skills/design/data/motion/tooltip-chain-instant.md +18 -0
  132. package/data/harnesses/code/skills/design/data/motion/trigger-anchored-reveal.md +18 -0
  133. package/data/harnesses/code/skills/design/data/tells.csv +34 -0
  134. package/data/harnesses/code/skills/design/data/typography/anton-work-sans.md +17 -0
  135. package/data/harnesses/code/skills/design/data/typography/archivo-black-archivo.md +17 -0
  136. package/data/harnesses/code/skills/design/data/typography/bitter-karla.md +17 -0
  137. package/data/harnesses/code/skills/design/data/typography/dm-serif-dm-sans.md +17 -0
  138. package/data/harnesses/code/skills/design/data/typography/fraunces-inter.md +17 -0
  139. package/data/harnesses/code/skills/design/data/typography/geist-geist-mono.md +17 -0
  140. package/data/harnesses/code/skills/design/data/typography/hubot-sans-mona-sans.md +17 -0
  141. package/data/harnesses/code/skills/design/data/typography/ibm-plex-sans-operator-single-family.md +17 -0
  142. package/data/harnesses/code/skills/design/data/typography/instrument-serif-instrument-sans.md +17 -0
  143. package/data/harnesses/code/skills/design/data/typography/inter-operator-single-family.md +17 -0
  144. package/data/harnesses/code/skills/design/data/typography/libre-baskerville-libre-franklin.md +17 -0
  145. package/data/harnesses/code/skills/design/data/typography/newsreader-inter.md +17 -0
  146. package/data/harnesses/code/skills/design/data/typography/playfair-display-source-sans.md +17 -0
  147. package/data/harnesses/code/skills/design/data/typography/public-sans-operator-single-family.md +17 -0
  148. package/data/harnesses/code/skills/design/data/typography/sohne-inter-fintech.md +17 -0
  149. package/data/harnesses/code/skills/design/data/typography/source-serif-source-sans.md +17 -0
  150. package/data/harnesses/code/skills/design/data/typography/space-grotesk-work-sans-space-mono.md +17 -0
  151. package/data/harnesses/code/skills/design/data/typography/spectral-manrope.md +17 -0
  152. package/data/harnesses/code/skills/design/data/voices/bright-collaborator.md +29 -0
  153. package/data/harnesses/code/skills/design/data/voices/direct-operator.md +29 -0
  154. package/data/harnesses/code/skills/design/data/voices/earnest-helper.md +29 -0
  155. package/data/harnesses/code/skills/design/data/voices/editorial-composed.md +29 -0
  156. package/data/harnesses/code/skills/design/data/voices/quiet-concierge.md +29 -0
  157. package/data/harnesses/code/skills/design/data/voices/warm-guide.md +29 -0
  158. package/data/harnesses/code/skills/design/design-md/SCHEMA.md +179 -0
  159. package/data/harnesses/code/skills/design/design-md/index.csv +67 -0
  160. package/data/harnesses/code/skills/design/design-md/library/airbnb.md +207 -0
  161. package/data/harnesses/code/skills/design/design-md/library/airtable.md +205 -0
  162. package/data/harnesses/code/skills/design/design-md/library/anthropic-claude.md +203 -0
  163. package/data/harnesses/code/skills/design/design-md/library/apple.md +206 -0
  164. package/data/harnesses/code/skills/design/design-md/library/binance.md +210 -0
  165. package/data/harnesses/code/skills/design/design-md/library/bmw.md +210 -0
  166. package/data/harnesses/code/skills/design/design-md/library/cal.md +209 -0
  167. package/data/harnesses/code/skills/design/design-md/library/clay.md +204 -0
  168. package/data/harnesses/code/skills/design/design-md/library/clickhouse.md +205 -0
  169. package/data/harnesses/code/skills/design/design-md/library/cohere.md +205 -0
  170. package/data/harnesses/code/skills/design/design-md/library/coinbase.md +198 -0
  171. package/data/harnesses/code/skills/design/design-md/library/composio.md +198 -0
  172. package/data/harnesses/code/skills/design/design-md/library/cursor.md +197 -0
  173. package/data/harnesses/code/skills/design/design-md/library/elevenlabs.md +199 -0
  174. package/data/harnesses/code/skills/design/design-md/library/expo.md +200 -0
  175. package/data/harnesses/code/skills/design/design-md/library/figma.md +199 -0
  176. package/data/harnesses/code/skills/design/design-md/library/framer.md +202 -0
  177. package/data/harnesses/code/skills/design/design-md/library/hashicorp.md +205 -0
  178. package/data/harnesses/code/skills/design/design-md/library/ibm.md +205 -0
  179. package/data/harnesses/code/skills/design/design-md/library/intercom.md +204 -0
  180. package/data/harnesses/code/skills/design/design-md/library/kraken.md +200 -0
  181. package/data/harnesses/code/skills/design/design-md/library/linear-app.md +198 -0
  182. package/data/harnesses/code/skills/design/design-md/library/lovable.md +199 -0
  183. package/data/harnesses/code/skills/design/design-md/library/meta.md +204 -0
  184. package/data/harnesses/code/skills/design/design-md/library/minimax.md +204 -0
  185. package/data/harnesses/code/skills/design/design-md/library/mintlify.md +210 -0
  186. package/data/harnesses/code/skills/design/design-md/library/miro.md +209 -0
  187. package/data/harnesses/code/skills/design/design-md/library/mistral-ai.md +201 -0
  188. package/data/harnesses/code/skills/design/design-md/library/mongodb.md +201 -0
  189. package/data/harnesses/code/skills/design/design-md/library/notion.md +204 -0
  190. package/data/harnesses/code/skills/design/design-md/library/nvidia.md +215 -0
  191. package/data/harnesses/code/skills/design/design-md/library/ollama.md +213 -0
  192. package/data/harnesses/code/skills/design/design-md/library/opencode-ai.md +216 -0
  193. package/data/harnesses/code/skills/design/design-md/library/posthog.md +218 -0
  194. package/data/harnesses/code/skills/design/design-md/library/raycast.md +214 -0
  195. package/data/harnesses/code/skills/design/design-md/library/replicate.md +202 -0
  196. package/data/harnesses/code/skills/design/design-md/library/resend.md +203 -0
  197. package/data/harnesses/code/skills/design/design-md/library/revolut.md +203 -0
  198. package/data/harnesses/code/skills/design/design-md/library/runwayml.md +203 -0
  199. package/data/harnesses/code/skills/design/design-md/library/sanity.md +200 -0
  200. package/data/harnesses/code/skills/design/design-md/library/sentry.md +201 -0
  201. package/data/harnesses/code/skills/design/design-md/library/shopify.md +202 -0
  202. package/data/harnesses/code/skills/design/design-md/library/slack.md +202 -0
  203. package/data/harnesses/code/skills/design/design-md/library/spacex.md +206 -0
  204. package/data/harnesses/code/skills/design/design-md/library/spotify.md +206 -0
  205. package/data/harnesses/code/skills/design/design-md/library/stripe.md +196 -0
  206. package/data/harnesses/code/skills/design/design-md/library/supabase.md +196 -0
  207. package/data/harnesses/code/skills/design/design-md/library/superhuman.md +194 -0
  208. package/data/harnesses/code/skills/design/design-md/library/tesla.md +198 -0
  209. package/data/harnesses/code/skills/design/design-md/library/theverge.md +199 -0
  210. package/data/harnesses/code/skills/design/design-md/library/together-ai.md +193 -0
  211. package/data/harnesses/code/skills/design/design-md/library/uber.md +195 -0
  212. package/data/harnesses/code/skills/design/design-md/library/vercel.md +195 -0
  213. package/data/harnesses/code/skills/design/design-md/library/voltagent.md +197 -0
  214. package/data/harnesses/code/skills/design/design-md/library/warp.md +196 -0
  215. package/data/harnesses/code/skills/design/design-md/library/webflow.md +197 -0
  216. package/data/harnesses/code/skills/design/design-md/library/wired.md +197 -0
  217. package/data/harnesses/code/skills/design/design-md/library/wise.md +198 -0
  218. package/data/harnesses/code/skills/design/design-md/library/x-ai.md +199 -0
  219. package/data/harnesses/code/skills/design/design-md/library/zapier.md +198 -0
  220. package/data/harnesses/code/skills/design/design-md/nurix.md +214 -0
  221. package/data/harnesses/code/skills/design/design-md/variants/editorial-luxury.md +184 -0
  222. package/data/harnesses/code/skills/design/design-md/variants/expressive-saas.md +216 -0
  223. package/data/harnesses/code/skills/design/design-md/variants/quiet-premium.md +211 -0
  224. package/data/harnesses/code/skills/design/design-md/variants/terse-dense-operator.md +212 -0
  225. package/data/harnesses/code/skills/design/design-md/variants/warm-approachable.md +216 -0
  226. package/data/harnesses/code/skills/design/references/compose.md +23 -0
  227. package/data/harnesses/code/skills/design/references/content.md +28 -0
  228. package/data/harnesses/code/skills/design/references/emission.md +21 -0
  229. package/data/harnesses/code/skills/design/references/existing-apps.md +27 -0
  230. package/data/harnesses/code/skills/design/references/intake.md +36 -0
  231. package/data/harnesses/code/skills/design/references/object-pass.md +24 -0
  232. package/data/harnesses/code/skills/design/references/ship-gate.md +29 -0
  233. package/data/harnesses/code/skills/design/references/ux-patterns/Readme.md +195 -0
  234. package/data/harnesses/code/skills/design/references/ux-patterns/ai-layer.md +49 -0
  235. package/data/harnesses/code/skills/design/references/ux-patterns/attributes-lifecycle.md +43 -0
  236. package/data/harnesses/code/skills/design/references/ux-patterns/container-choice.md +44 -0
  237. package/data/harnesses/code/skills/design/references/ux-patterns/creation-paths.md +46 -0
  238. package/data/harnesses/code/skills/design/references/ux-patterns/dashboards.md +42 -0
  239. package/data/harnesses/code/skills/design/references/ux-patterns/modes.md +42 -0
  240. package/data/harnesses/code/skills/design/references/ux-patterns/object-model.md +46 -0
  241. package/data/harnesses/code/skills/design/references/ux-patterns/page-archetype.md +48 -0
  242. package/data/harnesses/code/skills/design/references/ux-patterns/promotion-demotion.md +37 -0
  243. package/data/harnesses/code/skills/design/references/ux-patterns/settings.md +42 -0
  244. package/data/harnesses/code/skills/design/references/ux-patterns/standard-pages.md +46 -0
  245. package/data/harnesses/code/skills/design/references/ux-patterns/state-matrix.md +41 -0
  246. package/data/harnesses/code/skills/design/references/ux-patterns/table-mechanics.md +48 -0
  247. package/data/harnesses/code/skills/design/references/ux-patterns/verbs.md +45 -0
  248. package/data/harnesses/code/skills/design/references/ux-patterns/viewer-context.md +40 -0
  249. package/data/harnesses/code/skills/design/scripts/README-validator.md +27 -0
  250. package/data/harnesses/code/skills/design/scripts/select-chart.mjs +596 -0
  251. package/data/harnesses/code/skills/design/scripts/validate-design-md.mjs +1198 -0
  252. package/data/harnesses/discussion/CLAUDE.md +1 -1
  253. package/data/harnesses/discussion/agents/discussion-baseline.md +27 -2
  254. package/data/harnesses/discussion/harness.json +2 -2
  255. package/data/harnesses/discussion/rules/artifacts.md +2 -0
  256. package/data/harnesses/discussion/rules/method.md +5 -1
  257. package/package.json +1 -1
  258. package/data/harnesses/code/skills/design/data/catalog/rules.csv +0 -137
  259. package/data/harnesses/code/skills/design/data/combinations/Readme.md +0 -33
  260. package/data/harnesses/code/skills/design/data/combinations/accent-presets.md +0 -113
  261. package/data/harnesses/code/skills/design/data/combinations/charts.csv +0 -33
  262. package/data/harnesses/code/skills/design/data/combinations/fonts-known.json +0 -448
  263. package/data/harnesses/code/skills/design/data/combinations/icons.csv +0 -157
  264. package/data/harnesses/code/skills/design/data/combinations/landing.csv +0 -38
  265. package/data/harnesses/code/skills/design/data/combinations/lucide-names.json +0 -2001
  266. package/data/harnesses/code/skills/design/data/combinations/manifest.json +0 -330
  267. package/data/harnesses/code/skills/design/data/combinations/motion.csv +0 -10
  268. package/data/harnesses/code/skills/design/data/combinations/palettes.csv +0 -92
  269. package/data/harnesses/code/skills/design/data/combinations/product-router.csv +0 -80
  270. package/data/harnesses/code/skills/design/data/combinations/styles.csv +0 -67
  271. package/data/harnesses/code/skills/design/data/combinations/typography.csv +0 -64
  272. package/data/harnesses/code/skills/design/data/design-md/SCHEMA.md +0 -106
  273. package/data/harnesses/code/skills/design/data/design-md/library/airbnb.md +0 -154
  274. package/data/harnesses/code/skills/design/data/design-md/library/airtable.md +0 -151
  275. package/data/harnesses/code/skills/design/data/design-md/library/anthropic-claude.md +0 -139
  276. package/data/harnesses/code/skills/design/data/design-md/library/apple.md +0 -139
  277. package/data/harnesses/code/skills/design/data/design-md/library/binance.md +0 -140
  278. package/data/harnesses/code/skills/design/data/design-md/library/bmw.md +0 -140
  279. package/data/harnesses/code/skills/design/data/design-md/library/cal.md +0 -140
  280. package/data/harnesses/code/skills/design/data/design-md/library/clay.md +0 -139
  281. package/data/harnesses/code/skills/design/data/design-md/library/clickhouse.md +0 -139
  282. package/data/harnesses/code/skills/design/data/design-md/library/cohere.md +0 -147
  283. package/data/harnesses/code/skills/design/data/design-md/library/coinbase.md +0 -156
  284. package/data/harnesses/code/skills/design/data/design-md/library/composio.md +0 -138
  285. package/data/harnesses/code/skills/design/data/design-md/library/cursor.md +0 -138
  286. package/data/harnesses/code/skills/design/data/design-md/library/elevenlabs.md +0 -137
  287. package/data/harnesses/code/skills/design/data/design-md/library/expo.md +0 -148
  288. package/data/harnesses/code/skills/design/data/design-md/library/figma.md +0 -141
  289. package/data/harnesses/code/skills/design/data/design-md/library/framer.md +0 -156
  290. package/data/harnesses/code/skills/design/data/design-md/library/hashicorp.md +0 -140
  291. package/data/harnesses/code/skills/design/data/design-md/library/ibm.md +0 -153
  292. package/data/harnesses/code/skills/design/data/design-md/library/intercom.md +0 -158
  293. package/data/harnesses/code/skills/design/data/design-md/library/kraken.md +0 -156
  294. package/data/harnesses/code/skills/design/data/design-md/library/linear-app.md +0 -122
  295. package/data/harnesses/code/skills/design/data/design-md/library/lovable.md +0 -140
  296. package/data/harnesses/code/skills/design/data/design-md/library/meta.md +0 -139
  297. package/data/harnesses/code/skills/design/data/design-md/library/minimax.md +0 -139
  298. package/data/harnesses/code/skills/design/data/design-md/library/mintlify.md +0 -139
  299. package/data/harnesses/code/skills/design/data/design-md/library/miro.md +0 -153
  300. package/data/harnesses/code/skills/design/data/design-md/library/mistral-ai.md +0 -140
  301. package/data/harnesses/code/skills/design/data/design-md/library/mongodb.md +0 -155
  302. package/data/harnesses/code/skills/design/data/design-md/library/notion.md +0 -140
  303. package/data/harnesses/code/skills/design/data/design-md/library/nvidia.md +0 -141
  304. package/data/harnesses/code/skills/design/data/design-md/library/ollama.md +0 -145
  305. package/data/harnesses/code/skills/design/data/design-md/library/opencode-ai.md +0 -142
  306. package/data/harnesses/code/skills/design/data/design-md/library/posthog.md +0 -152
  307. package/data/harnesses/code/skills/design/data/design-md/library/raycast.md +0 -137
  308. package/data/harnesses/code/skills/design/data/design-md/library/replicate.md +0 -140
  309. package/data/harnesses/code/skills/design/data/design-md/library/resend.md +0 -170
  310. package/data/harnesses/code/skills/design/data/design-md/library/revolut.md +0 -145
  311. package/data/harnesses/code/skills/design/data/design-md/library/runwayml.md +0 -137
  312. package/data/harnesses/code/skills/design/data/design-md/library/sanity.md +0 -168
  313. package/data/harnesses/code/skills/design/data/design-md/library/sentry.md +0 -163
  314. package/data/harnesses/code/skills/design/data/design-md/library/shopify.md +0 -147
  315. package/data/harnesses/code/skills/design/data/design-md/library/slack.md +0 -158
  316. package/data/harnesses/code/skills/design/data/design-md/library/spacex.md +0 -171
  317. package/data/harnesses/code/skills/design/data/design-md/library/spotify.md +0 -166
  318. package/data/harnesses/code/skills/design/data/design-md/library/stripe.md +0 -160
  319. package/data/harnesses/code/skills/design/data/design-md/library/supabase.md +0 -173
  320. package/data/harnesses/code/skills/design/data/design-md/library/superhuman.md +0 -145
  321. package/data/harnesses/code/skills/design/data/design-md/library/tesla.md +0 -153
  322. package/data/harnesses/code/skills/design/data/design-md/library/theverge.md +0 -167
  323. package/data/harnesses/code/skills/design/data/design-md/library/together-ai.md +0 -140
  324. package/data/harnesses/code/skills/design/data/design-md/library/uber.md +0 -140
  325. package/data/harnesses/code/skills/design/data/design-md/library/vercel.md +0 -140
  326. package/data/harnesses/code/skills/design/data/design-md/library/voltagent.md +0 -130
  327. package/data/harnesses/code/skills/design/data/design-md/library/warp.md +0 -140
  328. package/data/harnesses/code/skills/design/data/design-md/library/webflow.md +0 -140
  329. package/data/harnesses/code/skills/design/data/design-md/library/wired.md +0 -139
  330. package/data/harnesses/code/skills/design/data/design-md/library/wise.md +0 -137
  331. package/data/harnesses/code/skills/design/data/design-md/library/x-ai.md +0 -138
  332. package/data/harnesses/code/skills/design/data/design-md/library/zapier.md +0 -158
  333. package/data/harnesses/code/skills/design/data/design-md/nurix.md +0 -138
  334. package/data/harnesses/code/skills/design/data/design-tokens/SCHEMA.md +0 -695
  335. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.resolver.json +0 -20
  336. package/data/harnesses/code/skills/design/data/design-tokens/airbnb/design.tokens.json +0 -1272
  337. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.resolver.json +0 -20
  338. package/data/harnesses/code/skills/design/data/design-tokens/airtable/design.tokens.json +0 -1268
  339. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.resolver.json +0 -20
  340. package/data/harnesses/code/skills/design/data/design-tokens/anthropic-claude/design.tokens.json +0 -1273
  341. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.resolver.json +0 -20
  342. package/data/harnesses/code/skills/design/data/design-tokens/apple/design.tokens.json +0 -1262
  343. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.resolver.json +0 -20
  344. package/data/harnesses/code/skills/design/data/design-tokens/binance/design.tokens.json +0 -1257
  345. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.resolver.json +0 -20
  346. package/data/harnesses/code/skills/design/data/design-tokens/bmw/design.tokens.json +0 -1270
  347. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.resolver.json +0 -20
  348. package/data/harnesses/code/skills/design/data/design-tokens/cal/design.tokens.json +0 -1270
  349. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.resolver.json +0 -20
  350. package/data/harnesses/code/skills/design/data/design-tokens/clay/design.tokens.json +0 -1261
  351. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.resolver.json +0 -20
  352. package/data/harnesses/code/skills/design/data/design-tokens/clickhouse/design.tokens.json +0 -1268
  353. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.resolver.json +0 -20
  354. package/data/harnesses/code/skills/design/data/design-tokens/cohere/design.tokens.json +0 -1281
  355. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.resolver.json +0 -20
  356. package/data/harnesses/code/skills/design/data/design-tokens/coinbase/design.tokens.json +0 -1262
  357. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.resolver.json +0 -20
  358. package/data/harnesses/code/skills/design/data/design-tokens/composio/design.tokens.json +0 -1271
  359. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.resolver.json +0 -20
  360. package/data/harnesses/code/skills/design/data/design-tokens/cursor/design.tokens.json +0 -1276
  361. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.resolver.json +0 -20
  362. package/data/harnesses/code/skills/design/data/design-tokens/elevenlabs/design.tokens.json +0 -1293
  363. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.resolver.json +0 -20
  364. package/data/harnesses/code/skills/design/data/design-tokens/expo/design.tokens.json +0 -1270
  365. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.resolver.json +0 -20
  366. package/data/harnesses/code/skills/design/data/design-tokens/figma/design.tokens.json +0 -1276
  367. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.resolver.json +0 -20
  368. package/data/harnesses/code/skills/design/data/design-tokens/framer/design.tokens.json +0 -1267
  369. package/data/harnesses/code/skills/design/data/design-tokens/goldens.json +0 -251
  370. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.resolver.json +0 -20
  371. package/data/harnesses/code/skills/design/data/design-tokens/hashicorp/design.tokens.json +0 -1273
  372. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.resolver.json +0 -20
  373. package/data/harnesses/code/skills/design/data/design-tokens/ibm/design.tokens.json +0 -1286
  374. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.resolver.json +0 -20
  375. package/data/harnesses/code/skills/design/data/design-tokens/intercom/design.tokens.json +0 -1290
  376. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.resolver.json +0 -20
  377. package/data/harnesses/code/skills/design/data/design-tokens/kraken/design.tokens.json +0 -1270
  378. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.resolver.json +0 -23
  379. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.dark.json +0 -599
  380. package/data/harnesses/code/skills/design/data/design-tokens/linear-app/design.tokens.json +0 -1272
  381. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.resolver.json +0 -20
  382. package/data/harnesses/code/skills/design/data/design-tokens/lovable/design.tokens.json +0 -1267
  383. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.resolver.json +0 -20
  384. package/data/harnesses/code/skills/design/data/design-tokens/meta/design.tokens.json +0 -1289
  385. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.resolver.json +0 -20
  386. package/data/harnesses/code/skills/design/data/design-tokens/minimax/design.tokens.json +0 -1258
  387. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.resolver.json +0 -20
  388. package/data/harnesses/code/skills/design/data/design-tokens/mintlify/design.tokens.json +0 -1284
  389. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.resolver.json +0 -20
  390. package/data/harnesses/code/skills/design/data/design-tokens/miro/design.tokens.json +0 -1291
  391. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.resolver.json +0 -20
  392. package/data/harnesses/code/skills/design/data/design-tokens/mistral-ai/design.tokens.json +0 -1263
  393. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.resolver.json +0 -20
  394. package/data/harnesses/code/skills/design/data/design-tokens/mongodb/design.tokens.json +0 -1270
  395. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.resolver.json +0 -20
  396. package/data/harnesses/code/skills/design/data/design-tokens/notion/design.tokens.json +0 -1261
  397. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.resolver.json +0 -20
  398. package/data/harnesses/code/skills/design/data/design-tokens/nurix/design.tokens.json +0 -1209
  399. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.resolver.json +0 -20
  400. package/data/harnesses/code/skills/design/data/design-tokens/nvidia/design.tokens.json +0 -1265
  401. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.resolver.json +0 -20
  402. package/data/harnesses/code/skills/design/data/design-tokens/ollama/design.tokens.json +0 -1253
  403. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.resolver.json +0 -20
  404. package/data/harnesses/code/skills/design/data/design-tokens/opencode-ai/design.tokens.json +0 -1268
  405. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.resolver.json +0 -20
  406. package/data/harnesses/code/skills/design/data/design-tokens/posthog/design.tokens.json +0 -1261
  407. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.resolver.json +0 -20
  408. package/data/harnesses/code/skills/design/data/design-tokens/raycast/design.tokens.json +0 -1263
  409. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.resolver.json +0 -20
  410. package/data/harnesses/code/skills/design/data/design-tokens/replicate/design.tokens.json +0 -1266
  411. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.resolver.json +0 -23
  412. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.dark.json +0 -623
  413. package/data/harnesses/code/skills/design/data/design-tokens/resend/design.tokens.json +0 -1276
  414. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.resolver.json +0 -20
  415. package/data/harnesses/code/skills/design/data/design-tokens/revolut/design.tokens.json +0 -1264
  416. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.resolver.json +0 -20
  417. package/data/harnesses/code/skills/design/data/design-tokens/runwayml/design.tokens.json +0 -1268
  418. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.resolver.json +0 -20
  419. package/data/harnesses/code/skills/design/data/design-tokens/sanity/design.tokens.json +0 -1270
  420. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.resolver.json +0 -20
  421. package/data/harnesses/code/skills/design/data/design-tokens/sentry/design.tokens.json +0 -1288
  422. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.resolver.json +0 -20
  423. package/data/harnesses/code/skills/design/data/design-tokens/shopify/design.tokens.json +0 -1272
  424. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.resolver.json +0 -20
  425. package/data/harnesses/code/skills/design/data/design-tokens/slack/design.tokens.json +0 -1265
  426. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.resolver.json +0 -20
  427. package/data/harnesses/code/skills/design/data/design-tokens/spacex/design.tokens.json +0 -1287
  428. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.resolver.json +0 -20
  429. package/data/harnesses/code/skills/design/data/design-tokens/spotify/design.tokens.json +0 -1286
  430. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.resolver.json +0 -20
  431. package/data/harnesses/code/skills/design/data/design-tokens/stripe/design.tokens.json +0 -1285
  432. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.resolver.json +0 -20
  433. package/data/harnesses/code/skills/design/data/design-tokens/supabase/design.tokens.json +0 -1287
  434. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.resolver.json +0 -20
  435. package/data/harnesses/code/skills/design/data/design-tokens/superhuman/design.tokens.json +0 -1278
  436. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.resolver.json +0 -20
  437. package/data/harnesses/code/skills/design/data/design-tokens/tesla/design.tokens.json +0 -1269
  438. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.resolver.json +0 -20
  439. package/data/harnesses/code/skills/design/data/design-tokens/theverge/design.tokens.json +0 -1285
  440. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.resolver.json +0 -20
  441. package/data/harnesses/code/skills/design/data/design-tokens/together-ai/design.tokens.json +0 -1303
  442. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.resolver.json +0 -20
  443. package/data/harnesses/code/skills/design/data/design-tokens/uber/design.tokens.json +0 -1274
  444. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.resolver.json +0 -20
  445. package/data/harnesses/code/skills/design/data/design-tokens/vercel/design.tokens.json +0 -1296
  446. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.resolver.json +0 -23
  447. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.dark.json +0 -612
  448. package/data/harnesses/code/skills/design/data/design-tokens/voltagent/design.tokens.json +0 -1282
  449. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.resolver.json +0 -20
  450. package/data/harnesses/code/skills/design/data/design-tokens/warp/design.tokens.json +0 -1287
  451. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.resolver.json +0 -20
  452. package/data/harnesses/code/skills/design/data/design-tokens/webflow/design.tokens.json +0 -1268
  453. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.resolver.json +0 -20
  454. package/data/harnesses/code/skills/design/data/design-tokens/wired/design.tokens.json +0 -1276
  455. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.resolver.json +0 -20
  456. package/data/harnesses/code/skills/design/data/design-tokens/wise/design.tokens.json +0 -1273
  457. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.resolver.json +0 -20
  458. package/data/harnesses/code/skills/design/data/design-tokens/x-ai/design.tokens.json +0 -1296
  459. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.resolver.json +0 -20
  460. package/data/harnesses/code/skills/design/data/design-tokens/zapier/design.tokens.json +0 -1286
  461. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/command-center.tsx +0 -249
  462. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/create-edit.tsx +0 -249
  463. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/dashboard.tsx +0 -225
  464. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/entity-detail.tsx +0 -249
  465. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/list-detail.tsx +0 -224
  466. package/data/harnesses/code/skills/design/data/operator-pack/exemplars/log-stream.tsx +0 -249
  467. package/data/harnesses/code/skills/design/data/operator-pack/fixtures.md +0 -88
  468. package/data/harnesses/code/skills/design/data/operator-pack/surface-catalog.md +0 -132
  469. package/data/harnesses/code/skills/design/data/operator-pack/trust-rubric.md +0 -76
  470. package/data/harnesses/code/skills/design/references/create.md +0 -173
  471. package/data/harnesses/code/skills/design/references/diagnosis.md +0 -108
  472. package/data/harnesses/code/skills/design/references/hard-rules.md +0 -177
  473. package/data/harnesses/code/skills/design/references/improve.md +0 -116
  474. package/data/harnesses/code/skills/design/references/interaction.md +0 -77
  475. package/data/harnesses/code/skills/design/references/introspect.md +0 -100
  476. package/data/harnesses/code/skills/design/references/lifecycle.md +0 -73
  477. package/data/harnesses/code/skills/design/references/personality.md +0 -575
  478. package/data/harnesses/code/skills/design/references/structure.md +0 -159
  479. package/data/harnesses/code/skills/design/scripts/convert-design-md.mjs +0 -1312
  480. package/data/harnesses/code/skills/design/scripts/derive-personality.mjs +0 -1498
  481. package/data/harnesses/code/skills/design/scripts/generate-fixtures.mjs +0 -551
  482. package/data/harnesses/code/skills/design/scripts/lib/checks.mjs +0 -1092
  483. package/data/harnesses/code/skills/design/scripts/lib/golden.mjs +0 -26
  484. package/data/harnesses/code/skills/design/scripts/lib/vocabulary.mjs +0 -65
  485. package/data/harnesses/code/skills/design/scripts/phase-gate.mjs +0 -538
  486. package/data/harnesses/code/skills/design/scripts/preship-sweep.mjs +0 -312
  487. package/data/harnesses/code/skills/design/scripts/render-rung.mjs +0 -890
  488. package/data/harnesses/code/skills/design/scripts/scaffold.mjs +0 -769
  489. package/data/harnesses/code/skills/design/scripts/self-integrity.mjs +0 -675
  490. package/data/harnesses/code/skills/design/scripts/snapshot-goldens.mjs +0 -164
  491. package/data/harnesses/code/skills/design/scripts/validate-combinations.mjs +0 -439
@@ -1,249 +0,0 @@
1
- // skills/design/data/operator-pack/exemplars/command-center.tsx — reference render — imitate the ambition and the composition; the project's tokens supply the look.
2
- // Surface: baseline
3
- import { useMemo, useState } from "react";
4
- import { Activity, AlertTriangle, ArrowDown, ArrowUp, Hand, Radio, RefreshCw, ShieldAlert, Signal, Undo2, WifiOff, type LucideIcon } from "lucide-react";
5
- import { Button } from "@nurix/components/button";
6
- import { Badge } from "@nurix/components/badge";
7
- import { Card } from "@nurix/components/card";
8
- import { Skeleton } from "@nurix/components/skeleton";
9
- import { EmptyState } from "@nurix/components/empty-state";
10
- import { Alert, AlertTitle, AlertDescription } from "@nurix/components/alert";
11
- import { ScrollArea } from "@nurix/components/scroll-area";
12
- import { Sparkline } from "@nurix/components/sparkline";
13
- import { Kbd } from "@nurix/components/kbd";
14
- import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogBody, DialogFooter, DialogClose } from "@nurix/components/dialog";
15
- import { Statistics, StatisticsHeader, StatisticsHeading, StatisticsTitle, StatisticsMetric, StatisticsValue, StatisticsUnit, StatisticsTrend } from "@nurix/components/statistics";
16
- type SurfaceState = "loading" | "ready" | "error";
17
- type PanelStatus = "ok" | "degraded" | "down" | "loading";
18
- type Sentiment = "negative" | "neutral" | "positive";
19
- interface HealthPanel { key: string; label: string; status: PanelStatus; p95: number; trend: number[]; since: string; }
20
- interface StreamEvent { id: string; at: string; session: string; kind: "started" | "escalated" | "resolved" | "dropped"; detail: string; }
21
- interface Escalation { id: string; session: string; reason: string; sentiment: Sentiment; waitingSec: number; }
22
- export interface CommandCenterProps {
23
- state?: SurfaceState;
24
- panels?: HealthPanel[];
25
- events?: StreamEvent[];
26
- escalations?: Escalation[];
27
- updatedAt?: string;
28
- onRetry?: () => void;
29
- }
30
-
31
- const STATUS_TONE: Record<PanelStatus, { text: string; word: string; Icon: LucideIcon }> = {
32
- ok: { text: "text-success", word: "healthy", Icon: Signal },
33
- degraded: { text: "text-warning", word: "degraded", Icon: AlertTriangle },
34
- down: { text: "text-destructive", word: "down", Icon: WifiOff },
35
- loading: { text: "text-muted-foreground", word: "probing", Icon: RefreshCw },
36
- };
37
- const SENTIMENT_TONE: Record<Sentiment, string> = { negative: "text-destructive", neutral: "text-muted-foreground", positive: "text-success" };
38
- const KIND_LABEL: Record<StreamEvent["kind"], string> = { started: "Session started", escalated: "Escalated", resolved: "Resolved", dropped: "Call dropped" };
39
-
40
- // Format a waiting duration in seconds as a compact mm:ss string.
41
- function fmtWait(sec: number): string {
42
- return `${Math.floor(sec / 60)}:${String(sec % 60).padStart(2, "0")}`;
43
- }
44
- // One KPI tile in the health header; the numeric value carries tabular figures.
45
- function KpiTile({ label, value, unit, trend }: { label: string; value: string; unit?: string; trend?: number }) {
46
- return (
47
- <Statistics variant="card" size="md">
48
- <StatisticsHeader><StatisticsHeading><StatisticsTitle size="sm">{label}</StatisticsTitle></StatisticsHeading></StatisticsHeader>
49
- <StatisticsMetric>
50
- <StatisticsValue className="tabular-nums">{value}</StatisticsValue>
51
- {unit ? <StatisticsUnit>{unit}</StatisticsUnit> : null}
52
- {trend !== undefined ? <StatisticsTrend value={trend} pill /> : null}
53
- </StatisticsMetric>
54
- </Statistics>
55
- );
56
- }
57
- // One subsystem health panel; loads, degrades, and fails independently and names which.
58
- function HealthTile({ panel }: { panel: HealthPanel }) {
59
- if (panel.status === "loading") {
60
- return (
61
- <Card className="flex flex-col gap-3 p-4" role="status" aria-busy="true">
62
- <Skeleton className="h-4 w-24" /><Skeleton className="h-7 w-16" /><Skeleton className="h-7 w-full" />
63
- </Card>
64
- );
65
- }
66
- const tone = STATUS_TONE[panel.status];
67
- return (
68
- <Card className="flex flex-col gap-2 p-4">
69
- <div className="flex items-center justify-between">
70
- <span className="text-small font-medium text-foreground">{panel.label}</span>
71
- <span className={`flex items-center gap-1 text-caption ${tone.text}`}><tone.Icon className="size-4" aria-hidden />{tone.word}</span>
72
- </div>
73
- <div className="flex items-baseline gap-1">
74
- <span className="text-h3 tabular-nums text-foreground">{panel.p95}</span>
75
- <span className="text-caption text-muted-foreground">ms p95</span>
76
- </div>
77
- <Sparkline points={panel.trend} type="line" height={28} className="w-full text-primary" />
78
- {panel.status === "degraded" ? <p className="text-caption text-warning">Stale since {panel.since}; showing last known values.</p> : null}
79
- {panel.status === "down" ? <p className="text-caption text-destructive">Probe timed out {panel.since} ago; retrying automatically.</p> : null}
80
- </Card>
81
- );
82
- }
83
- // The live session-event stream; additions announce politely without stealing focus.
84
- function StreamPane({ events }: { events: StreamEvent[] }) {
85
- return (
86
- <Card className="flex min-h-0 flex-col">
87
- <div className="flex items-center gap-2 border-b border-border px-4 py-3">
88
- <Activity className="size-4 text-primary" aria-hidden />
89
- <h2 className="text-h3">Live session stream</h2>
90
- <Badge variant="outline" className="ml-auto tabular-nums">{events.length}</Badge>
91
- </div>
92
- <ScrollArea className="min-h-0 flex-1">
93
- {/* w-0 min-w-full pins the list to the ScrollArea viewport, so truncation paints at the visible edge */}
94
- <ul aria-live="polite" aria-relevant="additions" className="w-0 min-w-full divide-y divide-border">
95
- {events.map((e) => (
96
- <li key={e.id} className="flex items-baseline gap-3 px-4 py-2 text-small">
97
- <time className="shrink-0 font-mono tabular-nums text-muted-foreground">{e.at}</time>
98
- <span className="shrink-0 font-mono text-muted-foreground">{e.session}</span>
99
- <span className="shrink-0 text-foreground">{KIND_LABEL[e.kind]}</span>
100
- <span className="min-w-0 flex-1 truncate text-muted-foreground" title={e.detail}>{e.detail}</span>
101
- </li>
102
- ))}
103
- </ul>
104
- </ScrollArea>
105
- </Card>
106
- );
107
- }
108
- // The escalation queue: a sortable, keyboard-actionable table of sessions flagged for human takeover.
109
- function EscalationTable({ rows, sort, onToggleSort, onTakeOver, onDismiss }: { rows: Escalation[]; sort: "asc" | "desc"; onToggleSort: () => void; onTakeOver: (e: Escalation) => void; onDismiss: (e: Escalation) => void }) {
110
- return (
111
- <table className="w-full border-collapse text-small">
112
- <thead className="sticky top-0 bg-card">
113
- <tr className="border-b border-border text-left text-caption text-muted-foreground">
114
- <th scope="col" className="px-3 py-2 font-medium">Session</th>
115
- <th scope="col" className="px-3 py-2 font-medium">Reason</th>
116
- <th scope="col" className="px-3 py-2 font-medium">Sentiment</th>
117
- <th scope="col" aria-sort={sort === "asc" ? "ascending" : "descending"} className="px-3 py-2 text-right font-medium">
118
- <button type="button" onClick={onToggleSort} className="ml-auto inline-flex items-center gap-1 rounded focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2">Waiting{sort === "asc" ? <ArrowUp className="size-4" aria-hidden /> : <ArrowDown className="size-4" aria-hidden />}</button>
119
- </th>
120
- <th scope="col" className="px-3 py-2 text-right font-medium">Actions</th>
121
- </tr>
122
- </thead>
123
- <tbody>
124
- {rows.map((e) => (
125
- <tr key={e.id} className="motion-lift border-b border-border">
126
- <td className="min-w-[9ch] px-3 py-2"><span className="whitespace-nowrap font-mono tabular-nums text-foreground">{e.session}</span></td>
127
- <td className="px-3 py-2 text-muted-foreground"><span className="line-clamp-1">{e.reason}</span></td>
128
- <td className="px-3 py-2"><span className={SENTIMENT_TONE[e.sentiment]}>{e.sentiment}</span></td>
129
- <td className="px-3 py-2 text-right"><span className="font-mono tabular-nums text-foreground">{fmtWait(e.waitingSec)}</span></td>
130
- <td className="px-3 py-2">
131
- <div className="flex items-center justify-end gap-2">
132
- <Button size="sm" onClick={() => onTakeOver(e)}><Hand className="size-4" aria-hidden />Take over</Button>
133
- <Button size="sm" variant="ghost" onClick={() => onDismiss(e)}>Dismiss</Button>
134
- </div>
135
- </td>
136
- </tr>
137
- ))}
138
- </tbody>
139
- </table>
140
- );
141
- }
142
- // The whole-surface loading state: skeleton tiles mirror the KPI, health, and pane grid.
143
- function CommandSkeleton() {
144
- return (
145
- <div className="flex flex-1 flex-col gap-4" role="status" aria-busy="true">
146
- <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">{[0, 1, 2, 3].map((i) => <Skeleton key={i} className="h-20 w-full" />)}</div>
147
- <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">{[0, 1, 2, 3].map((i) => <Skeleton key={i} className="h-28 w-full" />)}</div>
148
- <div className="grid min-h-64 flex-1 grid-cols-1 gap-4 lg:grid-cols-2"><Skeleton className="h-full w-full" /><Skeleton className="h-full w-full" /></div>
149
- </div>
150
- );
151
- }
152
- // Voice-AI live-ops bridge: monitor concurrent sessions, detect escalations, intervene under time pressure.
153
- export function CommandCenter({ state = "ready", panels = SEED_PANELS, events = SEED_EVENTS, escalations = SEED_ESCALATIONS, updatedAt = "14:32:07", onRetry }: CommandCenterProps) {
154
- const [sort, setSort] = useState<"asc" | "desc">("desc");
155
- const [active, setActive] = useState<Escalation | null>(null);
156
- const [handled, setHandled] = useState<{ id: string; session: string; verb: string } | null>(null);
157
- const rows = useMemo(() => {
158
- const visible = handled ? escalations.filter((e) => e.id !== handled.id) : escalations;
159
- return [...visible].sort((a, b) => (sort === "asc" ? a.waitingSec - b.waitingSec : b.waitingSec - a.waitingSec));
160
- }, [escalations, handled, sort]);
161
- return (
162
- <main data-density-step="tighter" className="flex min-h-[100dvh] flex-col gap-4 bg-background p-4 font-sans text-foreground">
163
- <header className="flex flex-wrap items-center gap-3">
164
- <Radio className="size-5 text-primary" aria-hidden />
165
- <h1 className="text-h1">Voice operations bridge</h1>
166
- <span className="flex items-center gap-1 text-small text-success"><Signal className="size-4" aria-hidden />Live</span>
167
- <span className="ml-auto flex items-center gap-2 text-small text-muted-foreground">Updated <time className="font-mono tabular-nums">{updatedAt}</time><Kbd>/</Kbd>to search</span>
168
- </header>
169
- {state === "loading" ? <CommandSkeleton /> : state === "error" ? (
170
- <div className="flex flex-1 items-center justify-center">
171
- <Alert variant="destructive" className="max-w-md">
172
- <AlertTitle>Telemetry feed unavailable</AlertTitle>
173
- <AlertDescription>The bridge lost its link to the session gateway, so live signal is not arriving. Reconnect to resume monitoring.</AlertDescription>
174
- <Button size="sm" variant="outline" onClick={onRetry} className="mt-3"><RefreshCw className="size-4" aria-hidden />Reconnect</Button>
175
- </Alert>
176
- </div>
177
- ) : (
178
- <>
179
- <section aria-label="Key metrics" className="grid grid-cols-2 gap-4 lg:grid-cols-4">{/* mock: illustrative KPI figures */}
180
- <KpiTile label="Active sessions" value="128" trend={6} />
181
- <KpiTile label="Escalations waiting" value={String(rows.length)} trend={-3} />
182
- <KpiTile label="Median handle time" value="2:41" unit="min" />
183
- <KpiTile label="Containment rate" value="72" unit="%" trend={2} />
184
- </section>
185
- <section aria-label="Subsystem health" className="grid grid-cols-2 gap-4 lg:grid-cols-4">
186
- {panels.map((p) => <HealthTile key={p.key} panel={p} />)}
187
- </section>
188
- <section aria-label="Live operations" className="grid min-h-0 flex-1 grid-cols-1 gap-4 lg:grid-cols-2">
189
- <StreamPane events={events} />
190
- <Card className="flex min-h-0 flex-col">
191
- <div className="flex items-center gap-2 border-b border-border px-4 py-3">
192
- <ShieldAlert className="size-4 text-primary" aria-hidden />
193
- <h2 className="text-h3">Escalation queue</h2>
194
- <Badge variant="outline" className="ml-auto tabular-nums">{rows.length}</Badge>
195
- </div>
196
- <ScrollArea className="min-h-0 flex-1">
197
- {rows.length === 0 ? (
198
- <EmptyState icon={<ShieldAlert className="size-8 text-muted-foreground" aria-hidden />} title="No escalations waiting" description="Every live session is being handled by the AI agent. Flagged sessions surface here for human takeover." />
199
- ) : (
200
- <EscalationTable rows={rows} sort={sort} onToggleSort={() => setSort((s) => (s === "asc" ? "desc" : "asc"))} onTakeOver={setActive} onDismiss={(e) => setHandled({ id: e.id, session: e.session, verb: "Dismissed" })} />
201
- )}
202
- </ScrollArea>
203
- </Card>
204
- </section>
205
- {handled ? (
206
- <div role="status" className="flex items-center gap-3 rounded-md border border-border bg-muted px-4 py-2 text-small text-foreground">
207
- <span>{handled.verb} session <span className="font-mono tabular-nums">{handled.session}</span>.</span>
208
- <Button size="sm" variant="ghost" className="ml-auto" onClick={() => setHandled(null)}><Undo2 className="size-4" aria-hidden />Undo</Button>
209
- </div>
210
- ) : null}
211
- </>
212
- )}
213
- <Dialog open={!!active} onOpenChange={(open) => { if (!open) setActive(null); }}>
214
- <DialogContent variant="danger" size="sm">
215
- <DialogHeader>
216
- <DialogTitle>Take over session {active?.session}?</DialogTitle>
217
- <DialogDescription>The AI agent will be muted and the caller connected to a human. The current turn is interrupted immediately.</DialogDescription>
218
- </DialogHeader>
219
- <DialogBody className="text-small text-muted-foreground">Flagged for: {active?.reason} Waiting {active ? fmtWait(active.waitingSec) : ""}.</DialogBody>
220
- <DialogFooter>
221
- <DialogClose asChild><Button variant="ghost" size="sm">Cancel</Button></DialogClose>
222
- <Button size="sm" onClick={() => { if (active) setHandled({ id: active.id, session: active.session, verb: "Took over" }); setActive(null); }}><Hand className="size-4" aria-hidden />Take over session</Button>
223
- </DialogFooter>
224
- </DialogContent>
225
- </Dialog>
226
- </main>
227
- );
228
- }
229
- // exemplar fixture data — seeded, domain-shaped
230
- const SEED_PANELS: HealthPanel[] = [
231
- { key: "asr", label: "Speech recognition", status: "ok", p95: 214, trend: [190, 205, 198, 212, 208, 214], since: "" },
232
- { key: "llm", label: "Language model", status: "degraded", p95: 1180, trend: [420, 610, 880, 1020, 1140, 1180], since: "14:29" },
233
- { key: "tts", label: "Speech synthesis", status: "ok", p95: 96, trend: [88, 92, 90, 94, 91, 96], since: "" },
234
- { key: "tel", label: "Telephony gateway", status: "down", p95: 0, trend: [140, 150, 0, 0, 0, 0], since: "2m" },
235
- ];
236
- const SEED_EVENTS: StreamEvent[] = [
237
- { id: "v1", at: "14:32:07", session: "cs-4821", kind: "escalated", detail: "Three low-confidence recognition turns on a billing dispute; caller growing frustrated." },
238
- { id: "v2", at: "14:32:01", session: "cs-4790", kind: "resolved", detail: "Refund confirmed, transcript archived." },
239
- { id: "v3", at: "14:31:44", session: "cs-4818", kind: "started", detail: "Inbound, plan upgrade intent." },
240
- { id: "v4", at: "14:31:22", session: "cs-4802", kind: "dropped", detail: "Carrier RTP timeout on the telephony gateway before the greeting completed." },
241
- { id: "v5", at: "14:31:05", session: "cs-4795", kind: "escalated", detail: "Explicit request for a human agent." },
242
- ];
243
- const SEED_ESCALATIONS: Escalation[] = [
244
- { id: "e-01", session: "cs-4821", reason: "Three low-confidence recognition turns on a billing dispute; caller growing frustrated.", sentiment: "negative", waitingSec: 187 },
245
- { id: "e-02", session: "cs-4795", reason: "Explicit request for a human agent.", sentiment: "neutral", waitingSec: 94 },
246
- { id: "e-03", session: "cs-4766", reason: "Sentiment dropped after a failed address verification.", sentiment: "negative", waitingSec: 63 },
247
- { id: "e-04", session: "cs-4740", reason: "Refund amount exceeds the agent's autonomous limit.", sentiment: "neutral", waitingSec: 41 },
248
- { id: "e-05", session: "cs-4712", reason: "Caller confirmed resolution; awaiting supervisor sign-off.", sentiment: "positive", waitingSec: 12 },
249
- ];
@@ -1,249 +0,0 @@
1
- // skills/design/data/operator-pack/exemplars/create-edit.tsx — reference render — imitate the ambition and the composition; the project's tokens supply the look.
2
- // Surface: brand-forward (delight-allowing)
3
- import { useState, type FormEvent, type ReactNode } from "react";
4
- import { TriangleAlert, CircleCheck, Plus, RotateCcw } from "lucide-react";
5
- import { Sheet, SheetContent, SheetHeader, SheetBody, SheetFooter, SheetTitle, SheetDescription } from "@nurix/components/sheet";
6
- import { Button } from "@nurix/components/button";
7
- import { Input } from "@nurix/components/input";
8
- import { NumberInput } from "@nurix/components/number-input";
9
- import { Switch } from "@nurix/components/switch";
10
- import { Checkbox } from "@nurix/components/checkbox";
11
- import { Label } from "@nurix/components/label";
12
- import { Badge } from "@nurix/components/badge";
13
- import { Kbd } from "@nurix/components/kbd";
14
- import { Skeleton } from "@nurix/components/skeleton";
15
- import { EmptyState } from "@nurix/components/empty-state";
16
- import { Alert, AlertTitle, AlertDescription } from "@nurix/components/alert";
17
- import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "@nurix/components/native-select";
18
- import { RadioGroupSegmented, RadioGroupSegmentedItem } from "@nurix/components/radio-group";
19
-
20
- export type RuleSurfaceStatus = "loading" | "empty" | "error" | "degraded" | "ready";
21
- export type ThresholdDirection = "above" | "below";
22
- type FormPhase = "form" | "preview" | "success";
23
- type SubmitStatus = "idle" | "submitting" | "failed";
24
- type FieldErrors = Partial<Record<keyof AlertRuleDraft, string>>;
25
-
26
- export interface NotifyChannel { id: string; label: string; kind: "email" | "webhook" | "pager"; }
27
- export interface MetricOption { slug: string; label: string; unit: string; }
28
- export interface SubmitOutcome { ok: boolean; message?: string; }
29
-
30
- export interface AlertRuleDraft {
31
- name: string; metricSlug: string; direction: ThresholdDirection;
32
- threshold: number | null; channelIds: string[]; enabled: boolean;
33
- }
34
-
35
- export interface CreateEditRuleSurfaceProps {
36
- mode: "create" | "edit"; status: RuleSurfaceStatus; open: boolean;
37
- metrics: MetricOption[]; channels: NotifyChannel[]; metricsCachedAt?: string | null;
38
- initial?: Partial<AlertRuleDraft>; onSubmit: (draft: AlertRuleDraft) => Promise<SubmitOutcome>;
39
- onCancel: () => void; onAddChannel: () => void; onRetryLoad: () => void;
40
- }
41
-
42
- const BLANK_DRAFT: AlertRuleDraft = { name: "", metricSlug: "", direction: "above", threshold: null, channelIds: [], enabled: true };
43
-
44
- // Collect blocking errors for the whole draft; re-run on every render so blur and submit share one source.
45
- function validate(draft: AlertRuleDraft): FieldErrors {
46
- const errors: FieldErrors = {};
47
- if (draft.name.trim().length < 3) errors.name = "Name the rule (3 characters or more) so it's findable in the alert list.";
48
- if (!draft.metricSlug) errors.metricSlug = "Choose the metric this rule watches.";
49
- if (draft.threshold == null) errors.threshold = "Set the threshold value to compare against.";
50
- if (draft.channelIds.length === 0) errors.channelIds = "Add at least one channel so alerts have somewhere to go.";
51
- return errors;
52
- }
53
-
54
- // Label-over-input wrapper: the visible label, the control, then an inline error (or hint) below.
55
- function Field({ id, label, hint, error, htmlFor, children }: { id: string; label: string; hint?: string; error?: string; htmlFor?: string; children: ReactNode }) {
56
- return (
57
- <div className="grid gap-1.5">
58
- <Label id={`${id}-label`} htmlFor={htmlFor} className="text-small font-medium">{label}</Label>
59
- {children}
60
- {error ? <p id={`${id}-error`} className="text-small text-destructive">{error}</p> : hint ? <p className="text-small text-muted-foreground">{hint}</p> : null}
61
- </div>
62
- );
63
- }
64
- // One label/value row inside the preview summary.
65
- function PreviewRow({ label, children }: { label: string; children: ReactNode }) {
66
- return (
67
- <div className="grid grid-cols-[8rem_1fr] gap-4">
68
- <dt className="text-muted-foreground">{label}</dt>
69
- <dd className="text-foreground">{children}</dd>
70
- </div>
71
- );
72
- }
73
- // The create/edit alert-rule surface: a side sheet that opens beside the alert list and returns to it on close.
74
- export function CreateEditRuleSurface(props: CreateEditRuleSurfaceProps) {
75
- const { mode, status, open, metrics, channels, metricsCachedAt, onSubmit, onCancel, onAddChannel, onRetryLoad } = props;
76
- const [draft, setDraft] = useState<AlertRuleDraft>(() => ({ ...BLANK_DRAFT, ...props.initial }));
77
- const [touched, setTouched] = useState<Record<string, boolean>>({});
78
- const [attempted, setAttempted] = useState(false);
79
- const [phase, setPhase] = useState<FormPhase>("form");
80
- const [submitStatus, setSubmitStatus] = useState<SubmitStatus>("idle");
81
- const [submitError, setSubmitError] = useState<string | null>(null);
82
- const errors = validate(draft);
83
- const metric = metrics.find((m) => m.slug === draft.metricSlug);
84
- const selectedChannels = channels.filter((c) => draft.channelIds.includes(c.id));
85
- const isForm = status === "ready" || status === "degraded";
86
- const busy = submitStatus === "submitting";
87
- function patch<K extends keyof AlertRuleDraft>(key: K, value: AlertRuleDraft[K]) { setDraft((d) => ({ ...d, [key]: value })); }
88
- function blur(key: keyof AlertRuleDraft) { setTouched((t) => ({ ...t, [key]: true })); }
89
- const show = (key: keyof AlertRuleDraft): string | undefined => ((attempted || touched[key]) && errors[key]) || undefined;
90
- // Validate the whole draft; a clean draft advances to the preview-then-commit step.
91
- function handlePreview(event: FormEvent) {
92
- event.preventDefault();
93
- setAttempted(true);
94
- setSubmitError(null);
95
- if (Object.keys(errors).length === 0) setPhase("preview");
96
- }
97
- // Commit the reviewed draft; failure returns to the form with entries preserved and the reason inline.
98
- async function handleConfirm() {
99
- setSubmitStatus("submitting");
100
- const outcome = await onSubmit(draft);
101
- if (outcome.ok) { setSubmitStatus("idle"); setPhase("success"); }
102
- else { setSubmitStatus("failed"); setSubmitError(outcome.message ?? "The alerting service rejected the rule."); setPhase("form"); }
103
- }
104
- function reset() { setDraft({ ...BLANK_DRAFT }); setTouched({}); setAttempted(false); setSubmitStatus("idle"); setSubmitError(null); setPhase("form"); }
105
- return (
106
- <Sheet open={open} onOpenChange={(next) => { if (!next) onCancel(); }}>
107
- <SheetContent side="right" size="lg" data-density-step="looser" className="bg-surface-overlay font-sans shadow-overlay">
108
- <SheetHeader showDivider>
109
- <SheetTitle className="text-h3">{mode === "create" ? "New alert rule" : "Edit alert rule"}</SheetTitle>
110
- <SheetDescription className="text-small">Watches one metric and notifies your channels when it crosses a threshold.</SheetDescription>
111
- </SheetHeader>
112
- <SheetBody>
113
- {status === "loading" && (
114
- <div className="grid gap-6" aria-hidden="true">
115
- {[0, 1, 2, 3].map((i) => <div key={i} className="grid gap-2"><Skeleton className="h-4 w-28" /><Skeleton className="h-9 w-full" /></div>)}
116
- </div>
117
- )}
118
- {status === "error" && (
119
- <div className="grid justify-items-center gap-4 py-8 text-center" role="alert">
120
- <TriangleAlert className="size-8 text-destructive" />
121
- <p className="text-h3 text-foreground">Couldn't load this rule</p>
122
- <p className="max-w-sm text-small text-muted-foreground">The alerting service didn't respond, so its current settings aren't available. Retry, or close and reopen it from the alert list.</p>
123
- <Button variant="outline" onClick={onRetryLoad}><RotateCcw className="size-4" /> Retry</Button>
124
- </div>
125
- )}
126
- {status === "empty" && (
127
- <EmptyState
128
- icon={<Plus className="size-6 text-muted-foreground" />}
129
- title="No notification channels yet"
130
- description="An alert rule needs somewhere to send alerts. Add a channel, then come back to finish this rule."
131
- action={<Button onClick={onAddChannel}><Plus className="size-4" /> Add a channel</Button>}
132
- />
133
- )}
134
- {isForm && phase === "form" && (
135
- <form id="rule-form" onSubmit={handlePreview} className="grid gap-6">
136
- {status === "degraded" && (
137
- <Alert role="status" aria-live="polite">
138
- <TriangleAlert className="size-4" /><AlertTitle>Metric list may be stale</AlertTitle>
139
- <AlertDescription>The metrics service is unreachable, so this is a cached catalog from {metricsCachedAt}. A metric added since then won't appear here yet.</AlertDescription>
140
- </Alert>
141
- )}
142
- {submitStatus === "failed" && submitError && (
143
- <Alert variant="destructive" role="alert">
144
- <TriangleAlert className="size-4" /><AlertTitle>Rule not created</AlertTitle>
145
- <AlertDescription>{submitError} Your entries are preserved, adjust and try again.</AlertDescription>
146
- </Alert>
147
- )}
148
- <Field id="name" label="Rule name" htmlFor="name" error={show("name")}>
149
- <Input id="name" value={draft.name} placeholder="API error rate over 2 percent" onChange={(e) => patch("name", e.target.value)} onBlur={() => blur("name")} aria-invalid={show("name") ? true : undefined} aria-describedby={show("name") ? "name-error" : undefined} />
150
- </Field>
151
- <Field id="metric" label="Metric" htmlFor="metric" error={show("metricSlug")}>
152
- <Select value={draft.metricSlug} onValueChange={(v) => { patch("metricSlug", v); blur("metricSlug"); }}>
153
- <SelectTrigger id="metric" aria-invalid={show("metricSlug") ? true : undefined}><SelectValue placeholder="Choose a metric to watch" /></SelectTrigger>
154
- <SelectContent>{metrics.map((m) => <SelectItem key={m.slug} value={m.slug}>{m.label}</SelectItem>)}</SelectContent>
155
- </Select>
156
- </Field>
157
- <div className="grid grid-cols-2 gap-4">
158
- <Field id="direction" label="Condition">
159
- <RadioGroupSegmented value={draft.direction} aria-labelledby="direction-label" onValueChange={(v) => patch("direction", v as ThresholdDirection)}>
160
- <RadioGroupSegmentedItem value="above">Above</RadioGroupSegmentedItem>
161
- <RadioGroupSegmentedItem value="below">Below</RadioGroupSegmentedItem>
162
- </RadioGroupSegmented>
163
- </Field>
164
- <Field id="threshold" label={`Threshold${metric ? ` (${metric.unit})` : ""}`} htmlFor="threshold" error={show("threshold")}>
165
- <NumberInput id="threshold" className="tabular-nums" value={draft.threshold} step={0.5} allowDecimals onSave={(v) => patch("threshold", v)} onBlur={() => blur("threshold")} aria-invalid={show("threshold") ? true : undefined} aria-describedby={show("threshold") ? "threshold-error" : undefined} />
166
- </Field>
167
- </div>
168
- <Field id="channels" label="Notify channels" error={show("channelIds")}>
169
- <div className="grid gap-2" role="group" aria-labelledby="channels-label">
170
- {channels.map((c) => (
171
- <Label key={c.id} className="flex items-center gap-3 text-small font-normal">
172
- <Checkbox checked={draft.channelIds.includes(c.id)} onCheckedChange={(v) => { patch("channelIds", v ? [...draft.channelIds, c.id] : draft.channelIds.filter((id) => id !== c.id)); blur("channelIds"); }} />
173
- <span className="text-foreground">{c.label}</span>
174
- <Badge variant="outline" className="ml-auto">{c.kind}</Badge>
175
- </Label>
176
- ))}
177
- </div>
178
- </Field>
179
- <Field id="enabled" label="Enable on save">
180
- <div className="flex items-center gap-3">
181
- <Switch checked={draft.enabled} aria-labelledby="enabled-label" onCheckedChange={(v) => patch("enabled", v)} />
182
- <span className="text-small text-muted-foreground">{draft.enabled ? "Starts evaluating as soon as it's created." : "Saved paused, enable it later from the alert list."}</span>
183
- </div>
184
- </Field>
185
- </form>
186
- )}
187
- {isForm && phase === "preview" && (
188
- <div className="grid gap-4">
189
- <p className="text-h3 text-foreground">Review before creating</p>
190
- <dl className="grid gap-3 text-small">
191
- <PreviewRow label="Rule"><span className="font-medium text-foreground">{draft.name}</span></PreviewRow>
192
- <PreviewRow label="Condition">{metric?.label} goes {draft.direction} <span className="font-mono tabular-nums">{draft.threshold}</span> {metric?.unit}</PreviewRow>
193
- <PreviewRow label="Channels">{selectedChannels.map((c) => c.label).join(", ")}</PreviewRow>
194
- <PreviewRow label="State">{draft.enabled ? "Enabled on create" : "Created paused"}</PreviewRow>
195
- </dl>
196
- <p className="text-small text-muted-foreground">A rule that pages is hard to unsend, so confirm the scope before creating.</p>
197
- </div>
198
- )}
199
- {isForm && phase === "success" && (
200
- <div className="grid justify-items-center gap-4 py-8 text-center" role="status" aria-live="polite">
201
- <span className="grid size-14 place-items-center rounded-full bg-surface-raised text-success shadow-md"><CircleCheck className="size-8" /></span>
202
- <p className="text-h3 text-foreground">Alert rule created</p>
203
- <p className="max-w-sm text-small text-muted-foreground">{draft.name} is {draft.enabled ? "live and evaluating now" : "saved and paused"}. It notifies <span className="tabular-nums">{selectedChannels.length}</span> channel{selectedChannels.length === 1 ? "" : "s"} when it fires.</p>
204
- <div className="flex items-center gap-2">
205
- <Button variant="outline" onClick={onCancel}>View rule</Button>
206
- <Button onClick={reset}>Create another rule</Button>
207
- </div>
208
- </div>
209
- )}
210
- </SheetBody>
211
- {isForm && phase !== "success" && (
212
- <SheetFooter showDivider>
213
- <div className="flex w-full items-center justify-between gap-4">
214
- <p className="text-small text-muted-foreground" role="status" aria-live="polite">
215
- {busy ? "Creating rule" : phase === "form" ? <>Press <Kbd size="sm">Enter</Kbd> to review before creating.</> : "Nothing is created until you confirm."}
216
- </p>
217
- <div className="flex items-center gap-2">
218
- {phase === "form" ? (
219
- <>
220
- <Button type="button" variant="ghost" onClick={onCancel}>Cancel</Button>
221
- <Button type="submit" form="rule-form" size="lg">{mode === "create" ? "Create rule" : "Save changes"}</Button>
222
- </>
223
- ) : (
224
- <>
225
- <Button type="button" variant="ghost" onClick={() => setPhase("form")} disabled={busy}>Back to edit</Button>
226
- <Button type="button" size="lg" onClick={handleConfirm} disabled={busy}>{busy ? "Creating rule" : "Confirm and create"}</Button>
227
- </>
228
- )}
229
- </div>
230
- </div>
231
- </SheetFooter>
232
- )}
233
- </SheetContent>
234
- </Sheet>
235
- );
236
- }
237
-
238
- // exemplar fixture data — seeded, domain-shaped
239
- export const metricCatalog: MetricOption[] = [
240
- { slug: "api_error_rate", label: "API error rate", unit: "%" },
241
- { slug: "p95_latency", label: "p95 response time", unit: "ms" },
242
- { slug: "queue_depth", label: "Ingest queue depth", unit: "jobs" },
243
- ];
244
-
245
- export const notifyChannels: NotifyChannel[] = [
246
- { id: "ch_oncall_primary", label: "On-call primary", kind: "pager" },
247
- { id: "ch_platform_alerts", label: "#platform-alerts", kind: "webhook" },
248
- { id: "ch_sre_mailing", label: "sre-team mailing list", kind: "email" },
249
- ];