genoma-evolution 1.0.0

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 (445) hide show
  1. package/.brv/.obsidian/app.json +1 -0
  2. package/.brv/.obsidian/appearance.json +1 -0
  3. package/.brv/.obsidian/core-plugins.json +33 -0
  4. package/.brv/.obsidian/graph.json +22 -0
  5. package/.brv/.obsidian/workspace.json +195 -0
  6. package/.brv/Sin ti/314/201tulo 1.canvas" +1 -0
  7. package/.brv/Sin ti/314/201tulo 2.canvas" +1 -0
  8. package/.brv/Sin ti/314/201tulo.canvas" +1 -0
  9. package/.brv/_queue_status.json +1 -0
  10. package/.brv/config.json +5 -0
  11. package/.brv/context-tree/_index.md +60 -0
  12. package/.brv/context-tree/_manifest.json +165 -0
  13. package/.brv/context-tree/backend/_index.md +24 -0
  14. package/.brv/context-tree/backend/backend/_index.md +40 -0
  15. package/.brv/context-tree/backend/backend/init.abstract.md +0 -0
  16. package/.brv/context-tree/backend/backend/init.md +27 -0
  17. package/.brv/context-tree/backend/backend/init.overview.md +29 -0
  18. package/.brv/context-tree/backend/backend/job_tracker.abstract.md +1 -0
  19. package/.brv/context-tree/backend/backend/job_tracker.md +273 -0
  20. package/.brv/context-tree/backend/backend/job_tracker.overview.md +31 -0
  21. package/.brv/context-tree/backend/backend/main.abstract.md +0 -0
  22. package/.brv/context-tree/backend/backend/main.md +1292 -0
  23. package/.brv/context-tree/backend/backend/main.overview.md +30 -0
  24. package/.brv/context-tree/backend/backend/requirements.abstract.md +1 -0
  25. package/.brv/context-tree/backend/backend/requirements.md +37 -0
  26. package/.brv/context-tree/backend/backend/requirements.overview.md +28 -0
  27. package/.brv/context-tree/docs/_index.md +37 -0
  28. package/.brv/context-tree/docs/api/_index.md +54 -0
  29. package/.brv/context-tree/docs/api/context.md +11 -0
  30. package/.brv/context-tree/docs/api/hermes_api_openapi_specification.abstract.md +0 -0
  31. package/.brv/context-tree/docs/api/hermes_api_openapi_specification.md +468 -0
  32. package/.brv/context-tree/docs/api/hermes_api_openapi_specification.overview.md +44 -0
  33. package/.brv/context-tree/frontend/_index.md +48 -0
  34. package/.brv/context-tree/frontend/hermes_dashboard/_index.md +31 -0
  35. package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.abstract.md +0 -0
  36. package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.md +41 -0
  37. package/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.overview.md +34 -0
  38. package/.brv/context-tree/frontend/src/_index.md +53 -0
  39. package/.brv/context-tree/frontend/src/components/_index.md +52 -0
  40. package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.abstract.md +0 -0
  41. package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.md +161 -0
  42. package/.brv/context-tree/frontend/src/components/sidebar_navigation_component.overview.md +32 -0
  43. package/.brv/context-tree/frontend/src/context.md +10 -0
  44. package/.brv/context-tree/frontend/src/functioncallingpage.abstract.md +0 -0
  45. package/.brv/context-tree/frontend/src/functioncallingpage.md +34 -0
  46. package/.brv/context-tree/frontend/src/functioncallingpage.overview.md +26 -0
  47. package/.brv/context-tree/frontend/src/lib/_index.md +48 -0
  48. package/.brv/context-tree/frontend/src/lib/api_client_library.abstract.md +1 -0
  49. package/.brv/context-tree/frontend/src/lib/api_client_library.md +403 -0
  50. package/.brv/context-tree/frontend/src/lib/api_client_library.overview.md +69 -0
  51. package/.brv/context-tree/frontend/src/page.abstract.md +0 -0
  52. package/.brv/context-tree/frontend/src/page.md +103 -0
  53. package/.brv/context-tree/frontend/src/page.overview.md +7 -0
  54. package/.brv/context-tree/frontend/src/settingspage.abstract.md +0 -0
  55. package/.brv/context-tree/frontend/src/settingspage.md +124 -0
  56. package/.brv/context-tree/frontend/src/settingspage.overview.md +34 -0
  57. package/.brv/context-tree/frontend/src/sidebar.abstract.md +0 -0
  58. package/.brv/context-tree/frontend/src/sidebar.md +170 -0
  59. package/.brv/context-tree/frontend/src/sidebar.overview.md +25 -0
  60. package/.brv/context-tree/meta/_index.md +24 -0
  61. package/.brv/context-tree/meta/curation_context/_index.md +24 -0
  62. package/.brv/context-tree/meta/curation_context/empty_context.abstract.md +4 -0
  63. package/.brv/context-tree/meta/curation_context/empty_context.md +35 -0
  64. package/.brv/context-tree/meta/curation_context/empty_context.overview.md +20 -0
  65. package/.brv/dream-log/drm-1777341062653.json +33 -0
  66. package/.brv/dream-state.json +8 -0
  67. package/.brv/dream.lock +0 -0
  68. package/.brv/review-backups/docs/api/hermes_api_openapi_specification.md +468 -0
  69. package/.claude/settings.local.json +7 -0
  70. package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/app.json +1 -0
  71. package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/appearance.json +1 -0
  72. package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/core-plugins.json +33 -0
  73. package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/graph.json +22 -0
  74. package/.claude/worktrees/phase-2-mcp/.brv/.obsidian/workspace.json +195 -0
  75. package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo 1.canvas" +1 -0
  76. package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo 2.canvas" +1 -0
  77. package/.claude/worktrees/phase-2-mcp/.brv/Sin t/303/255tulo.canvas" +1 -0
  78. package/.claude/worktrees/phase-2-mcp/.brv/_queue_status.json +1 -0
  79. package/.claude/worktrees/phase-2-mcp/.brv/config.json +5 -0
  80. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/_index.md +60 -0
  81. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/_manifest.json +165 -0
  82. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/_index.md +24 -0
  83. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/_index.md +40 -0
  84. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.abstract.md +0 -0
  85. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.md +27 -0
  86. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/init.overview.md +29 -0
  87. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.abstract.md +1 -0
  88. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.md +273 -0
  89. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/job_tracker.overview.md +31 -0
  90. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.abstract.md +0 -0
  91. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.md +1292 -0
  92. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/main.overview.md +30 -0
  93. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.abstract.md +1 -0
  94. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.md +37 -0
  95. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/backend/backend/requirements.overview.md +28 -0
  96. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/_index.md +37 -0
  97. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/_index.md +54 -0
  98. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/context.md +11 -0
  99. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.abstract.md +0 -0
  100. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.md +468 -0
  101. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/docs/api/hermes_api_openapi_specification.overview.md +44 -0
  102. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/_index.md +48 -0
  103. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/_index.md +31 -0
  104. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.abstract.md +0 -0
  105. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.md +41 -0
  106. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/hermes_dashboard/architecture_overview.overview.md +34 -0
  107. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/_index.md +53 -0
  108. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/_index.md +52 -0
  109. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.abstract.md +0 -0
  110. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.md +161 -0
  111. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/components/sidebar_navigation_component.overview.md +32 -0
  112. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/context.md +10 -0
  113. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.abstract.md +0 -0
  114. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.md +34 -0
  115. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/functioncallingpage.overview.md +26 -0
  116. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/_index.md +48 -0
  117. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.abstract.md +1 -0
  118. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.md +403 -0
  119. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/lib/api_client_library.overview.md +69 -0
  120. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.abstract.md +0 -0
  121. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.md +103 -0
  122. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/page.overview.md +7 -0
  123. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.abstract.md +0 -0
  124. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.md +124 -0
  125. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/settingspage.overview.md +34 -0
  126. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.abstract.md +0 -0
  127. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.md +170 -0
  128. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/frontend/src/sidebar.overview.md +25 -0
  129. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/_index.md +24 -0
  130. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/_index.md +24 -0
  131. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.abstract.md +4 -0
  132. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.md +35 -0
  133. package/.claude/worktrees/phase-2-mcp/.brv/context-tree/meta/curation_context/empty_context.overview.md +20 -0
  134. package/.claude/worktrees/phase-2-mcp/.brv/dream-log/drm-1777341062653.json +33 -0
  135. package/.claude/worktrees/phase-2-mcp/.brv/dream-state.json +8 -0
  136. package/.claude/worktrees/phase-2-mcp/.brv/dream.lock +0 -0
  137. package/.claude/worktrees/phase-2-mcp/.brv/review-backups/docs/api/hermes_api_openapi_specification.md +468 -0
  138. package/.claude/worktrees/phase-2-mcp/.claude/settings.local.json +13 -0
  139. package/.claude/worktrees/phase-2-mcp/.kilocode/package-lock.json +378 -0
  140. package/.claude/worktrees/phase-2-mcp/.kilocode/package.json +5 -0
  141. package/.claude/worktrees/phase-2-mcp/AGENTS.md +5 -0
  142. package/.claude/worktrees/phase-2-mcp/CLAUDE.md +29 -0
  143. package/.claude/worktrees/phase-2-mcp/QA_AUDIT_PLAN.md +156 -0
  144. package/.claude/worktrees/phase-2-mcp/README.md +316 -0
  145. package/.claude/worktrees/phase-2-mcp/agent-agnostic-evolution-dashboard.md +405 -0
  146. package/.claude/worktrees/phase-2-mcp/backend/__init__.py +0 -0
  147. package/.claude/worktrees/phase-2-mcp/backend/collectors/__init__.py +0 -0
  148. package/.claude/worktrees/phase-2-mcp/backend/collectors/claude_code_collector.py +277 -0
  149. package/.claude/worktrees/phase-2-mcp/backend/collectors/hermes_collector.py +68 -0
  150. package/.claude/worktrees/phase-2-mcp/backend/curator.py +512 -0
  151. package/.claude/worktrees/phase-2-mcp/backend/eval/__init__.py +19 -0
  152. package/.claude/worktrees/phase-2-mcp/backend/eval/engine.py +116 -0
  153. package/.claude/worktrees/phase-2-mcp/backend/eval/scorers.py +201 -0
  154. package/.claude/worktrees/phase-2-mcp/backend/generate_dataset.py +86 -0
  155. package/.claude/worktrees/phase-2-mcp/backend/job_tracker.py +232 -0
  156. package/.claude/worktrees/phase-2-mcp/backend/main.py +1746 -0
  157. package/.claude/worktrees/phase-2-mcp/backend/mcp_server.py +250 -0
  158. package/.claude/worktrees/phase-2-mcp/backend/promethean/__init__.py +24 -0
  159. package/.claude/worktrees/phase-2-mcp/backend/promethean/cycle_orchestrator.py +270 -0
  160. package/.claude/worktrees/phase-2-mcp/backend/promethean/delta_validator.py +191 -0
  161. package/.claude/worktrees/phase-2-mcp/backend/promethean/dspy_compiler.py +315 -0
  162. package/.claude/worktrees/phase-2-mcp/backend/promethean/gepa_strategist.py +213 -0
  163. package/.claude/worktrees/phase-2-mcp/backend/promethean/models.py +260 -0
  164. package/.claude/worktrees/phase-2-mcp/backend/promethean/skill_deployer.py +195 -0
  165. package/.claude/worktrees/phase-2-mcp/backend/promethean/trace_ingestion.py +142 -0
  166. package/.claude/worktrees/phase-2-mcp/backend/requirements.txt +6 -0
  167. package/.claude/worktrees/phase-2-mcp/backend/sdd_evolve.py +459 -0
  168. package/.claude/worktrees/phase-2-mcp/backend/skill_detector.py +227 -0
  169. package/.claude/worktrees/phase-2-mcp/backend/skill_registry.py +289 -0
  170. package/.claude/worktrees/phase-2-mcp/backend/storage/__init__.py +5 -0
  171. package/.claude/worktrees/phase-2-mcp/backend/storage/run_store.py +393 -0
  172. package/.claude/worktrees/phase-2-mcp/backend/storage/schema.sql +99 -0
  173. package/.claude/worktrees/phase-2-mcp/backend/validate_evolution.py +267 -0
  174. package/.claude/worktrees/phase-2-mcp/components.json +28 -0
  175. package/.claude/worktrees/phase-2-mcp/docs/api/hermes-api.openapi.yaml +438 -0
  176. package/.claude/worktrees/phase-2-mcp/docs/hero.svg +148 -0
  177. package/.claude/worktrees/phase-2-mcp/eslint.config.mjs +18 -0
  178. package/.claude/worktrees/phase-2-mcp/install.sh +245 -0
  179. package/.claude/worktrees/phase-2-mcp/next-env.d.ts +6 -0
  180. package/.claude/worktrees/phase-2-mcp/next.config.ts +32 -0
  181. package/.claude/worktrees/phase-2-mcp/package-lock.json +11936 -0
  182. package/.claude/worktrees/phase-2-mcp/package.json +41 -0
  183. package/.claude/worktrees/phase-2-mcp/pnpm-workspace.yaml +4 -0
  184. package/.claude/worktrees/phase-2-mcp/postcss.config.mjs +7 -0
  185. package/.claude/worktrees/phase-2-mcp/public/file.svg +1 -0
  186. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Bold.otf +0 -0
  187. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Heavy.otf +0 -0
  188. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Medium.otf +0 -0
  189. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Regular.otf +0 -0
  190. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Display-Semibold.otf +0 -0
  191. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Bold.otf +0 -0
  192. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Heavy.otf +0 -0
  193. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Medium.otf +0 -0
  194. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Regular.otf +0 -0
  195. package/.claude/worktrees/phase-2-mcp/public/fonts/SF-Pro-Text-Semibold.otf +0 -0
  196. package/.claude/worktrees/phase-2-mcp/public/globe.svg +1 -0
  197. package/.claude/worktrees/phase-2-mcp/public/next.svg +1 -0
  198. package/.claude/worktrees/phase-2-mcp/public/theme-preview.html +257 -0
  199. package/.claude/worktrees/phase-2-mcp/public/vercel.svg +1 -0
  200. package/.claude/worktrees/phase-2-mcp/public/window.svg +1 -0
  201. package/.claude/worktrees/phase-2-mcp/run.sh +26 -0
  202. package/.claude/worktrees/phase-2-mcp/skills-lock.json +10 -0
  203. package/.claude/worktrees/phase-2-mcp/specs/event-schema.md +223 -0
  204. package/.claude/worktrees/phase-2-mcp/specs/examples/run.jsonl +3 -0
  205. package/.claude/worktrees/phase-2-mcp/src/app/api/[...path]/route.ts +55 -0
  206. package/.claude/worktrees/phase-2-mcp/src/app/api/auth/token/route.ts +22 -0
  207. package/.claude/worktrees/phase-2-mcp/src/app/evolution/page.tsx +589 -0
  208. package/.claude/worktrees/phase-2-mcp/src/app/favicon.ico +0 -0
  209. package/.claude/worktrees/phase-2-mcp/src/app/globals.css +321 -0
  210. package/.claude/worktrees/phase-2-mcp/src/app/layout.tsx +63 -0
  211. package/.claude/worktrees/phase-2-mcp/src/app/page.tsx +70 -0
  212. package/.claude/worktrees/phase-2-mcp/src/app/skills/page.tsx +369 -0
  213. package/.claude/worktrees/phase-2-mcp/src/components/ApiConfigCard.tsx +199 -0
  214. package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.css +1 -0
  215. package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.d.ts +1 -0
  216. package/.claude/worktrees/phase-2-mcp/src/components/ColorBends.jsx +1 -0
  217. package/.claude/worktrees/phase-2-mcp/src/components/CoreLoopToggle.tsx +111 -0
  218. package/.claude/worktrees/phase-2-mcp/src/components/EnvironmentStatus.tsx +176 -0
  219. package/.claude/worktrees/phase-2-mcp/src/components/EvolutionBackground.tsx +1 -0
  220. package/.claude/worktrees/phase-2-mcp/src/components/ReactQueryProvider.tsx +24 -0
  221. package/.claude/worktrees/phase-2-mcp/src/components/Sidebar.tsx +247 -0
  222. package/.claude/worktrees/phase-2-mcp/src/components/SkillDiffViewer.tsx +154 -0
  223. package/.claude/worktrees/phase-2-mcp/src/components/ThemeAwareBackground.tsx +67 -0
  224. package/.claude/worktrees/phase-2-mcp/src/components/ThemeToggle.tsx +54 -0
  225. package/.claude/worktrees/phase-2-mcp/src/components/WelcomeHero.tsx +77 -0
  226. package/.claude/worktrees/phase-2-mcp/src/components/bits/ClickSpark.tsx +116 -0
  227. package/.claude/worktrees/phase-2-mcp/src/components/bits/CountUp.tsx +98 -0
  228. package/.claude/worktrees/phase-2-mcp/src/components/bits/DarkSelect.tsx +95 -0
  229. package/.claude/worktrees/phase-2-mcp/src/components/bits/DecryptedText.tsx +161 -0
  230. package/.claude/worktrees/phase-2-mcp/src/components/bits/ElectricBorder.tsx +184 -0
  231. package/.claude/worktrees/phase-2-mcp/src/components/bits/GlitchText.tsx +34 -0
  232. package/.claude/worktrees/phase-2-mcp/src/components/bits/ShinyText.tsx +55 -0
  233. package/.claude/worktrees/phase-2-mcp/src/components/bits/SpotlightCard.tsx +42 -0
  234. package/.claude/worktrees/phase-2-mcp/src/components/bits/TextType.tsx +95 -0
  235. package/.claude/worktrees/phase-2-mcp/src/components/bits/index.ts +9 -0
  236. package/.claude/worktrees/phase-2-mcp/src/components/pages/CuratorPage.tsx +632 -0
  237. package/.claude/worktrees/phase-2-mcp/src/components/pages/DatasetPage.tsx +271 -0
  238. package/.claude/worktrees/phase-2-mcp/src/components/pages/EvolutionPage.tsx +676 -0
  239. package/.claude/worktrees/phase-2-mcp/src/components/pages/FunctionCallingPage.tsx +1 -0
  240. package/.claude/worktrees/phase-2-mcp/src/components/pages/LogsPage.tsx +272 -0
  241. package/.claude/worktrees/phase-2-mcp/src/components/pages/MetricsPage.tsx +246 -0
  242. package/.claude/worktrees/phase-2-mcp/src/components/pages/OverviewPage.tsx +420 -0
  243. package/.claude/worktrees/phase-2-mcp/src/components/pages/SettingsPage.tsx +88 -0
  244. package/.claude/worktrees/phase-2-mcp/src/components/pages/SkillStudioPage.tsx +376 -0
  245. package/.claude/worktrees/phase-2-mcp/src/components/ui/animated-theme-toggler.tsx +97 -0
  246. package/.claude/worktrees/phase-2-mcp/src/components/ui/button.tsx +67 -0
  247. package/.claude/worktrees/phase-2-mcp/src/components/ui/card.tsx +103 -0
  248. package/.claude/worktrees/phase-2-mcp/src/components/ui/input.tsx +19 -0
  249. package/.claude/worktrees/phase-2-mcp/src/components/ui/separator.tsx +28 -0
  250. package/.claude/worktrees/phase-2-mcp/src/components/ui/sheet.tsx +147 -0
  251. package/.claude/worktrees/phase-2-mcp/src/components/ui/sidebar.tsx +702 -0
  252. package/.claude/worktrees/phase-2-mcp/src/components/ui/skeleton.tsx +13 -0
  253. package/.claude/worktrees/phase-2-mcp/src/components/ui/theme-toggle.tsx +272 -0
  254. package/.claude/worktrees/phase-2-mcp/src/components/ui/tooltip.tsx +57 -0
  255. package/.claude/worktrees/phase-2-mcp/src/hooks/use-mobile.ts +19 -0
  256. package/.claude/worktrees/phase-2-mcp/src/lib/api.ts +455 -0
  257. package/.claude/worktrees/phase-2-mcp/src/lib/queryClient.ts +12 -0
  258. package/.claude/worktrees/phase-2-mcp/src/lib/utils.ts +6 -0
  259. package/.claude/worktrees/phase-2-mcp/stitch/agent_dashboard/DESIGN_SPEC.md +521 -0
  260. package/.claude/worktrees/phase-2-mcp/stitch/agent_dashboard/prototype.html +676 -0
  261. package/.claude/worktrees/phase-2-mcp/stitch/curator_workspace/code.html +448 -0
  262. package/.claude/worktrees/phase-2-mcp/stitch/curator_workspace/screen.png +0 -0
  263. package/.claude/worktrees/phase-2-mcp/stitch/datasets/code.html +479 -0
  264. package/.claude/worktrees/phase-2-mcp/stitch/datasets/screen.png +0 -0
  265. package/.claude/worktrees/phase-2-mcp/stitch/evolution_history/code.html +461 -0
  266. package/.claude/worktrees/phase-2-mcp/stitch/evolution_history/screen.png +0 -0
  267. package/.claude/worktrees/phase-2-mcp/stitch/hermes_dashboard/DESIGN.md +192 -0
  268. package/.claude/worktrees/phase-2-mcp/stitch/hermes_dashboard/DESIGN_SPEC.md +455 -0
  269. package/.claude/worktrees/phase-2-mcp/stitch/hermes_overview/code.html +399 -0
  270. package/.claude/worktrees/phase-2-mcp/stitch/hermes_overview/screen.png +0 -0
  271. package/.claude/worktrees/phase-2-mcp/stitch/live_logs/code.html +324 -0
  272. package/.claude/worktrees/phase-2-mcp/stitch/live_logs/screen.png +0 -0
  273. package/.claude/worktrees/phase-2-mcp/stitch/skill_hub/code.html +596 -0
  274. package/.claude/worktrees/phase-2-mcp/stitch/skill_hub/screen.png +0 -0
  275. package/.claude/worktrees/phase-2-mcp/stitch/system_metrics/code.html +527 -0
  276. package/.claude/worktrees/phase-2-mcp/stitch/system_metrics/screen.png +0 -0
  277. package/.claude/worktrees/phase-2-mcp/stitch/system_settings/code.html +257 -0
  278. package/.claude/worktrees/phase-2-mcp/stitch/system_settings/screen.png +0 -0
  279. package/.claude/worktrees/phase-2-mcp/test_dashboard.py +201 -0
  280. package/.claude/worktrees/phase-2-mcp/tests/collectors/__init__.py +0 -0
  281. package/.claude/worktrees/phase-2-mcp/tests/collectors/fixtures/sample_session.jsonl +7 -0
  282. package/.claude/worktrees/phase-2-mcp/tests/collectors/test_claude_code_collector.py +171 -0
  283. package/.claude/worktrees/phase-2-mcp/tests/collectors/test_hermes_collector.py +167 -0
  284. package/.claude/worktrees/phase-2-mcp/tests/eval/test_engine.py +234 -0
  285. package/.claude/worktrees/phase-2-mcp/tests/eval/test_scorers.py +249 -0
  286. package/.claude/worktrees/phase-2-mcp/tests/storage/__init__.py +0 -0
  287. package/.claude/worktrees/phase-2-mcp/tests/storage/test_run_store.py +359 -0
  288. package/.claude/worktrees/phase-2-mcp/tests/test_curator.py +559 -0
  289. package/.claude/worktrees/phase-2-mcp/tests/test_mcp_server.py +114 -0
  290. package/.claude/worktrees/phase-2-mcp/tsconfig.json +34 -0
  291. package/.env.example +72 -0
  292. package/.kilocode/package-lock.json +378 -0
  293. package/.kilocode/package.json +5 -0
  294. package/AGENTS.md +5 -0
  295. package/CLAUDE.md +29 -0
  296. package/QA_AUDIT_PLAN.md +156 -0
  297. package/README.md +355 -0
  298. package/agent-agnostic-evolution-dashboard.md +405 -0
  299. package/backend/__init__.py +0 -0
  300. package/backend/collectors/__init__.py +0 -0
  301. package/backend/collectors/claude_code_collector.py +277 -0
  302. package/backend/collectors/hermes_collector.py +68 -0
  303. package/backend/curator.py +512 -0
  304. package/backend/eval/__init__.py +19 -0
  305. package/backend/eval/engine.py +116 -0
  306. package/backend/eval/scorers.py +201 -0
  307. package/backend/generate_dataset.py +86 -0
  308. package/backend/job_tracker.py +232 -0
  309. package/backend/main.py +1746 -0
  310. package/backend/mcp_server.py +250 -0
  311. package/backend/promethean/__init__.py +24 -0
  312. package/backend/promethean/cycle_orchestrator.py +270 -0
  313. package/backend/promethean/delta_validator.py +191 -0
  314. package/backend/promethean/dspy_compiler.py +315 -0
  315. package/backend/promethean/gepa_strategist.py +213 -0
  316. package/backend/promethean/models.py +260 -0
  317. package/backend/promethean/skill_deployer.py +195 -0
  318. package/backend/promethean/trace_ingestion.py +142 -0
  319. package/backend/requirements.txt +6 -0
  320. package/backend/sdd_evolve.py +459 -0
  321. package/backend/skill_detector.py +227 -0
  322. package/backend/skill_registry.py +289 -0
  323. package/backend/storage/__init__.py +5 -0
  324. package/backend/storage/run_store.py +393 -0
  325. package/backend/storage/schema.sql +99 -0
  326. package/backend/validate_evolution.py +267 -0
  327. package/bin/genoma.js +250 -0
  328. package/components.json +28 -0
  329. package/docs/api/hermes-api.openapi.yaml +438 -0
  330. package/docs/hero.svg +148 -0
  331. package/eslint.config.mjs +18 -0
  332. package/install.sh +245 -0
  333. package/next-env.d.ts +6 -0
  334. package/next.config.ts +32 -0
  335. package/package.json +46 -0
  336. package/pnpm-workspace.yaml +4 -0
  337. package/postcss.config.mjs +7 -0
  338. package/public/file.svg +1 -0
  339. package/public/fonts/SF-Pro-Display-Bold.otf +0 -0
  340. package/public/fonts/SF-Pro-Display-Heavy.otf +0 -0
  341. package/public/fonts/SF-Pro-Display-Medium.otf +0 -0
  342. package/public/fonts/SF-Pro-Display-Regular.otf +0 -0
  343. package/public/fonts/SF-Pro-Display-Semibold.otf +0 -0
  344. package/public/fonts/SF-Pro-Text-Bold.otf +0 -0
  345. package/public/fonts/SF-Pro-Text-Heavy.otf +0 -0
  346. package/public/fonts/SF-Pro-Text-Medium.otf +0 -0
  347. package/public/fonts/SF-Pro-Text-Regular.otf +0 -0
  348. package/public/fonts/SF-Pro-Text-Semibold.otf +0 -0
  349. package/public/globe.svg +1 -0
  350. package/public/next.svg +1 -0
  351. package/public/theme-preview.html +257 -0
  352. package/public/vercel.svg +1 -0
  353. package/public/window.svg +1 -0
  354. package/run.sh +26 -0
  355. package/scripts/postinstall.js +50 -0
  356. package/skills-lock.json +10 -0
  357. package/specs/event-schema.md +223 -0
  358. package/specs/examples/run.jsonl +3 -0
  359. package/src/app/api/[...path]/route.ts +55 -0
  360. package/src/app/api/auth/token/route.ts +22 -0
  361. package/src/app/evolution/page.tsx +589 -0
  362. package/src/app/favicon.ico +0 -0
  363. package/src/app/globals.css +321 -0
  364. package/src/app/layout.tsx +63 -0
  365. package/src/app/page.tsx +70 -0
  366. package/src/app/skills/page.tsx +369 -0
  367. package/src/components/ApiConfigCard.tsx +199 -0
  368. package/src/components/ColorBends.css +1 -0
  369. package/src/components/ColorBends.d.ts +1 -0
  370. package/src/components/ColorBends.jsx +1 -0
  371. package/src/components/CoreLoopToggle.tsx +111 -0
  372. package/src/components/EnvironmentStatus.tsx +176 -0
  373. package/src/components/EvolutionBackground.tsx +1 -0
  374. package/src/components/ReactQueryProvider.tsx +24 -0
  375. package/src/components/Sidebar.tsx +247 -0
  376. package/src/components/SkillDiffViewer.tsx +154 -0
  377. package/src/components/ThemeAwareBackground.tsx +67 -0
  378. package/src/components/ThemeToggle.tsx +54 -0
  379. package/src/components/WelcomeHero.tsx +77 -0
  380. package/src/components/bits/ClickSpark.tsx +116 -0
  381. package/src/components/bits/CountUp.tsx +98 -0
  382. package/src/components/bits/DarkSelect.tsx +95 -0
  383. package/src/components/bits/DecryptedText.tsx +161 -0
  384. package/src/components/bits/ElectricBorder.tsx +184 -0
  385. package/src/components/bits/GlitchText.tsx +34 -0
  386. package/src/components/bits/ShinyText.tsx +55 -0
  387. package/src/components/bits/SpotlightCard.tsx +42 -0
  388. package/src/components/bits/TextType.tsx +95 -0
  389. package/src/components/bits/index.ts +9 -0
  390. package/src/components/pages/CuratorPage.tsx +632 -0
  391. package/src/components/pages/DatasetPage.tsx +271 -0
  392. package/src/components/pages/EvolutionPage.tsx +676 -0
  393. package/src/components/pages/FunctionCallingPage.tsx +1 -0
  394. package/src/components/pages/LogsPage.tsx +272 -0
  395. package/src/components/pages/MetricsPage.tsx +246 -0
  396. package/src/components/pages/OverviewPage.tsx +420 -0
  397. package/src/components/pages/SettingsPage.tsx +88 -0
  398. package/src/components/pages/SkillStudioPage.tsx +376 -0
  399. package/src/components/ui/animated-theme-toggler.tsx +97 -0
  400. package/src/components/ui/button.tsx +67 -0
  401. package/src/components/ui/card.tsx +103 -0
  402. package/src/components/ui/input.tsx +19 -0
  403. package/src/components/ui/separator.tsx +28 -0
  404. package/src/components/ui/sheet.tsx +147 -0
  405. package/src/components/ui/sidebar.tsx +702 -0
  406. package/src/components/ui/skeleton.tsx +13 -0
  407. package/src/components/ui/theme-toggle.tsx +272 -0
  408. package/src/components/ui/tooltip.tsx +57 -0
  409. package/src/hooks/use-mobile.ts +19 -0
  410. package/src/lib/api.ts +455 -0
  411. package/src/lib/queryClient.ts +12 -0
  412. package/src/lib/utils.ts +6 -0
  413. package/stitch/agent_dashboard/DESIGN_SPEC.md +521 -0
  414. package/stitch/agent_dashboard/prototype.html +676 -0
  415. package/stitch/curator_workspace/code.html +448 -0
  416. package/stitch/curator_workspace/screen.png +0 -0
  417. package/stitch/datasets/code.html +479 -0
  418. package/stitch/datasets/screen.png +0 -0
  419. package/stitch/evolution_history/code.html +461 -0
  420. package/stitch/evolution_history/screen.png +0 -0
  421. package/stitch/hermes_dashboard/DESIGN.md +192 -0
  422. package/stitch/hermes_dashboard/DESIGN_SPEC.md +455 -0
  423. package/stitch/hermes_overview/code.html +399 -0
  424. package/stitch/hermes_overview/screen.png +0 -0
  425. package/stitch/live_logs/code.html +324 -0
  426. package/stitch/live_logs/screen.png +0 -0
  427. package/stitch/skill_hub/code.html +596 -0
  428. package/stitch/skill_hub/screen.png +0 -0
  429. package/stitch/system_metrics/code.html +527 -0
  430. package/stitch/system_metrics/screen.png +0 -0
  431. package/stitch/system_settings/code.html +257 -0
  432. package/stitch/system_settings/screen.png +0 -0
  433. package/test_dashboard.py +201 -0
  434. package/tests/collectors/__init__.py +0 -0
  435. package/tests/collectors/fixtures/sample_session.jsonl +7 -0
  436. package/tests/collectors/test_claude_code_collector.py +171 -0
  437. package/tests/collectors/test_hermes_collector.py +167 -0
  438. package/tests/eval/test_engine.py +234 -0
  439. package/tests/eval/test_scorers.py +249 -0
  440. package/tests/storage/__init__.py +0 -0
  441. package/tests/storage/test_run_store.py +359 -0
  442. package/tests/test_curator.py +559 -0
  443. package/tests/test_e2e_npm.py +621 -0
  444. package/tests/test_mcp_server.py +114 -0
  445. package/tsconfig.json +34 -0
@@ -0,0 +1,55 @@
1
+ import { NextRequest, NextResponse } from "next/server";
2
+
3
+ const HERMES_SERVER = "http://127.0.0.1:8000";
4
+
5
+ /**
6
+ * Catch-all proxy for Hermes web server endpoints.
7
+ *
8
+ * Routes with specific files at src/app/api/* take precedence.
9
+ * This handler catches everything else (e.g., /api/skills, /api/status, etc.)
10
+ * and proxies requests to the Hermes FastAPI backend (:9119).
11
+ */
12
+ async function handler(request: NextRequest): Promise<NextResponse> {
13
+ const { pathname, search } = new URL(request.url);
14
+ const targetUrl = `${HERMES_SERVER}${pathname}${search}`;
15
+
16
+ try {
17
+ const headers = new Headers(request.headers);
18
+ // Remove host header (Next.js sets it to localhost:3000)
19
+ headers.delete("host");
20
+
21
+ // Forward the session token if present
22
+ const token = request.headers.get("x-hermes-session-token");
23
+ if (!token) {
24
+ // Try to extract from referer or cookie (browser will have set it)
25
+ headers.set("x-hermes-session-token", "");
26
+ }
27
+
28
+ const proxyResponse = await fetch(targetUrl, {
29
+ method: request.method,
30
+ headers,
31
+ body: request.method !== "GET" && request.method !== "HEAD"
32
+ ? await request.text().catch(() => null)
33
+ : undefined,
34
+ });
35
+
36
+ const contentType = proxyResponse.headers.get("content-type") || "";
37
+ const body = contentType.includes("application/json")
38
+ ? await proxyResponse.json()
39
+ : await proxyResponse.text();
40
+
41
+ return NextResponse.json(body, {
42
+ status: proxyResponse.status,
43
+ headers: {
44
+ "content-type": contentType || "application/json",
45
+ },
46
+ });
47
+ } catch (err) {
48
+ return NextResponse.json(
49
+ { detail: `Backend unreachable: ${err instanceof Error ? err.message : "unknown"}` },
50
+ { status: 503 },
51
+ );
52
+ }
53
+ }
54
+
55
+ export { handler as GET, handler as POST, handler as PUT, handler as DELETE, handler as PATCH };
@@ -0,0 +1,22 @@
1
+ import { NextResponse } from "next/server";
2
+
3
+ const HERMES_SERVER = "http://127.0.0.1:8000";
4
+
5
+ /**
6
+ * Proxy the Hermes session token from the web server's HTML.
7
+ * The browser calls this to avoid CORS issues when fetching the token directly.
8
+ */
9
+ export async function GET() {
10
+ try {
11
+ const html = await fetch(`${HERMES_SERVER}/`, {
12
+ signal: AbortSignal.timeout(5_000),
13
+ }).then((r) => r.text());
14
+
15
+ const match = html.match(/__HERMES_SESSION_TOKEN__\s*=\s*"([^"]+)"/);
16
+ const token = match?.[1] ?? null;
17
+
18
+ return NextResponse.json({ token });
19
+ } catch {
20
+ return NextResponse.json({ token: null }, { status: 503 });
21
+ }
22
+ }
@@ -0,0 +1,589 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect, useCallback } from "react";
4
+ import { api, startEvolution, fetchJobs, fetchJob, fetchSkillDiff, fetchEvolutionRuns } from "@/lib/api";
5
+ import type { EvolutionJob, EvolutionRun, SkillDiff } from "@/lib/api";
6
+ import {
7
+ Zap, TrendingUp, GitCompare, History, Loader2, Play,
8
+ CheckCircle2, XCircle, Clock, Sparkles, AlertTriangle,
9
+ } from "lucide-react";
10
+
11
+ // ── Types ──────────────────────────────────────────────────────────
12
+ interface EvolvableSkill {
13
+ name: string;
14
+ description: string;
15
+ enabled: boolean;
16
+ tags: string[];
17
+ is_fork?: boolean;
18
+ category: string;
19
+ }
20
+
21
+ interface EvolvableProvider {
22
+ provider: string;
23
+ total: number;
24
+ enabled: number;
25
+ skills: EvolvableSkill[];
26
+ }
27
+
28
+ interface EvolvableResponse {
29
+ status: string;
30
+ providers: EvolvableProvider[];
31
+ }
32
+
33
+ // ── Provider config ────────────────────────────────────────────────
34
+ const PROVIDER_META: Record<string, { icon: string; color: string; label: string }> = {
35
+ hermes: { icon: "🪽", color: "emerald", label: "Hermes" },
36
+ "claude-code": { icon: "🤖", color: "violet", label: "Claude Code" },
37
+ opencode: { icon: "💻", color: "blue", label: "OpenCode" },
38
+ kilocode: { icon: "⚡", color: "amber", label: "Kilocode" },
39
+ antigravity: { icon: "🚀", color: "rose", label: "Antigravity" },
40
+ };
41
+
42
+ const COLOR_MAP: Record<string, string> = {
43
+ emerald: "bg-emerald-500/10 border-emerald-500/30 text-emerald-400",
44
+ violet: "bg-violet-500/10 border-violet-500/30 text-violet-400",
45
+ blue: "bg-blue-500/10 border-blue-500/30 text-blue-400",
46
+ amber: "bg-amber-500/10 border-amber-500/30 text-amber-400",
47
+ rose: "bg-rose-500/10 border-rose-500/30 text-rose-400",
48
+ };
49
+
50
+ // ── Sub-components ─────────────────────────────────────────────────
51
+
52
+ function ProviderTabs({
53
+ providers,
54
+ selected,
55
+ onSelect,
56
+ }: {
57
+ providers: string[];
58
+ selected: string;
59
+ onSelect: (p: string) => void;
60
+ }) {
61
+ return (
62
+ <div className="flex gap-2 flex-wrap mb-6">
63
+ <button
64
+ onClick={() => onSelect("all")}
65
+ className={`px-4 py-2 rounded-lg text-sm font-medium transition-all ${
66
+ selected === "all"
67
+ ? "bg-white/10 text-white border border-white/20"
68
+ : "bg-gray-800/50 text-gray-400 border border-transparent hover:border-white/10"
69
+ }`}
70
+ >
71
+ All Providers
72
+ </button>
73
+ {providers.map((p) => {
74
+ const meta = PROVIDER_META[p] ?? { icon: "🔧", color: "gray", label: p };
75
+ return (
76
+ <button
77
+ key={p}
78
+ onClick={() => onSelect(p)}
79
+ className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 ${
80
+ selected === p
81
+ ? COLOR_MAP[meta.color] + " border"
82
+ : "bg-gray-800/50 text-gray-400 border border-transparent hover:border-white/10"
83
+ }`}
84
+ >
85
+ <span>{meta.icon}</span>
86
+ <span className="capitalize">{meta.label}</span>
87
+ </button>
88
+ );
89
+ })}
90
+ </div>
91
+ );
92
+ }
93
+
94
+ function DeltaBadge({ improvement }: { improvement: number }) {
95
+ const isPositive = improvement > 0;
96
+ const isNeutral = improvement === 0;
97
+ return (
98
+ <span
99
+ className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-mono font-bold ${
100
+ isPositive
101
+ ? "bg-emerald-500/10 text-emerald-400 border border-emerald-500/20"
102
+ : isNeutral
103
+ ? "bg-gray-500/10 text-gray-400 border border-gray-500/20"
104
+ : "bg-red-500/10 text-red-400 border border-red-500/20"
105
+ }`}
106
+ >
107
+ <TrendingUp className={`w-3 h-3 ${!isPositive && !isNeutral ? "rotate-180" : ""}`} />
108
+ {isPositive ? "+" : ""}{improvement.toFixed(2)}
109
+ </span>
110
+ );
111
+ }
112
+
113
+ function JobStatusBadge({ status }: { status: string }) {
114
+ const config: Record<string, { icon: React.ReactNode; label: string; className: string }> = {
115
+ completed: { icon: <CheckCircle2 className="w-3.5 h-3.5" />, label: "Done", className: "bg-emerald-500/10 text-emerald-400 border-emerald-500/20" },
116
+ failed: { icon: <XCircle className="w-3.5 h-3.5" />, label: "Failed", className: "bg-red-500/10 text-red-400 border-red-500/20" },
117
+ queued: { icon: <Clock className="w-3.5 h-3.5" />, label: "Queued", className: "bg-amber-500/10 text-amber-400 border-amber-500/20" },
118
+ running: { icon: <Loader2 className="w-3.5 h-3.5 animate-spin" />, label: "Running", className: "bg-blue-500/10 text-blue-400 border-blue-500/20" },
119
+ optimizing: { icon: <Loader2 className="w-3.5 h-3.5 animate-spin" />, label: "Evolving", className: "bg-blue-500/10 text-blue-400 border-blue-500/20" },
120
+ evaluating: { icon: <Loader2 className="w-3.5 h-3.5 animate-spin" />, label: "Evaluating", className: "bg-purple-500/10 text-purple-400 border-purple-500/20" },
121
+ };
122
+ const c = config[status] ?? { icon: <Clock className="w-3.5 h-3.5" />, label: status, className: "bg-gray-500/10 text-gray-400 border-gray-500/20" };
123
+ return (
124
+ <span className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs border ${c.className}`}>
125
+ {c.icon}
126
+ {c.label}
127
+ </span>
128
+ );
129
+ }
130
+
131
+ function SkillCard({
132
+ skill,
133
+ provider,
134
+ onEvolve,
135
+ evolving,
136
+ runs,
137
+ }: {
138
+ skill: EvolvableSkill;
139
+ provider: string;
140
+ onEvolve: (skillName: string) => void;
141
+ evolving: boolean;
142
+ runs: EvolutionRun[];
143
+ }) {
144
+ const meta = PROVIDER_META[provider] ?? { icon: "🔧", color: "gray", label: provider };
145
+ const lastRun = runs
146
+ .filter((r) => r.skill_name === skill.name)
147
+ .sort((a, b) => b.timestamp.localeCompare(a.timestamp))[0];
148
+
149
+ return (
150
+ <div className="bg-gray-900/50 border border-gray-800 rounded-xl p-5 hover:border-gray-700 transition-all group">
151
+ <div className="flex items-start justify-between mb-3">
152
+ <div className="flex-1 min-w-0">
153
+ <h3 className="font-semibold text-white truncate">{skill.name}</h3>
154
+ <p className="text-xs text-gray-500 mt-0.5 line-clamp-1">
155
+ {skill.description.replace(/^---\s*/, "").slice(0, 80) || "No description"}
156
+ </p>
157
+ </div>
158
+ <span className={`shrink-0 text-xs px-2 py-0.5 rounded-full border ${COLOR_MAP[meta.color]}`}>
159
+ {meta.icon} {meta.label}
160
+ </span>
161
+ </div>
162
+
163
+ <div className="flex items-center gap-3 mb-4">
164
+ {skill.category && (
165
+ <span className="text-[10px] uppercase tracking-wider text-gray-600 bg-gray-800/50 px-2 py-0.5 rounded">
166
+ {skill.category}
167
+ </span>
168
+ )}
169
+ {lastRun && <DeltaBadge improvement={lastRun.improvement} />}
170
+ </div>
171
+
172
+ <button
173
+ onClick={() => onEvolve(skill.name)}
174
+ disabled={evolving}
175
+ className={`w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg text-sm font-semibold transition-all ${
176
+ evolving
177
+ ? "bg-gray-800 text-gray-500 cursor-not-allowed"
178
+ : lastRun
179
+ ? "bg-gradient-to-r from-emerald-500/20 to-teal-500/20 text-emerald-400 border border-emerald-500/30 hover:from-emerald-500/30 hover:to-teal-500/30"
180
+ : "bg-gradient-to-r from-blue-500/20 to-purple-500/20 text-blue-400 border border-blue-500/30 hover:from-blue-500/30 hover:to-purple-500/30"
181
+ }`}
182
+ >
183
+ {evolving ? (
184
+ <>
185
+ <Loader2 className="w-4 h-4 animate-spin" />
186
+ Evolving...
187
+ </>
188
+ ) : lastRun ? (
189
+ <>
190
+ <GitCompare className="w-4 h-4" />
191
+ Re-Evolve
192
+ </>
193
+ ) : (
194
+ <>
195
+ <Zap className="w-4 h-4" />
196
+ Evolve Now
197
+ </>
198
+ )}
199
+ </button>
200
+ </div>
201
+ );
202
+ }
203
+
204
+ function StatsBar({ stats }: { stats: { totalSkills: number; totalProviders: number; totalRuns: number; avgImprovement: number } }) {
205
+ return (
206
+ <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
207
+ {[
208
+ { label: "Skills", value: stats.totalSkills, icon: <Sparkles className="w-4 h-4" />, color: "emerald" },
209
+ { label: "Providers", value: stats.totalProviders, icon: <Zap className="w-4 h-4" />, color: "violet" },
210
+ { label: "Evolutions", value: stats.totalRuns, icon: <History className="w-4 h-4" />, color: "blue" },
211
+ { label: "Avg Δ", value: `${stats.avgImprovement >= 0 ? "+" : ""}${stats.avgImprovement.toFixed(2)}`, icon: <TrendingUp className="w-4 h-4" />, color: stats.avgImprovement >= 0 ? "emerald" : "red" },
212
+ ].map((stat) => (
213
+ <div
214
+ key={stat.label}
215
+ className="bg-gray-900/50 border border-gray-800 rounded-xl p-4 flex items-center gap-3"
216
+ >
217
+ <div className={`p-2 rounded-lg bg-${stat.color}-500/10 text-${stat.color}-400`}>
218
+ {stat.icon}
219
+ </div>
220
+ <div>
221
+ <div className="text-2xl font-bold text-white">{stat.value}</div>
222
+ <div className="text-xs text-gray-500">{stat.label}</div>
223
+ </div>
224
+ </div>
225
+ ))}
226
+ </div>
227
+ );
228
+ }
229
+
230
+ // ── Diff Viewer ────────────────────────────────────────────────────
231
+ function DiffViewer({ diff, onClose }: { diff: SkillDiff | null; onClose: () => void }) {
232
+ if (!diff) return null;
233
+ const improvement =
234
+ diff.metrics && typeof diff.metrics === "object" && "improvement" in diff.metrics
235
+ ? Number(diff.metrics.improvement)
236
+ : 0;
237
+
238
+ return (
239
+ <div className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center p-4">
240
+ <div className="bg-gray-950 border border-gray-800 rounded-2xl w-full max-w-5xl max-h-[85vh] overflow-hidden flex flex-col shadow-2xl">
241
+ {/* Header */}
242
+ <div className="p-6 border-b border-gray-800 flex items-center justify-between">
243
+ <div>
244
+ <h2 className="text-xl font-bold text-white flex items-center gap-3">
245
+ <GitCompare className="w-5 h-5 text-emerald-400" />
246
+ {diff.skill_name}
247
+ </h2>
248
+ <p className="text-sm text-gray-500 mt-1">Before/After Comparison</p>
249
+ </div>
250
+ <div className="flex items-center gap-4">
251
+ {diff.metrics && (
252
+ <DeltaBadge improvement={improvement} />
253
+ )}
254
+ <button
255
+ onClick={onClose}
256
+ className="p-2 rounded-lg hover:bg-gray-800 text-gray-400 hover:text-white transition-colors"
257
+ >
258
+
259
+ </button>
260
+ </div>
261
+ </div>
262
+
263
+ {/* Metrics summary */}
264
+ {diff.metrics && typeof diff.metrics === "object" && (
265
+ <div className="px-6 py-4 border-b border-gray-800 bg-gray-900/30">
266
+ <div className="grid grid-cols-2 md:grid-cols-5 gap-3">
267
+ {Object.entries(diff.metrics).filter(([k]) => ["baseline_score", "evolved_score", "improvement", "elapsed_seconds", "iterations"].includes(k)).map(([key, val]) => (
268
+ <div key={key} className="text-center">
269
+ <div className="text-xs text-gray-500 mb-1 capitalize">{key.replace(/_/g, " ")}</div>
270
+ <div className="text-lg font-mono font-bold text-white">
271
+ {key === "elapsed_seconds" ? `${Number(val).toFixed(1)}s` : key === "iterations" ? String(val) : Number(val).toFixed(3)}
272
+ </div>
273
+ </div>
274
+ ))}
275
+ </div>
276
+ </div>
277
+ )}
278
+
279
+ {/* Side-by-side */}
280
+ <div className="flex-1 overflow-auto grid grid-cols-2 divide-x divide-gray-800">
281
+ {/* Baseline */}
282
+ <div className="p-4">
283
+ <div className="flex items-center gap-2 mb-3">
284
+ <span className="text-xs font-semibold px-2 py-0.5 rounded bg-red-500/10 text-red-400 border border-red-500/20">
285
+ BEFORE
286
+ </span>
287
+ <span className="text-xs text-gray-500">
288
+ {diff.baseline ? `${diff.baseline.length} chars` : "N/A"}
289
+ </span>
290
+ </div>
291
+ <pre className="text-xs text-gray-400 whitespace-pre-wrap font-mono leading-relaxed bg-gray-900/50 rounded-lg p-3 border border-gray-800 max-h-[50vh] overflow-auto">
292
+ {diff.baseline?.slice(0, 5000) || "No baseline available"}
293
+ </pre>
294
+ </div>
295
+
296
+ {/* Evolved */}
297
+ <div className="p-4">
298
+ <div className="flex items-center gap-2 mb-3">
299
+ <span className="text-xs font-semibold px-2 py-0.5 rounded bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
300
+ AFTER
301
+ </span>
302
+ <span className="text-xs text-gray-500">
303
+ {diff.evolved ? `${diff.evolved.length} chars` : "N/A"}
304
+ </span>
305
+ {diff.metrics && (
306
+ <DeltaBadge improvement={improvement} />
307
+ )}
308
+ </div>
309
+ <pre className="text-xs text-gray-400 whitespace-pre-wrap font-mono leading-relaxed bg-gray-900/50 rounded-lg p-3 border border-gray-800 max-h-[50vh] overflow-auto">
310
+ {diff.evolved?.slice(0, 5000) || "No evolved version available"}
311
+ </pre>
312
+ </div>
313
+ </div>
314
+ </div>
315
+ </div>
316
+ );
317
+ }
318
+
319
+ // ── Main Page ──────────────────────────────────────────────────────
320
+ export default function EvolutionHubPage() {
321
+ const [providers, setProviders] = useState<EvolvableProvider[]>([]);
322
+ const [providerNames, setProviderNames] = useState<string[]>([]);
323
+ const [selectedProvider, setSelectedProvider] = useState("all");
324
+ const [search, setSearch] = useState("");
325
+ const [loading, setLoading] = useState(true);
326
+ const [evolvingSkill, setEvolvingSkill] = useState<string | null>(null);
327
+ const [activeJobId, setActiveJobId] = useState<string | null>(null);
328
+ const [runs, setRuns] = useState<EvolutionRun[]>([]);
329
+ const [selectedDiff, setSelectedDiff] = useState<SkillDiff | null>(null);
330
+ const [error, setError] = useState("");
331
+
332
+ // ── Data fetching ────────────────────────────────────────────────
333
+ const loadData = useCallback(async () => {
334
+ try {
335
+ setLoading(true);
336
+ const [evolvableData, runsData] = await Promise.all([
337
+ api<EvolvableResponse>("/api/evolution/evolvable"),
338
+ fetchEvolutionRuns().catch(() => [] as EvolutionRun[]),
339
+ ]);
340
+
341
+ if (evolvableData.status === "ok") {
342
+ setProviders(evolvableData.providers);
343
+ setProviderNames(evolvableData.providers.map((p) => p.provider));
344
+ }
345
+ setRuns(Array.isArray(runsData) ? runsData : []);
346
+ } catch (e) {
347
+ setError(e instanceof Error ? e.message : "Failed to load");
348
+ } finally {
349
+ setLoading(false);
350
+ }
351
+ }, []);
352
+
353
+ useEffect(() => {
354
+ loadData();
355
+ }, [loadData]);
356
+
357
+ // ── Poll active job ──────────────────────────────────────────────
358
+ useEffect(() => {
359
+ if (!activeJobId) return;
360
+ const interval = setInterval(async () => {
361
+ try {
362
+ const job = await fetchJob(activeJobId);
363
+ if (job.status === "completed" || job.status === "failed") {
364
+ setEvolvingSkill(null);
365
+ setActiveJobId(null);
366
+ // Reload runs to show new data
367
+ const runsData = await fetchEvolutionRuns().catch(() => [] as EvolutionRun[]);
368
+ setRuns(Array.isArray(runsData) ? runsData : []);
369
+ }
370
+ } catch {
371
+ // ignore poll errors
372
+ }
373
+ }, 2000);
374
+ return () => clearInterval(interval);
375
+ }, [activeJobId]);
376
+
377
+ // ── Actions ──────────────────────────────────────────────────────
378
+ const handleEvolve = async (skillName: string) => {
379
+ try {
380
+ setEvolvingSkill(skillName);
381
+ setError("");
382
+ const result = await startEvolution(skillName, 3);
383
+ if (result.error) {
384
+ setError(result.error);
385
+ setEvolvingSkill(null);
386
+ } else {
387
+ setActiveJobId(result.job_id);
388
+ }
389
+ } catch (e) {
390
+ setError(e instanceof Error ? e.message : "Evolution failed to start");
391
+ setEvolvingSkill(null);
392
+ }
393
+ };
394
+
395
+ const handleViewDiff = async (skillName: string, runDir?: string) => {
396
+ try {
397
+ // Find the run directory from runs
398
+ const run = runs.find((r) => r.skill_name === skillName);
399
+ if (!run) return;
400
+
401
+ // Fetch diff
402
+ const diffData = await fetchSkillDiff(skillName, "latest");
403
+ setSelectedDiff(diffData);
404
+ } catch (e) {
405
+ setError(e instanceof Error ? e.message : "Failed to load diff");
406
+ }
407
+ };
408
+
409
+ // ── Filtering ────────────────────────────────────────────────────
410
+ const filteredSkills = providers
411
+ .filter((p) => selectedProvider === "all" || p.provider === selectedProvider)
412
+ .flatMap((p) =>
413
+ p.skills
414
+ .filter((s) => {
415
+ const q = search.toLowerCase();
416
+ return (
417
+ !q ||
418
+ s.name.toLowerCase().includes(q) ||
419
+ s.description.toLowerCase().includes(q) ||
420
+ s.category?.toLowerCase().includes(q)
421
+ );
422
+ })
423
+ .map((s) => ({ ...s, _provider: p.provider }))
424
+ );
425
+
426
+ // ── Stats ────────────────────────────────────────────────────────
427
+ const stats = {
428
+ totalSkills: providers.reduce((acc, p) => acc + p.skills.length, 0),
429
+ totalProviders: providers.length,
430
+ totalRuns: runs.length,
431
+ avgImprovement:
432
+ runs.length > 0
433
+ ? runs.reduce((acc, r) => acc + (r.improvement || 0), 0) / runs.length
434
+ : 0,
435
+ };
436
+
437
+ // ── Render ───────────────────────────────────────────────────────
438
+ return (
439
+ <div className="min-h-screen px-6 py-8 max-w-7xl mx-auto">
440
+ {/* Header */}
441
+ <div className="mb-8">
442
+ <h1 className="text-4xl font-bold text-white flex items-center gap-3 mb-2">
443
+ <Sparkles className="w-8 h-8 text-emerald-400" />
444
+ Evolution Hub
445
+ </h1>
446
+ <p className="text-gray-500 text-lg">
447
+ Multi-provider AI skill evolution — Hermes · Claude Code · OpenCode · Kilocode
448
+ </p>
449
+ </div>
450
+
451
+ {/* Error banner */}
452
+ {error && (
453
+ <div className="mb-6 p-4 bg-red-500/10 border border-red-500/20 rounded-xl flex items-center gap-3 text-red-400">
454
+ <AlertTriangle className="w-5 h-5 shrink-0" />
455
+ <span className="text-sm">{error}</span>
456
+ <button onClick={() => setError("")} className="ml-auto text-red-400 hover:text-red-300">
457
+
458
+ </button>
459
+ </div>
460
+ )}
461
+
462
+ {/* Stats */}
463
+ {!loading && <StatsBar stats={stats} />}
464
+
465
+ {/* Filters */}
466
+ {!loading && (
467
+ <>
468
+ <ProviderTabs
469
+ providers={providerNames}
470
+ selected={selectedProvider}
471
+ onSelect={setSelectedProvider}
472
+ />
473
+ <div className="relative mb-6">
474
+ <input
475
+ type="text"
476
+ value={search}
477
+ onChange={(e) => setSearch(e.target.value)}
478
+ placeholder="Search skills..."
479
+ className="w-full p-3 bg-gray-900 border border-gray-800 rounded-xl text-white placeholder-gray-600 focus:outline-none focus:border-emerald-500/50 transition-colors"
480
+ />
481
+ </div>
482
+ </>
483
+ )}
484
+
485
+ {/* Loading */}
486
+ {loading && (
487
+ <div className="flex items-center justify-center py-20">
488
+ <Loader2 className="w-8 h-8 animate-spin text-emerald-400" />
489
+ </div>
490
+ )}
491
+
492
+ {/* Skill Grid */}
493
+ {!loading && (
494
+ <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4 mb-12">
495
+ {filteredSkills.map((skill) => (
496
+ <SkillCard
497
+ key={`${skill._provider}-${skill.name}`}
498
+ skill={skill}
499
+ provider={skill._provider}
500
+ onEvolve={handleEvolve}
501
+ evolving={evolvingSkill === skill.name}
502
+ runs={runs}
503
+ />
504
+ ))}
505
+ {filteredSkills.length === 0 && (
506
+ <div className="col-span-full text-center py-16 text-gray-600">
507
+ <Sparkles className="w-12 h-12 mx-auto mb-4 opacity-30" />
508
+ <p className="text-lg">No skills found</p>
509
+ <p className="text-sm mt-1">Try a different filter or search term</p>
510
+ </div>
511
+ )}
512
+ </div>
513
+ )}
514
+
515
+ {/* Evolution History */}
516
+ {!loading && runs.length > 0 && (
517
+ <div className="mb-12">
518
+ <h2 className="text-2xl font-bold text-white flex items-center gap-2 mb-4">
519
+ <History className="w-5 h-5 text-blue-400" />
520
+ Evolution History
521
+ </h2>
522
+ <div className="bg-gray-900/50 border border-gray-800 rounded-xl overflow-hidden">
523
+ <div className="overflow-x-auto">
524
+ <table className="w-full text-sm">
525
+ <thead>
526
+ <tr className="border-b border-gray-800 text-left">
527
+ <th className="p-4 text-gray-500 font-medium">Skill</th>
528
+ <th className="p-4 text-gray-500 font-medium">Date</th>
529
+ <th className="p-4 text-gray-500 font-medium">Baseline</th>
530
+ <th className="p-4 text-gray-500 font-medium">Evolved</th>
531
+ <th className="p-4 text-gray-500 font-medium">Δ Delta</th>
532
+ <th className="p-4 text-gray-500 font-medium">Time</th>
533
+ <th className="p-4 text-gray-500 font-medium">Status</th>
534
+ <th className="p-4 text-gray-500 font-medium">Actions</th>
535
+ </tr>
536
+ </thead>
537
+ <tbody>
538
+ {runs.slice(0, 50).map((run, i) => (
539
+ <tr key={i} className="border-b border-gray-800/50 hover:bg-gray-800/30 transition-colors">
540
+ <td className="p-4 font-medium text-white">{run.skill_name}</td>
541
+ <td className="p-4 text-gray-400 font-mono text-xs">
542
+ {run.timestamp.slice(0, 10)}
543
+ </td>
544
+ <td className="p-4 font-mono text-gray-400">
545
+ {(run.baseline_score ?? 0).toFixed(3)}
546
+ </td>
547
+ <td className="p-4 font-mono text-gray-400">
548
+ {(run.evolved_score ?? 0).toFixed(3)}
549
+ </td>
550
+ <td className="p-4">
551
+ <DeltaBadge improvement={run.improvement ?? 0} />
552
+ </td>
553
+ <td className="p-4 text-gray-500 font-mono text-xs">
554
+ {(run.elapsed_seconds ?? 0).toFixed(1)}s
555
+ </td>
556
+ <td className="p-4">
557
+ {run.constraints_passed !== undefined ? (
558
+ run.constraints_passed ? (
559
+ <span className="text-emerald-400 text-xs font-medium">✓ Pass</span>
560
+ ) : (
561
+ <span className="text-amber-400 text-xs font-medium">⚠ Issues</span>
562
+ )
563
+ ) : (
564
+ <span className="text-gray-600">—</span>
565
+ )}
566
+ </td>
567
+ <td className="p-4">
568
+ <button
569
+ onClick={() => handleViewDiff(run.skill_name)}
570
+ className="text-xs text-blue-400 hover:text-blue-300 transition-colors flex items-center gap-1"
571
+ >
572
+ <GitCompare className="w-3 h-3" />
573
+ Compare
574
+ </button>
575
+ </td>
576
+ </tr>
577
+ ))}
578
+ </tbody>
579
+ </table>
580
+ </div>
581
+ </div>
582
+ </div>
583
+ )}
584
+
585
+ {/* Diff Viewer Modal */}
586
+ <DiffViewer diff={selectedDiff} onClose={() => setSelectedDiff(null)} />
587
+ </div>
588
+ );
589
+ }