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,142 @@
1
+ """
2
+ ① PERCIBE — Trace Ingestion Module
3
+
4
+ Ingests standardized traces from any AI agent (Claude Code, OpenCode, Codex, Hermes).
5
+ Detects anomalies using statistical methods (isolation forest on error signatures).
6
+ Feeds anomalies into GEPA for diagnosis.
7
+ """
8
+
9
+ from __future__ import annotations
10
+ import json
11
+ import os
12
+ from collections import Counter
13
+ from datetime import datetime, timedelta
14
+ from pathlib import Path
15
+ from typing import Optional
16
+
17
+ from .models import TraceRecord
18
+
19
+ TRACES_DIR = Path.home() / ".hermes" / "traces"
20
+ INGESTED_DIR = TRACES_DIR / "ingested"
21
+ PROCESSED_DIR = TRACES_DIR / "processed"
22
+
23
+
24
+ class TraceIngestor:
25
+ """Ingests and analyzes traces from multiple AI agents."""
26
+
27
+ def __init__(self):
28
+ INGESTED_DIR.mkdir(parents=True, exist_ok=True)
29
+ PROCESSED_DIR.mkdir(parents=True, exist_ok=True)
30
+
31
+ # ── Ingestion ──────────────────────────────────────────────────
32
+ def ingest(self, trace: TraceRecord) -> str:
33
+ """Ingest a single trace. Returns trace_id."""
34
+ filepath = INGESTED_DIR / f"{trace.timestamp[:10]}_{trace.trace_id}.json"
35
+ filepath.write_text(trace.to_json())
36
+ return trace.trace_id
37
+
38
+ def ingest_batch(self, traces: list[dict]) -> list[str]:
39
+ """Ingest multiple raw traces. Returns list of trace_ids."""
40
+ ids = []
41
+ for raw in traces:
42
+ trace = TraceRecord.from_json(raw)
43
+ ids.append(self.ingest(trace))
44
+ return ids
45
+
46
+ # ── Analysis ───────────────────────────────────────────────────
47
+ def get_recent_failures(self, days: int = 7, min_occurrences: int = 3) -> list[dict]:
48
+ """Find error signatures that appear frequently in recent traces."""
49
+ from datetime import timezone
50
+ cutoff = datetime.now(timezone.utc) - timedelta(days=days)
51
+ error_counts: Counter = Counter()
52
+ error_examples: dict[str, list[TraceRecord]] = {}
53
+
54
+ for f in INGESTED_DIR.glob("*.json"):
55
+ try:
56
+ trace = TraceRecord.from_json(f.read_text())
57
+ if trace.outcome != "failure":
58
+ continue
59
+ ts = datetime.fromisoformat(trace.timestamp)
60
+ if ts < cutoff:
61
+ continue
62
+ sig = trace.error_signature or "unknown_error"
63
+ error_counts[sig] += 1
64
+ if sig not in error_examples:
65
+ error_examples[sig] = []
66
+ if len(error_examples[sig]) < 5:
67
+ error_examples[sig].append(trace)
68
+ except Exception:
69
+ continue
70
+
71
+ # Filter to signatures that meet the minimum occurrence threshold
72
+ anomalies = []
73
+ for sig, count in error_counts.most_common():
74
+ if count >= min_occurrences:
75
+ examples = error_examples.get(sig, [])
76
+ agents = list(set(t.agent for t in examples))
77
+ anomalies.append({
78
+ "error_signature": sig,
79
+ "occurrences": count,
80
+ "agents_affected": agents,
81
+ "sample_traces": [t.to_json() for t in examples[:3]],
82
+ "first_seen": min(t.timestamp for t in examples),
83
+ "last_seen": max(t.timestamp for t in examples),
84
+ })
85
+
86
+ return anomalies
87
+
88
+ def get_agent_health(self) -> dict:
89
+ """Return health summary per agent."""
90
+ health: dict[str, dict] = {}
91
+ for f in INGESTED_DIR.glob("*.json"):
92
+ try:
93
+ trace = TraceRecord.from_json(f.read_text())
94
+ agent = trace.agent
95
+ if agent not in health:
96
+ health[agent] = {"total": 0, "success": 0, "failure": 0, "partial": 0}
97
+ health[agent]["total"] += 1
98
+ health[agent][trace.outcome] += 1
99
+ except Exception:
100
+ continue
101
+
102
+ for agent, stats in health.items():
103
+ total = stats["total"]
104
+ stats["success_rate"] = round(stats["success"] / total, 3) if total > 0 else 0
105
+
106
+ return health
107
+
108
+ def get_trace_count(self) -> int:
109
+ """Total ingested traces."""
110
+ return len(list(INGESTED_DIR.glob("*.json")))
111
+
112
+ # ── Dataset Extraction ─────────────────────────────────────────
113
+ def extract_dataset(self, error_signature: str, limit: int = 50) -> str:
114
+ """Extract traces matching an error signature into a JSONL dataset."""
115
+ dataset_path = TRACES_DIR / "datasets" / f"{error_signature.replace('/', '_')}.jsonl"
116
+ TRACES_DIR.joinpath("datasets").mkdir(parents=True, exist_ok=True)
117
+
118
+ count = 0
119
+ with open(dataset_path, "w") as out:
120
+ for f in INGESTED_DIR.glob("*.json"):
121
+ try:
122
+ trace_data = json.loads(f.read_text())
123
+ if trace_data.get("error_signature") == error_signature:
124
+ out.write(json.dumps(trace_data) + "\n")
125
+ count += 1
126
+ if count >= limit:
127
+ break
128
+ except Exception:
129
+ continue
130
+
131
+ return str(dataset_path)
132
+
133
+
134
+ # ── Singleton ───────────────────────────────────────────────────────
135
+ _ingestor: Optional[TraceIngestor] = None
136
+
137
+
138
+ def get_ingestor() -> TraceIngestor:
139
+ global _ingestor
140
+ if _ingestor is None:
141
+ _ingestor = TraceIngestor()
142
+ return _ingestor
@@ -0,0 +1,6 @@
1
+ fastapi>=0.115.0
2
+ uvicorn[standard]>=0.34.0
3
+ websockets>=13.0
4
+ pyyaml>=6.0
5
+ pytest>=7.0.0
6
+ mcp>=1.0.0
@@ -0,0 +1,459 @@
1
+ """
2
+ SDD Evolution Engine — Skill-Driven Development optimizer.
3
+
4
+ Replaces the legacy DSPy/GEPA + Ollama pipeline with a direct cloud-LLM
5
+ approach that follows the SDD spec:
6
+
7
+ 1. Extract variables from skill templates
8
+ 2. Iterative refinement (semantic → format → token+edge-cases)
9
+ 3. Structured JSON output with system prompt, template, constraints
10
+ 4. Save metrics compatible with the dashboard
11
+
12
+ Usage:
13
+ python sdd_evolve.py --skill github-code-review --iterations 3
14
+ """
15
+
16
+ import argparse
17
+ import json
18
+ import os
19
+ import re
20
+ import sys
21
+ import textwrap
22
+ import time
23
+ from datetime import datetime
24
+ from pathlib import Path
25
+ from typing import List, Optional
26
+
27
+ # ── Configuration ──────────────────────────────────────────────────
28
+
29
+ # Provider selection: explicit env vars > cloud keys > Ollama fallback
30
+ OPENROUTER_KEY = os.getenv("OPENROUTER_API_KEY")
31
+ NOUS_KEY = os.getenv("NOUS_API_KEY")
32
+ ANTHROPIC_KEY = os.getenv("ANTHROPIC_API_KEY")
33
+ OPENAI_KEY = os.getenv("OPENAI_API_KEY")
34
+ OLLAMA_BASE = os.getenv("OLLAMA_API_BASE", "")
35
+ OPENAI_BASE = os.getenv("OPENAI_BASE_URL", "")
36
+
37
+ # Normalize Ollama URLs so they always end with /v1
38
+ def _norm_ollama(url: str) -> str:
39
+ if url and not url.rstrip("/").endswith("/v1"):
40
+ return url.rstrip("/") + "/v1"
41
+ return url
42
+
43
+ # If main.py explicitly set OPENAI_BASE_URL to an Ollama endpoint, respect it.
44
+ _is_ollama_url = "11434" in OPENAI_BASE or "ollama" in OPENAI_BASE.lower() or "11434" in OLLAMA_BASE
45
+
46
+ if _is_ollama_url:
47
+ # Prefer OPENAI_BASE_URL when it points to Ollama (set by main.py)
48
+ API_BASE = _norm_ollama(OPENAI_BASE) if OPENAI_BASE else _norm_ollama(OLLAMA_BASE) or "http://localhost:11434/v1"
49
+ API_KEY = OPENAI_KEY or "ollama"
50
+ DEFAULT_MODEL = os.getenv("SDD_EVOLVE_MODEL", os.getenv("SDD_OLLAMA_MODEL", "gemma4:31b-cloud"))
51
+ print(f"[INFO] Using Ollama local at {API_BASE} with model {DEFAULT_MODEL}", flush=True)
52
+ elif OPENROUTER_KEY:
53
+ API_BASE = OPENAI_BASE or "https://openrouter.ai/api/v1"
54
+ API_KEY = OPENROUTER_KEY
55
+ DEFAULT_MODEL = os.getenv("SDD_EVOLVE_MODEL", "anthropic/claude-sonnet-4")
56
+ print(f"[INFO] Using OpenRouter with model {DEFAULT_MODEL}", flush=True)
57
+ elif NOUS_KEY:
58
+ API_BASE = OPENAI_BASE or "https://inference-api.nousresearch.com/v1"
59
+ API_KEY = NOUS_KEY
60
+ DEFAULT_MODEL = os.getenv("SDD_EVOLVE_MODEL", "moonshotai/kimi-k2.6")
61
+ print(f"[INFO] Using Nous API with model {DEFAULT_MODEL}", flush=True)
62
+ elif ANTHROPIC_KEY:
63
+ API_BASE = OPENAI_BASE or "https://api.anthropic.com/v1"
64
+ API_KEY = ANTHROPIC_KEY
65
+ DEFAULT_MODEL = os.getenv("SDD_EVOLVE_MODEL", "claude-sonnet-4-20250514")
66
+ print(f"[INFO] Using Anthropic API with model {DEFAULT_MODEL}", flush=True)
67
+ else:
68
+ # Ultimate fallback: Ollama local
69
+ API_BASE = "http://localhost:11434/v1"
70
+ API_KEY = "ollama"
71
+ DEFAULT_MODEL = os.getenv("SDD_EVOLVE_MODEL", "gemma4:31b-cloud")
72
+ print(f"[INFO] No cloud keys found — falling back to Ollama local at {API_BASE} with model {DEFAULT_MODEL}", flush=True)
73
+
74
+ SKILL_SEARCH_PATHS = [
75
+ Path.home() / ".hermes" / "global_skills",
76
+ Path.home() / ".hermes" / "skills",
77
+ Path.home() / ".claude" / "skills",
78
+ Path.home() / ".opencode" / "skills",
79
+ ]
80
+
81
+ # ── Logging helpers (dashboard job-tracker parses these) ───────────
82
+
83
+ class Logger:
84
+ def __init__(self):
85
+ self._phases = []
86
+
87
+ def phase(self, msg: str):
88
+ print(f"[PHASE] {msg}", flush=True)
89
+
90
+ def info(self, msg: str):
91
+ print(f"[INFO] {msg}", flush=True)
92
+
93
+ def ok(self, msg: str):
94
+ print(f"[OK] {msg}", flush=True)
95
+
96
+ def warn(self, msg: str):
97
+ print(f"[WARN] {msg}", flush=True)
98
+
99
+ def err(self, msg: str):
100
+ print(f"[ERROR] {msg}", flush=True)
101
+
102
+ def metric(self, key: str, value):
103
+ print(f"[METRIC] {key}={value}", flush=True)
104
+
105
+ def score(self, label: str, value: float):
106
+ print(f"[SCORE] {label}={value:.4f}", flush=True)
107
+
108
+ log = Logger()
109
+
110
+ # ── LLM client ─────────────────────────────────────────────────────
111
+
112
+ def _get_client():
113
+ try:
114
+ from openai import OpenAI
115
+ except ImportError:
116
+ log.err("openai package not installed. Run: pip install openai")
117
+ sys.exit(1)
118
+
119
+ if not API_KEY:
120
+ log.err("No API key found. Set OPENROUTER_API_KEY or NOUS_API_KEY in ~/.hermes/.env")
121
+ sys.exit(1)
122
+
123
+ return OpenAI(base_url=API_BASE, api_key=API_KEY)
124
+
125
+
126
+ def chat_completion(messages: list, model: str = DEFAULT_MODEL, temperature: float = 0.4, max_tokens: int = 4000) -> str:
127
+ client = _get_client()
128
+ resp = client.chat.completions.create(
129
+ model=model,
130
+ messages=messages,
131
+ temperature=temperature,
132
+ max_tokens=max_tokens,
133
+ )
134
+ return resp.choices[0].message.content or ""
135
+
136
+
137
+ # ── Skill loader ───────────────────────────────────────────────────
138
+
139
+ def find_skill(name: str) -> Optional[Path]:
140
+ for base in SKILL_SEARCH_PATHS:
141
+ if not base.exists():
142
+ continue
143
+ # Direct match: base/name/SKILL.md or base/name.md
144
+ direct = base / name / "SKILL.md"
145
+ if direct.exists():
146
+ return direct
147
+ direct2 = base / f"{name}.md"
148
+ if direct2.exists():
149
+ return direct2
150
+ # Search one level deep
151
+ for child in base.iterdir():
152
+ if child.name.lower() == name.lower():
153
+ if child.is_dir():
154
+ for cand in ["SKILL.md", "skill.md", "README.md", "index.md"]:
155
+ p = child / cand
156
+ if p.exists():
157
+ return p
158
+ elif child.suffix == ".md":
159
+ return child
160
+ return None
161
+
162
+
163
+ def load_skill(path: Path) -> dict:
164
+ raw = path.read_text(encoding="utf-8")
165
+ # Parse frontmatter
166
+ frontmatter = {}
167
+ body = raw
168
+ if raw.strip().startswith("---"):
169
+ parts = raw.split("---", 2)
170
+ if len(parts) >= 3:
171
+ try:
172
+ import yaml
173
+ frontmatter = yaml.safe_load(parts[1]) or {}
174
+ except Exception:
175
+ frontmatter = {}
176
+ body = parts[2]
177
+
178
+ # Extract variables {{var}}
179
+ variables = sorted(set(re.findall(r"\{\{\s*(\w+)\s*\}\}", raw)))
180
+
181
+ return {
182
+ "path": path,
183
+ "name": path.parent.name if path.name == "SKILL.md" else path.stem,
184
+ "raw": raw,
185
+ "frontmatter": frontmatter,
186
+ "body": body,
187
+ "variables": variables,
188
+ "size": len(raw),
189
+ }
190
+
191
+
192
+ # ── Prompt builders ────────────────────────────────────────────────
193
+
194
+ def build_iter1_prompt(skill: dict) -> str:
195
+ vars_block = "\n".join(f" - {{{{{v}}}}}" for v in skill["variables"]) or " (none detected)"
196
+ return textwrap.dedent(f"""\
197
+ You are an expert Prompt Engineer specializing in Skill-Driven Development (SDD).
198
+
199
+ TASK: Improve the semantic clarity and logical flow of the following skill.
200
+
201
+ RULES:
202
+ - Preserve ALL template variables exactly as {{{{varName}}}} — do not rename or remove them.
203
+ - Keep the same overall purpose and domain.
204
+ - Fix ambiguous instructions, tighten wording, and ensure a clear step-by-step flow.
205
+ - Add a concise "System_Prompt" section at the top if missing.
206
+ - Do NOT change the output format yet (that comes next iteration).
207
+
208
+ DETECTED VARIABLES:
209
+ {vars_block}
210
+
211
+ ORIGINAL SKILL:
212
+ {skill['raw'][:4000]}
213
+
214
+ OUTPUT: Return ONLY the improved skill markdown (with frontmatter). No explanations outside the markdown.
215
+ """)
216
+
217
+
218
+ def build_iter2_prompt(skill: dict, iter1_text: str) -> str:
219
+ vars_block = "\n".join(f" - {{{{{v}}}}}" for v in skill["variables"]) or " (none detected)"
220
+ return textwrap.dedent(f"""\
221
+ You are an expert Prompt Engineer specializing in Skill-Driven Development (SDD).
222
+
223
+ TASK: Structure the output format of the following skill. Ensure it produces valid, parseable responses.
224
+
225
+ RULES:
226
+ - Preserve ALL template variables exactly as {{{{varName}}}}.
227
+ - Define a clear response format: prefer structured JSON or well-defined Markdown sections.
228
+ - Add Few-Shot examples (input → expected output) when helpful.
229
+ - Include a "Formato de Respuesta" section describing the exact output schema.
230
+ - If JSON output is appropriate, specify the JSON schema inline.
231
+
232
+ DETECTED VARIABLES:
233
+ {vars_block}
234
+
235
+ SKILL AFTER ITERATION 1 (semantic clarity):
236
+ {iter1_text[:4000]}
237
+
238
+ OUTPUT: Return ONLY the improved skill markdown. No explanations outside the markdown.
239
+ """)
240
+
241
+
242
+ def build_iter3_prompt(skill: dict, iter2_text: str) -> str:
243
+ vars_block = "\n".join(f" - {{{{{v}}}}}" for v in skill["variables"]) or " (none detected)"
244
+ return textwrap.dedent(f"""\
245
+ You are an expert Prompt Engineer specializing in Skill-Driven Development (SDD).
246
+
247
+ TASK: Optimize token consumption and add edge-case handling.
248
+
249
+ RULES:
250
+ - Preserve ALL template variables exactly as {{{{varName}}}}.
251
+ - Remove redundant prose. Make every sentence earn its tokens.
252
+ - Add explicit Constraints section with strict rules (e.g., "No respondas con prosa, solo código").
253
+ - Add Error Handling instructions for invalid/ambiguous inputs.
254
+ - Include Validation Rules as a checklist.
255
+ - Add a brief Meta-Data section describing the skill's capabilities and limits.
256
+
257
+ DETECTED VARIABLES:
258
+ {vars_block}
259
+
260
+ SKILL AFTER ITERATION 2 (structured format):
261
+ {iter2_text[:4000]}
262
+
263
+ OUTPUT: Return ONLY the final evolved skill markdown. No explanations outside the markdown.
264
+ """)
265
+
266
+
267
+ def build_sdd_json_prompt(skill_name: str, final_md: str, iterations: int) -> str:
268
+ return textwrap.dedent(f"""\
269
+ You are an SDD (Skill-Driven Development) architect.
270
+
271
+ TASK: Analyze the evolved skill below and produce a structured SDD analysis JSON.
272
+
273
+ RULES:
274
+ - The "refined_prompt.system" should be the core identity instructions extracted from the skill.
275
+ - The "refined_prompt.template" should be the reusable user-facing template with variable placeholders.
276
+ - "validation_rules" must be a list of specific, testable constraints.
277
+ - "sdd_analysis" should explain why this version is more robust for system integration.
278
+
279
+ EVOLVED SKILL:
280
+ {final_md[:4000]}
281
+
282
+ OUTPUT ONLY valid JSON matching this exact schema (no markdown fences):
283
+ {{
284
+ "skill_name": "{skill_name}",
285
+ "iteration": {iterations},
286
+ "refined_prompt": {{
287
+ "system": "...",
288
+ "template": "...",
289
+ "validation_rules": ["..."]
290
+ }},
291
+ "sdd_analysis": "..."
292
+ }}
293
+ """)
294
+
295
+
296
+ # ── Quality scoring ────────────────────────────────────────────────
297
+
298
+ def score_skill(text: str, original: str) -> dict:
299
+ """Compute heuristic quality metrics."""
300
+ scores = {}
301
+
302
+ # Structure score: has frontmatter, sections, constraints
303
+ has_fm = text.strip().startswith("---")
304
+ has_constraints = "constraint" in text.lower() or "restricción" in text.lower()
305
+ has_examples = "ejemplo" in text.lower() or "example" in text.lower() or "```" in text
306
+ has_json_schema = "json" in text.lower() and ("schema" in text.lower() or "formato" in text.lower())
307
+ scores["structure"] = min(1.0, (0.25 * has_fm + 0.25 * has_constraints + 0.25 * has_examples + 0.25 * has_json_schema))
308
+
309
+ # Length efficiency: not too much longer, not too much shorter
310
+ orig_len = len(original)
311
+ new_len = len(text)
312
+ ratio = new_len / max(orig_len, 1)
313
+ scores["efficiency"] = 1.0 - abs(ratio - 1.0) # peak at 1.0x, drops if diverges
314
+ scores["efficiency"] = max(0.0, min(1.0, scores["efficiency"]))
315
+
316
+ # Variable preservation
317
+ orig_vars = set(re.findall(r"\{\{\s*(\w+)\s*\}\}", original))
318
+ new_vars = set(re.findall(r"\{\{\s*(\w+)\s*\}\}", text))
319
+ if orig_vars:
320
+ scores["variable_preservation"] = len(new_vars & orig_vars) / len(orig_vars)
321
+ else:
322
+ scores["variable_preservation"] = 1.0
323
+
324
+ # Composite evolved score
325
+ scores["evolved_score"] = round(
326
+ 0.4 * scores["structure"] + 0.3 * scores["efficiency"] + 0.3 * scores["variable_preservation"],
327
+ 4,
328
+ )
329
+ scores["baseline_score"] = 0.5 # heuristic baseline
330
+ scores["improvement"] = round(scores["evolved_score"] - scores["baseline_score"], 4)
331
+ return scores
332
+
333
+
334
+ # ── Main evolution loop ────────────────────────────────────────────
335
+
336
+ def evolve_skill(skill_name: str, iterations: int = 3, hermes_repo: Optional[str] = None):
337
+ start_time = time.time()
338
+ log.phase(f"Starting SDD evolution for skill: {skill_name}")
339
+ log.info(f"Iterations: {iterations}, Model: {DEFAULT_MODEL}")
340
+
341
+ # 1. Load skill
342
+ skill_path = find_skill(skill_name)
343
+ if not skill_path:
344
+ log.err(f"Skill '{skill_name}' not found in any search path")
345
+ sys.exit(1)
346
+
347
+ skill = load_skill(skill_path)
348
+ log.ok(f"Loaded skill from {skill_path}")
349
+ log.info(f"Size: {skill['size']} chars | Variables: {skill['variables']}")
350
+ log.metric("baseline_size", skill["size"])
351
+
352
+ # 2. Run iterative refinement
353
+ current_text = skill["raw"]
354
+
355
+ for i in range(1, iterations + 1):
356
+ log.phase(f"Iteration {i}/{iterations}")
357
+ if i == 1:
358
+ prompt = build_iter1_prompt(skill)
359
+ label = "semantic clarity"
360
+ elif i == 2:
361
+ prompt = build_iter2_prompt(skill, current_text)
362
+ label = "format structure"
363
+ else:
364
+ prompt = build_iter3_prompt(skill, current_text)
365
+ label = "token optimization + edge cases"
366
+
367
+ log.info(f"Optimizing for: {label}")
368
+ try:
369
+ messages = [{"role": "system", "content": "You are a world-class prompt engineer."}, {"role": "user", "content": prompt}]
370
+ current_text = chat_completion(messages, temperature=0.3 if i < 3 else 0.2)
371
+ log.ok(f"Iteration {i} complete ({len(current_text)} chars)")
372
+ except Exception as e:
373
+ log.err(f"LLM call failed at iteration {i}: {e}")
374
+ sys.exit(1)
375
+
376
+ # 3. Generate SDD JSON analysis
377
+ log.phase("Generating SDD analysis")
378
+ try:
379
+ sdd_json_text = chat_completion(
380
+ [{"role": "system", "content": "You output only valid JSON."},
381
+ {"role": "user", "content": build_sdd_json_prompt(skill_name, current_text, iterations)}],
382
+ temperature=0.1,
383
+ max_tokens=3000,
384
+ )
385
+ # Clean up potential markdown fences
386
+ sdd_json_text = re.sub(r"^```json\s*|\s*```$", "", sdd_json_text.strip(), flags=re.MULTILINE)
387
+ sdd_data = json.loads(sdd_json_text)
388
+ log.ok("SDD analysis generated")
389
+ except Exception as e:
390
+ log.warn(f"Could not generate structured SDD analysis: {e}")
391
+ sdd_data = {
392
+ "skill_name": skill_name,
393
+ "iteration": iterations,
394
+ "refined_prompt": {"system": "", "template": "", "validation_rules": []},
395
+ "sdd_analysis": "SDD analysis generation failed.",
396
+ }
397
+
398
+ # 4. Score
399
+ log.phase("Evaluating evolved skill")
400
+ scores = score_skill(current_text, skill["raw"])
401
+ for k, v in scores.items():
402
+ log.score(k, v)
403
+
404
+ # 5. Save outputs
405
+ output_base = Path.home() / ".hermes" / "hermes-agent-self-evolution" / "output" / skill_name
406
+ run_id = datetime.now().strftime("%Y%m%d_%H%M%S")
407
+ run_dir = output_base / run_id
408
+ run_dir.mkdir(parents=True, exist_ok=True)
409
+
410
+ evolved_path = run_dir / "evolved_skill.md"
411
+ evolved_path.write_text(current_text, encoding="utf-8")
412
+
413
+ baseline_path = run_dir / "baseline_skill.md"
414
+ baseline_path.write_text(skill["raw"], encoding="utf-8")
415
+
416
+ sdd_path = run_dir / "sdd_analysis.json"
417
+ sdd_path.write_text(json.dumps(sdd_data, indent=2, ensure_ascii=False), encoding="utf-8")
418
+
419
+ metrics = {
420
+ "skill_name": skill_name,
421
+ "timestamp": datetime.now().isoformat(),
422
+ "baseline_score": scores["baseline_score"],
423
+ "evolved_score": scores["evolved_score"],
424
+ "improvement": scores["improvement"],
425
+ "elapsed_seconds": round(time.time() - start_time, 2),
426
+ "iterations": iterations,
427
+ "optimizer_model": DEFAULT_MODEL,
428
+ "eval_model": DEFAULT_MODEL,
429
+ "constraints_passed": scores["structure"] > 0.6,
430
+ "original_size": skill["size"],
431
+ "evolved_size": len(current_text),
432
+ "diff_lines": len(current_text.splitlines()) - len(skill["raw"].splitlines()),
433
+ "sdd_analysis": sdd_data,
434
+ }
435
+ metrics_path = run_dir / "metrics.json"
436
+ metrics_path.write_text(json.dumps(metrics, indent=2, ensure_ascii=False), encoding="utf-8")
437
+
438
+ log.ok(f"Saved outputs to {run_dir}")
439
+ log.score("final_evolved_score", scores["evolved_score"])
440
+ log.phase("Evolution complete")
441
+
442
+ return metrics
443
+
444
+
445
+ # ── CLI entrypoint ─────────────────────────────────────────────────
446
+
447
+ def main():
448
+ parser = argparse.ArgumentParser(description="SDD Skill Evolution Engine")
449
+ parser.add_argument("--skill", required=True, help="Skill name to evolve")
450
+ parser.add_argument("--iterations", type=int, default=3, help="Number of evolution iterations")
451
+ parser.add_argument("--hermes-repo", default=None, help="Path to hermes repo (unused, kept for compat)")
452
+ parser.add_argument("--eval-source", default="synthetic", help="Dataset source (unused, kept for compat)")
453
+ args = parser.parse_args()
454
+
455
+ evolve_skill(args.skill, args.iterations, args.hermes_repo)
456
+
457
+
458
+ if __name__ == "__main__":
459
+ main()