@nurix/etna 0.19.11 → 0.19.13

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