@nurix/etna 0.19.11 → 0.19.12

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